Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
957881b
Change `enumpoly` on extensive games to return only full profiles.
tturocy Jan 30, 2026
17d744e
Remove overelaborate checker for whether a profile extends to Nash - …
tturocy Jan 30, 2026
fd9c769
Test using (strategic) regret rather than agent regret - as `enumpoly…
tturocy Jan 30, 2026
5be1c6b
Removed no-longer-implemented functions
tturocy Jan 30, 2026
c829a6c
Remove unused function
tturocy Jan 30, 2026
9fd759e
Remove unneeded GetMembers
tturocy Jan 30, 2026
968a399
Proposes a change in behaviour to return profiles which have pure act…
tturocy Feb 4, 2026
d231a8c
Merge branch 'master' into issue_660
tturocy Feb 26, 2026
a5d2ac4
Merge branch 'master' into issue_660
tturocy Mar 6, 2026
0f02db1
Merge branch 'master' into issue_660
rahulsavani Mar 11, 2026
3946c5f
fix test_enumpoly_behavior_{7,8} given change in issue_756
rahulsavani Mar 11, 2026
0c69a08
stop_after from 2 to None in test_enumpoly_behavior_8
rahulsavani Mar 11, 2026
f46a2ed
removed test_nash_behavior_solver_no_subtests_only_profile and re-inc…
rahulsavani Mar 11, 2026
03f487c
test_enumpoly_behavior_{10,11,12} for 2 off equilibrium path
rahulsavani Mar 11, 2026
6242bf8
missing efg files
rahulsavani Mar 11, 2026
299731b
added 2 player game to test to centroid for 2-deviation infosets
rahulsavani Mar 12, 2026
018f33d
added 2 player game to test to centroid for 2-deviation infosets
rahulsavani Mar 12, 2026
7b56c7f
Return just a sample equilibrium for any set of realisation-equivalen…
tturocy Mar 18, 2026
7340d33
Fix wording for Nash equilibrium description
rahulsavani Mar 19, 2026
95a8fce
Clarify condition for returning Nash equilibrium profile
rahulsavani Mar 19, 2026
e29e1f9
Refine description of profiles in documentation
rahulsavani Mar 19, 2026
66946ee
fix id and tolerance in test_lcp_behavior_rational_23
rahulsavani Mar 19, 2026
e117fd3
Merge branch 'master' into issue_660
tturocy Mar 19, 2026
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
3 changes: 0 additions & 3 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -406,9 +406,6 @@ gambit_enumpoly_SOURCES = \
src/solvers/enumpoly/polypartial.imp \
src/solvers/enumpoly/polysolver.cc \
src/solvers/enumpoly/polysolver.h \
src/solvers/enumpoly/polyfeasible.h \
src/solvers/enumpoly/behavextend.cc \
src/solvers/enumpoly/behavextend.h \
src/solvers/enumpoly/efgpoly.cc \
src/solvers/enumpoly/nfgpoly.cc \
src/solvers/enumpoly/enumpoly.h \
Expand Down
13 changes: 13 additions & 0 deletions doc/tools.enumpoly.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,19 @@ supports which have the fewest strategies in total. For many classes
of games, this will tend to lower the average time until finding one equilibrium,
as well as finding the second equilibrium (if one exists).

For extensive games, a support of actions equates to allowing positive
probabilities over a subset of terminal nodes. The indifference conditions
used are those for the sequence form defined on the projection of the game
to that support of actions. A solution to these equations implies a probability
distribution over terminal nodes. The algorithm then searches for
a profile that is a Nash equilibrium that implements that probability
distribution. If there exists at least one such profile, a sample one is returned.
Note that for probability distributions which assign zero probability to some terminal
nodes, it is generally the case that there are (infinitely) many such profiles.
Subsequent analysis of unreached information sets can yield alternative
profiles that specify different choices at unreached information sets
while still satisfying the Nash equilibrium conditions.

When the verbose switch `-v` is used, the program outputs each support
as it is considered. The supports are presented as a comma-separated
list of binary strings, where each entry represents one player. The
Expand Down
4 changes: 2 additions & 2 deletions src/games/behavmixed.cc
Original file line number Diff line number Diff line change
Expand Up @@ -234,12 +234,12 @@ template <class T> MixedBehaviorProfile<T> MixedBehaviorProfile<T>::Normalize()
template <class T> MixedBehaviorProfile<T> MixedBehaviorProfile<T>::ToFullSupport() const
{
CheckVersion();
MixedBehaviorProfile<T> full(GetGame());
MixedBehaviorProfile full(GetGame());

for (auto player : m_support.GetGame()->GetPlayers()) {
for (auto infoset : player->GetInfosets()) {
for (auto action : infoset->GetActions()) {
full[action] = (m_support.Contains(action)) ? (*this)[action] : T(0);
full[action] = (m_support.Contains(action)) ? (*this)[action] : T{0};
}
}
}
Expand Down
34 changes: 8 additions & 26 deletions src/games/behavspt.cc
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,10 @@ void BehaviorSupportProfile::AddAction(const GameAction &p_action)
if (pos == support.end() || *pos != p_action) {
// Action is not in the support at the infoset; add at this location to keep sorted by number
support.insert(pos, p_action);
for (const auto &node : GetMembers(p_action->GetInfoset())) {
ActivateSubtree(node->GetChild(p_action));
for (const auto &node : p_action->GetInfoset()->GetMembers()) {
if (m_nonterminalReachable[node]) {
ActivateSubtree(node->GetChild(p_action));
}
}
}
}
Expand All @@ -86,25 +88,16 @@ bool BehaviorSupportProfile::RemoveAction(const GameAction &p_action)
auto pos = std::find(support.begin(), support.end(), p_action);
if (pos != support.end()) {
support.erase(pos);
for (const auto &node : GetMembers(p_action->GetInfoset())) {
DeactivateSubtree(node->GetChild(p_action));
for (const auto &node : p_action->GetInfoset()->GetMembers()) {
if (m_nonterminalReachable[node]) {
DeactivateSubtree(node->GetChild(p_action));
}
}
return !support.empty();
}
return false;
}

std::list<GameInfoset> BehaviorSupportProfile::GetInfosets(const GamePlayer &p_player) const
{
std::list<GameInfoset> answer;
for (const auto &infoset : p_player->GetInfosets()) {
if (m_infosetReachable.at(infoset)) {
answer.push_back(infoset);
}
}
return answer;
}

bool BehaviorSupportProfile::HasReachableMembers(const GameInfoset &p_infoset) const
{
const auto &members = p_infoset->GetMembers();
Expand Down Expand Up @@ -150,17 +143,6 @@ void BehaviorSupportProfile::DeactivateSubtree(const GameNode &n)
}
}

std::list<GameNode> BehaviorSupportProfile::GetMembers(const GameInfoset &p_infoset) const
{
std::list<GameNode> answer;
for (const auto &member : p_infoset->GetMembers()) {
if (m_nonterminalReachable.at(member)) {
answer.push_back(member);
}
}
return answer;
}

//========================================================================
// BehaviorSupportProfile: Sequence form
//========================================================================
Expand Down
14 changes: 0 additions & 14 deletions src/games/behavspt.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,20 +130,6 @@ class BehaviorSupportProfile {
//@{
/// Can the information set be reached under this support?
bool IsReachable(const GameInfoset &p_infoset) const { return m_infosetReachable.at(p_infoset); }
/// Get the information sets for the player reachable under the support
std::list<GameInfoset> GetInfosets(const GamePlayer &) const;
/// Get the members of the information set reachable under the support
std::list<GameNode> GetMembers(const GameInfoset &) const;
//@}

/// @name Identification of dominated actions
//@{
/// Returns true if action 'a' is dominated by action 'b'
bool Dominates(const GameAction &a, const GameAction &b, bool p_strict) const;
/// Returns true if the action is dominated by some other action
bool IsDominated(const GameAction &a, bool p_strict) const;
/// Returns a copy of the support with dominated actions eliminated
BehaviorSupportProfile Undominated(bool p_strict) const;
//@}

class Infosets {
Expand Down
Loading
Loading