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

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);
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;

View File

@@ -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:

View File

@@ -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><>Ԫ
}