Generating games with GAMUT#
GAMUT is a suite of parameterised game generators covering a wide range of game families studied in the game theory literature. Written in Java, GAMUT can generate instances of 35 game classes, including random games, coordination games, covariant games, voting games, and many more.
PyGambit’s generate_gamut function calls GAMUT as an external subprocess and returns the resulting game as a Game object, ready for analysis with PyGambit’s full suite of tools. Before running this tutorial, you will need Java and gamut.jar installed; see the catalog documentation for full installation instructions.
Note: The cell outputs in this notebook were generated locally. To reproduce them, update the
gamut_jarargument in each cell to the path of your localgamut.jar.
This tutorial covers:
Generating classic two-player games with no additional parameters
Generating parameterised random normal-form games
Exploring how the covariance parameter in
CovariantGameaffects equilibrium structureGenerating multi-player games
Controlling payoff normalisation and obtaining integer payoffs
[1]:
import pygambit as gbt
Discovering available game classes#
gbt.catalog.gamut_games() returns a DataFrame listing all 35 GAMUT game classes, their descriptions, and whether they support more than two players. Use this as a quick reference when choosing a game to generate:
[2]:
gbt.catalog.gamut_games()
[2]:
| Class | Description | Players | |
|---|---|---|---|
| 0 | ArmsRace | Arms race with cost and demand functions chose... | n |
| 1 | BattleOfTheSexes | Coordination game where players prefer to meet... | 2 |
| 2 | BertrandOligopoly | Bertrand oligopoly with arbitrary cost and dem... | n |
| 3 | BidirectionalLEG | Bidirectional local-effect game on a specified... | n |
| 4 | Chicken | Classic 2x2 Chicken game. | 2 |
| 5 | CollaborationGame | Game where all players choosing the same actio... | n |
| 6 | CongestionGame | Congestion game where payoffs depend on how ma... | n |
| 7 | CoordinationGame | Pure coordination game rewarding matching acti... | n |
| 8 | CournotDuopoly | Cournot duopoly with arbitrary cost and invers... | 2 |
| 9 | CovariantGame | Game with payoffs whose cross-player correlati... | n |
| 10 | DispersionGame | Game where dispersed action choices are rewarded. | n |
| 11 | GrabTheDollar | Simultaneous competition to claim a prize first. | 2 |
| 12 | GreedyGame | Players each choose a subset from a set; payof... | 2 |
| 13 | GuessThirdsAve | Players guess a number trying to reach 2/3 of ... | n |
| 14 | HawkAndDove | Classic 2x2 Hawk and Dove game. | 2 |
| 15 | LocationGame | Hotelling-style two-player location game on a ... | 2 |
| 16 | MajorityVoting | Majority voting game with arbitrary candidate ... | n |
| 17 | MatchingPennies | Classic 2x2 Matching Pennies game. | 2 |
| 18 | MinimumEffortGame | Payoffs depend on the minimum effort exerted a... | n |
| 19 | NPlayerChicken | N-player Chicken game with cooperation costs a... | n |
| 20 | NPlayerPrisonersDilemma | N-player Prisoner's Dilemma with parameterised... | n |
| 21 | PolymatrixGame | Polymatrix game formed by two-player edge game... | n |
| 22 | PrisonersDilemma | Classic 2x2 Prisoner's Dilemma. | 2 |
| 23 | RandomCompoundGame | Compound game whose payoffs are sums of random... | n |
| 24 | RandomGame | Game with payoffs drawn uniformly at random. | n |
| 25 | RandomGraphicalGame | Random graphical game on a specified graph. | n |
| 26 | RandomLEG | Random local-effect game on a specified graph. | n |
| 27 | RandomZeroSum | Two-player zero-sum game with random payoffs. | 2 |
| 28 | RockPaperScissors | Classic Rock, Paper, Scissors game. | 2 |
| 29 | ShapleyGame | Shapley's original game; no stable equilibrium... | 2 |
| 30 | SimpleInspectionGame | Inspection game where players choose from diff... | 2 |
| 31 | TravelersDilemma | Players claim a value; the lowest claim wins a... | n |
| 32 | TwoByTwoGame | 2x2 game of a specified type per Rapoport's cl... | 2 |
| 33 | UniformLEG | Local-effect game where all edges share the sa... | n |
| 34 | WarOfAttrition | Players choose concession times; payoffs depen... | 2 |
Classic two-player games#
Many of GAMUT’s game classes correspond directly to well-known games from the game theory literature and require no additional parameters to generate. Here we generate Battle of the Sexes, a canonical 2×2 coordination game.
In Battle of the Sexes, two players must independently decide whether to go to the Opera or a Football match. Both prefer to attend the same event, but player 1 prefers the Opera while player 2 prefers Football. The game has two pure-strategy Nash equilibria — both go to the Opera, or both go to Football — and one mixed-strategy equilibrium.
[3]:
g_bos = gbt.catalog.generate_gamut(
"BattleOfTheSexes",
params={
"int_payoffs": True,
"int_mult": 1,
"normalize": True,
"min_payoff": 0,
"max_payoff": 3
},
gamut_jar="~/Downloads/gamut.jar",
)
g_bos.title = "Battle of the Sexes"
for player in g_bos.players:
for strategy, label in zip(player.strategies, ["Opera", "Football"], strict=True):
strategy.label = label
g_bos
[3]:
Battle of the Sexes
| Player2 | |||
| Opera | Football | ||
| Player1 | Opera | 3,3 | 0,0 |
| Football | 0,0 | 3,3 | |
Now let’s compute all Nash equilibria using the linear complementarity method, which is well-suited to two-player games:
[4]:
result_bos = gbt.nash.lcp_solve(g_bos)
len(result_bos.equilibria)
[4]:
3
As expected, the solver finds three equilibria: two pure-strategy equilibria (both play Opera, or both play Football) and one mixed-strategy equilibrium in which each player randomises between the two options:
[5]:
result_bos.equilibria[0]
[5]:
[6]:
result_bos.equilibria[1]
[6]:
[7]:
result_bos.equilibria[2]
[7]:
Payoff normalisation and integer payoffs#
By default, GAMUT draws payoffs uniformly from the range [-100, 100]. These global parameters let you rescale and discretise payoffs:
Parameter |
Type |
Effect |
|---|---|---|
|
boolean flag |
Enable rescaling to [ |
|
number |
Lower bound after normalisation |
|
number |
Upper bound after normalisation |
|
boolean flag |
Round all payoffs to integers |
|
boolean flag |
Multiplier used before rounding when converting from double to integer payoffs |
See the GAMUT documentation for more info on the available Global parameters.
Parameterised random normal-form games#
Most GAMUT game classes accept parameters to control the number of players, the number of actions, and the structure of payoffs. These are passed as a dictionary to the params argument; each key maps to a GAMUT command-line flag.
RandomGame is the most general generator: payoffs are drawn independently and uniformly at random from a fixed range. It serves as a useful baseline for testing algorithms. The players parameter controls the number of players, and actions controls the number of actions per player. When actions is a list, each element gives the action count for the corresponding player, allowing asymmetric games:
[8]:
g_rand = gbt.catalog.generate_gamut(
"RandomGame",
params={"players": 2, "actions": [3, 3]},
gamut_jar="~/Downloads/gamut.jar",
)
g_rand.title = "Random Game (2 players, 3x4)"
g_rand
[8]:
Random Game (2 players, 3x4)
| Player2 | ||||
| 1 | 2 | 3 | ||
| Player1 | 1 | -24.90896560296312,-41.46093893377729 | -97.04833183504611,-23.563809906970732 | 50.0831929786506,26.051862305230316 |
| 2 | -65.96410417734546,44.090181858304135 | 30.77026176277343,-17.52125395472777 | -10.707266835174579,26.28680487237078 | |
| 3 | -65.52630679123462,-87.74228077603547 | -3.9604024034780565,-61.10491491476051 | -94.29034279305093,-45.34942611324284 | |
[9]:
gbt.nash.lcp_solve(g_rand).equilibria[0]
[9]:
Covariant games#
CovariantGame generates two-player games in which the degree of alignment between players’ interests is controlled by a covariance parameter r.
When
r = 1the game is a common-payoff game: both players receive identical payoffs.When
r = 0payoffs are independent — equivalent toRandomGame.As
rapproaches-1(the minimum for a two-player game) the game approaches a zero-sum game.
Let’s compare an equilibrium under high positive covariance (nearly a coordination game) with one under negative covariance (a more adversarial setting):
[10]:
g_cov_pos = gbt.catalog.generate_gamut(
"CovariantGame",
params={"players": 2, "actions": [3, 3], "r": 0.8},
gamut_jar="~/Downloads/gamut.jar",
)
g_cov_pos.title = "Covariant Game (r=0.8)"
eqm_pos = gbt.nash.lcp_solve(g_cov_pos).equilibria[0]
eqm_pos
[10]:
[11]:
g_cov_neg = gbt.catalog.generate_gamut(
"CovariantGame",
params={"players": 2, "actions": [3, 3], "r": -0.5},
gamut_jar="~/Downloads/gamut.jar",
)
g_cov_neg.title = "Covariant Game (r=-0.5)"
eqm_neg = gbt.nash.lcp_solve(g_cov_neg).equilibria[0]
eqm_neg
[11]:
With high positive covariance (r = 0.8) the game is close to a coordination game, so an equilibrium in pure or near-pure strategies is typical. With negative covariance (r = -0.5) the game is more adversarial, making genuinely mixed equilibria more likely.
Multi-player games#
GAMUT includes several n-player game families. Here we use MajorityVoting, a model of a committee in which each player votes for one of several candidates. The candidate who receives the most votes wins, and each player has a privately known preferred candidate.
Voting games naturally lend themselves to pure-strategy analysis — each player simply votes for their preferred candidate. gbt.nash.enumpure_solve searches exhaustively for pure-strategy Nash equilibria and works for games with any number of players:
[12]:
g_mv = gbt.catalog.generate_gamut(
"MajorityVoting",
params={
"int_payoffs": True,
"int_mult": 1,
"players": 3,
"actions": 3
},
gamut_jar="~/Downloads/gamut.jar",
)
g_mv.title = "Majority Voting (3 players, 3 candidates)"
g_mv
[12]:
Majority Voting (3 players, 3 candidates)
| Player2 | ||||
| 1 | 2 | 3 | ||
| Player1 | 1 | 39,54,97 | 39,54,97 | 39,54,97 |
| 2 | 39,54,97 | -42,-25,87 | 39,54,97 | |
| 3 | 39,54,97 | 39,54,97 | 32,-98,-29 | |
| Player2 | ||||
| 1 | 2 | 3 | ||
| Player1 | 1 | 39,54,97 | -42,-25,87 | 39,54,97 |
| 2 | -42,-25,87 | -42,-25,87 | -42,-25,87 | |
| 3 | 39,54,97 | -42,-25,87 | 32,-98,-29 | |
| Player2 | ||||
| 1 | 2 | 3 | ||
| Player1 | 1 | 39,54,97 | 39,54,97 | 32,-98,-29 |
| 2 | 39,54,97 | -42,-25,87 | 32,-98,-29 | |
| 3 | 32,-98,-29 | 32,-98,-29 | 32,-98,-29 | |
[13]:
result_mv = gbt.nash.enumpure_solve(g_mv)
result_mv.equilibria[0]
[13]:
