混合整数规划框架多次添加变量
This commit is contained in:
@@ -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;
|
||||||
|
20
src/main.cpp
20
src/main.cpp
@@ -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:
|
||||||
|
105
src/solver.cpp
105
src/solver.cpp
@@ -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>
|
||||||
|
}
|
||||||
|
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;
|
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>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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><>Ԫ
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user