Program Listing for File epec_polybase.cpp
↰ Return to documentation for file (src/games/algorithms/EPEC/epec_polybase.cpp
)
/* #############################################
* This file is part of
* ZERO
*
* Copyright (c) 2020
* Released under the Creative Commons
* CC BY-NC-SA 4.0 License
*
* Find out more at
* https://github.com/ds4dm/ZERO
* #############################################*/
#include "games/algorithms/EPEC/epec_polybase.h"
bool Algorithms::EPEC::PolyBase::isSolved(unsigned int *player,
arma::vec * profitableDeviation,
double tol) const
{
if (!this->EPECObject->NashEquilibrium)
return false;
tol = this->EPECObject->Stats.AlgorithmData.DeviationTolerance.get();
if (tol < 0)
tol = 1e-5;
this->EPECObject->TheNashGame->isSolved(
this->EPECObject->SolutionX, *player, *profitableDeviation, tol);
arma::vec objvals =
this->EPECObject->TheNashGame->computeQPObjectiveValues(this->EPECObject->SolutionX, true);
for (unsigned int i = 0; i < this->EPECObject->NumPlayers; ++i) {
double val =
this->EPECObject->bestResponse(*profitableDeviation, i, this->EPECObject->SolutionX);
if (val == GRB_INFINITY)
return false;
if (!Utils::isEqual(val, objvals.at(i), tol, 1 - tol)) {
*player = i;
LOG_S(0) << "Algorithms::EPEC::PolyBase::isSolved: deviation for player " << i << " -- of "
<< std::abs(val - objvals.at(i));
return false;
}
}
return true;
}
bool Algorithms::EPEC::PolyBase::isSolved(double tol) {
unsigned int countryNumber;
arma::vec ProfDevn;
bool ret = this->isSolved(&countryNumber, &ProfDevn, tol);
return ret;
}
unsigned int Algorithms::EPEC::PolyBase::getPositionLeadFollPoly(const unsigned int i,
const unsigned int j,
const unsigned int k) const {
const auto LeaderStart = this->EPECObject->TheNashGame->getPrimalLoc(i);
const auto FollPoly = this->PolyLCP.at(i).get()->convPolyPosition(k, true);
return LeaderStart + FollPoly + j;
}
unsigned int Algorithms::EPEC::PolyBase::getPositionLeadLeadPoly(const unsigned int i,
const unsigned int j,
const unsigned int k) const {
const auto LeaderStart = this->EPECObject->TheNashGame->getPrimalLoc(i);
const auto FollPoly = this->PolyLCP.at(i).get()->convPolyPosition(k, true);
return LeaderStart + FollPoly + this->PolyLCP.at(i)->getLStart() + j;
}
unsigned long int Algorithms::EPEC::PolyBase::getNumPolyLead(const unsigned int i) const {
return this->PolyLCP.at(i).get()->convNumPoly(true);
}
unsigned int Algorithms::EPEC::PolyBase::getPositionProbab(const unsigned int i,
const unsigned int k) const {
const auto PolyProbab = dynamic_cast<MathOpt::PolyLCP *>(this->EPECObject->PlayersLCP.at(i).get())
->convPolyWeight(k, true);
if (PolyProbab == 0)
return 0;
const auto LeaderStart = this->EPECObject->TheNashGame->getPrimalLoc(i);
return LeaderStart + PolyProbab;
}
bool Algorithms::EPEC::PolyBase::isPureStrategy(const double tol) const {
for (unsigned int i = 0; i < this->EPECObject->getNumPlayers(); ++i) {
if (!isPureStrategy(i, tol))
return false;
}
return true;
}
bool Algorithms::EPEC::PolyBase::isPureStrategy(const unsigned int i, const double tol) const {
const unsigned int nPoly = this->getNumPolyLead(i);
for (unsigned int j = 0; j < nPoly; j++) {
const double probab = this->getValProbab(i, j);
if (probab > 1 - tol) // Current Strategy is a pure strategy!
return true;
}
return false;
}
std::vector<unsigned int> Algorithms::EPEC::PolyBase::mixedStrategyPoly(const unsigned int i,
const double tol) const {
std::vector<unsigned int> polys{};
const unsigned int nPoly = this->getNumPolyLead(i);
for (unsigned int j = 0; j < nPoly; j++) {
const double probab = this->getValProbab(i, j);
if (probab > tol)
polys.push_back(j);
}
std::cout << "\n";
return polys;
}
double Algorithms::EPEC::PolyBase::getValProbab(const unsigned int i, const unsigned int k) const {
const unsigned int varname{this->getPositionProbab(i, k)};
if (varname == 0)
return 1;
return this->EPECObject->SolutionX.at(varname);
}
double Algorithms::EPEC::PolyBase::getValLeadFollPoly(const unsigned int i,
const unsigned int j,
const unsigned int k,
const double tol) const {
if (!this->EPECObject->LCPModel)
throw ZEROException(ZEROErrorCode::Assertion, "LCPModel not made nor solved");
const double probab = this->getValProbab(i, k);
if (probab > 1 - tol)
return this->EPECObject->getValLeadFoll(i, j);
else
return this->EPECObject->SolutionX.at(this->getPositionLeadFollPoly(i, j, k)) / probab;
}
double Algorithms::EPEC::PolyBase::getValLeadLeadPoly(const unsigned int i,
const unsigned int j,
const unsigned int k,
const double tol) const {
if (!this->EPECObject->LCPModel)
throw ZEROException(ZEROErrorCode::Assertion, "LCPModel not made nor solved");
const double probab = this->getValProbab(i, k);
if (probab > 1 - tol)
return this->EPECObject->getValLeadLead(i, j);
else
return this->EPECObject->SolutionX.at(this->getPositionLeadLeadPoly(i, j, k)) / probab;
}
void Algorithms::EPEC::PolyBase::makeThePureLCP() {
try {
LOG_S(1) << "Game::EPEC::makeThePureLCP: editing the LCP model.";
this->EPECObject->LCPModelBase =
std::unique_ptr<GRBModel>(new GRBModel(*this->EPECObject->LCPModel));
const unsigned int nPolyLead = [this]() {
unsigned int ell = 0;
for (unsigned int i = 0; i < this->EPECObject->getNumPlayers(); ++i)
ell += (this->getNumPolyLead(i));
return ell;
}();
// Add a binary variable for each polyhedron of each leader
GRBVar pure_bin[nPolyLead];
GRBLinExpr objectiveTerm{0};
unsigned int count{0}, i, j;
for (i = 0; i < this->EPECObject->getNumPlayers(); i++) {
for (j = 0; j < this->getNumPolyLead(i); ++j) {
pure_bin[count] = this->EPECObject->LCPModel->addVar(
0, 1, 0, GRB_BINARY, "pureBin_" + std::to_string(i) + "_" + std::to_string(j));
this->EPECObject->LCPModel->addGenConstrIndicator(
pure_bin[count],
1,
this->EPECObject->LCPModel->getVarByName("x_" +
std::to_string(this->getPositionProbab(i, j))),
GRB_EQUAL,
0,
"Indicator_PNE_" + std::to_string(count));
objectiveTerm += pure_bin[count];
count++;
}
}
this->EPECObject->LCPModel->setObjective(objectiveTerm, GRB_MAXIMIZE);
} catch (GRBException &e) {
throw ZEROException(ZEROErrorCode::SolverError,
std::to_string(e.getErrorCode()) + e.getMessage());
}
}