5 #include <boost/log/trivial.hpp> 6 #include <boost/program_options.hpp> 12 using namespace Utils;
23 return (arma::min(arma::min(abs(M))) <= tol);
36 return (arma::min(arma::min(abs(M))) <= tol);
41 cout <<
"<" << p.first <<
", " << p.second <<
">" 47 ost <<
"<" << p.first <<
", " << p.second <<
">" 53 os <<
"Quadratic program with linear inequality constraints: " <<
'\n';
54 os << Q.
getNy() <<
" decision variables parametrized by " << Q.
getNx()
55 <<
" variables" <<
'\n';
56 os << Q.
getb().n_rows <<
" linear inequalities" <<
'\n' <<
'\n';
78 this->getQ().save(filename +
"_Q.txt", arma::file_type::arma_ascii);
79 this->getC().save(filename +
"_C.txt", arma::file_type::arma_ascii);
80 this->getA().save(filename +
"_A.txt", arma::file_type::arma_ascii);
81 this->getB().save(filename +
"_B.txt", arma::file_type::arma_ascii);
82 this->getc().save(filename +
"_c.txt", arma::file_type::arma_ascii);
83 this->getb().save(filename +
"_b.txt", arma::file_type::arma_ascii);
88 file.open(filename, append ? ios::app : ios::out);
90 file <<
"\n\nOBJECTIVES\n";
91 file <<
"Q:" << this->getQ();
92 file <<
"C:" << this->getC();
93 file <<
"c\n" << this->getc();
94 file <<
"\n\nCONSTRAINTS\n";
95 file <<
"A:" << this->getA();
96 file <<
"B:" << this->getB();
97 file <<
"b\n" << this->getb();
127 A = arma::join_rows(arma::zeros<arma::sp_mat>(this->Ncons, pars), A);
130 C = arma::join_rows(arma::zeros<arma::sp_mat>(this->Ny, pars), C);
135 arma::sp_mat A_temp =
136 arma::join_rows(A.cols(0, position - 1),
137 arma::zeros<arma::sp_mat>(this->Ncons, pars));
138 if (static_cast<unsigned int>(position) < A.n_cols) {
139 A = arma::join_rows(A_temp, A.cols(position, A.n_cols - 1));
146 arma::sp_mat C_temp = arma::join_rows(
147 C.cols(0, position - 1), arma::zeros<arma::sp_mat>(this->Ny, pars));
148 if (static_cast<unsigned int>(position) < C.n_cols) {
149 C = arma::join_rows(C_temp, C.cols(position, C.n_cols - 1));
171 this->Ny = this->Q.n_rows;
172 this->Nx = this->C.n_cols;
173 this->Ncons = this->b.
size();
179 const arma::sp_mat &A,
const arma::sp_mat &B,
180 const arma::vec &c,
const arma::vec &b)
190 throw string(
"Error in MP_Param::set: Invalid data");
195 arma::sp_mat &&A, arma::sp_mat &&B,
196 arma::vec &&c, arma::vec &&b)
206 throw string(
"Error in MP_Param::set: Invalid data");
212 return this->
set(obj.
Q, obj.
C, cons.
A, cons.
B, obj.
c, cons.
b);
216 return this->
set(obj.Q, obj.C, cons.A, cons.B, obj.c, cons.b);
238 if (this->Q.n_cols != Ny) {
241 if (this->A.n_cols != Nx) {
244 if (this->B.n_cols != Ny) {
247 if (this->C.n_rows != Ny) {
250 if (this->c.size() != Ny) {
253 if (this->A.n_rows != Ncons) {
256 if (this->B.n_rows != Ncons) {
265 unsigned int Ny = obj.
Q.n_rows;
266 unsigned int Nx = obj.
C.n_cols;
267 unsigned int Ncons = cons.
b.size();
268 if (checkobj && obj.
Q.n_cols != Ny) {
271 if (checkobj && obj.
C.n_rows != Ny) {
274 if (checkobj && obj.
c.size() != Ny) {
277 if (checkcons && cons.
A.n_cols != Nx) {
280 if (checkcons && cons.
B.n_cols != Ny) {
283 if (checkcons && cons.
A.n_rows != Ncons) {
286 if (checkcons && cons.
B.n_rows != Ncons) {
314 for (
unsigned int i = 0; i < Ny; i++)
315 y[i] = this->QuadModel.addVar(0, GRB_INFINITY, 0, GRB_CONTINUOUS,
318 for (
auto val = Q.begin(); val != Q.end(); ++val) {
320 double value = (*val);
323 yQy += 0.5 * y[i] * value * y[j];
325 QuadModel.setObjective(yQy, GRB_MINIMIZE);
327 this->made_yQy =
true;
343 if (x.size() != this->Nx)
345 throw "Game::QP_Param::solveFixed: Invalid argument size: " +
347 unique_ptr<GRBModel> model(
new GRBModel(this->QuadModel));
349 GRBQuadExpr yQy = model->getObjective();
354 for (
unsigned int i = 0; i < this->Ny; i++) {
355 y[i] = model->getVarByName(
"y_" +
to_string(i));
356 yQy += (Cx[i] + c[i]) * y[i];
358 model->setObjective(yQy, GRB_MINIMIZE);
359 for (
unsigned int i = 0; i < this->Ncons; i++) {
361 for (
auto j = B.begin_row(i); j != B.end_row(i); ++j)
362 LHS += (*j) * y[j.col()];
363 model->addConstr(LHS, GRB_LESS_EQUAL, b[i] - Ax[i]);
366 model->set(GRB_IntParam_OutputFlag, 0);
368 }
catch (
const char *e) {
369 cerr <<
" Error in Game::QP_Param::solveFixed: " << e <<
'\n';
372 cerr <<
"String: Error in Game::QP_Param::solveFixed: " << e <<
'\n';
374 }
catch (exception &e) {
375 cerr <<
"Exception: Error in Game::QP_Param::solveFixed: " << e.what()
378 }
catch (GRBException &e) {
379 cerr <<
"GRBException: Error in Game::QP_Param::solveFixed: " 380 << e.getErrorCode() <<
"; " << e.getMessage() <<
'\n';
403 MP_Param::addDummy(pars, vars, position);
404 }
catch (
const char *e) {
405 cerr <<
" Error in Game::QP_Param::addDummy: " << e <<
'\n';
408 cerr <<
"String: Error in Game::QP_Param::addDummy: " << e <<
'\n';
410 }
catch (exception &e) {
411 cerr <<
"Exception: Error in Game::QP_Param::addDummy: " << e.what()
428 if (!this->dataCheck()) {
429 throw string(
"Inconsistent data for KKT of Game::QP_Param::KKT");
435 arma::join_rows(this->Q, this->B.t()),
436 arma::join_rows(-this->B,
437 arma::zeros<arma::sp_mat>(this->Ncons, this->Ncons)));
439 N = arma::join_cols(this->C, -this->A);
441 q = arma::join_cols(this->c, this->b);
448 const arma::sp_mat &A,
const arma::sp_mat &B,
449 const arma::vec &c,
const arma::vec &b)
452 this->made_yQy =
false;
454 MP_Param::set(Q, C, A, B, c, b);
455 }
catch (
string &e) {
456 cerr <<
"String: " << e <<
'\n';
457 throw string(
"Error in QP_Param::set: Invalid Data");
463 arma::sp_mat &&A, arma::sp_mat &&B,
464 arma::vec &&c, arma::vec &&b)
467 this->made_yQy =
false;
469 MP_Param::set(Q, C, A, B, c, b);
470 }
catch (
string &e) {
471 cerr <<
"String: " << e <<
'\n';
472 throw string(
"Error in QP_Param::set: Invalid Data");
481 return this->
set(move(obj.Q), move(obj.C), move(cons.A), move(cons.B),
482 move(obj.c), move(cons.b));
487 return this->
set(obj.
Q, obj.
C, cons.
A, cons.
B, obj.
c, cons.
b);
491 bool checkFeas,
double tol)
const {
498 if (y.n_rows != this->getNy())
499 throw string(
"Error in QP_Param::computeObjective: Invalid size of y");
500 if (x.n_rows != this->getNx())
501 throw string(
"Error in QP_Param::computeObjective: Invalid size of x");
503 arma::vec slack = A * x + B * y - b;
505 if (slack.max() >= tol)
510 arma::vec obj = 0.5 * y.t() * Q * y + (C * x).t() * y + c.t() * y;
526 BOOST_LOG_TRIVIAL(trace) <<
"Saved QP_Param to file " << filename;
547 arma::sp_mat Q, A, B, C;
551 if (headercheck !=
"QP_Param")
552 throw string(
"Error in QP_Param::load: In valid header - ") + headercheck;
559 this->
set(Q, C, A, B, c, b);
563 arma::sp_mat MC, arma::vec MCRHS,
564 unsigned int n_LeadVar, arma::sp_mat LeadA,
566 : env{e}, LeaderConstraints{LeadA}, LeaderConsRHS{LeadRHS}
588 this->n_LeadVar = n_LeadVar;
589 this->Nplayers = Players.size();
590 this->Players = Players;
591 this->MarketClearing = MC;
594 this->primal_position.resize(this->Nplayers + 1);
595 this->dual_position.resize(this->Nplayers + 1);
596 this->set_positions();
613 for (
unsigned int i = 0; i < this->
Nplayers; ++i)
614 this->
Players.at(i)->save(filename,
false);
616 string(
"NashGame::MarketClearing"),
false);
619 string(
"NashGame::LeaderConstraints"),
false);
621 string(
"NashGame::LeaderConsRHS"),
false);
624 BOOST_LOG_TRIVIAL(trace) <<
"Saved NashGame to file " << filename;
648 throw string(
"Error in NashGame::load: To load NashGame from file, it has " 649 "to be constructed using NashGame(GRBEnv*) constructor");
652 if (headercheck !=
"NashGame")
653 throw string(
"Error in NashGame::load: In valid header - ") + headercheck;
657 vector<shared_ptr<QP_Param>>
Players;
658 Players.resize(Nplayers);
659 for (
unsigned int i = 0; i <
Nplayers; ++i) {
662 Players.at(i) = temp;
663 pos = Players.at(i)->load(filename, pos);
667 string(
"NashGame::MarketClearing"));
672 string(
"NashGame::LeaderConstraints"));
675 string(
"NashGame::LeaderConsRHS"));
678 string(
"NashGame::n_LeadVar"));
702 unsigned int pr_cnt{0},
704 for (
unsigned int i = 0; i <
Nplayers; i++) {
706 pr_cnt +=
Players.at(i)->getNy();
715 for (
unsigned int i = 0; i <
Nplayers; i++) {
717 dl_cnt +=
Players.at(i)->getb().n_rows;
748 unsigned int NvarFollow{0}, NvarLead{0};
755 M.zeros(NvarFollow, NvarLead);
759 for (
unsigned int i = 0; i <
Nplayers; i++) {
760 this->
Players[i]->KKT(Mi[i], Ni[i], qi[i]);
761 unsigned int Nprim, Ndual;
762 Nprim = this->
Players[i]->getNy();
763 Ndual = this->
Players[i]->getA().n_rows;
766 BOOST_LOG_TRIVIAL(trace) <<
"Game::NashGame::FormulateLCP: Region 1";
775 BOOST_LOG_TRIVIAL(trace) <<
"Game::NashGame::FormulateLCP: Region 2";
779 Mi[i].submat(0, 0, Nprim - 1, Nprim - 1);
781 BOOST_LOG_TRIVIAL(trace) <<
"Game::NashGame::FormulateLCP: Region 3";
790 BOOST_LOG_TRIVIAL(trace) <<
"Game::NashGame::FormulateLCP: Region 4";
795 Mi[i].submat(0, Nprim, Nprim - 1, Nprim + Ndual - 1);
798 BOOST_LOG_TRIVIAL(trace) <<
"Game::NashGame::FormulateLCP: Region RHS";
800 qi[i].subvec(0, Nprim - 1);
803 Compl.push_back({j, j});
806 BOOST_LOG_TRIVIAL(trace) <<
"Game::NashGame::FormulateLCP: Region 5";
813 Ni[i].submat(Nprim, 0, Ni[i].n_rows - 1,
816 BOOST_LOG_TRIVIAL(trace) <<
"Game::NashGame::FormulateLCP: Region 6";
821 Mi[i].submat(Nprim, 0, Nprim + Ndual - 1, Nprim - 1);
823 BOOST_LOG_TRIVIAL(trace) <<
"Game::NashGame::FormulateLCP: Region 7";
833 BOOST_LOG_TRIVIAL(trace) <<
"Game::NashGame::FormulateLCP: Region 8";
837 Mi[i].submat(Nprim, Nprim, Nprim + Ndual - 1, Nprim + Ndual - 1);
839 BOOST_LOG_TRIVIAL(trace) <<
"Game::NashGame::FormulateLCP: Region RHS";
842 qi[i].subvec(Nprim, qi[i].n_rows - 1);
845 Compl.push_back({j, j + n_LeadVar});
848 BOOST_LOG_TRIVIAL(trace) <<
"Game::NashGame::FormulateLCP: MC RHS";
849 if (this->
MCRHS.n_elem >= 1)
857 Compl.push_back({j, j});
860 M.save(M_name, arma::coord_ascii);
861 q.save(q_name, arma::arma_ascii);
876 arma::sp_mat A_out_expl, A_out_MC, A_out;
877 unsigned int NvarLead{0};
882 unsigned int n_Row, n_Col;
885 A_out_expl.zeros(n_Row, NvarLead);
894 A_in.cols(this->MC_dual_position, n_Col - 1);
896 if (this->
MCRHS.n_rows) {
898 A_out_MC.submat(0, 0, this->
MCRHS.n_rows - 1,
900 A_out_MC.submat(this->
MCRHS.n_rows, 0, 2 * this->MCRHS.n_rows - 1,
903 return arma::join_cols(A_out_expl, A_out_MC);
904 }
catch (
const char *e) {
905 cerr <<
"Error in NashGame::RewriteLeadCons: " << e <<
'\n';
908 cerr <<
"String: Error in NashGame::RewriteLeadCons: " << e <<
'\n';
910 }
catch (exception &e) {
911 cerr <<
"Exception: Error in NashGame::RewriteLeadCons: " << e.what()
944 arma::zeros<arma::sp_mat>(nnR, par));
959 BOOST_LOG_TRIVIAL(error)
960 <<
"addDummy at non-final position not implemented";
977 throw string(
"Error in NashGame::addLeadCons: Leader constraint size " 978 "incompatible --- ") +
992 file.open(filename +
".nash", append ? ios::app : ios::out);
994 file <<
"\n\n\n\n\n\n\n";
998 file <<
"\nMCRHS\n" << this->
MCRHS;
1011 for (
const auto &pl : this->
Players) {
1013 file <<
"--------------------------------------------------\n";
1014 file.open(filename +
".nash", ios::app);
1015 file <<
"\n\n\n\n PLAYER " << count++ <<
"\n\n";
1017 pl->QP_Param::write(filename +
".nash",
true);
1020 file.open(filename +
".nash", ios::app);
1021 file <<
"--------------------------------------------------\n";
1022 file <<
"\nPrimal Positions:\t";
1025 file <<
"\nDual Positions:\t";
1030 file <<
"\nnLeader:\t" << this->
n_LeadVar;
1037 file <<
"\n\n\n KKT CONDITIONS - LCP\n";
1038 file <<
"\nM: " << M;
1039 file <<
"\nq:\n" << q;
1040 file <<
"\n Complementarities:\n";
1041 for (
const auto &p : Compl)
1042 file <<
"<" << p.first <<
", " << p.second <<
">" 1046 file <<
"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n";
1052 unsigned int player,
1071 unsigned int nStart, nEnd;
1078 solOther.zeros(nVar - nEnd + nStart);
1080 solOther.subvec(0, nStart - 1) = x.subvec(0, nStart - 1);
1082 solOther.subvec(nStart, nVar + nStart - nEnd - 1) =
1086 solOther.zeros(nVar - nEnd + nStart);
1087 solOther = x.subvec(0, nVar - nEnd + nStart -
1091 return this->
Players.at(player)->solveFixed(solOther);
1096 unsigned int player,
1111 auto model = this->
Respond(player, x, fullvec);
1113 const int status = model->get(GRB_IntAttr_Status);
1114 if (status == GRB_OPTIMAL) {
1118 for (
unsigned int i = 0; i < Nx; ++i)
1120 model->getVarByName(
"y_" +
to_string(i)).get(GRB_DoubleAttr_X);
1122 return model->get(GRB_DoubleAttr_ObjVal);
1124 return GRB_INFINITY;
1128 bool checkFeas)
const {
1138 for (
unsigned int i = 0; i < this->
Nplayers; ++i) {
1141 unsigned int nStart, nEnd;
1145 arma::vec x_i, x_minus_i;
1147 x_minus_i.zeros(nVar - nEnd + nStart);
1149 x_minus_i.subvec(0, nStart - 1) = x.subvec(0, nStart - 1);
1152 x_minus_i.subvec(nStart, nVar + nStart - nEnd - 1) =
1157 x_i = x.subvec(nStart, nEnd - 1);
1160 this->
Players.at(i)->computeObjective(x_i, x_minus_i, checkFeas);
1167 arma::vec &violSol,
double tol)
const {
1180 for (
unsigned int i = 0; i < this->
Nplayers; ++i) {
1181 double val = this->
RespondSol(violSol, i, sol,
true);
1182 if (val == GRB_INFINITY)
1184 if (abs(val - objvals.at(i)) > tol) {
1217 BOOST_LOG_TRIVIAL(warning) <<
"Game::EPEC::resetLCP: resetting LCPs.";
1218 for (
unsigned int i = 0; i < this->nCountr; ++i) {
1219 if (this->countries_LCP.at(i))
1220 this->countries_LCP.at(i).reset();
1221 this->countries_LCP.at(i) = std::unique_ptr<Game::LCP>(
1222 new LCP(this->
env, *this->countries_LL.at(i).get()));
1237 if (this->finalized)
1238 cerr <<
"Warning in Game::EPEC::finalize: Model already finalized\n";
1240 this->nCountr = this->getNcountries();
1243 this->prefinalize();
1246 this->convexHullVariables = std::vector<unsigned int>(this->nCountr, 0);
1247 BOOST_LOG_TRIVIAL(trace) <<
"Finalizing...";
1248 this->Stats.feasiblePolyhedra = std::vector<unsigned int>(this->nCountr, 0);
1249 this->computeLeaderLocations(this->n_MCVar);
1251 this->LeadObjec = vector<shared_ptr<Game::QP_objective>>(nCountr);
1252 this->LeadObjec_ConvexHull =
1253 vector<shared_ptr<Game::QP_objective>>(nCountr);
1254 this->country_QP = vector<shared_ptr<Game::QP_Param>>(nCountr);
1255 this->countries_LCP = vector<unique_ptr<Game::LCP>>(nCountr);
1256 this->SizesWithoutHull = vector<unsigned int>(nCountr, 0);
1257 for (
unsigned int i = 0; i < this->nCountr; i++) {
1258 BOOST_LOG_TRIVIAL(trace) <<
"Finalizing country " << i;
1259 this->add_Dummy_Lead(i);
1260 this->LeadObjec.at(i) = std::make_shared<Game::QP_objective>();
1261 this->LeadObjec_ConvexHull.at(i) = std::make_shared<Game::QP_objective>();
1262 this->make_obj_leader(i, *this->LeadObjec.at(i).get());
1263 this->countries_LCP.at(i) = std::unique_ptr<Game::LCP>(
1264 new LCP(this->
env, *this->countries_LL.at(i).get()));
1265 this->SizesWithoutHull.at(i) = *this->LocEnds.at(i);
1267 BOOST_LOG_TRIVIAL(trace) <<
"Finalized";
1269 }
catch (
const char *e) {
1272 }
catch (
string e) {
1273 cerr <<
"String in Game::EPEC::finalize : " << e <<
'\n';
1275 }
catch (GRBException &e) {
1276 cerr <<
"GRBException in Game::EPEC::finalize : " << e.getErrorCode()
1277 <<
": " << e.getMessage() <<
'\n';
1279 }
catch (exception &e) {
1280 cerr <<
"Exception in Game::EPEC::finalize : " << e.what() <<
'\n';
1284 this->finalized =
true;
1288 this->postfinalize();
1292 const unsigned int i
1296 const unsigned int nEPECvars = this->nVarinEPEC;
1297 const unsigned int nThisCountryvars = *this->LocEnds.at(i);
1300 if (nEPECvars < nThisCountryvars)
1302 "String in Game::EPEC::add_Dummy_Lead: Invalid variable counts " +
1306 this->countries_LL.at(i).get()->addDummy(nEPECvars - nThisCountryvars);
1307 }
catch (
const char *e) {
1310 }
catch (
string e) {
1311 cerr <<
"String in Game::EPEC::add_Dummy_All_Lead : " << e <<
'\n';
1313 }
catch (GRBException &e) {
1314 cerr <<
"GRBException in Game::EPEC::add_Dummy_All_Lead : " 1315 << e.getErrorCode() <<
": " << e.getMessage() <<
'\n';
1317 }
catch (exception &e) {
1318 cerr <<
"Exception in Game::EPEC::add_Dummy_All_Lead : " << e.what()
1325 this->LeaderLocations = vector<unsigned int>(this->nCountr);
1326 this->LeaderLocations.at(0) = 0;
1327 for (
unsigned int i = 1; i < this->nCountr; i++) {
1328 this->LeaderLocations.at(i) =
1329 this->LeaderLocations.at(i - 1) + *this->LocEnds.at(i - 1);
1332 this->LeaderLocations.back() + *this->LocEnds.back() + addSpaceForMC;
1336 arma::vec &solOther)
const {
1337 const unsigned int nEPECvars = this->nVarinEPEC;
1338 const unsigned int nThisCountryvars = *this->LocEnds.at(i);
1339 const unsigned int nThisCountryHullVars = this->convexHullVariables.at(i);
1340 const unsigned int nConvexHullVars = std::accumulate(
1341 this->convexHullVariables.rbegin(), this->convexHullVariables.rend(), 0);
1343 solOther.zeros(nEPECvars -
1347 nThisCountryHullVars);
1350 for (
unsigned int j = 0, count = 0, current = 0; j < this->nCountr; ++j) {
1352 current = *this->LocEnds.at(j) - this->convexHullVariables.at(j);
1353 solOther.subvec(count, count + current - 1) =
1354 x.subvec(this->LeaderLocations.at(j),
1355 this->LeaderLocations.at(j) + current - 1);
1360 for (
unsigned int j = 0; j < this->n_MCVar; j++)
1361 solOther.at(solOther.n_rows - this->n_MCVar + j) =
1362 x.at(this->nVarinEPEC - this->n_MCVar + j);
1363 BOOST_LOG_TRIVIAL(debug) <<
"EPEC::get_x_minus_i: Over";
1367 const arma::vec &x)
const {
1368 if (!this->finalized)
1369 throw string(
"Error in Game::EPEC::Respond: Model not finalized");
1371 if (i >= this->nCountr)
1372 throw string(
"Error in Game::EPEC::Respond: Invalid country number");
1375 this->get_x_minus_i(x, i, solOther);
1376 return this->countries_LCP.at(i).get()->MPECasMILP(
1377 this->LeadObjec.at(i).get()->C, this->LeadObjec.at(i).get()->c, solOther,
1382 unsigned int player,
1384 const arma::vec &prevDev = {}
1397 auto model = this->
Respond(player, x);
1398 const int status = model->get(GRB_IntAttr_Status);
1399 if (status == GRB_UNBOUNDED || status == GRB_OPTIMAL) {
1400 unsigned int Nx = this->countries_LCP.at(player)->getNcol();
1402 for (
unsigned int i = 0; i < Nx; ++i)
1404 model->getVarByName(
"x_" +
to_string(i)).get(GRB_DoubleAttr_X);
1406 if (status == GRB_UNBOUNDED) {
1407 BOOST_LOG_TRIVIAL(warning) <<
"Game::EPEC::Respondsol: deviation is " 1410 model->setObjective(obj);
1412 if (!prevDev.empty()) {
1413 BOOST_LOG_TRIVIAL(trace)
1414 <<
"Generating an improvement basing on the extreme ray.";
1416 GRBQuadExpr QuadObj = model->getObjective();
1418 for (
unsigned int i = 0; i < QuadObj.size(); ++i)
1419 objcoeff.at(i) = QuadObj.getCoeff(i);
1422 arma::vec objvalue = prevDev * objcoeff;
1423 arma::vec newobjvalue{0};
1424 double improved{
false};
1428 for (
unsigned int i = 0; i < Nx; ++i)
1429 sol.at(i) = sol.at(i) + model->getVarByName(
"x_" +
to_string(i))
1430 .get(GRB_DoubleAttr_UnbdRay);
1431 newobjvalue = sol * objcoeff;
1432 if (newobjvalue.at(0) < objvalue.at(0))
1435 return newobjvalue.at(0);
1438 return model->get(GRB_DoubleAttr_ObjVal);
1441 if (status == GRB_OPTIMAL) {
1442 return model->get(GRB_DoubleAttr_ObjVal);
1445 return GRB_INFINITY;
1447 return GRB_INFINITY;
1469 if (!this->nashgame)
1473 this->nashgame->isSolved(this->sol_x, *countryNumber, *ProfDevn);
1474 arma::vec objvals = this->nashgame->ComputeQPObjvals(this->sol_x,
true);
1475 for (
unsigned int i = 0; i < this->nCountr; ++i) {
1476 double val = this->
RespondSol(*ProfDevn, i, this->sol_x);
1477 if (val == GRB_INFINITY)
1479 BOOST_LOG_TRIVIAL(debug) <<
"EPEC::isSolved: " << i <<
" Devnval: " << val
1480 <<
" Obj Val: " << objvals.at(i);
1481 if (abs(val - objvals.at(i)) > tol) {
1492 unsigned int countryNumber;
1494 bool ret = this->
isSolved(&countryNumber, &ProfDevn, tol);
1514 if (!this->finalized)
1515 throw string(
"Error in Game::EPEC::make_country_QP: Model not finalized");
1516 if (i >= this->nCountr)
1518 "Error in Game::EPEC::make_country_QP: Invalid country number");
1521 this->country_QP.at(i) = std::make_shared<Game::QP_Param>(this->
env);
1522 const auto &origLeadObjec = *this->LeadObjec.at(i).get();
1525 origLeadObjec.
Q, origLeadObjec.C, origLeadObjec.c});
1527 this->countries_LCP.at(i)->makeQP(*this->LeadObjec_ConvexHull.at(i).get(),
1528 *this->country_QP.at(i).get());
1529 this->Stats.feasiblePolyhedra.at(i) =
1530 this->countries_LCP.at(i)->getFeasiblePolyhedra();
1543 for (
unsigned int i = 0; i < this->nCountr; ++i) {
1546 for (
unsigned int i = 0; i < this->nCountr; ++i) {
1549 unsigned int originalSizeWithoutHull = this->LeadObjec.at(i)->Q.n_rows;
1550 unsigned int convHullVarCount =
1551 this->LeadObjec_ConvexHull.at(i)->Q.n_rows - originalSizeWithoutHull;
1553 BOOST_LOG_TRIVIAL(trace)
1554 <<
"Game::EPEC::make_country_QP: Added " << convHullVarCount
1555 <<
" convex hull variables to QP #" << i;
1558 this->convexHullVariables.at(i) = convHullVarCount;
1561 if (this->nCountr > 1) {
1562 for (
unsigned int j = 0; j < this->nCountr; j++) {
1564 this->country_QP.at(j)->addDummy(
1565 convHullVarCount, 0,
1566 this->country_QP.at(j)->getNx() -
1574 }
catch (
const char *e) {
1577 }
catch (
string e) {
1578 cerr <<
"String in Game::EPEC::make_country_QP : " << e <<
'\n';
1580 }
catch (GRBException &e) {
1581 cerr <<
"GRBException in Game::EPEC::make_country_QP : " 1582 << e.getErrorCode() <<
": " << e.getMessage() <<
'\n';
1584 }
catch (exception &e) {
1585 cerr <<
"Exception in Game::EPEC::make_country_QP : " << e.what() <<
'\n';
1590 this->computeLeaderLocations(this->n_MCVar);
1594 std::vector<arma::vec>
1596 const arma::vec &guessSol,
1597 const std::vector<arma::vec>
1608 devns = std::vector<arma::vec>(this->nCountr);
1610 for (
unsigned int i = 0; i < this->nCountr; ++i) {
1613 objVal = this->
RespondSol(devns.at(i), i, guessSol, prevDev.at(i));
1614 BOOST_LOG_TRIVIAL(debug) <<
"EPEC::getAllDevns: " << i <<
" " << objVal;
1615 if (objVal == GRB_INFINITY)
1623 const std::vector<arma::vec>
1641 infeasCheck =
false;
1642 unsigned int added = 0;
1643 for (
unsigned int i = 0; i < this->nCountr; ++i) {
1645 if (!devns.at(i).empty())
1646 this->countries_LCP.at(i)->addPolyFromX(devns.at(i), ret);
1648 BOOST_LOG_TRIVIAL(debug)
1649 <<
"Game::EPEC::addDeviatedPolyhedron: added polyhedron for player " 1650 << i <<
" " << added;
1654 BOOST_LOG_TRIVIAL(trace) <<
"Game::EPEC::addDeviatedPolyhedron: NO " 1655 "polyhedron added for player " 1663 bool stopOnSingleInfeasibility)
1680 BOOST_LOG_TRIVIAL(trace) <<
"Adding random polyhedra to countries";
1681 bool infeasible{
true};
1682 for (
unsigned int i = 0; i < this->nCountr; i++) {
1683 auto addedPolySet = this->countries_LCP.at(i)->addAPoly(
1684 aggressiveLevel, this->Stats.AlgorithmParam.addPolyMethod);
1685 if (stopOnSingleInfeasibility && addedPolySet.empty()) {
1686 BOOST_LOG_TRIVIAL(info)
1687 <<
"Game::EPEC::addRandomPoly2All: No Nash equilibrium. due to " 1688 "infeasibility of country " 1692 if (!addedPolySet.empty())
1701 this->sol_x.zeros(this->nVarinEPEC);
1703 bool solved = {
false};
1704 bool addRandPoly{
false};
1705 bool infeasCheck{
false};
1712 std::vector<arma::vec> prevDevns(this->nCountr);
1713 this->Stats.numIteration = 0;
1715 for (
unsigned int i = 0; i < this->nCountr; ++i) {
1716 long int seed = this->Stats.AlgorithmParam.addPolyMethodSeed < 0
1717 ? chrono::high_resolution_clock::now()
1720 42 + this->countries_LCP.at(i)->getNrow()
1721 : this->Stats.AlgorithmParam.addPolyMethodSeed;
1722 this->countries_LCP.at(i)->addPolyMethodSeed = seed;
1725 if (this->Stats.AlgorithmParam.timeLimit > 0)
1726 this->initTime = std::chrono::high_resolution_clock::now();
1731 ++this->Stats.numIteration;
1732 BOOST_LOG_TRIVIAL(info) <<
"Game::EPEC::iterativeNash: Iteration " 1736 BOOST_LOG_TRIVIAL(info) <<
"Game::EPEC::iterativeNash: using " 1737 "heuristical polyhedra selection";
1739 this->addRandomPoly2All(this->Stats.AlgorithmParam.aggressiveness,
1740 this->Stats.numIteration == 1);
1747 unsigned int deviatedCountry{0};
1748 arma::vec countryDeviation{};
1749 if (this->
isSolved(&deviatedCountry, &countryDeviation, 20)) {
1751 this->Stats.pureNE = this->isPureStrategy();
1752 if ((this->Stats.AlgorithmParam.pureNE && !this->Stats.pureNE)) {
1753 BOOST_LOG_TRIVIAL(info)
1754 <<
"Game::EPEC::iterativeNash: pureNE control ";
1758 if (this->Stats.AlgorithmParam.recoverStrategy ==
1760 BOOST_LOG_TRIVIAL(info)
1761 <<
"Game::EPEC::iterativeNash: triggering recover strategy " 1762 "(incrementalEnumeration)";
1764 }
else if (this->Stats.AlgorithmParam.recoverStrategy ==
1766 BOOST_LOG_TRIVIAL(info) <<
"Game::EPEC::iterativeNash: triggering " 1767 "recover strategy (combinatorial)";
1770 std::vector<std::set<unsigned long int>> excludeList;
1771 std::vector<long int> start;
1772 for (
unsigned int j = 0; j < this->nCountr; ++j) {
1773 excludeList.push_back(
1774 this->countries_LCP.at(j)->getAllPolyhedra());
1775 start.push_back(-1);
1787 std::vector<arma::vec> devns = std::vector<arma::vec>(this->nCountr);
1788 this->getAllDevns(devns, this->sol_x, prevDevns);
1790 unsigned int addedPoly = this->addDeviatedPolyhedron(devns, infeasCheck);
1791 if (addedPoly == 0 && this->Stats.numIteration > 1 &&
1793 BOOST_LOG_TRIVIAL(error)
1794 <<
" In Game::EPEC::iterativeNash: Not " 1795 "Solved, but no deviation? Error!\n This might be due to " 1796 "numerical issues (tollerances) " 1802 if (infeasCheck && this->Stats.numIteration == 1) {
1803 BOOST_LOG_TRIVIAL(warning)
1804 <<
" In Game::EPEC::iterativeNash: Problem is infeasible";
1810 this->make_country_QP();
1813 if (this->Stats.AlgorithmParam.timeLimit > 0) {
1814 const std::chrono::duration<double> timeElapsed =
1815 std::chrono::high_resolution_clock::now() - this->initTime;
1816 const double timeRemaining =
1817 this->Stats.AlgorithmParam.timeLimit - timeElapsed.count();
1818 addRandPoly = !this->computeNashEq(this->Stats.AlgorithmParam.pureNE,
1823 addRandPoly = !this->computeNashEq(this->Stats.AlgorithmParam.pureNE) &&
1827 this->Stats.lostIntermediateEq++;
1828 for (
unsigned int i = 0; i < this->nCountr; ++i) {
1829 BOOST_LOG_TRIVIAL(info) <<
"Game::EPEC::iterativeNash: Country " << i
1830 << this->countries_LCP.at(i)->feas_detail_str();
1834 if (this->Stats.AlgorithmParam.timeLimit > 0) {
1835 const std::chrono::duration<double> timeElapsed =
1836 std::chrono::high_resolution_clock::now() - this->initTime;
1837 const double timeRemaining =
1838 this->Stats.AlgorithmParam.timeLimit - timeElapsed.count();
1839 if (timeRemaining <= 0) {
1850 const std::vector<long int> combination,
1851 const std::vector<std::set<unsigned long int>> &excludeList) {
1854 this->Stats.pureNE ==
true) ||
1858 if (this->Stats.AlgorithmParam.timeLimit > 0) {
1859 const std::chrono::duration<double> timeElapsed =
1860 std::chrono::high_resolution_clock::now() - this->initTime;
1861 const double timeRemaining =
1862 this->Stats.AlgorithmParam.timeLimit - timeElapsed.count();
1863 if (timeRemaining <= 0) {
1869 std::vector<long int> childCombination(combination);
1872 for (i = 0; i < this->getNcountries(); i++) {
1873 if (childCombination.at(i) == -1) {
1879 for (
unsigned int j = 0;
1880 j < this->countries_LCP.at(i)->getNumTheoreticalPoly(); ++j) {
1881 if (this->countries_LCP.at(i)->checkPolyFeas(j)) {
1882 childCombination.at(i) = j;
1883 this->combinatorial_pure_NE(childCombination, excludeList);
1889 BOOST_LOG_TRIVIAL(trace)
1890 <<
"Game::EPEC::combinatorial_pure_NE: considering a FULL combination";
1891 bool excluded =
false;
1892 if (!excludeList.empty()) {
1894 for (
unsigned int j = 0; j < this->nCountr; ++j) {
1895 if (excludeList.at(j).find(childCombination.at(j)) ==
1896 excludeList.at(j).end()) {
1903 BOOST_LOG_TRIVIAL(trace)
1904 <<
"Game::EPEC::combinatorial_pure_NE: considering a " 1905 "FEASIBLE combination of polyhedra.";
1906 for (
unsigned int j = 0; j < this->getNcountries(); ++j) {
1907 this->countries_LCP.at(j)->clearPolyhedra();
1908 this->countries_LCP.at(j)->addThePoly(childCombination.at(j));
1910 this->make_country_QP();
1912 if (this->Stats.AlgorithmParam.timeLimit > 0) {
1913 const std::chrono::duration<double> timeElapsed =
1914 std::chrono::high_resolution_clock::now() - this->initTime;
1915 const double timeRemaining =
1916 this->Stats.AlgorithmParam.timeLimit - timeElapsed.count();
1917 res = this->computeNashEq(
false, timeRemaining,
true);
1919 res = this->computeNashEq(
false, -1.0,
true);
1924 if ((this->isPureStrategy())) {
1925 BOOST_LOG_TRIVIAL(info)
1926 <<
"Game::EPEC::combinatorial_pure_NE: found a pure strategy.";
1928 this->Stats.pureNE =
true;
1934 BOOST_LOG_TRIVIAL(trace)
1935 <<
"Game::EPEC::combinatorial_pure_NE: configuration pruned.";
1941 void ::Game::EPEC::make_country_LCP() {
1942 if (this->country_QP.front() ==
nullptr) {
1943 BOOST_LOG_TRIVIAL(error) <<
"Exception in Game::EPEC::make_country_LCP : " 1944 "no country QP has been " 1951 this->country_QP.front()->getNx() + this->country_QP.front()->getNy();
1952 arma::sp_mat MC(0, Nvar), dumA(0, Nvar);
1953 arma::vec
MCRHS, dumb;
1956 this->make_MC_cons(MC, MCRHS);
1957 BOOST_LOG_TRIVIAL(trace) <<
"Game::EPEC::make_country_LCP(): Market Clearing " 1958 "constraints are ready";
1959 this->nashgame = std::unique_ptr<Game::NashGame>(
new Game::NashGame(
1960 this->
env, this->country_QP, MC, MCRHS, 0, dumA, dumb));
1961 BOOST_LOG_TRIVIAL(trace)
1962 <<
"Game::EPEC::make_country_LCP(): NashGame is ready";
1963 this->lcp = std::unique_ptr<Game::LCP>(
new Game::LCP(this->
env, *nashgame));
1964 BOOST_LOG_TRIVIAL(trace) <<
"Game::EPEC::make_country_LCP(): LCP is ready";
1965 BOOST_LOG_TRIVIAL(trace)
1966 <<
"Game::EPEC::make_country_LCP(): indicators set to " 1967 << this->Stats.AlgorithmParam.indicators;
1968 this->lcp->useIndicators =
1969 this->Stats.AlgorithmParam.indicators;
1971 this->lcpmodel = this->lcp->LCPasMIP(
false);
1973 BOOST_LOG_TRIVIAL(trace) << *nashgame;
1978 double localTimeLimit,
1990 this->nashEq =
false;
1991 BOOST_LOG_TRIVIAL(trace)
1992 <<
" Game::EPEC::computeNashEq: Making the Master LCP";
1993 this->make_country_LCP();
1994 BOOST_LOG_TRIVIAL(trace) <<
" Game::EPEC::computeNashEq: Made the Master LCP";
1995 if (localTimeLimit > 0) {
1996 this->lcpmodel->set(GRB_DoubleParam_TimeLimit, localTimeLimit);
1998 if (this->Stats.AlgorithmParam.boundPrimals) {
1999 for (
unsigned int c = 0; c < this->nashgame->getNprimals(); c++) {
2000 this->lcpmodel->getVarByName(
"x_" +
to_string(c))
2001 .set(GRB_DoubleAttr_UB, this->Stats.AlgorithmParam.boundBigM);
2006 BOOST_LOG_TRIVIAL(info) <<
" Game::EPEC::computeNashEq: (pureNE flag is " 2007 "true) Searching for a pure NE.";
2008 this->make_pure_LCP();
2013 this->lcpmodel->set(GRB_IntParam_SolutionLimit, GRB_MAXINT);
2014 this->lcpmodel->optimize();
2015 this->Stats.wallClockTime += this->lcpmodel->get(GRB_DoubleAttr_Runtime);
2020 this->lcp->extractSols(this->lcpmodel.get(), sol_z, sol_x,
true);
2021 }
catch (GRBException &e) {
2022 BOOST_LOG_TRIVIAL(error)
2023 <<
"GRBException in Game::EPEC::computeNashEq : " << e.getErrorCode()
2024 <<
": " << e.getMessage() <<
" ";
2029 int scount = this->lcpmodel->get(GRB_IntAttr_SolCount);
2030 BOOST_LOG_TRIVIAL(info)
2031 <<
"Game::EPEC::computeNashEq: number of equilibria is " << scount;
2032 for (
int k = 0, stop = 0; k < scount && stop == 0; ++k) {
2033 this->lcpmodel->getEnv().set(GRB_IntParam_SolutionNumber, k);
2035 this->lcp->extractSols(this->lcpmodel.get(), sol_z, sol_x,
true);
2037 BOOST_LOG_TRIVIAL(info)
2038 <<
"Game::EPEC::computeNashEq: an Equilibrium has been found";
2043 this->nashEq =
true;
2044 BOOST_LOG_TRIVIAL(info)
2045 <<
"Game::EPEC::computeNashEq: an Equilibrium has been found";
2049 BOOST_LOG_TRIVIAL(info)
2050 <<
"Game::EPEC::computeNashEq: no equilibrium has been found.";
2051 int status = this->lcpmodel->get(GRB_IntAttr_Status);
2052 if (status == GRB_TIME_LIMIT)
2057 return this->nashEq;
2062 if (x.size() < this->getnVarinEPEC()) {
2063 BOOST_LOG_TRIVIAL(error)
2064 <<
"Exception in Game::EPEC::warmstart: number of variables " 2065 "does not fit this instance.";
2068 if (!this->finalized) {
2069 BOOST_LOG_TRIVIAL(error)
2070 <<
"Exception in Game::EPEC::warmstart: EPEC is not finalized.";
2073 if (this->country_QP.front() ==
nullptr) {
2074 BOOST_LOG_TRIVIAL(warning)
2075 <<
"Game::EPEC::warmstart: Generating QP as of warmstart.";
2079 std::vector<arma::vec> devns = std::vector<arma::vec>(this->nCountr);
2080 std::vector<arma::vec> prevDevns = std::vector<arma::vec>(this->nCountr);
2081 this->getAllDevns(devns, this->sol_x, prevDevns);
2082 this->make_country_QP();
2088 BOOST_LOG_TRIVIAL(warning) <<
"Game::EPEC::warmstart: " 2089 "The loaded solution is optimal.";
2091 BOOST_LOG_TRIVIAL(warning)
2092 <<
"Game::EPEC::warmstart: " 2093 "The loaded solution is NOT optimal. Trying to repair.";
2110 BOOST_LOG_TRIVIAL(trace)
2111 <<
"Game::EPEC::make_pure_LCP: editing the LCP model.";
2112 this->lcpmodel_base = std::unique_ptr<GRBModel>(
new GRBModel(*lcpmodel));
2113 const unsigned int nPolyLead = [
this]() {
2114 unsigned int ell = 0;
2115 for (
unsigned int i = 0; i < this->getNcountries(); ++i)
2116 ell += (this->getNPoly_Lead(i));
2121 GRBVar pure_bin[nPolyLead];
2122 GRBLinExpr objectiveTerm{0};
2123 unsigned int count{0}, i, j;
2124 for (i = 0; i < this->getNcountries(); i++) {
2125 for (j = 0; j < this->getNPoly_Lead(i); ++j) {
2126 pure_bin[count] = this->lcpmodel->addVar(0, 1, 0, GRB_BINARY,
2130 this->lcpmodel->addGenConstrIndicator(
2132 this->lcpmodel->getVarByName(
2133 "x_" +
to_string(this->getPosition_Probab(i, j))),
2134 GRB_EQUAL, 0,
"Indicator_PNE_" +
to_string(count));
2136 this->lcpmodel->addConstr(
2137 this->lcpmodel->getVarByName(
2138 "x_" +
to_string(this->getPosition_Probab(i, j))),
2139 GRB_GREATER_EQUAL, pure_bin[count]);
2141 objectiveTerm += pure_bin[count];
2146 this->lcpmodel->setObjective(objectiveTerm, GRB_MAXIMIZE);
2147 BOOST_LOG_TRIVIAL(trace)
2148 <<
"Game::EPEC::make_pure_LCP: using indicator constraints.";
2150 this->lcpmodel->setObjective(objectiveTerm, GRB_MINIMIZE);
2151 BOOST_LOG_TRIVIAL(trace)
2152 <<
"Game::EPEC::make_pure_LCP: using indicator constraints.";
2154 }
catch (GRBException &e) {
2155 cerr <<
"GRBException in Game::EPEC::make_pure_LCP : " << e.getErrorCode()
2156 <<
": " << e.getMessage() <<
'\n';
2162 const std::vector<long int> combination,
2163 const std::vector<std::set<unsigned long int>> &excludeList) {
2165 if (this->Stats.AlgorithmParam.timeLimit > 0) {
2167 if (this->Stats.numIteration <= 0) {
2168 this->initTime = std::chrono::high_resolution_clock::now();
2171 if (combination.empty()) {
2172 std::vector<long int> start;
2173 for (
unsigned int j = 0; j < this->nCountr; ++j)
2174 start.push_back(-1);
2175 this->combinatorial_pure_NE(start, excludeList);
2177 this->combinatorial_pure_NE(combination, excludeList);
2191 std::stringstream final_msg;
2192 if (!this->finalized)
2193 throw string(
"Error in Game::EPEC::iterativeNash: Object not yet " 2197 BOOST_LOG_TRIVIAL(error)
2198 <<
"Game::EPEC::findNashEq: a Nash Eq was " 2199 "already found. Calling this findNashEq might lead to errors!";
2204 switch (this->Stats.AlgorithmParam.algorithm) {
2207 this->iterativeNash();
2208 final_msg <<
"Inner approximation algorithm completed. ";
2213 final_msg <<
"CombinatorialPNE algorithm completed. ";
2217 this->fullEnumerationNash();
2218 final_msg <<
"Full enumeration algorithm completed. ";
2222 if (this->lcpmodel) {
2223 this->Stats.numVar = this->lcpmodel->get(GRB_IntAttr_NumVars);
2224 this->Stats.numConstraints = this->lcpmodel->get(GRB_IntAttr_NumConstrs);
2225 this->Stats.numNonZero = this->lcpmodel->get(GRB_IntAttr_NumNZs);
2228 switch (this->Stats.status) {
2230 final_msg <<
"No Nash equilibrium exists.";
2233 final_msg <<
"Found a Nash equilibrium (" 2234 << (this->Stats.pureNE == 0 ?
"MNE" :
"PNE") <<
").";
2237 final_msg <<
"Nash equilibrium not found. Time limit attained";
2240 final_msg <<
"Nash equilibrium not found. Numerical issues might affect " 2244 final_msg <<
"Nash equilibrium not found. Time limit attained";
2247 BOOST_LOG_TRIVIAL(info) <<
"Game::EPEC::findNashEq: " << final_msg.str();
2250 for (
unsigned int i = 0; i < this->nCountr; ++i)
2251 this->countries_LCP.at(i)->EnumerateAll(
true);
2252 this->make_country_QP();
2253 BOOST_LOG_TRIVIAL(trace)
2254 <<
"Game::EPEC::findNashEq: Starting fullEnumeration search";
2255 BOOST_LOG_TRIVIAL(debug) <<
"EPEC::fullEnumerationNash: " 2257 << this->Stats.AlgorithmParam.timeLimit;
2258 this->computeNashEq(this->Stats.AlgorithmParam.pureNE,
2259 this->Stats.AlgorithmParam.timeLimit);
2260 BOOST_LOG_TRIVIAL(debug) <<
"EPEC::fullEnumerationNash: " 2261 <<
"computeNashEq completed " 2266 if (this->isPureStrategy())
2267 this->Stats.pureNE =
true;
2269 BOOST_LOG_TRIVIAL(debug) <<
"EPEC::fullEnumerationNash: " 2270 <<
"computeNashEq completed " 2280 this->Stats.AlgorithmParam.algorithm = algorithm;
2288 this->Stats.AlgorithmParam.recoverStrategy = strategy;
2292 const unsigned int j)
const {
2298 const auto LeaderStart = this->nashgame->getPrimalLoc(i);
2299 return LeaderStart + j;
2303 const unsigned int j)
const {
2309 const auto LeaderStart = this->nashgame->getPrimalLoc(i);
2310 return LeaderStart + this->countries_LCP.at(i)->getLStart() + j;
2314 const unsigned int j,
2315 const unsigned int k)
const {
2322 const auto LeaderStart = this->nashgame->getPrimalLoc(i);
2323 const auto FollPoly = this->countries_LCP.at(i)->conv_PolyPosition(k);
2324 return LeaderStart + FollPoly + j;
2328 const unsigned int j,
2329 const unsigned int k)
const {
2336 const auto LeaderStart = this->nashgame->getPrimalLoc(i);
2337 const auto FollPoly = this->countries_LCP.at(i)->conv_PolyPosition(k);
2338 return LeaderStart + FollPoly + this->countries_LCP.at(i)->getLStart() + j;
2346 return this->countries_LCP.at(i)->conv_Npoly();
2350 const unsigned int k)
const {
2356 const auto PolyProbab = this->countries_LCP.at(i)->conv_PolyWt(k);
2357 if (PolyProbab == 0)
2359 const auto LeaderStart = this->nashgame->getPrimalLoc(i);
2360 return LeaderStart + PolyProbab;
2369 for (
unsigned int i = 0; i < this->getNcountries(); ++i) {
2370 if (!isPureStrategy(i, tol))
2382 const unsigned int nPoly = this->getNPoly_Lead(i);
2383 for (
unsigned int j = 0; j < nPoly; j++) {
2384 const double probab = this->getVal_Probab(i, j);
2385 if (probab > 1 - tol)
2392 const double tol)
const 2398 std::vector<unsigned int> polys{};
2399 const unsigned int nPoly = this->getNPoly_Lead(i);
2400 for (
unsigned int j = 0; j < nPoly; j++) {
2401 const double probab = this->getVal_Probab(i, j);
2410 const unsigned int k)
const {
2411 const unsigned int varname{this->getPosition_Probab(i, k)};
2414 return this->lcpmodel->getVarByName(
"x_" +
std::to_string(varname))
2415 .get(GRB_DoubleAttr_X);
2419 const unsigned int j)
const {
2420 if (!this->lcpmodel)
2421 throw std::string(
"Error in Game::EPEC::getVal_LeadFoll: " 2422 "Game::EPEC::lcpmodel not made and solved");
2423 return this->lcpmodel
2424 ->getVarByName(
"x_" +
to_string(this->getPosition_LeadFoll(i, j)))
2425 .get(GRB_DoubleAttr_X);
2429 const unsigned int j)
const {
2430 if (!this->lcpmodel)
2431 throw std::string(
"Error in Game::EPEC::getVal_LeadLead: " 2432 "Game::EPEC::lcpmodel not made and solved");
2433 return this->lcpmodel
2434 ->getVarByName(
"x_" +
to_string(this->getPosition_LeadLead(i, j)))
2435 .get(GRB_DoubleAttr_X);
2439 const unsigned int j,
2440 const unsigned int k,
2441 const double tol)
const {
2442 if (!this->lcpmodel)
2443 throw std::string(
"Error in Game::EPEC::getVal_LeadFollPoly: " 2444 "Game::EPEC::lcpmodel not made and solved");
2445 const double probab = this->getVal_Probab(i, k);
2446 if (probab > 1 - tol)
2447 return this->getVal_LeadFoll(i, j);
2449 return this->lcpmodel
2451 "x_" +
to_string(this->getPosition_LeadFollPoly(i, j, k)))
2452 .get(GRB_DoubleAttr_X) /
2457 const unsigned int j,
2458 const unsigned int k,
2459 const double tol)
const {
2460 if (!this->lcpmodel)
2461 throw std::string(
"Error in Game::EPEC::getVal_LeadLeadPoly: " 2462 "Game::EPEC::lcpmodel not made and solved");
2463 const double probab = this->getVal_Probab(i, k);
2464 if (probab > 1 - tol)
2465 return this->getVal_LeadLead(i, j);
2467 return this->lcpmodel
2469 "x_" +
to_string(this->getPosition_LeadLeadPoly(i, j, k)))
2470 .get(GRB_DoubleAttr_X) /
2477 return string(
"NO_NASH_EQ_FOUND");
2479 return string(
"NASH_EQ_FOUND");
2481 return string(
"TIME_LIMIT");
2483 return string(
"UNINITIALIZED");
2485 return string(
"NUMERICAL_ISSUES");
2487 return string(
"UNKNOWN_STATUS_") +
to_string(static_cast<int>(st));
2493 return string(
"fullEnumeration");
2495 return string(
"innerApproximation");
2497 return string(
"combinatorialPNE");
2499 return string(
"UNKNOWN_ALGORITHM_") +
to_string(static_cast<int>(al));
2505 return string(
"incrementalEnumeration");
2507 return string(
"combinatorial");
2509 return string(
"UNKNOWN_RECOVER_STRATEGY_") +
2516 return string(
"sequential");
2518 return string(
"reverse_sequential");
2520 return string(
"random");
2522 return string(
"UNKNOWN_ALGORITHM_") +
to_string(static_cast<int>(add));
2526 std::stringstream ss;
2532 ss <<
"Time Limit: " << al.
timeLimit <<
'\n';
2533 ss <<
"Indicators: " << std::boolalpha << al.
indicators;
unsigned int getPosition_LeadFoll(const unsigned int i, const unsigned int j) const
std::ostream & operator<<(std::ostream &os, const QP_Param &Q)
arma::sp_mat MarketClearing
Market clearing constraints.
Class to handle parameterized quadratic programs(QP)
bool warmstart(const arma::vec x)
Warmstarts EPEC with a solution.
bool dataCheck(bool forcesymm=true) const
Check that the data for the MP_Param class is valid Always works after calls to MP_Param::size() Chec...
void make_country_QP()
Makes the Game::QP_Param for all the countries.
string to_string(const Game::EPECsolveStatus st)
void write(std::string filename, bool append=true, bool KKT=false) const
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="")
arma::sp_mat getQ() const
Read-only access to the private variable Q.
arma::vec getc() const
Read-only access to the private variable c.
std::vector< std::shared_ptr< QP_Param > > Players
The QP that each player solves.
unsigned int getPosition_LeadLeadPoly(const unsigned int i, const unsigned int j, const unsigned int k) const
class to handle parameterized mathematical programs(MP)
unsigned int getPosition_LeadLead(const unsigned int i, const unsigned int j) const
struct to handle the constraint params of MP_Param/QP_Param
NashGame(GRBEnv *e) noexcept
To be used only when NashGame is being loaded from a file.
void get_x_minus_i(const arma::vec &x, const unsigned int &i, arma::vec &solOther) const
unsigned int aggressiveness
in EPEC::iterativeNash
double getVal_Probab(const unsigned int i, const unsigned int k) const
bool computeNashEq(bool pureNE=false, double localTimeLimit=-1.0, bool check=false)
void make_pure_LCP(bool indicators=false)
void appendSave(const vec &matrix, const std::string out, const std::string header="", bool erase=false)
std::vector< unsigned int > dual_position
std::vector< std::pair< unsigned int, unsigned int > > perps
void combinatorial_pure_NE(const std::vector< long int > combination, const std::vector< std::set< unsigned long int >> &excludeList)
bool isSolved(const arma::vec &sol, unsigned int &violPlayer, arma::vec &violSol, double tol=1e-4) const
void finalize()
Finalizes the creation of a Game::EPEC object.
arma::vec ComputeQPObjvals(const arma::vec &x, bool checkFeas=false) const
void combinatorialPNE(const std::vector< long int > combination={}, const std::vector< std::set< unsigned long int >> &excludeList={})
double computeObjective(const arma::vec &y, const arma::vec &x, bool checkFeas=true, double tol=1e-6) const
long int load(std::string filename, long int pos=0)
Loads the Game::QP_Param object stored in a file.
unsigned int MC_dual_position
bool operator==(const QP_Param &Q2) const
virtual void postfinalize()
Empty function - optionally reimplementable in derived class.
arma::sp_mat RewriteLeadCons() const
Rewrites leader constraint adjusting for dual variables. Rewrites leader constraints given earlier wi...
std::unique_ptr< GRBModel > solveFixed(arma::vec x)
arma::vec MCRHS
RHS to the Market Clearing constraints.
bool isZero(arma::mat M, double tol=1e-6) noexcept
void save(std::string filename, bool erase=true) const
Saves the Game::QP_Param object in a loadable file.
unsigned int getPosition_Probab(const unsigned int i, const unsigned int k) const
unsigned int getNx() const
Read-only access to the private variable Nx.
std::unique_ptr< GRBModel > Respond(unsigned int player, const arma::vec &x, bool fullvec=true) const
Given the decision of other players, find the optimal response for player in position player...
arma::sp_mat resize_patch(const arma::sp_mat &Mat, const unsigned int nR, const unsigned int nC)
virtual void prefinalize()
Empty function - optionally reimplementable in derived class.
Class to handle and solve linear complementarity problems.
Solution found for the instance.
arma::sp_mat getA() const
Read-only access to the private variable A.
bool addRandomPoly2All(unsigned int aggressiveLevel=1, bool stopOnSingleInfeasibility=false)
void write(std::string filename, bool append) const
Writes a given parameterized Mathematical program to a set of files.
unsigned int KKT(arma::sp_mat &M, arma::sp_mat &N, arma::vec &q) const
Compute the KKT conditions for the given QP.
virtual MP_Param & addDummy(unsigned int pars, unsigned int vars=0, int position=-1)
void setRecoverStrategy(Game::EPECRecoverStrategy strategy)
unsigned int size()
Calculates Nx, Ny and Ncons Computes parameters in MP_Param:
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
Adds the next polyhedra by selecting random feasible one.
double getVal_LeadLeadPoly(const unsigned int i, const unsigned int j, const unsigned int k, const double tol=1e-5) const
Adds polyhedra by selecting them in order.
arma::sp_mat getC() const
Read-only access to the private variable C.
Instance proved to be infeasible.
Not started to solve the problem.
virtual MP_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)
Setting the data, while keeping the input objects intact.
double RespondSol(arma::vec &sol, unsigned int player, const arma::vec &x, bool fullvec=true) const
int make_yQy()
Adds the Gurobi Quadratic objective to the Gurobi model QuadModel.
unsigned int getNleaderVars() const
Gets the number of leader variables.
void add_Dummy_Lead(const unsigned int i)
Add Dummy variables for the leaders.
arma::vec LeaderConsRHS
Upper level leader constraints RHS.
arma::sp_mat getB() const
Read-only access to the private variable B.
std::unique_ptr< GRBModel > Respond(const unsigned int i, const arma::vec &x) const
unsigned int getNPoly_Lead(const unsigned int i) const
Time limit reached, nash equilibrium not found.
unsigned int getPosition_LeadFollPoly(const unsigned int i, const unsigned int j, const unsigned int k) const
struct to handle the objective params of MP_Param/QP_Param
NashGame & addDummy(unsigned int par=0, int position=-1)
Add dummy variables in a NashGame object.
bool isPureStrategy(const unsigned int i, const double tol=1e-5) const
Add random polyhedra in each iteration.
unsigned int Leader_position
Game::EPECAddPolyMethod addPolyMethod
bool indicators
Uses bigM if false.
double getVal_LeadFoll(const unsigned int i, const unsigned int j) const
double RespondSol(arma::vec &sol, unsigned int player, const arma::vec &x, const arma::vec &prevDev) const
std::vector< unsigned int > mixedStratPoly(const unsigned int i, const double tol=1e-5) const
arma::sp_mat LeaderConstraints
Upper level leader constraints LHS.
ostream & operator<<(ostream &ost, const perps &C)
std::vector< unsigned int > primal_position
unsigned int addDeviatedPolyhedron(const std::vector< arma::vec > &devns, bool &infeasCheck) const
unsigned int getNy() const
Read-only access to the private variable Ny.
void print(const perps &C) noexcept
void write(std::string filename, bool append=true) const
bool getAllDevns(std::vector< arma::vec > &devns, const arma::vec &guessSol, const std::vector< arma::vec > &prevDev={}) const
Given a potential solution vector, returns a profitable deviation (if it exists) for all players...
unsigned int Nplayers
Number of players in the Nash Game.
double timeLimit
Controls the timelimit for solve in Game::EPEC::findNashEq.
double getVal_LeadFollPoly(const unsigned int i, const unsigned int j, const unsigned int k, const double tol=1e-5) const
void computeLeaderLocations(const unsigned int addSpaceForMC=0)
QP_Param & addDummy(unsigned int pars, unsigned int vars=0, int position=-1) override
Stores the configuration for EPEC algorithms.
Class to model Nash-cournot games with each player playing a QP.
long int load(std::string filename, long int pos=0)
Loads the Game::NashGame object stored in a file.
Game::EPECalgorithm algorithm
NashGame & addLeadCons(const arma::vec &a, double b)
Adds Leader constraint to a NashGame object.
arma::vec getb() const
Read-only access to the private variable b.
void fullEnumerationNash()
unsigned int getNshadow() const
Gets the number of Market clearing Shadow prices.
double getVal_LeadLead(const unsigned int i, const unsigned int j) const
bool isSolved(unsigned int *countryNumber, arma::vec *ProfDevn, double tol=51e-4) const
unsigned int getNprimals() const
Return the number of primal variables.
void save(std::string filename, bool erase=true) const
Saves the Game::NashGame object in a loadable file.
void setAlgorithm(Game::EPECalgorithm algorithm)