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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 24 additions & 3 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@
of a game in strategic (table) representation.
- Added `Game.get_payoffs`, which returns the payoff to each player at a pure-strategy
contingency, for a game in any representation.
- Added `Game.get_strategies(player)`, `Game.get_sequences(player)`, `Game.get_min_payoff(player)`,
and `Game.get_max_payoff(player)`, replacing `Player.strategies`/`.sequences`/`.min_payoff`/
`.max_payoff` now that `Player` has been removed.

### Changed
- `Infoset` is now a lazy, node-anchored view (like `Node.player`/`Node.outcome`), constructed
Expand All @@ -53,6 +56,19 @@
- `Game.behavior_support_profile`'s `actions` filter callable is now called as
`actions(node, action)` (two positional arguments, where `node` is a representative node of
the information set and `action` is the action's label) rather than with a single `Action`.
- `Node.player` now returns the player's label (`str`), or `None` at a terminal node, directly
rather than a lazy `NodePlayer` proxy object. `Infoset.player`/`Event.player`/`Sequence.player`
now likewise return a label (`str`) rather than a `Player` object.
- `StrategySupport.player`, `BehaviorSupport.player`, `MixedStrategy.player`, and
`MixedBehavior.player` now return a label (`str`) rather than a `Player` object.
- `Game.players` now iterates player labels (`str`) rather than `Player` objects; indexing by
label is no longer supported (a label is already in hand once iterated) -- use `in` to test
membership.
- `Game.append_move`, `Game.insert_move`, `Game.reveal`, `Game.relabel_strategies`, and
`Game.set_strategies` now take `player` as a label (`str`) rather than accepting a `Player`
object.
- `Game.strategy_support_profile`'s `strategies` filter callable's `player` argument is now a
label (`str`) rather than a `Player` object.
- Command-line tools are now implemented in `pygambit` rather than C++-based compiled programs.
The `gambit-convert` utility has been removed.
- Refreshed GUI icons and standardised dialog layout and formatting
Expand All @@ -78,11 +94,16 @@
(`pip install gtdraw`) to run tutorials locally or build the documentation.
- `Game.contingencies` now yields contingencies as a mapping from player label to strategy
label, rather than a list of per-player strategy indices.
- `Player.strategies` now iterates strategy labels (`str`) rather than `Strategy` objects;
indexing by label is no longer supported (a label is already in hand once iterated) -- use
`in` to test membership.
- `Game.strategy_support_profile`'s `strategies` filter callable is now called as
`strategies(player, label)` (two positional arguments) rather than with a single `Strategy`.
- Removed `Player`. Players are now identified purely by label (`str`), as returned by iterating
`Game.players`. `Player.strategies`/`.sequences`/`.min_payoff`/`.max_payoff` are replaced by
`Game.get_strategies`/`Game.get_sequences`/`Game.get_min_payoff`/`Game.get_max_payoff`;
`Player.number` had no remaining use once labels are unambiguous (recover via
`list(game.players).index(label)` if truly needed); `Player.is_chance` and `Game.players.chance`
are removed outright, with no replacement -- test `Node.event`/`Node.infoset` truthiness
instead. `GamePlayerRep` in the C++ core is unaffected by this change (a separate, later piece
of work).
- `Game.get_behavior`'s `player` and `strategy` parameters are now labels (`str`) rather than
accepting a `Player`/`Strategy` object; `StrategyBehavior.player`/`.strategy` now return
labels rather than `Player`/`Strategy` objects.
Expand Down
17 changes: 4 additions & 13 deletions doc/pygambit.api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ Representation of games
:toctree: api/

Game
Player
Outcome
Node
Infoset
Expand Down Expand Up @@ -107,28 +106,20 @@ Information about the game
Game.outcomes
Game.min_payoff
Game.max_payoff
Game.get_min_payoff
Game.get_max_payoff
Game.root
Game.get_infosets
Game.get_events
Game.get_strategies
Game.get_sequences
Game.nodes
Game.contingencies
Game.get_outcome
Game.get_payoffs
Game.subgames
Game.minimal_subgame

.. autosummary::
:toctree: api/

Player.label
Player.number
Player.game
Player.strategies
Player.is_chance
Player.min_payoff
Player.max_payoff
Player.sequences

.. autosummary::
:toctree: api/

Expand Down
12 changes: 2 additions & 10 deletions doc/tutorials/01_quickstart.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@
"id": "9d8203e8",
"metadata": {},
"outputs": [],
"source": "tom, jerry = g.players\ng.relabel_players({tom.label: \"Tom\", jerry.label: \"Jerry\"})\n\nfor player in g.players:\n cooperate, defect = player.strategies\n g.relabel_strategies(player, {cooperate: \"Cooperate\", defect: \"Defect\"})"
"source": "tom, jerry = g.players\ng.relabel_players({tom: \"Tom\", jerry: \"Jerry\"})\n\nfor player in g.players:\n cooperate, defect = g.get_strategies(player)\n g.relabel_strategies(player, {cooperate: \"Cooperate\", defect: \"Defect\"})"
},
{
"cell_type": "markdown",
Expand Down Expand Up @@ -268,15 +268,7 @@
"id": "980bf6b1",
"metadata": {},
"outputs": [],
"source": [
"payoffs = msp.payoffs\n",
"for player in g.players:\n",
" print(f\"{player.label} plays the equilibrium strategy:\")\n",
" print(f\"Probability of cooperating: {msp[player.label]['Cooperate']}\")\n",
" print(f\"Probability of defecting: {msp[player.label]['Defect']}\")\n",
" print(f\"Payoff: {payoffs[player.label]}\")\n",
" print()"
]
"source": "payoffs = msp.payoffs\nfor player in g.players:\n print(f\"{player} plays the equilibrium strategy:\")\n print(f\"Probability of cooperating: {msp[player]['Cooperate']}\")\n print(f\"Probability of defecting: {msp[player]['Defect']}\")\n print(f\"Payoff: {payoffs[player]}\")\n print()"
},
{
"cell_type": "markdown",
Expand Down
32 changes: 5 additions & 27 deletions doc/tutorials/03_stripped_down_poker.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -82,21 +82,15 @@
"cell_type": "markdown",
"id": "d9796238",
"metadata": {},
"source": [
"In addition to the two named players, Gambit also instantiates a chance player."
]
"source": "In addition to the two named players, Gambit also instantiates a chance player internally to represent moves of chance. It isn't exposed as a value you can access directly -- `Game.players` lists only the personal players; chance moves are identified via `Node.event` instead (see below)."
},
{
"cell_type": "code",
"execution_count": null,
"id": "841f9f74",
"metadata": {},
"outputs": [],
"source": [
"print(g.players[\"Alice\"])\n",
"print(g.players[\"Bob\"])\n",
"print(g.players.chance)"
]
"source": "list(g.players)"
},
{
"cell_type": "markdown",
Expand Down Expand Up @@ -538,7 +532,7 @@
"id": "d4ecff88",
"metadata": {},
"outputs": [],
"source": "list(g.players[\"Alice\"].strategies)"
"source": "g.get_strategies(\"Alice\")"
},
{
"cell_type": "markdown",
Expand Down Expand Up @@ -597,7 +591,7 @@
"id": "56e2f847",
"metadata": {},
"outputs": [],
"source": "gnm_payoffs = gnm_eqm.payoffs\ngnm_strategy_values = gnm_eqm.strategy_values\nfor player in g.players:\n print(\n f\"{player.label}'s expected payoffs playing:\"\n )\n for strategy in player.strategies:\n print(\n f\"Strategy {strategy}: {gnm_strategy_values[player.label][strategy]:.4f}\"\n )\n print(\n f\"{player.label}'s overall expected payoff: {gnm_payoffs[player.label]:.4f}\"\n )\n print()"
"source": "gnm_payoffs = gnm_eqm.payoffs\ngnm_strategy_values = gnm_eqm.strategy_values\nfor player in g.players:\n print(\n f\"{player}'s expected payoffs playing:\"\n )\n for strategy in g.get_strategies(player):\n print(\n f\"Strategy {strategy}: {gnm_strategy_values[player][strategy]:.4f}\"\n )\n print(\n f\"{player}'s overall expected payoff: {gnm_payoffs[player]:.4f}\"\n )\n print()"
},
{
"cell_type": "markdown",
Expand All @@ -618,23 +612,7 @@
"id": "d18a91f0",
"metadata": {},
"outputs": [],
"source": [
"for player in g.players:\n",
" print(\n",
" f\"{player.label}'s expected payoffs:\"\n",
" )\n",
" gnm_action_values = gnm_eqm.as_behavior().action_values\n",
" lcp_action_values = eqm.action_values\n",
" for node in g.get_infosets(player.label):\n",
" for action in node.actions:\n",
" print(\n",
" f\"At information set {node.infoset.number}, \"\n",
" f\"when playing {action} - \"\n",
" f\"gnm: {gnm_action_values[node][action]:.4f}\"\n",
" f\", lcp: {str(lcp_action_values[node][action])}\"\n",
" )\n",
" print()"
]
"source": "for player in g.players:\n print(\n f\"{player}'s expected payoffs:\"\n )\n gnm_action_values = gnm_eqm.as_behavior().action_values\n lcp_action_values = eqm.action_values\n for node in g.get_infosets(player):\n for action in node.actions:\n print(\n f\"At information set {node.infoset.number}, \"\n f\"when playing {action} - \"\n f\"gnm: {gnm_action_values[node][action]:.4f}\"\n f\", lcp: {str(lcp_action_values[node][action])}\"\n )\n print()"
},
{
"cell_type": "markdown",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,7 @@
"id": "6e3e9303-453a-4bac-a449-fa8fda2ba5ec",
"metadata": {},
"outputs": [],
"source": [
"eq = pure_Nash_equilibria[0]\n",
"for behavior in eq.as_behavior():\n",
" for infoset, probs in behavior:\n",
" print(infoset.player.label, \"infoset:\", infoset.number, \"behavior probabilities:\", probs)"
]
"source": "eq = pure_Nash_equilibria[0]\nfor behavior in eq.as_behavior():\n for infoset, probs in behavior:\n print(infoset.player, \"infoset:\", infoset.number, \"behavior probabilities:\", probs)"
},
{
"cell_type": "markdown",
Expand Down
2 changes: 1 addition & 1 deletion doc/tutorials/interoperability_tutorials/gamut.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@
"id": "gamut-bos-gen",
"metadata": {},
"outputs": [],
"source": "g_chicken = gbt.catalog.generate_gamut(\n \"Chicken\",\n params={\n \"int_payoffs\": True,\n \"int_mult\": 1,\n \"normalize\": True,\n \"min_payoff\": 0,\n \"max_payoff\": 4,\n },\n gamut_jar=\"~/Downloads/gamut.jar\",\n)\ng_chicken.title = \"Chicken\"\nfor player in g_chicken.players:\n labels = {strategy: label\n for strategy, label in zip(player.strategies, [\"Swerve\", \"Straight\"], strict=True)}\n g_chicken.relabel_strategies(player, labels)\ng_chicken"
"source": "g_chicken = gbt.catalog.generate_gamut(\n \"Chicken\",\n params={\n \"int_payoffs\": True,\n \"int_mult\": 1,\n \"normalize\": True,\n \"min_payoff\": 0,\n \"max_payoff\": 4,\n },\n gamut_jar=\"~/Downloads/gamut.jar\",\n)\ng_chicken.title = \"Chicken\"\nfor player in g_chicken.players:\n labels = {strategy: label\n for strategy, label in zip(\n g_chicken.get_strategies(player), [\"Swerve\", \"Straight\"], strict=True\n )}\n g_chicken.relabel_strategies(player, labels)\ng_chicken"
},
{
"cell_type": "markdown",
Expand Down
4 changes: 2 additions & 2 deletions doc/tutorials/interoperability_tutorials/openspiel.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@
"id": "b684325e",
"metadata": {},
"outputs": [],
"source": "gbt_matrix_rps_game = gbt.catalog.generate_openspiel(\"matrix_rps\")\n\ngbt_matrix_rps_game.title = \"Rock-Paper-Scissors\"\n\nfor player in gbt_matrix_rps_game.players:\n names = [\"Rock\", \"Paper\", \"Scissors\"]\n labels = {strategy: name\n for strategy, name in zip(player.strategies, names, strict=True)}\n gbt_matrix_rps_game.relabel_strategies(player, labels)\n\ngbt_matrix_rps_game"
"source": "gbt_matrix_rps_game = gbt.catalog.generate_openspiel(\"matrix_rps\")\n\ngbt_matrix_rps_game.title = \"Rock-Paper-Scissors\"\n\nfor player in gbt_matrix_rps_game.players:\n names = [\"Rock\", \"Paper\", \"Scissors\"]\n labels = {strategy: name\n for strategy, name in zip(\n gbt_matrix_rps_game.get_strategies(player), names, strict=True\n )}\n gbt_matrix_rps_game.relabel_strategies(player, labels)\n\ngbt_matrix_rps_game"
},
{
"cell_type": "markdown",
Expand Down Expand Up @@ -343,7 +343,7 @@
"id": "fcd42af0",
"metadata": {},
"outputs": [],
"source": "p1_payoffs, p2_payoffs = gbt_prisoners_dilemma_game.to_arrays(dtype=float)\np1, p2 = gbt_prisoners_dilemma_game.players\nops_prisoners_dilemma_game = pyspiel.create_matrix_game(\n gbt_prisoners_dilemma_game.title,\n \"Classic Prisoner's Dilemma\", # description\n list(p1.strategies),\n list(p2.strategies),\n p1_payoffs,\n p2_payoffs\n)"
"source": "p1_payoffs, p2_payoffs = gbt_prisoners_dilemma_game.to_arrays(dtype=float)\np1, p2 = gbt_prisoners_dilemma_game.players\nops_prisoners_dilemma_game = pyspiel.create_matrix_game(\n gbt_prisoners_dilemma_game.title,\n \"Classic Prisoner's Dilemma\", # description\n gbt_prisoners_dilemma_game.get_strategies(p1),\n gbt_prisoners_dilemma_game.get_strategies(p2),\n p1_payoffs,\n p2_payoffs\n)"
},
{
"cell_type": "markdown",
Expand Down
Loading
Loading