4 #include <boost/log/trivial.hpp> 5 #include <boost/program_options.hpp> 7 #include <gurobi_c++.h> 15 using namespace Utils;
17 bool operator==(vector<short int> Fix1, vector<short int> Fix2)
25 if (Fix1.size() != Fix2.size())
27 for (
unsigned int i = 0; i < Fix1.size(); i++) {
28 if (Fix1.at(i) != Fix2.at(i))
34 bool operator<(vector<short int> Fix1, vector<short int> Fix2)
46 if (Fix1.size() != Fix2.size())
48 for (
unsigned int i = 0; i < Fix1.size(); i++) {
49 if (Fix1.at(i) != Fix2.at(i) && Fix1.at(i) * Fix2.at(i) != 0) {
56 bool operator>(vector<int> Fix1, vector<int> Fix2) {
return (Fix2 < Fix1); }
65 this->Ai = unique_ptr<spmat_Vec>(
new spmat_Vec());
66 this->bi = unique_ptr<vec_Vec>(
new vec_Vec());
67 this->RlxdModel.set(GRB_IntParam_OutputFlag,
VERBOSE);
69 this->nR = this->M.n_rows;
70 this->nC = this->M.n_cols;
88 [](pair<unsigned int, unsigned int> a,
89 pair<unsigned int, unsigned int> b) {
return a.first < b.first; });
90 for (
auto p : this->
Compl)
91 if (p.first != p.second) {
124 for (
unsigned int i = 0; i <
M.n_rows; i++) {
125 unsigned int count = i < LeadStart ? i : i +
nLeader;
126 this->
Compl.push_back({i, count});
130 [](pair<unsigned int, unsigned int> a,
131 pair<unsigned int, unsigned int> b) {
return a.first < b.first; });
157 this->Compl =
perps(Compl);
158 sort(this->Compl.begin(), this->Compl.end(),
159 [](pair<unsigned int, unsigned int> a,
160 pair<unsigned int, unsigned int> b) {
return a.first < b.first; });
162 for (
auto p : this->Compl) {
163 if (p.first != p.second) {
190 BOOST_LOG_TRIVIAL(trace)
191 <<
"Game::LCP::makeRelaxed: Creating a model with : " <<
nR 192 <<
" variables and " <<
nC <<
" constraints";
194 BOOST_LOG_TRIVIAL(trace)
195 <<
"Game::LCP::makeRelaxed: Initializing variables";
196 for (
unsigned int i = 0; i <
nC; i++)
197 x[i] =
RlxdModel.addVar(0, GRB_INFINITY, 1, GRB_CONTINUOUS,
199 for (
unsigned int i = 0; i <
nR; i++)
200 z[i] =
RlxdModel.addVar(0, GRB_INFINITY, 1, GRB_CONTINUOUS,
202 BOOST_LOG_TRIVIAL(trace) <<
"Game::LCP::makeRelaxed: Added variables";
203 for (
unsigned int i = 0; i <
nR; i++) {
205 for (
auto v =
M.begin_row(i); v !=
M.end_row(i); ++v)
206 expr += (*v) * x[v.col()];
210 BOOST_LOG_TRIVIAL(trace)
211 <<
"Game::LCP::makeRelaxed: Added equation definitions";
213 if (this->
_A.n_nonzero != 0 && this->_b.n_rows != 0) {
214 if (
_A.n_cols != nC ||
_A.n_rows !=
_b.n_rows) {
215 BOOST_LOG_TRIVIAL(trace) <<
"(" <<
_A.n_rows <<
"," <<
_A.n_cols
216 <<
")\t" <<
_b.n_rows <<
" " <<
nC;
217 throw string(
"Game::LCP::makeRelaxed: A and b are incompatible! Thrown " 218 "from makeRelaxed()");
220 for (
unsigned int i = 0; i <
_A.n_rows; i++) {
222 for (
auto a =
_A.begin_row(i); a !=
_A.end_row(i); ++a)
223 expr += (*a) * x[a.col()];
227 BOOST_LOG_TRIVIAL(trace)
228 <<
"Game::LCP::makeRelaxed: Added common constraints";
232 }
catch (
const char *e) {
233 cerr <<
"Error in Game::LCP::makeRelaxed: " << e <<
'\n';
236 cerr <<
"String: Error in Game::LCP::makeRelaxed: " << e <<
'\n';
238 }
catch (exception &e) {
239 cerr <<
"Exception: Error in Game::LCP::makeRelaxed: " << e.what() <<
'\n';
241 }
catch (GRBException &e) {
242 cerr <<
"GRBException: Error in Game::LCP::makeRelaxed: " 243 << e.getErrorCode() <<
"; " << e.getMessage() <<
'\n';
272 unique_ptr<GRBModel> model(
new GRBModel(this->
RlxdModel));
273 for (
auto i : FixEq) {
275 throw "Game::LCP::LCP_Polyhed_fixed: Element in FixEq is greater than nC";
276 model->getVarByName(
"z_" +
to_string(i)).set(GRB_DoubleAttr_UB, 0);
278 for (
auto i : FixVar) {
280 throw "Game::LCP::LCP_Polyhed_fixed: Element in FixEq is greater than nC";
281 model->getVarByName(
"z_" +
to_string(i)).set(GRB_DoubleAttr_UB, 0);
287 arma::Col<int> FixEq,
288 arma::Col<int> FixVar
307 unique_ptr<GRBModel> model{
new GRBModel(this->
RlxdModel)};
308 for (
unsigned int i = 0; i <
nC; i++)
310 model->getVarByName(
"x_" +
to_string(i)).set(GRB_DoubleAttr_UB, 0);
311 for (
unsigned int i = 0; i <
nR; i++)
313 model->getVarByName(
"z_" +
to_string(i)).set(GRB_DoubleAttr_UB, 0);
336 if (Fixes.size() != this->
nR)
338 "Game::LCP::LCPasMIP: Bad size for Fixes in Game::LCP::LCPasMIP");
339 vector<unsigned int> FixVar, FixEq;
340 for (
unsigned int i = 0; i <
nR; i++) {
346 return this->
LCPasMIP(FixEq, FixVar, solve);
350 vector<unsigned int> FixEq,
351 vector<unsigned int> FixVar,
366 unique_ptr<GRBModel> model{
new GRBModel(this->
RlxdModel)};
371 for (
unsigned int i = 0; i <
nC; i++)
372 x[i] = model->getVarByName(
"x_" +
to_string(i));
373 for (
unsigned int i = 0; i <
nR; i++)
374 z[i] = model->getVarByName(
"z_" +
to_string(i));
376 for (
unsigned int i = 0; i <
nR; i++)
377 u[i] = model->addVar(0, 1, 0, GRB_BINARY,
"u_" +
to_string(i));
379 for (
unsigned int i = 0; i <
nR; i++)
380 v[i] = model->addVar(0, 1, 0, GRB_BINARY,
"v_" +
to_string(i));
384 BOOST_LOG_TRIVIAL(trace)
385 <<
"Using indicator constraints for complementarities.";
387 BOOST_LOG_TRIVIAL(trace)
388 <<
"Using bigM for complementarities with M=" << this->
bigM;
392 for (
const auto p :
Compl) {
397 expr =
bigM * u[p.first];
398 model->addConstr(expr, GRB_GREATER_EQUAL, z[p.first],
402 model->addGenConstrIndicator(
403 u[p.first], 1, z[p.first], GRB_LESS_EQUAL, 0,
409 model->addConstr(expr, GRB_GREATER_EQUAL, x[p.second],
413 model->addGenConstrIndicator(
414 v[p.first], 1, x[p.second], GRB_LESS_EQUAL, 0,
419 model->addConstr(u[p.first] + v[p.first], GRB_EQUAL, 1,
423 for (
auto i : FixVar)
424 model->addConstr(x[i], GRB_EQUAL, 0.0);
426 model->addConstr(z[i], GRB_EQUAL, 0.0);
429 model->set(GRB_DoubleParam_IntFeasTol, this->
eps_int);
430 model->set(GRB_DoubleParam_FeasibilityTol, this->
eps);
431 model->set(GRB_DoubleParam_OptimalityTol, this->
eps);
434 model->set(GRB_IntParam_SolutionLimit, 1);
438 }
catch (
const char *e) {
439 cerr <<
"Error in Game::LCP::LCPasMIP: " << e <<
'\n';
442 cerr <<
"String: Error in Game::LCP::LCPasMIP: " << e <<
'\n';
444 }
catch (exception &e) {
445 cerr <<
"Exception: Error in Game::LCP::LCPasMIP: " << e.what() <<
'\n';
447 }
catch (GRBException &e) {
448 cerr <<
"GRBException: Error in Game::LCP::LCPasMIP: " << e.getErrorCode()
449 <<
"; " << e.getMessage() <<
'\n';
464 const unsigned int nR =
M.n_rows;
465 const unsigned int nC =
M.n_cols;
468 throw "Game::LCP::errorCheck: M and q have unequal number of rows";
470 throw "Game::LCP::errorCheck: Inconsistency between number of leader " 475 return (nR ==
q.n_rows && nR +
nLeader == nC);
479 cout <<
"LCP with " << this->
nR <<
" rows and " << this->
nC <<
" columns." 492 const std::vector<arma::sp_mat *> tempAi = [](
spmat_Vec &uv) {
493 std::vector<arma::sp_mat *> v{};
494 for (
const auto &x : uv)
495 v.push_back(x.get());
498 const std::vector<arma::vec *> tempbi = [](
vec_Vec &uv) {
499 std::vector<arma::vec *> v{};
500 std::for_each(uv.begin(), uv.end(),
501 [&v](
const std::unique_ptr<arma::vec> &ptr) {
502 v.push_back(ptr.get());
506 arma::sp_mat A_common;
507 A_common = arma::join_cols(this->
_A, -this->
M);
508 arma::vec b_common = arma::join_cols(this->
_b, this->
q);
509 if (
Ai->size() == 1) {
510 A.zeros(
Ai->at(0)->n_rows + A_common.n_rows,
511 Ai->at(0)->n_cols + A_common.n_cols);
512 b.zeros(
bi->at(0)->n_rows + b_common.n_rows);
513 A = arma::join_cols(*
Ai->at(0), A_common);
514 b = arma::join_cols(*
bi->at(0), b_common);
521 const vector<arma::sp_mat *>
523 const vector<arma::vec *>
548 const unsigned int nPoly{
static_cast<unsigned int>(
Ai->size())};
552 "Game::ConvexHull: Empty vector of polyhedra given! Problem might be " 555 const unsigned int nC{
static_cast<unsigned int>(
Ai->front()->n_cols)};
556 const unsigned int nComm{
static_cast<unsigned int>(Acom.n_rows)};
558 if (nComm > 0 && Acom.n_cols !=
nC)
559 throw string(
"Game::ConvexHull: Inconsistent number of variables in the " 560 "common polyhedron");
561 if (nComm > 0 && nComm != bcom.n_rows)
562 throw string(
"Game::ConvexHull: Inconsistent number of rows in LHS and RHS " 563 "in the common polyhedron");
566 unsigned int nFinCons{0}, nFinVar{0};
567 if (nPoly !=
bi->size())
569 "Game::ConvexHull: Inconsistent number of LHS and RHS for polyhedra");
570 for (
unsigned int i = 0; i != nPoly; i++) {
571 if (
Ai->at(i)->n_cols !=
nC)
572 throw string(
"Game::ConvexHull: Inconsistent number of variables in the " 576 if (
Ai->at(i)->n_rows !=
bi->at(i)->n_rows)
577 throw string(
"Game::ConvexHull: Inconsistent number of rows in LHS and " 578 "RHS of polyhedra ") +
581 nFinCons +=
Ai->at(i)->n_rows;
584 nFinCons += nPoly * nComm;
586 const unsigned int FirstCons = nFinCons;
596 nFinVar = nPoly *
nC + nPoly +
598 A.zeros(nFinCons, nFinVar);
607 for (
unsigned int i = 0; i < nPoly; i++) {
608 BOOST_LOG_TRIVIAL(trace) <<
"Game::ConvexHull: Handling Polyhedron " 609 << i + 1 <<
" out of " << nPoly;
615 for (
unsigned int j = 0; j <
nC; j++) {
616 A.at(FirstCons + 2 * j, nC + (i * nC) + j) = 1;
617 A.at(FirstCons + 2 * j + 1, nC + (i * nC) + j) = -1;
620 A.at(FirstCons + nC * 2, nC + nPoly * nC + i) = 1;
621 A.at(FirstCons + nC * 2 + 1, nC + nPoly * nC + i) = -1;
625 for (
unsigned int j = 0; j <
nC; j++) {
626 A.at(FirstCons + 2 * j, j) = -1;
627 A.at(FirstCons + 2 * j + 1, j) = 1;
630 b.at(FirstCons + nC * 2) = 1;
631 b.at(FirstCons + nC * 2 + 1) = -1;
638 const unsigned int nFinCons,
639 const unsigned int nFinVar,
640 const vector<arma::sp_mat *>
642 const vector<arma::vec *>
648 const arma::vec &bcom
660 const unsigned int nPoly{
static_cast<unsigned int>(
Ai->size())};
661 const unsigned int nC{
static_cast<unsigned int>(
Ai->front()->n_cols)};
663 const unsigned int nCommnz{
664 static_cast<unsigned int>(Acom.n_nonzero + bcom.n_rows)};
665 for (
unsigned int i = 0; i < nPoly; i++) {
666 N +=
Ai->at(i)->n_nonzero;
667 N +=
bi->at(i)->n_rows;
673 arma::umat locations;
675 locations.zeros(2, N);
678 unsigned int count{0}, rowCount{0}, colCount{
nC};
679 for (
unsigned int i = 0; i < nPoly; i++) {
680 for (
auto it =
Ai->at(i)->begin(); it !=
Ai->at(i)->end();
683 locations(0, count) = rowCount + it.row();
684 locations(1, count) = colCount + it.col();
688 for (
unsigned int j = 0; j <
bi->at(i)->n_rows;
691 locations(0, count) = rowCount + j;
692 locations(1, count) =
nC +
nC * nPoly + i;
693 val(count) = -
bi->at(i)->at(j);
696 rowCount +=
Ai->at(i)->n_rows;
699 for (
auto it = Acom.begin(); it != Acom.end(); ++it)
701 locations(0, count) = rowCount + it.row();
702 locations(1, count) = colCount + it.col();
706 for (
unsigned int j = 0; j < bcom.n_rows; ++j)
708 locations(0, count) = rowCount + j;
709 locations(1, count) =
nC +
nC * nPoly + i;
710 val(count) = -bcom.at(j);
713 rowCount += Acom.n_rows;
717 A = arma::sp_mat(locations, val, nFinCons, nFinVar);
739 throw "Game::LPSolve: Inconsistency in no of Vars in isFeas()";
741 throw "Game::LPSolve: Inconsistency in no of Constr in isFeas()";
743 arma::vec sol = arma::vec(c.n_rows, arma::fill::zeros);
744 const double lb = Positivity ? 0 : -GRB_INFINITY;
747 GRBModel model = GRBModel(env);
751 for (
unsigned int i = 0; i <
nC; i++)
752 x[i] = model.addVar(lb, GRB_INFINITY, c.at(i), GRB_CONTINUOUS,
755 for (
unsigned int i = 0; i <
nR; i++) {
757 for (
auto j = A.begin_row(i); j != A.end_row(i); ++j)
758 lin += (*j) * x[j.col()];
759 a[i] = model.addConstr(lin, GRB_LESS_EQUAL, b.at(i));
761 model.set(GRB_IntParam_OutputFlag,
VERBOSE);
762 model.set(GRB_IntParam_DualReductions, 0);
764 status = model.get(GRB_IntAttr_Status);
765 if (status == GRB_OPTIMAL)
766 for (
unsigned int i = 0; i <
nC; i++)
767 sol.at(i) = x[i].get(GRB_DoubleAttr_X);
784 if (model->get(GRB_IntAttr_Status) == GRB_LOADED)
786 auto status = model->get(GRB_IntAttr_Status);
787 if (!(status == GRB_OPTIMAL || status == GRB_SUBOPTIMAL ||
788 status == GRB_SOLUTION_LIMIT))
793 for (
unsigned int i = 0; i <
nR; i++) {
794 x[i] = model->getVarByName(
"x_" +
to_string(i)).get(GRB_DoubleAttr_X);
796 z[i] = model->getVarByName(
"z_" +
to_string(i)).get(GRB_DoubleAttr_X);
798 for (
unsigned int i = nR; i <
nC; i++)
799 x[i] = model->getVarByName(
"x_" +
to_string(i)).get(GRB_DoubleAttr_X);
825 vector<short int> solEncoded(
nR, 0);
826 for (
const auto p :
Compl) {
835 BOOST_LOG_TRIVIAL(error) <<
"Infeasible point given! Stay alert! " << x(j)
836 <<
" " << z(i) <<
" with i=" << i;
867 const unsigned int nCompl = this->
Compl.size();
868 vector<short int> encoding = this->
solEncode(x);
869 std::stringstream enc_str;
870 for (
auto vv : encoding)
871 enc_str << vv <<
" ";
872 BOOST_LOG_TRIVIAL(trace)
873 <<
"Game::LCP::addPolyFromX: Handling deviation with encoding: " 874 << enc_str.str() <<
'\n';
877 std::vector<short int> bin =
num_to_vec(i, nCompl);
878 if (encoding < bin) {
879 BOOST_LOG_TRIVIAL(trace) <<
"LCP::addPolyFromX: Encoding " << i
880 <<
" already in All Polyhedra! ";
886 BOOST_LOG_TRIVIAL(trace)
887 <<
"LCP::addPolyFromX: New encoding not in All Polyhedra! ";
890 for (
short &i : encoding) {
901 const vector<short int>
928 BOOST_LOG_TRIVIAL(trace) <<
"Game::LCP::FixToPoly: Working on polyhedron" 932 BOOST_LOG_TRIVIAL(trace) <<
"Game::LCP::FixToPoly: Previously known " 933 "infeasible polyhedron. Not added" 940 BOOST_LOG_TRIVIAL(trace)
941 <<
"Game::LCP::FixToPoly: Previously added polyhedron. Not added " 947 unique_ptr<arma::sp_mat> Aii =
948 unique_ptr<arma::sp_mat>(
new arma::sp_mat(
nR,
nC));
950 unique_ptr<arma::vec> bii =
951 unique_ptr<arma::vec>(
new arma::vec(
nR, arma::fill::zeros));
952 for (
unsigned int i = 0; i < this->
nR; i++) {
953 if (Fix.at(i) == 0) {
955 "Error in Game::LCP::FixToPoly. 0s not allowed in argument vector");
959 for (
auto j = this->
M.begin_row(i); j != this->
M.end_row(i); ++j)
961 Aii->at(i, j.col()) =
963 bii->at(i) = -this->
q(i);
968 Aii->at(i, varpos) = 1;
972 bool add = !checkFeas;
978 custAi->push_back(std::move(Aii));
979 custbi->push_back(std::move(bii));
982 this->
Ai->push_back(std::move(Aii));
983 this->
bi->push_back(std::move(bii));
991 const unsigned long int 998 const vector<short int> &Fix
1002 unsigned long int FixNumber =
vec_to_num(Fix);
1004 BOOST_LOG_TRIVIAL(trace) <<
"Game::LCP::checkPolyFeas: Previously known " 1005 "infeasible polyhedron. " 1011 BOOST_LOG_TRIVIAL(trace) <<
"Game::LCP::checkPolyFeas: Previously known " 1012 "feasible polyhedron." 1017 unsigned int count{0};
1021 for (
auto i : Fix) {
1023 model.getVarByName(
"z_" +
to_string(count)).set(GRB_DoubleAttr_UB, 0);
1029 .set(GRB_DoubleAttr_UB, 0);
1032 model.set(GRB_IntParam_OutputFlag,
VERBOSE);
1034 if (model.get(GRB_IntAttr_Status) == GRB_OPTIMAL) {
1038 BOOST_LOG_TRIVIAL(trace)
1039 <<
"Game::LCP::checkPolyFeas: Detected infeasibility of " << FixNumber
1040 <<
" (GRB_STATUS=" << model.get(GRB_IntAttr_Status) <<
")";
1044 }
catch (
const char *e) {
1045 cerr <<
"Error in Game::LCP::FixToPoly: " << e <<
'\n';
1047 }
catch (
string e) {
1048 cerr <<
"String: Error in Game::LCP::FixToPoly: " << e <<
'\n';
1050 }
catch (exception &e) {
1051 cerr <<
"Exception: Error in Game::LCP::FixToPoly: " << e.what() <<
'\n';
1053 }
catch (GRBException &e) {
1054 cerr <<
"GRBException: Error in Game::LCP::FixToPoly: " << e.getErrorCode()
1055 <<
": " << e.getMessage() <<
'\n';
1062 const vector<short int>
1091 vector<short int> MyFix(Fix);
1093 for (i = 0; i < this->
nR; i++) {
1094 if (Fix.at(i) == 0) {
1101 this->
FixToPolies(MyFix, checkFeas, custom, custAi, custbi);
1103 this->
FixToPolies(MyFix, checkFeas, custom, custAi, custbi);
1105 this->
FixToPoly(Fix, checkFeas, custom, custAi, custbi);
1121 const bool isInfeas =
1124 if (!isAll && !isInfeas) {
1135 const bool isInfeas =
1139 if (!isAll && !isInfeas) {
1147 std::uniform_int_distribution<unsigned long int> dist(
1152 unsigned long int randomPolyId = dist(engine);
1155 if (!isAll && !isInfeas)
1156 return randomPolyId;
1160 BOOST_LOG_TRIVIAL(error)
1161 <<
"Error in Game::LCP::getNextPoly: unrecognized method " 1168 std::set<std::vector<short int>>
1170 std::set<std::vector<short int>> Polys) {
1184 const unsigned int nCompl = this->
Compl.size();
1188 BOOST_LOG_TRIVIAL(warning)
1189 <<
"Warning in Game::LCP::randomPoly: " 1190 <<
"Cannot add " << nPoly <<
" polyhedra. Promising a maximum of " 1200 BOOST_LOG_TRIVIAL(error) <<
"nPoly can't be negative, i.e., " << nPoly;
1202 "Error in Game::LCP::addAPoly: nPoly reached a negative value!");
1205 bool complete{
false};
1207 unsigned long int choice_decimal = this->
getNextPoly(method);
1211 const std::vector<short int> choice =
num_to_vec(choice_decimal, nCompl);
1212 auto added = this->
FixToPoly(choice,
true);
1215 Polys.insert(choice);
1216 if (Polys.size() == nPoly) {
1227 BOOST_LOG_TRIVIAL(warning)
1228 <<
"Warning in Game::LCP::addThePoly: Cannot add " << decimalEncoding
1229 <<
" polyhedra, since it does not exist!";
1232 const unsigned int nCompl = this->
Compl.size();
1233 const std::vector<short int> choice =
num_to_vec(decimalEncoding, nCompl);
1247 vector<short int> Fix = vector<short int>(
nR, 0);
1251 if (this->
Ai->empty()) {
1252 BOOST_LOG_TRIVIAL(warning)
1253 <<
"Empty vector of polyhedra given! Problem might be infeasible." 1256 unique_ptr<arma::sp_mat> A(
new arma::sp_mat(1, this->
M.n_cols));
1257 unique_ptr<arma::vec> b(
new arma::vec(1));
1259 this->
Ai->push_back(std::move(A));
1260 this->
bi->push_back(std::move(b));
1274 if (this->
Ai->empty())
1276 const unsigned int Nx_old{
static_cast<unsigned int>(QP_obj.
C.n_cols)};
1280 BOOST_LOG_TRIVIAL(trace) <<
"LCP::makeQP: No. feasible polyhedra: " 1283 const unsigned int Ncons{
static_cast<unsigned int>(QP_cons.
B.n_rows)};
1284 const unsigned int Ny{
static_cast<unsigned int>(QP_cons.
B.n_cols)};
1286 QP_cons.
A.zeros(Ncons, Nx_old);
1291 QP.
set(QP_obj, QP_cons);
1306 unique_ptr<GRBModel> model(
new GRBModel(this->
RlxdModel));
1307 GRBQuadExpr obj = 0;
1310 for (
const auto p : this->
Compl) {
1311 unsigned int i = p.first;
1312 unsigned int j = p.second;
1313 z[i] = model->getVarByName(
"z_" +
to_string(i));
1314 x[i] = model->getVarByName(
"x_" +
to_string(j));
1317 model->setObjective(obj, GRB_MINIMIZE);
1321 int status = model->get(GRB_IntAttr_Status);
1322 if (status != GRB_OPTIMAL ||
1323 model->get(GRB_DoubleAttr_ObjVal) > this->
eps)
1324 throw "Game::LCP::LCPasQP: LCP infeasible";
1325 }
catch (
const char *e) {
1326 cerr <<
"Error in Game::LCP::LCPasQP: " << e <<
'\n';
1328 }
catch (
string e) {
1329 cerr <<
"String: Error in Game::LCP::LCPasQP: " << e <<
'\n';
1331 }
catch (exception &e) {
1332 cerr <<
"Exception: Error in Game::LCP::LCPasQP: " << e.what() <<
'\n';
1334 }
catch (GRBException &e) {
1335 cerr <<
"GRBException: Error in Game::LCP::LCPasQP: " << e.getErrorCode()
1336 <<
"; " << e.getMessage() <<
'\n';
1353 return this->
LCPasMIP({}, {}, solve);
1356 unique_ptr<GRBModel>
1358 const arma::vec &x_minus_i,
bool solve)
1370 unique_ptr<GRBModel> model = this->
LCPasMIP(
true);
1372 model->set(GRB_IntParam_SolutionLimit, GRB_MAXINT);
1373 if (C.n_cols != x_minus_i.n_rows)
1374 throw string(
"Game::LCP::LCPasMILP: Bad size of x_minus_i");
1375 if (c.n_rows != C.n_rows)
1376 throw string(
"Game::LCP::LCPasMILP: Bad size of c");
1377 arma::vec Cx(c.n_rows, arma::fill::zeros);
1380 }
catch (exception &e) {
1381 cerr <<
"Exception in Game::LCP::MPECasMIQP: " << e.what() <<
'\n';
1383 }
catch (
string &e) {
1384 cerr <<
"Exception in Game::LCP::MPECasMIQP: " << e <<
'\n';
1387 arma::vec obj = c + Cx;
1389 for (
unsigned int i = 0; i < obj.n_rows; i++)
1390 expr += obj.at(i) * model->getVarByName(
"x_" +
to_string(i));
1391 model->setObjective(expr, GRB_MINIMIZE);
1392 model->set(GRB_IntParam_OutputFlag,
VERBOSE);
1398 unique_ptr<GRBModel>
1400 const arma::vec &c,
const arma::vec &x_minus_i,
1413 auto model = this->
MPECasMILP(C, c, x_minus_i,
false);
1417 if (Q.n_nonzero != 0)
1419 GRBLinExpr linexpr = model->getObjective(0);
1420 GRBQuadExpr expr{linexpr};
1421 for (
auto it = Q.begin(); it != Q.end(); ++it)
1422 expr += (*it) * model->getVarByName(
"x_" +
to_string(it.row())) *
1423 model->getVarByName(
"x_" +
to_string(it.col()));
1424 model->setObjective(expr, GRB_MINIMIZE);
1432 ofstream outfile(filename, append ? ios::app : ios::out);
1434 outfile <<
nR <<
" rows and " <<
nC <<
" columns in the LCP\n";
1436 <<
" \nnLeader: " <<
nLeader <<
"\n\n";
1438 outfile <<
"M: " << this->
M;
1439 outfile <<
"q: " << this->
q;
1440 outfile <<
"Complementarity: \n";
1441 for (
const auto &p : this->
Compl)
1442 outfile <<
"<" << p.first <<
", " << p.second <<
">" 1444 outfile <<
"A: " << this->
_A;
1445 outfile <<
"b: " << this->
_b;
1460 BOOST_LOG_TRIVIAL(trace) <<
"Saved LCP to file " << filename;
1465 throw string(
"Error in LCP::load: To load LCP from file, it has to be " 1466 "constructed using LCP(GRBEnv*) constructor");
1470 if (headercheck !=
"LCP")
1471 throw string(
"Error in LCP::load: In valid header - ") + headercheck;
1491 this->
nLeader = this->LeadEnd - this->LeadStart + 1;
1493 for (
unsigned int i = 0; i < M.n_rows; i++) {
1494 unsigned int count = i < LeadStart ? i : i +
nLeader;
1495 Compl.push_back({i, count});
1498 [](std::pair<unsigned int, unsigned int> a,
1499 std::pair<unsigned int, unsigned int> b) {
1500 return a.first <= b.first;
1507 std::stringstream ss;
1508 ss <<
"\tProven feasible: ";
1532 const unsigned int nPoly = this->
conv_Npoly();
1534 BOOST_LOG_TRIVIAL(error) <<
"Error in Game::LCP::conv_PolyPosition: " 1535 "Invalid argument. Out of bounds for i";
1536 throw std::string(
"Error in Game::LCP::conv_PolyPosition: Invalid " 1537 "argument. Out of bounds for i");
1539 const unsigned int nC = this->
M.n_cols;
1552 const unsigned int nPoly = this->
conv_Npoly();
1557 throw std::string(
"Error in Game::LCP::conv_PolyWt: " 1558 "Invalid argument. Out of bounds for i");
1560 const unsigned int nC = this->
M.n_cols;
1562 return nC + nPoly * nC + i;
std::set< unsigned long int > AllPolyhedra
Decimal encoding of polyhedra that have been enumerated.
bool operator>(vector< int > Fix1, vector< int > Fix2)
std::set< unsigned long int > knownInfeas
Decimal encoding of polyhedra known to be infeasible.
unsigned int conv_PolyWt(const unsigned long int i) const
Class to handle parameterized quadratic programs(QP)
std::set< unsigned long int > feasiblePoly
Decimal encoding of polyhedra that have been enumerated.
string to_string(const Game::EPECsolveStatus st)
QP_Param & set(const arma::sp_mat &Q, const arma::sp_mat &C, const arma::sp_mat &A, const arma::sp_mat &B, const arma::vec &c, const arma::vec &b) final
Setting the data, while keeping the input objects intact.
long int appendRead(vec &matrix, const std::string in, long int pos, const std::string header="")
LCP & EnumerateAll(bool solveLP=true)
Brute force computation of LCP feasible region.
bool checkPolyFeas(const unsigned long int &decimalEncoding)
bool FixToPoly(const std::vector< short int > Fix, bool checkFeas=false, bool custom=false, spmat_Vec *custAi={}, vec_Vec *custbi={})
Computes the equation of the feasibility polyhedron corresponding to the given Fix.
void defConst(GRBEnv *env)
Assign default values to LCP attributes.
arma::vec LPSolve(const arma::sp_mat &A, const arma::vec &b, const arma::vec &c, int &status, bool Positivity=false)
unsigned long int maxTheoreticalPoly
unsigned long int vec_to_num(std::vector< short int > binary)
LCP & makeQP(Game::QP_objective &QP_obj, Game::QP_Param &QP)
struct to handle the constraint params of MP_Param/QP_Param
void write(std::string filename, bool append=true) const
arma::sp_mat M
M in that defines the LCP.
void compConvSize(arma::sp_mat &A, const unsigned int nFinCons, const unsigned int nFinVar, const std::vector< arma::sp_mat *> *Ai, const std::vector< arma::vec *> *bi, const arma::sp_mat &Acom, const arma::vec &bcom)
bool errorCheck(bool throwErr=true) const
void appendSave(const vec &matrix, const std::string out, const std::string header="", bool erase=false)
long double eps
The threshold for optimality and feasability tollerances.
std::unique_ptr< GRBModel > MPECasMILP(const arma::sp_mat &C, const arma::vec &c, const arma::vec &x_minus_i, bool solve=false)
Helps solving an LCP as an MIP.
std::vector< std::pair< unsigned int, unsigned int > > perps
std::vector< std::unique_ptr< arma::sp_mat > > spmat_Vec
arma::vec q
q in that defines the LCP
arma::sp_mat RewriteLeadCons() const
Rewrites leader constraint adjusting for dual variables. Rewrites leader constraints given earlier wi...
unsigned int ConvexHull(const std::vector< arma::sp_mat *> *Ai, const std::vector< arma::vec *> *bi, arma::sp_mat &A, arma::vec &b, const arma::sp_mat Acom={}, const arma::vec bcom={})
int reverseSequentialPolyCounter
std::unique_ptr< GRBModel > LCPasQP(bool solve=false)
Solves the LCP as a QP using Gurobi.
long int addPolyMethodSeed
std::unique_ptr< vec_Vec > bi
Vector to contain the RHS of inner approx polyhedra.
arma::sp_mat resize_patch(const arma::sp_mat &Mat, const unsigned int nR, const unsigned int nC)
bool madeRlxdModel
Keep track if LCP::RlxdModel is made.
perps Compl
Compl stores data in <Eqn, Var> form.
bool isZero(const T val) const
Class to handle and solve linear complementarity problems.
unsigned int conv_PolyPosition(const unsigned long int i) const
std::unique_ptr< GRBModel > LCPasMIP(std::vector< unsigned int > FixEq={}, std::vector< unsigned int > FixVar={}, bool solve=false)
const NashGame & FormulateLCP(arma::sp_mat &M, arma::vec &q, perps &Compl, bool writeToFile=false, std::string M_name="dat/LCP.txt", std::string q_name="dat/q.txt") const
bool useIndicators
constraints. BigM formulation otherwise
std::string feas_detail_str() const
Adds the next polyhedra by selecting random feasible one.
bool extractSols(GRBModel *model, arma::vec &z, arma::vec &x, bool extractZ=false) const
Extracts variable and equation values from a solved Gurobi model for LCP.
std::vector< short int > solEncode(GRBModel *model) const
Given a Gurobi model, extracts variable values and equation values, encodes it in 0/+1/-1 format and ...
Adds polyhedra by selecting them in order.
std::unique_ptr< spmat_Vec > Ai
Vector to contain the LHS of inner approx polyhedra.
LCP()=delete
Class has no default constructors.
LCP & FixToPolies(const std::vector< short int > Fix, bool checkFeas=false, bool custom=false, spmat_Vec *custAi={}, vec_Vec *custbi={})
Computes the equation of the feasibility polyhedron corresponding to the given Fix.
long int load(std::string filename, long int pos=0)
unsigned int conv_Npoly() const
unsigned int sequentialPolyCounter
void print(std::string end="\)
Print a summary of the LCP.
unsigned int ConvexHull(arma::sp_mat &A, arma::vec &b)
struct to handle the objective params of MP_Param/QP_Param
arma::vec getMCLeadRHS() const
void makeRelaxed()
Makes a Gurobi object that relaxes complementarity constraints in an LCP.
bool addThePoly(const unsigned long int &decimalEncoding)
std::unique_ptr< GRBModel > MPECasMIQP(const arma::sp_mat &Q, const arma::sp_mat &C, const arma::vec &c, const arma::vec &x_minus_i, bool solve=false)
Helps solving an LCP as an MIQPs.
std::vector< std::unique_ptr< arma::vec > > vec_Vec
long double bigM
bigM used to rewrite the LCP as MIP
unsigned long int getNextPoly(Game::EPECAddPolyMethod method)
std::unique_ptr< GRBModel > LCP_Polyhed_fixed(std::vector< unsigned int > FixEq={}, std::vector< unsigned int > FixVar={})
void save(std::string filename, bool erase=true) const
std::set< std::vector< short int > > addAPoly(unsigned long int nPoly=1, Game::EPECAddPolyMethod method=Game::EPECAddPolyMethod::sequential, std::set< std::vector< short int >> Polys={})
Class to model Nash-cournot games with each player playing a QP.
bool operator==(vector< short int > Fix1, vector< short int > Fix2)
Checks if two vector<int> are of same size and hold same values in the same order.
unsigned int feasiblePolyhedra
void initializeNotProcessed()
LCP & addPolyFromX(const arma::vec &x, bool &ret)
std::vector< short int > num_to_vec(unsigned long int number, const unsigned int &nCompl)