Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,6 @@ game_SOURCES = \
src/games/behavmixed.h \
src/games/stratspt.cc \
src/games/stratspt.h \
src/games/stratpure.cc \
src/games/stratpure.h \
src/games/stratmixed.h \
src/games/file.cc \
Expand Down
3 changes: 3 additions & 0 deletions src/games/behavmixed.cc
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ template <class T> MixedBehaviorProfile<T> MixedBehaviorProfile<T>::ToFullSuppor

template <class T> T MixedBehaviorProfile<T>::GetLiapValue() const
{
m_support.GetGame()->BuildComputedValues();
return MixedStrategyProfile<T>(*this).GetLiapValue();
}

Expand Down Expand Up @@ -356,6 +357,7 @@ template <class T> T MixedBehaviorProfile<T>::GetRegret(const GameInfoset &p_inf

template <class T> T MixedBehaviorProfile<T>::GetMaxRegret() const
{
m_support.GetGame()->BuildComputedValues();
return MixedStrategyProfile<T>(*this).GetMaxRegret();
}

Expand Down Expand Up @@ -553,6 +555,7 @@ template <class T> bool MixedBehaviorProfile<T>::IsDefinedAt(GameInfoset p_infos
template <class T> MixedStrategyProfile<T> MixedBehaviorProfile<T>::ToMixedProfile() const
{
CheckVersion();
m_support.GetGame()->BuildComputedValues();
return MixedStrategyProfile<T>(*this);
}

Expand Down
10 changes: 4 additions & 6 deletions src/games/file.cc
Original file line number Diff line number Diff line change
Expand Up @@ -411,23 +411,21 @@ void ReadOutcomeList(GameFileLexer &p_parser, Game &p_nfg)
void ParseOutcomeBody(GameFileLexer &p_parser, Game &p_nfg)
{
ReadOutcomeList(p_parser, p_nfg);
const StrategySupportProfile profile(p_nfg);
for (auto iter : StrategyContingencies(profile)) {
for (const auto &profile : StrategyContingencies(p_nfg)) {
p_parser.ExpectCurrentToken(TOKEN_NUMBER, "outcome index");
if (const int outcomeId = std::stoi(p_parser.GetLastText())) {
iter->SetOutcome(p_nfg->GetOutcome(outcomeId));
profile->SetOutcome(p_nfg->GetOutcome(outcomeId));
}
p_parser.GetNextToken();
}
}

void ParsePayoffBody(GameFileLexer &p_parser, Game &p_nfg)
{
const StrategySupportProfile profile(p_nfg);
for (auto iter : StrategyContingencies(profile)) {
for (const auto &profile : StrategyContingencies(p_nfg)) {
for (const auto &player : p_nfg->GetPlayers()) {
p_parser.ExpectCurrentToken(TOKEN_NUMBER, "numerical payoff");
iter->GetOutcome()->SetPayoff(player, Number(p_parser.GetLastText()));
profile->GetOutcome()->SetPayoff(player, Number(p_parser.GetLastText()));
p_parser.GetNextToken();
}
}
Expand Down
28 changes: 28 additions & 0 deletions src/games/game.cc
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,24 @@ GameRep::~GameRep()
}
}

void GameRep::IndexStrategies() const
{
const size_t n = m_players.size();
m_pureStrategies.m_radices.resize(n);
m_pureStrategies.m_strides.resize(n);

long stride = 1L;
for (size_t i = 0; i < n; ++i) {
const auto &player = m_players[i];
m_pureStrategies.m_strides[i] = stride;
m_pureStrategies.m_radices[i] = player->m_strategies.size();
for (auto [st, strategy] : enumerate(player->m_strategies)) {
strategy->m_number = st + 1;
}
stride *= m_pureStrategies.m_radices[i];
}
}

//------------------------------------------------------------------------
// GameRep: Writing data files
//------------------------------------------------------------------------
Expand Down Expand Up @@ -405,6 +423,16 @@ template <class T> T MixedStrategyProfile<T>::GetMaxRegret() const
[this](const auto &player) -> T { return this->GetRegret(player); });
}

MixedStrategyProfile<Rational> PureStrategyProfileRep::ToMixedStrategyProfile() const
{
auto temp = m_game->NewMixedStrategyProfile(Rational(0));
temp = Rational(0);
for (const auto &player : m_game->GetPlayers()) {
temp[GetStrategy(player)] = Rational(1);
}
return temp;
}

template class MixedStrategyProfileRep<double>;
template class MixedStrategyProfileRep<Rational>;

Expand Down
24 changes: 23 additions & 1 deletion src/games/game.h
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ class GameInfosetRep : public std::enable_shared_from_this<GameInfosetRep> {
/// relatively efficient.
class GameStrategyRep : public std::enable_shared_from_this<GameStrategyRep> {
friend class GameExplicitRep;
friend class GameRep;
friend class GameTreeRep;
friend class GameTableRep;
friend class GameAGGRep;
Expand All @@ -283,7 +284,6 @@ class GameStrategyRep : public std::enable_shared_from_this<GameStrategyRep> {
bool m_valid{true};
GamePlayerRep *m_player;
int m_number;
long m_offset{-1L};
std::string m_label;
std::map<GameInfosetRep *, int> m_behav;

Expand Down Expand Up @@ -360,6 +360,7 @@ class GamePlayerRep : public std::enable_shared_from_this<GamePlayerRep> {
friend class GameInfosetRep;
friend class GameNodeRep;
friend class StrategySupportProfile;
friend class PureStrategyProfileRep;
template <class T> friend class MixedBehaviorProfile;
template <class T> friend class MixedStrategyProfile;

Expand Down Expand Up @@ -594,6 +595,24 @@ inline GameNode GameNodeRep::Actions::iterator::GetOwner() const { return m_chil

enum class TraversalOrder { Preorder, Postorder };

class CartesianProductSpace {
public:
std::vector<int> m_radices;
std::vector<long> m_strides;
};

class CartesianSubset {
public:
const CartesianProductSpace *m_space{nullptr};
std::vector<std::vector<int>> m_allowedDigits;
};

template <class T> class CartesianTensor {
public:
const CartesianProductSpace *m_space{nullptr};
std::vector<T> m_data;
};

/// This is the class for representing an arbitrary finite game.
class GameRep : public std::enable_shared_from_this<GameRep> {
friend class GameOutcomeRep;
Expand All @@ -602,13 +621,15 @@ class GameRep : public std::enable_shared_from_this<GameRep> {
friend class GamePlayerRep;
friend class PureStrategyProfileRep;
friend class TablePureStrategyProfileRep;
friend class StrategySupportProfile;
template <class T> friend class MixedBehaviorProfile;
template <class T> friend class MixedStrategyProfile;
template <class T> friend class TableMixedStrategyProfileRep;

protected:
std::vector<std::shared_ptr<GamePlayerRep>> m_players;
std::vector<std::shared_ptr<GameOutcomeRep>> m_outcomes;
mutable CartesianProductSpace m_pureStrategies;
std::string m_title, m_comment;
unsigned int m_version{0};

Expand All @@ -618,6 +639,7 @@ class GameRep : public std::enable_shared_from_this<GameRep> {
//@{
/// Mark that the content of the game has changed
void IncrementVersion() { m_version++; }
void IndexStrategies() const;
//@}

/// Hooks for derived classes to update lazily-computed orderings if required
Expand Down
33 changes: 12 additions & 21 deletions src/games/gameagg.cc
Original file line number Diff line number Diff line change
Expand Up @@ -51,21 +51,21 @@ class AGGPureStrategyProfileRep : public PureStrategyProfileRep {

Rational AGGPureStrategyProfileRep::GetPayoff(const GamePlayer &p_player) const
{
const std::shared_ptr<agg::AGG> aggPtr = dynamic_cast<GameAGGRep &>(*m_nfg).aggPtr;
const std::shared_ptr<agg::AGG> aggPtr = dynamic_cast<GameAGGRep &>(*m_game).aggPtr;
std::vector<int> s(aggPtr->getNumPlayers());
for (int i = 1; i <= aggPtr->getNumPlayers(); i++) {
s[i - 1] = m_profile.at(m_nfg->GetPlayer(i))->GetNumber() - 1;
s[i - 1] = GetStrategy(m_game->GetPlayer(i))->GetNumber() - 1;
}
return Rational(aggPtr->getPurePayoff(p_player->GetNumber() - 1, s));
}

Rational AGGPureStrategyProfileRep::GetStrategyValue(const GameStrategy &p_strategy) const
{
const int player = p_strategy->GetPlayer()->GetNumber();
const std::shared_ptr<agg::AGG> aggPtr = dynamic_cast<GameAGGRep &>(*m_nfg).aggPtr;
const std::shared_ptr<agg::AGG> aggPtr = dynamic_cast<GameAGGRep &>(*m_game).aggPtr;
std::vector<int> s(aggPtr->getNumPlayers());
for (int i = 1; i <= aggPtr->getNumPlayers(); i++) {
s[i - 1] = m_profile.at(m_nfg->GetPlayer(i))->GetNumber() - 1;
s[i - 1] = GetStrategy(m_game->GetPlayer(i))->GetNumber() - 1;
}
s[player - 1] = p_strategy->GetNumber() - 1;
return Rational(aggPtr->getPurePayoff(player - 1, s));
Expand Down Expand Up @@ -236,23 +236,14 @@ GameAGGRep::NewMixedStrategyProfile(const Rational &, const StrategySupportProfi

bool GameAGGRep::IsConstSum() const
{
auto profile = NewPureStrategyProfile();
Rational sum(0);
for (const auto &player : m_players) {
sum += profile->GetPayoff(player);
}

for (auto iter : StrategyContingencies(std::const_pointer_cast<GameRep>(shared_from_this()))) {
Rational newsum(0);
for (const auto &player : m_players) {
newsum += iter->GetPayoff(player);
}
if (newsum != sum) {
return false;
}
}

return true;
auto payoff_sum = [&](const PureStrategyProfile &p) {
return sum_function(m_players, [&](const auto &player) { return p->GetPayoff(player); });
};
const Rational sum = payoff_sum(NewPureStrategyProfile());

auto contingencies = StrategyContingencies(std::const_pointer_cast<GameRep>(shared_from_this()));
return std::all_of(contingencies.begin(), contingencies.end(),
[&](const PureStrategyProfile &p) { return payoff_sum(p) == sum; });
}

//------------------------------------------------------------------------
Expand Down
20 changes: 10 additions & 10 deletions src/games/gamebagg.cc
Original file line number Diff line number Diff line change
Expand Up @@ -50,26 +50,26 @@ class BAGGPureStrategyProfileRep : public PureStrategyProfileRep {

Rational BAGGPureStrategyProfileRep::GetPayoff(const GamePlayer &p_player) const
{
const std::shared_ptr<agg::BAGG> baggPtr = dynamic_cast<GameBAGGRep &>(*m_nfg).baggPtr;
std::vector<int> s(m_nfg->NumPlayers());
for (size_t i = 1; i <= m_nfg->NumPlayers(); i++) {
s[i - 1] = m_profile.at(m_nfg->GetPlayer(i))->GetNumber() - 1;
const std::shared_ptr<agg::BAGG> baggPtr = dynamic_cast<GameBAGGRep &>(*m_game).baggPtr;
std::vector<int> s(m_game->NumPlayers());
for (size_t i = 1; i <= m_game->NumPlayers(); i++) {
s[i - 1] = GetStrategy(m_game->GetPlayer(i))->GetNumber() - 1;
}
const int bp = dynamic_cast<GameBAGGRep &>(*m_nfg).agent2baggPlayer[p_player->GetNumber()];
const int bp = dynamic_cast<GameBAGGRep &>(*m_game).agent2baggPlayer[p_player->GetNumber()];
const int tp = p_player->GetNumber() - 1 - baggPtr->typeOffset[bp - 1];
return Rational(baggPtr->getPurePayoff(bp - 1, tp, s));
}

Rational BAGGPureStrategyProfileRep::GetStrategyValue(const GameStrategy &p_strategy) const
{
const int player = p_strategy->GetPlayer()->GetNumber();
const std::shared_ptr<agg::BAGG> baggPtr = dynamic_cast<GameBAGGRep &>(*m_nfg).baggPtr;
std::vector<int> s(m_nfg->NumPlayers());
for (size_t i = 1; i <= m_nfg->NumPlayers(); i++) {
s[i - 1] = m_profile.at(m_nfg->GetPlayer(i))->GetNumber() - 1;
const std::shared_ptr<agg::BAGG> baggPtr = dynamic_cast<GameBAGGRep &>(*m_game).baggPtr;
std::vector<int> s(m_game->NumPlayers());
for (size_t i = 1; i <= m_game->NumPlayers(); i++) {
s[i - 1] = GetStrategy(m_game->GetPlayer(i))->GetNumber() - 1;
}
s[player - 1] = p_strategy->GetNumber() - 1;
const int bp = dynamic_cast<GameBAGGRep &>(*m_nfg).agent2baggPlayer[player];
const int bp = dynamic_cast<GameBAGGRep &>(*m_game).agent2baggPlayer[player];
const int tp = player - 1 - baggPtr->typeOffset[bp - 1];
return Rational(baggPtr->getPurePayoff(bp - 1, tp, s));
}
Expand Down
Loading