From 46f91a353e4332e89ae6b5b49a700dd2f9f3e2d1 Mon Sep 17 00:00:00 2001 From: DeepMind Technologies Ltd Date: Thu, 14 Mar 2024 22:53:03 +0000 Subject: [PATCH] Add universal_poker colab now that it's fixed. \n PiperOrigin-RevId: 615929759 Change-Id: I7b315fe3b1d80bbec88705bedfd30380eb2358c8 --- open_spiel/colabs/test_universal_poker.ipynb | 313 +++++++++++++++++++ 1 file changed, 313 insertions(+) create mode 100644 open_spiel/colabs/test_universal_poker.ipynb diff --git a/open_spiel/colabs/test_universal_poker.ipynb b/open_spiel/colabs/test_universal_poker.ipynb new file mode 100644 index 0000000000..8018ed7276 --- /dev/null +++ b/open_spiel/colabs/test_universal_poker.ipynb @@ -0,0 +1,313 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "v8KR9V4Hy-vw" + }, + "source": [ + "# Imports" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "cellView": "both", + "id": "idfu7sA0vExR" + }, + "outputs": [], + "source": [ + "from __future__ import absolute_import\n", + "from __future__ import division\n", + "from __future__ import print_function\n", + "\n", + "import sys\n", + "assert sys.version_info.major == 3\n", + "import os\n", + "\n", + "add_paths = True\n", + "if add_paths:\n", + " sys.path.insert(0, os.path.join(os.path.abspath(os.getcwd()), '..', '..'))\n", + " sys.path.insert(\n", + " 0,\n", + " os.path.join(os.path.abspath(os.getcwd()), '..', '..', 'build', 'python'))\n", + " import pyspiel\n", + " from pyspiel.universal_poker import load_universal_poker_from_acpc_gamedef\n", + "\n", + "\n", + "from open_spiel.python.algorithms import cfr\n", + "from open_spiel.python.algorithms import exploitability\n", + "from open_spiel.python.algorithms import expected_game_score\n", + "from open_spiel.python.bots import uniform_random\n", + "from open_spiel.python.visualizations import treeviz" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "HLXNc0ZCvExt" + }, + "outputs": [], + "source": [ + "games_list = pyspiel.registered_names()\n", + "\n", + "print(\"Registered games:\")\n", + "print(games_list)\n", + "\n", + "game = pyspiel.load_game(\"universal_poker\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "vqyfMHs2vEx7" + }, + "outputs": [], + "source": [ + "\"\"\"Test that Python and C++ bots can be called by a C++ algorithm.\"\"\"\n", + "\n", + "from absl.testing import absltest\n", + "import numpy as np\n", + "\n", + "from open_spiel.python.bots import uniform_random\n", + "\n", + "game = pyspiel.load_game(\"leduc_poker\")\n", + "bots = [\n", + " pyspiel.make_uniform_random_bot(0, 1234),\n", + " uniform_random.UniformRandomBot(1, np.random.RandomState(4321)),\n", + "]\n", + "results = np.array([\n", + " pyspiel.evaluate_bots(game.new_initial_state(), bots, iteration)\n", + " for iteration in range(10000)\n", + "])\n", + "leduc_average_results = np.mean(results, axis=0)\n", + "print(leduc_average_results)\n", + "\n", + "game = pyspiel.load_game(\"universal_poker\")\n", + "bots = [\n", + " pyspiel.make_uniform_random_bot(0, 1234),\n", + " uniform_random.UniformRandomBot(1, np.random.RandomState(4321)),\n", + "]\n", + "results = np.array([\n", + " pyspiel.evaluate_bots(game.new_initial_state(), bots, iteration)\n", + " for iteration in range(10000)\n", + "])\n", + "universal_poker_average_results = np.mean(results, axis=0)\n", + "print(universal_poker_average_results)\n", + "\n", + "#np.testing.assert_allclose(universal_poker_average_results, leduc_average_results, atol=0.1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "RhI6kVnkvEyE" + }, + "outputs": [], + "source": [ + "universal_poker_kuhn_limit_3p = \"\"\"\\\n", + "GAMEDEF\n", + "limit\n", + "numPlayers = 3\n", + "numRounds = 1\n", + "blind = 1 1 1\n", + "raiseSize = 1\n", + "firstPlayer = 1\n", + "maxRaises = 1\n", + "numSuits = 1\n", + "numRanks = 4\n", + "numHoleCards = 1\n", + "numBoardCards = 0\n", + "END GAMEDEF\n", + "\"\"\"\n", + "\n", + "game = load_universal_poker_from_acpc_gamedef(universal_poker_kuhn_limit_3p)\n", + "str(game)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "lpLJhzBEvEyM" + }, + "outputs": [], + "source": [ + "# Compare exloitability for two games\n", + "players = 2\n", + "iterations = 10\n", + "print_freq = 1\n", + "\n", + "def compare_exploitability(game_1, game_2):\n", + " cfr_solver_1 = cfr.CFRSolver(game_1)\n", + " cfr_solver_2 = cfr.CFRSolver(game_2)\n", + " for i in range(iterations):\n", + " cfr_solver_1.evaluate_and_update_policy()\n", + " cfr_solver_2.evaluate_and_update_policy()\n", + " if i % print_freq == 0:\n", + " conv_1 = exploitability.exploitability(game_1,\n", + " cfr_solver_1.average_policy())\n", + " conv_2 = exploitability.exploitability(game_2,\n", + " cfr_solver_2.average_policy())\n", + "\n", + " print(\"Iteration {} exploitability of the {} vs: {}\".format(\n", + " i, conv_1, conv_2))\n", + "\n", + " print(\"Final exploitability is {} vs {}\".format(conv_1, conv_2))\n", + "\n", + "\n", + "game_1 = pyspiel.load_game(\"kuhn_poker\",\n", + " {\"players\": 2})\n", + "\n", + "universal_poker_kuhn_limit_2p = \"\"\"\\\n", + "GAMEDEF\n", + "limit\n", + "numPlayers = 2\n", + "numRounds = 1\n", + "blind = 1 1\n", + "raiseSize = 1\n", + "firstPlayer = 1\n", + "maxRaises = 1\n", + "numSuits = 1\n", + "numRanks = 3\n", + "numHoleCards = 1\n", + "numBoardCards = 0\n", + "END GAMEDEF\n", + "\"\"\"\n", + "game_2 = load_universal_poker_from_acpc_gamedef(universal_poker_kuhn_limit_2p)\n", + "\n", + "compare_exploitability(game_1, game_2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "0Zltqy5PNM8P" + }, + "outputs": [], + "source": [ + "game_1 = pyspiel.load_game(\"leduc_poker\",\n", + " {\"players\": 2})\n", + "# Taken verbatim from the linked paper above: \"In Leduc hold'em, the deck\n", + "# consists of two suits with three cards in each suit. There are two rounds.\n", + "# In the first round a single private card is dealt to each player. In the\n", + "# second round a single board card is revealed. There is a two-bet maximum,\n", + "# with raise amounts of 2 and 4 in the first and second round, respectively.\n", + "# Both players start the first round with 1 already in the pot.\n", + "\n", + "universal_poker_leduc_limit_2p = \"\"\"\\\n", + "GAMEDEF\n", + "limit\n", + "numPlayers = 2\n", + "numRounds = 2\n", + "blind = 1 1\n", + "raiseSize = 1 1\n", + "firstPlayer = 1 1\n", + "maxRaises = 2 2\n", + "raiseSize = 2 4\n", + "numSuits = 2\n", + "numRanks = 3\n", + "numHoleCards = 1\n", + "numBoardCards = 0 1\n", + "END GAMEDEF\n", + "\"\"\"\n", + "game_2 = load_universal_poker_from_acpc_gamedef(universal_poker_leduc_limit_2p)\n", + "\n", + "compare_exploitability(game_1, game_2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "zk4rz8mvvEyb" + }, + "outputs": [], + "source": [ + "game = \"universal_poker\"\n", + "out = \"/tmp/gametree.png\"\n", + "prog = \"dot\"\n", + "group_infosets = False\n", + "group_terminal = False\n", + "verbose = False\n", + "\n", + "\n", + "def _zero_sum_node_decorator(state):\n", + " \"\"\"Custom node decorator that only shows the return of the first player.\"\"\"\n", + " attrs = treeviz.default_node_decorator(state) # get default attributes\n", + " if state.is_terminal():\n", + " attrs[\"label\"] = str(int(state.returns()[0]))\n", + " return attrs\n", + "\n", + "game = load_universal_poker_from_acpc_gamedef(universal_poker_kuhn_limit_2p)\n", + "game_type = game.get_type()\n", + "\n", + "if game_type.dynamics != pyspiel.GameType.Dynamics.SEQUENTIAL:\n", + " raise ValueError(\"Game must be sequential, not {}\".format(game_type.dynamics))\n", + "\n", + "if (game_type.utility == pyspiel.GameType.Utility.ZERO_SUM and\n", + " game.num_players() == 2):\n", + " gametree = treeviz.GameTree(\n", + " game,\n", + " node_decorator=_zero_sum_node_decorator,\n", + " group_infosets=group_infosets,\n", + " group_terminal=group_terminal)\n", + "else:\n", + " gametree = treeviz.GameTree(game) # use default decorators\n", + "\n", + "if verbose:\n", + " logging.info(\"Game tree:\\n%s\", gametree.to_string())\n", + "\n", + "gametree.draw(out, prog=prog)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "4rvvGu65M1jk" + }, + "outputs": [], + "source": [] + } + ], + "metadata": { + "colab": { + "last_runtime": { + "build_target": "//research/colab/notebook:notebook_backend_py3", + "kind": "private" + }, + "name": "test_universal_poker.ipynb", + "provenance": [ + { + "file_id": "1ZX9X01BBrKZp5EAIEXTLwzxuTbEj0rTJ", + "timestamp": 1575292378817 + } + ] + }, + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "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.6.7" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +}