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
32 changes: 2 additions & 30 deletions doc/pygambit.api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ Representation of games
Game
Outcome
Node
Infoset
Event
Branch
Subgame

Expand Down Expand Up @@ -141,8 +139,6 @@ Information about the game
Node.prior_action
Node.prior_sibling
Node.next_sibling
Node.infoset
Node.event
Node.members
Node.actions
Node.action_probs
Expand All @@ -159,30 +155,6 @@ Information about the game
Subgame.parent
Subgame.children

.. autosummary::

:toctree: api/

Infoset.label
Infoset.game
Infoset.is_absent_minded
Infoset.player
Infoset.actions
Infoset.members
Infoset.precedes

.. autosummary::

:toctree: api/

Event.label
Event.game
Event.is_absent_minded
Event.player
Event.actions
Event.members
Event.precedes

.. autosummary::

:toctree: api/
Expand Down Expand Up @@ -357,15 +329,15 @@ Subsets of actions
BehaviorSupportProfile.__getitem__
BehaviorSupportProfile.__setitem__
BehaviorSupportProfile.copy
BehaviorSupportProfile.is_reachable
BehaviorSupportProfile.is_infoset_reachable

BehaviorSupport
BehaviorSupport.player
BehaviorSupport.__iter__
BehaviorSupport.__getitem__

ActionSupport
ActionSupport.infoset
ActionSupport.history
ActionSupport.__iter__
ActionSupport.__contains__

