混合整数规划框架多次添加变量

This commit is contained in:
2025-08-26 00:04:41 +08:00
parent 9f029ef7e4
commit 3cd5dca89e
3 changed files with 61 additions and 66 deletions

View File

@@ -13,7 +13,7 @@ namespace sv {
LinSolver& operator=(const LinSolver& solver); LinSolver& operator=(const LinSolver& solver);
Var* addVars(int col, VarType type); 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 addConstr(const Expr& expr, ConstrOper sense, double rhs);
void setObjective(Expr obje, int sense = MDL_MAXIMIZE); void setObjective(Expr obje, int sense = MDL_MAXIMIZE);
void print(); void print();
@@ -29,7 +29,7 @@ namespace sv {
rtn feasible_solution(); rtn feasible_solution();
void _gaussian(std::pair<size_t, size_t> p); void _gaussian(std::pair<size_t, size_t> p);
Var* vars; std::vector<std::pair<int, Var*>> vars;
matrix table; matrix table;
matrix ope_table; matrix ope_table;

View File

@@ -11,18 +11,24 @@ int main(int argc, char* argv[])
{ {
Model mdl; 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(2 * int_var[0] + int_var[1], ConstrOper::LESS_EQUAL, 10);
mdl.addConstr(3 * vars[0] + 6 * vars[1], ConstrOper::LESS_EQUAL, 40); mdl.addConstr(3 * int_var[0] + 6 * int_var[1], ConstrOper::LESS_EQUAL, 40);
mdl.addConstr(3 * vars[0] + 6 * vars[1] + 4 * vars[2], ConstrOper::LESS_EQUAL, 50); mdl.addConstr(3 * int_var[0] + 6 * int_var[1] + 4 * int_var[2], ConstrOper::LESS_EQUAL, 50);
mdl.setObjective(100 * vars[0] + 150 * vars[1] + 120 * vars[2], MDL_MAXIMIZE); 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()) { switch(mdl.optimize()) {
case OPTIMAL: case OPTIMAL:
cout << "OPTIMAL SOLUTION: " << mdl.get(DoubleAttr::Obj) << endl; cout << "OPTIMAL SOLUTION: " << mdl.get(DoubleAttr::Obj) << endl;
for (int i = 0; i < mdl.get(IntAttr::NumVars); i++) { for (int i = 0; i < 3; i++) {
cout << "var[" << i << "] : " << vars[i].get(DoubleAttr::X) << endl; 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; break;
case INFEASIBLE: case INFEASIBLE:

View File

@@ -31,35 +31,21 @@ LinSolver::LinSolver() :
rtn_(LOADED), rtn_(LOADED),
cn(0), cn(0),
bn(1), bn(1),
sense(0), sense(0)
vars(nullptr)
{ {
} }
sv::LinSolver::~LinSolver() sv::LinSolver::~LinSolver()
{ {
delete[] vars; for (auto& var : vars) {
delete[] var.second; // <20>ͷ<EFBFBD>ԭ<EFBFBD><D4AD><EFBFBD>ڴ<EFBFBD>
}
} }
sv::LinSolver::LinSolver(const LinSolver& solver) 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; *this = solver;
vars = nullptr;
if (solver.vars != nullptr && cn > 0) {
vars = new Var[cn];
for (int i = 0; i < cn; i++) {
vars[i] = solver.vars[i];
}
}
} }
LinSolver& sv::LinSolver::operator=(const LinSolver& solver) LinSolver& sv::LinSolver::operator=(const LinSolver& solver)
@@ -67,16 +53,18 @@ LinSolver& sv::LinSolver::operator=(const LinSolver& solver)
if (this == &solver) { if (this == &solver) {
return *this; return *this;
} }
delete[] vars; // <20>ͷ<EFBFBD>ԭ<EFBFBD><D4AD><EFBFBD>ڴ<EFBFBD> for (auto& var : vars) {
vars = nullptr; delete[] var.second; // <20>ͷ<EFBFBD>ԭ<EFBFBD><D4AD><EFBFBD>ڴ<EFBFBD>
}
cn = solver.cn; vars.clear();
if (cn > 0) { vars.reserve(solver.vars.size());
vars = new Var[cn]; for (auto& var : solver.vars) {
for (int i = 0; i < cn; i++) { vars.push_back(std::pair(var.first, new Var[var.first]));
vars[i] = solver.vars[i]; // <20><EFBFBD><EEBFBD> for (int i = 0; i < var.first; i++) {
vars.back().second[i] = var.second[i];
} }
} }
cn = solver.cn;
table = solver.table; table = solver.table;
cn = solver.cn, bn = solver.bn; cn = solver.cn, bn = solver.bn;
basic = solver.basic; basic = solver.basic;
@@ -89,23 +77,28 @@ LinSolver& sv::LinSolver::operator=(const LinSolver& solver)
Var* LinSolver::addVars(int num, VarType type) Var* LinSolver::addVars(int num, VarType type)
{ {
Var* old = vars; Var* var = new Var[num];
vars = new Var[cn + num]; for (int c = 0; c < num; c++) {
for (int c = cn; c < cn + num; c++) { var[c].col = c + cn, var[c].type = type;
vars[c].col = c;
vars[c].type = type;
} }
vars.push_back(std::pair(num, var));
memcpy(vars, old, sizeof(Var) * cn);
delete[] old;
cn += num; 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> assert(idx >= 0 && idx < cn); // <20><><EFBFBD><EFBFBD>Խ<EFBFBD><D4BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
return vars[idx]; 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) void LinSolver::addConstr(const Expr& expr, ConstrOper sense, double rhs)
@@ -173,7 +166,7 @@ rtn LinSolver::optimize()
cn = ope_table.front().size() - bn; cn = ope_table.front().size() - bn;
for (int row = 1; row < bn; row++) { for (int row = 1; row < bn; row++) {
if (basic.at(row - 1) - 1 < cn) { 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_; std::stack<Node> list_;
Node root_node; Node root_node = { solver, 0, solver.obj_ };
root_node.solver = solver;
root_node.lower_bound = 0;
root_node.upper_bound = solver.obj_;
Node incumbent_node = root_node; Node incumbent_node = root_node;
list_.push(root_node); list_.push(root_node);
@@ -223,8 +212,8 @@ rtn Model::optimize()
int branch_var_index = -1; int branch_var_index = -1;
for (int i = 0; i < current_node.solver.get(IntAttr::NumVars); i++) { for (int i = 0; i < current_node.solver.get(IntAttr::NumVars); i++) {
if (current_node.solver.vars[i].type == VarType::INTEGER) { if (current_node.solver.getVar(i).type == VarType::INTEGER) {
if (fabs(int(current_node.solver.vars[i].val) - current_node.solver.vars[i].val) > 1e-10) { if (fabs(int(current_node.solver.getVar(i).val) - current_node.solver.getVar(i).val) > 1e-10) {
branch_var_index = i; branch_var_index = i;
break; break;
} }
@@ -259,7 +248,7 @@ rtn Model::optimize()
solver.rtn_ = incumbent_node.solver.rtn_; solver.rtn_ = incumbent_node.solver.rtn_;
solver.obj_ = incumbent_node.solver.obj_; solver.obj_ = incumbent_node.solver.obj_;
for (int i = 0; i < solver.cn; i++) { 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_; return solver.rtn_;
} }
@@ -332,7 +321,7 @@ rtn LinSolver::feasible_solution()
basic.push_back(cn - bn + i); 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; bool initial_feasible = true;
for (int row = 1; row < bn; row++) { for (int row = 1; row < bn; row++) {
if (ope_table.at(row).front() < 0) { 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) { if (!initial_feasible) {
vector<double> coeff = ope_table.front(); vector<double> coeff = ope_table.front();
ope_table.front() = vector<double>(cn, .0); ope_table.front() = vector<double>(cn, .0);
@@ -393,10 +382,10 @@ rtn LinSolver::feasible_solution()
rtn LinSolver::_pivot(pair<size_t, size_t>& p) rtn LinSolver::_pivot(pair<size_t, size_t>& p)
{ {
p = make_pair(0, 0); p = make_pair(0, 0);
double cmin = DBL_MAX; double cmin = INT_MAX;
vector<double> coef = ope_table.front(); 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++) { for (size_t col = 1; col < coef.size(); col++) {
if (cmin > coef.at(col) && find(basic.begin(), basic.end(), col) == basic.end()) { if (cmin > coef.at(col) && find(basic.begin(), basic.end(), col) == basic.end()) {
cmin = coef.at(col); cmin = coef.at(col);
@@ -406,7 +395,7 @@ rtn LinSolver::_pivot(pair<size_t, size_t>& p)
if (cmin >= 0) { if (cmin >= 0) {
return OPTIMAL; return OPTIMAL;
} }
double bmin = DBL_MAX; double bmin = INT_MAX;
for (size_t row = 1; row < bn; row++) { for (size_t row = 1; row < bn; row++) {
double tmp = ope_table.at(row).front() / ope_table.at(row).at(p.second); 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) { 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; return UNBOUNDED;
} }
@@ -433,13 +422,13 @@ void LinSolver::_gaussian(pair<size_t, size_t> p)
{ {
size_t x = p.first, y = p.second; 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); double norm = ope_table.at(x).at(y);
for (size_t col = 0; col < ope_table.at(x).size(); col++) { for (size_t col = 0; col < ope_table.at(x).size(); col++) {
ope_table.at(x).at(col) /= norm; ope_table.at(x).at(col) /= norm;
} }
// === <20><><EFBFBD><EFBFBD><EFBFBD>б任 === // === <20><><EFBFBD><EFBFBD><EFBFBD>б任 ===
for (size_t row = 0; row < bn; row++) { for (size_t row = 0; row < bn; row++) {
if (row == x) { if (row == x) {
continue; 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><>Ԫ
} }