diff --git a/inc/solver.hpp b/inc/solver.hpp index f5f796a..b6315cb 100644 --- a/inc/solver.hpp +++ b/inc/solver.hpp @@ -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 p); - Var* vars; + std::vector> vars; matrix table; matrix ope_table; diff --git a/src/main.cpp b/src/main.cpp index da91f48..b1e9b2f 100644 --- a/src/main.cpp +++ b/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: diff --git a/src/solver.cpp b/src/solver.cpp index bb7be80..3f80d54 100644 --- a/src/solver.cpp +++ b/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; // ÊÍ·ÅÔ­ÓÐÄÚ´æ + } } 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; // �ͷ�ԭ���ڴ� - vars = nullptr; - - cn = solver.cn; - if (cn > 0) { - vars = new Var[cn]; - for (int i = 0; i < cn; i++) { - vars[i] = solver.vars[i]; // ��� + for (auto& var : vars) { + delete[] var.second; // ÊÍ·ÅÔ­ÓÐÄÚ´æ + } + 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); // ����Խ���� - return vars[idx]; + assert(idx >= 0 && idx < cn); // Ìí¼ÓÔ½½ç¼ì²é + 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 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); } - // === �жϳ�ʼ���Ƿ�Ϊ���н� === + // === Åжϳõʼ½âÊÇ·ñΪ¿ÉÐнâ === 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() } } - // === �����ʼ���н� === + // === ¹¹Ôì³õʼ¿ÉÐнâ === if (!initial_feasible) { vector coeff = ope_table.front(); ope_table.front() = vector(cn, .0); @@ -393,10 +382,10 @@ rtn LinSolver::feasible_solution() rtn LinSolver::_pivot(pair& p) { p = make_pair(0, 0); - double cmin = DBL_MAX; + double cmin = INT_MAX; vector coef = ope_table.front(); - // === ������Ԫ��������Сֵ === + // === ·ÇÖ÷ÖáÔªËØÖÐÕÒ×îСֵ === 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& 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& 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 p) { size_t x = p.first, y = p.second; - // === ���й�һ�� === + // === Ö÷ÐйéÒ»»¯ === 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; } - // === �����б任 === + // === ÆäÓàÐб任 === for (size_t row = 0; row < bn; row++) { if (row == x) { continue; @@ -451,6 +440,6 @@ void LinSolver::_gaussian(pair p) } } } - basic.at(x - 1) = y; // ��Ԫ + basic.at(x - 1) = y; // »»Ôª }