混合整数规划框架多次添加变量
This commit is contained in:
@@ -13,7 +13,7 @@ namespace sv {
|
||||
LinSolver& operator=(const LinSolver& solver);
|
||||
|
||||
Var* addVars(int col, VarType type);
|
||||
const Var& getVar(int idx);
|
||||
Var& getVar(int idx);
|
||||
void addConstr(const Expr& expr, ConstrOper sense, double rhs);
|
||||
void setObjective(Expr obje, int sense = MDL_MAXIMIZE);
|
||||
void print();
|
||||
@@ -29,7 +29,7 @@ namespace sv {
|
||||
rtn feasible_solution();
|
||||
void _gaussian(std::pair<size_t, size_t> p);
|
||||
|
||||
Var* vars;
|
||||
std::vector<std::pair<int, Var*>> vars;
|
||||
|
||||
matrix table;
|
||||
matrix ope_table;
|
||||
|
20
src/main.cpp
20
src/main.cpp
@@ -11,18 +11,24 @@ int main(int argc, char* argv[])
|
||||
{
|
||||
Model mdl;
|
||||
|
||||
Var* vars = mdl.addVars(3, VarType::INTEGER);
|
||||
Var* int_var = mdl.addVars(3, VarType::INTEGER);
|
||||
Var* con_var = mdl.addVars(2, VarType::CONTINUOUS);
|
||||
|
||||
mdl.addConstr(2 * vars[0] + vars[1], ConstrOper::LESS_EQUAL, 10);
|
||||
mdl.addConstr(3 * vars[0] + 6 * vars[1], ConstrOper::LESS_EQUAL, 40);
|
||||
mdl.addConstr(3 * vars[0] + 6 * vars[1] + 4 * vars[2], ConstrOper::LESS_EQUAL, 50);
|
||||
mdl.setObjective(100 * vars[0] + 150 * vars[1] + 120 * vars[2], MDL_MAXIMIZE);
|
||||
mdl.addConstr(2 * int_var[0] + int_var[1], ConstrOper::LESS_EQUAL, 10);
|
||||
mdl.addConstr(3 * int_var[0] + 6 * int_var[1], ConstrOper::LESS_EQUAL, 40);
|
||||
mdl.addConstr(3 * int_var[0] + 6 * int_var[1] + 4 * int_var[2], ConstrOper::LESS_EQUAL, 50);
|
||||
mdl.addConstr(2.3 * con_var[0] + 2.6 * con_var[1], ConstrOper::LESS_EQUAL, 80);
|
||||
mdl.addConstr(con_var[0] + 2 * con_var[1], ConstrOper::LESS_EQUAL, 70);
|
||||
mdl.setObjective(100 * int_var[0] + 150 * int_var[1] + 120 * int_var[2] + 82.6 * con_var[0] + 90.4 * con_var[1], MDL_MAXIMIZE);
|
||||
|
||||
switch(mdl.optimize()) {
|
||||
case OPTIMAL:
|
||||
cout << "OPTIMAL SOLUTION: " << mdl.get(DoubleAttr::Obj) << endl;
|
||||
for (int i = 0; i < mdl.get(IntAttr::NumVars); i++) {
|
||||
cout << "var[" << i << "] : " << vars[i].get(DoubleAttr::X) << endl;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
cout << "integer var [" << i << "] : " << int_var[i].get(DoubleAttr::X) << endl;
|
||||
}
|
||||
for (int i = 0; i < 2; i++) {
|
||||
cout << "continuous var [" << i << "] : " << con_var[i].get(DoubleAttr::X) << endl;
|
||||
}
|
||||
break;
|
||||
case INFEASIBLE:
|
||||
|
103
src/solver.cpp
103
src/solver.cpp
@@ -31,35 +31,21 @@ LinSolver::LinSolver() :
|
||||
rtn_(LOADED),
|
||||
cn(0),
|
||||
bn(1),
|
||||
sense(0),
|
||||
vars(nullptr)
|
||||
sense(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
sv::LinSolver::~LinSolver()
|
||||
{
|
||||
delete[] vars;
|
||||
for (auto& var : vars) {
|
||||
delete[] var.second; // <20>ͷ<EFBFBD>ԭ<EFBFBD><D4AD><EFBFBD>ڴ<EFBFBD>
|
||||
}
|
||||
}
|
||||
|
||||
sv::LinSolver::LinSolver(const LinSolver& solver)
|
||||
: vars(nullptr),
|
||||
cn(solver.cn),
|
||||
bn(solver.bn),
|
||||
table(solver.table),
|
||||
basic(solver.basic),
|
||||
rtn_(solver.rtn_),
|
||||
obj_(solver.obj_),
|
||||
sense(solver.sense)
|
||||
{
|
||||
delete[] vars;
|
||||
vars = nullptr;
|
||||
if (solver.vars != nullptr && cn > 0) {
|
||||
vars = new Var[cn];
|
||||
for (int i = 0; i < cn; i++) {
|
||||
vars[i] = solver.vars[i];
|
||||
}
|
||||
}
|
||||
*this = solver;
|
||||
}
|
||||
|
||||
LinSolver& sv::LinSolver::operator=(const LinSolver& solver)
|
||||
@@ -67,16 +53,18 @@ LinSolver& sv::LinSolver::operator=(const LinSolver& solver)
|
||||
if (this == &solver) {
|
||||
return *this;
|
||||
}
|
||||
delete[] vars; // <20>ͷ<EFBFBD>ԭ<EFBFBD><D4AD><EFBFBD>ڴ<EFBFBD>
|
||||
vars = nullptr;
|
||||
|
||||
cn = solver.cn;
|
||||
if (cn > 0) {
|
||||
vars = new Var[cn];
|
||||
for (int i = 0; i < cn; i++) {
|
||||
vars[i] = solver.vars[i]; // <20><EFBFBD><EEBFBD>
|
||||
for (auto& var : vars) {
|
||||
delete[] var.second; // <20>ͷ<EFBFBD>ԭ<EFBFBD><D4AD><EFBFBD>ڴ<EFBFBD>
|
||||
}
|
||||
vars.clear();
|
||||
vars.reserve(solver.vars.size());
|
||||
for (auto& var : solver.vars) {
|
||||
vars.push_back(std::pair(var.first, new Var[var.first]));
|
||||
for (int i = 0; i < var.first; i++) {
|
||||
vars.back().second[i] = var.second[i];
|
||||
}
|
||||
}
|
||||
cn = solver.cn;
|
||||
table = solver.table;
|
||||
cn = solver.cn, bn = solver.bn;
|
||||
basic = solver.basic;
|
||||
@@ -89,23 +77,28 @@ LinSolver& sv::LinSolver::operator=(const LinSolver& solver)
|
||||
|
||||
Var* LinSolver::addVars(int num, VarType type)
|
||||
{
|
||||
Var* old = vars;
|
||||
vars = new Var[cn + num];
|
||||
for (int c = cn; c < cn + num; c++) {
|
||||
vars[c].col = c;
|
||||
vars[c].type = type;
|
||||
Var* var = new Var[num];
|
||||
for (int c = 0; c < num; c++) {
|
||||
var[c].col = c + cn, var[c].type = type;
|
||||
}
|
||||
|
||||
memcpy(vars, old, sizeof(Var) * cn);
|
||||
delete[] old;
|
||||
vars.push_back(std::pair(num, var));
|
||||
cn += num;
|
||||
return vars;
|
||||
return vars.back().second;
|
||||
}
|
||||
|
||||
const Var& sv::LinSolver::getVar(int idx)
|
||||
Var& sv::LinSolver::getVar(int idx)
|
||||
{
|
||||
assert(idx >= 0 && idx < cn); // <20><><EFBFBD><EFBFBD>Խ<EFBFBD><D4BD><EFBFBD><EFBFBD>
|
||||
return vars[idx];
|
||||
assert(idx >= 0 && idx < cn); // <20><><EFBFBD><EFBFBD>Խ<EFBFBD><D4BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
static Var err_var;
|
||||
for (auto& var : vars) {
|
||||
if (var.first <= idx) {
|
||||
idx -= var.first;
|
||||
}
|
||||
else {
|
||||
return var.second[idx];
|
||||
}
|
||||
}
|
||||
return err_var;
|
||||
}
|
||||
|
||||
void LinSolver::addConstr(const Expr& expr, ConstrOper sense, double rhs)
|
||||
@@ -173,7 +166,7 @@ rtn LinSolver::optimize()
|
||||
cn = ope_table.front().size() - bn;
|
||||
for (int row = 1; row < bn; row++) {
|
||||
if (basic.at(row - 1) - 1 < cn) {
|
||||
vars[basic.at(row - 1) - 1].val = ope_table.at(row).front();
|
||||
getVar(basic.at(row - 1) - 1).val = ope_table.at(row).front();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -206,11 +199,7 @@ rtn Model::optimize()
|
||||
|
||||
std::stack<Node> list_;
|
||||
|
||||
Node root_node;
|
||||
root_node.solver = solver;
|
||||
root_node.lower_bound = 0;
|
||||
root_node.upper_bound = solver.obj_;
|
||||
|
||||
Node root_node = { solver, 0, solver.obj_ };
|
||||
Node incumbent_node = root_node;
|
||||
|
||||
list_.push(root_node);
|
||||
@@ -223,8 +212,8 @@ rtn Model::optimize()
|
||||
int branch_var_index = -1;
|
||||
|
||||
for (int i = 0; i < current_node.solver.get(IntAttr::NumVars); i++) {
|
||||
if (current_node.solver.vars[i].type == VarType::INTEGER) {
|
||||
if (fabs(int(current_node.solver.vars[i].val) - current_node.solver.vars[i].val) > 1e-10) {
|
||||
if (current_node.solver.getVar(i).type == VarType::INTEGER) {
|
||||
if (fabs(int(current_node.solver.getVar(i).val) - current_node.solver.getVar(i).val) > 1e-10) {
|
||||
branch_var_index = i;
|
||||
break;
|
||||
}
|
||||
@@ -259,7 +248,7 @@ rtn Model::optimize()
|
||||
solver.rtn_ = incumbent_node.solver.rtn_;
|
||||
solver.obj_ = incumbent_node.solver.obj_;
|
||||
for (int i = 0; i < solver.cn; i++) {
|
||||
solver.vars[i].val = incumbent_node.solver.vars[i].val;
|
||||
solver.getVar(i).val = incumbent_node.solver.getVar(i).val;
|
||||
}
|
||||
return solver.rtn_;
|
||||
}
|
||||
@@ -332,7 +321,7 @@ rtn LinSolver::feasible_solution()
|
||||
basic.push_back(cn - bn + i);
|
||||
}
|
||||
|
||||
// === <20>жϳ<D0B6>ʼ<EFBFBD><CABC><EFBFBD>Ƿ<EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD>н<EFBFBD> ===
|
||||
// === <20>жϳ<D0B6>ʼ<EFBFBD><CABC><EFBFBD>Ƿ<EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD>н<EFBFBD> ===
|
||||
bool initial_feasible = true;
|
||||
for (int row = 1; row < bn; row++) {
|
||||
if (ope_table.at(row).front() < 0) {
|
||||
@@ -341,7 +330,7 @@ rtn LinSolver::feasible_solution()
|
||||
}
|
||||
}
|
||||
|
||||
// === <20><><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC><EFBFBD>н<EFBFBD> ===
|
||||
// === <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD>н<EFBFBD> ===
|
||||
if (!initial_feasible) {
|
||||
vector<double> coeff = ope_table.front();
|
||||
ope_table.front() = vector<double>(cn, .0);
|
||||
@@ -393,10 +382,10 @@ rtn LinSolver::feasible_solution()
|
||||
rtn LinSolver::_pivot(pair<size_t, size_t>& p)
|
||||
{
|
||||
p = make_pair(0, 0);
|
||||
double cmin = DBL_MAX;
|
||||
double cmin = INT_MAX;
|
||||
vector<double> coef = ope_table.front();
|
||||
|
||||
// === <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Сֵ ===
|
||||
// === <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Сֵ ===
|
||||
for (size_t col = 1; col < coef.size(); col++) {
|
||||
if (cmin > coef.at(col) && find(basic.begin(), basic.end(), col) == basic.end()) {
|
||||
cmin = coef.at(col);
|
||||
@@ -406,7 +395,7 @@ rtn LinSolver::_pivot(pair<size_t, size_t>& p)
|
||||
if (cmin >= 0) {
|
||||
return OPTIMAL;
|
||||
}
|
||||
double bmin = DBL_MAX;
|
||||
double bmin = INT_MAX;
|
||||
for (size_t row = 1; row < bn; row++) {
|
||||
double tmp = ope_table.at(row).front() / ope_table.at(row).at(p.second);
|
||||
if (ope_table.at(row).at(p.second) > 0 && bmin > tmp) {
|
||||
@@ -415,7 +404,7 @@ rtn LinSolver::_pivot(pair<size_t, size_t>& p)
|
||||
}
|
||||
}
|
||||
|
||||
if (abs(bmin - DBL_MAX) < 1e-10) {
|
||||
if (abs(bmin - INT_MAX) < 1e-10) {
|
||||
return UNBOUNDED;
|
||||
}
|
||||
|
||||
@@ -433,13 +422,13 @@ void LinSolver::_gaussian(pair<size_t, size_t> p)
|
||||
{
|
||||
size_t x = p.first, y = p.second;
|
||||
|
||||
// === <20><><EFBFBD>й<EFBFBD>һ<EFBFBD><D2BB> ===
|
||||
// === <20><><EFBFBD>й<EFBFBD>һ<EFBFBD><D2BB> ===
|
||||
double norm = ope_table.at(x).at(y);
|
||||
for (size_t col = 0; col < ope_table.at(x).size(); col++) {
|
||||
ope_table.at(x).at(col) /= norm;
|
||||
}
|
||||
|
||||
// === <20><><EFBFBD><EFBFBD><EFBFBD>б任 ===
|
||||
// === <20><><EFBFBD><EFBFBD><EFBFBD>б任 ===
|
||||
for (size_t row = 0; row < bn; row++) {
|
||||
if (row == x) {
|
||||
continue;
|
||||
@@ -451,6 +440,6 @@ void LinSolver::_gaussian(pair<size_t, size_t> p)
|
||||
}
|
||||
}
|
||||
}
|
||||
basic.at(x - 1) = y; // <20><>Ԫ
|
||||
basic.at(x - 1) = y; // <20><>Ԫ
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user