Expand Down
47 changes: 37 additions & 10 deletions doc/tutorials/03_stripped_down_poker.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@
"\n",
"In other words, Bob's decision when Alice Bets with a Queen should be part of the same information set as Bob's decision when Alice Bets with a King.\n",
"\n",
"To set this scenario up in Gambit, we'll need to add both possible moves as part of the same information set (represented in Gambit as an `Infoset`).\n",
"To set this scenario up in Gambit, we'll need to add both possible moves as part of the same information set.\n",
"This can be done with a single selector: `gbt.H.path(..., \"Bet\")` describes the node reached by *any* single action from the root (either card), followed by \"Bet\" -- so it matches both of Bob's decision nodes at once, joining them into one information set:"
]
},
Expand Down Expand Up @@ -356,7 +356,7 @@
"id": "f45a82b6",
"metadata": {},
"outputs": [],
"source": "for infoset, mixed_action in eqm[\"Alice\"]:\n print(\n f\"At information set {infoset.number}, \"\n f\"Alice plays Bet with probability: {mixed_action['Bet']}\"\n f\" and Fold with probability: {mixed_action['Fold']}\"\n )"
"source": "for number, (_infoset, mixed_action) in enumerate(eqm[\"Alice\"], start=1):\n print(\n f\"At information set {number}, \"\n f\"Alice plays Bet with probability: {mixed_action['Bet']}\"\n f\" and Fold with probability: {mixed_action['Fold']}\"\n )"
},
{
"cell_type": "markdown",
Expand All @@ -366,18 +366,45 @@
"We can alternatively iterate through each of a player's actions like so:"
]
},
{
"cell_type": "markdown",
"id": "9c1f6a2e",
"metadata": {},
"source": [
"Indexing the profile directly by a `Node` requires identifying it with a `Selector`, since `MixedBehaviorProfile.__getitem__` accepts only a player label or a `Selector`, not a bare `Node`.\n",
"\n",
"A `Node`'s own path of action labels back to the root builds exactly the `Selector` that matches it:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b7c1e8a4",
"metadata": {},
"outputs": [],
"source": [
"def selector_for_node(node):\n",
" labels = []\n",
" current = node\n",
" while current.parent is not None:\n",
" labels.append(current.prior_action.label)\n",
" current = current.parent\n",
" labels.reverse()\n",
" return gbt.H.path(*labels)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "83bbd3e5",
"metadata": {},
"outputs": [],
"source": [
"for node in g.get_infosets(\"Alice\"):\n",
"for number, node in enumerate(g.get_infosets(\"Alice\"), start=1):\n",
" for action in node.actions:\n",
" print(\n",
" f\"At information set {node.infoset.number}, \"\n",
" f\"Alice plays {action} with probability: {eqm[node][action]}\"\n",
" f\"At information set {number}, \"\n",
" f\"Alice plays {action} with probability: {eqm[selector_for_node(node)][action]}\"\n",
" )"
]
},
Expand Down Expand Up @@ -416,7 +443,7 @@
"id": "2966e700",
"metadata": {},
"outputs": [],
"source": "(bob_node,) = g.get_infosets(\"Bob\")\nbob_infoset = bob_node.infoset\neqm[bob_node][\"Call\"]"
"source": "(bob_node,) = g.get_infosets(\"Bob\")\neqm[selector_for_node(bob_node)][\"Call\"]"
},
{
"cell_type": "markdown",
Expand All @@ -436,7 +463,7 @@
"outputs": [],
"source": [
"bob_action_values = eqm.action_values[bob_node]\n",
"for action in bob_infoset.actions:\n",
"for action in bob_node.actions:\n",
" print(\n",
" f\"When Bob plays {action} his expected payoff is {bob_action_values[action]}\"\n",
" )"
Expand All @@ -461,7 +488,7 @@
"metadata": {},
"outputs": [],
"source": [
"for node in bob_infoset.members:\n",
"for node in bob_node.members:\n",
" print(\n",
" f\"Bob's belief in reaching the {node.parent.prior_action.label} -> \"\n",
" f\"{node.prior_action.label} node is: {eqm.beliefs[node]}\"\n",
Expand Down Expand Up @@ -504,7 +531,7 @@
"outputs": [],
"source": [
"bob_node_values = eqm.node_values[\"Bob\"]\n",
"for node in bob_infoset.members:\n",
"for node in bob_node.members:\n",
" print(\n",
" f\"The probability that the node {node.parent.prior_action.label} -> \"\n",
" f\"{node.prior_action.label} is reached is: {eqm.realiz_probs[node]}. \",\n",
Expand Down Expand Up @@ -642,7 +669,7 @@
"id": "d18a91f0",
"metadata": {},
"outputs": [],
"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()"
"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 number, node in enumerate(g.get_infosets(player), start=1):\n for action in node.actions:\n print(\n f\"At information set {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,7 +84,7 @@
"id": "6e3e9303-453a-4bac-a449-fa8fda2ba5ec",
"metadata": {},
"outputs": [],
"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)"
"source": "eq = pure_Nash_equilibria[0]\nfor behavior in eq.as_behavior():\n for number, (_infoset, probs) in enumerate(behavior, start=1):\n print(behavior.player, \"infoset:\", number, \"behavior probabilities:\", probs)"
},
{
"cell_type": "markdown",
Expand Down
8 changes: 4 additions & 4 deletions doc/tutorials/interoperability_tutorials/openspiel.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -500,9 +500,9 @@
"metadata": {},
"outputs": [],
"source": [
"for infoset, mixed_action in eqm[\"Pl0\"]:\n",
"for number, (_infoset, mixed_action) in enumerate(eqm[\"Pl0\"], start=1):\n",
" print(\n",
" f\"At information set {infoset.number}, \"\n",
" f\"At information set {number}, \"\n",
" f\"Player 0 plays action 0 with probability: {mixed_action['p0a0']}\"\n",
" f\" and action 1 with probability: {mixed_action['p0a1']}\"\n",
" f\" and action 2 with probability: {mixed_action['p0a2']}\"\n",
Expand Down Expand Up @@ -534,9 +534,9 @@
"metadata": {},
"outputs": [],
"source": [
"for infoset, mixed_action in eqm[\"Pl1\"]:\n",
"for number, (_infoset, mixed_action) in enumerate(eqm[\"Pl1\"], start=1):\n",
" print(\n",
" f\"At information set {infoset.number}, \"\n",
" f\"At information set {number}, \"\n",
" f\"Player 1 plays action 0 with probability: {mixed_action['p1a0']}\"\n",
" f\" and action 1 with probability: {mixed_action['p1a1']}\"\n",
" f\" and action 2 with probability: {mixed_action['p1a2']}\"\n",
Expand Down
Loading
Loading