Program Listing for File epec_models.h

Return to documentation for file (include/interfaces/epec_models.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 "zero.h"
#include <armadillo>
#include <gurobi_c++.h>
#include <iostream>
#include <memory>
#include <utility>

namespace Models {
  namespace EPEC {
     typedef struct FollPar    FollPar;
     typedef struct DemPar     DemPar;
     typedef struct LeadPar    LeadPar;
     typedef struct LeadAllPar LeadAllPar;


     enum class TaxType {
        StandardTax,
        SingleTax,
        CarbonTax
     };

     struct FollPar {

        std::vector<double> costs_quad =
             {};
        std::vector<double> costs_lin =
             {};
        std::vector<double> capacities =
             {};
        std::vector<double> emission_costs =
             {};
        std::vector<double>      tax_caps = {};
        std::vector<std::string> names    = {};
        FollPar(std::vector<double>      costs_quad_     = {},
                  std::vector<double>      costs_lin_      = {},
                  std::vector<double>      capacities_     = {},
                  std::vector<double>      emission_costs_ = {},
                  std::vector<double>      tax_caps_       = {},
                  std::vector<std::string> names_          = {})
             : costs_quad{costs_quad_}, costs_lin{costs_lin_}, capacities{capacities_},
                emission_costs{emission_costs_}, tax_caps(tax_caps_), names{names_} {}
     };

     /*
      * @brief Stores the parameters of the demand curve in a country model
      */
     struct DemPar {
        double alpha = 100;
        double beta = 2;
        DemPar(double alpha = 100, double beta = 2) : alpha{alpha}, beta{beta} {};
     };

     /*
      * @brief Stores the parameters of the leader in a country model
      */
     struct LeadPar {
        double import_limit = -1;
        double export_limit = -1;
        double price_limit  = -1;
        bool   tradeAllowed = true;

        Models::EPEC::TaxType tax_type = Models::EPEC::TaxType::StandardTax;
        /*
         * @brief Dictates whether the leader objective willinclude tax revenues
         */
        bool tax_revenue = false;
        LeadPar(double       imp_lim     = -1,
                  double       exp_lim     = -1,
                  double       price_limit = -1,
                  bool         tax_revenue = false,
                  unsigned int tax_type_   = 0,
                  bool         tradeBool   = true)
             : import_limit{imp_lim}, export_limit{exp_lim}, price_limit{price_limit},
                tax_revenue{tax_revenue}, tradeAllowed{tradeBool} {
          switch (tax_type_) {
          case 0:
             tax_type = Models::EPEC::TaxType::StandardTax;
             break;
          case 1:
             tax_type = Models::EPEC::TaxType::SingleTax;
             break;
          case 2:
             tax_type = Models::EPEC::TaxType::CarbonTax;
             break;
          default:
             tax_type = Models::EPEC::TaxType::StandardTax;
          }
        }
     };

     struct LeadAllPar {
        unsigned int          n_followers;
        std::string           name;
        Models::EPEC::FollPar FollowerParam = {};
        Models::EPEC::DemPar  DemandParam   = {};
        Models::EPEC::LeadPar LeaderParam   = {};
        LeadAllPar(unsigned int          n_foll,
                      std::string           name,
                      Models::EPEC::FollPar FP = {},
                      Models::EPEC::DemPar  DP = {},
                      Models::EPEC::LeadPar LP = {})
             : n_followers{n_foll}, name{std::move(name)}, FollowerParam{FP}, DemandParam{DP},
                LeaderParam{LP} {
          // Nothing here
        }
     };

     struct EPECInstance {
        std::vector<Models::EPEC::LeadAllPar> Countries = {};
        arma::sp_mat TransportationCosts                = {};

        explicit EPECInstance(std::string filename) {
          this->load(filename);
        }
        EPECInstance(std::vector<Models::EPEC::LeadAllPar> Countries_, arma::sp_mat Transp_)
             : Countries{Countries_}, TransportationCosts{Transp_} {}

        void load(const std::string &filename);

        void save(const std::string &filename);
     };

     enum class LeaderVars {
        FollowerStart,
        NetImport,
        NetExport,
        CountryImport,
        Caps,
        Tax,
        TaxQuad,
        DualVar,
        ConvHullDummy,
        End
     };

     std::ostream &operator<<(std::ostream &ost, const FollPar &P);

     std::ostream &operator<<(std::ostream &ost, const DemPar P);

     std::ostream &operator<<(std::ostream &ost, const LeadPar P);

     std::ostream &operator<<(std::ostream &ost, const LeadAllPar &P);

     std::ostream &operator<<(std::ostream &ost, const LeaderVars l);

     std::ostream &operator<<(std::ostream &ost, const EPECInstance &I);

     using LeadLocs = std::map<LeaderVars, unsigned int>;

     void increaseVal(LeadLocs &         L,
                            const LeaderVars   start,
                            const unsigned int val,
                            const bool         startnext = true);

     void decreaseVal(LeadLocs &         L,
                            const LeaderVars   start,
                            const unsigned int val,
                            const bool         startnext = true);

     void init(LeadLocs &L);

     LeaderVars operator+(Models::EPEC::LeaderVars a, int b);

     class EPEC : public Game::EPEC {
        // Mandatory virtuals
     private:
        void makeObjectivePlayer(const unsigned int i, MathOpt::QP_Objective &QP_obj) final;

        void updateLocations() override;

        void preFinalize() override;

        void postFinalize() override{};
        // override;

     public:
        // Rest
     private:
        std::vector<LeadAllPar> AllLeadPars = {};
        std::vector<std::shared_ptr<MathOpt::QP_Param>> MC_QP =
             {};
        arma::sp_mat TranspCosts = {};
        std::vector<unsigned int> nImportMarkets =
             {};
        std::vector<LeadLocs> Locations = {};

        std::map<std::string, unsigned int> name2nos = {};
        unsigned int                        taxVars  = {0};
        std::vector<arma::sp_mat>           LeadConses{};
        std::vector<arma::vec>              LeadRHSes{};

        bool dataCheck(bool chkAllLeadPars     = true,
                            bool chkcountriesLL     = true,
                            bool chkMC_QP           = true,
                            bool chkLeadConses      = true,
                            bool chkLeadRHSes       = true,
                            bool chknImportMarkets  = true,
                            bool chkLocations       = true,
                            bool chkLeaderLocations = true,
                            bool chkLeadObjec       = true) const;

        // Super low level
        bool ParamValid(const LeadAllPar &Param) const;

        void make_LL_QP(const LeadAllPar & Params,
                             const unsigned int follower,
                             MathOpt::QP_Param *Foll,
                             const LeadLocs &   Loc) noexcept;

        void make_LL_LeadCons(arma::sp_mat &                LeadCons,
                                     arma::vec &                   LeadRHS,
                                     const LeadAllPar &            Param,
                                     const Models::EPEC::LeadLocs &Loc             = {},
                                     const unsigned int            import_lim_cons = 1,
                                     const unsigned int            export_lim_cons = 1,
                                     const unsigned int            price_lim_cons  = 1,
                                     const unsigned int            activeTaxCaps   = 0,
                                     const unsigned int            disableTrade    = 0) const noexcept;

        void add_Leaders_tradebalance_constraints(const unsigned int i);

        void make_MC_leader(const unsigned int i);

        void makeMCConstraints(arma::sp_mat &MCLHS, arma::vec &MCRHS) const override;

        void WriteCountrySolution(const unsigned int i,
                                          const std::string &filename,
                                          const arma::vec &  x,
                                          const bool         append = true) const;

        void WriteFollower(const unsigned int i,
                                 const unsigned int j,
                                 const std::string &filename,
                                 const arma::vec &  x,
                                 bool               append) const;

     public:                        // Attributes
        bool quadraticTax = {false};

        // double TimeLimit = {-1}; ///< Controls the TimeLimit (s) for findNashEq

        EPEC() = delete;

        EPEC(GRBEnv *env, arma::sp_mat TranspCosts = {})
             : Game::EPEC(env), TranspCosts{TranspCosts} {}

        EPEC &addCountry(
             LeadAllPar Params,
             const unsigned int addnlLeadVars = 0);

        EPEC &addTranspCosts(const arma::sp_mat &costs);

        unsigned int getPosition(const unsigned int countryCount,
                                         const LeaderVars   var = LeaderVars::FollowerStart) const;

        unsigned int getPosition(const std::string &countryCount,
                                         const LeaderVars   var = LeaderVars::FollowerStart) const;

        EPEC &unlock();

        std::unique_ptr<GRBModel> Respond(const std::string &name, const arma::vec &x) const;

        // Data access methods
        Game::NashGame *get_LowerLevelNash(const unsigned int i) const;

        // Writing model files
        void
        writeLeadParams(const std::string &filename, const unsigned int i, bool append = true) const;

        void readSolutionJSON(const std::string &filename);

        void
        writeSolutionJSON(const std::string &filename, const arma::vec &x, const arma::vec &z) const;

        void writeSolution(const int writeLevel, const std::string &filename) const;

        const EPECInstance getInstance() const {
          return EPECInstance(this->AllLeadPars, this->TranspCosts);
        }
     };

     /*
      * @brief Enum class for handling print of labels and their values.
      */
     enum class prn { label, val };

     std::ostream &operator<<(std::ostream &ost, Models::EPEC::prn l);
  } // namespace EPEC
} // namespace Models

// Gurobi functions
std::string to_string(const GRBVar &var);

std::string to_string(const GRBConstr &cons, const GRBModel &model);

Models::EPEC::FollPar operator+(const Models::EPEC::FollPar &F1, const Models::EPEC::FollPar &F2);