diff --git a/example/Demo.ipynb b/example/Demo.ipynb new file mode 100644 index 0000000..0b9c5cf --- /dev/null +++ b/example/Demo.ipynb @@ -0,0 +1,1337 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "7fd0a68d-08b1-4e51-91fe-7b6a28b3e9e1", + "metadata": {}, + "source": [ + "# Memento Demo" + ] + }, + { + "cell_type": "markdown", + "id": "154a348b-b553-4901-9cd0-b8af1e68f834", + "metadata": {}, + "source": [ + "## Imports" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "1448051e-c0f0-4a60-8d51-5d2ba6d644ef", + "metadata": {}, + "outputs": [], + "source": [ + "from twosigma.memento import memento_function\n", + "import time" + ] + }, + { + "cell_type": "markdown", + "id": "b69fe0fe-365f-401b-9d26-8b435ec20bb0", + "metadata": {}, + "source": [ + "## Set up a Demo Sandbox (not normally necessary)\n", + "Expand and run this section if you wish to sandbox and reset the memoization state" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "a6bccc0c-1760-4270-882c-964e10c2c39e", + "metadata": {}, + "outputs": [], + "source": [ + "from twosigma.memento import list_memoized_functions, Environment, ConfigurationRepository, forget_cluster\n", + "import os\n", + "from pathlib import Path\n", + "\n", + "demo_home = f\"{os.path.expanduser('~')}/.memento/env/memento_demo\"\n", + "Path.mkdir(Path(demo_home), parents=True, exist_ok=True)\n", + "Environment.set({\"name\": \"memento_demo\", \"base_dir\": demo_home})" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "6c6b03ad-3821-4573-bc95-39bf301ff8a2", + "metadata": {}, + "outputs": [], + "source": [ + "forget_cluster()" + ] + }, + { + "cell_type": "markdown", + "id": "52ee7606-0061-4e11-9c7d-ec065decf522", + "metadata": {}, + "source": [ + "## Hello, World\n", + "This demo shows caching in action. The function `hello` has an artificial 1 second delay which is clearly run the first time it encounters the \"hello\" input but not the second.\n", + "\n", + "Calling the function with a different input incurs the delay again, as it is a unique computation." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "0769dd65-0613-4f11-ad52-dc6d350f67c5", + "metadata": {}, + "outputs": [], + "source": [ + "@memento_function\n", + "def hello(n: str) -> str:\n", + " print(f\"Calculating for {n}...\")\n", + " time.sleep(1)\n", + " return f\"hello, {n}!\"" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "013530f7-9d70-48fe-b423-a3c5d1d902ee", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Calculating for world...\n" + ] + }, + { + "data": { + "text/plain": [ + "'hello, world!'" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "hello(\"world\")" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "96b4f5b5-fcb7-4658-9b61-3bebb1207470", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'hello, world!'" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "hello(\"world\")" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "85948e2d-29d3-4cc5-8b94-1409ed2c6b03", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Calculating for there...\n" + ] + }, + { + "data": { + "text/plain": [ + "'hello, there!'" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "hello(\"there\")" + ] + }, + { + "cell_type": "markdown", + "id": "3bc6194e-b4d8-4891-84fc-60b76c38542f", + "metadata": {}, + "source": [ + "Memento calculates a version of the function" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "bce812f3-e320-427b-84f9-366ced01206d", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'a3170059eeed6797'" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "v1 = hello.version()\n", + "v1" + ] + }, + { + "cell_type": "markdown", + "id": "923b9a99-becc-4845-b431-6796a6bc99e8", + "metadata": {}, + "source": [ + "If we change the function, the version changes:" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "9bc35c5f-298e-4ed3-97f2-8f99658d275a", + "metadata": {}, + "outputs": [], + "source": [ + "@memento_function\n", + "def hello(n: str) -> str:\n", + " print(f\"Calculating for {n}...\")\n", + " time.sleep(1)\n", + " return f\"Hello, {n.title()}!\" # Hello is captialized, and we use the title case for n as well" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "c7bd455d-f3f8-4dbe-990e-caa8a13ff83b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'4b2ee18534d039f7'" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "v2 = hello.version()\n", + "v2" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "324355f0-6f25-4a32-aeaf-cf75bf8b74ab", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Calculating for world...\n" + ] + }, + { + "data": { + "text/plain": [ + "'Hello, World!'" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "hello(\"world\")" + ] + }, + { + "cell_type": "markdown", + "id": "a7ff5c03-9093-4965-a15c-4144a8c9796a", + "metadata": {}, + "source": [ + "Now, if we change it back, the version goes back to what it was before" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "8cb1c3a4-efcb-458d-ac08-36e8397cc728", + "metadata": {}, + "outputs": [], + "source": [ + "@memento_function\n", + "def hello(n: str) -> str:\n", + " print(f\"Calculating for {n}...\")\n", + " time.sleep(1)\n", + " return f\"hello, {n}!\"" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "68f822c6-6c0a-4ab5-ab92-ee96b1223700", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'a3170059eeed6797'" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "v3 = hello.version()\n", + "v3" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "19465222-8fa4-4382-bef0-fc9d89fa7f6e", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "v3 == v1" + ] + }, + { + "cell_type": "markdown", + "id": "eb70dbc9-dd33-476a-a16b-189f196e1cff", + "metadata": { + "jp-MarkdownHeadingCollapsed": true + }, + "source": [ + "## Double and Add\n", + "This demo shows three functions, `increment(x)`, `double(x)`, and `increment_and_double(x)`" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "66f681dc-d8db-413d-9a6c-b6cb1f68f4db", + "metadata": {}, + "outputs": [], + "source": [ + "@memento_function\n", + "def increment(x):\n", + " print(f\"increment({x})\")\n", + " return x + 1\n", + "\n", + "@memento_function\n", + "def double(x):\n", + " print(f\"double({x})\")\n", + " return x * 2\n", + "\n", + "@memento_function\n", + "def increment_and_double(x):\n", + " print(f\"increment_and_double({x})\")\n", + " return double(increment(x))" + ] + }, + { + "cell_type": "markdown", + "id": "e727b85f-6e82-464d-b478-15b186ecea8e", + "metadata": {}, + "source": [ + "Basic usage" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "657c2175-ffa8-47ed-a5fc-beb3fe22ea34", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "increment(1)\n" + ] + }, + { + "data": { + "text/plain": [ + "2" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "increment(1)" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "c02cbf91-f1ed-4771-afed-ee6a58bc8400", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "double(2)\n" + ] + }, + { + "data": { + "text/plain": [ + "4" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "double(2)" + ] + }, + { + "cell_type": "markdown", + "id": "e83e6d17-d4ed-4dc5-8e11-04558a16fbd0", + "metadata": {}, + "source": [ + "Now, we call increment_and_double" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "2c64ac03-fc14-41a2-9bdb-fd10182f018d", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "increment_and_double(2)\n", + "increment(2)\n", + "double(3)\n" + ] + }, + { + "data": { + "text/plain": [ + "6" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "increment_and_double(2)" + ] + }, + { + "cell_type": "markdown", + "id": "4b900e40-b298-4000-8d4b-0613ff3df04d", + "metadata": {}, + "source": [ + "We can instruct Memento to graph the dependencies of `increment_and_double`, which it gets from static analysis of the code. This is the expected call graph (which can differ from the actual if branches are taken)." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "d37e37a6-b367-4b40-a17c-69639d389181", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "%3\n", + "\n", + "\n", + "\n", + "c9a1baa8\n", + "\n", + "increment_and_double\n", + "\n", + "\n", + "\n", + "99cd6260\n", + "\n", + "double\n", + "\n", + "\n", + "\n", + "c9a1baa8->99cd6260\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "4566a700\n", + "\n", + "increment\n", + "\n", + "\n", + "\n", + "c9a1baa8->4566a700\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "increment_and_double.dependencies()" + ] + }, + { + "cell_type": "markdown", + "id": "1c5077c0-833c-40ab-8f7f-c29e1fc9bdc1", + "metadata": {}, + "source": [ + "We can introspect on the memento (the metadata artifact recorded when we called `increment_and_double(2)`)" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "31a44896-a95d-4d56-9465-24c044a608d6", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Memento(time=datetime.datetime(2024, 3, 31, 21, 13, 30, 18678, tzinfo=tzutc()), invocation_metadata=InvocationMetadata(fn_reference_with_args=FunctionReferenceWithArguments(fn_reference=FunctionReference('__main__:increment_and_double#eaa2b7f9012bc881', partial_args=(), partial_kwargs=None, external=False), args=(2,), kwargs={}, context_args={}), invocations=[FunctionReferenceWithArguments(fn_reference=FunctionReference('__main__:increment#b67215ccb618c9d0', partial_args=(), partial_kwargs=None, external=False), args=(2,), kwargs={}, context_args={}), FunctionReferenceWithArguments(fn_reference=FunctionReference('__main__:double#885a872da7be0a6d', partial_args=(), partial_kwargs=None, external=False), args=(3,), kwargs={}, context_args={})], runtime=datetime.timedelta(microseconds=4276), result_type=), function_dependencies={FunctionReference('__main__:double#885a872da7be0a6d', partial_args=(), partial_kwargs=None, external=False), FunctionReference('__main__:increment#b67215ccb618c9d0', partial_args=(), partial_kwargs=None, external=False), FunctionReference('__main__:increment_and_double#eaa2b7f9012bc881', partial_args=(), partial_kwargs=None, external=False)}, runner={'type': 'local'}, correlation_id='cid_3810c7b9f91f', content_key=VersionedDataSourceKey(key='c/31068125b3d6543518fbb7ce7878b1db2ebfb1268f2af67483779f91f5c99530', version='146b29b5-3d13-495b-ac7c-418bbc1cb2cf'))" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "increment_and_double.memento(2)" + ] + }, + { + "cell_type": "markdown", + "id": "30f43fcf-d667-4633-8bc6-fed6f419de79", + "metadata": {}, + "source": [ + "We can ask Memento to show what it actually observed from the call graph:" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "769c4f69-b8b3-40ea-8531-43fa4c8b8b14", + "metadata": {}, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "%3\n", + "\n", + "\n", + "\n", + "n1\n", + "\n", + "\n", + "increment_and_double(x=2)\n", + "-> number\n", + "0:00:00.004276\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "n2\n", + "\n", + "\n", + "increment(x=2)\n", + "-> number\n", + "0:00:00.000040\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "n1->n2\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "n3\n", + "\n", + "\n", + "double(x=3)\n", + "-> number\n", + "0:00:00.000029\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "n1->n3\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "increment_and_double.memento(2).graph()" + ] + }, + { + "cell_type": "markdown", + "id": "fd6b8561-e2c4-4473-9ab7-c0a459c57033", + "metadata": {}, + "source": [ + "## Fizz Buzz Example\n", + "In this example, we implement Fizz Buzz, defined as follows:\n", + "```\n", + "Given an integer n, return a string array answer (1-indexed) where:\n", + "\n", + "answer[i] == \"FizzBuzz\" if i is divisible by 3 and 5.\n", + "answer[i] == \"Fizz\" if i is divisible by 3.\n", + "answer[i] == \"Buzz\" if i is divisible by 5.\n", + "answer[i] == i (as a string) if none of the above conditions are true.\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "13363352-3237-4e9c-bba7-0bea0c2a3af9", + "metadata": {}, + "outputs": [], + "source": [ + "@memento_function\n", + "def fizz_buzz(n: int) -> list[str]:\n", + " print(f\"Calculating {n}\")\n", + " time.sleep(0.2)\n", + " if n == 0:\n", + " return []\n", + " answer = \"\"\n", + " if (n % 3) == 0:\n", + " answer += \"Fizz\"\n", + " if (n % 5) == 0:\n", + " answer += \"Buzz\"\n", + " return fizz_buzz(n-1) + [answer or str(n)]" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "d505d40f-6ffd-4478-bdca-219f2b8c83f0", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Calculating 1\n", + "Calculating 0\n" + ] + }, + { + "data": { + "text/plain": [ + "['1']" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fizz_buzz(1)" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "c0b53630-291f-436d-83fb-c3f3b6cd012d", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['1']" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fizz_buzz(1)" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "2bdc6994-f968-4e12-8936-bef8a6702997", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Calculating 5\n", + "Calculating 4\n", + "Calculating 3\n", + "Calculating 2\n" + ] + }, + { + "data": { + "text/plain": [ + "['1', '2', 'Fizz', '4', 'Buzz']" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fizz_buzz(5)" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "bc68c92a-3c53-4b62-8177-7c3c346c67c1", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Calculating 20\n", + "Calculating 19\n", + "Calculating 18\n", + "Calculating 17\n", + "Calculating 16\n", + "Calculating 15\n", + "Calculating 14\n", + "Calculating 13\n", + "Calculating 12\n", + "Calculating 11\n", + "Calculating 10\n", + "Calculating 9\n", + "Calculating 8\n", + "Calculating 7\n", + "Calculating 6\n" + ] + }, + { + "data": { + "text/plain": [ + "['1',\n", + " '2',\n", + " 'Fizz',\n", + " '4',\n", + " 'Buzz',\n", + " 'Fizz',\n", + " '7',\n", + " '8',\n", + " 'Fizz',\n", + " 'Buzz',\n", + " '11',\n", + " 'Fizz',\n", + " '13',\n", + " '14',\n", + " 'FizzBuzz',\n", + " '16',\n", + " '17',\n", + " 'Fizz',\n", + " '19',\n", + " 'Buzz']" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fizz_buzz(20)" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "866846a5-59fd-4f30-b288-2f74ee1315f0", + "metadata": {}, + "outputs": [], + "source": [ + "m = fizz_buzz.memento(1)" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "52b2efec-64e8-4af6-b628-0b4155b7d031", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[(0,),\n", + " (1,),\n", + " (2,),\n", + " (3,),\n", + " (4,),\n", + " (5,),\n", + " (6,),\n", + " (7,),\n", + " (8,),\n", + " (9,),\n", + " (10,),\n", + " (11,),\n", + " (12,),\n", + " (13,),\n", + " (14,),\n", + " (15,),\n", + " (16,),\n", + " (17,),\n", + " (18,),\n", + " (19,),\n", + " (20,)]" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sorted([m.invocation_metadata.fn_reference_with_args.args for m in fizz_buzz.list_mementos()])" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "4b9f2e90-6f7a-4352-9233-9d72fe2b69a1", + "metadata": {}, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "%3\n", + "\n", + "\n", + "\n", + "n1\n", + "\n", + "\n", + "fizz_buzz(n=20)\n", + "-> list_result\n", + "0:00:03.059921\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "n2\n", + "\n", + "\n", + "fizz_buzz(n=19)\n", + "-> list_result\n", + "0:00:02.857348\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "n1->n2\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "n3\n", + "\n", + "\n", + "fizz_buzz(n=18)\n", + "-> list_result\n", + "0:00:02.654348\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "n2->n3\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "n4\n", + "\n", + "\n", + "fizz_buzz(n=17)\n", + "-> list_result\n", + "0:00:02.451883\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "n3->n4\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "n5\n", + "\n", + "\n", + "fizz_buzz(n=16)\n", + "-> list_result\n", + "0:00:02.249322\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "n4->n5\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "n6\n", + "\n", + "\n", + "fizz_buzz(n=15)\n", + "-> list_result\n", + "0:00:02.046878\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "n5->n6\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "n7\n", + "\n", + "\n", + "fizz_buzz(n=14)\n", + "-> list_result\n", + "0:00:01.843399\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "n6->n7\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "n8\n", + "\n", + "\n", + "fizz_buzz(n=13)\n", + "-> list_result\n", + "0:00:01.638363\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "n7->n8\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "n9\n", + "\n", + "\n", + "fizz_buzz(n=12)\n", + "-> list_result\n", + "0:00:01.433738\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "n8->n9\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "n10\n", + "\n", + "\n", + "fizz_buzz(n=11)\n", + "-> list_result\n", + "0:00:01.228284\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "n9->n10\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "n11\n", + "\n", + "\n", + "fizz_buzz(n=10)\n", + "-> list_result\n", + "0:00:01.023622\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "n10->n11\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "n12\n", + "\n", + "\n", + "fizz_buzz(n=9)\n", + "-> list_result\n", + "0:00:00.819005\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "n11->n12\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "n13\n", + "\n", + "\n", + "fizz_buzz(n=8)\n", + "-> list_result\n", + "0:00:00.614102\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "n12->n13\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "n14\n", + "\n", + "\n", + "fizz_buzz(n=7)\n", + "-> list_result\n", + "0:00:00.407984\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "n13->n14\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "n15\n", + "\n", + "\n", + "fizz_buzz(n=6)\n", + "-> list_result\n", + "0:00:00.203490\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "n14->n15\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "n16\n", + "\n", + "\n", + "fizz_buzz(n=5)\n", + "-> list_result\n", + "0:00:00.816944\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "n15->n16\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "n17\n", + "\n", + "\n", + "fizz_buzz(n=4)\n", + "-> list_result\n", + "0:00:00.612324\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "n16->n17\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "n18\n", + "\n", + "\n", + "fizz_buzz(n=3)\n", + "-> list_result\n", + "0:00:00.408278\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "n17->n18\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "n19\n", + "\n", + "\n", + "fizz_buzz(n=2)\n", + "-> list_result\n", + "0:00:00.204779\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "n18->n19\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "n20\n", + "\n", + "\n", + "fizz_buzz(n=1)\n", + "-> list_result\n", + "0:00:00.405597\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "n19->n20\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "n21\n", + "\n", + "\n", + "fizz_buzz(n=0)\n", + "-> list_result\n", + "0:00:00.200649\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "n20->n21\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fizz_buzz.memento(20).graph()" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "c643653c-1968-4e92-bdf7-cfe5eea1b56f", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['1',\n", + " '2',\n", + " 'Fizz',\n", + " '4',\n", + " 'Buzz',\n", + " 'Fizz',\n", + " '7',\n", + " '8',\n", + " 'Fizz',\n", + " 'Buzz',\n", + " '11',\n", + " 'Fizz',\n", + " '13',\n", + " '14',\n", + " 'FizzBuzz']" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fizz_buzz(15)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.10.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}