From 724e88988e2a266272f33d1805c26e6297bf5405 Mon Sep 17 00:00:00 2001 From: StephenPasteris Date: Mon, 3 Nov 2025 17:04:29 +0000 Subject: [PATCH 01/29] Rebased onto lastest master --- Makefile.am | 2 +- src/games/behavspt.cc | 12 ++++++++---- src/games/behavspt.h | 2 +- src/{solvers/enumpoly => games}/indexproduct.h | 0 src/solvers/enumpoly/polypartial.imp | 2 +- src/solvers/enumpoly/polysolver.cc | 2 +- 6 files changed, 12 insertions(+), 8 deletions(-) rename src/{solvers/enumpoly => games}/indexproduct.h (100%) diff --git a/Makefile.am b/Makefile.am index 4325353ef..5f7151100 100644 --- a/Makefile.am +++ b/Makefile.am @@ -287,6 +287,7 @@ game_SOURCES = \ src/gambit.h \ src/games/gameseq.cc \ src/games/gameseq.h \ + src/games/indexproduct.h \ src/games/ndarray.h \ src/games/number.h \ src/games/gameobject.h \ @@ -401,7 +402,6 @@ gambit_nashsupport_SOURCES = \ gambit_enumpoly_SOURCES = \ ${core_SOURCES} ${game_SOURCES} ${gambit_nashsupport_SOURCES} \ - src/solvers/enumpoly/indexproduct.h \ src/solvers/enumpoly/rectangle.h \ src/solvers/enumpoly/poly.cc \ src/solvers/enumpoly/poly.h \ diff --git a/src/games/behavspt.cc b/src/games/behavspt.cc index 6b9004acc..e98352bbe 100644 --- a/src/games/behavspt.cc +++ b/src/games/behavspt.cc @@ -274,12 +274,14 @@ std::shared_ptr BehaviorSupportProfile::GetSequenceForm() cons SequencesWrapper BehaviorSupportProfile::GetSequences() const { - return SequencesWrapper(GetSequenceForm()->GetSequences()); + auto sequences = GetSequenceForm()->GetSequences(); + return SequencesWrapper(sequences); } PlayerSequencesWrapper BehaviorSupportProfile::GetSequences(GamePlayer &p_player) const { - return PlayerSequencesWrapper(GetSequenceForm()->GetSequences(p_player)); + auto sequences = GetSequenceForm()->GetSequences(p_player); + return PlayerSequencesWrapper(sequences); } int BehaviorSupportProfile::GetConstraintEntry(const GameInfoset &p_infoset, @@ -303,12 +305,14 @@ MixedBehaviorProfile BehaviorSupportProfile::ToMixedBehaviorProfile( InfosetsWrapper BehaviorSupportProfile::GetInfosets() const { - return InfosetsWrapper(GetSequenceForm()->GetInfosets()); + auto infosets = GetSequenceForm()->GetInfosets(); + return InfosetsWrapper(infosets); } ContingenciesWrapper BehaviorSupportProfile::GetContingencies() const { - return ContingenciesWrapper(GetSequenceForm()->GetContingencies()); + auto contingencies = GetSequenceForm()->GetContingencies(); + return ContingenciesWrapper(contingencies); } } // end namespace Gambit diff --git a/src/games/behavspt.h b/src/games/behavspt.h index 099234ba0..4018c4c10 100644 --- a/src/games/behavspt.h +++ b/src/games/behavspt.h @@ -30,7 +30,7 @@ namespace Gambit { class GameSequenceForm; -class GameSequenceRep; +struct GameSequenceRep; class SequencesWrapper; class PlayerSequencesWrapper; class InfosetsWrapper; diff --git a/src/solvers/enumpoly/indexproduct.h b/src/games/indexproduct.h similarity index 100% rename from src/solvers/enumpoly/indexproduct.h rename to src/games/indexproduct.h diff --git a/src/solvers/enumpoly/polypartial.imp b/src/solvers/enumpoly/polypartial.imp index 9248c5251..9bf84f466 100644 --- a/src/solvers/enumpoly/polypartial.imp +++ b/src/solvers/enumpoly/polypartial.imp @@ -21,7 +21,7 @@ // #include "polypartial.h" -#include "indexproduct.h" +#include "games/indexproduct.h" namespace Gambit { diff --git a/src/solvers/enumpoly/polysolver.cc b/src/solvers/enumpoly/polysolver.cc index 7a59fd5c9..d7b5d15a7 100644 --- a/src/solvers/enumpoly/polysolver.cc +++ b/src/solvers/enumpoly/polysolver.cc @@ -21,7 +21,7 @@ // #include "polysolver.h" -#include "indexproduct.h" +#include "games/indexproduct.h" namespace Gambit { From c327bd224312c3df3b7442bc9f6343ebc4960589 Mon Sep 17 00:00:00 2001 From: StephenPasteris Date: Tue, 11 Nov 2025 11:35:09 +0000 Subject: [PATCH 02/29] Moved indexproduct.h back to enumpoly --- Makefile.am | 2 +- src/{games => solvers/enumpoly}/indexproduct.h | 0 src/solvers/enumpoly/polypartial.imp | 2 +- src/solvers/enumpoly/polysolver.cc | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) rename src/{games => solvers/enumpoly}/indexproduct.h (100%) diff --git a/Makefile.am b/Makefile.am index 5f7151100..4325353ef 100644 --- a/Makefile.am +++ b/Makefile.am @@ -287,7 +287,6 @@ game_SOURCES = \ src/gambit.h \ src/games/gameseq.cc \ src/games/gameseq.h \ - src/games/indexproduct.h \ src/games/ndarray.h \ src/games/number.h \ src/games/gameobject.h \ @@ -402,6 +401,7 @@ gambit_nashsupport_SOURCES = \ gambit_enumpoly_SOURCES = \ ${core_SOURCES} ${game_SOURCES} ${gambit_nashsupport_SOURCES} \ + src/solvers/enumpoly/indexproduct.h \ src/solvers/enumpoly/rectangle.h \ src/solvers/enumpoly/poly.cc \ src/solvers/enumpoly/poly.h \ diff --git a/src/games/indexproduct.h b/src/solvers/enumpoly/indexproduct.h similarity index 100% rename from src/games/indexproduct.h rename to src/solvers/enumpoly/indexproduct.h diff --git a/src/solvers/enumpoly/polypartial.imp b/src/solvers/enumpoly/polypartial.imp index 9bf84f466..9248c5251 100644 --- a/src/solvers/enumpoly/polypartial.imp +++ b/src/solvers/enumpoly/polypartial.imp @@ -21,7 +21,7 @@ // #include "polypartial.h" -#include "games/indexproduct.h" +#include "indexproduct.h" namespace Gambit { diff --git a/src/solvers/enumpoly/polysolver.cc b/src/solvers/enumpoly/polysolver.cc index d7b5d15a7..7a59fd5c9 100644 --- a/src/solvers/enumpoly/polysolver.cc +++ b/src/solvers/enumpoly/polysolver.cc @@ -21,7 +21,7 @@ // #include "polysolver.h" -#include "games/indexproduct.h" +#include "indexproduct.h" namespace Gambit { From 2b80cec0c68d86366e86451f488fc6a76128e3fa Mon Sep 17 00:00:00 2001 From: StephenPasteris Date: Tue, 11 Nov 2025 11:45:48 +0000 Subject: [PATCH 03/29] Made one-liners in wrapper methods --- src/games/behavspt.cc | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/games/behavspt.cc b/src/games/behavspt.cc index e98352bbe..6b9004acc 100644 --- a/src/games/behavspt.cc +++ b/src/games/behavspt.cc @@ -274,14 +274,12 @@ std::shared_ptr BehaviorSupportProfile::GetSequenceForm() cons SequencesWrapper BehaviorSupportProfile::GetSequences() const { - auto sequences = GetSequenceForm()->GetSequences(); - return SequencesWrapper(sequences); + return SequencesWrapper(GetSequenceForm()->GetSequences()); } PlayerSequencesWrapper BehaviorSupportProfile::GetSequences(GamePlayer &p_player) const { - auto sequences = GetSequenceForm()->GetSequences(p_player); - return PlayerSequencesWrapper(sequences); + return PlayerSequencesWrapper(GetSequenceForm()->GetSequences(p_player)); } int BehaviorSupportProfile::GetConstraintEntry(const GameInfoset &p_infoset, @@ -305,14 +303,12 @@ MixedBehaviorProfile BehaviorSupportProfile::ToMixedBehaviorProfile( InfosetsWrapper BehaviorSupportProfile::GetInfosets() const { - auto infosets = GetSequenceForm()->GetInfosets(); - return InfosetsWrapper(infosets); + return InfosetsWrapper(GetSequenceForm()->GetInfosets()); } ContingenciesWrapper BehaviorSupportProfile::GetContingencies() const { - auto contingencies = GetSequenceForm()->GetContingencies(); - return ContingenciesWrapper(contingencies); + return ContingenciesWrapper(GetSequenceForm()->GetContingencies()); } } // end namespace Gambit From 451ba0c867f9861b2de3755c9ffa0dc687f87a72 Mon Sep 17 00:00:00 2001 From: StephenPasteris Date: Tue, 11 Nov 2025 11:52:11 +0000 Subject: [PATCH 04/29] Changed GameSequenceRep from struct to class --- src/games/behavspt.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/behavspt.h b/src/games/behavspt.h index 4018c4c10..099234ba0 100644 --- a/src/games/behavspt.h +++ b/src/games/behavspt.h @@ -30,7 +30,7 @@ namespace Gambit { class GameSequenceForm; -struct GameSequenceRep; +class GameSequenceRep; class SequencesWrapper; class PlayerSequencesWrapper; class InfosetsWrapper; From 54f33c7e3793da9b2f78483414ccde5695d0604e Mon Sep 17 00:00:00 2001 From: StephenPasteris Date: Wed, 12 Nov 2025 11:51:43 +0000 Subject: [PATCH 05/29] Defined GetReachableInfosets() --- src/games/behavspt.cc | 24 ++++++++++++++++++++++++ src/games/behavspt.h | 4 ++++ 2 files changed, 28 insertions(+) diff --git a/src/games/behavspt.cc b/src/games/behavspt.cc index 6b9004acc..a18b978be 100644 --- a/src/games/behavspt.cc +++ b/src/games/behavspt.cc @@ -311,4 +311,28 @@ ContingenciesWrapper BehaviorSupportProfile::GetContingencies() const return ContingenciesWrapper(GetSequenceForm()->GetContingencies()); } +//======================================================================== +// BehaviorSupportProfile: Reachable Information Sets +//======================================================================== + +void BehaviorSupportProfile::FindReachableInfosets(GameNode p_node) const +{ + if (!p_node->IsTerminal()) { + auto infoset = p_node->GetInfoset(); + m_reachable->insert(infoset); + for (auto action : GetActions(infoset)) { + FindReachableInfosets(p_node->GetChild(action)); + } + } +} + +std::shared_ptr> BehaviorSupportProfile::GetReachableInfosets() const +{ + if (!m_reachable) { + m_reachable = std::make_shared>(); + FindReachableInfosets(GetGame()->GetRoot()); + } + return m_reachable; +} + } // end namespace Gambit diff --git a/src/games/behavspt.h b/src/games/behavspt.h index 099234ba0..2d083ae49 100644 --- a/src/games/behavspt.h +++ b/src/games/behavspt.h @@ -160,6 +160,10 @@ class BehaviorSupportProfile { ToMixedBehaviorProfile(const std::map, double> &) const; InfosetsWrapper GetInfosets() const; ContingenciesWrapper GetContingencies() const; + + mutable std::shared_ptr> m_reachable; + void FindReachableInfosets(GameNode p_node) const; + std::shared_ptr> GetReachableInfosets() const; }; } // end namespace Gambit From a78b64f573f9bb06456ccfde17b4515c3e1d24a5 Mon Sep 17 00:00:00 2001 From: StephenPasteris Date: Wed, 12 Nov 2025 12:01:49 +0000 Subject: [PATCH 06/29] reset m_reachable to nullptr during addition or removal of actions --- src/games/behavspt.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/games/behavspt.cc b/src/games/behavspt.cc index a18b978be..261458ce2 100644 --- a/src/games/behavspt.cc +++ b/src/games/behavspt.cc @@ -66,6 +66,7 @@ size_t BehaviorSupportProfile::BehaviorProfileLength() const void BehaviorSupportProfile::AddAction(const GameAction &p_action) { + m_reachable = nullptr; auto &support = m_actions.at(p_action->GetInfoset()); auto pos = std::find_if(support.begin(), support.end(), [p_action](const GameAction &a) { return a->GetNumber() >= p_action->GetNumber(); @@ -81,6 +82,7 @@ void BehaviorSupportProfile::AddAction(const GameAction &p_action) bool BehaviorSupportProfile::RemoveAction(const GameAction &p_action) { + m_reachable = nullptr; auto &support = m_actions.at(p_action->GetInfoset()); auto pos = std::find(support.begin(), support.end(), p_action); if (pos != support.end()) { From f5dbc77ea1ee8426cd7a64711f68b5f856dabde9 Mon Sep 17 00:00:00 2001 From: StephenPasteris Date: Wed, 12 Nov 2025 13:04:46 +0000 Subject: [PATCH 07/29] fixed issue with FindReachableInfosets --- src/games/behavspt.cc | 14 +++++++++++--- src/solvers/enumpoly/efgpoly.cc | 7 ++++--- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/games/behavspt.cc b/src/games/behavspt.cc index 261458ce2..2843123dc 100644 --- a/src/games/behavspt.cc +++ b/src/games/behavspt.cc @@ -321,9 +321,17 @@ void BehaviorSupportProfile::FindReachableInfosets(GameNode p_node) const { if (!p_node->IsTerminal()) { auto infoset = p_node->GetInfoset(); - m_reachable->insert(infoset); - for (auto action : GetActions(infoset)) { - FindReachableInfosets(p_node->GetChild(action)); + + if (p_node->GetPlayer()->IsChance()) { + for (auto action : infoset->GetActions()) { + FindReachableInfosets(p_node->GetChild(action)); + } + } + else { + m_reachable->insert(infoset); + for (auto action : GetActions(infoset)) { + FindReachableInfosets(p_node->GetChild(action)); + } } } } diff --git a/src/solvers/enumpoly/efgpoly.cc b/src/solvers/enumpoly/efgpoly.cc index a6775ca82..de0534dd5 100644 --- a/src/solvers/enumpoly/efgpoly.cc +++ b/src/solvers/enumpoly/efgpoly.cc @@ -80,9 +80,10 @@ Polynomial BuildSequenceVariable(ProblemData &p_data, const GameSequence } ProblemData::ProblemData(const BehaviorSupportProfile &p_support) - : m_support(p_support), space(std::make_shared(m_support.GetSequences().size() - - m_support.GetInfosets().size() - - m_support.GetPlayers().size())) + : m_support(p_support), + space(std::make_shared(m_support.GetSequences().size() - + m_support.GetReachableInfosets()->size() - + m_support.GetPlayers().size())) { for (auto sequence : m_support.GetSequences()) { if (sequence->action && From c3172d39bd73135288cd6735ec18530ca0a56690 Mon Sep 17 00:00:00 2001 From: StephenPasteris Date: Wed, 12 Nov 2025 13:58:01 +0000 Subject: [PATCH 08/29] changed *m_reachable from set to map --- src/games/behavspt.cc | 12 +++++++++--- src/games/behavspt.h | 4 ++-- src/solvers/enumpoly/efgpoly.cc | 7 +++---- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/games/behavspt.cc b/src/games/behavspt.cc index 2843123dc..9e8282e62 100644 --- a/src/games/behavspt.cc +++ b/src/games/behavspt.cc @@ -328,7 +328,7 @@ void BehaviorSupportProfile::FindReachableInfosets(GameNode p_node) const } } else { - m_reachable->insert(infoset); + (*m_reachable)[infoset] = true; for (auto action : GetActions(infoset)) { FindReachableInfosets(p_node->GetChild(action)); } @@ -336,10 +336,16 @@ void BehaviorSupportProfile::FindReachableInfosets(GameNode p_node) const } } -std::shared_ptr> BehaviorSupportProfile::GetReachableInfosets() const +std::shared_ptr> BehaviorSupportProfile::GetReachableInfosets() const { if (!m_reachable) { - m_reachable = std::make_shared>(); + m_reachable = std::make_shared>(); + for (size_t pl = 0; pl <= GetGame()->NumPlayers(); pl++) { + const GamePlayer player = (pl == 0) ? GetGame()->GetChance() : GetGame()->GetPlayer(pl); + for (const auto &infoset : player->GetInfosets()) { + (*m_reachable)[infoset] = false; + } + } FindReachableInfosets(GetGame()->GetRoot()); } return m_reachable; diff --git a/src/games/behavspt.h b/src/games/behavspt.h index 2d083ae49..f07a0c384 100644 --- a/src/games/behavspt.h +++ b/src/games/behavspt.h @@ -161,9 +161,9 @@ class BehaviorSupportProfile { InfosetsWrapper GetInfosets() const; ContingenciesWrapper GetContingencies() const; - mutable std::shared_ptr> m_reachable; + mutable std::shared_ptr> m_reachable; void FindReachableInfosets(GameNode p_node) const; - std::shared_ptr> GetReachableInfosets() const; + std::shared_ptr> GetReachableInfosets() const; }; } // end namespace Gambit diff --git a/src/solvers/enumpoly/efgpoly.cc b/src/solvers/enumpoly/efgpoly.cc index de0534dd5..a6775ca82 100644 --- a/src/solvers/enumpoly/efgpoly.cc +++ b/src/solvers/enumpoly/efgpoly.cc @@ -80,10 +80,9 @@ Polynomial BuildSequenceVariable(ProblemData &p_data, const GameSequence } ProblemData::ProblemData(const BehaviorSupportProfile &p_support) - : m_support(p_support), - space(std::make_shared(m_support.GetSequences().size() - - m_support.GetReachableInfosets()->size() - - m_support.GetPlayers().size())) + : m_support(p_support), space(std::make_shared(m_support.GetSequences().size() - + m_support.GetInfosets().size() - + m_support.GetPlayers().size())) { for (auto sequence : m_support.GetSequences()) { if (sequence->action && From be771f5d32e0f7ff68bc8a837b488f8def77c3da Mon Sep 17 00:00:00 2001 From: StephenPasteris Date: Wed, 12 Nov 2025 14:20:22 +0000 Subject: [PATCH 09/29] Made Infosets class --- src/games/behavspt.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/games/behavspt.h b/src/games/behavspt.h index f07a0c384..2480b6af9 100644 --- a/src/games/behavspt.h +++ b/src/games/behavspt.h @@ -147,6 +147,26 @@ class BehaviorSupportProfile { BehaviorSupportProfile Undominated(bool p_strict) const; //@} + class Infosets { + private: + const BehaviorSupportProfile *m_support; + + public: + Infosets(const BehaviorSupportProfile *p_support) : m_support(p_support) {} + + size_t size() const + { + auto reachable_infosets = m_support->GetReachableInfosets(); + size_t count = 0; + for (auto [key, value] : *reachable_infosets) { + if (value) { + ++count; + } + } + return count; + } + }; + mutable std::shared_ptr m_sequenceForm; std::shared_ptr GetSequenceForm() const; SequencesWrapper GetSequences() const; From 2354b97a4f0d116862fce050119bcd1847a3f1f0 Mon Sep 17 00:00:00 2001 From: StephenPasteris Date: Wed, 12 Nov 2025 14:36:07 +0000 Subject: [PATCH 10/29] Removed InfosetsWrapper --- src/games/behavspt.cc | 5 ----- src/games/behavspt.h | 2 +- src/games/gameseq.h | 10 ---------- 3 files changed, 1 insertion(+), 16 deletions(-) diff --git a/src/games/behavspt.cc b/src/games/behavspt.cc index 9e8282e62..7d6e5c1cf 100644 --- a/src/games/behavspt.cc +++ b/src/games/behavspt.cc @@ -303,11 +303,6 @@ MixedBehaviorProfile BehaviorSupportProfile::ToMixedBehaviorProfile( return GetSequenceForm()->ToMixedBehaviorProfile(p_profile); } -InfosetsWrapper BehaviorSupportProfile::GetInfosets() const -{ - return InfosetsWrapper(GetSequenceForm()->GetInfosets()); -} - ContingenciesWrapper BehaviorSupportProfile::GetContingencies() const { return ContingenciesWrapper(GetSequenceForm()->GetContingencies()); diff --git a/src/games/behavspt.h b/src/games/behavspt.h index 2480b6af9..234818762 100644 --- a/src/games/behavspt.h +++ b/src/games/behavspt.h @@ -178,7 +178,7 @@ class BehaviorSupportProfile { GameRep::Players GetPlayers() const { return GetGame()->GetPlayers(); } MixedBehaviorProfile ToMixedBehaviorProfile(const std::map, double> &) const; - InfosetsWrapper GetInfosets() const; + Infosets GetInfosets() const { return Infosets(this); }; ContingenciesWrapper GetContingencies() const; mutable std::shared_ptr> m_reachable; diff --git a/src/games/gameseq.h b/src/games/gameseq.h index d5718599f..94d31e482 100644 --- a/src/games/gameseq.h +++ b/src/games/gameseq.h @@ -324,16 +324,6 @@ class PlayerSequencesWrapper { GameSequenceForm::PlayerSequences m_sequences; }; -class InfosetsWrapper { -public: - explicit InfosetsWrapper(const GameSequenceForm::Infosets &infosets) : m_infosets(infosets) {} - - std::size_t size() const { return m_infosets.size(); } - -private: - GameSequenceForm::Infosets m_infosets; -}; - class ContingenciesWrapper { public: explicit ContingenciesWrapper(const GameSequenceForm::Contingencies &contingencies) From d71a2a6488a0a3dbe42161a1ba226c8472486423 Mon Sep 17 00:00:00 2001 From: StephenPasteris Date: Wed, 12 Nov 2025 20:55:13 +0000 Subject: [PATCH 11/29] Added PlayerSequences to BehaviorSupportProfile --- Makefile.am | 1 + src/games/behavspt.cc | 6 ++++-- src/games/behavspt.h | 4 +++- src/games/behavsptseqform.h | 38 +++++++++++++++++++++++++++++++++ src/games/gameseq.h | 3 +++ src/solvers/enumpoly/efgpoly.cc | 1 + 6 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 src/games/behavsptseqform.h diff --git a/Makefile.am b/Makefile.am index 4325353ef..1eb4a3ec8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -300,6 +300,7 @@ game_SOURCES = \ src/games/gametree.h \ src/games/behavspt.cc \ src/games/behavspt.h \ + src/games/behavsptseqform.h \ src/games/behavpure.cc \ src/games/behavpure.h \ src/games/behavmixed.cc \ diff --git a/src/games/behavspt.cc b/src/games/behavspt.cc index 7d6e5c1cf..623131d0a 100644 --- a/src/games/behavspt.cc +++ b/src/games/behavspt.cc @@ -22,6 +22,7 @@ #include "gambit.h" #include "gameseq.h" +#include "behavsptseqform.h" namespace Gambit { @@ -279,9 +280,10 @@ SequencesWrapper BehaviorSupportProfile::GetSequences() const return SequencesWrapper(GetSequenceForm()->GetSequences()); } -PlayerSequencesWrapper BehaviorSupportProfile::GetSequences(GamePlayer &p_player) const +BehaviorSupportProfile::PlayerSequences +BehaviorSupportProfile::GetSequences(GamePlayer &p_player) const { - return PlayerSequencesWrapper(GetSequenceForm()->GetSequences(p_player)); + return PlayerSequences(GetSequenceForm(), p_player); } int BehaviorSupportProfile::GetConstraintEntry(const GameInfoset &p_infoset, diff --git a/src/games/behavspt.h b/src/games/behavspt.h index 234818762..1638a7475 100644 --- a/src/games/behavspt.h +++ b/src/games/behavspt.h @@ -167,10 +167,12 @@ class BehaviorSupportProfile { } }; + class PlayerSequences; + mutable std::shared_ptr m_sequenceForm; std::shared_ptr GetSequenceForm() const; SequencesWrapper GetSequences() const; - PlayerSequencesWrapper GetSequences(GamePlayer &p_player) const; + PlayerSequences GetSequences(GamePlayer &p_player) const; int GetConstraintEntry(const GameInfoset &p_infoset, const GameAction &p_action) const; const Rational & GetPayoff(const std::map> &p_profile, diff --git a/src/games/behavsptseqform.h b/src/games/behavsptseqform.h new file mode 100644 index 000000000..e3161e02b --- /dev/null +++ b/src/games/behavsptseqform.h @@ -0,0 +1,38 @@ +// +// Created by Stephen Pasteris on 12/11/2025. +// + +#ifndef GAMBIT_BEHAVSPT_SEQ_FORM_H +#define GAMBIT_BEHAVSPT_SEQ_FORM_H + +#include "gambit.h" +#include "gameseq.h" + +namespace Gambit { + +class BehaviorSupportProfile::PlayerSequences { +private: + std::shared_ptr m_sfg; + GamePlayer m_player; + +public: + PlayerSequences(const std::shared_ptr p_sfg, const GamePlayer &p_player) + : m_sfg(p_sfg), m_player(p_player) + { + } + + size_t size() const { return m_sfg->m_sequences.at(m_player).size(); } + + std::vector::const_iterator begin() const + { + return m_sfg->m_sequences.at(m_player).begin(); + } + std::vector::const_iterator end() const + { + return m_sfg->m_sequences.at(m_player).end(); + } +}; + +} // namespace Gambit + +#endif // GAMBIT_BEHAVSPT_SEQ_FORM_H diff --git a/src/games/gameseq.h b/src/games/gameseq.h index 94d31e482..bdba7b216 100644 --- a/src/games/gameseq.h +++ b/src/games/gameseq.h @@ -56,6 +56,9 @@ class GameSequenceRep { using GameSequence = std::shared_ptr; class GameSequenceForm { + + friend class BehaviorSupportProfile; + private: BehaviorSupportProfile m_support; std::map> m_sequences; diff --git a/src/solvers/enumpoly/efgpoly.cc b/src/solvers/enumpoly/efgpoly.cc index a6775ca82..00537d700 100644 --- a/src/solvers/enumpoly/efgpoly.cc +++ b/src/solvers/enumpoly/efgpoly.cc @@ -26,6 +26,7 @@ #include "polysystem.h" #include "polysolver.h" #include "behavextend.h" +#include "games/behavsptseqform.h" using namespace Gambit; using namespace Gambit::Nash; From 16821e95edc1c749b755bbfa7787615d03af17ab Mon Sep 17 00:00:00 2001 From: StephenPasteris Date: Thu, 13 Nov 2025 08:42:06 +0000 Subject: [PATCH 12/29] Added Sequences to BehaviorSupportProfile --- src/games/behavspt.cc | 4 +-- src/games/behavspt.h | 3 +- src/games/behavsptseqform.h | 70 +++++++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+), 3 deletions(-) diff --git a/src/games/behavspt.cc b/src/games/behavspt.cc index 623131d0a..b50ee66ac 100644 --- a/src/games/behavspt.cc +++ b/src/games/behavspt.cc @@ -275,9 +275,9 @@ std::shared_ptr BehaviorSupportProfile::GetSequenceForm() cons return m_sequenceForm; } -SequencesWrapper BehaviorSupportProfile::GetSequences() const +BehaviorSupportProfile::Sequences BehaviorSupportProfile::GetSequences() const { - return SequencesWrapper(GetSequenceForm()->GetSequences()); + return Sequences(GetSequenceForm()); } BehaviorSupportProfile::PlayerSequences diff --git a/src/games/behavspt.h b/src/games/behavspt.h index 1638a7475..5cb9c6522 100644 --- a/src/games/behavspt.h +++ b/src/games/behavspt.h @@ -167,11 +167,12 @@ class BehaviorSupportProfile { } }; + class Sequences; class PlayerSequences; mutable std::shared_ptr m_sequenceForm; std::shared_ptr GetSequenceForm() const; - SequencesWrapper GetSequences() const; + Sequences GetSequences() const; PlayerSequences GetSequences(GamePlayer &p_player) const; int GetConstraintEntry(const GameInfoset &p_infoset, const GameAction &p_action) const; const Rational & diff --git a/src/games/behavsptseqform.h b/src/games/behavsptseqform.h index e3161e02b..c86595cdf 100644 --- a/src/games/behavsptseqform.h +++ b/src/games/behavsptseqform.h @@ -10,6 +10,76 @@ namespace Gambit { +class BehaviorSupportProfile::Sequences { +private: + const std::shared_ptr m_sfg; + +public: + class iterator { + private: + const std::shared_ptr m_sfg; + std::map>::const_iterator m_currentPlayer; + std::vector::const_iterator m_currentSequence; + + public: + iterator(const std::shared_ptr p_sfg, bool p_end) : m_sfg(p_sfg) + { + if (p_end) { + m_currentPlayer = m_sfg->m_sequences.cend(); + } + else { + m_currentPlayer = m_sfg->m_sequences.cbegin(); + m_currentSequence = m_currentPlayer->second.cbegin(); + } + } + + GameSequence operator*() const { return *m_currentSequence; } + GameSequence operator->() const { return *m_currentSequence; } + + iterator &operator++() + { + if (m_currentPlayer == m_sfg->m_sequences.cend()) { + return *this; + } + m_currentSequence++; + if (m_currentSequence != m_currentPlayer->second.cend()) { + return *this; + } + m_currentPlayer++; + if (m_currentPlayer != m_sfg->m_sequences.cend()) { + m_currentSequence = m_currentPlayer->second.cbegin(); + } + return *this; + } + + bool operator==(const iterator &it) const + { + if (m_sfg != it.m_sfg || m_currentPlayer != it.m_currentPlayer) { + return false; + } + if (m_currentPlayer == m_sfg->m_sequences.end()) { + return true; + } + return (m_currentSequence == it.m_currentSequence); + } + bool operator!=(const iterator &it) const { return !(*this == it); } + }; + + Sequences(const std::shared_ptr p_sfg) : m_sfg(p_sfg) {} + + size_t size() const + { + return std::accumulate( + m_sfg->m_sequences.cbegin(), m_sfg->m_sequences.cend(), 0, + [](int acc, const std::pair> &seq) { + return acc + seq.second.size(); + }); + } + + iterator begin() const { return {m_sfg, false}; } + iterator end() const { return {m_sfg, true}; } +}; + class BehaviorSupportProfile::PlayerSequences { private: std::shared_ptr m_sfg; From ee0441b379597a6ab1d50dd92011b212c71b78fe Mon Sep 17 00:00:00 2001 From: StephenPasteris Date: Thu, 13 Nov 2025 09:02:12 +0000 Subject: [PATCH 13/29] Added Contingencies to BehaviorSupportProfile --- src/games/behavspt.cc | 4 +-- src/games/behavspt.h | 3 +- src/games/behavsptseqform.h | 66 +++++++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 3 deletions(-) diff --git a/src/games/behavspt.cc b/src/games/behavspt.cc index b50ee66ac..47284f8cd 100644 --- a/src/games/behavspt.cc +++ b/src/games/behavspt.cc @@ -305,9 +305,9 @@ MixedBehaviorProfile BehaviorSupportProfile::ToMixedBehaviorProfile( return GetSequenceForm()->ToMixedBehaviorProfile(p_profile); } -ContingenciesWrapper BehaviorSupportProfile::GetContingencies() const +BehaviorSupportProfile::Contingencies BehaviorSupportProfile::GetContingencies() const { - return ContingenciesWrapper(GetSequenceForm()->GetContingencies()); + return Contingencies(GetSequenceForm()); } //======================================================================== diff --git a/src/games/behavspt.h b/src/games/behavspt.h index 5cb9c6522..a2b6ac7d8 100644 --- a/src/games/behavspt.h +++ b/src/games/behavspt.h @@ -169,6 +169,7 @@ class BehaviorSupportProfile { class Sequences; class PlayerSequences; + class Contingencies; mutable std::shared_ptr m_sequenceForm; std::shared_ptr GetSequenceForm() const; @@ -182,7 +183,7 @@ class BehaviorSupportProfile { MixedBehaviorProfile ToMixedBehaviorProfile(const std::map, double> &) const; Infosets GetInfosets() const { return Infosets(this); }; - ContingenciesWrapper GetContingencies() const; + Contingencies GetContingencies() const; mutable std::shared_ptr> m_reachable; void FindReachableInfosets(GameNode p_node) const; diff --git a/src/games/behavsptseqform.h b/src/games/behavsptseqform.h index c86595cdf..9c04e20d7 100644 --- a/src/games/behavsptseqform.h +++ b/src/games/behavsptseqform.h @@ -103,6 +103,72 @@ class BehaviorSupportProfile::PlayerSequences { } }; +class BehaviorSupportProfile::Contingencies { +private: + const std::shared_ptr m_sfg; + +public: + Contingencies(const std::shared_ptr p_sfg) : m_sfg(p_sfg) {} + + class iterator { + private: + const std::shared_ptr m_sfg; + bool m_end{false}; + std::map m_indices; + + public: + using iterator_category = std::input_iterator_tag; + + iterator(const std::shared_ptr p_sfg, bool p_end = false) + : m_sfg(p_sfg), m_end(p_end) + { + for (auto [player, sequences] : m_sfg->m_sequences) { + m_indices[player] = 0; + } + } + + std::map operator*() const + { + std::map ret; + for (auto [player, index] : m_indices) { + ret[player] = m_sfg->m_sequences.at(player)[index]; + } + return ret; + } + + std::map operator->() const + { + std::map ret; + for (auto [player, index] : m_indices) { + ret[player] = m_sfg->m_sequences.at(player)[index]; + } + return ret; + } + + iterator &operator++() + { + for (auto [player, index] : m_indices) { + if (index < m_sfg->m_sequences.at(player).size() - 1) { + m_indices[player]++; + return *this; + } + m_indices[player] = 0; + } + m_end = true; + return *this; + } + + bool operator==(const iterator &it) const + { + return (m_end == it.m_end && m_sfg == it.m_sfg && m_indices == it.m_indices); + } + bool operator!=(const iterator &it) const { return !(*this == it); } + }; + + iterator begin() { return {m_sfg}; } + iterator end() { return {m_sfg, true}; } +}; + } // namespace Gambit #endif // GAMBIT_BEHAVSPT_SEQ_FORM_H From 574664eb893aeaacaeb8a3a61c64ec7286d712e4 Mon Sep 17 00:00:00 2001 From: StephenPasteris Date: Thu, 13 Nov 2025 09:09:56 +0000 Subject: [PATCH 14/29] Removed wrapper classes --- src/games/gameseq.h | 45 --------------------------------------------- 1 file changed, 45 deletions(-) diff --git a/src/games/gameseq.h b/src/games/gameseq.h index bdba7b216..cee33a5b2 100644 --- a/src/games/gameseq.h +++ b/src/games/gameseq.h @@ -296,51 +296,6 @@ class GameSequenceForm { ToMixedBehaviorProfile(const std::map &) const; }; -class SequencesWrapper { -public: - explicit SequencesWrapper(const GameSequenceForm::Sequences &sequences) : m_sequences(sequences) - { - } - - auto begin() const { return m_sequences.begin(); } - auto end() const { return m_sequences.end(); } - - std::size_t size() const { return m_sequences.size(); } - -private: - GameSequenceForm::Sequences m_sequences; -}; - -class PlayerSequencesWrapper { -public: - explicit PlayerSequencesWrapper(const GameSequenceForm::PlayerSequences &sequences) - : m_sequences(sequences) - { - } - - auto begin() const { return m_sequences.begin(); } - auto end() const { return m_sequences.end(); } - - std::size_t size() const { return m_sequences.size(); } - -private: - GameSequenceForm::PlayerSequences m_sequences; -}; - -class ContingenciesWrapper { -public: - explicit ContingenciesWrapper(const GameSequenceForm::Contingencies &contingencies) - : m_contingencies(contingencies) - { - } - - auto begin() { return m_contingencies.begin(); } - auto end() { return m_contingencies.end(); } - -private: - GameSequenceForm::Contingencies m_contingencies; -}; - } // end namespace Gambit #endif // GAMESEQ_H From a1b343e8096e9aadd33a353e69ec2d22ea217799 Mon Sep 17 00:00:00 2001 From: StephenPasteris Date: Thu, 13 Nov 2025 13:40:18 +0000 Subject: [PATCH 15/29] Moved ToMixedBehaviorProfile into BehaviorSupportProfile --- src/games/behavspt.cc | 23 ++++++++++++++++++----- src/games/gameseq.cc | 19 ------------------- src/games/gameseq.h | 3 --- 3 files changed, 18 insertions(+), 27 deletions(-) diff --git a/src/games/behavspt.cc b/src/games/behavspt.cc index 47284f8cd..6c26b921a 100644 --- a/src/games/behavspt.cc +++ b/src/games/behavspt.cc @@ -299,15 +299,28 @@ const Rational &BehaviorSupportProfile::GetPayoff( return GetSequenceForm()->GetPayoff(p_profile, p_player); } -MixedBehaviorProfile BehaviorSupportProfile::ToMixedBehaviorProfile( - const std::map, double> &p_profile) const +BehaviorSupportProfile::Contingencies BehaviorSupportProfile::GetContingencies() const { - return GetSequenceForm()->ToMixedBehaviorProfile(p_profile); + return Contingencies(GetSequenceForm()); } -BehaviorSupportProfile::Contingencies BehaviorSupportProfile::GetContingencies() const +MixedBehaviorProfile +BehaviorSupportProfile::ToMixedBehaviorProfile(const std::map &x) const { - return Contingencies(GetSequenceForm()); + MixedBehaviorProfile b(*this); + for (auto sequence : GetSequences()) { + if (sequence->action == nullptr) { + continue; + } + const double parent_prob = x.at(sequence->parent.lock()); + if (parent_prob > 0) { + b[sequence->action] = x.at(sequence) / parent_prob; + } + else { + b[sequence->action] = 0; + } + } + return b; } //======================================================================== diff --git a/src/games/gameseq.cc b/src/games/gameseq.cc index 1205c459f..b8df35c50 100644 --- a/src/games/gameseq.cc +++ b/src/games/gameseq.cc @@ -111,23 +111,4 @@ void GameSequenceForm::FillTableau() FillTableau(m_support.GetGame()->GetRoot(), Rational(1), currentSequence); } -MixedBehaviorProfile -GameSequenceForm::ToMixedBehaviorProfile(const std::map &x) const -{ - MixedBehaviorProfile b(m_support); - for (auto sequence : GetSequences()) { - if (sequence->action == nullptr) { - continue; - } - const double parent_prob = x.at(sequence->parent.lock()); - if (parent_prob > 0) { - b[sequence->action] = x.at(sequence) / parent_prob; - } - else { - b[sequence->action] = 0; - } - } - return b; -} - } // end namespace Gambit diff --git a/src/games/gameseq.h b/src/games/gameseq.h index cee33a5b2..544943f22 100644 --- a/src/games/gameseq.h +++ b/src/games/gameseq.h @@ -291,9 +291,6 @@ class GameSequenceForm { return 0; } } - - MixedBehaviorProfile - ToMixedBehaviorProfile(const std::map &) const; }; } // end namespace Gambit From 448762f4981ed188b993c1876c4012dcd2cd5a99 Mon Sep 17 00:00:00 2001 From: StephenPasteris Date: Thu, 13 Nov 2025 13:45:37 +0000 Subject: [PATCH 16/29] Removed nested classes from GameSequenceForm --- src/games/gameseq.h | 166 -------------------------------------------- 1 file changed, 166 deletions(-) diff --git a/src/games/gameseq.h b/src/games/gameseq.h index 544943f22..5a0b97c46 100644 --- a/src/games/gameseq.h +++ b/src/games/gameseq.h @@ -98,164 +98,6 @@ class GameSequenceForm { size_t size() const { return m_sfg->m_infosets.size(); } }; - class Sequences { - private: - const GameSequenceForm *m_sfg; - - public: - class iterator { - private: - const GameSequenceForm *m_sfg; - std::map>::const_iterator m_currentPlayer; - std::vector::const_iterator m_currentSequence; - - public: - iterator(const GameSequenceForm *p_sfg, bool p_end) : m_sfg(p_sfg) - { - if (p_end) { - m_currentPlayer = m_sfg->m_sequences.cend(); - } - else { - m_currentPlayer = m_sfg->m_sequences.cbegin(); - m_currentSequence = m_currentPlayer->second.cbegin(); - } - } - - GameSequence operator*() const { return *m_currentSequence; } - GameSequence operator->() const { return *m_currentSequence; } - - iterator &operator++() - { - if (m_currentPlayer == m_sfg->m_sequences.cend()) { - return *this; - } - m_currentSequence++; - if (m_currentSequence != m_currentPlayer->second.cend()) { - return *this; - } - m_currentPlayer++; - if (m_currentPlayer != m_sfg->m_sequences.cend()) { - m_currentSequence = m_currentPlayer->second.cbegin(); - } - return *this; - } - - bool operator==(const iterator &it) const - { - if (m_sfg != it.m_sfg || m_currentPlayer != it.m_currentPlayer) { - return false; - } - if (m_currentPlayer == m_sfg->m_sequences.end()) { - return true; - } - return (m_currentSequence == it.m_currentSequence); - } - bool operator!=(const iterator &it) const { return !(*this == it); } - }; - - Sequences(const GameSequenceForm *p_sfg) : m_sfg(p_sfg) {} - - size_t size() const - { - return std::accumulate( - m_sfg->m_sequences.cbegin(), m_sfg->m_sequences.cend(), 0, - [](int acc, const std::pair> &seq) { - return acc + seq.second.size(); - }); - } - - iterator begin() const { return {m_sfg, false}; } - iterator end() const { return {m_sfg, true}; } - }; - - class PlayerSequences { - private: - const GameSequenceForm *m_sfg; - GamePlayer m_player; - - public: - PlayerSequences(const GameSequenceForm *p_sfg, const GamePlayer &p_player) - : m_sfg(p_sfg), m_player(p_player) - { - } - - size_t size() const { return m_sfg->m_sequences.at(m_player).size(); } - - std::vector::const_iterator begin() const - { - return m_sfg->m_sequences.at(m_player).begin(); - } - std::vector::const_iterator end() const - { - return m_sfg->m_sequences.at(m_player).end(); - } - }; - - class Contingencies { - private: - const GameSequenceForm *m_sfg; - - public: - Contingencies(const GameSequenceForm *p_sfg) : m_sfg(p_sfg) {} - - class iterator { - private: - const GameSequenceForm *m_sfg; - bool m_end{false}; - std::map m_indices; - - public: - using iterator_category = std::input_iterator_tag; - - iterator(const GameSequenceForm *p_sfg, bool p_end = false) : m_sfg(p_sfg), m_end(p_end) - { - for (auto [player, sequences] : m_sfg->m_sequences) { - m_indices[player] = 0; - } - } - - std::map operator*() const - { - std::map ret; - for (auto [player, index] : m_indices) { - ret[player] = m_sfg->m_sequences.at(player)[index]; - } - return ret; - } - - std::map operator->() const - { - std::map ret; - for (auto [player, index] : m_indices) { - ret[player] = m_sfg->m_sequences.at(player)[index]; - } - return ret; - } - - iterator &operator++() - { - for (auto [player, index] : m_indices) { - if (index < m_sfg->m_sequences.at(player).size() - 1) { - m_indices[player]++; - return *this; - } - m_indices[player] = 0; - } - m_end = true; - return *this; - } - - bool operator==(const iterator &it) const - { - return (m_end == it.m_end && m_sfg == it.m_sfg && m_indices == it.m_indices); - } - bool operator!=(const iterator &it) const { return !(*this == it); } - }; - - iterator begin() { return {m_sfg}; } - iterator end() { return {m_sfg, true}; } - }; - explicit GameSequenceForm(const BehaviorSupportProfile &p_support) : m_support(p_support) { BuildSequences(); @@ -266,16 +108,8 @@ class GameSequenceForm { const BehaviorSupportProfile &GetSupport() const { return m_support; } - Sequences GetSequences() const { return {this}; } - - PlayerSequences GetSequences(const GamePlayer &p_player) const { return {this, p_player}; } - - Contingencies GetContingencies() const { return {this}; } - GameRep::Players GetPlayers() const { return m_support.GetGame()->GetPlayers(); } - Infosets GetInfosets() const { return {this}; } - const Rational &GetPayoff(const std::map &p_profile, const GamePlayer &p_player) const { From 65a4519b5fb2ae27b38f65bbe19b77a790c45efd Mon Sep 17 00:00:00 2001 From: StephenPasteris Date: Fri, 14 Nov 2025 10:18:47 +0000 Subject: [PATCH 17/29] Renamed m_reachable m_reachableInfosets --- src/games/behavspt.cc | 14 +++++++------- src/games/behavspt.h | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/games/behavspt.cc b/src/games/behavspt.cc index 6c26b921a..9fb3ee3cd 100644 --- a/src/games/behavspt.cc +++ b/src/games/behavspt.cc @@ -67,7 +67,7 @@ size_t BehaviorSupportProfile::BehaviorProfileLength() const void BehaviorSupportProfile::AddAction(const GameAction &p_action) { - m_reachable = nullptr; + m_reachableInfosets = nullptr; auto &support = m_actions.at(p_action->GetInfoset()); auto pos = std::find_if(support.begin(), support.end(), [p_action](const GameAction &a) { return a->GetNumber() >= p_action->GetNumber(); @@ -83,7 +83,7 @@ void BehaviorSupportProfile::AddAction(const GameAction &p_action) bool BehaviorSupportProfile::RemoveAction(const GameAction &p_action) { - m_reachable = nullptr; + m_reachableInfosets = nullptr; auto &support = m_actions.at(p_action->GetInfoset()); auto pos = std::find(support.begin(), support.end(), p_action); if (pos != support.end()) { @@ -338,7 +338,7 @@ void BehaviorSupportProfile::FindReachableInfosets(GameNode p_node) const } } else { - (*m_reachable)[infoset] = true; + (*m_reachableInfosets)[infoset] = true; for (auto action : GetActions(infoset)) { FindReachableInfosets(p_node->GetChild(action)); } @@ -348,17 +348,17 @@ void BehaviorSupportProfile::FindReachableInfosets(GameNode p_node) const std::shared_ptr> BehaviorSupportProfile::GetReachableInfosets() const { - if (!m_reachable) { - m_reachable = std::make_shared>(); + if (!m_reachableInfosets) { + m_reachableInfosets = std::make_shared>(); for (size_t pl = 0; pl <= GetGame()->NumPlayers(); pl++) { const GamePlayer player = (pl == 0) ? GetGame()->GetChance() : GetGame()->GetPlayer(pl); for (const auto &infoset : player->GetInfosets()) { - (*m_reachable)[infoset] = false; + (*m_reachableInfosets)[infoset] = false; } } FindReachableInfosets(GetGame()->GetRoot()); } - return m_reachable; + return m_reachableInfosets; } } // end namespace Gambit diff --git a/src/games/behavspt.h b/src/games/behavspt.h index a2b6ac7d8..ae394b940 100644 --- a/src/games/behavspt.h +++ b/src/games/behavspt.h @@ -185,7 +185,7 @@ class BehaviorSupportProfile { Infosets GetInfosets() const { return Infosets(this); }; Contingencies GetContingencies() const; - mutable std::shared_ptr> m_reachable; + mutable std::shared_ptr> m_reachableInfosets; void FindReachableInfosets(GameNode p_node) const; std::shared_ptr> GetReachableInfosets() const; }; From c28a6aafde10335e49d5c0a33f1349a77c07285a Mon Sep 17 00:00:00 2001 From: StephenPasteris Date: Fri, 14 Nov 2025 11:06:50 +0000 Subject: [PATCH 18/29] Made m_reachableInfosets consistent with m_infosetReachable --- src/games/behavspt.cc | 3 +-- src/games/behavspt.h | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/games/behavspt.cc b/src/games/behavspt.cc index 9fb3ee3cd..4265a079c 100644 --- a/src/games/behavspt.cc +++ b/src/games/behavspt.cc @@ -331,14 +331,13 @@ void BehaviorSupportProfile::FindReachableInfosets(GameNode p_node) const { if (!p_node->IsTerminal()) { auto infoset = p_node->GetInfoset(); - + (*m_reachableInfosets)[infoset] = true; if (p_node->GetPlayer()->IsChance()) { for (auto action : infoset->GetActions()) { FindReachableInfosets(p_node->GetChild(action)); } } else { - (*m_reachableInfosets)[infoset] = true; for (auto action : GetActions(infoset)) { FindReachableInfosets(p_node->GetChild(action)); } diff --git a/src/games/behavspt.h b/src/games/behavspt.h index ae394b940..aba74e876 100644 --- a/src/games/behavspt.h +++ b/src/games/behavspt.h @@ -158,8 +158,8 @@ class BehaviorSupportProfile { { auto reachable_infosets = m_support->GetReachableInfosets(); size_t count = 0; - for (auto [key, value] : *reachable_infosets) { - if (value) { + for (auto [infoset, is_reachable] : *reachable_infosets) { + if (is_reachable && !infoset->GetPlayer()->IsChance()) { ++count; } } From 6a1b586fcc6a9edc897ab53cdfd68e2a1fddc9f9 Mon Sep 17 00:00:00 2001 From: StephenPasteris Date: Fri, 14 Nov 2025 11:59:03 +0000 Subject: [PATCH 19/29] Used brace initialisation --- src/games/behavspt.cc | 6 +++--- src/games/behavspt.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/games/behavspt.cc b/src/games/behavspt.cc index 4265a079c..0e40703de 100644 --- a/src/games/behavspt.cc +++ b/src/games/behavspt.cc @@ -277,13 +277,13 @@ std::shared_ptr BehaviorSupportProfile::GetSequenceForm() cons BehaviorSupportProfile::Sequences BehaviorSupportProfile::GetSequences() const { - return Sequences(GetSequenceForm()); + return {GetSequenceForm()}; } BehaviorSupportProfile::PlayerSequences BehaviorSupportProfile::GetSequences(GamePlayer &p_player) const { - return PlayerSequences(GetSequenceForm(), p_player); + return {GetSequenceForm(), p_player}; } int BehaviorSupportProfile::GetConstraintEntry(const GameInfoset &p_infoset, @@ -301,7 +301,7 @@ const Rational &BehaviorSupportProfile::GetPayoff( BehaviorSupportProfile::Contingencies BehaviorSupportProfile::GetContingencies() const { - return Contingencies(GetSequenceForm()); + return {GetSequenceForm()}; } MixedBehaviorProfile diff --git a/src/games/behavspt.h b/src/games/behavspt.h index aba74e876..3f8783a37 100644 --- a/src/games/behavspt.h +++ b/src/games/behavspt.h @@ -182,7 +182,7 @@ class BehaviorSupportProfile { GameRep::Players GetPlayers() const { return GetGame()->GetPlayers(); } MixedBehaviorProfile ToMixedBehaviorProfile(const std::map, double> &) const; - Infosets GetInfosets() const { return Infosets(this); }; + Infosets GetInfosets() const { return {this}; }; Contingencies GetContingencies() const; mutable std::shared_ptr> m_reachableInfosets; From 2ec1dcfc5b6f914edc90da60ecdebc3c13bb1209 Mon Sep 17 00:00:00 2001 From: StephenPasteris Date: Tue, 18 Nov 2025 11:27:03 +0000 Subject: [PATCH 20/29] Moved PlayerSequences into behavspt.h --- src/games/behavspt.cc | 17 ++++++++++++++++- src/games/behavspt.h | 19 ++++++++++++++++++- src/games/behavsptseqform.h | 23 ----------------------- 3 files changed, 34 insertions(+), 25 deletions(-) diff --git a/src/games/behavspt.cc b/src/games/behavspt.cc index 0e40703de..e533e9842 100644 --- a/src/games/behavspt.cc +++ b/src/games/behavspt.cc @@ -283,7 +283,7 @@ BehaviorSupportProfile::Sequences BehaviorSupportProfile::GetSequences() const BehaviorSupportProfile::PlayerSequences BehaviorSupportProfile::GetSequences(GamePlayer &p_player) const { - return {GetSequenceForm(), p_player}; + return {this, p_player}; } int BehaviorSupportProfile::GetConstraintEntry(const GameInfoset &p_infoset, @@ -323,6 +323,21 @@ BehaviorSupportProfile::ToMixedBehaviorProfile(const std::map::const_iterator BehaviorSupportProfile::PlayerSequences::begin() const +{ + return m_support->GetSequenceForm()->m_sequences.at(m_player).begin(); +} + +std::vector::const_iterator BehaviorSupportProfile::PlayerSequences::end() const +{ + return m_support->GetSequenceForm()->m_sequences.at(m_player).end(); +} + +size_t BehaviorSupportProfile::PlayerSequences::size() const +{ + return m_support->GetSequenceForm()->m_sequences.at(m_player).size(); +} + //======================================================================== // BehaviorSupportProfile: Reachable Information Sets //======================================================================== diff --git a/src/games/behavspt.h b/src/games/behavspt.h index 3f8783a37..b66f48c2a 100644 --- a/src/games/behavspt.h +++ b/src/games/behavspt.h @@ -35,6 +35,7 @@ class SequencesWrapper; class PlayerSequencesWrapper; class InfosetsWrapper; class ContingenciesWrapper; +using GameSequence = std::shared_ptr; /// This class represents a subset of the actions in an extensive game. /// It is enforced that each player has at least one action at each @@ -168,7 +169,23 @@ class BehaviorSupportProfile { }; class Sequences; - class PlayerSequences; + + class PlayerSequences { + private: + const BehaviorSupportProfile *m_support; + GamePlayer m_player; + + public: + PlayerSequences(const BehaviorSupportProfile *p_support, const GamePlayer &p_player) + : m_support(p_support), m_player(p_player) + { + } + + size_t size() const; + std::vector::const_iterator begin() const; + std::vector::const_iterator end() const; + }; + class Contingencies; mutable std::shared_ptr m_sequenceForm; diff --git a/src/games/behavsptseqform.h b/src/games/behavsptseqform.h index 9c04e20d7..c42ec57c7 100644 --- a/src/games/behavsptseqform.h +++ b/src/games/behavsptseqform.h @@ -80,29 +80,6 @@ class BehaviorSupportProfile::Sequences { iterator end() const { return {m_sfg, true}; } }; -class BehaviorSupportProfile::PlayerSequences { -private: - std::shared_ptr m_sfg; - GamePlayer m_player; - -public: - PlayerSequences(const std::shared_ptr p_sfg, const GamePlayer &p_player) - : m_sfg(p_sfg), m_player(p_player) - { - } - - size_t size() const { return m_sfg->m_sequences.at(m_player).size(); } - - std::vector::const_iterator begin() const - { - return m_sfg->m_sequences.at(m_player).begin(); - } - std::vector::const_iterator end() const - { - return m_sfg->m_sequences.at(m_player).end(); - } -}; - class BehaviorSupportProfile::Contingencies { private: const std::shared_ptr m_sfg; From 1ab5af53d95ed7c9f7348173e283bf9153668439 Mon Sep 17 00:00:00 2001 From: StephenPasteris Date: Tue, 18 Nov 2025 12:00:38 +0000 Subject: [PATCH 21/29] changed attribute in Sequences to BehaviorSupportProfile --- src/games/behavspt.cc | 5 +---- src/games/behavsptseqform.h | 11 ++++++----- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/games/behavspt.cc b/src/games/behavspt.cc index e533e9842..448e00c21 100644 --- a/src/games/behavspt.cc +++ b/src/games/behavspt.cc @@ -275,10 +275,7 @@ std::shared_ptr BehaviorSupportProfile::GetSequenceForm() cons return m_sequenceForm; } -BehaviorSupportProfile::Sequences BehaviorSupportProfile::GetSequences() const -{ - return {GetSequenceForm()}; -} +BehaviorSupportProfile::Sequences BehaviorSupportProfile::GetSequences() const { return {this}; } BehaviorSupportProfile::PlayerSequences BehaviorSupportProfile::GetSequences(GamePlayer &p_player) const diff --git a/src/games/behavsptseqform.h b/src/games/behavsptseqform.h index c42ec57c7..5a1ba95ff 100644 --- a/src/games/behavsptseqform.h +++ b/src/games/behavsptseqform.h @@ -12,7 +12,7 @@ namespace Gambit { class BehaviorSupportProfile::Sequences { private: - const std::shared_ptr m_sfg; + const BehaviorSupportProfile *m_support; public: class iterator { @@ -65,19 +65,20 @@ class BehaviorSupportProfile::Sequences { bool operator!=(const iterator &it) const { return !(*this == it); } }; - Sequences(const std::shared_ptr p_sfg) : m_sfg(p_sfg) {} + Sequences(const BehaviorSupportProfile *p_support) : m_support(p_support) {} size_t size() const { return std::accumulate( - m_sfg->m_sequences.cbegin(), m_sfg->m_sequences.cend(), 0, + m_support->GetSequenceForm()->m_sequences.cbegin(), + m_support->GetSequenceForm()->m_sequences.cend(), 0, [](int acc, const std::pair> &seq) { return acc + seq.second.size(); }); } - iterator begin() const { return {m_sfg, false}; } - iterator end() const { return {m_sfg, true}; } + iterator begin() const { return {m_support->GetSequenceForm(), false}; } + iterator end() const { return {m_support->GetSequenceForm(), true}; } }; class BehaviorSupportProfile::Contingencies { From fca0af57b433b9493423c348d9af2bef21d75514 Mon Sep 17 00:00:00 2001 From: StephenPasteris Date: Tue, 18 Nov 2025 12:10:01 +0000 Subject: [PATCH 22/29] changed attribute in Contingencies to BehaviorSupportProfile --- src/games/behavspt.cc | 2 +- src/games/behavsptseqform.h | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/games/behavspt.cc b/src/games/behavspt.cc index 448e00c21..0bf497a93 100644 --- a/src/games/behavspt.cc +++ b/src/games/behavspt.cc @@ -298,7 +298,7 @@ const Rational &BehaviorSupportProfile::GetPayoff( BehaviorSupportProfile::Contingencies BehaviorSupportProfile::GetContingencies() const { - return {GetSequenceForm()}; + return {this}; } MixedBehaviorProfile diff --git a/src/games/behavsptseqform.h b/src/games/behavsptseqform.h index 5a1ba95ff..c1145fd32 100644 --- a/src/games/behavsptseqform.h +++ b/src/games/behavsptseqform.h @@ -83,10 +83,10 @@ class BehaviorSupportProfile::Sequences { class BehaviorSupportProfile::Contingencies { private: - const std::shared_ptr m_sfg; + const BehaviorSupportProfile *m_support; public: - Contingencies(const std::shared_ptr p_sfg) : m_sfg(p_sfg) {} + Contingencies(const BehaviorSupportProfile *p_support) : m_support(p_support) {} class iterator { private: @@ -143,8 +143,8 @@ class BehaviorSupportProfile::Contingencies { bool operator!=(const iterator &it) const { return !(*this == it); } }; - iterator begin() { return {m_sfg}; } - iterator end() { return {m_sfg, true}; } + iterator begin() { return {m_support->GetSequenceForm()}; } + iterator end() { return {m_support->GetSequenceForm(), true}; } }; } // namespace Gambit From 97603ac0003495d7a1821beba0511c5396476205 Mon Sep 17 00:00:00 2001 From: StephenPasteris Date: Tue, 18 Nov 2025 12:26:39 +0000 Subject: [PATCH 23/29] renamed Contingencies and GetContingencies to SequenceContingencies and GetSequenceContingencies --- src/games/behavspt.cc | 3 ++- src/games/behavspt.h | 4 ++-- src/games/behavsptseqform.h | 4 ++-- src/solvers/enumpoly/efgpoly.cc | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/games/behavspt.cc b/src/games/behavspt.cc index 0bf497a93..7e833e358 100644 --- a/src/games/behavspt.cc +++ b/src/games/behavspt.cc @@ -296,7 +296,8 @@ const Rational &BehaviorSupportProfile::GetPayoff( return GetSequenceForm()->GetPayoff(p_profile, p_player); } -BehaviorSupportProfile::Contingencies BehaviorSupportProfile::GetContingencies() const +BehaviorSupportProfile::SequenceContingencies +BehaviorSupportProfile::GetSequenceContingencies() const { return {this}; } diff --git a/src/games/behavspt.h b/src/games/behavspt.h index b66f48c2a..2f89c8828 100644 --- a/src/games/behavspt.h +++ b/src/games/behavspt.h @@ -186,7 +186,7 @@ class BehaviorSupportProfile { std::vector::const_iterator end() const; }; - class Contingencies; + class SequenceContingencies; mutable std::shared_ptr m_sequenceForm; std::shared_ptr GetSequenceForm() const; @@ -200,7 +200,7 @@ class BehaviorSupportProfile { MixedBehaviorProfile ToMixedBehaviorProfile(const std::map, double> &) const; Infosets GetInfosets() const { return {this}; }; - Contingencies GetContingencies() const; + SequenceContingencies GetSequenceContingencies() const; mutable std::shared_ptr> m_reachableInfosets; void FindReachableInfosets(GameNode p_node) const; diff --git a/src/games/behavsptseqform.h b/src/games/behavsptseqform.h index c1145fd32..778a3fe6d 100644 --- a/src/games/behavsptseqform.h +++ b/src/games/behavsptseqform.h @@ -81,12 +81,12 @@ class BehaviorSupportProfile::Sequences { iterator end() const { return {m_support->GetSequenceForm(), true}; } }; -class BehaviorSupportProfile::Contingencies { +class BehaviorSupportProfile::SequenceContingencies { private: const BehaviorSupportProfile *m_support; public: - Contingencies(const BehaviorSupportProfile *p_support) : m_support(p_support) {} + SequenceContingencies(const BehaviorSupportProfile *p_support) : m_support(p_support) {} class iterator { private: diff --git a/src/solvers/enumpoly/efgpoly.cc b/src/solvers/enumpoly/efgpoly.cc index 00537d700..7b2019321 100644 --- a/src/solvers/enumpoly/efgpoly.cc +++ b/src/solvers/enumpoly/efgpoly.cc @@ -101,7 +101,7 @@ Polynomial GetPayoff(ProblemData &p_data, const GamePlayer &p_player) { Polynomial equation(p_data.space); - for (auto profile : p_data.m_support.GetContingencies()) { + for (auto profile : p_data.m_support.GetSequenceContingencies()) { auto pay = p_data.m_support.GetPayoff(profile, p_player); if (pay != Rational(0)) { Polynomial term(p_data.space, double(pay)); From bbcc097f8743cc691b115feb33e95f45dcd39349 Mon Sep 17 00:00:00 2001 From: StephenPasteris Date: Tue, 18 Nov 2025 13:15:15 +0000 Subject: [PATCH 24/29] Moved Sequences into behavspt.h --- src/games/behavspt.cc | 59 ++++++++++++++++++++++++++++++ src/games/behavspt.h | 31 +++++++++++++++- src/games/behavsptseqform.h | 71 ------------------------------------- 3 files changed, 89 insertions(+), 72 deletions(-) diff --git a/src/games/behavspt.cc b/src/games/behavspt.cc index 7e833e358..91e1bbe40 100644 --- a/src/games/behavspt.cc +++ b/src/games/behavspt.cc @@ -321,6 +321,65 @@ BehaviorSupportProfile::ToMixedBehaviorProfile(const std::mapGetSequenceForm()->m_sequences.cbegin(), + m_support->GetSequenceForm()->m_sequences.cend(), 0, + [](int acc, const std::pair> &seq) { + return acc + seq.second.size(); + }); +} + +BehaviorSupportProfile::Sequences::iterator BehaviorSupportProfile::Sequences::begin() const +{ + return {m_support->GetSequenceForm(), false}; +} +BehaviorSupportProfile::Sequences::iterator BehaviorSupportProfile::Sequences::end() const +{ + return {m_support->GetSequenceForm(), true}; +} + +BehaviorSupportProfile::Sequences::iterator::iterator( + const std::shared_ptr p_sfg, bool p_end) + : m_sfg(p_sfg) +{ + if (p_end) { + m_currentPlayer = m_sfg->m_sequences.cend(); + } + else { + m_currentPlayer = m_sfg->m_sequences.cbegin(); + m_currentSequence = m_currentPlayer->second.cbegin(); + } +} + +BehaviorSupportProfile::Sequences::iterator & +BehaviorSupportProfile::Sequences::iterator::operator++() +{ + if (m_currentPlayer == m_sfg->m_sequences.cend()) { + return *this; + } + m_currentSequence++; + if (m_currentSequence != m_currentPlayer->second.cend()) { + return *this; + } + m_currentPlayer++; + if (m_currentPlayer != m_sfg->m_sequences.cend()) { + m_currentSequence = m_currentPlayer->second.cbegin(); + } + return *this; +} + +bool BehaviorSupportProfile::Sequences::iterator::operator==(const iterator &it) const +{ + if (m_sfg != it.m_sfg || m_currentPlayer != it.m_currentPlayer) { + return false; + } + if (m_currentPlayer == m_sfg->m_sequences.end()) { + return true; + } + return (m_currentSequence == it.m_currentSequence); +} + std::vector::const_iterator BehaviorSupportProfile::PlayerSequences::begin() const { return m_support->GetSequenceForm()->m_sequences.at(m_player).begin(); diff --git a/src/games/behavspt.h b/src/games/behavspt.h index 2f89c8828..4c84091c5 100644 --- a/src/games/behavspt.h +++ b/src/games/behavspt.h @@ -168,7 +168,36 @@ class BehaviorSupportProfile { } }; - class Sequences; + class Sequences { + private: + const BehaviorSupportProfile *m_support; + + public: + class iterator { + private: + const std::shared_ptr m_sfg; + std::map>::const_iterator m_currentPlayer; + std::vector::const_iterator m_currentSequence; + + public: + iterator(const std::shared_ptr p_sfg, bool p_end); + + GameSequence operator*() const { return *m_currentSequence; } + GameSequence operator->() const { return *m_currentSequence; } + + iterator &operator++(); + + bool operator==(const iterator &it) const; + bool operator!=(const iterator &it) const { return !(*this == it); } + }; + + Sequences(const BehaviorSupportProfile *p_support) : m_support(p_support) {} + + size_t size() const; + + iterator begin() const; + iterator end() const; + }; class PlayerSequences { private: diff --git a/src/games/behavsptseqform.h b/src/games/behavsptseqform.h index 778a3fe6d..de4c99475 100644 --- a/src/games/behavsptseqform.h +++ b/src/games/behavsptseqform.h @@ -10,77 +10,6 @@ namespace Gambit { -class BehaviorSupportProfile::Sequences { -private: - const BehaviorSupportProfile *m_support; - -public: - class iterator { - private: - const std::shared_ptr m_sfg; - std::map>::const_iterator m_currentPlayer; - std::vector::const_iterator m_currentSequence; - - public: - iterator(const std::shared_ptr p_sfg, bool p_end) : m_sfg(p_sfg) - { - if (p_end) { - m_currentPlayer = m_sfg->m_sequences.cend(); - } - else { - m_currentPlayer = m_sfg->m_sequences.cbegin(); - m_currentSequence = m_currentPlayer->second.cbegin(); - } - } - - GameSequence operator*() const { return *m_currentSequence; } - GameSequence operator->() const { return *m_currentSequence; } - - iterator &operator++() - { - if (m_currentPlayer == m_sfg->m_sequences.cend()) { - return *this; - } - m_currentSequence++; - if (m_currentSequence != m_currentPlayer->second.cend()) { - return *this; - } - m_currentPlayer++; - if (m_currentPlayer != m_sfg->m_sequences.cend()) { - m_currentSequence = m_currentPlayer->second.cbegin(); - } - return *this; - } - - bool operator==(const iterator &it) const - { - if (m_sfg != it.m_sfg || m_currentPlayer != it.m_currentPlayer) { - return false; - } - if (m_currentPlayer == m_sfg->m_sequences.end()) { - return true; - } - return (m_currentSequence == it.m_currentSequence); - } - bool operator!=(const iterator &it) const { return !(*this == it); } - }; - - Sequences(const BehaviorSupportProfile *p_support) : m_support(p_support) {} - - size_t size() const - { - return std::accumulate( - m_support->GetSequenceForm()->m_sequences.cbegin(), - m_support->GetSequenceForm()->m_sequences.cend(), 0, - [](int acc, const std::pair> &seq) { - return acc + seq.second.size(); - }); - } - - iterator begin() const { return {m_support->GetSequenceForm(), false}; } - iterator end() const { return {m_support->GetSequenceForm(), true}; } -}; - class BehaviorSupportProfile::SequenceContingencies { private: const BehaviorSupportProfile *m_support; From 560917bce4302216654816da0a43fe70b52a3c52 Mon Sep 17 00:00:00 2001 From: StephenPasteris Date: Tue, 18 Nov 2025 13:36:37 +0000 Subject: [PATCH 25/29] Moved SequenceContingencies into behavspt.h --- src/games/behavspt.cc | 43 ++++++++++++++++++++++++ src/games/behavspt.h | 35 +++++++++++++++++++- src/games/behavsptseqform.h | 66 ------------------------------------- 3 files changed, 77 insertions(+), 67 deletions(-) diff --git a/src/games/behavspt.cc b/src/games/behavspt.cc index 91e1bbe40..032cc41de 100644 --- a/src/games/behavspt.cc +++ b/src/games/behavspt.cc @@ -395,6 +395,49 @@ size_t BehaviorSupportProfile::PlayerSequences::size() const return m_support->GetSequenceForm()->m_sequences.at(m_player).size(); } +BehaviorSupportProfile::SequenceContingencies::iterator::iterator( + const std::shared_ptr p_sfg, bool p_end) + : m_sfg(p_sfg), m_end(p_end) +{ + for (auto [player, sequences] : m_sfg->m_sequences) { + m_indices[player] = 0; + } +} + +std::map +BehaviorSupportProfile::SequenceContingencies::iterator::operator*() const +{ + std::map ret; + for (auto [player, index] : m_indices) { + ret[player] = m_sfg->m_sequences.at(player)[index]; + } + return ret; +} + +std::map +BehaviorSupportProfile::SequenceContingencies::iterator::operator->() const +{ + std::map ret; + for (auto [player, index] : m_indices) { + ret[player] = m_sfg->m_sequences.at(player)[index]; + } + return ret; +} + +BehaviorSupportProfile::SequenceContingencies::iterator & +BehaviorSupportProfile::SequenceContingencies::iterator::operator++() +{ + for (auto [player, index] : m_indices) { + if (index < m_sfg->m_sequences.at(player).size() - 1) { + m_indices[player]++; + return *this; + } + m_indices[player] = 0; + } + m_end = true; + return *this; +} + //======================================================================== // BehaviorSupportProfile: Reachable Information Sets //======================================================================== diff --git a/src/games/behavspt.h b/src/games/behavspt.h index 4c84091c5..537c630cc 100644 --- a/src/games/behavspt.h +++ b/src/games/behavspt.h @@ -215,7 +215,40 @@ class BehaviorSupportProfile { std::vector::const_iterator end() const; }; - class SequenceContingencies; + class SequenceContingencies { + private: + const BehaviorSupportProfile *m_support; + + public: + SequenceContingencies(const BehaviorSupportProfile *p_support) : m_support(p_support) {} + + class iterator { + private: + const std::shared_ptr m_sfg; + bool m_end{false}; + std::map m_indices; + + public: + using iterator_category = std::input_iterator_tag; + + iterator(const std::shared_ptr p_sfg, bool p_end = false); + + std::map operator*() const; + + std::map operator->() const; + + iterator &operator++(); + + bool operator==(const iterator &it) const + { + return (m_end == it.m_end && m_sfg == it.m_sfg && m_indices == it.m_indices); + } + bool operator!=(const iterator &it) const { return !(*this == it); } + }; + + iterator begin() { return {m_support->GetSequenceForm()}; } + iterator end() { return {m_support->GetSequenceForm(), true}; } + }; mutable std::shared_ptr m_sequenceForm; std::shared_ptr GetSequenceForm() const; diff --git a/src/games/behavsptseqform.h b/src/games/behavsptseqform.h index de4c99475..3b3bb09d2 100644 --- a/src/games/behavsptseqform.h +++ b/src/games/behavsptseqform.h @@ -10,72 +10,6 @@ namespace Gambit { -class BehaviorSupportProfile::SequenceContingencies { -private: - const BehaviorSupportProfile *m_support; - -public: - SequenceContingencies(const BehaviorSupportProfile *p_support) : m_support(p_support) {} - - class iterator { - private: - const std::shared_ptr m_sfg; - bool m_end{false}; - std::map m_indices; - - public: - using iterator_category = std::input_iterator_tag; - - iterator(const std::shared_ptr p_sfg, bool p_end = false) - : m_sfg(p_sfg), m_end(p_end) - { - for (auto [player, sequences] : m_sfg->m_sequences) { - m_indices[player] = 0; - } - } - - std::map operator*() const - { - std::map ret; - for (auto [player, index] : m_indices) { - ret[player] = m_sfg->m_sequences.at(player)[index]; - } - return ret; - } - - std::map operator->() const - { - std::map ret; - for (auto [player, index] : m_indices) { - ret[player] = m_sfg->m_sequences.at(player)[index]; - } - return ret; - } - - iterator &operator++() - { - for (auto [player, index] : m_indices) { - if (index < m_sfg->m_sequences.at(player).size() - 1) { - m_indices[player]++; - return *this; - } - m_indices[player] = 0; - } - m_end = true; - return *this; - } - - bool operator==(const iterator &it) const - { - return (m_end == it.m_end && m_sfg == it.m_sfg && m_indices == it.m_indices); - } - bool operator!=(const iterator &it) const { return !(*this == it); } - }; - - iterator begin() { return {m_support->GetSequenceForm()}; } - iterator end() { return {m_support->GetSequenceForm(), true}; } -}; - } // namespace Gambit #endif // GAMBIT_BEHAVSPT_SEQ_FORM_H From 4aceb2e95c5cb461945f817bdda99817d5780c8c Mon Sep 17 00:00:00 2001 From: StephenPasteris Date: Tue, 18 Nov 2025 13:49:02 +0000 Subject: [PATCH 26/29] Removed behavsptseqform.h --- Makefile.am | 1 - src/games/behavspt.cc | 1 - src/games/behavsptseqform.h | 15 --------------- src/solvers/enumpoly/efgpoly.cc | 1 - 4 files changed, 18 deletions(-) delete mode 100644 src/games/behavsptseqform.h diff --git a/Makefile.am b/Makefile.am index 1eb4a3ec8..4325353ef 100644 --- a/Makefile.am +++ b/Makefile.am @@ -300,7 +300,6 @@ game_SOURCES = \ src/games/gametree.h \ src/games/behavspt.cc \ src/games/behavspt.h \ - src/games/behavsptseqform.h \ src/games/behavpure.cc \ src/games/behavpure.h \ src/games/behavmixed.cc \ diff --git a/src/games/behavspt.cc b/src/games/behavspt.cc index 032cc41de..d953c0944 100644 --- a/src/games/behavspt.cc +++ b/src/games/behavspt.cc @@ -22,7 +22,6 @@ #include "gambit.h" #include "gameseq.h" -#include "behavsptseqform.h" namespace Gambit { diff --git a/src/games/behavsptseqform.h b/src/games/behavsptseqform.h deleted file mode 100644 index 3b3bb09d2..000000000 --- a/src/games/behavsptseqform.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// Created by Stephen Pasteris on 12/11/2025. -// - -#ifndef GAMBIT_BEHAVSPT_SEQ_FORM_H -#define GAMBIT_BEHAVSPT_SEQ_FORM_H - -#include "gambit.h" -#include "gameseq.h" - -namespace Gambit { - -} // namespace Gambit - -#endif // GAMBIT_BEHAVSPT_SEQ_FORM_H diff --git a/src/solvers/enumpoly/efgpoly.cc b/src/solvers/enumpoly/efgpoly.cc index 7b2019321..e88cca353 100644 --- a/src/solvers/enumpoly/efgpoly.cc +++ b/src/solvers/enumpoly/efgpoly.cc @@ -26,7 +26,6 @@ #include "polysystem.h" #include "polysolver.h" #include "behavextend.h" -#include "games/behavsptseqform.h" using namespace Gambit; using namespace Gambit::Nash; From 821ce92677941e4a5e658e9706c7603c6ab5df01 Mon Sep 17 00:00:00 2001 From: Theodore Turocy Date: Tue, 18 Nov 2025 16:14:37 +0000 Subject: [PATCH 27/29] Minor cleanups --- src/games/behavspt.h | 9 +-------- src/games/gameseq.h | 3 --- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/src/games/behavspt.h b/src/games/behavspt.h index 537c630cc..8e118a402 100644 --- a/src/games/behavspt.h +++ b/src/games/behavspt.h @@ -45,9 +45,9 @@ using GameSequence = std::shared_ptr; /// computational approaches that enumerate possible equilibrium /// supports. class BehaviorSupportProfile { -protected: Game m_efg; std::map> m_actions; + mutable std::shared_ptr m_sequenceForm; std::map m_infosetReachable; std::map m_nonterminalReachable; @@ -58,7 +58,6 @@ class BehaviorSupportProfile { public: class Support { - private: const BehaviorSupportProfile *m_profile; GameInfoset m_infoset; @@ -149,7 +148,6 @@ class BehaviorSupportProfile { //@} class Infosets { - private: const BehaviorSupportProfile *m_support; public: @@ -169,12 +167,10 @@ class BehaviorSupportProfile { }; class Sequences { - private: const BehaviorSupportProfile *m_support; public: class iterator { - private: const std::shared_ptr m_sfg; std::map>::const_iterator m_currentPlayer; std::vector::const_iterator m_currentSequence; @@ -200,7 +196,6 @@ class BehaviorSupportProfile { }; class PlayerSequences { - private: const BehaviorSupportProfile *m_support; GamePlayer m_player; @@ -216,7 +211,6 @@ class BehaviorSupportProfile { }; class SequenceContingencies { - private: const BehaviorSupportProfile *m_support; public: @@ -250,7 +244,6 @@ class BehaviorSupportProfile { iterator end() { return {m_support->GetSequenceForm(), true}; } }; - mutable std::shared_ptr m_sequenceForm; std::shared_ptr GetSequenceForm() const; Sequences GetSequences() const; PlayerSequences GetSequences(GamePlayer &p_player) const; diff --git a/src/games/gameseq.h b/src/games/gameseq.h index 5a0b97c46..4b7a1c91e 100644 --- a/src/games/gameseq.h +++ b/src/games/gameseq.h @@ -56,10 +56,8 @@ class GameSequenceRep { using GameSequence = std::shared_ptr; class GameSequenceForm { - friend class BehaviorSupportProfile; -private: BehaviorSupportProfile m_support; std::map> m_sequences; NDArray m_payoffs; @@ -89,7 +87,6 @@ class GameSequenceForm { public: class Infosets { - private: const GameSequenceForm *m_sfg; public: From 8f0cbcd408685def90475bfdf1b53a9c2276c459 Mon Sep 17 00:00:00 2001 From: Theodore Turocy Date: Tue, 18 Nov 2025 16:29:17 +0000 Subject: [PATCH 28/29] Promote GameSequence to be a GameObject --- src/games/behavspt.cc | 6 +++--- src/games/behavspt.h | 11 ++++------- src/games/game.h | 35 +++++++++++++++++++++++++++++++++++ src/games/gameseq.cc | 3 ++- src/games/gameseq.h | 27 --------------------------- 5 files changed, 44 insertions(+), 38 deletions(-) diff --git a/src/games/behavspt.cc b/src/games/behavspt.cc index d953c0944..be017148e 100644 --- a/src/games/behavspt.cc +++ b/src/games/behavspt.cc @@ -288,9 +288,9 @@ int BehaviorSupportProfile::GetConstraintEntry(const GameInfoset &p_infoset, return GetSequenceForm()->GetConstraintEntry(p_infoset, p_action); } -const Rational &BehaviorSupportProfile::GetPayoff( - const std::map> &p_profile, - const GamePlayer &p_player) const +const Rational & +BehaviorSupportProfile::GetPayoff(const std::map &p_profile, + const GamePlayer &p_player) const { return GetSequenceForm()->GetPayoff(p_profile, p_player); } diff --git a/src/games/behavspt.h b/src/games/behavspt.h index 8e118a402..59e89fbbc 100644 --- a/src/games/behavspt.h +++ b/src/games/behavspt.h @@ -30,12 +30,10 @@ namespace Gambit { class GameSequenceForm; -class GameSequenceRep; class SequencesWrapper; class PlayerSequencesWrapper; class InfosetsWrapper; class ContingenciesWrapper; -using GameSequence = std::shared_ptr; /// This class represents a subset of the actions in an extensive game. /// It is enforced that each player has at least one action at each @@ -48,6 +46,7 @@ class BehaviorSupportProfile { Game m_efg; std::map> m_actions; mutable std::shared_ptr m_sequenceForm; + mutable std::shared_ptr> m_reachableInfosets; std::map m_infosetReachable; std::map m_nonterminalReachable; @@ -248,16 +247,14 @@ class BehaviorSupportProfile { Sequences GetSequences() const; PlayerSequences GetSequences(GamePlayer &p_player) const; int GetConstraintEntry(const GameInfoset &p_infoset, const GameAction &p_action) const; - const Rational & - GetPayoff(const std::map> &p_profile, - const GamePlayer &p_player) const; + const Rational &GetPayoff(const std::map &p_profile, + const GamePlayer &p_player) const; GameRep::Players GetPlayers() const { return GetGame()->GetPlayers(); } MixedBehaviorProfile - ToMixedBehaviorProfile(const std::map, double> &) const; + ToMixedBehaviorProfile(const std::map &) const; Infosets GetInfosets() const { return {this}; }; SequenceContingencies GetSequenceContingencies() const; - mutable std::shared_ptr> m_reachableInfosets; void FindReachableInfosets(GameNode p_node) const; std::shared_ptr> GetReachableInfosets() const; }; diff --git a/src/games/game.h b/src/games/game.h index 53cea45f8..2af71a604 100644 --- a/src/games/game.h +++ b/src/games/game.h @@ -48,6 +48,9 @@ using GameInfoset = GameObjectPtr; class GameStrategyRep; using GameStrategy = GameObjectPtr; +class GameSequenceRep; +using GameSequence = GameObjectPtr; + class GamePlayerRep; using GamePlayer = GameObjectPtr; @@ -316,6 +319,36 @@ class GameStrategyRep : public std::enable_shared_from_this { //@} }; +class GameSequenceRep : public std::enable_shared_from_this { +public: + bool m_valid{true}; + GamePlayer player; + GameAction action; + size_t number; + std::weak_ptr parent; + + explicit GameSequenceRep(const GamePlayer &p_player, const GameAction &p_action, size_t p_number, + std::weak_ptr p_parent) + : player(p_player), action(p_action), number(p_number), parent(p_parent) + { + } + + bool IsValid() const { return m_valid; } + void Invalidate() { m_valid = false; } + + Game GetGame() const; + GameInfoset GetInfoset() const { return (action) ? action->GetInfoset() : nullptr; } + + bool operator<(const GameSequenceRep &other) const + { + return player < other.player || (player == other.player && action < other.action); + } + bool operator==(const GameSequenceRep &other) const + { + return player == other.player && action == other.action; + } +}; + /// A player in a game class GamePlayerRep : public std::enable_shared_from_this { friend class GameRep; @@ -945,6 +978,8 @@ inline void GameOutcomeRep::SetPayoff(const GamePlayer &p_player, const Number & inline GamePlayer GameStrategyRep::GetPlayer() const { return m_player->shared_from_this(); } inline Game GameStrategyRep::GetGame() const { return m_player->GetGame(); } +inline Game GameSequenceRep::GetGame() const { return player->GetGame(); } + inline Game GameActionRep::GetGame() const { return m_infoset->GetGame(); } inline Game GameInfosetRep::GetGame() const { return m_game->shared_from_this(); } diff --git a/src/games/gameseq.cc b/src/games/gameseq.cc index b8df35c50..d0a4a755a 100644 --- a/src/games/gameseq.cc +++ b/src/games/gameseq.cc @@ -44,7 +44,8 @@ void GameSequenceForm::BuildSequences(const GameNode &n, for (auto action : m_support.GetActions(n->GetInfoset())) { if (m_correspondence.find(action) == m_correspondence.end()) { m_sequences[n->GetPlayer()].push_back(std::make_shared( - n->GetPlayer(), action, m_sequences[n->GetPlayer()].size() + 1, tmp_sequence)); + n->GetPlayer(), action, m_sequences[n->GetPlayer()].size() + 1, + tmp_sequence.get_shared())); m_correspondence[action] = m_sequences[n->GetPlayer()].back(); } p_currentSequences[n->GetPlayer()] = m_correspondence[action]; diff --git a/src/games/gameseq.h b/src/games/gameseq.h index 4b7a1c91e..bcf4fec70 100644 --- a/src/games/gameseq.h +++ b/src/games/gameseq.h @@ -28,33 +28,6 @@ namespace Gambit { -class GameSequenceRep { -public: - GamePlayer player; - GameAction action; - size_t number; - std::weak_ptr parent; - - explicit GameSequenceRep(const GamePlayer &p_player, const GameAction &p_action, size_t p_number, - std::weak_ptr p_parent) - : player(p_player), action(p_action), number(p_number), parent(p_parent) - { - } - - GameInfoset GetInfoset() const { return (action) ? action->GetInfoset() : nullptr; } - - bool operator<(const GameSequenceRep &other) const - { - return player < other.player || (player == other.player && action < other.action); - } - bool operator==(const GameSequenceRep &other) const - { - return player == other.player && action == other.action; - } -}; - -using GameSequence = std::shared_ptr; - class GameSequenceForm { friend class BehaviorSupportProfile; From bc656aaf9dcd59eab12ee57c554208e80e9fdc70 Mon Sep 17 00:00:00 2001 From: Theodore Turocy Date: Tue, 18 Nov 2025 16:34:41 +0000 Subject: [PATCH 29/29] Address clang-tidy error. --- src/games/gameseq.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/gameseq.cc b/src/games/gameseq.cc index d0a4a755a..367a7ec7c 100644 --- a/src/games/gameseq.cc +++ b/src/games/gameseq.cc @@ -43,7 +43,7 @@ void GameSequenceForm::BuildSequences(const GameNode &n, auto tmp_sequence = p_currentSequences.at(n->GetPlayer()); for (auto action : m_support.GetActions(n->GetInfoset())) { if (m_correspondence.find(action) == m_correspondence.end()) { - m_sequences[n->GetPlayer()].push_back(std::make_shared( + m_sequences[n->GetPlayer()].emplace_back(std::make_shared( n->GetPlayer(), action, m_sequences[n->GetPlayer()].size() + 1, tmp_sequence.get_shared())); m_correspondence[action] = m_sequences[n->GetPlayer()].back();