diff --git a/doc/pygambit.rst b/doc/pygambit.rst index ce251cb5b..dba4d6a83 100644 --- a/doc/pygambit.rst +++ b/doc/pygambit.rst @@ -57,6 +57,8 @@ These tutorials assume you have read the new user tutorials and are familiar wit tutorials/interoperability_tutorials/openspiel tutorials/interoperability_tutorials/gamut + tutorials/interoperability_tutorials/sagemath_normal_form + tutorials/interoperability_tutorials/sagemath_extensive_form API documentation ---------------- diff --git a/doc/tutorials/interoperability_tutorials/sagemath_extensive_form.ipynb b/doc/tutorials/interoperability_tutorials/sagemath_extensive_form.ipynb new file mode 100644 index 000000000..cd6cdf764 --- /dev/null +++ b/doc/tutorials/interoperability_tutorials/sagemath_extensive_form.ipynb @@ -0,0 +1,1514 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "fd12d347", + "metadata": {}, + "source": [ + "# Using Gambit with SageMath: extensive form games\n", + "\n", + "A strategic form game is a table of payoffs. An **extensive form game** is a tree: players move in sequence, chance may intervene, and a player may be unable to tell apart the situations they find themselves in.\n", + "\n", + "SageMath's `ExtensiveFormGame` is a thin layer over Gambit's tree games. The tree itself, the information sets, and the equilibrium solvers are all Gambit's; what Sage adds is its own notation, exact rational arithmetic, plotting, and the rest of a computer algebra system.\n", + "\n", + "This tutorial builds a few trees, walks through the interface, and ends with a puzzle that can be solved only by Sage.\n", + "\n", + "The companion tutorial [Using Gambit with SageMath: strategic form games](sagemath_normal_form.ipynb) covers `NormalFormGame` and the strategic form interface.\n", + "\n", + "> **Requirements.** As for the companion tutorial: a SageMath build containing [sagemath/sage#42367](https://github.com/sagemath/sage/pull/42367), the optional `pygambit` package, and the **SageMath kernel**.\n", + "> The `gtdraw` section additionally needs the optional `gtdraw` package and a LaTeX installation." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "1024561a", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:16:29.873621Z", + "iopub.status.busy": "2026-08-23T17:16:29.873430Z", + "iopub.status.idle": "2026-08-23T17:16:32.679478Z", + "shell.execute_reply": "2026-08-23T17:16:32.678550Z" + } + }, + "outputs": [], + "source": [ + "from fractions import Fraction\n", + "\n", + "import pygambit as gbt" + ] + }, + { + "cell_type": "markdown", + "id": "09f9a136", + "metadata": {}, + "source": [ + "## Building a tree\n", + "\n", + "We build the Battle of the Sexes as a sequential game: Amy chooses first, Bob sees what she chose and responds.\n", + "\n", + "Two things are worth knowing before we start. A node is identified by the path of action labels leading to it, so `root.children['game']` is the node reached when Amy plays `game`. And an outcome is attached with `set_outcome`, which takes a label for the new outcome and the list of payoffs it awards." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "ae2f549a", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:16:32.681727Z", + "iopub.status.busy": "2026-08-23T17:16:32.681418Z", + "iopub.status.idle": "2026-08-23T17:16:32.698583Z", + "shell.execute_reply": "2026-08-23T17:16:32.697847Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "An extensive form game with 2 players" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "battle = ExtensiveFormGame(players=[\"Amy\", \"Bob\"])\n", + "battle.append_move(battle.root, \"Amy\", [\"game\", \"movie\"])\n", + "\n", + "for choice in [\"game\", \"movie\"]:\n", + " battle.append_move(battle.root.children[choice], \"Bob\", [\"game\", \"movie\"])\n", + "\n", + "payoffs = {(\"game\", \"game\"): [3, 2], (\"game\", \"movie\"): [1, 1],\n", + " (\"movie\", \"game\"): [0, 0], (\"movie\", \"movie\"): [2, 3]}\n", + "\n", + "for (amy, bob), payoff in payoffs.items():\n", + " battle.set_outcome(battle.root.children[amy].children[bob],\n", + " f\"{amy},{bob}\", payoff)\n", + "\n", + "battle" + ] + }, + { + "cell_type": "markdown", + "id": "15e1547c", + "metadata": {}, + "source": [ + "Because Bob observes Amy's choice, he is at a different decision point in each branch. That gives three information sets — one for Amy and one for each of Bob's two nodes — each containing a single node." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "933a455b", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:16:32.700367Z", + "iopub.status.busy": "2026-08-23T17:16:32.700175Z", + "iopub.status.idle": "2026-08-23T17:16:32.703897Z", + "shell.execute_reply": "2026-08-23T17:16:32.703235Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(3, [1, 1, 1])" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "len(battle.infosets), sorted(len(list(s.members)) for s in battle.infosets)" + ] + }, + { + "cell_type": "markdown", + "id": "68fb2823", + "metadata": {}, + "source": [ + "The `players`, `infosets`, `outcomes` and `root` properties expose the underlying Gambit objects, so anything the Gambit API can do with them is available.\n", + "`to_efg` returns the whole tree as a string in Gambit's extensive form format, which is a convenient way to see the structure that the short representation above hides." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "469abff9", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:16:32.705240Z", + "iopub.status.busy": "2026-08-23T17:16:32.705084Z", + "iopub.status.idle": "2026-08-23T17:16:32.707808Z", + "shell.execute_reply": "2026-08-23T17:16:32.707100Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "EFG 2 R \"Untitled extensive game\" { \"Amy\" \"Bob\" }\n", + "\"\"\n", + "\n", + "p \"\" 1 1 \"\" { \"game\" \"movie\" } 0\n", + "p \"\" 2 1 \"\" { \"game\" \"movie\" } 0\n", + "t \"\" 1 \"game,game\" { 3, 2 }\n", + "t \"\" 2 \"game,movie\" { 1, 1 }\n", + "p \"\" 2 2 \"\" { \"game\" \"movie\" } 0\n", + "t \"\" 3 \"movie,game\" { 0, 0 }\n", + "t \"\" 4 \"movie,movie\" { 2, 3 }\n", + "\n" + ] + } + ], + "source": [ + "print(battle.to_efg())" + ] + }, + { + "cell_type": "markdown", + "id": "28ec7be8", + "metadata": {}, + "source": [ + "## Drawing the tree\n", + "\n", + "`plot` draws the tree. The default backend uses Sage's own graphics, so it works anywhere Sage does." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "22a8dabc", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:16:32.709265Z", + "iopub.status.busy": "2026-08-23T17:16:32.709111Z", + "iopub.status.idle": "2026-08-23T17:16:33.266198Z", + "shell.execute_reply": "2026-08-23T17:16:33.265578Z" + } + }, + "outputs": [ + { + "data": { + "image/png": "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GjRoEIgWK1iwoPz73/+WatWqnRasz3TWAZkrWbLkadmitq228fTp053gFQS6D+m+lNmXZCA9AjUyPEWZfnYyP1yGFY7LtjSwXH755ZFeNc/StnO/+Gibatv64TKscFy2pfsc9WlkhECN0zRv3jxNRu2ny7Bye9mWHkzJenJO2879Eui3y7ByetmWS/c5nXQISI9AjQwHvZQvX975d8eOHX13GVZuL9si68m51G3nx8uwcnLZls6Vr3SfY6ITZISbciBDep30smXL5KeffvL1CO/s6NWrl1Nb1Fszcg11zugtLfV098033yzjx48P8yfk3bu16XSpmk3PmjUr0qsDCxGoAQCw2NnnioRv6TWtWn/VOuHy5cvl559/du67rJdf6U0BdMDLjTfeKHFxcZFeVSusWbNGJk6c6Jxp2Lhxo5w4ccIZ/a2jeHWQlF4H7OXbfYb79o56avvLL7902u3AgQPOSHqdS14zR71OPShXEJzNqVOnnFHvn376qbMf/vLLL069Wi/l0v2wU6dOcv3112dpal/4Exl1AGkw1lmSHn74Ydm5c6dcfPHFzjWu7qAePd29dOlSWb16tVSsWFGeffZZJwgF9frO77//3hlMt2jRIqlQoYJTs65Xr54UKlRI9u7d69y/+quvvnLa9c4773TaK6i1Rj2Nq3eMGj16tNNftK30/tI6ycexY8dk/fr1Tlv9+uuv0rp1a3nzzTed2bqCSPuLfpnR9tq1a5c0bNjQGch53nnnOX/funWrfPvtt7Ju3TqpXLmyPP/883LbbbcFdj8MtEjfZxP56+jRo+aWW25x7nl78803m5UrV2b63LVr15quXbs6z+3cubM5fPiwCZpRo0aZAgUKmLp165qpU6eaU6dOZfi8vXv3mhEjRpjChQub6tWrm9WrV5ug0W3WbS9SpIjTFtomGTl58qTTlnXq1DEFCxZ02jhoDh065OxTum/pPqb7WmZ0H+3SpYvzXN13dR9GsBCoA+T48eOmXbt2plChQubDDz/M8uumT59uihYtaq644opAHSReeeUV5+B4zz33mGPHjmXpNVu3bjWNGzc255xzjlmzZo0JCt1W3Wbddm2DrNC+pG2rbaxtHRS63bov6T7173//O8uv031W913dh3VfRnAQqAPk4YcfdrLDzz//PNuvXbx4sYmPjzeDBw82QaDbGxUVZR588EGT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qAEAsBiB2kd+++03KVeunPz3v//N9/e++eabZeTIkeIltBdtRb+CJxj4xoMPPmj69u2b/PvevXtNhw4dTMWKFU2BAgVM5cqVzT333GMOHjyYreWOHj3aXHbZZeacc85xfq666irz7bffpnnOmjVrTKlSpbK9bJvaSw0ePNg0btzYaa8GDRrkaLnr1683N910k6lWrZrRXezll18+7Tlea6+M2mrbtm2mU6dOpnDhwqZ06dLm3nvvNSdOnMj2sqdOnWouuOACp831/x999JGv2mr16tXmtttuc/a/+Ph4U7duXfPKK69ke7nTpk0zTZo0MSVKlHDaXPvnhAkTPN1WyBoyap84duyYvPPOO9K/f//kx6Kjo6Vz587yySefyObNm2XcuHEyb948ueuuu7K17IULF0rXrl1lwYIF8vXXX0vVqlWlffv28vPPPyc/p379+lK9enWZNGmSeLW9lDFG+vbtK7feemuOl3306FGpUaOGPPfcc1KhQoUMn+Ol9sqorRITE+W6666TI0eOyFdffSWTJ0+WadOmyYMPPpitZWt/0rbu2bOnrFmzxvn/LbfcIt9++61v2mrFihVStmxZmThxonz33XcydOhQeeyxx+T111/P1rJLlSrlvFbbbO3atdKnTx/nZ86cOZ5sK2RDFgM6LKfftsuUKXPW5/3zn/90vtnnRkJCgilWrJgZP358msefeuopc/nllxs/tNewYcNynFGnpll1Rhm1l9oro7b69NNPTXR0tPn555+TH/vggw9MwYIFs5XN3XLLLeaaa65J85ieBdIM1C9tlZGBAweaNm3a5Pr9GjVqZJ544glPthWyjozaJ7744gtp2rTpGZ/zyy+/yEcffSStW7fO1Xtpxnjq1CnnG35qzZs3l6VLl8qJEyfED+2V17zSXhm1lWZ19erVk3PPPTf5sQ4dOjjbohlkVuly9OxMarqcJUuW+KatMnLw4MHT9p/s0DM/8+fPl02bNskVV1zhybZC1hGofUIHkKU+aKamp60LFy4slSpVkuLFi8vbb7+dq/d69NFHnWVdffXVaR7Xx/Tg8Ouvv4qX2yu/eKW9MmorXefy5cuneaxkyZJSoECBbG1PRsvR39Mvw8ttldGXkw8//FAGDBiQ7eVrgC9atKjTzlp6eO2116Rdu3aebCtkHYHaJ7Q2Fh8fn+HfXn75ZVm5cqVMnz5dtm7dKg888ECO3+f555+XDz74wMnM079foUKFkjNuL7dXfvFKe2XWVlFRURlmehk9fibpn5/RMrzeVi6tUeu4kSeffPK0AJsVxYoVk9WrV8uyZcvkmWeecfZlHUPixbZC1sVm47mwWJkyZWT//v0Z/k0HNOlP3bp1pXTp0nL55ZfLX//6V6lYsWK23uPFF1+UESNGOAPSdNBKevv27XP+rwNnvNxe+cUr7ZVRW2l/Sj3gS+lztCSSPkM+E11O+sxv9+7dpy3Dy23l+v7776Vt27Zyxx13yBNPPJGj5esA0Vq1ajn/btiwoWzYsEGeffZZufLKKz3XVsg6MmqfaNSokXMgOBvNVlR261cvvPCCDB8+XP7zn/9kWoNbv369VK5c2TlY+aW98pJX2iujtmrRooWz/rt27Up+7LPPPpOCBQtKkyZNsrxsXc7cuXPTPKbLadmypW/ays2k27RpI7169XIy4XDR/Tn9vuyVtkI2ZGPgGSy2du1aExsba/bt25f82KxZs8y7775r1q1bZ3766Sfn94suusi0atUqW8v+xz/+4Vzjqte77tq1K/nn0KFDaZ7Xq1ev06619VJ7qS1btphVq1aZAQMGmNq1azv/1p/sXB+sz3Vfp9ewP/TQQ86/ddlebK+M2kpH/terV8+5pn7lypVm3rx5ztUEgwYNytayFy9ebGJiYsxzzz1nNmzY4Pxf3+ubb77xTVvpdfVly5Y13bt3T7P/7N69O1vLHjFihPnss8/M1q1bnbZ66aWXnPcaM2aMJ9sKWUeg9pFLL73U/N///V/y759//rlp0aKFM0GCTrRw/vnnm0ceecTs378/zev0+9rYsWMzXa47cUf6H72EyXXs2DFTvHhx8/XXXxuvtpdq3bp1htuqX3Sy2l763IyWocv2antl1FY64cl1111nChUq5EyyoUH6+PHjaZ5ztrZSU6ZMMXXq1DFxcXHOZCB6iVNqXm8r3U8y6g+6X2WnrYYOHWpq1arl7MslS5Z09u3Jkyd7uq2QNQRqH9GMWWd2SkxMzPJrNKjot/LNmzfn6r1ff/11065dO+MltBdtRb+CFzCYzEeuvfZa2bJlizNjWJUqVbL0Gq0533nnnXL++efn6r3j4uKcS0W8hPairehX8IIojdaRXgkAAJAxRn0DAGAxAjUAABYjUAMAYDECNQAAFiNQAwBgMQI1AAAWI1ADAGAxAjUAABYjUAMAYDECNQAAFiNQAwBgMQI1AAAWI1ADAGAxAjUAABYjUAMAYDECNQAAFiNQAwBgMQI1AAAWI1ADAGAxAjUAABYjUAMAYDECNQAAFiNQAwBgMQI1AAAWI1ADAGAxAjUAABYjUAMAYDECNQAAFiNQAwBgMQI1AAAWI1ADAGAxAjUAABYjUAMAYDECNQAAFiNQAwBgMQI1AAAWI1ADAGAxAjUAABYjUAMAYDECNQAAFiNQAwBgMQI1AAAWI1ADAGAxAjUAABYjUAMAYDECNQAAFiNQAwBgMQI1AAAWI1ADAGAxAjUAABYjUAMAYDECNQAAFiNQAwBgMQI1AAAWI1ADAGAxAjUAABYjUAMAYDECNQAAFiNQAwBgMQI1AAAWI1ADAGAxAjUAAGKv/wfdyRGI4rx/NwAAAABJRU5ErkJggg==", + "text/plain": [ + "Graphics object consisting of 20 graphics primitives" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "battle.plot(backend=\"sage\")" + ] + }, + { + "cell_type": "markdown", + "id": "c29ffa88", + "metadata": {}, + "source": [ + "The `'gtdraw'` backend instead produces a TikZ picture, which is what you want for a paper: it is vector output with real LaTeX typesetting. It returns a picture object whose LaTeX source you can paste into a document, and which can also be rendered to PDF, SVG or PNG.\n", + "Rendering compiles the source, so it needs a LaTeX installation on the kernel's `PATH` (`pdflatex`), plus `pdftocairo` from poppler for SVG and PNG. The cell below checks for both and skips the rendering if they are missing; `picture.content()` is the full source either way." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "2df55a18", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:16:33.267589Z", + "iopub.status.busy": "2026-08-23T17:16:33.267366Z", + "iopub.status.idle": "2026-08-23T17:16:33.281307Z", + "shell.execute_reply": "2026-08-23T17:16:33.280686Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "% TikZ code with built-in styling for game trees\n", + "% TikZ libraries required for game trees\n", + "\\usetikzlibrary{shapes}\n", + "\\usetikzlibrary{arrows.meta}\n", + "\n", + "% Style settings for game tree formatting\n" + ] + } + ], + "source": [ + "picture = battle.plot(backend=\"gtdraw\")\n", + "print(\"\\n\".join(picture.content().splitlines()[:6]))" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "1dde74fc", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:16:33.282632Z", + "iopub.status.busy": "2026-08-23T17:16:33.282468Z", + "iopub.status.idle": "2026-08-23T17:16:35.220399Z", + "shell.execute_reply": "2026-08-23T17:16:35.219647Z" + } + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from shutil import which\n", + "\n", + "from IPython.display import SVG\n", + "\n", + "if which(\"pdflatex\") and which(\"pdftocairo\"):\n", + " display(SVG(filename=picture.svg(view=False)))\n", + "else:\n", + " print(\"pdflatex and pdftocairo are not both on PATH; skipping the rendering.\")" + ] + }, + { + "cell_type": "markdown", + "id": "7ba40bdc", + "metadata": {}, + "source": [ + "## Information sets\n", + "\n", + "Now suppose Amy and Bob choose *simultaneously*. The tree is the same shape, but Bob no longer knows which branch he is in: his two nodes have to be bundled into a single information set.\n", + "\n", + "`append_infoset` does that. Instead of giving Bob a fresh move at the second node, we say that the node belongs to the same information set as an existing one." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "6e0e6e2d", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:16:35.222053Z", + "iopub.status.busy": "2026-08-23T17:16:35.221853Z", + "iopub.status.idle": "2026-08-23T17:16:35.227479Z", + "shell.execute_reply": "2026-08-23T17:16:35.226831Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(2, [1, 2])" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "simultaneous = ExtensiveFormGame(players=[\"Amy\", \"Bob\"])\n", + "simultaneous.append_move(simultaneous.root, \"Amy\", [\"game\", \"movie\"])\n", + "simultaneous.append_move(simultaneous.root.children[\"game\"], \"Bob\",\n", + " [\"game\", \"movie\"])\n", + "simultaneous.append_infoset(simultaneous.root.children[\"movie\"],\n", + " simultaneous.root.children[\"game\"])\n", + "\n", + "for (amy, bob), payoff in payoffs.items():\n", + " simultaneous.set_outcome(simultaneous.root.children[amy].children[bob],\n", + " f\"{amy},{bob}\", payoff)\n", + "\n", + "len(simultaneous.infosets), sorted(len(list(s.members))\n", + " for s in simultaneous.infosets)" + ] + }, + { + "cell_type": "markdown", + "id": "abc8a31e", + "metadata": {}, + "source": [ + "Two information sets now, one of which contains two nodes. Sage can also confirm that the game has perfect recall, meaning no player ever forgets something they previously knew — an assumption every one of Gambit's solvers relies on." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "97932afe", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:16:35.228945Z", + "iopub.status.busy": "2026-08-23T17:16:35.228763Z", + "iopub.status.idle": "2026-08-23T17:16:35.231957Z", + "shell.execute_reply": "2026-08-23T17:16:35.231358Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "simultaneous.is_perfect_recall" + ] + }, + { + "cell_type": "markdown", + "id": "839852c9", + "metadata": {}, + "source": [ + "That single change to the information structure changes the answer.\n", + "`obtain_nash` sends the game to a Gambit solver and hands back one profile per equilibrium; we read off what each is worth to each player, exactly, with `QQ`." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "dc5db809", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:16:35.233295Z", + "iopub.status.busy": "2026-08-23T17:16:35.233157Z", + "iopub.status.idle": "2026-08-23T17:16:35.275705Z", + "shell.execute_reply": "2026-08-23T17:16:35.275246Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "sequential [[3, 2], [3, 2], [2, 3]]\n", + "simultaneous [[3, 2], [2, 3]]\n" + ] + } + ], + "source": [ + "def payoff_table(game, equilibria):\n", + " return [[QQ(eq.payoff(player)) for player in game.players]\n", + " for eq in equilibria]\n", + "\n", + "\n", + "print(\"sequential \", payoff_table(battle,\n", + " battle.obtain_nash(algorithm=\"enumpure\")))\n", + "print(\"simultaneous\", payoff_table(simultaneous,\n", + " simultaneous.obtain_nash(algorithm=\"enumpure\")))" + ] + }, + { + "cell_type": "markdown", + "id": "035299df", + "metadata": {}, + "source": [ + "When Bob moves second he can condition on Amy's choice, and there are three pure equilibria (two of which end at the same outcome). When the players move simultaneously, only two survive." + ] + }, + { + "cell_type": "markdown", + "id": "56e531a8", + "metadata": {}, + "source": [ + "### Behaviour and mixed strategy profiles\n", + "\n", + "By default the solvers work directly on the tree, and an equilibrium comes back as a **behavior profile**: it gives, for every action, the probability of playing it *conditional on reaching that information set*. Index it by an action, an information set or a player.\n", + "\n", + "Passing `use_strategic=True` solves the reduced strategic form instead, and an equilibrium comes back as a **mixed strategy profile** over complete contingent plans. The two are indexed differently and are not interchangeable — indexing one the way you would index the other raises a `TypeError`." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "53bf7311", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:16:35.277323Z", + "iopub.status.busy": "2026-08-23T17:16:35.277144Z", + "iopub.status.idle": "2026-08-23T17:16:35.281137Z", + "shell.execute_reply": "2026-08-23T17:16:35.280515Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "behavior, by action [1, 0, 1, 0, 1, 0]\n", + "mixed, by strategy [1, 0, 0, 0]\n" + ] + } + ], + "source": [ + "behavior = battle.obtain_nash(algorithm=\"enumpure\")[0]\n", + "mixed = battle.obtain_nash(algorithm=\"enumpure\", use_strategic=True)[0]\n", + "\n", + "game = battle._gambit_()\n", + "print(\"behavior, by action \", [QQ(behavior[a]) for a in game.actions])\n", + "print(\"mixed, by strategy \", [QQ(mixed[s]) for s in game.players[\"Bob\"].strategies])" + ] + }, + { + "cell_type": "markdown", + "id": "2b75e1c9", + "metadata": {}, + "source": [ + "The choice of algorithm is separate. `'lcp'` is the default for a game with at most two players and `'enumpoly'` for more; `'lp'` (constant sum, two players), `'enumpure'`, `'logit'` and `'liap'` are also available.\n", + "\n", + "As in the strategic form, `obtain_nash` answers with exact rationals by default. `'lcp'` and `'lp'` are asked to compute exactly throughout, while the numerical solvers compute in floating point and have their answer rounded to the exact equilibrium it approximates, once Gambit has confirmed in exact arithmetic that it is one. `rational=False` returns the raw floating point answer, and `tolerance` controls how far a probability may be moved to be rounded." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "cfe68ddf", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:16:35.282362Z", + "iopub.status.busy": "2026-08-23T17:16:35.282212Z", + "iopub.status.idle": "2026-08-23T17:16:35.296280Z", + "shell.execute_reply": "2026-08-23T17:16:35.295715Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "rational=True [[1, 0, 1, 0, 0, 1]]\n", + "rational=False [[0.9999999867182776, 1.3281724096823341e-08, 0.999999986718284, 1.3281717697986011e-08, 2.342948554313063e-24, 1.0]]\n" + ] + } + ], + "source": [ + "for rational in [True, False]:\n", + " equilibria = battle.obtain_nash(algorithm=\"logit\", rational=rational)\n", + " print(f\"rational={str(rational):5s}\",\n", + " [[QQ(eq[a]) if rational else eq[a] for a in game.actions]\n", + " for eq in equilibria])" + ] + }, + { + "cell_type": "markdown", + "id": "215c3289", + "metadata": {}, + "source": [ + "## Chance moves\n", + "\n", + "Real games often start with a deal, a roll, or some other move by nature. `append_chance_move` adds one. Its probabilities are optional and default to a uniform distribution over the actions, held exactly; `set_chance_probs` changes them afterwards.\n", + "\n", + "Here is a miniature poker game. Nature deals Alice a high or low card. Alice sees it and either bets or checks. Bob does *not* see the card — his two nodes go into one information set — and either calls or folds.\n", + "\n", + "Two of the leaves award the same payoffs, namely those where Bob folds. Giving `set_outcome` an outcome the game already has, rather than a label and a fresh list of payoffs, awards that same outcome at another leaf instead of creating a duplicate." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "8528d0b7", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:16:35.297555Z", + "iopub.status.busy": "2026-08-23T17:16:35.297400Z", + "iopub.status.idle": "2026-08-23T17:16:35.304306Z", + "shell.execute_reply": "2026-08-23T17:16:35.303792Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(['1/2', '1/2'], 5)" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "poker = ExtensiveFormGame(players=[\"Alice\", \"Bob\"])\n", + "poker.append_chance_move(poker.root, [\"High\", \"Low\"])\n", + "\n", + "for card in [\"High\", \"Low\"]:\n", + " poker.append_move(poker.root.children[card], \"Alice\", [\"bet\", \"check\"])\n", + "\n", + "poker.append_move(poker.root.children[\"High\"].children[\"bet\"], \"Bob\",\n", + " [\"call\", \"fold\"])\n", + "poker.append_infoset(poker.root.children[\"Low\"].children[\"bet\"],\n", + " poker.root.children[\"High\"].children[\"bet\"])\n", + "\n", + "poker.set_outcome(poker.root.children[\"High\"].children[\"bet\"].children[\"call\"],\n", + " \"High,bet,call\", [2, -2])\n", + "poker.set_outcome(poker.root.children[\"Low\"].children[\"bet\"].children[\"call\"],\n", + " \"Low,bet,call\", [-2, 2])\n", + "\n", + "poker.set_outcome(poker.root.children[\"High\"].children[\"bet\"].children[\"fold\"],\n", + " \"Bob folds\", [1, -1])\n", + "poker.set_outcome(poker.root.children[\"Low\"].children[\"bet\"].children[\"fold\"],\n", + " \"Bob folds\")\n", + "\n", + "poker.set_outcome(poker.root.children[\"High\"].children[\"check\"],\n", + " \"High,check\", [1, -1])\n", + "poker.set_outcome(poker.root.children[\"Low\"].children[\"check\"],\n", + " \"Low,check\", [-1, 1])\n", + "\n", + "[str(action.prob) for action in poker.root.infoset.actions], len(poker.outcomes)" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "45db887f", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:16:35.305525Z", + "iopub.status.busy": "2026-08-23T17:16:35.305368Z", + "iopub.status.idle": "2026-08-23T17:16:35.370348Z", + "shell.execute_reply": "2026-08-23T17:16:35.369524Z" + } + }, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAhwAAAKUCAYAAABPHeHJAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjksIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvJkbTWQAAAAlwSFlzAAAPYQAAD2EBqD+naQAAYylJREFUeJzt3Qd4FNX6x/E3hQ5SpUoRQSnSOzYQK+oVsYAFQRC9V4p6LVixYMPuVUERBBEVUVBBFESlKKAUQXoHKYLSlSIlOf/nPfufkIQkbJKd7M7M9/M8AbJldnI42fntmfeciTPGGAEAAHBRvJsbBwAAIHAAAIA8wQgHAABwHYEDAAC4jsABAABcR+AAAACuI3AAAADXETgAAIDrCBwAAMB1BA4AAOA6AgcAAHAdgQMAALiOwAEAAFxH4AAAAK4jcAAAANcROAAAgOsIHAAAwHUEDgAA4DoCBwAAcB2BAwAAuI7AAQAAXEfgAAAAriNwAAAA1xE4AACA6wgcAADAdQQOAADgOgIHAABwHYEDAAC4jsABAABcR+AAAACuI3AAAADXETgAAIDrCBwAAMB1BA4AAOA6AgcAAHAdgQMAALiOwAEAAFxH4AAAAK4jcAAAANcROAAAgOsIHAAAwHUEDgAA4DoCBwAAcB2BAwAAuI7AAQAAXEfgAAAAriNwAAiEuLg4+fzzz6O9G0BgETgA+MK2bdukT58+Ur16dSlQoIBUrlxZrrjiCvnuu++ivWsARCSRVgDgdRs2bJCzzjpLSpQoIc8//7zUr19fjhw5IpMnT5ZevXrJihUror2LQOAxwgHA8+644w57ymTOnDlyzTXXyOmnny5169aV//73v/LTTz+lPG7Hjh1y1VVXSeHChaVmzZoyfvz4lPuSkpKkR48ecuqpp0qhQoXkjDPOkNdeey3N63Tr1k06dOggL774olSoUEFKly5tA42GG8ehQ4fk/vvvtyMsOtKirzNs2LCU+5ctWybt27eXokWLSrly5aRLly52vwC/I3AA8LRdu3bJpEmT7IG/SJEix92vox6OJ554Qq677jpZtGiRPejfeOON9vkqOTlZTjnlFBkzZowNBf3795eHHnrIfp/a1KlTZe3atfbv9957T0aMGGG/HDfffLOMHj1a/ve//8ny5cvlrbfesuFCbd26Vc477zxp2LChzJs3z+73H3/8YfcJ8Ls4Y4yJ9k4AQE7pqEaLFi1k3LhxdvQiMzoC8sgjj8iAAQPs9/v375dixYrJV199JZdcckmGz9EQo4Hg008/TRnhmDZtmg0cCQkJ9jYNC/Hx8TZkrFq1yo6MTJkyRS644ILjtqch5ueff7anehybN2+2oyErV660IzOAX1HDAcDTnM9MGihORGs7HDoaooHjzz//TLlNRyOGDh0qv/32mxw8eFAOHz5sRyNS01M1TthQempl8eLF9t8LFy609+koRkbmz59vR0acEY/UNMQQOOBnBA4AnqY1Eho29PSF1ldkJV++fGm+1+fpqRSlp07uvvtueemll6RVq1Y2jLzwwgt2RCLcbWjtR1b0cTpzZuDAgcfdp8EF8DMCBwBPK1WqlFx88cXy5ptvSt++fY+r49izZ0+aOo7M/PDDD9K6dWtbgJp61CE76tWrZ0PF9OnTMzyl0rhxYxk7dqxUq1ZNEhN5+0WwUDQKwPMGDRpkZ5k0b97cHtBXr15tRzy0cFNHK8JRo0YNW8ip9RVai/Hoo4/K3Llzs7UfGiS6du0q3bt3t4uMrV+/3tZ8OIWnWhOiRarXX3+9rT1Zt26dfPPNN/bxuv+AnxE4AHieTmX95ZdfpG3btnLPPffImWeeKRdeeKFd9Gvw4MFhbePf//63dOzYUTp16mSLUHfu3JlmtCNc+no6NVefW6tWLenZs6ctUFUVK1aUmTNn2nChozK6n3feeacUL17cFp4CfsYsFQAA4DoiNQAAcB2BAwAAuI7AAQAAXEfgAAAAriNwAAAA1xE4AACA6wgcAADAdQQOAADgOgIHAABwHYEDAAC4jsABAABcR+AAAACuI3AAAADXETgAAIDrEt1/CQA45uDBg/Ltt9/KvHnzZM2aNXL06FEpVaqUNG7cWNq0aSM1a9akuQAfijPGmGjvBAD/++uvv+Tpp5+WoUOHyq5du6RkyZJy2mmnSWJiouzcuVPWrl0rycnJ0q5dO+nfv7+ce+650d5lABFE4ADgumnTpkmXLl1k9+7dcs0118jVV18t1apVk7i4uJTHHDhwQL7//nsZNWqULF26VHr16iUvvfSSFChQgP8hwAcIHABcNX78eBsyGjVqJAMGDJCKFStm+Xgd5fjoo4/k5ZdflrZt28oXX3xB6AB8gMABwDVLliyRpk2b2tMjAwcOlHz58oX93NmzZ0vv3r2la9euMmTIEP6XAI8jcABwhRaDtmrVyp5G+fjjj3M0SjFmzBg7KjJ58mS56KKLXNlPAHmDwAHAFePGjbO1Gu+//740bNgwR9vQmvZu3brZkZGffvop4vsIIO+wDgcAVwwaNMgGjZyGDaVFpTfffLP8/PPPsmDBgojuH4C8ReAAEHGHDx+WH374QS655JJcb+u8886TQoUKyXfffReRfQMQHQQOABGn01o1dNStWzfX29J1OmrVqiW//PJLRPYNQHQQOABE3Pbt2+3f5cqVi8j2ypYtK3/++WdEtgUgOggcACL/xhIfnzJTJRJ0bY7Ui4QB8B4CB4CIq169uv17w4YNEdmebqdGjRoR2RaA6CBwAIi4U0891V4rJRIzS/bu3Wuvs9KkSZOI7BuA6CBwAIg4Pf3RsWNHmTBhQq5Pq+jS5gkJCXLFFVdEbP8A5D0CBwBX6MXXtm3bZhcAy6m///5bRo4caa/FEqkCVADRQeAA4Aq9WNutt95qL8K2cePGHK0y+txzz9mryOrfALyNwAHANXp5+QoVKshtt90mmzZtylbYeOWVV+yVZt944w2pUqUK/0uAxxE4ALjmpJNOsiuE6kqhnTp1ks8++8xOcc3Kli1bbEAZPny4vPrqq3ZpcwDex8XbALhOrxh79913y3vvvSdVq1aVq666Sho3bmynz+qF2Xbu3GlXJ50yZYp8//33Ur58eXn33Xflwgsv5H8H8InEaO8AAP/TKbIaMtasWWMDx+DBg+XQoUPHPa527drSo0cPu+5Gu3btorKvANzBCAcA1+nUWL0eSv369e2sFb3Oio5orF692t5XunRpW2SqS5jrZehbtWolY8aMkWuvvZb/HcAnCBwAXDdixAi55ZZb7EJg4VyuXq8yu3nzZlm0aFHKMukAvI3AASBPRzfCMXv2bGndujWjHICPEDgAxNTohoNRDsBfCBwAYmp0w8EoB+AvBA4AMTe64WCUA/APAgeAmBvdcDDKAfgHgQNATI5uOBjlAPyBwAEgJkc3HIxyAP5A4AAQs6MbDkY5AO8jcACI2dENB6McgPcROADE9OiGg1EOwNsIHABienTDwSgH4G0EDgAxP7rhYJQD8C4CB4CYH91wMMoBeBeBA4AnRjccjHIA3kTgAOCJ0Q0HoxyANxE4AHhmdMPBKAfgPQQOAJ4Z3XAwygF4D4EDgKdGNxyMcgDeQuAA4KnRDQejHIC3EDgAeG50w8EoB+AdBA4AnhvdcDDKAXgHgQOAJ0c3HIxyAN5A4ADgydENB6McgDcQOAB4dnTDwSgHEPsIHAA8O7rhYJQDiH0EDgCeHt1wMMoBxDYCBwBPj244GOUAYhuBA4DnRzccjHIAsYvAAcDzoxsORjmA2EXgAOCL0Q0HoxxAbCJwAPDF6IaDUQ4gNhE4APhmdMPBKAcQewgcAHwzuuFglAOIPQQOAL4a3XAwygHEFgIHAF+NbjgY5QBiC4EDgO9GNxyMcgCxg8ABwHejGw5GOYDYQeAA4MvRDQejHEBsIHAA8OXohoNRDiA2EDgA+HZ0w8EoBxB9BA4Avh3dcDDKAUQfgQOAr0c3HIxyANFF4ADg69ENB6McQHQROAD4fnTDwSgHED0EDgC+H91wMMoBRA+BA0AgRjccjHIA0UHgABCI0Q0HoxxAdBA4AARmdMPBKAeQ9wgcQMAFaXTDwSgHkPcIHEDABW10w8EoB5C3CBxAgAVxdMPBKAeQt+Lz+PUAxJCvvvpKTjrpJHn22WclaFq1aiW9evWSMWPGSHJycrR3B/A9RjgAAIDrGOEAAACuI3AAAADXETgAAIDrCBwAAMB1BA4AAOA6AgcQI0aMEClRInvP6dZNpEOHnL3eueeKfPihuO7ee0X69hXP+v57kVq1RNyeOfvnnyInnyyyZYu7rwNEC4EDcFlmoWDaNJG4OJE9e0Lfd+oksmpV3vx3fPmlyLZtIp07H7ttyBCRNm1ETjop7X6ld/CgSOHCIitWiOhaYRdeGDpQ6vNatRKZPDnt4++/X2T4cJH167O/n7kJVJGi+//wwyLx//9uuXWryA03iJxxRui2u+7K/LmPPx5q4127RPr0CT1H265KlVAI27v32GPLlhXp0kXkscfc/5mAaCBwADGiUKHQQScv/O9/Irfccuwgqg4c0OW+RR56KOvnTpkiUrly6FP/jBmhwPHVVyLz54u0bStyxRUiCxYce7z+TBddJPLWW+I5s2aJrF4tcu21x247dCgUsDSENGiQ9fPHjxe58kqR338Pfb34osjixaHRrEmTRHr0SPt4/T/54AOR3bvd+XmAaCJwADF8SuWpp0IH7GLFRG69VeSBB0QyutyJHsgqVBApXVqkVy+RI0cyf50dO0S+/VbkX/9Ke7t+Utftt2yZ9X5+8cWx5776amgEoFkzkZo1RZ55JvT3hAlpn6OP/+gjibjp00WaNxcpUCD08+v+Hz0auk/3QdvTORWycGFo5Oa++449//bbRa6/PvPtjx4dCksFCx67rVo1kddeE7n5ZpHixTN/7qZNIkuWiFx6qciZZ4qMHRsKY6edJnL++SJPPx3aR2d/Vb16IuXLi3z2Wc7bBIhVBA4gRuknXT0oDRwYGj3QYfjBg49/3NSpImvXhv5+771QcNGvzPz4Y2hYv3bt7O+THrz1dIx+as/s/r//FilVKu3tGgr0APzbbxIxWuvQvn0o7Pz6a6hthg0LhTSnRkX3xRlt0XBSpkzo79Sntc47L/PX0BGcpk1ztn86uqH7kFldjp5O0dNQiYnHt9UPP+TsNYFYRuAA8oAepIsWTfuln3yz8vrroSF3HWY//XSR/v1Dn4DTK1lS5I03Qqc4Lr9c5LLLRL77LvPtbtggUq5c2tMp4frpp1CoaN064/tfeklk/36R665Le3ulSsdeO1IGDQqd2nF+dq31eOKJ0D7oPurog44GaahQ+vfdd4fCiQYRrWHRmhmtW8mM7m/FijnbPx0JyiyY7dwpMmBAaIQlPW2rSLYTECsIHEAe0NoGHdJP/TV0aNbPWbky9Gk3tfTfq7p1RRISjn2vpxZ0xkNmtOgz9SmC7B5ENdRkFFb0lIkWSX788fG1KFqf4tSJRMry5aEiVT1N4jjrLJF9+0Q2bw59r2FCg4YxoVEDDQB6ekNHeXRESIOXhpVIt9Vff4VGUtKftnLu01BYp07GBaLaVpFsJyBWpBvMA+CGIkVEatRIe5tzUMxK6oOp0gNnevnyHf+crKZw6mmFnBYl6mmCjC4sqyFDR2M++UTkgguOv19naSgttowUbYvM2se5XQOHnmbRUQ0NSXqQ11MoGga0DbI6nZKbtvr669Apq6pV096uIytamKsjXFqnkf7/zmmrSLYTECsY4QBilE6hnDMn7W3z5uV+u40ahU4nZPdAqrM1dKhfiyjTj2zo9FVd00M/uWdEiyf14KqjMZGi4UFnkaQOYfq9Ftg6p3CcOg4tbtVwoUFE/9ZRjxPVbzhttWxZ9vctdWFt6pENbbv8+UPBLbORE20rfV3AbwgcQIzSdRv007kWgurBXoshFy06/lN9dunBTD9Bz5yZ9nYNIXqqZ82a0Pc6fVO/d0Yn9CCqoxdacJo6bOhsDa2b0Nktug39Sr2+hNLTGeecc+zUSnbottKfjtq4UeSOO0KFqNpOuiaI7p+eovjvf4+d8nHqOEaNOlaroSHkl19OXL+hLr44dPolPWc/9PTN9u2hfzvBRGed6AhH6voNDT0aNrS+Rf9PNXw4bZWUdOxxeipFC4TThzrAFwwAV3XtasyVVx5/+9Sp+tncmN27Q98PH25M8eJpH/Pkk8aUKWNM0aLGdO9uTN++xrRsmfW277zTmPPOy3qfHnjAmM6d09722GOh/Un/pfulzj7bmHfeSfscfZ2MnqP7ldrppxvz0Ucm23Q7WW1/2jRjmjUzJn9+Y8qXN6ZfP2OOHEm7jXvuCT1nyZJjtzVoYMzJJxuTnJz16+/aZUyhQsasWJH29oz2qWrV0H3ffmvMKadk/H+d0df69cce9+GHxpxxRvbbCfCCOP0j2qEHQHh0kS1dp+H993PXYn/8ETq9oZ+m09cZZLZ2hxaj6oiCvn52TJwYWvtCR2fSTwH1Al1nREdZ3n47vMfrCqI6yqGzaLJLi4J1PRRdyRTwGw/++gPBoMPrujqnDuvrLBQ9faELdulKn7mlszN0aF9PTYQTOPS0yssvZz9sKD2NoEubezFsKF1R9M03Q6c+Us8GyozOgtHZM9mlM4uuuSbrhcgAL2OEA4hROiVTV6bUegNdTluLSB95RKRjx2jvGQBkH4EDAAC4jlkqAADAdQQOAADgOgIHAABwHYEDAAC4jsABAABcR+AAfODo0aNy5ZVXyr333hvtXfG9RYsWSePGjWVKJBZEAQKEabGAD7z33nvSrVs3WbBggTTUi4fAVZdccols3rzZho9458ItALJE4AB8MLpRq1YtqV+/vowbNy7auxMIs2fPltatW8uYMWPk2muvjfbuAJ5A4AA8jtGN6GCUA8geAgfgYYxuRA+jHED2EDgAD2N0I7oY5QDCR+AAPIrRjehjlAMIH4ED8ChGN2IDoxxAeAgcgAcxuhE7GOUAwkPgADyI0Y3YwigHcGIEDsBjGN2IPYxyACdG4AA8htGN2MQoB5A1AgfgIYxuxC5GOYCsETgAD2F0I7YxygFkjsABeASjG7GPUQ4gcwQOwCMY3fAGRjmAjBE4AA9gdMM7GOUAMkbgADyA0Q1vYZQDOB6BA4hxjG54D6McwPEIHECMY3TDmxjlANIicAAxjNEN72KUA0iLwAHEMEY3vI1RDuAYAgcQoxjd8D5GOYBjCBxAjGJ0wx8Y5QBCCBxADGJ0wz8Y5QBCCBxADGJ0w18Y5QAIHEDMYXTDfxjlAETiaQRE07Rp0yQuLk727Nljvx8xYoSUKFEi0P8pH3zwgaxdu1b69+8f7V1BhLRq1UouvvhieeKJJyQ5Odkz7crvJyKJwAHXzZo1SxISEuyw8ol06tRJVq1a5er+DBkyRNq0aSMnnXRSmrATK6MbAwYMkKuuukoaNmwY7d1BBD322GOydOlSGTt2bEy1ayz9fu7atUv69OkjZ5xxhhQuXFiqVKkiffv2lb1797r2msg7BA647t1337VvIj/++KNs3Lgxy8cWKlRIypYt6+r+HDhwwL65PvTQQxJrGN3wr1gd5Yil38/ff//dfr344ouyePFiO+I5adIk6dGjh2uviTxkABft27fPFCtWzKxYscJ06tTJPPHEE2nunzp1qtFuuHv3bvv98OHDTfHixdM85osvvjBNmjQxBQoUMKVLlzZXXXVVyn2HDh0y9913n6lYsaIpXLiwad68ud1mONK/drQdOXLEnHbaaWl+PvjLrFmzbJ8bM2aMiQWx/Pvp0LbKnz+//f2AtzHCAVd9/PHHdnhUv2666SYZPny4htywnz9x4kTp2LGjXHbZZbJgwQL57rvvpGnTpin333LLLTJz5kwZPXq0LFq0SK699lo7erF69WrxGkY3/C/WRjm88Pupp1P09GdiYmK2fz7EmGgnHvhb69atzauvvmr/rZ9QypQpY6ZMmRL2J6hWrVqZG2+8McNtr1mzxsTFxZktW7akub1du3bmwQcf9NQIB6MbwRFLoxyx/PupduzYYapUqWIefvjhHP18iC2McMA1K1eulDlz5kjnzp3t9/oJRYvO9JxxuBYuXCjt2rXL8L5ffvnFfho7/fTTpWjRoilf06dPt7M8vITRjeCIlVGOWP/9/Ouvv+zISZ06dWzBLbyPMSq4ZtiwYXbWRaVKlVJu0zegfPnyye7du6VkyZIn3IYWqWVG36y1un7+/Pn279T0jc0rmJkSPHoAbd26tZ2xoqcZoiGWfz///vtve+pFH/fZZ5/ZfYL3McIBV+gb2ciRI+Wll16yn4Kcr19//VWqVq1qP9GHo379+va8cEYaNWokSUlJ8ueff0qNGjXSfJUvX168gtGN4In2KEcs/37qyMZFF10k+fPnl/Hjx0vBggVz/HMixkT7nA786bPPPrOV5Xv27Dnuvoceesg0bNgwrHPEen98fLzp37+/WbZsmVm0aJEZOHBgyv16/rhatWpm7NixZt26dWbOnDnmueeeMxMnTsx037Zu3WoWLFhg3nnnHfvaM2bMsN/v3LnTuOHFF180N910k93/9KjdCK6sajkOHjxo3njjDXPhhRe6UmMUq7+ff/31l2nRooWpV6+erQHR31Xn6+jRoxFvB+QtAgdccfnll5v27dtneN/8+fPtm5j+Hc60O32z0jdAfYPUoraOHTum3Hf48GH7Zqdvavny5TPly5e30/L0jS8zjz32mH3N9F/62m5o06aN3b4W0HXu3NksX7485b4RI0bY+zTwIHguvvhiU7duXZOUlJQmaJQrVy6lX+rvSVB+P53Xy+hr/fr1EW0D5D0u3ga4rG3btnaJaKcwT4eZtTjv4Ycflg4dOthh6XHjxvH/EOBrrIwaNcqueKurzOopiNRTU7UGonHjxlHdTyASKBoF8vjcufr000/t2gTqhRde4P8goLTOoXbt2tK1a1dby5GdNTAAr6FoFIhi8NBruVx99dVy/fXXy4oVK/i/CIhDhw7JoEGDpFq1arJ8+XI76kXYgN8ROIAo+v86KjvioesNEDyCETR0Jkjv3r3ljz/+iPYuAXmGwAHEyIhH6uDRs2dPPvH6zIwZM9IEDUY0EDQEDiAGg4cWCnJA8he9CqoWhAJBReAAYoyObugFr+Lj+fX0E11C/JtvvrEreKZfeRMIAt7RgBigByBdJlpXeBwyZEiWS0bDuy644AJZsmSJnQqrBcNAkBA4gCjTkQy9PLhe3vuGG26I9u7AZRUqVJCpU6fKI488YkMHI1kICgIHEGU9evSQefPm2dCB4IxoPfnkk/YUS4kSJTjFgkAgcABRwCkUKE6xIEgIHEBe/9JxCgWpcIoFQUHgAFyWfnorp1CQHqdYEAQEDsBlzmqSBQoUYBYKwj7F4tBrrAB+QOAAXKYHDC0M/PXXX5mFgrBPsehImMqXLx+tBl/g8vRALleP/OSTT2Tu3LmycskSOXz4sJQoVUoaNW0q5557rlxxxRW2ZoPpj8iJI0eO2MCxatUqGTdunMybO1fWrVplQ+zJ5ctLk2bN7KjI+eefz/RaxDwCB5ADW7ZskXvvuceGjUQRaRgXJ2cmJUlBEdkuIr/kyydrjhyR8mXKSL+HH5Y+ffow9RHZpqdX/nvnnTLl+++laEKCNDFGzkhOtn1ui4jMS0yULUePSo1q1WTAs89Kp06dWFAMMYvAAWSTXmDt1ltukcL//CMPHj0qN4tI8Qwet0REXhORYSLSsnlz+WTcOKlUqRLtjbAKjV999VV54P77pbox8nBSklwjYgNtmseJyEwReSkuTj43Rjp26CDvvf++FC1alFZGzCFwANnw/vvvS9euXe2b/9vGSMkwnvOjiNyQmCj5KlaUGbNmETpwQv3795cBAwbIPSLyVAZBIyOfikj3hASp17SpTP72W0IHYg6BAwjTwoULpVnTptI1KUmGZLPi+jcROScxUSo3aSIzZs7k9AoypbUaV199tQwUkfuz2U5zRKRdQoJcfeONMuK992hlxBQCBxCGpKQkadKggZgVK2RuUpLkz0Gr6UjHuSLy8iuvyF133UW74zi7d++WWjVqSOvdu2WcMZKTy7sN15EOEfnqq6/k0ksvpZURM5gWC4Rh4sSJ8uvSpfJWDsOGOlsX/RKRgU8/bWcfAOkNHTpU9u7ZI4NyGDZUN+1r8fHyzIABNDBiCoEDCMPbgwdL84QEaZXL1uorItt27JAvv/ySdsfx/ezNN6VTcrJUyEXbaFC5MzlZfpw9W5YtW0YrI2YQOIAT0DUPfpgxQ65KSsp1W9UTkdPy5ZMZM2bQ7jhuTZe1v/0mHSLQLpeLSGJcHP0MMYXAAZzA+vXr5e8DB6RxhFqq8ZEjsmDePNodaSxYsCDUPyLQLjqrpU5iYso2gVhA4ABOYM+ePfbvkyPUUmW1OHDnTtod7vazpKSUbQKxgMABnIBzLYt/ItRSB0Ukf/6clp7Cr5w+EbF+FhdHP0NMIXAAJ1CjRg17nQpdOTQSliQkSK16Ws0BHHPGGWeE+kcEGkVXIF2aaptALCBwACdQuHBhqXvGGTI9Ai21V0R+NUaaNWtGuyONOnXqSOGCBSUS5cSL9RRNUhL9DDGFwAGE4cauXeXT+HjJbeXFSF1ELC5OrrlGF0cHjklMTJROnTvL0MREye18qLdF7IUD27ZtSxMjZhA4gDB0795dEvLnl/65aK1dIvJMQoINGxUrVqTdcZzeffrIb0ePyqBctM1yvWBgfLz8u3dvajgQU1jaHAjT66+/Ln379pWJItI+m62WLCKd4+JkStGisnTFCgIHMtW7Vy8Z/tZb8nNyspyZzXY6ICJtEhJkb9WqsnDJEilUqBAtjZhB4ACysQBYh3/9S779+mv5NDk57NBxWETuEJF34+Lkk08+sRfmAjKzb98+ObtlS9m2cqVMOnpUGmajPujq+HiZnT+/TJsxg/oNxBxOqQDh/rLEx8vHn3wiF7ZvL5f9f4g4UU3HbBFpmpAg7+nXe+8RNnBCRYsWlSlTp8opdetK87g4e3n6/ScYPRsvImcmJsrcQoXkq0mTCBuISYxwADkY6Rg0aJD0u+8+STp8WK5JTrZXgdXhbx3A/lNEfhGRzxIS7JVlG9StKyNGjZKGDcP9rAqIHDp0SJ544gl5fuBAKRoXJ9cnJdlr+dTSAlMR2Swiul7tx4mJsuroUbmwXTsZ+u67UqVKFZoPMYnAAeTQ9u3bZfjw4TLinXdk5bp1Nog4TipcWFq2bi29+/aV9u3bS0JCAu2MHNmwYYO8/fbbMvr992XDli1p7itTvLi0vfBC6dO3r5x99tkSF5fTa8wC7iNwALmwefNmOfXUU+Wbb76RMmXKyOHDh6VEiRLyzDPPyJ9//ikTJkygfZFrerG/8847z17XR5cr13BbtmxZ6dy5s7Rs2VJefPFFWhkxT0fmAOTQ1KlT5ejRo1KvXj0bOBy1atWS0aNHy5EjR1KWRgdyygm0VatWlWrVqqXcriuJ6n2AF1A0CuTCtGnTjgsbqk2bNnLgwAGZx1VhEaF+pn0q/SkTvW3x4sWyY8cO2hkxj8ABROBAkF6jRo2kWLFi9n4gN/bv3y9z5szJsJ/paRbnlAsQ6wgcQA5t3LhR1q1bl+GBQJepPueccwgcyLXZs2fbU3MZ9TOdkVK9enX6GTyBwAHk0PTpocu5nXuuToo9nh4gfvzxR3uwAHJKR8n0lJ1e3C2zfsZIGryAwAFEuH7DQR0H3KzfSN3PqOOAFxA4gAjXbzio44Cb9RsO6jjgFQQOIML1Gw7qOOBm/YaDOg54BYEDcKF+w0EdB3LjRPUbqfsZdRyIdQQOwIX6DQd1HHCzfiN1P6OOA7GOwAG4UL/hoI4DbtZvOKjjgBcQOAAX6jcc1HHAzfoNB3Uc8AICB+BS/YaDOg64Wb+Rup9Rx4FYRuAAXKrfcFDHATfrN1L3M+o4EMsIHIBL9RsO6jjgZv2GgzoOxDoCB+BS/YaDOg64Wb/hoI4DsY7AAbhYv+GgjgNu1m+k7mfUcSBWETgAF+s3HNRxwM36jdT9jDoOxCoCB+Bi/YaDOg64Wb/hoI4DsYzAAbhYv+GgjgNu1m84qONALCNwAC7Xbzio44Cb9Rup+xl1HIhFBA7A5foNB3UccLN+I3U/o44DsYjAAbhcv+GgjgNu1m84qONArCJwAC7Xbzio44Cb9RsO6jgQqwgcQB7Ubzio44Cb9Rup+xl1HIg1BA4gD+o3HNRxwM36jdT9jDoOxBoCB5AH9RsO6jjgZv2GgzoOxCICB5AH9RsO6jjgZv2GgzoOxCICB5BH9RsO6jjgZv1G6n5GHQdiCYEDyKP6DQd1HHCzfiN1P6OOA7GEwAHkUf2GgzoOuFm/4aCOA7GGwAHkUf2GgzoOuFm/4aCOA7GGwAHkYf2GgzoOuFm/kbqfUceBWEHgAPKwfsNBHQfcrN9I3c+o40CsIHAAeVi/4aCOA27Wbzio40AsIXAAeVi/4aCOA27Wbzio40AsIXAAeVy/4aCOA27Wb6TuZ9RxIBYQOIA8rt9wUMcBN+s3Uvcz6jgQCwgcQB7Xbzio44Cb9RsO6jgQKwgcQB7Xbzio44Cb9RsO6jgQKwgcQBTqNxzUcQSb2/UbDuo4EAsIHEAU6jcc1HEEm9v1Gw7qOBALCBxAFOo3HNRxBFde1G84qONALCBwAFGo33BQxxFceVG/4aCOA7GAwAFEqX7DQR1HMOVV/YaDOg5EG4EDiFL9hoM6jmDKq/oNB3UciDYCBxCl+g0HdRzBk5f1Gw7qOBBtBA4gSvUbDuo4gicv6zcc1HEg2ggcQBTrNxzUcQRLXtdvOKjjQDQROIAo1m84qOMIlryu33BQx4FoInAAUazfcFDHERzRqN9wUMeBaCJwAP9v06ZNeV6/4aCOIziiUb/hoI4D0UTgAP6fXsJbRxratm0blTa57rrrZN++ffZgBP9auXKlnH/++Xlev+G4+eab5Y8//ojKayPY4owxJto7AQAA/I0RDgAA4DoCBwAAcB2BAwAAuI7AAQAAXEfgAAAAriNwwLd0mYO77pKYsWGDiC4suXChe68xbVroNfbsce81kBb9DAgPgQPIxIgRIiVK0DxwF/0MQUHgAAAAriNwwNeOHhXp3Ts0UlG6tMgjj4g4S90dPixy//0ilSqJFCki0qJF6JSE0r9vuUVk797QKQr9evzx8F4zOVlk4ECRGjVEChTQ5aRFnn762P3r1onoYqaFC4s0aKBLXad9/qxZerVakUKFRCpXFunbV6+/cez+Q4dC+6336fZr1hQZNizjfTl4UOSyy0RathTZtSt7bYfw0c/oZwiDrjQK+NF55xlTtKgxd95pzIoVxowaZUzhwsYMGRK6/4YbjGnd2pgZM4xZs8aYF14wpkABY1atMubQIWNefdWYk04yZuvW0Nfff4f3uvffb0zJksaMGBHa7g8/GPPOO8asX69Rx5hatYz58ktjVq405pprjKla1ZgjR0LPXbQotM+vvBLaj5kzjWnUyJhu3Y5t/7rrjKlc2Zhx44xZu9aYb781ZvTo0H1Tp4ZeY/duY/bsMebss4254AJj9u2LdOvCQT+jnyE8BA74+kBQu7YxycnHbuvXL3SbBoG4OGO2bEn7nHbtjHnwwdC/hw83pnjx7L3mX3+FQosGjPScwDF06LHbli4N3bZ8eej7Ll2Mue22tM/TwBIfb8zBg6GQoo+fMiXj13cChwasBg2M6dgxFJ7gHvoZ/QzhSQxnFATwKj2VoKdDHK1aibz0ksi8eaFTK6efnvbxerpCT73k1PLloW20a5f5Y+rXP/bvChVCf//5p0itWiLz54usWSPywQfHHqP7qadp1q/XC8yJJCToZcaz3o8LLhBp1kxkzJjQ4+Eu+hn9DCdG4EBg6YFYD/DpD8hFi+Z8m1p3cSL58h37txOGNFA4f99+e6huIz2tBdEwEg6t2xg7VmTZMpF69cJ7DtxBPwNCCBzwtZ9+Ov57LbJs1EgkKSk0snDOORk/N3/+0GOyQ7etoeO770RuvTX7+9u4scjSpaGC04xoeNBQMn16aBQjM889FwpOOtKiBbBRuhJ6YNDP6Gc4MWapwNc2bRL5739FVq4U+egjkddfF7nzztCplBtvFLn5ZpFx40KnK+bODc0u+eqr0HOrVRPZty8UHnbsEDlw4MSvV7CgSL9+oVkkI0eKrF0bOhhlNoskPX2uzlrp1Su0QNjq1SLjx4v06XNsn7p2FeneXeTzz0P7rYFCT52k9+KLoZ/x/PNFVqzITqshu+hn9DOEIcxaD8BztJjvjjuM+fe/Q7NNdObIAw8cKyI9fNiY/v2NqVbNmHz5jClf3pirrgrNFHHoc0uXDhViPvZYeK+blGTMU0+FZp/odqtUMeaZZ44VjS5YcOyxOptEb9NiT8ecOcZceGFotkqRIsbUr2/M008fu1+LR+++25gKFYzJn9+YGjWMeffd42epOPr0CT1WC04RefQz+hnCE6d/hBNMAAAAcopTKgAAwHUEDgAA4DoCBwAAcB2BAwAAuI7AAQAAXEfgAAAAriNwAAAA1xE4AACA6wgcCJRt27ZJ48aN5fvvvxcv6du3r/TS9c7hCT///LPtZ2t1bXsP+de//iXPP/98tHcDPkXgQKB8++23smDBAqmf+hrxHlC5cmUZMWKEHDlyJNq7gjBMmDBBNm3aJNWrV/dUe5188skyatSoaO8GfIrAgUCZNm2a1KtXT8qUKSNe0qZNGzlw4IDMmzcv2ruCMPuZ/p/FxcV5qr10nxcvXiw79GqFQIQROBDIA4HXNGrUSIoVK2b3H7Ft//79MmfOHE/2s/POO8/+PWPGjGjvCnyIwIHA0CFuPafuxQNBYmKinHPOOQQOD5g9e7Y99eXFflalShV7GohgCzcQOBAY06dPt3+fe+654kV6APvxxx+p44hxerDWU3Z16tQRr/YzAgfcQOBAYHi1fsNBHYc3eLV+w0EdB9xC4EBgeLV+w0EdR+zzcv2GgzoOuIXAgUDwcv2GgzqO2Ofl+g0HdRxwC4EDgeD1+g0HdRyxzev1Gw7qOOAGAgcCYerUqZ6u33BQxxHbvF6/4aCOA24gcCAQvF6/4aCOI3b5oX7DQR0H3EDggO9t3LhR1q1b54sDAXUcscsP9RsO6jjgBgIHfM8v9RsO6jhik1/qNxzUcSDSCBzwPa+vv5EedRyxyS/1Gw7qOBBpBA74nl/qNxzUccQeP9VvOKjjQKQROOBrfqrfcFDHEXv8VL/hoI4DkUbggK/5rX7DQR1HbPFb/YaDOg5EEoEDvua3+g0HdRyxxW/1Gw7qOBBJBA74mt/qNxzUccQOP9ZvOKjjQCQROOBbfqzfcFDHETv8WL/hoI4DkUTggG/5tX7DQR1HbPBr/YaDOg5ECoEDvuXX+g0HdRyxwa/1Gw7qOBApBA74ll/rNxzUcUSfn+s3HNRxIFIIHPAlP9dvOKjjiD4/1284qONApBA44Et+r99wUMcRXX6v33BQx4FIIHDAFd26dZMOHTpErXX9Xr/hCHodRyz0Mz/Xbzio40AkEDiQ4Zu4voE6X6VLl5ZLLrlEFi1a5JnW8nv9hh/qOLzez4JQv+GgjgORQOBAhvSNf+vWrfbru+++s/UCl19+uSdaKwj1G36p4/ByPwtC/YaDOg5EAoEDGSpQoICUL1/efjVs2FD69esnmzZtku3bt9v7Fy9eLOeff74UKlTIfjK97bbbZN++fcdt54knnpCyZcvKSSedJLfffrscPnzY9RYPSv2GH+o4vNzPglK/4aCOA7lF4MAJ6Rv8Bx98IDVq1LBv+lozoJ9MS5YsKXPnzpVPPvlEvv32W+ndu3ea5+kn1uXLl8vUqVPlo48+ks8++8weGNwWlPoNv9VxeLGfBaF+w0EdB3LNAOl07drVJCQkmCJFitgv7SYVKlQw8+fPt/cPGTLElCxZ0uzbty/lORMnTjTx8fFm27ZtKdsoVaqU2b9/f8pjBg8ebIoWLWqSkpJcbfPq1aubPn36BOb/9ciRI6ZYsWLmmWeeMV7i5X6m+5QvXz7zxhtvmKD47bff7P/R2LFjo70r8ChGOJChtm3bysKFC+3Xzz//LBdddJFceuml8ttvv9lPkw0aNJAiRYqkPP6ss86S5ORkWblyZcpt+pjChQunfN+qVSv7KVaHzN0SpPoNP9RxeLWfBal+w0EdB3IrMddbgC/pm7wObTuaNGkixYsXl3feeUdHxTIdRg5neNnNIeig1W849MD3+OOP24Ngvnz5xCu82s+CVr/hoI4DucEIB8Kib97x8fFy8OBB+yarn0h1WqBj5syZ9v7TTz895bZff/3VPt7x008/SdGiReWUU05xrdWDVr/htzoOL/WzINVvOKjjQG4QOJChQ4cOybZt2+yXDm336dPHDlNfccUVcuONN0rBggWla9eusmTJElusp/d36dJFypUrl7INnSnQo0cPWbZsmXz99dfy2GOP2YI/PWDklA6nDxw4UD788EPZsmVLYNffCHc9jqSkJJk/f768/PLL8s0330isidV+tnfvXnnqqafk888/l127dgV2/Y1w1+PQ/0edKfXcc8/JL7/8EqW9Q6zjlAoyNGnSJKlQoYL9tx7IatWqZWcJOG+ykydPljvvvFOaNWtmz59fffXV9qCWWrt27aRmzZr29Ia+IXXu3NkO++fGnj175IEHHkj5vlq1anLBBRfYWgAdmg9a/Ub6Og49KGsdhAaP77//3h4YnGmkV155pb0vlsRqP9Pw8uijj9p/6yhG7dq15cILL7T7paE3aPUb6es4dGaQTkPWfqb/1poWbXsnrDVu3Djau4oYFKeVo9HeCSA7KleuLJs3b05zsD169GjK9/oJWKdT6qexSpUq+bpxdQRDTzvoG//QoUNlxYoV9nbn070eHJ3vn3zySXn44Yejur9eoaenNAA57Ze+nyUkJEivXr1s0NWgU6pUKfEzDRM6qqP9bNCgQfLHH3/YGhttB22j1IeRTz/91AZDID0CBzzn+uuvt5+C9WCbkdQHhtQjILqCpS4M5XXOqYPUIxgaKPRNP6vPD/pJVBfRQnh09ktWy6xrca6OdKQfAWnfvr3kz5/f882ss4b0NJwzgqGnrjRgZPZ759APA34P+sgZAgc85/XXX7fD7OEOzjkB5D//+Y/9dOZl+mavn7y1SFJDRupP4FnRx+rpKH0uwqN1IEOGDAl7BVfnYPzaa69J3759Pd3MGzZskFNPPTWsIJuarhiry9QDGaFoFJ6j6yxk50ygHpR1quXdd98tXqcHNT01osING+qMM84gbOSgn2V3ufjTTjtNbrrpJvG6qlWrSvfu3bMVNrRvah0RkBkCBzw51K3X4AiXfkqbMGGCLSz0g3vuuUd69uwZ9pRMHeEJ2rokkQoc2eljOnqkRa5+qOfQvvXWW2/ZOigNEuHQYNK6dWvX9w3eReCA5+i5c10gKlwjRozw1ScvPRi8+eabth4jnIOBnk7KzsETIXpKIdzwoP8PX375pR3h8NPvmV6XRmelhNPPdMSNfoasEDjgSWeffbb95H4iuiaDrufgN3owGDt2rJ0KHM7BgANBzoKdLqUeznoeI0eOtI/1mxIlSthRGy22PlE7aJ/U9WCAzBA44El6AE09FTY9fXO84YYbbODwK61L0YOBHhSyCh36OL+cTsprGiJOdOpqwIABdu0PP4/0fPXVVycM+Bo2/DA7B+4hcMCTWrZsmel9evDV+999913fLz2txX3OwSCjn1Vv0/Pqfm8HN4NtZtNANdTefPPNgVjbRH+fRo0adcKF54CsEDjgSTr9LqO5/ho2dDXE8ePHZ6uw1MuaN29ul3rP7KDox6H+vKK1QhmdStB+pu2qF5kLSpi79tpr5dlnn83wPh1tzOpDAKAIHPAs/USV+lSCHhj0ol16mqF06dISJB07drTXmElPP51Tv5G7q9meeeaZaW7TPqcjS3qdlaCdQujXr5+dLptRyKKf4UQIHPAsPVWQei0Kv01/za577733uOmy2iY6AoLIBFtn+quuwOmH6a+Rmi6b2YgjkBqBA75ZAGz48OGBPo/sTJfVZdyd0KELfumoDyJTx6GBw2/TX3MzXdbpZ0H+vUP4CBzw9AJgzvl1nY3ihxUeI3EwGDdunK1jUXr1VeRO6lMFfp3+mtPpsnoFX1W/fv1o7xI8gMABTx9c9fRJixYtfD39Nbt0GqxecKtQoUJ88ozQtFA9wOqMFL1wII61y5gxY2wdCyMcCAcXbwMAAK5jhAMxb+/evfLGG2/IlVd2kAoVqkj+/AWlUKEiUqtWPenWrZstFD3RJbODZseOHfLSSy/J5Zdfbov5ChYsaGs5dHEmLSz99ttvs3XxtyDQq5w+88wzctFFl0iZMuVtPytcuJg0atTMXmn4xx9/zNZFA4Pgt99+k8cff1wuuOACOfnkk+1UdB1h0ymyesXcefPmRXsXEUMY4UDMOnz4sD0ADBz4ghw6dFji4s6T5OSmIqLV8LrK6EpJTJwlR48ullNOqSaDB79uD7BBduDAAenfv78NaKpNmzZ2LQmdRaBXPl22bJk9cK5cudLWdwwePNg+Jsj++usvue+++2XYsGFiTH4x5nwxprGIlBGRQyKyRBITZ8jRo+ulXr1GMmzY29KsWTMJeqC966675KOPPrJBVq/ro2FWZ+7s379fFi9eLNOnT5fNmzfbmhed2ZJ+ejECyAAxaOPGjebMMxuauLhEI9LPiGwx2lsz/ppj4uMv0Y+epmfP28yRI0dMEK1cudKcfvrppkCBAubJJ58027dvz/BxycnJZsaMGeacc86xbdavXz+TlJRkguiXX34xFSpUNgkJRY3IC0ZkdyZ9LMmITDYJCU1MXFy8efbZZ207BpH2nbJly5pSpUqZQYMGmX379mX4uKNHj5ovvvjC1KpVy+TPn98MHjw4z/cVsYXAgZjz+++/mypVqpvExCpGZH4WQSP1V7IRGWIDSufO1wfuALpmzRpTvnx5++a+fPnysJ6jbfT888/b0NG7d+/AHUAXLlxoihUrYRISmhqR9WH2s8NG5CHbZo899pgJmh9//NEUKlTItGnTxmzdujWs5xw8eNDccccdts1ef/111/cRsYvAgZiiB73zz7/QJCZWNCIbwjwIpP76xL6xvfHGGyYodESnadOmpkaNGuaPP/7I9vPfeust22ajR482QXHgwAFz6qk1TUJCQyOyNwf97GnbZpMnTzZBsWvXLlOhQgVz7rnn2vbL7u/13XffbeLj482cOXNc20fENgIHYsrw4cPtG7nIpBwcBJyv/5iCBQubTZs2mSB44YUX7Bv5zz//nONtXHvttaZ06dL2oBIEDzzwgImPL2BEluewjyWb+Ph29nSMfoIPgltvvdUUL17cbN68OUfPP3z4sGncuLE588wz7ekWBA+BAzFDPwWdfnodExfXIRdhQ7/+MgkJJ5mHHnrI+J2+iVesWNEeDHJDh8fz5ctnXn75ZeN3f//9tylS5CQj8kAu+9kKG47fe+8943fbtm2z/UPDbW7MmjXLttnEiRMjtm/wDqbFImbMmTNHVq1aJsb0zuWWiklSUlcZMuRd309j1Gt6/P7779KrV69cbUdnsVxzzTV2pobf6Uqs+/f/LSL/yeWWzpD4+ItkyBD/t9kHH3xgr53So0ePXG1Hp8s2btw4EP0MxyNwIGbMmjVL4uMLich5EdjaJbJjxzbZsGGD+L3NNCw0bNgw19u65JJLZOnSpXbdE7+3Wb58dUUktPx7biQnXyLz5s21l2f3e5tpWChZsmSutqPXXtF+Nnv27IjtG7yDwIGYoXP34+N1rn5iBLYWOgAvWrRI/N5mkQgbStdRUEuWLBE/W7BgsRw5Epk203526NBBWbNmjfhZJPuZbkcXWdO1PBAsBA7EjH379klSUokIba1Eyjb9TH8+vc5HJOgKkc42/eyvv/Tni2w/08Wu/CyS/czZjt/7GY5H4EDM0CtPJiT8FaGt/Z2yTT/Tn+/vv0M/a245BwC/t1nRovrzRbaf6YXy/Ez7hK7IGglOf/V7P8PxCByIGXXr1pXkZB3Oj8R1UX61f/p9OWVts19/Df2subVw4UL7d506dcTPGjSoK4mJkTrV9qskJuaXGjVqiN/7WaROT2p/1euu6BeChcCBmKFFacnJOjQdiYKyKVK8eGk57bTTxO9tpterWL58ea63NWXKFKlZs6aULl1a/N5mSUmL9XJtud5WXNwUadiwsb1Eu9/bTAs9IzGapv2sRYsWtoAUwULgQMzQizxVraoBYVAut3RQEhKGS48eXSU+3t9dvH379lKmTBl7Ebbc2Llzp4wePdpefdfvdPqvXtVU5J1cbklnQE2Unj1vEb+76aab5J9//pGRI0fmajsLFiywweWWW/zfZjiev9+N4SkaDu67724RGS0iP+ZiS09IXNzfcscdd4jf6YGzd+/e9mqcOpMgp/r16yf58uWTW2+9VfxOixZvvbW7JCS88P+hISeMxMXdKSVLlpEbbrhB/O6UU06R6667Tp544gnZvn17jraRnJxsL1lfvXp1+de//hXxfYQHRHvlMSA1XfK4RYvWJjGxuhHZloPVH7+xV/N85plnAtOw//zzj6lTp46pX7++2bNnT7af//HHH9vVH4cMGWKCYu/evXZZ8vj4s4zIgRz0s0G2zcaNG2eCQlcb1eXvL7vsMrvCbXbpFYy1zaZOnerK/iH2ETgQc9atW2dOPrmCSUiobURWZ+MgMNbExxc0l1zSPnCXqF+0aJEpUaKEadasWdjXkNGl5N99912TmJhobrzxxsBdLXbmzJn2mjvx8ecbkT/DvoaKyMtGJM707dvXBM3XX39t+8uVV14ZdrjVDxH9+/e3YUNDB4KLwIGYtHLlSnuJ+vj4Qkbk+RNc0XO1iYu70b6hXXXV1YG5mFZ68+fPt9dV0Qtsvfnmm2b//v2ZPnbJkiX2oKFt1qNHj8AFNMf06dNNiRKlTULCyUZELxz4Txb9bL69YJu22b333muSkpJMEE2YMMEUK1bMnHLKKXZ0LLPRDg2wejn7Fi1amLi4OPPUU08FLtQirTj9I9qndYDM1oV48MEHZdAgLYgsKMnJ7UWkmYhU+v+psyskPn6WJCdPkxIlSstrr70sXbp0CXT1++7du+W///2vvPfee3YhLy0qbdKkiVSoUEEOHz4sy5Ytkx9++MEW7ultb775plx11VUSZH/88YfccUdvGTfuU0lMPFmOHr1URJqIiE7b/EfXXpWEhOmSlDRfKlc+VYYNe1suvPBCCbKNGzfK7bffLpMmTZKKFSva5cr1GimlSpWSAwcO2Cm0U6dOtXVFtWvXlqFDh0rr1q2jvduIMgIHYt6WLVvktddek8mTv5VVq1bJP/+EVnUsU6aCVK9eRf7979ulc+fOvl98KTvWr18v77zzjkybNs3ODNAZBqpy5crStGlT6dSpkw0afp/OmR0rVqyQF198UWbPniurV6+QI0cO29srVaomNWtWk7vuuksuu+wySUyMxNL7/qBramiYmDlzpg0XzjVldHp18+bN5eabb5YLLrjA97PFEB4CBzxBZ0/oAWHGjBly8KBOe02wIyC6eNCECRPk8ssvj/YuxiydHaBtpgfK0HRQZOacc86R008/XYYMGWLbTAPZ3Llz5eyzz5aVK1fa+5CxpKSklDYjyCIjxE54gg7P6pCtflIqUqSIFCxY0C5QpZ/Y9T5kzmkzwkbW9HooP//8s+1nGmiLFi1qD5z169e33+toETKXus2AjBA44InzxevWrZM2bdqkuV1rNfQ2DgSIBK1rOXLkyHH9rFixYvY0FP0MyB0CB2Le9OnT7d/nnnvucffpwUFrFPbs2ROFPYOfaKDQVVszupaME2ypsQdyjsCBmKdv9PXq1bMHg4wOBHoQ0JkXQG77mfanjGY56e1bt26V1atX08hADhE44JkDQUZOPfVUW8fBcDdyW78xZ86cTPuZXueHOg4gdwgc8GT9hoM6DrhZv+GgjgPIPQIHYlpW9RsO6jjgZv1G6n5GHQeQcwQOeLZ+w0EdB9ys30jdz6jjAHKOwAHP1m84qOOAm/UbDuo4gNwhcMCz9RsO6jjgZv2GgzoOIHcIHPB0/YaDOg64Wb+Rup9RxwHkDIEDnq7fcFDHATfrN1L3M+o4gJwhcMDT9RsO6jjgZv2GgzoOIOcIHPB0/YaDOg64Wb/hoI4DyDkCBzxfv+GgjgNu1m+k7mfUcQDZR+CA5+s3HNRxwM36jdT9jDoOIPsIHPB8/YaDOg64Wb/hoI4DyBkCBzxfv+GgjgNu1m84qOMAcobAAV/Ubzio44Cb9Rup+xl1HED2EDjgi/oNB3UccLN+I3U/o44DyB4CB3xRv+GgjgNu1m84qOMAso/AAV/Ubzio44Cb9RsO6jiA7CNwwDf1Gw7qOOBm/UbqfkYdBxA+Agd8U7/hxzqOnTt3StmyZWXDhg0SC5o1aybjxo2TINdv+K2Ogz6GvELggG/qN/xYx/Hss8/KFVdcIdWqVUu57c4775QmTZpIgQIFpGHDhhF7rRkzZtjXqlixoj0Qf/7558c95tFHH5UHHnhAkpOTJaj1G36r48ioj6X3zz//SLdu3eyHgcTEROnQoUOOXisofQwZI3DAN/UbfqvjOHjwoAwbNkxuvfXWNLfr6E337t2lU6dOET8QN2jQQN54441MH3PZZZfJ3r17ZfLkyRLU+g0/1XFk1sfSS0pKkkKFCknfvn3lggsuyPHrBaWPIWOJmdwOeLJ+w6EHk1GjRsmePXukRIkS4kVff/21/TTZqlWrNLf/73//s39v375dFi1aFLHXu/TSS+1XVvQTffv27eWjjz464WP9XL+Rup+NHDnShsDcnJ6JtT6WXpEiRWTw4MH23zNnzrS/VzkRlD6GjDHCAV/Vb/ipjkOHn/UTdKxp3ry5p9s1EvUbfqnjoI8hLxE44Kv6DT/VcWihqJ7rjjWVKlWyp7+8eI49UvUbfqnjoI8hLxE44Kv6DT/Vcej59YIFC0Z8uzo6UbRo0ZSvDz74IFvP13P5GjYOHTokQa3f8EsdR0Z9rG7duil9I1qnNLzcx5A5ajjgu/oNv9Rx6Kml3bt3R3y7eoBcuHBhyvflypXL1vN37dolhQsXtgeFINdv+KGOI6M+9tVXX9lQpqL1f+zlPobMMcIB39Vv+KWOo1GjRrJs2bKIb1ffxGvUqJHypZ/Ss2PJkiXSuHFjCXr9hh/qODLqY1WrVk3pG3r6LBq83MeQOQIHfFe/4Zc6josvvliWLl163CfQNWvW2BGKbdu22SFx/bd+HT58OFevt2/fvpRtqfXr19t/6+mu1DTAXXTRRRL0+g0/1HFk1scyosFE+4OOPui01dR9JVx+72M4AQNE2W+//Wa0K44dOzbi2+7SpYtp3Lix8aqWLVuat956K81t5513nm2v9F/r169PeYx+P3z48Gy91tSpUzPcbteuXVMes3nzZpMvXz6zadMm4zVTpkyxP8+SJUsivu0WLVqYG264wfilj2WkatWqGfYPh/Y//V77UVD7GLJG4EDUjRw50r7pbN++PeLbHjZsmImLizO7d+82XjRx4kRTu3Ztk5SUFPZz9I0/MTHRrFq1KuL7c++995qePXsaL3r44YdNmTJlTHJycsS33a9fP1OxYkVXth2LfSyzMFGiRAmza9euwPYxZI1TKvBl/YZf6jh0AaTbb79dtmzZEvZzJk2aJLfddpvUrFkz4vuj13UZMGCAeJEb9RsO3e7vv/9uT3cFoY9l1u8eeughKVmyZGD7GLIWp6njBI8BXHXaaafZ5YydFTQjSbu3FsFde+218tJLL0V8+/BO/YYeCF955RXp1atXxLf/999/2+3rapw9e/aM+PYBP2CEA75af8OP63Eg9tbf8Nt6HEBeIHDAd+tvpKcHmQULFuT4+g/wPjfW30jPCbYMGgMZI3DAt/UbfqnjQGzXb/ihjgPICwQO+G79Db+tx4HYXH/DT+txAHmBwIGo2bRpk6v1Gw7qOILN7foNB3UcQNYIHPB1/YaDOo7gyov6DQd1HEDmCBzwdf2GgzqO4MqL+g0HdRxA5ggc8HX9hoM6jmDKq/oNB3UcQOYIHIha/cbatWvz7EBAHUcw5VX9hoM6DiBzBA74vn7DQR1H8ORl/YaDOg4gYwQO+L5+w0EdR/DkZf2GgzoOIGMEDvi+fsNBHUew5HX9hoM6DiBjBA74vn7DQR1HsOR1/YaDOg4gYwQOBKJ+w0EdR3BEo37DQR0HcDwCBwJRv+GgjiM4olG/4aCOAzgegQN5bvv27XLTTTdFpeW1juPSSy+V1atXR+X1kTcOHjwohw8flmuuuSYqTX7OOefYy9UvXrw4Kq8PxKI4w7WUAQCAyxjhAAAAriNwAAAA1xE4AACA6wgcAADAdQQORM3jj4s0bHjs+27dRDp0yP12jRG57TaRUqV0sS+RhQuzfvy0aaHH7dmT+WNGjBApUSL3+4a8Rz8DYkNitHcAiLRJk0IBQYNE9eoiUVjuAwFAPwOyh8AB31m7VqRCBZHWraO9J/Az+hmQPZxSQa4kJ4sMHChSo4ZIgQIiVaqIPP106L5+/UROP12kcOHQSMOjj4ocOeJug+tpmT59RDZuDJ0mqVZN5NAhkb59RcqWFSlYUOTss0Xmzs16OzpCoj+L7vtVV4ns3OnufiNr9DPA+xjhQK48+KDIO++IvPJK6EC+davIihWh+4oVCx24K1YU0QUXe/YM3Xb//e41+muviZx2msiQIaFQkZAQer2xY0Xee0+kalWR558XufhikTVrQnUe6f38s0j37iLPPCPSsWNo6Pyxx9zbZ5wY/QzwAV1pFMiJv/4ypkABY955J7zHP/+8MU2aHPv+sceMadDg2Pdduxpz5ZW5/7945RVjqlYN/XvfPmPy5TPmgw+O3X/4sDEVK4b2R02dqmWmxuzeHfr++uuNueSStNvs1MmY4sVzv2/IPvoZ4A+cUkGOLV8eOl3Rrl3G93/6aWjUo3x5kaJFQ6dU9FRHXp9n19M4Z5117LZ8+USaNw/tf0b09lat0t6W/nvkHfoZ4A8EDuRYoUKZ3/fTTyKdO4tceqnIl1+KLFgg8vDDIocP522D69iFSn/BUL09s4uIOs9BbKCfAf5A4ECO1awZOhh8993x982cGaqX0JDRtGnosb/9lveNrcWs+fOL/Pjjsdt0xGPePJHatTN+Tp06ocCUWvrvkXfoZ4A/UDSKHNMZHzoTRYsy9aCupy22bxdZujR0oNfTJ6NHizRrJjJxoshnn+V9YxcpIvKf/4jcd1+oQFRnnmjR6IEDIj16ZPwcndGiU2r1cboQ2TffhApHER30M8AfGOFArmhdxj33iPTvHxox6NRJ5M8/Ra68UuTuu0V69w6tJjprVuix0fDccyJXXy3SpYtI48ah2SmTJ4uULJnx41u2FBk6VOT110P7roHjkUfyeq+RGv0M8L44rRyN9k4AAAB/Y4QDAAC4jsABAABcR+AAAACuI3AAAADXETgAAIDrCBwAAMB1BA4AAOA6AgcAAHAdgQMAALiOwAFXPPnkk9JJ1zn3kM2bN0vjxo1lxowZ0d4VhKl79+5yv17Mx0Nmzpxp+9lGvdgQECAEDrhi5MiRUq5cOU+1bqVKlWTHjh3yxRdfRHtXEIb9+/fLqFGjpKpelthD6tWrJ4sWLZLJekEfIEAIHIi4TZs2ydq1a6VNmzaeat24uDi7z9OmTYv2riAMs2fPliNHjniun5100knSpEkT+hkCh8CBiJs+fbr9+9xzz/Vc6+rBa8GCBbJnz55o7wpOQINhmTJlpE6dOp5rKyfYcu1MBAmBAxGnb6Q6bKwHAy8eCPQg8MMPP0R7VxBGP9P/Lx2Z8hrd799//13WrFkT7V0B8gyBAxE3depUzw1zO0499VSpXLkyw90eqN+YM2eOZ/vZWWedJQkJCfQzBAqBAxGllffr1q3z7IGAOg5v8Gr9hoM6DgQRgQMR5eX6DQd1HLHPy/UbDuo4EDQEDkSUl+s3HNRxxD4v1284qONA0BA44MqBwMuo44htXq/fcFDHgaAhcCBivF6/4aCOI7Z5vX7DQR0HgobAgYjxQ/2GgzqO2OWH+g0HdRwIEgIHIsYP9RsO6jhilx/qNxzUcSBICByIGD/Ubzio44hNfqnfcFDHgSAhcCAi/FK/4aCOIzb5pX7DQR0HgoTAgYjwU/2GgzqO2OOn+g0HdRwICgIHIsJP9RsO6jhij5/qNxzUcSAoCByICD/Vbzio44gtfqvfcFDHgaAgcCDX/Fa/4aCOI7b4rX7DQR0HgoLAgVzzY/2GgzqO2OHH+o3U/UyvsmyMifauAK4hcCDX/Fi/4aCOI3b4sX7DoT/X1q1bZfXq1dHeFcA1BA7kmh/rNxzUccQGv9ZvOKjjQBAQOJArfq3fcFDHERv8Wr/hoI4DQUDgQK74uX7DQR1H9Pm5fsPBehzwOwIHcsXP9RsO6jiiz8/1Gw7qOOB3BA7kip/rNxzUcUSX3+s3HNRxwO8IHMgxv9dvOKjjiC6/1284qOOA3xE4kGNBqN9wUMcRPUGo33BQxwE/I3Agx4JQv+GgjiN6glC/4aCOA35G4ECOBaF+w0EdR3QEpX7DQR0H/IzAgRwJSv2GgzqO6AhK/YaDOg74GYEDORKk+g0HdRx5L0j1Gw7qOOBXBA7kSJDqNxzUceS9INVvOKjjgF8ROJAjQarfcFDHkbeCVr/hoI4DfkXgQLYFrX7DQR1H3gpa/YaDOg74FYEDGZo8ebJ069ZNhg4dKmvWrBFjTKDrN7Kq49CD4k8//STPPfecdOnSRbZt2xbVffSSd999V3r27CkffvihbNmyRYJev5FVHcfBgwfl+++/l/79+8stt9xi+x3gJXEmdY8G/t+jjz4qTz31VEp7lC1bVi644AJp27atDSMrVqyQxYsXB669dGTntNNOk+eff16SkpLsAeCHH36Qf/75J+Uxc+fOlaZNm0Z1P73immuukbFjx6Z8X61atZR+9sorr9jvP/nkEwmar7/+Wtq3by8jRoyQtWvXynfffWdPLx09ejTlMRp6ixcvHtX9BLKDwIEMffnll3LFFVekuS0hIcEeZFWhQoXkqquusgcG/TSmB2G/FvbpJ8n58+fbT5z6xv/tt9+mtEdycnKaT6H58+eXv//+2/6NE3vppZfk/vvvt+3oSExMTDmwlipVSjp27JjSzypWrOjbZtURDD2NpP1MQ70GjPTt4ahZs6asWrUqSnsK5AyBAxnasWOHnHzyyVm2TuoA4oyAXHLJJXLTTTd5Pnzs2rVLhgwZYgPGjz/+aEcwMgoY6bVq1UpmzZqVp/vqZTNnzpSzzz47y8ekPuA6IyAadnUEwOs2bNggw4cPt/3s559/tj9nRgEjNb3/5ptvlmHDhuXpvgK5ReBAlrMy9A0x7M4UF2cPxvqcqlWrerplX3/9denbt2/KzxQOPRDcfffd9nQLwqNBrlixYlkeYDNSuHBh+euvv2wI9LJevXrJoEGDsv08ra3q0aOHK/sEuIWiUWRKi0L1IBouPTA//fTTng8b6rbbbpPWrVtLfHz4vyJ60NQRDoSvYMGCUr9+/Ww32Xvvvef5sKEef/xxqVKlSrZ/FvoZvIjAgSzf1JxTJieiIwE6q+XBBx/0RYsWKFBAxo8fn+2DAQeC7DvnnHOyFWwHDhxoi039QE9bfvPNN1KkSJGww23RokWlVq1aru8bEGkEDmR58AzndIIekPWg8fbbb3u+diO10qVL2+I9fYMP52BQqVIlKV++fJ7sm9/6WTinVLRv6WmE++67T/zkjDPOkC+++CKsPqZtoO2VnZE3IFbQa5GpM8880w55Z0U/mWqtx+eff+7LmRk6G2DChAknfIN3QheyL5xRIW1fnaUyePBgX4Vah/5sWpdxItoPdSVSwIsIHMjyTb558+aZd574eFvwp6MAJUuW9G1LapDQmQRZ0dkrnE7JmcqVK2c5I0r7oU67/uyzzyRfvnziV127dpWHH344y8foKc6WLVvm2T4BkUTgQJZ0ymJm59f1QDBx4kSpXr2671tRp/o+9thjmd6vp54IHDmjIxYa6jIaRdLbdHErDbVBWORqwIAB0qlTpyxH1Fq0aJGn+wRECoEDOT6/PmrUqEAdZDVw3HDDDRkeDPR0UoMGDaKyX36gM4IyCiIadr/66iu7/kYQ6M+sq4vqyGJGxcp6iq9EiRJR2TcgtwgcyFJmw7c6/fW6664LVOvpwUCv/aFtkv5g0KRJE1/WsOQVDa6pVxt1Ro0++OCDwH2i17opnSGlRcip+5mGL+qE4GUEDmRJL56V+tOl36a/RmK6rP59otUykbXGjRsfd+rOT9NfczNd1imS1ZHGjEaCAK8gcOCEnKvCOufa/Tb9NTfTZZ1CviCdWnLrU73OivLz9NdITJeln8HLCBwI641PlStXzrfTX3M6XdYJXhwIcs8pPm7WrJlvp7/mZLqsc80UHQFiwS94GYEDJ6RXja1QoYJMmjTJ19Nfs0tHe5544gmpU6cOC35FwLXXXmtPVWk/8/P015xMl9VZUnrFXBb8gpdx8TYcR4v1/vjjD3thrZNOOsleIhxZ04LHbdu2yeHDh+0sAmYSnJieitI2O3LkiO1j2teQNa3j2Lp1q+1vemrPOa0HeAEjHLAOHTpkZwRcfPHF9o1MRzR0BVH9ty7MdP3119tLaId75dQgOHDggB3uPv/88+3Ij84q0DbTf+vf+slUL1VPmx2jV3h988037eiQrqtxyimn2LbSf+tpKr1o3i+//BLF/9XYs3PnTnnxxRftaTtdaE9HgbSQWwNa7dq1pU+fPrJ06dJo7yZwQoxwQL788ku5/fbb5ffff7fnjPUAqlfw1EuA79q1SxYsWGDrFZYtW2bPr+uqm3Xr1g1sy2mAGD16tH2j1/bRkKaFtc5S8Nu3b7cHTa13Wbt2bcp5+CAskJZVm73zzju2EHT//v1y2WWX2Zk9ejpKa4L0U/v8+fPtaqKbNm2Syy+/XN566y0b4oI8AvTqq6/Ko48+av/9r3/9y85S0ZoqrefYsmWLzJs3T8aOHWtHJDt37iyvv/66nVkGxCSDwEpKSjJ33XWXDlmYSy+91CxfvjzTxyYnJ5vvvvvO1KpVy+TPn9+8//77JogOHz5sunbtatvsuuuuM+vWrcuyfcePH2+qVatmChcubCZMmGCC6ODBg6ZDhw62zXr06GE2b96c6WOPHDliRo8ebcqXL29KlChhpk2bZoJo7969pm3btiYuLs7ceeed5o8//sj0sYcOHTLvvvuuKVmypClXrpyZP39+nu4rEC4CR4Bp2NA3tP/97382UIR78Ljlllvs8z7++GMTJNpGN910k0lMTDQjR44M+3l///236dixo8mXL5+ZPHmyCZKjR4+ayy67zBQqVMiGr3Dt3LnTtGvXzj5v9uzZJkj0d+zss882xYsXN1OnTg37eVu3bjXNmze3QW3JkiWu7iOQEwSOgNI3f/3EqWEju/STe+fOnU2xYsXMb7/9ZoJi+PDhts0+/PDDHI2MXHzxxaZs2bJm+/btJihefPFFG06//vrrbD/3wIEDpmXLlubUU0+1oS0oHnjgARtOcxK09uzZY+rWrWsaNGhgRz6AWELgCKB//vnHVKxY0bRv3z7skY2M3thOOeUUc+WVV5og2L17t/3E2aVLlxxv4/fff7fD3npaIQg2bdpkChYsaEfScmr16tV2lOP+++83QbB06VITHx9vnnrqqRxvQ0+pJCQkmOeffz6i+wbkFoEjgEaNGmU/qWdVsxGOoUOH2k+va9euNX736quv2lMpGhpyY+DAgbYGJgijHI888ogdBfvrr79ytZ377rvPnibYv3+/8bv//Oc/pkKFCnZELDf0tGflypXtKS0gVjAtNoBGjhxpZ07kdtVCnSqr0/R0Om0Q2qxDhw52unBudO/e3c7Y+OSTT8Tv3n//fbnxxhttH8mNf//737Jnzx47m8rPdCaK/i7psu65XfjsP//5j53tM3369IjtH5BbBI6A0YPd3Llz7dTX3NJps3rl1Dlz5oif6QJoixYtikib6ZTFevXq+b7NdJrmb7/9FpE20+nEVatW9X2brVy50q5ToiuK5pZevViDnt/bDN5C4AgYPRDs3r3brrMRCbodXZ/Dz9asWWNXeKTNwrd8+XL7t4arSNC2d7bpV87PF4l+pkug67owfv/dhLcQOAJGP607oxORoJfP1lVK/cyNNnO26VdOn9CfNRK07f3eZvxuwu8IHAHjXK9CV8iM1LLLuT1HH8Q28/t1QyLdZrod2ix7gvC7CW8hcASMXiRLr1+hy5VHgm6nYcOG4mennXaa/aROm4VPh/P18vKRuC6K1h3pdho0aCB+5vx8kehnehFBvb6K33834S0EjgDSa1hoxX9uLyqm9SBalHbWWWeJnyUkJNgLZ+n1ZHJr1apVtjjQ722mn6z1ABqJNvv555/tp3W/t5leJFG/ItFmU6ZMsaHD720GbyFwBNCtt95qP/1MnTo1V9t5++237UWkdOpjENpsxowZ8uuvv+ZqO3qlVL0Cr06x9buePXvK+PHj7WyV3NALkukVZSMx4yWW6YiQ9jOdGpvbU1H/+9//7EwVRjgQU6K9EAjynq4u2qxZM1O7dm173YbcrACZm1UkvUSXia5Zs6Zdajuniyk5K0AOGDDABIEu+KWLWOmFAXO6oq1eMFDfpgYPHmyCYNu2bble0XbMmDG2zT755JOI7huQWwSOgFq8eLFd8VJXJNRro2R3WfPGjRub6tWrm3379pmg+PHHH+3Kqvfcc0+2D6B6tc/TTz89cNe40Cvk6sHvmWeeyfZzN2zYYCpVqmTatGmT7T7qh2v2DBkyJEdLo5cqVcpeLDCnIQ9wC4EjwPQS83oA1QuxaYgId2RDw4YuNb1w4UITNK+99po9GNx+++1hL7W9aNEic8YZZ9hLrmv7BU3//v1tm/Xr1y/ssPXTTz+ZKlWq2Au3bdmyxQSJBoU77rgjJaiFO6Kmo0Enn3yyqVevnr3aLhBrCBwBp5eY1+td6IXY9NoomR1Edaj3iSeesKdRdGQjiGHDoZ889aJkNWrUMB988IG9GF5GNm7caA+yeuVPvYLnqlWrTBDpAfSFF16w16LRg+HYsWPNkSNHMnzsmjVrTJ8+fewFzPS03+bNm01Q2+zhhx+2HwhatGhhJk6cmOkoj45qdO/e3QYUHQ3asWNHnu8vEI44/SPadSSIro0bN0rfvn1tgZ/OLtDlynW1Q50KqrMDdJqezkbRAtHbb79dnnrqqYgt6ORVOtOkT58+djaATjXWNtOpoIUKFZI///zTTuPUJeS1nbRtH330USlQoIAE2cKFC6V3794yc+ZMKVu2rG2zOnXqSP78+WXbtm0yf/58224lSpSQfv36yT333GP7XJDNmjXL9jNtl0qVKkmLFi3sNZC0XTZv3izz5s2zy+5re2ofu+OOO+wqo0AsInAgxbp162yFvIYLXRJZV4vUAKKV7jq9TmejlCxZkhZLtxz1Rx99ZMOFhhCdiqgHzEaNGsm5554rnTt3ZvGlDILHxx9/bA+Wq1evtsvG68ydxo0b24sKXnfddTa4IUQ/E+rU4E8//dSGMv09TU5OlpNPPtnORGnXrp107NjRBjcglhE4AACA6xh7AwAAriNwAAAA1xE4AACA6wgcAACAwAEAALyPEQ4AAOA6AgcAAHAdgQMAALiOwAEAAFxH4AAAAK4jcAAAANcROAAAgOsIHAAAwHUEDgAA4DoCBwAAcB2BAwAAuI7AAQAAXEfgAAAAriNwAAAA1xE4AACA6wgcAADAdQQOAADgOgIHAABwHYHDZ3bu3Clly5aVDRs2SCxo1qyZjBs3TmIZbUab0c8A9xE4fObZZ5+VK664QqpVq2a///XXX+X666+XypUrS6FChaR27dry2muvRey1NFAUK1bMhpwOHTrIypUr0zzm0UcflQceeECSk5PFK22m7rzzTmnSpIkUKFBAGjZsGLHXmjFjhn2tihUrSlxcnHz++efHPcarbZbetGnT5Morr5QKFSpIkSJFbDt+8MEHOXot+lkw+xn8hcDhIwcPHpRhw4bJrbfemnLb/Pnz5eSTT5ZRo0bJ0qVL5eGHH5YHH3xQ3njjjVy/3vTp06VXr17y008/yZQpU+To0aNy0UUXyf79+1Mec9lll8nevXtl8uTJ4pU2U8YY6d69u3Tq1Cmir6dt06BBgyzb36ttlt6sWbOkfv36MnbsWFm0aJFtz5tvvlkmTJiQrdejnwWzn8GHDHxj7NixpkyZMid83B133GHatm0b8df/888/jXap6dOnp7m9W7dupkuXLsaLbfbYY4+ZBg0auPLa2lafffZZhvd5uc2y0r59e3PLLbfk6vXpZ8HoZ/AfRjh8RIdRmzZtesLH6aeaUqVKRfz1dbsq/babN28uP/zwg3i5zfKaX9ssEn2PfhaMfgb/SYz2DiBytFBUz9lmZfbs2TJmzBiZOHFiRJteP0j997//lbPPPlvOPPPMNPdVqlRJNm7caM8Vx8fHe67NosGPbfbpp5/K3Llz5e23387xa9PPgtPP4D/0MB/Rc+sFCxbM9H6t4dAivv79+8uFF14Y9nb1E1DRokVTvjIq/Ovdu7c9T//RRx8dd58Wq+ob2qFDh8RrbZZT4bRZVrzWZnXr1k35WS+99NIMC0i7desm77zzjn1sTtHPgtPP4D+McPhImTJlZPfu3Rnet2zZMjn//POlZ8+e8sgjj2Rruzp8vnDhwpTvy5Url+b+Pn36yPjx4+1Q+ymnnHLc83ft2iWFCxe2b25earPcOFGbnYjX2uyrr76SI0eO2H+n32ct+tQZEy+//LItGs0p+lmw+hn8h8DhI40aNbKzUTIa2dCw0bVrV3n66aezvV19M6pRo0aGw9t6EPjss8/sJ9hTTz01w+cvWbJEGjduLF5qs9zKrM3C5bU2q1q1aoaP1X5x+eWXy8CBA+W2227L0evRz4LZz+A/nFLxkYsvvtiGi9SfPvX7tm3b2lMoWmOxbds2+7V9+/Zcv55OidUDz4cffmjX4nC2rUPu6Yd9dbqsV9pMrVmzxn5ydH4e/bd+HT58OFevt2/fvpRtqfXr19t/63l0r7dZRmFDp1727dtXrr766pT+oZ+qs4N+Fsx+Bh+K9jQZRFbLli3NW2+9lWZap/43p/+qWrVqmufpbcOHD8/Wa2W03fTb2bx5s8mXL5/ZtGmT8UqbqfPOOy/Dn239+vW5arOpU6dmuN2uXbt6vs3S058po59V29ah7am3abtkhn4W3H4GfyFw+MzEiRNN7dq1TVJSUtjP0Tf9xMREs2rVqojvz7333mt69uxpYhltljdtltmBsUSJEmbXrl252g79zJ9tBn+hhsNn2rdvL6tXr5YtW7bY5czDMWnSJHt+vWbNmhHfH13y/N5775VYRpvlTZtl1vceeughKVmypOQG/cyfbQZ/idPUEe2dAAAA/kbRKAAAcB2BAwAAuI7AAQAAXEfgAAAAriNwAAAA1xE4AACA6wgcAADAdQQOAADgOgIHAABwHYEDAAC4jsABAABcR+AAAACuI3AAAADXETgAAIDrCBwAAMB1BA4AAOA6AgcAAHAdgQMAALiOwAEAAFxH4AAAAK4jcAAAANcROAAAgOsIHAAAwHUEDgAA4DoCBwAAcB2BAwAAuI7AAQAAXEfgAAAAriNwAAAA1xE4AACA6wgcAADAdQQOAADgOgIHAABwHYEDAAC4jsABAABcR+AAAACuI3AAAADXETgAAIDrCBwAAMB1BA4AAOA6AgcAAHAdgQMAALiOwAEAAFxH4AAAAK4jcAAAANcROAAAgOsIHAAAwHUEDgAA4DoCBwAAcB2BAwAAuI7AAQAAXEfgAAAAriNwAAAA1xE4AACA6wgcAADAdQQOAADgOgIHAABwHYEDAAAQOAAAgPcxwgEAAFxH4AAAAK4jcAAAANcROAAAgOsIHAAAwHUEDgAA4DoCBwAAELf9H/yH/m8ns53fAAAAAElFTkSuQmCC", + "text/plain": [ + "Graphics object consisting of 32 graphics primitives" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "poker.plot(backend=\"sage\")" + ] + }, + { + "cell_type": "markdown", + "id": "a915228c", + "metadata": {}, + "source": [ + "Alice knows her card and Bob does not, so this is a game of incomplete information — and its equilibrium involves bluffing. Because the chance probabilities are exact rationals and `'lcp'` computes exactly, the answer is exact too." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "3a1e9237", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:16:35.372103Z", + "iopub.status.busy": "2026-08-23T17:16:35.371890Z", + "iopub.status.idle": "2026-08-23T17:16:35.378735Z", + "shell.execute_reply": "2026-08-23T17:16:35.378015Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'Alice bets holding High': 1,\n", + " 'Alice bets holding Low (a bluff)': 1/3,\n", + " 'Bob calls': 2/3}" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "equilibrium = poker.obtain_nash()[0]\n", + "game = poker._gambit_()\n", + "\n", + "with_high, with_low = game.players[\"Alice\"].infosets\n", + "bob_infoset, = game.players[\"Bob\"].infosets\n", + "\n", + "{\"Alice bets holding High\": QQ(equilibrium[with_high.actions[\"bet\"]]),\n", + " \"Alice bets holding Low (a bluff)\": QQ(equilibrium[with_low.actions[\"bet\"]]),\n", + " \"Bob calls\": QQ(equilibrium[bob_infoset.actions[\"call\"]])}" + ] + }, + { + "cell_type": "markdown", + "id": "8eedd88c", + "metadata": {}, + "source": [ + "Alice always bets with a high card, bluffs with a low card exactly one third of the time, and Bob calls two thirds of the time. The game is worth `1/3` to Alice:" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "c1c7dce7", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:16:35.380622Z", + "iopub.status.busy": "2026-08-23T17:16:35.380428Z", + "iopub.status.idle": "2026-08-23T17:16:35.384606Z", + "shell.execute_reply": "2026-08-23T17:16:35.383622Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "1/3" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "QQ(equilibrium.payoff(game.players[\"Alice\"]))" + ] + }, + { + "cell_type": "markdown", + "id": "a3fc7265", + "metadata": {}, + "source": [ + "## Editing a tree\n", + "\n", + "A tree does not have to be built strictly from the root down. `insert_move` puts a new move immediately *above* an existing node, pushing the subtree below it down a level, and `delete_tree` removes everything below a node, turning it back into a leaf.\n", + "\n", + "Here Bob gets a chance to walk away before Alice moves at all, and then the branch in which he plays is cut back off." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "2e2693cc", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:16:35.386102Z", + "iopub.status.busy": "2026-08-23T17:16:35.385939Z", + "iopub.status.idle": "2026-08-23T17:16:35.391795Z", + "shell.execute_reply": "2026-08-23T17:16:35.390997Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "as built root: Alice ['L', 'R'], 2 leaves\n", + "after insert_move root: Bob ['play', 'walk'], 3 leaves\n", + "after delete_tree root: Bob ['play', 'walk'], 2 leaves\n" + ] + } + ], + "source": [ + "def describe(game, note):\n", + " root = game.root.infoset\n", + " leaves = sum(1 for node in game._gambit_().nodes if node.is_terminal)\n", + " print(f\"{note:18s} root: {root.player.label:5s} \"\n", + " f\"{[action.label for action in root.actions]}, {leaves} leaves\")\n", + "\n", + "\n", + "editable = ExtensiveFormGame(players=[\"Alice\", \"Bob\"])\n", + "editable.append_move(editable.root, \"Alice\", [\"L\", \"R\"])\n", + "editable.set_outcome(editable.root.children[\"L\"], \"L\", [2, 5])\n", + "editable.set_outcome(editable.root.children[\"R\"], \"R\", [3, 1])\n", + "describe(editable, \"as built\")\n", + "\n", + "editable.insert_move(editable.root, \"Bob\", [\"play\", \"walk\"])\n", + "describe(editable, \"after insert_move\")\n", + "\n", + "editable.delete_tree(editable.root.children[\"play\"])\n", + "describe(editable, \"after delete_tree\")" + ] + }, + { + "cell_type": "markdown", + "id": "cdcdca5d", + "metadata": {}, + "source": [ + "## Moving games between Sage and Gambit\n", + "\n", + "An `ExtensiveFormGame` can also wrap a tree game you already built with PyGambit. The wrapper does not copy anything — `_gambit_` hands back the very same object, so the two views stay in sync." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "bf14b609", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:16:35.393386Z", + "iopub.status.busy": "2026-08-23T17:16:35.393197Z", + "iopub.status.idle": "2026-08-23T17:16:35.398241Z", + "shell.execute_reply": "2026-08-23T17:16:35.397614Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(An extensive form game with 2 players, True)" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tree = gbt.Game.new_tree(players=[\"Alice\", \"Bob\"], title=\"tiny\")\n", + "tree.append_move(tree.root, tree.players[\"Alice\"], [\"L\", \"R\"])\n", + "for leaf, label, payoff in zip(tree.root.children, [\"L\", \"R\"],\n", + " [[2, 5], [3, 1]], strict=True):\n", + " tree.set_outcome(leaf, tree.add_outcome(label, payoff))\n", + "\n", + "wrapped = ExtensiveFormGame(tree)\n", + "wrapped, wrapped._gambit_() is tree" + ] + }, + { + "cell_type": "markdown", + "id": "b7dfd7d5", + "metadata": {}, + "source": [ + "Games can be written to and read from Gambit's `.efg` format, so a tree built in Sage can be opened in the Gambit GUI and vice versa.\n", + "As in the strategic form, `save_efg` writes the game the object holds and so is an ordinary method, while `load_efg` builds a new game from a file and so is a class method." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "02488d73", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:16:35.399604Z", + "iopub.status.busy": "2026-08-23T17:16:35.399427Z", + "iopub.status.idle": "2026-08-23T17:16:35.404528Z", + "shell.execute_reply": "2026-08-23T17:16:35.403939Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(An extensive form game with 2 players, 3)" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "path = tmp_filename(ext=\".efg\")\n", + "poker.save_efg(path)\n", + "\n", + "reloaded = ExtensiveFormGame.load_efg(path)\n", + "reloaded, len(reloaded.infosets)" + ] + }, + { + "cell_type": "markdown", + "id": "f997d2f4", + "metadata": {}, + "source": [ + "## The game catalog\n", + "\n", + "As in the strategic form case, Gambit's catalog of games from the literature is available directly, through the same pair of class methods. `ExtensiveFormGame.gambit_catalog_games` lists only the tree games, since those are the ones that keep their structure here." + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "dc58a657", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:16:35.405962Z", + "iopub.status.busy": "2026-08-23T17:16:35.405786Z", + "iopub.status.idle": "2026-08-23T17:16:35.429807Z", + "shell.execute_reply": "2026-08-23T17:16:35.428939Z" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
GameTitle
0journals/ijgt/selten1975/fig1Selten's horse (Selten IJGT 1975, Figure 1)
1journals/ijgt/selten1975/fig3Selten (IJGT 1975) Figure 3
\n", + "
" + ], + "text/plain": [ + " Game Title\n", + "0 journals/ijgt/selten1975/fig1 Selten's horse (Selten IJGT 1975, Figure 1)\n", + "1 journals/ijgt/selten1975/fig3 Selten (IJGT 1975) Figure 3" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ExtensiveFormGame.gambit_catalog_games(n_players=3)" + ] + }, + { + "cell_type": "markdown", + "id": "5f393739", + "metadata": {}, + "source": [ + "Selten's horse is the classic example of a Nash equilibrium that is not sequentially rational." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "ef08e1d5", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:16:35.431469Z", + "iopub.status.busy": "2026-08-23T17:16:35.431251Z", + "iopub.status.idle": "2026-08-23T17:16:35.436442Z", + "shell.execute_reply": "2026-08-23T17:16:35.435824Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(An extensive form game with 3 players, [[1, 1, 1], [3, 2, 2]])" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "horse = ExtensiveFormGame.load_from_gambit_catalog(\"journals/ijgt/selten1975/fig1\")\n", + "\n", + "horse, payoff_table(horse, horse.obtain_nash(algorithm=\"enumpure\"))" + ] + }, + { + "cell_type": "markdown", + "id": "bf6cd8ae", + "metadata": {}, + "source": [ + "Both are Nash equilibria, but only one of them survives if you insist that every player behave optimally at every information set they might reach.\n", + "\n", + "The usual tool for ruling out the other one is subgame perfection, and here it is no help at all: only the root begins a subgame, so the game has no *proper* subgames to refine away anything. That is exactly why Selten introduced this example." + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "f1b81467", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:16:35.438175Z", + "iopub.status.busy": "2026-08-23T17:16:35.438003Z", + "iopub.status.idle": "2026-08-23T17:16:35.441487Z", + "shell.execute_reply": "2026-08-23T17:16:35.440748Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[True, False, False]" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "[node.is_subgame_root for node in [horse.root,\n", + " horse.root.children[\"L\"],\n", + " horse.root.children[\"R\"]]]" + ] + }, + { + "cell_type": "markdown", + "id": "9738648b", + "metadata": {}, + "source": [ + "## Case study: the absent-minded driver\n", + "\n", + "Gambit's solvers assume **perfect recall**. When a game violates that assumption they refuse to compute equilibria for it — and they are right to, because the standard theory does not apply.\n", + "\n", + "The best known such game is Piccione and Rubinstein's absent-minded driver. A driver must take the second of two identical exits. The two junctions look exactly the same, so they lie in one information set, and at each the driver either continues or exits. Since he cannot tell them apart, he cannot condition on which one he is at.\n", + "\n", + "Gilboa's version of the game is in the catalog." + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "e0da0793", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:16:35.443297Z", + "iopub.status.busy": "2026-08-23T17:16:35.443130Z", + "iopub.status.idle": "2026-08-23T17:16:35.446842Z", + "shell.execute_reply": "2026-08-23T17:16:35.446354Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(An extensive form game with 1 player, False, 1)" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "driver = ExtensiveFormGame.load_from_gambit_catalog(\"journals/geb/gilboa1997/fig1\")\n", + "\n", + "driver, driver.is_perfect_recall, len(driver.infosets)" + ] + }, + { + "cell_type": "markdown", + "id": "6ffa0b96", + "metadata": {}, + "source": [ + "One player, one information set, and no perfect recall. Asking for equilibria says so:" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "c744b4c8", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:16:35.448253Z", + "iopub.status.busy": "2026-08-23T17:16:35.448093Z", + "iopub.status.idle": "2026-08-23T17:16:35.451768Z", + "shell.execute_reply": "2026-08-23T17:16:35.451085Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Computing equilibria of games with imperfect recall is not supported.\n" + ] + } + ], + "source": [ + "try:\n", + " driver.obtain_nash(algorithm=\"liap\")\n", + "except RuntimeError as error:\n", + " print(error)" + ] + }, + { + "cell_type": "markdown", + "id": "0e3a4a94", + "metadata": {}, + "source": [ + "What we can still do is hand Gambit a *plan* and ask what it is worth. A plan here is a single number: the probability $p$ of continuing at a junction. Gambit evaluates it exactly." + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "c2be3c93", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:16:35.453106Z", + "iopub.status.busy": "2026-08-23T17:16:35.452948Z", + "iopub.status.idle": "2026-08-23T17:16:35.457941Z", + "shell.execute_reply": "2026-08-23T17:16:35.457386Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[(0, 0), (1/4, 13/16), (1/2, 5/4), (3/4, 21/16), (1, 1)]" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "game = driver._gambit_()\n", + "\n", + "\n", + "def value(p):\n", + " \"\"\"Expected payoff of continuing with probability ``p`` at each junction.\"\"\"\n", + " plan = game.mixed_behavior_profile(rational=True)\n", + " plan[game.actions[\"B\"]] = Fraction(str(p))\n", + " plan[game.actions[\"E\"]] = Fraction(str(1 - p))\n", + " return QQ(plan.payoff(game.players[\"Player 1\"]))\n", + "\n", + "\n", + "[(p, value(p)) for p in [0, 1/4, 1/2, 3/4, 1]]" + ] + }, + { + "cell_type": "markdown", + "id": "23a2d8ce", + "metadata": {}, + "source": [ + "Gambit evaluates one plan at a time. Sage can recover the whole function.\n", + "\n", + "The value is a polynomial in $p$ of degree two — the driver passes at most two junctions — so five exact sample points are more than enough to reconstruct it by interpolation over `QQ`. No floating point, no curve fitting." + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "2a7c9b5b", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:16:35.459541Z", + "iopub.status.busy": "2026-08-23T17:16:35.459375Z", + "iopub.status.idle": "2026-08-23T17:16:35.465665Z", + "shell.execute_reply": "2026-08-23T17:16:35.465061Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "-3*p^2 + 4*p" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "R = QQ[\"p\"]\n", + "value_polynomial = R.lagrange_polynomial([(p, value(p))\n", + " for p in [0, 1/4, 1/2, 3/4, 1]])\n", + "value_polynomial" + ] + }, + { + "cell_type": "markdown", + "id": "290c348e", + "metadata": {}, + "source": [ + "With the value function in hand, finding the best plan is calculus, which is exactly what Sage is for." + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "4a8d3a41", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:16:35.467002Z", + "iopub.status.busy": "2026-08-23T17:16:35.466837Z", + "iopub.status.idle": "2026-08-23T17:16:36.994661Z", + "shell.execute_reply": "2026-08-23T17:16:36.994075Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[p == (2/3)]" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "p = var(\"p\")\n", + "expected_value = value_polynomial(p)\n", + "\n", + "critical_points = solve(diff(expected_value, p) == 0, p)\n", + "critical_points" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "5512a160", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:16:36.996060Z", + "iopub.status.busy": "2026-08-23T17:16:36.995871Z", + "iopub.status.idle": "2026-08-23T17:16:36.999270Z", + "shell.execute_reply": "2026-08-23T17:16:36.998706Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(2/3, 4/3)" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "p_star = critical_points[0].rhs()\n", + "p_star, expected_value.subs(p=p_star)" + ] + }, + { + "cell_type": "markdown", + "id": "24325d35", + "metadata": {}, + "source": [ + "So the driver's best plan is to continue with probability $2/3$, worth $4/3$ — both exact.\n", + "\n", + "The interesting part is the comparison with $p = 1/3$, the probability at which the driver, reasoning at a junction about what to do *now*, is indifferent between continuing and exiting. That plan is worth only $1$. Planning ahead and reasoning in the moment give genuinely different answers, which is the whole point of the example." + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "d4fd2ac6", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:16:37.000631Z", + "iopub.status.busy": "2026-08-23T17:16:37.000476Z", + "iopub.status.idle": "2026-08-23T17:16:37.003881Z", + "shell.execute_reply": "2026-08-23T17:16:37.003301Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(1, 4/3)" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "value(1/3), value(p_star)" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "774ca496", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:16:37.005227Z", + "iopub.status.busy": "2026-08-23T17:16:37.005069Z", + "iopub.status.idle": "2026-08-23T17:16:37.144685Z", + "shell.execute_reply": "2026-08-23T17:16:37.144073Z" + } + }, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "Graphics object consisting of 3 graphics primitives" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "plot(expected_value, (p, 0, 1), thickness=2, gridlines=True,\n", + " axes_labels=[\"probability $p$ of continuing\", \"expected payoff\"]) \\\n", + " + point((p_star, value(p_star)), size=60, color=\"red\") \\\n", + " + point((1/3, value(1/3)), size=60, color=\"green\")" + ] + }, + { + "cell_type": "markdown", + "id": "0836d3c8", + "metadata": {}, + "source": [ + "The red point is the optimal plan, the green one the point of indifference at a junction.\n", + "\n", + "Gambit evaluated the plans; Sage found the function behind them and optimised it. Neither step works without the other.\n", + "\n", + "## Summary\n", + "\n", + "| Task | Call |\n", + "|---|---|\n", + "| New tree | `ExtensiveFormGame(players=[...])` |\n", + "| Wrap a PyGambit tree | `ExtensiveFormGame(game)` |\n", + "| Add a move | `game.append_move(node, player, actions)` |\n", + "| Add a move by chance | `game.append_chance_move(node, actions, probs)` |\n", + "| Change chance probabilities | `game.set_chance_probs(node, probs)` |\n", + "| Bundle nodes into one information set | `game.append_infoset(node, like)` |\n", + "| Attach payoffs | `game.set_outcome(node, label, payoffs)` |\n", + "| Award an existing outcome again | `game.set_outcome(node, outcome)` |\n", + "| Insert a move above a node | `game.insert_move(node, player, actions)` |\n", + "| Cut a subtree | `game.delete_tree(node)` |\n", + "| Navigate | `game.root.children['action']` |\n", + "| Inspect | `game.players`, `game.infosets`, `game.outcomes` |\n", + "| Check the recall assumption | `game.is_perfect_recall` |\n", + "| Solve | `game.obtain_nash(algorithm='enumpure')` |\n", + "| Solve the reduced strategic form | `game.obtain_nash(use_strategic=True)` |\n", + "| Ask for floating point answers | `game.obtain_nash(rational=False)` |\n", + "| Draw | `game.plot(backend='sage')`, `game.plot(backend='gtdraw')` |\n", + "| Show the tree as text | `game.to_efg()` |\n", + "| Read and write `.efg` | `ExtensiveFormGame.load_efg(path)`, `game.save_efg(path)` |\n", + "| Browse the catalog | `ExtensiveFormGame.gambit_catalog_games()` |\n", + "| Load a catalog game | `ExtensiveFormGame.load_from_gambit_catalog(slug)` |\n", + "\n", + "Further reading:\n", + "\n", + "- [SageMath game theory reference](https://doc.sagemath.org/html/en/reference/game_theory/index.html)\n", + "- [PyGambit API documentation](https://gambitproject.readthedocs.io/en/latest/pygambit.api.html)\n", + "- [Gambit's own extensive form tutorial](../02_extensive_form.ipynb)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "SageMath 10.10.beta6", + "language": "sage", + "name": "sagemath" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.13" + }, + "nbsphinx": { + "execute": "never" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/doc/tutorials/interoperability_tutorials/sagemath_normal_form.ipynb b/doc/tutorials/interoperability_tutorials/sagemath_normal_form.ipynb new file mode 100644 index 000000000..659dc14ed --- /dev/null +++ b/doc/tutorials/interoperability_tutorials/sagemath_normal_form.ipynb @@ -0,0 +1,1692 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "1c480c77", + "metadata": {}, + "source": [ + "# Using Gambit with SageMath: strategic form games\n", + "\n", + "[SageMath](https://www.sagemath.org/) is a general-purpose open-source mathematics system built on top of Python.\n", + "Its `sage.game_theory` module includes a `NormalFormGame` class, which integrates Gambit solvers.\n", + "\n", + "This tutorial shows how a game can be created and analyzed by the two libraries, walks through each part of the interface, and finishes with two case studies that use SageMath to do things Gambit cannot do on its own: solving a game whose payoffs are *symbols* rather than numbers, and building a game out of a combinatorial object.\n", + "\n", + "The clear benefit of using both libraries is their combined expertise:\n", + "\n", + "- **Gambit** knows how to compute equilibria. Its solvers are fast, numerous, and established.\n", + "- **SageMath** knows how to do mathematics *around* the game: exact rational and symbolic algebra, graphs and other combinatorial structures, plotting, and calculus.\n", + "\n", + "> **Requirements.** This tutorial uses the SageMath interface introduced in [sagemath/sage#42367](https://github.com/sagemath/sage/pull/42367), which at the time of writing has not yet been released.\n", + "> You will need a SageMath build containing that work, plus the optional `pygambit` package (`sage --pip install pygambit`).\n", + "> Run the notebook with the **SageMath kernel**, not a plain Python kernel: the examples below rely on Sage's preparser, which makes `1/3` an exact rational rather than a floating point number." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "d1134409", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:12:24.207645Z", + "iopub.status.busy": "2026-08-23T17:12:24.207516Z", + "iopub.status.idle": "2026-08-23T17:12:26.598272Z", + "shell.execute_reply": "2026-08-23T17:12:26.597746Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "SageMath 10.10.beta8 | pygambit 16.7.0\n" + ] + } + ], + "source": [ + "import itertools\n", + "\n", + "import numpy as np\n", + "from sage.version import version\n", + "\n", + "import pygambit as gbt\n", + "\n", + "print(\"SageMath\", version, \"| pygambit\", gbt.__version__)" + ] + }, + { + "cell_type": "markdown", + "id": "84b38ee5", + "metadata": {}, + "source": [ + "## From a Gambit game to a Sage game\n", + "\n", + "We start on the Gambit side, with the Prisoner's Dilemma built from a pair of payoff arrays." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "bb4c86e2", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:12:26.599552Z", + "iopub.status.busy": "2026-08-23T17:12:26.599377Z", + "iopub.status.idle": "2026-08-23T17:12:26.603404Z", + "shell.execute_reply": "2026-08-23T17:12:26.602862Z" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "

Prisoner's Dilemma

\n", + "
2
12
113,30,5
25,01,1
\n" + ], + "text/plain": [ + "Game(title='Prisoner's Dilemma')" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pd_gambit = gbt.Game.from_arrays(\n", + " np.array([[3, 0], [5, 1]]),\n", + " np.array([[3, 5], [0, 1]]),\n", + " title=\"Prisoner's Dilemma\",\n", + ")\n", + "pd_gambit" + ] + }, + { + "cell_type": "markdown", + "id": "c96064c9", + "metadata": {}, + "source": [ + "Passing that `Game` straight to `NormalFormGame` converts it.\n", + "A Sage normal form game is a mapping from strategy profiles (tuples of integers) to lists of payoffs, so this is what we get back:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "863f135f", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:12:26.604567Z", + "iopub.status.busy": "2026-08-23T17:12:26.604446Z", + "iopub.status.idle": "2026-08-23T17:12:26.643128Z", + "shell.execute_reply": "2026-08-23T17:12:26.642485Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "Normal Form Game with the following utilities: {(0, 0): [3, 3], (0, 1): [0, 5], (1, 0): [5, 0], (1, 1): [1, 1]}" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pd = NormalFormGame(pd_gambit)\n", + "pd" + ] + }, + { + "cell_type": "markdown", + "id": "d69f3883", + "metadata": {}, + "source": [ + "Gambit stores payoffs either as exact rationals or as decimals, and Sage keeps this distinction. The integer payoffs above came back as elements of `QQ`, which is the field of rational numbers, and *not* as floating point approximations." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "e4fb56bb", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:12:26.644478Z", + "iopub.status.busy": "2026-08-23T17:12:26.644283Z", + "iopub.status.idle": "2026-08-23T17:12:26.648068Z", + "shell.execute_reply": "2026-08-23T17:12:26.647339Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "Rational Field" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "parent(pd.utilities[(0, 0)][0])" + ] + }, + { + "cell_type": "markdown", + "id": "4693f7cf", + "metadata": {}, + "source": [ + "That matters for all downstream applications. `payoff_matrices` returns the two payoff matrices as Sage matrices over `QQ`, which we can then do linear algebra on." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "6608cae6", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:12:26.649329Z", + "iopub.status.busy": "2026-08-23T17:12:26.649185Z", + "iopub.status.idle": "2026-08-23T17:12:26.656284Z", + "shell.execute_reply": "2026-08-23T17:12:26.655796Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(\n", + "[3 0] [3 5] \n", + "[5 1], [0 1], Rational Field\n", + ")" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "A, B = pd.payoff_matrices()\n", + "A, B, A.base_ring()" + ] + }, + { + "cell_type": "markdown", + "id": "3bc37b15", + "metadata": {}, + "source": [ + "## From a Sage game to a Gambit game\n", + "\n", + "The other direction is the `_gambit_` method, which every Sage `NormalFormGame` provides.\n", + "It returns a `pygambit.Game`, so the whole Gambit API is available from there, including writing the game out in Gambit's own strategic form format.\n", + "To test this out, we will load the Prisoner's Dilemma directly from the SageMath strategic game catalog." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "5e49d4cf", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:12:26.657551Z", + "iopub.status.busy": "2026-08-23T17:12:26.657408Z", + "iopub.status.idle": "2026-08-23T17:12:26.662200Z", + "shell.execute_reply": "2026-08-23T17:12:26.661783Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "NFG 1 R \"Untitled strategic game\" { \"1\" \"2\" }\n", + "\n", + "{ { \"1\" \"2\" }\n", + "{ \"1\" \"2\" }\n", + "}\n", + "\"\"\n", + "\n", + "{\n", + "{ \"\" -2, -2 }\n", + "{ \"\" 0, -5 }\n", + "{ \"\" -5, 0 }\n", + "{ \"\" -4, -4 }\n", + "}\n", + "1 2 3 4 \n", + "\n" + ] + } + ], + "source": [ + "pd = game_theory.normal_form_games.PrisonersDilemma()\n", + "print(pd._gambit_().to_nfg())" + ] + }, + { + "cell_type": "markdown", + "id": "0f683478", + "metadata": {}, + "source": [ + "Payoffs are handed to Gambit one at a time, and each keeps the kind of value it is: an exact Sage integer or rational becomes a Gambit `Rational`, an inexact real becomes a Gambit `Decimal`. Nothing is rounded or truncated on the way." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "fecfdf0f", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:12:26.663581Z", + "iopub.status.busy": "2026-08-23T17:12:26.663453Z", + "iopub.status.idle": "2026-08-23T17:12:26.666821Z", + "shell.execute_reply": "2026-08-23T17:12:26.666399Z" + } + }, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\frac{1}{3}$" + ], + "text/plain": [ + "Rational(1, 3)" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "exact = NormalFormGame([matrix(QQ, [[1/3, 2], [1, 5/7]])])._gambit_()\n", + "exact[\"1\", \"1\"][exact.players[\"1\"]]" + ] + }, + { + "cell_type": "markdown", + "id": "42bda8b9", + "metadata": {}, + "source": [ + "`_gambit_` takes one option. `maximization=False` negates every payoff, so a game written down in terms of *costs* is handed to Gambit as a game to be maximised." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "537d16f8", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:12:26.668042Z", + "iopub.status.busy": "2026-08-23T17:12:26.667906Z", + "iopub.status.idle": "2026-08-23T17:12:26.671281Z", + "shell.execute_reply": "2026-08-23T17:12:26.670724Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[-2, 2]" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "g_max = pd._gambit_()\n", + "g_min = pd._gambit_(maximization=False)\n", + "\n", + "[QQ(g_max[\"1\", \"1\"][g_max.players[\"1\"]]),\n", + " QQ(g_min[\"1\", \"1\"][g_min.players[\"1\"]])]" + ] + }, + { + "cell_type": "markdown", + "id": "9cc777d6", + "metadata": {}, + "source": [ + "## Saving and loading games\n", + "\n", + "Because the conversion goes through Gambit, Sage can read and write Gambit's `.nfg` files directly.\n", + "This is the simplest way to move a game between a Sage session and the Gambit GUI, or to keep a game under version control.\n", + "\n", + "`save_nfg` writes the game the object holds, so it is an ordinary method. `load_nfg` builds a *new* game from a file, so it is a class method: call it on the class and it hands you the game back." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "74dbb8a2", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:12:26.672369Z", + "iopub.status.busy": "2026-08-23T17:12:26.672254Z", + "iopub.status.idle": "2026-08-23T17:12:26.676158Z", + "shell.execute_reply": "2026-08-23T17:12:26.675652Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "Normal Form Game with the following utilities: {(0, 0): [-2, -2], (0, 1): [-5, 0], (1, 0): [0, -5], (1, 1): [-4, -4]}" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "path = tmp_filename(ext=\".nfg\")\n", + "pd.save_nfg(path)\n", + "\n", + "reloaded = NormalFormGame.load_nfg(path)\n", + "reloaded" + ] + }, + { + "cell_type": "markdown", + "id": "15f5764a", + "metadata": {}, + "source": [ + "The round trip is exact. Gambit's `.nfg` format records a rational payoff as a fraction rather than a decimal, so a game of exact payoffs survives a trip through the disk unchanged." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "1f4c31df", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:12:26.677314Z", + "iopub.status.busy": "2026-08-23T17:12:26.677183Z", + "iopub.status.idle": "2026-08-23T17:12:26.681753Z", + "shell.execute_reply": "2026-08-23T17:12:26.681239Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(1/3, Rational Field)" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fractions = NormalFormGame([matrix(QQ, [[1/3, 2], [1, 5/7]])])\n", + "path = tmp_filename(ext=\".nfg\")\n", + "fractions.save_nfg(path)\n", + "\n", + "back = NormalFormGame.load_nfg(path)\n", + "back.utilities[(0, 0)][0], parent(back.utilities[(0, 0)][0])" + ] + }, + { + "cell_type": "markdown", + "id": "f480f1f8", + "metadata": {}, + "source": [ + "## The Gambit game catalog\n", + "\n", + "As SageMath's catalog of normal form games consists of mostly simpler, common games, we extend it by Gambit's catalog. It allows Sage to access a variety of games from the research literature.\n", + "\n", + "Listing and loading are two separate class methods. `gambit_catalog_games` returns a table of what is available." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "e871f78c", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:12:26.682904Z", + "iopub.status.busy": "2026-08-23T17:12:26.682770Z", + "iopub.status.idle": "2026-08-23T17:12:26.703831Z", + "shell.execute_reply": "2026-08-23T17:12:26.703310Z" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
GameTitle
0books/myerson1991/fig2_1A simple Poker game
1books/myerson1991/fig4_2Myerson (1991) Figure 4.2
2books/shohamleytonbrown2008/fig5_1Fig 5.1 from Shoham and Leyton-Brown (2008)
3books/shohamleytonbrown2008/fig5_10Fig 5.10 from Shoham and Leyton-Brown (2008)
4books/shohamleytonbrown2008/fig5_11Fig 5.11 from Shoham and Leyton-Brown (2008)
5books/shohamleytonbrown2008/fig5_12Fig 5.12 from Shoham and Leyton-Brown (2008)
6books/shohamleytonbrown2008/fig5_15Fig 5.15 from Shoham and Leyton-Brown (2008)
7books/shohamleytonbrown2008/fig5_2Fig 5.2 from Shoham and Leyton-Brown (2008)
8books/shohamleytonbrown2008/fig5_9Fig 5.9 from Shoham and Leyton-Brown (2008)
9books/shohamleytonbrown2008/fig6_2Fig 6.2 from Shoham and Leyton-Brown (2008)
10books/shohamleytonbrown2008/fig6_8Fig 6.8 from Shoham and Leyton-Brown (2008)
11books/vonstengel2022/fig10.1Figure 10.1 from von Stengel (2022)
12books/vonstengel2022/fig10.12Figure 10.12 from von Stengel (2022)
13books/vonstengel2022/fig10.5Figure 10.5 from von Stengel (2022)
14books/vonstengel2022/fig10.7Figure 10.7 from von Stengel (2022)
15books/watson2013/exercise29_6Princess Bride signaling game (from Watson)
16books/watson2013/fig29_1Job-market signaling game (version from Watson)
17conf/itcs/jakobsen2016/fig1aJakobsen, Sorensen, Conitzer (2016) Figure 1(a)
18conf/itcs/jakobsen2016/fig1bJakobsen, Sorensen, Conitzer (2016) Figure 1(b)
19conf/itcs/jakobsen2016/fig1cJakobsen, Sorensen, Conitzer (2016) Figure 1(c)
20conf/itcs/jakobsen2016/fig3Jakobsen, Sorensen, Conitzer (2016) Figure 3
21journals/geb/bagwell1995Bagwell (GEB 1995) commitment and (un)observab...
22journals/geb/gilboa1997/fig1Absent-Minded Driver (Gilboa 1997, GEB, Figure 2)
23journals/geb/gilboa1997/fig2Two-Selves Absent-Minded Driver (Gilboa 1997, ...
24journals/geb/wichardt2008Wichardt (2008): 2 players, imperfect recall
25journals/ijgt/nau2004/sec3Battle of the Sexes
26journals/ijgt/nau2004/sec4Three-player game with a unique Nash solution ...
27journals/ijgt/nau2004/sec5Game with a continuum of completely mixed-stra...
28journals/ijgt/nau2004/sec62x2x4 game with Nash equilibria in the relativ...
29journals/ijgt/selten1975/fig1Selten's horse (Selten IJGT 1975, Figure 1)
30journals/ijgt/selten1975/fig2Selten (IJGT 1975) Figure 2
31journals/ijgt/selten1975/fig3Selten (IJGT 1975) Figure 3
32journals/mor/vonstengelforges2008/fig1Figure 1 from von Stengel and Forges (2008)
33journals/mor/vonstengelforges2008/fig6Figure 6 from von Stengel and Forges (2008)
34journals/mor/vonstengelforges2008/fig9Figure 9 from von Stengel and Forges (2008)
35journals/other/reiley2008/fig1Stripped-down poker (Reiley et al 2008)
36journals/other/shapley1974/fig2Fig 2 from 'A Note on the Lemke-Howson Algorit...
37journals/other/shapley1974/fig3Fig 3 from 'A Note on the Lemke-Howson Algorit...
\n", + "
" + ], + "text/plain": [ + " Game \\\n", + "0 books/myerson1991/fig2_1 \n", + "1 books/myerson1991/fig4_2 \n", + "2 books/shohamleytonbrown2008/fig5_1 \n", + "3 books/shohamleytonbrown2008/fig5_10 \n", + "4 books/shohamleytonbrown2008/fig5_11 \n", + "5 books/shohamleytonbrown2008/fig5_12 \n", + "6 books/shohamleytonbrown2008/fig5_15 \n", + "7 books/shohamleytonbrown2008/fig5_2 \n", + "8 books/shohamleytonbrown2008/fig5_9 \n", + "9 books/shohamleytonbrown2008/fig6_2 \n", + "10 books/shohamleytonbrown2008/fig6_8 \n", + "11 books/vonstengel2022/fig10.1 \n", + "12 books/vonstengel2022/fig10.12 \n", + "13 books/vonstengel2022/fig10.5 \n", + "14 books/vonstengel2022/fig10.7 \n", + "15 books/watson2013/exercise29_6 \n", + "16 books/watson2013/fig29_1 \n", + "17 conf/itcs/jakobsen2016/fig1a \n", + "18 conf/itcs/jakobsen2016/fig1b \n", + "19 conf/itcs/jakobsen2016/fig1c \n", + "20 conf/itcs/jakobsen2016/fig3 \n", + "21 journals/geb/bagwell1995 \n", + "22 journals/geb/gilboa1997/fig1 \n", + "23 journals/geb/gilboa1997/fig2 \n", + "24 journals/geb/wichardt2008 \n", + "25 journals/ijgt/nau2004/sec3 \n", + "26 journals/ijgt/nau2004/sec4 \n", + "27 journals/ijgt/nau2004/sec5 \n", + "28 journals/ijgt/nau2004/sec6 \n", + "29 journals/ijgt/selten1975/fig1 \n", + "30 journals/ijgt/selten1975/fig2 \n", + "31 journals/ijgt/selten1975/fig3 \n", + "32 journals/mor/vonstengelforges2008/fig1 \n", + "33 journals/mor/vonstengelforges2008/fig6 \n", + "34 journals/mor/vonstengelforges2008/fig9 \n", + "35 journals/other/reiley2008/fig1 \n", + "36 journals/other/shapley1974/fig2 \n", + "37 journals/other/shapley1974/fig3 \n", + "\n", + " Title \n", + "0 A simple Poker game \n", + "1 Myerson (1991) Figure 4.2 \n", + "2 Fig 5.1 from Shoham and Leyton-Brown (2008) \n", + "3 Fig 5.10 from Shoham and Leyton-Brown (2008) \n", + "4 Fig 5.11 from Shoham and Leyton-Brown (2008) \n", + "5 Fig 5.12 from Shoham and Leyton-Brown (2008) \n", + "6 Fig 5.15 from Shoham and Leyton-Brown (2008) \n", + "7 Fig 5.2 from Shoham and Leyton-Brown (2008) \n", + "8 Fig 5.9 from Shoham and Leyton-Brown (2008) \n", + "9 Fig 6.2 from Shoham and Leyton-Brown (2008) \n", + "10 Fig 6.8 from Shoham and Leyton-Brown (2008) \n", + "11 Figure 10.1 from von Stengel (2022) \n", + "12 Figure 10.12 from von Stengel (2022) \n", + "13 Figure 10.5 from von Stengel (2022) \n", + "14 Figure 10.7 from von Stengel (2022) \n", + "15 Princess Bride signaling game (from Watson) \n", + "16 Job-market signaling game (version from Watson) \n", + "17 Jakobsen, Sorensen, Conitzer (2016) Figure 1(a) \n", + "18 Jakobsen, Sorensen, Conitzer (2016) Figure 1(b) \n", + "19 Jakobsen, Sorensen, Conitzer (2016) Figure 1(c) \n", + "20 Jakobsen, Sorensen, Conitzer (2016) Figure 3 \n", + "21 Bagwell (GEB 1995) commitment and (un)observab... \n", + "22 Absent-Minded Driver (Gilboa 1997, GEB, Figure 2) \n", + "23 Two-Selves Absent-Minded Driver (Gilboa 1997, ... \n", + "24 Wichardt (2008): 2 players, imperfect recall \n", + "25 Battle of the Sexes \n", + "26 Three-player game with a unique Nash solution ... \n", + "27 Game with a continuum of completely mixed-stra... \n", + "28 2x2x4 game with Nash equilibria in the relativ... \n", + "29 Selten's horse (Selten IJGT 1975, Figure 1) \n", + "30 Selten (IJGT 1975) Figure 2 \n", + "31 Selten (IJGT 1975) Figure 3 \n", + "32 Figure 1 from von Stengel and Forges (2008) \n", + "33 Figure 6 from von Stengel and Forges (2008) \n", + "34 Figure 9 from von Stengel and Forges (2008) \n", + "35 Stripped-down poker (Reiley et al 2008) \n", + "36 Fig 2 from 'A Note on the Lemke-Howson Algorit... \n", + "37 Fig 3 from 'A Note on the Lemke-Howson Algorit... " + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "NormalFormGame.gambit_catalog_games()" + ] + }, + { + "cell_type": "markdown", + "id": "4a0ef38f", + "metadata": {}, + "source": [ + "Its keyword arguments are passed on to Gambit's own catalog listing, so the table can be filtered — by the number of players, for instance." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "72d366ce", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:12:26.704968Z", + "iopub.status.busy": "2026-08-23T17:12:26.704838Z", + "iopub.status.idle": "2026-08-23T17:12:26.716989Z", + "shell.execute_reply": "2026-08-23T17:12:26.716487Z" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
GameTitle
0journals/ijgt/nau2004/sec4Three-player game with a unique Nash solution ...
1journals/ijgt/nau2004/sec5Game with a continuum of completely mixed-stra...
2journals/ijgt/nau2004/sec62x2x4 game with Nash equilibria in the relativ...
3journals/ijgt/selten1975/fig1Selten's horse (Selten IJGT 1975, Figure 1)
4journals/ijgt/selten1975/fig3Selten (IJGT 1975) Figure 3
\n", + "
" + ], + "text/plain": [ + " Game \\\n", + "0 journals/ijgt/nau2004/sec4 \n", + "1 journals/ijgt/nau2004/sec5 \n", + "2 journals/ijgt/nau2004/sec6 \n", + "3 journals/ijgt/selten1975/fig1 \n", + "4 journals/ijgt/selten1975/fig3 \n", + "\n", + " Title \n", + "0 Three-player game with a unique Nash solution ... \n", + "1 Game with a continuum of completely mixed-stra... \n", + "2 2x2x4 game with Nash equilibria in the relativ... \n", + "3 Selten's horse (Selten IJGT 1975, Figure 1) \n", + "4 Selten (IJGT 1975) Figure 3 " + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "NormalFormGame.gambit_catalog_games(n_players=3)" + ] + }, + { + "cell_type": "markdown", + "id": "6b5ce8a5", + "metadata": {}, + "source": [ + "`load_from_gambit_catalog` takes a slug from the `Game` column and returns the game.\n", + "Here is Bagwell's game on commitment and observability:" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "818b0d19", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:12:26.718202Z", + "iopub.status.busy": "2026-08-23T17:12:26.718060Z", + "iopub.status.idle": "2026-08-23T17:12:26.721761Z", + "shell.execute_reply": "2026-08-23T17:12:26.721244Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "Normal Form Game with the following utilities: {(0, 0): [5, 2],\n", + " (0, 1): [249/50, 199/100],\n", + " (0, 2): [151/50, 101/100],\n", + " (0, 3): [3, 1],\n", + " (1, 0): [6, 3],\n", + " (1, 1): [201/50, 399/100],\n", + " (1, 2): [299/50, 301/100],\n", + " (1, 3): [4, 4]}" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "NormalFormGame.load_from_gambit_catalog(\"journals/geb/bagwell1995\")" + ] + }, + { + "cell_type": "markdown", + "id": "12fb5b1f", + "metadata": {}, + "source": [ + "That one is a tree game in Gambit's catalog, and a `NormalFormGame` is always a strategic form game, so it arrives as its reduced strategic form: each player's strategies are complete contingent plans rather than single moves. The companion tutorial loads the same game as a tree." + ] + }, + { + "cell_type": "markdown", + "id": "17c23058", + "metadata": {}, + "source": [ + "## Solving games\n", + "\n", + "`obtain_nash` is Sage's entry point to equilibrium computation.\n", + "Without a passed parameter of which algorithm to use, it picks a sensible default; with the specification of algorithm, it dispatches either to Sage's own exact routines or to one of Gambit's solvers.\n", + "\n", + "Our test case is the Battle of the Sexes, which has two pure equilibria and one mixed one." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "089e7b2a", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:12:26.722976Z", + "iopub.status.busy": "2026-08-23T17:12:26.722820Z", + "iopub.status.idle": "2026-08-23T17:12:26.790181Z", + "shell.execute_reply": "2026-08-23T17:12:26.789741Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[[(0, 1), (0, 1)], [(3/4, 1/4), (1/4, 3/4)], [(1, 0), (1, 0)]]" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "battle = NormalFormGame([matrix([[3, 1], [0, 2]]),\n", + " matrix([[2, 1], [0, 3]])])\n", + "battle.obtain_nash()" + ] + }, + { + "cell_type": "markdown", + "id": "908a8a1a", + "metadata": {}, + "source": [ + "The answer is *exact*: the mixed equilibrium comes out as `3/4` and `1/4`, not as decimals.\n", + "\n", + "That holds whichever solver computes it. `'enumeration'` stays in Sage, while `'LCP'` and `'enummixed'` are Gambit's, and all three agree exactly.\n", + "(Sage also offers `'lrs'`, which uses the external `lrslib` package; it is not installed here, so it is left out of the comparison below.)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "ab42b2c8", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:12:26.791590Z", + "iopub.status.busy": "2026-08-23T17:12:26.791456Z", + "iopub.status.idle": "2026-08-23T17:12:26.796941Z", + "shell.execute_reply": "2026-08-23T17:12:26.796402Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "enumeration [[(0, 1), (0, 1)], [(3/4, 1/4), (1/4, 3/4)], [(1, 0), (1, 0)]]\n", + "LCP [[(0, 1), (0, 1)], [(3/4, 1/4), (1/4, 3/4)], [(1, 0), (1, 0)]]\n", + "enummixed [[(0, 1), (0, 1)], [(3/4, 1/4), (1/4, 3/4)], [(1, 0), (1, 0)]]\n" + ] + } + ], + "source": [ + "for algorithm in [\"enumeration\", \"LCP\", \"enummixed\"]:\n", + " print(f\"{algorithm:12s}\", battle.obtain_nash(algorithm=algorithm))" + ] + }, + { + "cell_type": "markdown", + "id": "828a2894", + "metadata": {}, + "source": [ + "This is what the `rational` argument of `obtain_nash` does, and it defaults to `True`. Sage asks the solvers that have an exact mode — `'LCP'`, `'lp'` and `'enummixed'` — to compute in exact arithmetic throughout. The purely numerical ones (`'gnm'`, `'ipa'`, `'logit'`, `'liap'`, `'enumpoly'`) have no exact mode, so they compute in floating point and Sage then rounds the answer to the exact equilibrium it approximates, keeping the rounding only once Gambit has confirmed in exact arithmetic that it really is one. How far a probability may be moved to be rounded is set by `tolerance`.\n", + "\n", + "Passing `rational=False` skips all of that and returns what the solver computed." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "61546695", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:12:26.798212Z", + "iopub.status.busy": "2026-08-23T17:12:26.798065Z", + "iopub.status.idle": "2026-08-23T17:12:26.801437Z", + "shell.execute_reply": "2026-08-23T17:12:26.800798Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[[(0.0, 1.0), (0.0, 1.0)],\n", + " [(0.7499999999999999, 0.25), (0.24999999999999994, 0.7500000000000001)],\n", + " [(1.0, 0.0), (1.0, 0.0)]]" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "battle.obtain_nash(algorithm=\"LCP\", rational=False)" + ] + }, + { + "cell_type": "markdown", + "id": "15895aa1", + "metadata": {}, + "source": [ + "So exactness is no longer the thing that separates the two libraries: use Sage's solvers when you want its own exact routines on a small game, and Gambit's when the game is large enough that they become the bottleneck.\n", + "\n", + "Sage can also tell you whether the game is degenerate, which is worth checking before trusting an equilibrium count, and whether it is constant sum." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "17f544c1", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:12:26.802691Z", + "iopub.status.busy": "2026-08-23T17:12:26.802562Z", + "iopub.status.idle": "2026-08-23T17:12:26.805585Z", + "shell.execute_reply": "2026-08-23T17:12:26.804969Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(False, False)" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "battle.is_degenerate(), battle.is_constant_sum()" + ] + }, + { + "cell_type": "markdown", + "id": "d041d5a4", + "metadata": {}, + "source": [ + "## Games with more than two players\n", + "\n", + "A two player game is a pair of matrices, but a game with $n$ players needs $n$ payoff arrays of $n$ dimensions each, and a Sage matrix is only ever two dimensional.\n", + "For more than two players, pass NumPy arrays instead.\n", + "\n", + "Here is a three player consensus game: everybody picks one of two options, and everybody scores a point only if all three agree." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "fd8ee4e1", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:12:26.806820Z", + "iopub.status.busy": "2026-08-23T17:12:26.806687Z", + "iopub.status.idle": "2026-08-23T17:12:26.810774Z", + "shell.execute_reply": "2026-08-23T17:12:26.810260Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[[(0, 1), (0, 1), (0, 1)], [(1, 0), (1, 0), (1, 0)]]" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "agree = np.zeros((2, 2, 2), dtype=int)\n", + "agree[0, 0, 0] = 1\n", + "agree[1, 1, 1] = 1\n", + "\n", + "consensus = NormalFormGame([agree, agree, agree])\n", + "consensus.obtain_nash(algorithm=\"enumpure\")" + ] + }, + { + "cell_type": "markdown", + "id": "984ad51b", + "metadata": {}, + "source": [ + "Both \"everyone picks the first option\" and \"everyone picks the second\" are equilibria, as expected.\n", + "\n", + "Since Sage's own solvers only handle two players, every algorithm for larger games comes from the Gambit solver integration. These are: `'gnm'`, `'enumpure'`, `'enumpoly'`, `'liap'`, `'simpdiv'`, `'ipa'` and `'logit'`.\n", + "The default for a game with more than two players is `'enumpoly'`, which finds the mixed equilibrium too." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "76ef7676", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:12:26.812050Z", + "iopub.status.busy": "2026-08-23T17:12:26.811907Z", + "iopub.status.idle": "2026-08-23T17:12:26.824562Z", + "shell.execute_reply": "2026-08-23T17:12:26.824178Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[[(0, 1), (0, 1), (0, 1)],\n", + " [(1/2, 1/2), (1/2, 1/2), (1/2, 1/2)],\n", + " [(1, 0), (1, 0), (1, 0)]]" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "consensus.obtain_nash()" + ] + }, + { + "cell_type": "markdown", + "id": "503b6b13", + "metadata": {}, + "source": [ + "`'enumpoly'` is one of the solvers with no exact mode, so the `1/2` above is a rounded answer that Gambit then verified. A game of three or more players can have a genuinely irrational equilibrium, and there the rounding fails and the floating point answer is returned instead." + ] + }, + { + "cell_type": "markdown", + "id": "1ae76060", + "metadata": {}, + "source": [ + "## Plotting a game\n", + "\n", + "Sage can draw a two player game as a labelled payoff bimatrix, optionally marking each player's best responses and the pure equilibria." + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "5b711f6b", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:12:26.825863Z", + "iopub.status.busy": "2026-08-23T17:12:26.825727Z", + "iopub.status.idle": "2026-08-23T17:12:27.287971Z", + "shell.execute_reply": "2026-08-23T17:12:27.287488Z" + } + }, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAARoAAACwCAYAAADQQ6GGAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjksIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvJkbTWQAAAAlwSFlzAAAPYQAAD2EBqD+naQAAFvRJREFUeJztnQl0FFW6x/8kJoSwScBIJomKKEFEUAL6osyIICgcWR4zOgLywH0BXFBcUIEREI4buGZwAzfEUR+Kg8CgsogYlSiCYHgKOAjTMcIoSyAQSL3zz7WmO01IAuH2Uv3/nVOnu6vqVlffvvWv73731vfVcRzHgRBCWCTO5sGFEEJCI4QICbJohBDWkdAIIawjoRFCWEdCI4SwjoRGCGEdCY0QwjoSGiGEdSQ0QgjrSGiEENaR0AghrCOhEUJYR0IjhLCOhEYIYR0JjRDCOhIaIYR1JDRCCOtIaIQQ1pHQCCGsI6ERQlhHQiOEsI6ERghhnWPgMerXr4+SkhLEx8cjNTUVsUxRUREOHDigulBdHLJtJCUlobi4GLap47UEchSYsrKycJ+GEFFBXFxcueDYxnMWjSs0rMC0tDTEMj6fT3WhuqiybfB6CQWeExp2l7Zs2VIuMps3b0Ysk5GRobpQXVTZNkLlXpAzWAhhHQmNEMI6EhohhHUkNEII60hohBDWkdAIIawjoRFCWEdCI4SwjoRGCGEdCY0QwjoSGiGEdSQ0IWToUKBfv1B+o4hWxo0DzjwTnkFCcxgiUaeOf2naFLj4YmDVKrt/kIhN7rgD+PBDeAYJzWFAYfH5zMJGcMwxwCWX2PtzROzSoIG5mXkFCc1hULcu0Ly5WWjW3nUX8OOPwM8/m+2rVwNduwL16plGct11wK5dBx/nL39hOAugUSPg+uuBffsQsezcCQwaxMiFAMP7TJkCdOkC3Hqr2f7qq0DHjkDDhqZeBg5k9DZ/+cWLjQW4YAFw1lmmblhH3GfePOC000w9DBgA7N7tL8dwbA89BJx8sinTvj3w1lsIC/y9I0aY39ykCXD88cCzzwIMTHfllea3t2xpfo/LkiXA2WebNpOWBtx9N7B/v9k2bRqQng4Ex2fr0wcYMuTQXafp0019JSUBrVsDzzyDqEFCc4RQQF57DTjlFCMqvEho8bAhfvEF8OabwAcfAMOHVyxHS+jbb4FFi4DXXwdmzzbCE6mMHAl88gkwZw6wcCHw8cfAl1/6t1Mkx48Hvv4aeOcdYONG080MhhfOU08By5cbcb7sMmDqVGDmTGDuXHPsJ5/073/ffebCys0F1qwBbrsNuOIKcwGHg5deApo1Az7/3IjOjTcCl14KnHuuqY+LLgIGDzbtYMsWoFcvoFMnUy+5ucALLwATJphjsdzWraYNuPzyixFjinplPPcccO+9wMSJpv08+CBw//3mvKICx2Okp6czNGn569FkyBDHiY93nPr1zcKaS0tznPx8s/3ZZx2nSRPH2bXLX2buXMeJi3OcwkL/MVJSHKe42L9Pbq7jNGjgOAcOOBFXFzt2OE5CguO8+aZ/3a+/Ok5ysuPcckvlZT7/3NTNzp3m86JF5vMHH/j3mTTJrFu/3r/u+usd56KLzHvWYVKS4yxfXvHYV1/tOAMGhL4uzj/fcTp39n/ev9+0gcGD/et8PvObPv3UcUaPdpysLMcpK/Nvf/rpiv9znz6Oc9VV/u3TpjlO8+bm2GTsWMdp396/PTPTcWbOrHhe48c7Tk6OE1HXyaGQRXMYXHABsHKlWT77DOjRA+jZE/jnP81dhuY9uxgu551nzON16/zruE9ysv9zTo6xjniXjzQ2bABKS00XwKVxYyAry//5q6+Avn2BE080XQh2M8imTRWP1a6d/z27HqwDdosC17ldrrVrgZISoHt346twl5dfBtavR1gIPH9Gv6QVe8YZFc+f8DewLfB/ZZcxsC3s2gW4QR9pubz9NrB3r/lM6/jyy82xg2HXnO3j6qsr1gctpHDVB2I9lKdNKCLsKrlkZ5sLj2Yt72eBDSuQQ60/3H1CjRu2Pvjc3PX0UVBsudBXc9xxRmDYjQj2OyUk+N/zeIGf3XWuz8J9ZZeKvoxA6PMIB5Wdb/Bvcs+9srbgBNVl795mX/5GdrHYJX3sscq/260PtrNzzqm4LUQhf2uNhKYWsNHExQF79gBt2pj+Mi8+16qhb4PbW7Xyl2GfnfvTwUny8szdKSMDEQcdnLyY6JfIzDTrduwAvvsOOP98oKDA+BomT/ZvX7Gi9t/LuqSgULT4PdEGz5/WSqDgLF9uLD5XOPn/9+9vLJnvvzdthDeuyqC1xHK0MA/lw4l0JDSHAc3cwkK/847OTZrDvDuxezF2rBk1oOOT5i6dhnQQumY14Z2eJjCdnexysQwdxhSkSIMXBn/PqFFASooZKeP58lx5AZ1wApCYaJy4N9wAfPONcQwfje/lPBI6gHk379zZCBwvVoqyOzITqdx0k3F08//nf7tunak3OtYD/2eKBtsOnd10dFcF29TNN5sROnbX2RYp6myHPG6kI6E5DObPN0OV7sXAIUaOLrl+CY4a3HKLMYXpg/jjHw82h7t1A049FfjDH0xjYb+cjShS4flTRDhfiI38zjuNv4BDrOwqzZgBjB4NPPEE0KED8MgjZpi2tlCwKGyTJpk7+bHHmuPzuyIdWh/vv28Emj65lBT/zSUQDvNzG4WI0wKq4pprTJt6+GHzH9Bqpo/InWYQ6XgugZybRiI9PV3pVizUBbuGvJAefdRcPNGC2kV460MWjagSjirRF8Ou4fbtwAMPmPUcaRKipkhoRLWwO0Tznv4YOiw5QsLJa0LUFAmNqBI+NpCfr0oStSMCxzqEEF5DQiOEsI6ERghhHQmNEEJCI4SIfmTRCCGsI6ERQlhHQiOEsI6ERghhHQmNEMI6EhohhHUkNEII63guHk1iYiJKS0sRFxeHNDdKVYzi8/lQVlamulBdHLJtJCQkYF8IEot5Tmji4+PLK1AIUT28IR84cAC28VyYCFdoZNEEWzSpiGV8viK1i0raBq+XUOA5oUlNTS0PUchuUyhCFEZDuEaKzObNeYhlMjL+C1u2FKpdBLUNXi+hQM5gIYR1JDRCCOtIaIQQ1pHQCCGsI6ERQlhHQiOEsI6ERghhHQmNEMI6EhohhHUkNEII60hohBDWkdAIIawjoRFHTu4rQLuLgUZtzZLz38C8RTUqOmlSI3Tq1BwNG2YiNTUD/fodh3XrovwZ36VLgd69gd/9DqhTB3jnnVAUjQokNOLIyUgDJt8FrJhjlq7nAn2vA9b8X7VFlyxJwrBhO5GXV4iFC3/C/v1Ajx7Ho7i4TvT+I8XFQPv2wFNPhbJoVCChCWbnTmDQIKB+fYAR+qZMAbp0AW691Wx/9VWgY0egYUOgeXNg4ECgqMhffvFic0tasAA46yygXj2ga1ezz7x5wGmnAY0aAQMGALt3+8sx/thDDwEnn2zKsNW99RYimt4XAr0uAFqdbJaJo4AGyUDeV9UWnT+/CEOHFuP000vRvn0ppk/fhk2bjkF+fiKilp49gQkTgP79Q1k0KpDQBDNyJPDJJ8CcOcDChcDHHwNffunfzrCH48cDX39t7NuNG4GhQw+u2XHjzO1p+XLgxx+Byy4Dpk4FZs4E5s41x37ySf/+990HTJ8O5OYCa9YAt90GXHEFb/2IChilbdYcoHgPkNPhsItv326aYkqKoiN6kSjvFFuwZl56yYhBt25mHS9+dpxdrrrK/57WxxNPAGefDezaBTRo4N/G29N555n3V18N3HMPsH69KUP+9Cdg0SLgrruM3fzYY8BHHwE5Of5jL1sGTJsGnH8+IpbVBUBOf6Bkr7FmZk8D2px6WIegMTdyZBN07lyCtm1LrZ2qCB8SmkA2bABKS41wuDRuDGRl+T9/9ZWxVlauBP79b8CNT7xpE9CmjX+/du38748/HkhO9ouMu+7zz837tWuBkhKge/eK/w6tJ3a/Ipmsk4GV7wO/7gDengcMuR1Y8sZhic3w4SlYtSoRy5YVWj1VET4kNIG4cdrpY6lsPS2PHj3MQl/NcccZgbnoIiMKgSQk+N/zeIGf3XWuSLmv7FKlp1fcr25dRDSJicApJ5n3HdsBX6wCHn8RmDapRsVHjGiCOXPqYenSn5CRYT9ItggPEppAWrY0gkBLIzPTrNuxA/juO9N9KSgAtm4FJk/2b1+xovb/Ai0hCgpFK5K7STWBorx3X412o8jMnp2MxYt/QosW+0NyeiI8SGgC4UjSkCHAqFH0SjLSOTB2LHNSGAvkhBPMHZxO3BtuAL75xjiGj8b33nGHcQDTuunc2QgcHcn0+/CcIpHRDwE9uwCZacDOYmDWe8DiPGD+S9UWHTYsBTNn1se77xahYcMyFBYaZ3Djxg7q1YvSDED0033/vf8zBwrYxU5JMW3HTtGoQKNOwdApS4fsJZcAF15oHLockk5KMl2lGTOAN980Vggtm0ceOTr/BAVrzBjOZDPfx+7Ye+8BLVogYvlpKzD4NiCrG9BtEPDZSiMy3X/v32fcFOCk35ziAeTmNiwfaerSpTnS0jL/s7zxRjKiFlq39Km5fjWOYPL9mDH+fejfO+mkIyoazXgugZybRiI9Pf3opFuhX4Z+k0cfNaNHUVkXzcOXbmXo7eZ1xqOIhHQrR61dHClDf5sKwRuWl66TalDXKRiOKtEXw5Gn7duBBx4w6/v2tf5neJIlnwFL/xbus4gcliwxzxvEGBKaymB3aN0644/JzjaT9po1C/mf4wk2Lgv3GUQWGzciFpHQBMOOcX5+WP4MIbxKXNj6qTFoPgoRqxwTtqn+nPTGuShXXmmGb4MnqonIZfceoGB99fu1bgkk16tYdHcdFBQkVF+0dSmSkz01ThHThEdo3n4b2LbNzK6l951zVTiUzFEdOl2DZ9GKyIIik31J9fvl/x3o0LZi0YIEZGenVV8034cOHaqf+Ceig/D5aJo2BW65xSwc6XnxRWDwYDNBjU8t33QTcOrhPZwnQgQtFYpITfYLXtW6tFxEqi3aWg9XeonwO4N9PuAf/zBLfDzQq5cJk8AJcYzPwtmyIrJgdyjIUqlx0WRHlkoMEh5nMJ+QZveJs29PPNHMtKWgUHQYpoGi88or/jksQoioJjwWDSPX8ZkeRpnjA4xnnnnwPpyCf+yx4Tg7IYQnhIbhMS+91Dw/dCiaNInZyU1CeI3wCA2dvkKImCE8QsNocgy1wFCWDNrtBn5yCYzRK4SIesIjNIy7y+DcjJvLhxeDI9oJITxFeISGISvff98fvFsI4WnCM7zNxw0YVU4IEROEx6JhECmmGfnrX808Ggts27YNffr0QSzDOjCvv6JPnxGIZVgH5nUr+vQJyjYRg2zbtjUGhIaZHukQZvoRpiEJfraJaUxqSdOmTTGHSeBiGDeKmuoisC6YdeF5xDoZv0Uc9LbQcKLeli3Agw+a/EZyBgvhacIjNIzu/+mnJr+0EMLzhMcZ3Lo1sGdPWL5aCBErQsM0JbffDixebOLSMIdR4CKE8BTh6TpdfLF57dat4npmfqG/5oBSowrhJcIjNHz04FAwCJYQwlOER2iC80szf9JrrwHPPw98/TVw661hOS0hhBdT4n70kQnbyfg0fMiS0fWYG1QI4SlCb9Ew/SYDkjNGMNPNXnaZP+Iew3cKITxHaC0aWiwUk7VrjQXzr3+ZVyGEpwmtRcNYwDffDNx4ozIcCBFDhNaiYQ5rJo/js07nnAM89RTw888hPQUhhNeFJicHeO45k+3g+uuBWbNMyAhG2GMgLIpQLDFuXOWB2YXwGOEZdeIT24yyt2wZsHq1mSXM2cKpqUAshXa44w7gww8R1TzzDNCihQk0n51trNbQFY8sJj0NdOoDNDwdSM0G+l0LrKtB6mAAubkN0K5dGho1yixfcnKaY968KoL3RxnhHd4mWVkmURxHo15/HTEFs3IyY2e08sYbZs7TvfeaiZa//z3QsyewaVMoikceSz4Dhg0G8mYDC18B9h8AevwPULy72qIZGQcwefIvWLHCV7507VqCvn1TsWaNN9JDh19oXJilsl8/IFwxZLp0AUaMMC2fqV4YvuLZZ80Q/JVXmoiALVsC8+b5yyxZYmIe161r5gLdfTewf7/ZNm2av1sYCC22IUMO3XWaPh047TRzi+fDp7zlRyqPPWbypV9zjTnnqVOBzEzenkNRPPKY/zIw9FLg9FZA+zbA9IeBTVuA/NXVFu3dew969SpBq1b7y5eJE39FgwZlyMurCy8QOUITCTBLZrNmJqkdRYejY8w/de65JjMDk9oxVczu3SaeDofrO3Uys5l5dbzwAjBhgjkWy23dWvFxi19+ARYsAAYNqvz76b/i7X3iRODbb028nvvvN+cVaezbB+TnAz16VFzPzwwDYrd4dLD9N59jyuElQuSjfrNmJaO4OA45OXvhBcKfezuSYHyc++4z7++5x/iNKDzXXmvWjRljBGXVKuC998ztlyNnfBCU1gfnBTFEKfdLSTEPj86c6X94lKl/uT74YVKX8eNNmNP+/c1nOi8454jWkWsFRQoUUV4RtPwC4efCQtvFIx8+IDxyAtC5E9A2q0ZFVq9OKPfNlJTUQYMGDmbPLkKbNqXwArJoAmnXrmJXjv6TM87wr3OvCuaiosXBUbTA6IDM6rBrl/E3EVounPG897e7Ep/nuvxyc+xgOMz/44+mL0HfjbvQQlpfM4diWAiOjug+gR+a4pHL8DHAqm+B15+ocZGsrFKsXOlDXl4hbrxxJ4YMaYa1a73ho5FFE0hw7GK2+MB17hVAv0tlVwTXBe7Xu7fZl+ll2MXikAodE5Xh+nLYfeIco0AqE6ZwQ0uP5xVsflCEg82Uo188shkxFpjzAbD0b0BGWo2LJSYCp5xifHwdO+7DF18k4vHHG2LatNrH0A43smiOFD5KQWeCKy6En+k0phOY1KtnukG0ZDii1qqVGcOtDF5dLLdhA1tbxYVdqEiDVwV/C+c/BcLP9GnZLR6ZsC3Qkvnf+cBHM4EWmbU+3N69XjDvZNEcOTfdZIZJ6DQePhxYtw4YOxYYORKIC9Bvdp9o2axZY55UrwqOQvERjUaNzDgvu1x8mp1OZB430uA50TnOmd7sRnKUjmPTN9wQiuKRx7D7gZnvAu8+BzSsDxQWmfWNGwH1qp4TM3r0sejZcw8yM/dj5844zJpVH4sXJ2H+/N+OEeWo63Sk0Ppgts1Ro4wTmU5e+ldcZ7JL165mG4Vo4MCqj8lxXk5mfPhh4M47gfr1jY8oUuPz/PnPJhTrAw+Y2d5t25o6CczVRfHk0/o//HBExaOK3FfNa5fLK66f/rAZ9ibjpgAz3gJ++KTCLj/9FI/Bg5vB54tH48ZlaNduX7nIdO9eAi9Qx3ECbX/v5O9JT0/HZtcpG6NERF0MHWpeKTYRURfNsXlzXvhOZOjt5nXGoxGR1ylUbUMWjbALJzUuXapaDpw9TCdxjCGhEXbZuFE1HMjGZYhFNOokhLCOhEYIYR11nYSoLbv3AAXVzN5u3RJIrndw0d11UFBQ9ezf1q1LkZwc3WM2EhohagtFJvuSqvfJ/zvQoe3BRQsSkJ1d9ezh/HwfOnTYh2hGQiNEbaG1QiGpbp9DWCsUkqrgPtGOhEaI2sIuUSXWSo2KJjtRb63UBDmDhRDWkdAIISQ0QojoRxaNEMI6EhohhHUkNEII63guTERiYiJKS0sRFxeHNKZAiWF8Ph/KyspUFwfVRSpiHZ+vqLw+EhISsI8pKSzjOaGJj48vr0AhRPVQeA8wHYVlPDdhLykpCSUlJeWCk8oUuzFMUVFReSNSXaguDtU2eL2EAs9ZNEKIyEPOYCGEdSQ0QgjrSGiEENaR0AghrCOhEUJYR0IjhLCOhEYIYR0JjRDCOhIaIYR1JDRCCOtIaIQQ1pHQCCGsI6ERQlhHQiOEsI6ERghhHQmNEMI6EhohhHUkNEII60hohBDWkdAIIawjoRFCSGiEENGPLBohBGzz/9kzItzZ01P9AAAAAElFTkSuQmCC", + "text/plain": [ + "Graphics object consisting of 28 graphics primitives" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "battle.plot(player_labels=[\"Amy\", \"Bob\"],\n", + " strategy_labels=[[\"game\", \"movie\"], [\"game\", \"movie\"]],\n", + " best_responses=True, pure_nash=True)" + ] + }, + { + "cell_type": "markdown", + "id": "6ec1ea0f", + "metadata": {}, + "source": [ + "## Case study 1: a game whose payoffs are symbols\n", + "\n", + "Everything so far could be described as file conversion. This is where the integration starts to pay for itself.\n", + "\n", + "Gambit's solvers work on numbers. Sage's symbolic ring works on *expressions*, and a `NormalFormGame` is perfectly happy to hold them. So we can write down a whole family of games at once and solve it in closed form.\n", + "\n", + "The example is Hawk–Dove. Two animals contest a resource worth $v$. Two doves split it; a hawk takes it from a dove; two hawks fight and share the value minus a cost $c$ of injury." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "40eff1c4", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:12:27.289403Z", + "iopub.status.busy": "2026-08-23T17:12:27.289196Z", + "iopub.status.idle": "2026-08-23T17:12:27.327435Z", + "shell.execute_reply": "2026-08-23T17:12:27.326907Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "Normal Form Game with the following utilities: {(0, 0): [-1/2*c + 1/2*v, -1/2*c + 1/2*v],\n", + " (0, 1): [v, 0],\n", + " (1, 0): [0, v],\n", + " (1, 1): [1/2*v, 1/2*v]}" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "v, c, p = var(\"v c p\")\n", + "\n", + "H = matrix([[(v - c)/2, v],\n", + " [0, v/2]])\n", + "hawk_dove = NormalFormGame([H, H.transpose()])\n", + "hawk_dove" + ] + }, + { + "cell_type": "markdown", + "id": "b1671913", + "metadata": {}, + "source": [ + "In the mixed equilibrium each animal plays Hawk with some probability $p$ that leaves its opponent indifferent between the two behaviours.\n", + "We write that indifference condition down and ask Sage to solve it." + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "00206d88", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:12:27.328834Z", + "iopub.status.busy": "2026-08-23T17:12:27.328650Z", + "iopub.status.idle": "2026-08-23T17:12:28.653056Z", + "shell.execute_reply": "2026-08-23T17:12:28.652543Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[p == v/c]" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "hawk = p*(v - c)/2 + (1 - p)*v\n", + "dove = (1 - p)*v/2\n", + "\n", + "solution = solve(hawk == dove, p)\n", + "solution" + ] + }, + { + "cell_type": "markdown", + "id": "6a1a0d3c", + "metadata": {}, + "source": [ + "The equilibrium share of hawks is $p^* = v/c$ — a closed form valid for every $v$ and $c$ at once, which no numerical solver could have produced.\n", + "Being an ordinary Sage expression, we can now plot it, differentiate it, or take limits of it." + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "81e592cd", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:12:28.654471Z", + "iopub.status.busy": "2026-08-23T17:12:28.654291Z", + "iopub.status.idle": "2026-08-23T17:12:28.806994Z", + "shell.execute_reply": "2026-08-23T17:12:28.806435Z" + } + }, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAnYAAAHWCAYAAAD6oMSKAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjksIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvJkbTWQAAAAlwSFlzAAAPYQAAD2EBqD+naQAAgABJREFUeJztnQeYFMXWhj9yviCIBCVLFAQFRAQBE4jhihH1SlDwiqIIXBOiv4ggSYLAJScJkiRIDoJkQUmSg8QlJ0EQdmF353++6jvszLINC+zsTp0+7/P0bk9PTXd/dXq6z5yqOpXK5/P5cJ2kSpXK/L+Bj6YYKX3OKX18W1i6dCnKli2LW265JaVPRVEURVGsI3VKn4CiBDJ27Fjs3btXK0VRFEVRbgB17JQUh1HMV155BX/88Qdy585tlhEjRuDbb79N6VNTFEVRFKtIpU2xyVTR2hR7VdavX4++ffvi0KFDKFSoEG6//Xa8++67yJEjRzJZSFEURVHs56YjdrNnz0aNGjWQLVs2ZM+eHXXr1sW6desSLLtp0yZ88cUXqFq1KvLly4f06dOb/8899xxWrFgRVDY2NhY5c+ZEmjRp8Oeffwa9t3LlSuMocRk6dOgVxylcuLB5LzFNeowWtWjRwpS/8847sW/fvkTpZrm33noLRYsWRYYMGYx+rj/77LMYN25citRZIP76IZMmTTLHo5MUv16io6MxYMAAVK9e3byfMWNGlCpVCp999hn++usvJBdFihRB8eLFce7cOXNO99xzjzp1iqIoinK9+G4AfoxL//79falSpfLly5fPd++99/qyZMlitmfNmtW3devWKz73yCOPmPdz5MjhK126tPnMrbfearalSZPGN2bMmKDyTz31lHlv2rRpQdu7dOly+RwaNGgQ9N6+ffvM9oIFCyZ4zoFER0f7GjdubLaXLVvWd/jw4UTp37Nnz+Xzzpw5s69cuXK+ChUq+HLmzGm2lS9fPsXqLP7xOnfubP7nyZPHV7lyZV/u3LnN+ZMzZ874atSoYd5PnTq1r1ChQqYe0qdPb7bxeEePHvWFmtjYWF+VKlV8c+fO9bVr186cX8uWLc26oiiKoiiJ56YcOzo1w4cPv7z9r7/+uuyI1K9f/4rPTZw40bdhw4YrHupTp041js0//vEPsw8/3bp1M/v6z3/+E/SZJ554wjgiefPmvcKBGzlyZIIOX3zHLioqyvf888+bbffdd5/v5MmTidb/7rvvms81atTId/bs2aD36JwNHDgwxeos/vHopA0aNMh8hly6dMks5OWXXzZlePxdu3Zd/uypU6d8zz33nHnvhRde8CUnzZs3961bty5Zj6koiqIoUrgpx+6999674j06IXwve/bs17XPzz77zHwuMAK1atUqs61SpUqXt8XExJh933PPPcax4vv+CBRp0qSJ2TZkyJAEz5n8/fffvjp16pjXtWrVStAxuhr+z/7+++9hV2eJOR7hufN9RukS0s86KlCggIku7t2795rnsnbtWt9rr73mu//++40zevr0ad+HH37oe+edd3xPPvmk76uvvrrsXF6NRYsWXZeTrSiKoihKHGlxEzRt2vSKbeXKlTP9tM6cOYOTJ08iV65cQe/v378f33//PdauXYsTJ07g4sWLZvuxY8fM/99//x2vvvqqWb/33nuRNWtW0//s7Nmzpk8aO9lz3zVr1sTdd9+N7777DosXLzb96siSJUvMf/YpSwh+9qmnnsKyZcvw5JNP4ocffjDnez0UKFDA/Odnqdffly0c6iw+DRs2THD7lClTzP+XXnrJ1Gt8MmfOjEcffRTDhw83ueU4oOFq9OzZ05Tt3Lmz0fj444+je/fuZhAEbVewYEHTn/C999676n5oV0VRFEVRboybcuyKFSuW4Hamq4iIiDAd4QOdFDphzZo1Q2RkpOs+T506FXdyadPigQcewLx587B8+XLjLNCJI37HjnBbo0aNcPjwYezcudMMLmBH/IR4+OGHjYP08ssvY+TIkUiXLt11627evLnR8tVXX5l98LwefPBBPPTQQ8ifP3+K1ll8SpcuneD2jRs3Xnbw3AZh+AeSHDx4EFdj+/btZvAD7cWy58+fNw4enTpCx7FkyZIYPHjwNR07RVEURVFSaFRslixZEt5p6tRXzLKwa9cuvPnmm8ZB+c9//mOicBx1ydGvLMeHPrl06VKCERy/Q8f/jJDRkeIo1DvuuCPovcDPJARzpfmjZDfi1JEKFSqYyGDt2rWNIzNw4EC89tpr5lzq1KmDrVu3pmidJeZ4jA7664NOc0LLgQMHTJkLFy5ctT4YkWMeOsLoXuXKlS9HUAOdT0YeFUVRFEURkKB4woQJxgFhpOybb74xzhEjOf5mTEarEsLfpEqnjc6Mf8opf1SL7+/e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", + "text/plain": [ + "Graphics object consisting of 1 graphics primitive" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "p_star = solution[0].rhs()\n", + "\n", + "plot(p_star.subs(v=2), (c, 2, 10), axes_labels=[\"cost $c$\", \"hawk share $p^*$\"],\n", + " thickness=2, gridlines=True)" + ] + }, + { + "cell_type": "markdown", + "id": "a360b077", + "metadata": {}, + "source": [ + "And we can check the formula against Gambit.\n", + "Substituting $v = 2$, $c = 5$ turns the symbolic matrices into numeric ones, at which point the game converts and Gambit's `enummixed` solver applies." + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "0ec6a91b", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:12:28.808254Z", + "iopub.status.busy": "2026-08-23T17:12:28.808102Z", + "iopub.status.idle": "2026-08-23T17:12:28.813189Z", + "shell.execute_reply": "2026-08-23T17:12:28.812544Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[[(0, 1), (1, 0)], [(2/5, 3/5), (2/5, 3/5)], [(1, 0), (0, 1)]]" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "numeric = NormalFormGame([H.subs(v=2, c=5),\n", + " H.transpose().subs(v=2, c=5)])\n", + "numeric.obtain_nash(algorithm=\"enummixed\")" + ] + }, + { + "cell_type": "markdown", + "id": "638113c9", + "metadata": {}, + "source": [ + "The middle equilibrium puts weight `2/5` on Hawk, and the formula gives the same value exactly. The two answers can be compared directly rather than up to a floating point tolerance." + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "cddb87cf", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:12:28.814484Z", + "iopub.status.busy": "2026-08-23T17:12:28.814335Z", + "iopub.status.idle": "2026-08-23T17:12:28.818995Z", + "shell.execute_reply": "2026-08-23T17:12:28.818382Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "p_hat = numeric.obtain_nash(algorithm=\"enummixed\")[1][0][0]\n", + "\n", + "QQ(p_star.subs(v=2, c=5)) == p_hat" + ] + }, + { + "cell_type": "markdown", + "id": "d5c499a1", + "metadata": {}, + "source": [ + "## Case study 2: from a graph to a game\n", + "\n", + "The second thing Sage brings is its library of mathematical objects. Here we turn a *graph* into a game and let Gambit analyse it.\n", + "\n", + "In the **max cut game**, every vertex of a graph is a player choosing one of two sides. A player's payoff is the number of its incident edges that end up cut, that is, joining vertices on opposite sides. A pure Nash equilibrium is exactly a cut that no single vertex can improve by switching sides — a *locally* optimal cut.\n", + "\n", + "We use the house graph: five vertices, six edges." + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "adcb2c9d", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:12:28.820208Z", + "iopub.status.busy": "2026-08-23T17:12:28.820079Z", + "iopub.status.idle": "2026-08-23T17:12:28.995407Z", + "shell.execute_reply": "2026-08-23T17:12:28.994866Z" + } + }, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "Graphics object consisting of 12 graphics primitives" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "G = graphs.HouseGraph()\n", + "G.plot(vertex_labels=True)" + ] + }, + { + "cell_type": "markdown", + "id": "3e04602e", + "metadata": {}, + "source": [ + "Building the game is a matter of filling in one payoff array per vertex.\n", + "Sage's graph API supplies the vertices and the neighbours, and NumPy holds the payoffs." + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "bb2dea49", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:12:28.996943Z", + "iopub.status.busy": "2026-08-23T17:12:28.996753Z", + "iopub.status.idle": "2026-08-23T17:12:29.003034Z", + "shell.execute_reply": "2026-08-23T17:12:29.002478Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "5" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def max_cut_game(graph):\n", + " \"\"\"Return the max cut game of ``graph`` as a Sage ``NormalFormGame``.\"\"\"\n", + " vertices = sorted(graph.vertices())\n", + " arrays = [np.zeros((2,) * len(vertices), dtype=int) for _ in vertices]\n", + " for profile in itertools.product([0, 1], repeat=len(vertices)):\n", + " side = dict(zip(vertices, profile, strict=True))\n", + " for i, u in enumerate(vertices):\n", + " arrays[i][profile] = sum(1 for w in graph.neighbors(u)\n", + " if side[w] != side[u])\n", + " return NormalFormGame(arrays)\n", + "\n", + "\n", + "game = max_cut_game(G)\n", + "len(game.players)" + ] + }, + { + "cell_type": "markdown", + "id": "6a4ac7b2", + "metadata": {}, + "source": [ + "Five players, so this is squarely in Gambit's territory. `'enumpure'` enumerates the pure equilibria." + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "21c02cd5", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:12:29.004413Z", + "iopub.status.busy": "2026-08-23T17:12:29.004257Z", + "iopub.status.idle": "2026-08-23T17:12:29.009042Z", + "shell.execute_reply": "2026-08-23T17:12:29.008505Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "6" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "equilibria = game.obtain_nash(algorithm=\"enumpure\")\n", + "len(equilibria)" + ] + }, + { + "cell_type": "markdown", + "id": "a2e32102", + "metadata": {}, + "source": [ + "Each equilibrium is a cut, so we read the profiles back and count how many edges each one cuts.\n", + "The probabilities are exact, so a pure strategy is the integer `0` or `1` and needs no rounding." + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "d4e3fcc5", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:12:29.010232Z", + "iopub.status.busy": "2026-08-23T17:12:29.010110Z", + "iopub.status.idle": "2026-08-23T17:12:29.013389Z", + "shell.execute_reply": "2026-08-23T17:12:29.012939Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(0, 0, 1, 1, 0) cuts 4 edges\n", + "(0, 1, 1, 0, 0) cuts 5 edges\n", + "(0, 1, 1, 0, 1) cuts 5 edges\n", + "(1, 0, 0, 1, 0) cuts 5 edges\n", + "(1, 0, 0, 1, 1) cuts 5 edges\n", + "(1, 1, 0, 0, 1) cuts 4 edges\n" + ] + } + ], + "source": [ + "def cut_size(profile):\n", + " return sum(1 for (u, w) in G.edges(labels=False) if profile[u] != profile[w])\n", + "\n", + "\n", + "profiles = sorted({tuple(int(s[1]) for s in eq) for eq in equilibria})\n", + "for profile in profiles:\n", + " print(f\"{profile} cuts {cut_size(profile)} edges\")" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "034dccb2", + "metadata": { + "execution": { + "iopub.execute_input": "2026-08-23T17:12:29.014483Z", + "iopub.status.busy": "2026-08-23T17:12:29.014370Z", + "iopub.status.idle": "2026-08-23T17:12:29.102185Z", + "shell.execute_reply": "2026-08-23T17:12:29.101652Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "5" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "G.max_cut(value_only=True)" + ] + }, + { + "cell_type": "markdown", + "id": "215df832", + "metadata": {}, + "source": [ + "Four of the six equilibria achieve the optimum of five cut edges, but two of them get stuck at four.\n", + "Those are the locally stable cuts that are not globally optimal, and the ratio $4/5$ is this game's price of anarchy.\n", + "\n", + "Gambit found the equilibria; Sage certified which of them were actually good. Neither library could have produced that sentence alone.\n", + "\n", + "## Summary\n", + "\n", + "| Task | Call |\n", + "|---|---|\n", + "| Gambit game to Sage | `NormalFormGame(game)` |\n", + "| Sage game to Gambit | `game._gambit_()` |\n", + "| Read and write `.nfg` | `NormalFormGame.load_nfg(path)`, `game.save_nfg(path)` |\n", + "| Browse the Gambit catalog | `NormalFormGame.gambit_catalog_games()` |\n", + "| Load a catalog game | `NormalFormGame.load_from_gambit_catalog(slug)` |\n", + "| Solve with Sage (exact, two players) | `game.obtain_nash(algorithm='enumeration')` |\n", + "| Solve with Gambit | `game.obtain_nash(algorithm='LCP')` and friends |\n", + "| Solve with more than two players | `game.obtain_nash(algorithm='enumpoly')` |\n", + "| Ask for floating point answers | `game.obtain_nash(rational=False)` |\n", + "| Draw the payoff bimatrix | `game.plot()` |\n", + "\n", + "For games in extensive form — trees, information sets, and chance moves — see the companion tutorial, [Using Gambit with SageMath: extensive form games](sagemath_extensive_form.ipynb).\n", + "\n", + "Further reading:\n", + "\n", + "- [SageMath game theory reference](https://doc.sagemath.org/html/en/reference/game_theory/index.html)\n", + "- [PyGambit API documentation](https://gambitproject.readthedocs.io/en/latest/pygambit.api.html)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "SageMath 10.10.beta6", + "language": "sage", + "name": "sagemath" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.13" + }, + "nbsphinx": { + "execute": "never" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/pyproject.toml b/pyproject.toml index e2e4e55f2..4c4698000 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -86,6 +86,12 @@ unfixable = [] # Allow unused variables when underscore-prefixed. dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" +[tool.ruff.lint.per-file-ignores] +# The SageMath tutorials run on the SageMath Jupyter kernel, which injects Sage's +# globals (NormalFormGame, matrix, QQ, plot, ...) into every cell, so ruff cannot +# see where those names come from. +"doc/tutorials/interoperability_tutorials/sagemath_*.ipynb" = ["F821"] + [tool.ruff.format] quote-style = "double" indent-style = "space" diff --git a/tests/test_tutorials.py b/tests/test_tutorials.py index 6d6a4bb9e..cffd1a1a1 100644 --- a/tests/test_tutorials.py +++ b/tests/test_tutorials.py @@ -1,4 +1,5 @@ import contextlib +import functools import os import sys from pathlib import Path @@ -35,6 +36,14 @@ def _find_tutorial_notebooks(): return notebooks +@functools.lru_cache(maxsize=1) +def _available_kernels(): + """Return the set of Jupyter kernel names installed on this machine.""" + from jupyter_client.kernelspec import KernelSpecManager + + return set(KernelSpecManager().find_kernel_specs()) + + # Discover notebooks at import time so pytest can parametrize them. _NOTEBOOKS = _find_tutorial_notebooks() @@ -62,6 +71,15 @@ def test_execute_notebook(nb_path): # Prefer the notebook's kernelspec if provided, otherwise let nbclient pick the default. kernel_name = nb.metadata.get("kernelspec", {}).get("name") + # Notebooks for other systems (e.g. the SageMath tutorials, which declare the + # "sagemath" kernel) can only be executed where that kernel is installed. + # Their outputs are pre-saved for docs builds, so skip rather than fail. + if kernel_name and kernel_name not in _available_kernels(): + pytest.skip( + f"Notebook {nb_path.name} needs the {kernel_name!r} Jupyter kernel, " + "which is not installed" + ) + client = NotebookClient( nb, timeout=600, @@ -78,3 +96,36 @@ def test_execute_notebook(nb_path): # Ensure kernel is shut down. with contextlib.suppress(Exception): client.shutdown_kernel() + + +@pytest.mark.tutorials +@pytest.mark.parametrize("nb_path", _NOTEBOOKS, ids=[p.name for p in _NOTEBOOKS]) +def test_prerendered_notebooks_keep_outputs(nb_path): + """Notebooks the docs build cannot execute must ship their stored outputs. + + ``nbsphinx`` only executes notebooks that have no stored outputs, so tutorials that + cannot run on Read the Docs (no Java for GAMUT, no SageMath for the Sage tutorials) + opt out with ``"nbsphinx": {"execute": "never"}`` and commit their outputs instead. + If those outputs are ever stripped, the notebook silently renders as bare code with + no results at all, which is easy to miss when reviewing a docs build. + """ + nb = nbformat.read(str(nb_path), as_version=4) + kernel_name = nb.metadata.get("kernelspec", {}).get("name") + prerendered = nb.metadata.get("nbsphinx", {}).get("execute") == "never" + + # The docs build only has a plain Python kernel, so anything else must opt out. + if kernel_name and kernel_name != "python3": + assert prerendered, ( + f"{nb_path.name} declares the {kernel_name!r} kernel, which the docs build " + 'does not have. Set notebook metadata "nbsphinx": {"execute": "never"} and ' + "commit the notebook with its outputs." + ) + + if not prerendered: + pytest.skip(f"{nb_path.name} is executed during the docs build") + + code_cells = [cell for cell in nb.cells if cell.cell_type == "code"] + assert any(cell.get("outputs") for cell in code_cells), ( + f"{nb_path.name} sets nbsphinx execute='never' but has no stored outputs, so it " + "would render without any results. Re-run the notebook and commit it." + )