Program Listing for File epec.h

Return to documentation for file (include/games/epec.h)

/* #############################################
 *             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
 * #############################################*/


#pragma once
#include "support/codes.h"
#include "zero.h"
#include <armadillo>
#include <gurobi_c++.h>
#include <iostream>
#include <mathopt/lcp/lcp.h>
#include <memory>
#include <set>
#include <string>

namespace Data::EPEC {

  enum class Algorithms {

     FullEnumeration,
     InnerApproximation,
     CombinatorialPne,
     OuterApproximation
  };
  enum class RecoverStrategy {
     IncrementalEnumeration,
     Combinatorial
  };

  enum class BranchingStrategy {
     HybridBranching,
     DeviationBranching,
  };


  class DataObject : public ZEROAlgorithmData {
  public:
     Attr<Data::EPEC::Algorithms> Algorithm = {
          Data::EPEC::Algorithms::FullEnumeration};
     Attr<Data::EPEC::RecoverStrategy> RecoverStrategy = {
          Data::EPEC::RecoverStrategy::IncrementalEnumeration};
     Attr<Data::LCP::PolyhedraStrategy>
                              PolyhedraStrategy;
     Attr<unsigned int> Aggressiveness{
          1};
     Attr<std::vector<unsigned int>> FeasiblePolyhedra =
          std::vector<unsigned int>();
     Attr<std::vector<unsigned int>> OuterComplementarities =
          std::vector<unsigned int>();
     Attr<int> LostIntermediateEq = {0};
     Attr<Data::LCP::Algorithms>
          LCPSolver;

     Attr<Data::EPEC::BranchingStrategy> BranchingStrategy =
          Data::EPEC::BranchingStrategy::HybridBranching;

     DataObject()
          : PolyhedraStrategy{static_cast<Data::LCP::PolyhedraStrategy>(0)},
             LCPSolver{static_cast<Data::LCP::Algorithms>(0)} {};
  };

} // namespace Data::EPEC

namespace Game {

  class EPEC : public AbstractGame<Data::EPEC::DataObject> {
  private:
     std::shared_ptr<Algorithms::EPEC::PolyBase>
          Algorithm{};
     std::vector<unsigned int>
          SizesWithoutHull{};
     std::unique_ptr<MathOpt::LCP> TheLCP;
     std::unique_ptr<GRBModel>     LCPModel;
     std::unique_ptr<GRBModel> LCPModelBase;
  protected:
     std::vector<std::shared_ptr<Game::NashGame>>
          PlayersLowerLevels{};
     std::vector<std::shared_ptr<MathOpt::LCP>>
          PlayersLCP{};

     std::vector<std::shared_ptr<MathOpt::QP_Param>>
          PlayersQP{};
     std::vector<std::shared_ptr<MathOpt::QP_Objective>>
          LeaderObjective{};
     std::vector<std::shared_ptr<MathOpt::QP_Objective>>
          LeaderObjectiveConvexHull{};

     std::unique_ptr<Game::NashGame> TheNashGame;

     std::vector<unsigned int> LeaderLocations{};
     std::vector<const unsigned int *>
          LocEnds{};
     std::vector<unsigned int>
                      ConvexHullVariables{};
     unsigned int numMCVariables{0};

     bool      Finalized{false};
     arma::vec SolutionZ,
          SolutionX;
     bool warmstart(const arma::vec &x);

  private:
     void addDummyLead(unsigned int i);
     void makePlayerQP(unsigned int i);

     void makePlayersQPs();

     void makeTheLCP();


     void computeLeaderLocations(unsigned int addSpaceForMC = 0);

     void getXMinusI(const arma::vec &x, const unsigned int &i, arma::vec &xMinusI) const;

     bool computeNashEq(
          bool pureNE, double localTimeLimit, bool check, bool linearWelfare, bool quadraticWelfare);

  protected:
     virtual void makeObjectivePlayer(const unsigned int i, MathOpt::QP_Objective &QP_obj) = 0;

     virtual void preFinalize() = 0;

     virtual void postFinalize() = 0;

     virtual void updateLocations() = 0;
     virtual void makeMCConstraints(arma::sp_mat &MC, arma::vec &RHS) const {
        MC.zeros();
        RHS.zeros();
     };

  public: // functions
     // Friends algorithmic classes
     friend class Algorithms::EPEC::PolyBase;

     friend class Algorithms::EPEC::InnerApproximation;

     friend class Algorithms::EPEC::CutAndPlay;

     friend class Algorithms::EPEC::CombinatorialPNE;

     friend class Algorithms::EPEC::FullEnumeration;

     EPEC(GRBEnv *env) { this->Env = env; };

     void finalize();

     // Override AbstractGame methods
     void findNashEq() override;
     bool isSolved(double tol = 1e-5) const override;
     bool isPureStrategy(double tol = 1e-5) const override;

     std::unique_ptr<GRBModel> bestResponseProgram(const unsigned int i, const arma::vec &x, MathOpt::PolyLCP *customLCP = nullptr) const;

     double bestResponse(arma::vec &       sol,
                             unsigned int      player,
                             const arma::vec & x,
                             const arma::vec & prevDev   = {},
                             MathOpt::PolyLCP *customLCP = nullptr) const;

     const arma::vec getX() const { return this->SolutionX; }

     const arma::vec getZ() const { return this->SolutionZ; }

     void setAlgorithm(Data::EPEC::Algorithms algorithm);

     void setRecoverStrategy(Data::EPEC::RecoverStrategy strategy);

     void setBranchingStrategy(Data::EPEC::BranchingStrategy strategy);

     void setAggressiveness(unsigned int a) { this->Stats.AlgorithmData.Aggressiveness = a; }

     void setAddPolyMethod(Data::LCP::PolyhedraStrategy add) {
        this->Stats.AlgorithmData.PolyhedraStrategy.set(add);
     }

     unsigned int getPositionLeadFoll(unsigned int i, unsigned int j) const;

     unsigned int getPositionLeadLead(unsigned int i, unsigned int j) const;

     // The following obtain the variable values
     double getValLeadFoll(unsigned int i, unsigned int j) const;

     double getValLeadLead(unsigned int i, unsigned int j) const;

    double getValProbab(unsigned int i, unsigned int k);
    double getValLeadFollPoly(unsigned int i,
                              unsigned int j,
                              unsigned int k,
                              double       tol=1e-5) const;
    double getValLeadLeadPoly(unsigned int i,
                              unsigned int j,
                              unsigned int k,
                              double       tol=1e-5) const;

    std::vector<unsigned int> mixedStrategyPoly(unsigned int i, double tol=1e-5) const;

     const MathOpt::LCP &getLCPDescription() const { return *this->TheLCP.get(); }

     const GRBModel &getLCPModel() const { return *this->LCPModel.get(); }

     void writeLCPModel(const std::string &filename) const { this->LCPModel->write(filename); }

     void getXWithoutHull(const arma::vec &x, arma::vec &xWithoutHull) const;
     void
     getXofI(const arma::vec &x, const unsigned int &i, arma::vec &xOfI, bool hull = false) const;
     void setWelfareObjective(bool linear, bool quadratic);
  };
}; // namespace Game

namespace std {

  string to_string(Data::EPEC::Algorithms al);

  string to_string(Data::EPEC::RecoverStrategy st);

  string to_string(Data::EPEC::BranchingStrategy st);

}; // namespace std

#include "interfaces/epec_models.h"