调整线性规划获取属性的接口

This commit is contained in:
2025-05-16 17:39:10 +08:00
parent 6d3594c9ba
commit 0ae1785e6c
3 changed files with 311 additions and 47 deletions

View File

@ -9,24 +9,26 @@ int main(int argc, char* argv[])
{
Model mdl;
Var* vars = mdl.addVars(3);
Var* vars = mdl.addVars(2);
mdl.addConstr(vars[0] + vars[1] + vars[2], '<', 4);
mdl.addConstr(vars[0], '<', 2);
mdl.addConstr(vars[2], '<', 3);
mdl.addConstr(3 * vars[1] + vars[2], '<', 6);
mdl.addConstr(vars[0] + vars[1], ConstrOper::LESS_EQUAL, 2);
mdl.addConstr(vars[0] + vars[1], ConstrOper::GREATER_EQUAL, 1);
mdl.addConstr(5 * vars[0] - 2 * vars[1], ConstrOper::GREATER_EQUAL, -2);
mdl.setObjective(vars[0] + 14 * vars[1] + 6 * vars[2]);
mdl.setObjective(vars[0] + 2 * vars[1], MDL_MAXIMIZE);
switch(mdl.optimize(false)) {
switch(mdl.optimize()) {
case Rtn::OPTIMAL:
cout << "find solution: " << mdl.get() << endl;
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;
}
break;
case Rtn::INFEASIBLE:
cout << "no solution" << endl;
cout << "INFEASIBLE MODEL" << endl;
break;
case Rtn::UNBOUNDED:
cout << "unbounded solution" << endl;
cout << "UNBOUNDED SOLUTION" << endl;
break;
default:
assert(false);

View File

@ -32,16 +32,16 @@ Expr operator+(const Expr& x)
Expr operator+(Var x, Var y)
{
Expr exp;
exp.coeffs.resize(std::max(x.col + 1, y.col + 1), 0);
exp.coeffs[x.col] = x.coeffs;
exp.coeffs[y.col] = y.coeffs;
exp.coeffs.resize(std::max(x.get(IntAttr::ModelColumn) + 1, y.get(IntAttr::ModelColumn) + 1), 0);
exp.coeffs[x.get(IntAttr::ModelColumn)] = x.get(DoubleAttr::Coeff);
exp.coeffs[y.get(IntAttr::ModelColumn)] = y.get(DoubleAttr::Coeff);
return exp;
}
Expr operator+(Var x, double a)
{
Expr exp;
exp.coeffs.resize(x.col + 1);
exp.coeffs.resize(x.get(IntAttr::ModelColumn) + 1);
exp.constant = a;
return exp;
}
@ -85,9 +85,9 @@ Expr operator-(Var x)
Expr operator-(Var x, Var y)
{
Expr exp;
exp.coeffs.resize(std::max(x.col + 1, y.col + 1), 0);
exp.coeffs[x.col] = x.coeffs;
exp.coeffs[y.col] = -y.coeffs;
exp.coeffs.resize(std::max(x.get(IntAttr::ModelColumn) + 1, y.get(IntAttr::ModelColumn) + 1), 0);
exp.coeffs[x.get(IntAttr::ModelColumn)] = x.get(DoubleAttr::Coeff);
exp.coeffs[y.get(IntAttr::ModelColumn)] = -y.get(DoubleAttr::Coeff);
return exp;
}
@ -104,8 +104,8 @@ Expr operator-(double a, Var x)
Expr operator*(double a, Var x)
{
Expr exp;
exp.coeffs.resize(x.col + 1, 0);
exp.coeffs[x.col] = a * x.coeffs;
exp.coeffs.resize(x.get(IntAttr::ModelColumn) + 1, 0);
exp.coeffs[x.get(IntAttr::ModelColumn)] = a * x.get(DoubleAttr::Coeff);
return exp;
}
@ -147,6 +147,7 @@ Expr operator/(const Expr& x, double a)
Model::Model():
cn(0),
bn(0),
sense(0),
vars(nullptr)
{
@ -165,22 +166,50 @@ Var* Model::addVars(int num)
return vars;
}
void Model::addConstr(const Expr& expr, char sense, double rhs)
void Model::addConstr(const Expr& expr, ConstrOper sense, double rhs)
{
matrix.push_back(vector<double>(1, rhs)); // TODO<44><4F>û<EFBFBD>ȴ<EFBFBD>С<EFBFBD><D0A1>û<EFBFBD><C3BB><EFBFBD>dz<EFBFBD><C7B3><EFBFBD>
matrix.back().insert(matrix.back().end(), expr.coeffs.begin(), expr.coeffs.end());
if (sense == ConstrOper::LESS_EQUAL) {
matrix.push_back(vector<double>(1, rhs - expr.constant));
matrix.back().insert(matrix.back().end(), expr.coeffs.begin(), expr.coeffs.end());
}
else if (sense == ConstrOper::GREATER_EQUAL) {
matrix.push_back(vector<double>(1, expr.constant - rhs));
for (int coeff : expr.coeffs) {
matrix.back().push_back(-coeff);
}
}
else {
addConstr(expr, ConstrOper::LESS_EQUAL, rhs);
addConstr(expr, ConstrOper::GREATER_EQUAL, rhs);
}
for (int c = matrix.back().size(); c <= cn; c++) {
matrix.back().push_back(0);
}
}
void Model::setObjective(Expr obje, int sense)
void Model::setObjective(Expr obje, int _sense)
{
matrix.insert(matrix.begin(), obje.coeffs);
matrix.front().insert(matrix.front().begin(), obje.constant); // TODO<44><4F>д<EFBFBD>IJ<EFBFBD><C4B2><EFBFBD><EFBFBD><EFBFBD>
for (int c = matrix.front().size(); c <= cn; c++) {
matrix.front().push_back(0);
assert(_sense == 1 || _sense == -1);
if (sense == 0) {
matrix.insert(matrix.begin(), obje.coeffs);
matrix.front().insert(matrix.front().begin(), -obje.constant);
for (int c = obje.coeffs.size() + 1; c <= cn; c++) {
matrix.front().push_back(0);
}
}
else {
matrix.front().front() = -obje.constant;
for (int c = 0; c < obje.coeffs.size(); c++) {
matrix.front()[c + 1] = obje.coeffs[c];
}
for (int c = obje.coeffs.size() + 1; c <= cn; c++) {
matrix.front()[c] = 0;
}
}
sense = _sense;
}
void Model::print()
@ -193,7 +222,7 @@ void Model::print()
}
}
Rtn Model::optimize(bool isMax)
Rtn Model::optimize()
{
bn = matrix.size();
for (int row = 1; row < bn; row++) {
@ -203,12 +232,10 @@ Rtn Model::optimize(bool isMax)
}
}
cn = matrix.front().size();
if (!isMax) {
for (int i = 0; i < cn; i++) {
matrix.front()[i] = -matrix.front()[i];
}
for (int i = 0; i < cn; i++) {
matrix.front()[i] = sense * matrix.front()[i];
}
for (size_t i = 1; i < bn; i++) {
basic.push_back(cn - bn + i);
}
@ -246,9 +273,9 @@ Rtn Model::optimize(bool isMax)
auto iter = find(basic.begin(), basic.end(), cn);
if (iter != basic.end()) {
for (int col = 1; col < matrix.front().size(); col++) {
if (matrix.front()[col] != 1) {
t = make_pair(iter - basic.begin(), col);
_pivot(t);
if (fabs(matrix.front()[col]) > 1e-10) {
t = make_pair(iter - basic.begin() + 1, col);
_gaussian(t);
break;
}
}
@ -270,15 +297,25 @@ Rtn Model::optimize(bool isMax)
}
}
res = isMax ? _simplex() : _simplex();
res = -sense * _simplex();
for (int row = 1; row < bn; row++) {
if (basic[row - 1] - 1 < cn - bn) {
vars[basic[row - 1] - 1].val = matrix[row].front();
}
}
return rtn;
}
double Model::get()
double Model::get(DoubleAttr attr)
{
return res;
}
int Model::get(IntAttr attr)
{
return cn - bn;
}
double Model::_simplex()
{
pair<size_t, size_t> t;
@ -289,7 +326,6 @@ double Model::_simplex()
}
_gaussian(t);
}
return matrix.front().front();
}
@ -381,6 +417,7 @@ void Expr::operator+=(const Expr& expr)
for (int c = 0; c < expr.coeffs.size(); c++) {
coeffs[c] += expr.coeffs[c];
}
constant += expr.constant;
}
void Expr::operator-=(const Expr& expr)
@ -389,6 +426,7 @@ void Expr::operator-=(const Expr& expr)
for (int c = 0; c < expr.coeffs.size(); c++) {
coeffs[c] -= expr.coeffs[c];
}
constant -= expr.constant;
}
void Expr::operator*=(double mult)
@ -396,6 +434,7 @@ void Expr::operator*=(double mult)
for (int c = 0; c < coeffs.size(); c++) {
coeffs[c] *= mult;
}
constant *= mult;
}
void Expr::operator/=(double a)
@ -403,6 +442,7 @@ void Expr::operator/=(double a)
for (int c = 0; c < coeffs.size(); c++) {
coeffs[c] /= a;
}
constant /= a;
}
Expr Expr::operator+(const Expr& rhs)
@ -411,6 +451,7 @@ Expr Expr::operator+(const Expr& rhs)
for (int c = 0; c < rhs.coeffs.size(); c++) {
coeffs[c] += rhs.coeffs[c];
}
constant += rhs.constant;
return *this;
}
@ -420,5 +461,22 @@ Expr Expr::operator-(const Expr& rhs)
for (int c = 0; c < rhs.coeffs.size(); c++) {
coeffs[c] -= rhs.coeffs[c];
}
constant -= rhs.constant;
return *this;
}
double Var::get(DoubleAttr attr)
{
switch (attr) {
case DoubleAttr::Coeff:
return coeffs;
case DoubleAttr::X:
return val;
}
return val;
}
int Var::get(IntAttr attr)
{
return col;
}