From 46904b82074bd03f9bea9f5db6c2fda497ba4205 Mon Sep 17 00:00:00 2001 From: Lilian Besson Date: Tue, 23 Feb 2021 00:03:24 +0100 Subject: [PATCH] Fix #29 --- ...s_the_best_one_based_on_the_datatype.ipynb | 5323 +++++++++++++++++ 1 file changed, 5323 insertions(+) create mode 100644 Extending_lolviz_with_a_unified_display_function_that_chooses_the_best_one_based_on_the_datatype.ipynb diff --git a/Extending_lolviz_with_a_unified_display_function_that_chooses_the_best_one_based_on_the_datatype.ipynb b/Extending_lolviz_with_a_unified_display_function_that_chooses_the_best_one_based_on_the_datatype.ipynb new file mode 100644 index 0000000..c4ff52f --- /dev/null +++ b/Extending_lolviz_with_a_unified_display_function_that_chooses_the_best_one_based_on_the_datatype.ipynb @@ -0,0 +1,5323 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "toc": "true" + }, + "source": [ + "

Table of Contents

\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Extending [lolviz](https://github.com/parrt/lolviz) with a unified display function that chooses the best one based on the datatype\n", + "\n", + "> See [this issue](https://github.com/parrt/lolviz/issues/27): « Could we add a \"super\" display function that chooses the best one based on the datatype? »" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T21:00:49.497356Z", + "start_time": "2021-02-22T21:00:49.307423Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPython 3.6.9\n", + "IPython 7.16.1\n", + "\n", + "lolviz 1.4.4\n", + "\n", + "compiler : GCC 8.4.0\n", + "system : Linux\n", + "release : 5.4.0-65-generic\n", + "machine : x86_64\n", + "processor : x86_64\n", + "CPU cores : 8\n", + "interpreter: 64bit\n" + ] + } + ], + "source": [ + "%load_ext watermark\n", + "%watermark -v -m -p lolviz" + ] + }, + { + "cell_type": "code", + "execution_count": 164, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T21:33:43.068635Z", + "start_time": "2021-02-22T21:33:43.064744Z" + } + }, + "outputs": [], + "source": [ + "import lolviz" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Adding this unified display function" + ] + }, + { + "cell_type": "code", + "execution_count": 316, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T22:44:57.087340Z", + "start_time": "2021-02-22T22:44:57.074846Z" + } + }, + "outputs": [], + "source": [ + "modes = [ \"str\", \"matrix\", \"call\", \"calls\", \"obj\", \"tree\", \"lol\", \"list\", \"tree\" ]\n", + "\n", + "def unified_lolviz(obj=None, mode:modes=None, **kwargs):\n", + " \"\"\" Unified function to display `obj` with lolviz, in Jupyter notebook only.\"\"\"\n", + " try:\n", + " if mode == \"str\" or isinstance(obj, str):\n", + " return lolviz.strviz(obj, **kwargs)\n", + " elif \"\" == str(type(obj)):\n", + " # can't use isinstance(obj, np.ndarray) without import numpy!\n", + " return lolviz.matrixviz(obj, **kwargs)\n", + " elif mode == \"matrix\":\n", + " # Experimental transparent use of np.array()\n", + " try:\n", + " from numpy import array as _\n", + " return lolviz.matrixviz(_(obj), **kwargs)\n", + " del _\n", + " except:\n", + " return lolviz.matrixviz(obj, **kwargs)\n", + " elif mode == \"call\":\n", + " from sys import _getframe\n", + " return lolviz.callviz(frame=_getframe(1), **kwargs)\n", + " del _getframe\n", + " elif mode == \"calls\":\n", + " return lolviz.callsviz( **kwargs)\n", + " elif mode == \"lol\" or isinstance(obj, (tuple, list)) and obj and isinstance(obj[0], (tuple, list)):\n", + " # obj is a list, is non empty, and obj[0] is a list!\n", + " return lolviz.lolviz(obj, **kwargs)\n", + " elif mode == \"list\" or isinstance(obj, (tuple, list)):\n", + " return lolviz.listviz(obj, **kwargs)\n", + " elif mode == \"tree\" or isinstance(obj, dict):\n", + " return lolviz.treeviz(obj, **kwargs) # default\n", + " else:\n", + " return lolviz.objviz(obj, **kwargs) # default\n", + " except TypeError:\n", + " # unable to use lolviz, let's just return the object,\n", + " # it will be nicely displayed by IPython\n", + " return obj\n", + "\n", + "viz = unified_lolviz" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Testing naively" + ] + }, + { + "cell_type": "code", + "execution_count": 95, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T21:19:54.236216Z", + "start_time": "2021-02-22T21:19:54.199863Z" + } + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "node139754583851912\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "2\n", + "\n", + "\n", + "3\n", + "\n", + "\n", + "'hi'\n", + "\n", + "\n", + "'mom'\n", + "\n", + "\n", + "{3, 4}\n", + "\n", + "{'parrt': 'user'}\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 95, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "data = ['hi', 'mom', {3, 4}, {\"parrt\": \"user\"}]\n", + "viz(data)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Testing from within a Jupyter notebook\n", + "\n", + "I test here all [the features of lolviz](https://github.com/parrt/lolviz#functionality) :" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### List" + ] + }, + { + "cell_type": "code", + "execution_count": 96, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T21:19:55.266004Z", + "start_time": "2021-02-22T21:19:55.257420Z" + } + }, + "outputs": [], + "source": [ + "squares = [ i**2 for i in range(10) ]" + ] + }, + { + "cell_type": "code", + "execution_count": 97, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T21:19:55.623201Z", + "start_time": "2021-02-22T21:19:55.614046Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]" + ] + }, + "execution_count": 97, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "squares" + ] + }, + { + "cell_type": "code", + "execution_count": 98, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T21:19:56.050026Z", + "start_time": "2021-02-22T21:19:55.997691Z" + } + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "node139754583807368\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "2\n", + "\n", + "\n", + "3\n", + "\n", + "\n", + "4\n", + "\n", + "\n", + "5\n", + "\n", + "\n", + "6\n", + "\n", + "\n", + "7\n", + "\n", + "\n", + "8\n", + "\n", + "\n", + "9\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "4\n", + "\n", + "\n", + "9\n", + "\n", + "\n", + "16\n", + "\n", + "\n", + "25\n", + "\n", + "\n", + "36\n", + "\n", + "\n", + "49\n", + "\n", + "\n", + "64\n", + "\n", + "81\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 98, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "viz(squares)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Under the hood of this unified function `viz`, it was calling `lolvzi.listviz`:" + ] + }, + { + "cell_type": "code", + "execution_count": 99, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T21:19:56.583483Z", + "start_time": "2021-02-22T21:19:56.531316Z" + } + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "node139754583807368\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "2\n", + "\n", + "\n", + "3\n", + "\n", + "\n", + "4\n", + "\n", + "\n", + "5\n", + "\n", + "\n", + "6\n", + "\n", + "\n", + "7\n", + "\n", + "\n", + "8\n", + "\n", + "\n", + "9\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "4\n", + "\n", + "\n", + "9\n", + "\n", + "\n", + "16\n", + "\n", + "\n", + "25\n", + "\n", + "\n", + "36\n", + "\n", + "\n", + "49\n", + "\n", + "\n", + "64\n", + "\n", + "81\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 99, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "lolviz.listviz(squares)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### List of lists" + ] + }, + { + "cell_type": "code", + "execution_count": 100, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T21:19:56.863026Z", + "start_time": "2021-02-22T21:19:56.858620Z" + } + }, + "outputs": [], + "source": [ + "n, m = 3, 4\n", + "example_matrix = [[0 if i != j else 1 for i in range(n)] for j in range(m)]" + ] + }, + { + "cell_type": "code", + "execution_count": 101, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T21:19:57.028640Z", + "start_time": "2021-02-22T21:19:57.023185Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[[1, 0, 0], [0, 1, 0], [0, 0, 1], [0, 0, 0]]" + ] + }, + "execution_count": 101, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "example_matrix" + ] + }, + { + "cell_type": "code", + "execution_count": 102, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T21:19:57.286784Z", + "start_time": "2021-02-22T21:19:57.231629Z" + } + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "node139754583524616\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "2\n", + "\n", + "3\n", + "\n", + "\n", + "\n", + "node139754583553160\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "2\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "node139754583524616:0->node139754583553160:w\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "node139754580861448\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "2\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "1\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "node139754583524616:1->node139754580861448:w\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "node139754584005064\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "2\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "0\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "node139754583524616:2->node139754584005064:w\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "node139754584017544\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "2\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "node139754583524616:3->node139754584017544:w\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 102, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "viz(example_matrix)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If we want, we can force the `lolviz.matrixviz` mode:" + ] + }, + { + "cell_type": "code", + "execution_count": 103, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T21:19:57.734136Z", + "start_time": "2021-02-22T21:19:57.682448Z" + } + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "node139754583226288\n", + "\n", + "\n", + "1\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "1\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "1\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 103, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "viz(example_matrix, mode='matrix')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "And this works without having to manually import numpy or convert the list-of-list to a numpy array!" + ] + }, + { + "cell_type": "code", + "execution_count": 104, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T21:19:58.538958Z", + "start_time": "2021-02-22T21:19:58.529778Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Object `np` not found.\n" + ] + } + ], + "source": [ + "np?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### List of lists of lists???" + ] + }, + { + "cell_type": "code", + "execution_count": 105, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T21:19:59.362434Z", + "start_time": "2021-02-22T21:19:59.352624Z" + } + }, + "outputs": [], + "source": [ + "n, m, o = 2, 3, 4\n", + "example_3D_matrix = [[[\n", + " 1 if i < j < k else 0\n", + " for i in range(n)]\n", + " for j in range(m)]\n", + " for k in range(o)]" + ] + }, + { + "cell_type": "code", + "execution_count": 106, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T21:19:59.656264Z", + "start_time": "2021-02-22T21:19:59.648794Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[[[0, 0], [0, 0], [0, 0]],\n", + " [[0, 0], [0, 0], [0, 0]],\n", + " [[0, 0], [1, 0], [0, 0]],\n", + " [[0, 0], [1, 0], [1, 1]]]" + ] + }, + "execution_count": 106, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "example_3D_matrix" + ] + }, + { + "cell_type": "code", + "execution_count": 107, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T21:20:00.073184Z", + "start_time": "2021-02-22T21:20:00.013993Z" + } + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "node139754583973640\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "2\n", + "\n", + "3\n", + "\n", + "\n", + "\n", + "node139754584018632\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "2\n", + "\n", + "\n", + "[0, 0]\n", + "\n", + "\n", + "[0, 0]\n", + "\n", + "[0, 0]\n", + "\n", + "\n", + "\n", + "node139754583973640:0->node139754584018632:w\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "node139754583903240\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "2\n", + "\n", + "\n", + "[0, 0]\n", + "\n", + "\n", + "[0, 0]\n", + "\n", + "[0, 0]\n", + "\n", + "\n", + "\n", + "node139754583973640:1->node139754583903240:w\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "node139754583995272\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "2\n", + "\n", + "\n", + "[0, 0]\n", + "\n", + "\n", + "[1, 0]\n", + "\n", + "[0, 0]\n", + "\n", + "\n", + "\n", + "node139754583973640:2->node139754583995272:w\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "node139754583538440\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "2\n", + "\n", + "\n", + "[0, 0]\n", + "\n", + "\n", + "[1, 0]\n", + "\n", + "[1, 1]\n", + "\n", + "\n", + "\n", + "node139754583973640:3->node139754583538440:w\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 107, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "viz(example_3D_matrix)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "It works, even if it is not as pretty." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Tree\n", + "Only for binary trees, apparently. Let's try with a dictionary that looks like a binary tree:" + ] + }, + { + "cell_type": "code", + "execution_count": 108, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T21:20:05.501818Z", + "start_time": "2021-02-22T21:20:05.494074Z" + } + }, + "outputs": [], + "source": [ + "anakin = {\n", + " \"name\": \"Anakin Skywalker\",\n", + " \"son\": {\n", + " \"name\": \"Luke Skywalker\",\n", + " },\n", + " \"daughter\": {\n", + " \"name\": \"Leia Skywalker\",\n", + " },\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 109, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T21:20:05.794288Z", + "start_time": "2021-02-22T21:20:05.788786Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'daughter': {'name': 'Leia Skywalker'},\n", + " 'name': 'Anakin Skywalker',\n", + " 'son': {'name': 'Luke Skywalker'}}\n" + ] + } + ], + "source": [ + "from pprint import pprint\n", + "pprint(anakin)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Then by remembering the correction function, we can do:" + ] + }, + { + "cell_type": "code", + "execution_count": 110, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T21:20:15.198056Z", + "start_time": "2021-02-22T21:20:15.136153Z" + } + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "node139754865714016\n", + "\n", + "\n", + "'name' \n", + "\n", + "\n", + " 'Anakin Skywalker'\n", + "\n", + "\n", + "'son' \n", + "\n", + "\n", + "    \n", + "\n", + "\n", + "'daughter' \n", + "\n", + "\n", + "    \n", + "\n", + "\n", + "\n", + "node139754864857448\n", + "\n", + "\n", + "'name' \n", + "\n", + "\n", + " 'Luke Skywalker'\n", + "\n", + "\n", + "\n", + "node139754865714016:c->node139754864857448\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "node139754863124272\n", + "\n", + "\n", + "'name' \n", + "\n", + "\n", + " 'Leia Skywalker'\n", + "\n", + "\n", + "\n", + "node139754865714016:c->node139754863124272\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 110, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "lolviz.treeviz(anakin)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "But it's simpler to use the automatic function!" + ] + }, + { + "cell_type": "code", + "execution_count": 111, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T21:20:16.464414Z", + "start_time": "2021-02-22T21:20:16.406024Z" + } + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "node139754865714016\n", + "\n", + "\n", + "'name' \n", + "\n", + "\n", + " 'Anakin Skywalker'\n", + "\n", + "\n", + "'son' \n", + "\n", + "\n", + "    \n", + "\n", + "\n", + "'daughter' \n", + "\n", + "\n", + "    \n", + "\n", + "\n", + "\n", + "node139754864857448\n", + "\n", + "\n", + "'name' \n", + "\n", + "\n", + " 'Luke Skywalker'\n", + "\n", + "\n", + "\n", + "node139754865714016:c->node139754864857448\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "node139754863124272\n", + "\n", + "\n", + "'name' \n", + "\n", + "\n", + " 'Leia Skywalker'\n", + "\n", + "\n", + "\n", + "node139754865714016:c->node139754863124272\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 111, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "viz(anakin)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "It works out of the box for dictionaries!\n", + "\n", + "Let's check another example:" + ] + }, + { + "cell_type": "code", + "execution_count": 116, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T21:22:09.715116Z", + "start_time": "2021-02-22T21:22:09.709228Z" + } + }, + "outputs": [], + "source": [ + "anakin_rec = {\n", + " \"name\": \"Anakin Skywalker\",\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 117, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T21:22:11.096862Z", + "start_time": "2021-02-22T21:22:11.094367Z" + } + }, + "outputs": [], + "source": [ + "luke_rec = {\n", + " \"name\": \"Luke Skywalker\",\n", + " \"father\": anakin_rec,\n", + "}\n", + "leia_rec = {\n", + " \"name\": \"Leia Skywalker\",\n", + " \"father\": anakin_rec,\n", + "}," + ] + }, + { + "cell_type": "code", + "execution_count": 118, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T21:22:12.124089Z", + "start_time": "2021-02-22T21:22:12.117992Z" + } + }, + "outputs": [], + "source": [ + "anakin_rec.update({\n", + " \"son\": luke_rec,\n", + " \"daughter\": leia_rec,\n", + "})" + ] + }, + { + "cell_type": "code", + "execution_count": 121, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T21:22:20.809362Z", + "start_time": "2021-02-22T21:22:20.803453Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'daughter': ({'father': ,\n", + " 'name': 'Leia Skywalker'},),\n", + " 'name': 'Anakin Skywalker',\n", + " 'son': {'father': ,\n", + " 'name': 'Luke Skywalker'}}\n" + ] + } + ], + "source": [ + "from pprint import pprint\n", + "pprint(anakin_rec)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "But it's simpler to use the automatic function!" + ] + }, + { + "cell_type": "code", + "execution_count": 124, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T21:22:37.021528Z", + "start_time": "2021-02-22T21:22:36.971979Z" + } + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "node139754864347464\n", + "\n", + "\n", + "'name' \n", + "\n", + "\n", + " 'Anakin Skywalker'\n", + "\n", + "\n", + "'son' \n", + "\n", + "\n", + "    \n", + "\n", + "\n", + "'daughter' \n", + "\n", + "\n", + "    \n", + "\n", + "\n", + "\n", + "node139754864052696\n", + "\n", + "\n", + "'name' \n", + "\n", + "\n", + " 'Luke Skywalker'\n", + "\n", + "\n", + "'father' \n", + "\n", + "\n", + "    \n", + "\n", + "\n", + "\n", + "node139754864347464:c->node139754864052696\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "node139754859924336\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "  \n", + "\n", + "\n", + "\n", + "node139754864347464:c->node139754859924336\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "node139754864052696:c->node139754864347464\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "node139754862935784\n", + "\n", + "\n", + "'name' \n", + "\n", + "\n", + " 'Leia Skywalker'\n", + "\n", + "\n", + "'father' \n", + "\n", + "\n", + "    \n", + "\n", + "\n", + "\n", + "node139754859924336:c->node139754862935784\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "node139754862935784:c->node139754864347464\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 124, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "viz(anakin_rec)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "It works too for recursive dictionaries!\n", + "\n", + "Let's check another example:" + ] + }, + { + "cell_type": "code", + "execution_count": 125, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T21:22:50.339063Z", + "start_time": "2021-02-22T21:22:50.329594Z" + } + }, + "outputs": [], + "source": [ + "class Tree:\n", + " def __init__(self, value, left=None, right=None):\n", + " self.value = value\n", + " self.left = left\n", + " self.right = right\n", + " \n", + "root = Tree('parrt',\n", + " Tree('mary',\n", + " Tree('jim',\n", + " Tree('srinivasan'),\n", + " Tree('april'))),\n", + " Tree('xue',None,Tree('mike')))" + ] + }, + { + "cell_type": "code", + "execution_count": 126, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T21:22:52.036406Z", + "start_time": "2021-02-22T21:22:51.971620Z" + } + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "node139754584139312\n", + "\n", + "\n", + "\n", + "Tree\n", + "\n", + "\n", + "\n", + "value \n", + "\n", + " 'parrt'\n", + "\n", + "\n", + "\n", + "\n", + "left\n", + "\n", + "\n", + "right\n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + "\n", + "node139754584139200\n", + "\n", + "\n", + "\n", + "Tree\n", + "\n", + "\n", + "\n", + "value \n", + "\n", + " 'mary'\n", + "\n", + "\n", + "\n", + "\n", + "left\n", + "\n", + "\n", + "right\n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + "\n", + "node139754584139312:c->node139754584139200\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "node139754584139256\n", + "\n", + "\n", + "\n", + "Tree\n", + "\n", + "\n", + "\n", + "value \n", + "\n", + " 'xue'\n", + "\n", + "\n", + "\n", + "\n", + "left\n", + "\n", + "\n", + "right\n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + "\n", + "node139754584139312:c->node139754584139256\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "node139754584138864\n", + "\n", + "\n", + "\n", + "Tree\n", + "\n", + "\n", + "\n", + "value \n", + "\n", + " 'jim'\n", + "\n", + "\n", + "\n", + "\n", + "left\n", + "\n", + "\n", + "right\n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + "\n", + "node139754584139200:c->node139754584138864\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "node139754584140040\n", + "\n", + "\n", + "\n", + "Tree\n", + "\n", + "\n", + "\n", + "value \n", + "\n", + " 'srinivasan'\n", + "\n", + "\n", + "\n", + "\n", + "left\n", + "\n", + "\n", + "right\n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + "\n", + "node139754584138864:c->node139754584140040\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "node139754584139928\n", + "\n", + "\n", + "\n", + "Tree\n", + "\n", + "\n", + "\n", + "value \n", + "\n", + " 'april'\n", + "\n", + "\n", + "\n", + "\n", + "left\n", + "\n", + "\n", + "right\n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + "\n", + "node139754584138864:c->node139754584139928\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "node139754584139088\n", + "\n", + "\n", + "\n", + "Tree\n", + "\n", + "\n", + "\n", + "value \n", + "\n", + " 'mike'\n", + "\n", + "\n", + "\n", + "\n", + "left\n", + "\n", + "\n", + "right\n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + "\n", + "node139754584139256:c->node139754584139088\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 126, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "lolviz.treeviz(root)" + ] + }, + { + "cell_type": "code", + "execution_count": 127, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T21:22:55.432029Z", + "start_time": "2021-02-22T21:22:55.362276Z" + } + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "node139754584139312\n", + "\n", + "\n", + "\n", + "Tree\n", + "\n", + "\n", + "\n", + "value \n", + "\n", + " 'parrt'\n", + "\n", + "\n", + "\n", + "\n", + "left\n", + "\n", + "\n", + "right\n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + "\n", + "node139754584139200\n", + "\n", + "\n", + "\n", + "Tree\n", + "\n", + "\n", + "\n", + "value \n", + "\n", + " 'mary'\n", + "\n", + "\n", + "\n", + "\n", + "left\n", + "\n", + "\n", + "right\n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + "\n", + "node139754584139312:c->node139754584139200\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "node139754584139256\n", + "\n", + "\n", + "\n", + "Tree\n", + "\n", + "\n", + "\n", + "value \n", + "\n", + " 'xue'\n", + "\n", + "\n", + "\n", + "\n", + "left\n", + "\n", + "\n", + "right\n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + "\n", + "node139754584139312:c->node139754584139256\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "node139754584138864\n", + "\n", + "\n", + "\n", + "Tree\n", + "\n", + "\n", + "\n", + "value \n", + "\n", + " 'jim'\n", + "\n", + "\n", + "\n", + "\n", + "left\n", + "\n", + "\n", + "right\n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + "\n", + "node139754584139200:c->node139754584138864\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "node139754584140040\n", + "\n", + "\n", + "\n", + "Tree\n", + "\n", + "\n", + "\n", + "value \n", + "\n", + " 'srinivasan'\n", + "\n", + "\n", + "\n", + "\n", + "left\n", + "\n", + "\n", + "right\n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + "\n", + "node139754584138864:c->node139754584140040\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "node139754584139928\n", + "\n", + "\n", + "\n", + "Tree\n", + "\n", + "\n", + "\n", + "value \n", + "\n", + " 'april'\n", + "\n", + "\n", + "\n", + "\n", + "left\n", + "\n", + "\n", + "right\n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + "\n", + "node139754584138864:c->node139754584139928\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "node139754584139088\n", + "\n", + "\n", + "\n", + "Tree\n", + "\n", + "\n", + "\n", + "value \n", + "\n", + " 'mike'\n", + "\n", + "\n", + "\n", + "\n", + "left\n", + "\n", + "\n", + "right\n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + " \n", + "\n", + "\n", + "\n", + "node139754584139256:c->node139754584139088\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 127, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "viz(root, mode=\"tree\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Objects" + ] + }, + { + "cell_type": "code", + "execution_count": 128, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T21:23:02.175733Z", + "start_time": "2021-02-22T21:23:02.127908Z" + } + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "node139754865714016\n", + "\n", + "\n", + "'name' \n", + "\n", + "\n", + " 'Anakin Skywalker'\n", + "\n", + "\n", + "'son' \n", + "\n", + "\n", + "    \n", + "\n", + "\n", + "'daughter' \n", + "\n", + "\n", + "    \n", + "\n", + "\n", + "\n", + "node139754864857448\n", + "\n", + "\n", + "'name' \n", + "\n", + "\n", + " 'Luke Skywalker'\n", + "\n", + "\n", + "\n", + "node139754865714016:c->node139754864857448\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "node139754863124272\n", + "\n", + "\n", + "'name' \n", + "\n", + "\n", + " 'Leia Skywalker'\n", + "\n", + "\n", + "\n", + "node139754865714016:c->node139754863124272\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 128, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "viz(anakin)" + ] + }, + { + "cell_type": "code", + "execution_count": 129, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T21:23:02.850836Z", + "start_time": "2021-02-22T21:23:02.790322Z" + } + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "node139754578804232\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "1\n", + "\n", + "2\n", + "\n", + "\n", + "\n", + "node139754864857448\n", + "\n", + "\n", + "'name' \n", + "\n", + "\n", + " 'Luke Skywalker'\n", + "\n", + "\n", + "\n", + "node139754578804232:1->node139754864857448:w\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "node139754863124272\n", + "\n", + "\n", + "'name' \n", + "\n", + "\n", + " 'Leia Skywalker'\n", + "\n", + "\n", + "\n", + "node139754578804232:2->node139754863124272:w\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 129, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "viz(anakin.values())" + ] + }, + { + "cell_type": "code", + "execution_count": 130, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T21:23:05.331753Z", + "start_time": "2021-02-22T21:23:05.271109Z" + } + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "node139754578801480\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "1\n", + "\n", + "2\n", + "\n", + "\n", + "\n", + "node139754578215752\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "'name'\n", + "\n", + "'Anakin Skywalker'\n", + "\n", + "\n", + "\n", + "node139754578801480:0->node139754578215752:w\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "node139754579571144\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "'son'\n", + "\n", + "  \n", + "\n", + "\n", + "\n", + "node139754578801480:1->node139754579571144:w\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "node139754578173512\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "'daughter'\n", + "\n", + "  \n", + "\n", + "\n", + "\n", + "node139754578801480:2->node139754578173512:w\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "node139754864857448\n", + "\n", + "\n", + "'name' \n", + "\n", + "\n", + " 'Luke Skywalker'\n", + "\n", + "\n", + "\n", + "node139754579571144:c->node139754864857448\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "node139754863124272\n", + "\n", + "\n", + "'name' \n", + "\n", + "\n", + " 'Leia Skywalker'\n", + "\n", + "\n", + "\n", + "node139754578173512:c->node139754863124272\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 130, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "viz(anakin.items())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For complex numbers for instance?" + ] + }, + { + "cell_type": "code", + "execution_count": 131, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T21:23:07.388434Z", + "start_time": "2021-02-22T21:23:07.380331Z" + } + }, + "outputs": [], + "source": [ + "z = 1+4j" + ] + }, + { + "cell_type": "code", + "execution_count": 132, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T21:23:07.723890Z", + "start_time": "2021-02-22T21:23:07.716998Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(1+4j)\n" + ] + } + ], + "source": [ + "print(z)" + ] + }, + { + "cell_type": "code", + "execution_count": 133, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T21:23:08.148923Z", + "start_time": "2021-02-22T21:23:08.101786Z" + } + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "node139754581383056\n", + "<complex:(1+4j)>\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 133, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "viz(z)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "OK, this fails.\n", + "We could improve `viz` for `complex`, but it's beyond the scope of this small experiment." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Calls\n", + "\n", + "Let's explore a recursive function:" + ] + }, + { + "cell_type": "code", + "execution_count": 176, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T21:44:53.950971Z", + "start_time": "2021-02-22T21:44:53.943638Z" + } + }, + "outputs": [], + "source": [ + "def factorial(n):\n", + " if n < 0: return 0\n", + " elif n == 0: return 1\n", + " else: return n * factorial(n - 1)" + ] + }, + { + "cell_type": "code", + "execution_count": 177, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T21:44:54.562409Z", + "start_time": "2021-02-22T21:44:54.558447Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " 0! = 1\n", + " 1! = 1\n", + " 2! = 2\n", + " 3! = 6\n", + " 4! = 24\n", + " 5! = 120\n", + " 6! = 720\n", + " 7! = 5040\n", + " 8! = 40320\n", + " 9! = 362880\n", + "10! = 3628800\n", + "11! = 39916800\n" + ] + } + ], + "source": [ + "for n in range(12):\n", + " print(f\"{n:>2}! = {factorial(n):>10}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "And now with some visualization:" + ] + }, + { + "cell_type": "code", + "execution_count": 178, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T21:44:57.235964Z", + "start_time": "2021-02-22T21:44:57.232955Z" + } + }, + "outputs": [], + "source": [ + "from IPython.display import display" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This is what `lolviz.callviz` shows:" + ] + }, + { + "cell_type": "code", + "execution_count": 180, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T21:45:03.300181Z", + "start_time": "2021-02-22T21:45:02.979466Z" + } + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "node139754583156104\n", + "\n", + "\n", + "\n", + "factorial2\n", + "\n", + "\n", + "\n", + "n \n", + "\n", + " 4\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "node139755216231048\n", + "\n", + "\n", + "\n", + "factorial2\n", + "\n", + "\n", + "\n", + "n \n", + "\n", + " 3\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "node50772520\n", + "\n", + "\n", + "\n", + "factorial2\n", + "\n", + "\n", + "\n", + "n \n", + "\n", + " 2\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "node51975112\n", + "\n", + "\n", + "\n", + "factorial2\n", + "\n", + "\n", + "\n", + "n \n", + "\n", + " 1\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "node52305768\n", + "\n", + "\n", + "\n", + "factorial2\n", + "\n", + "\n", + "\n", + "n \n", + "\n", + " 0\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " 4! = 24\n" + ] + } + ], + "source": [ + "def factorial2(n):\n", + " display(lolviz.callviz(varnames=[\"n\"]))\n", + " if n < 0: return 0\n", + " elif n == 0: return 1\n", + " else: return n * factorial2(n - 1)\n", + " \n", + "n = 4\n", + "print(f\"{n:>2}! = {factorial2(n):>10}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We really see the \"call stack\" as the system keeps track of the nested calls. I like that! 👌\n", + "\n", + "But again, I'm lazy, I want to just use the `viz` function:" + ] + }, + { + "cell_type": "code", + "execution_count": 181, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T21:45:14.434563Z", + "start_time": "2021-02-22T21:45:14.427343Z" + } + }, + "outputs": [], + "source": [ + "def factorial3(n):\n", + " display(viz(varnames=[\"n\"], mode=\"call\"))\n", + " if n < 0: return 0\n", + " elif n == 0: return 1\n", + " else: return n * factorial3(n - 1)" + ] + }, + { + "cell_type": "code", + "execution_count": 183, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T21:45:19.367780Z", + "start_time": "2021-02-22T21:45:19.094960Z" + } + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "node139754858422344\n", + "\n", + "\n", + "\n", + "factorial3\n", + "\n", + "\n", + "\n", + "n \n", + "\n", + " 4\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "node52010408\n", + "\n", + "\n", + "\n", + "factorial3\n", + "\n", + "\n", + "\n", + "n \n", + "\n", + " 3\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "node139755216156424\n", + "\n", + "\n", + "\n", + "factorial3\n", + "\n", + "\n", + "\n", + "n \n", + "\n", + " 2\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "node51838072\n", + "\n", + "\n", + "\n", + "factorial3\n", + "\n", + "\n", + "\n", + "n \n", + "\n", + " 1\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "node51345896\n", + "\n", + "\n", + "\n", + "factorial3\n", + "\n", + "\n", + "\n", + "n \n", + "\n", + " 0\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4! = 24\n" + ] + } + ], + "source": [ + "n = 4\n", + "print(f\"{n}! = {factorial3(n)}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Okay, by using the optional `frame=` argument of `lolviz.callviz`, and some `sys._getframe` black magic, we can do this!\n", + "\n", + "> See " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Can we write a `@show_recursion` function decorator, to automatically do this visualization of recursive calls for us?" + ] + }, + { + "cell_type": "code", + "execution_count": 274, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T22:06:23.681497Z", + "start_time": "2021-02-22T22:06:23.676355Z" + } + }, + "outputs": [], + "source": [ + "def show_recursion(varnames=None):\n", + " def showing_recursion_with_varnames(function):\n", + " nonlocal varnames\n", + " # https://stackoverflow.com/questions/582056/getting-list-of-parameter-names-inside-python-function#4051447\n", + " if varnames is None:\n", + " varnames = function.__code__.co_varnames\n", + " import lolviz\n", + " from IPython.display import display\n", + " from functools import wraps\n", + " @wraps(function)\n", + " def wrapped_function(*args, **kwargs):\n", + " nonlocal display, wraps, varnames, lolviz\n", + " ##print(f\"args = {args}, of type = {type(args)}\")\n", + " ##print(f\"kwargs = {kwargs}, of type = {type(kwargs)}\")\n", + " #print(f\"varnames = {varnames}\")\n", + " display(lolviz.callsviz(varnames=varnames))\n", + " return function(*args, **kwargs)\n", + " return wrapped_function\n", + " return showing_recursion_with_varnames" + ] + }, + { + "cell_type": "code", + "execution_count": 275, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T22:06:33.593612Z", + "start_time": "2021-02-22T22:06:33.044487Z" + }, + "scrolled": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "node52368264\n", + "\n", + "\n", + "\n", + "globals\n", + "\n", + "\n", + "\n", + "n \n", + "\n", + " 4\n", + "\n", + "\n", + "\n", + "node52300856\n", + "\n", + "\n", + "\n", + "wrapped_function\n", + "\n", + " ... \n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "node52368264\n", + "\n", + "\n", + "\n", + "globals\n", + "\n", + "\n", + "\n", + "n \n", + "\n", + " 4\n", + "\n", + "\n", + "\n", + "node52300856\n", + "\n", + "\n", + "\n", + "wrapped_function\n", + "\n", + " ... \n", + "\n", + "\n", + "\n", + "\n", + "node52572888\n", + "\n", + "\n", + "\n", + "factorial4\n", + "\n", + "\n", + "\n", + "n \n", + "\n", + " 4\n", + "\n", + "\n", + "\n", + "f0 \n", + "\n", + " 0\n", + "\n", + "\n", + "\n", + "f1 \n", + "\n", + " 1\n", + "\n", + "\n", + "\n", + "\n", + "node52289640\n", + "\n", + "\n", + "\n", + "wrapped_function\n", + "\n", + " ... \n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "node52368264\n", + "\n", + "\n", + "\n", + "globals\n", + "\n", + "\n", + "\n", + "n \n", + "\n", + " 4\n", + "\n", + "\n", + "\n", + "node52300856\n", + "\n", + "\n", + "\n", + "wrapped_function\n", + "\n", + " ... \n", + "\n", + "\n", + "\n", + "\n", + "node52572888\n", + "\n", + "\n", + "\n", + "factorial4\n", + "\n", + "\n", + "\n", + "n \n", + "\n", + " 4\n", + "\n", + "\n", + "\n", + "f0 \n", + "\n", + " 0\n", + "\n", + "\n", + "\n", + "f1 \n", + "\n", + " 1\n", + "\n", + "\n", + "\n", + "\n", + "node52289640\n", + "\n", + "\n", + "\n", + "wrapped_function\n", + "\n", + " ... \n", + "\n", + "\n", + "\n", + "\n", + "node52302344\n", + "\n", + "\n", + "\n", + "factorial4\n", + "\n", + "\n", + "\n", + "n \n", + "\n", + " 3\n", + "\n", + "\n", + "\n", + "f0 \n", + "\n", + " 0\n", + "\n", + "\n", + "\n", + "f1 \n", + "\n", + " 1\n", + "\n", + "\n", + "\n", + "\n", + "node51698888\n", + "\n", + "\n", + "\n", + "wrapped_function\n", + "\n", + " ... \n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "node52368264\n", + "\n", + "\n", + "\n", + "globals\n", + "\n", + "\n", + "\n", + "n \n", + "\n", + " 4\n", + "\n", + "\n", + "\n", + "node52300856\n", + "\n", + "\n", + "\n", + "wrapped_function\n", + "\n", + " ... \n", + "\n", + "\n", + "\n", + "\n", + "node52572888\n", + "\n", + "\n", + "\n", + "factorial4\n", + "\n", + "\n", + "\n", + "n \n", + "\n", + " 4\n", + "\n", + "\n", + "\n", + "f0 \n", + "\n", + " 0\n", + "\n", + "\n", + "\n", + "f1 \n", + "\n", + " 1\n", + "\n", + "\n", + "\n", + "\n", + "node52289640\n", + "\n", + "\n", + "\n", + "wrapped_function\n", + "\n", + " ... \n", + "\n", + "\n", + "\n", + "\n", + "node52302344\n", + "\n", + "\n", + "\n", + "factorial4\n", + "\n", + "\n", + "\n", + "n \n", + "\n", + " 3\n", + "\n", + "\n", + "\n", + "f0 \n", + "\n", + " 0\n", + "\n", + "\n", + "\n", + "f1 \n", + "\n", + " 1\n", + "\n", + "\n", + "\n", + "\n", + "node51698888\n", + "\n", + "\n", + "\n", + "wrapped_function\n", + "\n", + " ... \n", + "\n", + "\n", + "\n", + "\n", + "node52518392\n", + "\n", + "\n", + "\n", + "factorial4\n", + "\n", + "\n", + "\n", + "n \n", + "\n", + " 2\n", + "\n", + "\n", + "\n", + "f0 \n", + "\n", + " 0\n", + "\n", + "\n", + "\n", + "f1 \n", + "\n", + " 1\n", + "\n", + "\n", + "\n", + "\n", + "node52508424\n", + "\n", + "\n", + "\n", + "wrapped_function\n", + "\n", + " ... \n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "node52368264\n", + "\n", + "\n", + "\n", + "globals\n", + "\n", + "\n", + "\n", + "n \n", + "\n", + " 4\n", + "\n", + "\n", + "\n", + "node52300856\n", + "\n", + "\n", + "\n", + "wrapped_function\n", + "\n", + " ... \n", + "\n", + "\n", + "\n", + "\n", + "node52572888\n", + "\n", + "\n", + "\n", + "factorial4\n", + "\n", + "\n", + "\n", + "n \n", + "\n", + " 4\n", + "\n", + "\n", + "\n", + "f0 \n", + "\n", + " 0\n", + "\n", + "\n", + "\n", + "f1 \n", + "\n", + " 1\n", + "\n", + "\n", + "\n", + "\n", + "node52289640\n", + "\n", + "\n", + "\n", + "wrapped_function\n", + "\n", + " ... \n", + "\n", + "\n", + "\n", + "\n", + "node52302344\n", + "\n", + "\n", + "\n", + "factorial4\n", + "\n", + "\n", + "\n", + "n \n", + "\n", + " 3\n", + "\n", + "\n", + "\n", + "f0 \n", + "\n", + " 0\n", + "\n", + "\n", + "\n", + "f1 \n", + "\n", + " 1\n", + "\n", + "\n", + "\n", + "\n", + "node51698888\n", + "\n", + "\n", + "\n", + "wrapped_function\n", + "\n", + " ... \n", + "\n", + "\n", + "\n", + "\n", + "node52518392\n", + "\n", + "\n", + "\n", + "factorial4\n", + "\n", + "\n", + "\n", + "n \n", + "\n", + " 2\n", + "\n", + "\n", + "\n", + "f0 \n", + "\n", + " 0\n", + "\n", + "\n", + "\n", + "f1 \n", + "\n", + " 1\n", + "\n", + "\n", + "\n", + "\n", + "node52508424\n", + "\n", + "\n", + "\n", + "wrapped_function\n", + "\n", + " ... \n", + "\n", + "\n", + "\n", + "\n", + "node51700728\n", + "\n", + "\n", + "\n", + "factorial4\n", + "\n", + "\n", + "\n", + "n \n", + "\n", + " 1\n", + "\n", + "\n", + "\n", + "f0 \n", + "\n", + " 0\n", + "\n", + "\n", + "\n", + "f1 \n", + "\n", + " 1\n", + "\n", + "\n", + "\n", + "\n", + "node52233672\n", + "\n", + "\n", + "\n", + "wrapped_function\n", + "\n", + " ... \n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4! = 24\n" + ] + } + ], + "source": [ + "@show_recursion()\n", + "def factorial4(n, f0=0, f1=1):\n", + " # this is automatically done: display(viz(varnames=[\"n\"], mode=\"call\"))\n", + " if n < 0: return f0\n", + " elif n == 0: return f1\n", + " else: return n * factorial4(n - 1, f0=f0, f1=f1)\n", + " \n", + "n = 4\n", + "print(f\"{n}! = {factorial4(n)}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Well it works, but it's not clean.\n", + "\n", + "I would very much prefer something like [rcviz](https://github.com/DamnedFacts/rcviz), or a more powerful tool like [pyan](https://github.com/davidfraser/pyan) or [pycallgraph](http://pycallgraph.slowchop.com/en/master/).\n", + "\n", + "From the standard library, I just discovered the [trace](https://docs.python.org/3.6/library/trace.html) module, but it seems to be oriented for the command line usage, not in a notebook." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Trying `rcviz`" + ] + }, + { + "cell_type": "code", + "execution_count": 278, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T22:32:04.364752Z", + "start_time": "2021-02-22T22:32:01.368586Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Defaulting to user installation because normal site-packages is not writeable\n", + "Collecting git+https://github.com/DamnedFacts/rcviz\n", + " Cloning https://github.com/DamnedFacts/rcviz to /tmp/pip-req-build-5jsw_yji\n", + "Requirement already satisfied: graphviz in /usr/local/lib/python3.6/dist-packages (from rcviz==0.2) (0.16)\n", + "\u001b[33mWARNING: You are using pip version 20.3.3; however, version 21.0.1 is available.\n", + "You should consider upgrading via the '/usr/bin/python3 -m pip install --upgrade pip' command.\u001b[0m\n" + ] + } + ], + "source": [ + "!pip install git+https://github.com/DamnedFacts/rcviz" + ] + }, + { + "cell_type": "code", + "execution_count": 289, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T22:36:38.280618Z", + "start_time": "2021-02-22T22:36:38.277390Z" + } + }, + "outputs": [], + "source": [ + "import rcviz" + ] + }, + { + "cell_type": "code", + "execution_count": 290, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T22:36:46.037121Z", + "start_time": "2021-02-22T22:36:45.920038Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4! = 24\n", + "callviz: Rendering in inline in Jupyter Notebook\n" + ] + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "%3\n", + "\n", + "nodes=5\n", + "\n", + "\n", + "52454264\n", + "\n", + "factorial5(4)\n", + "\n", + "ret: 24\n", + "\n", + "\n", + "\n", + "51188824\n", + "\n", + "factorial5(3)\n", + "\n", + "ret: 6\n", + "\n", + "\n", + "\n", + "52454264->51188824\n", + "\n", + "\n", + "1 (⇑4)\n", + "\n", + "\n", + "\n", + "52429000\n", + "\n", + "factorial5(2)\n", + "\n", + "ret: 2\n", + "\n", + "\n", + "\n", + "51188824->52429000\n", + "\n", + "\n", + "2 (⇑3)\n", + "\n", + "\n", + "\n", + "52674728\n", + "\n", + "factorial5(1)\n", + "\n", + "ret: 1\n", + "\n", + "\n", + "\n", + "52429000->52674728\n", + "\n", + "\n", + "3 (⇑2)\n", + "\n", + "\n", + "\n", + "52203256\n", + "\n", + "factorial5(0)\n", + "\n", + "ret: 1\n", + "\n", + "\n", + "\n", + "52674728->52203256\n", + "\n", + "\n", + "4 (⇑1)\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 290, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "cg = rcviz.CallGraph()\n", + "\n", + "@rcviz.viz(cg)\n", + "def factorial5(n):\n", + " if n < 0: return 0\n", + " elif n == 0: return 1\n", + " else: return n * factorial5(n - 1)\n", + " \n", + "n = 4\n", + "print(f\"{n}! = {factorial5(n)}\")\n", + "\n", + "cg.render()" + ] + }, + { + "cell_type": "code", + "execution_count": 291, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T22:36:59.103651Z", + "start_time": "2021-02-22T22:36:58.991406Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4! = 3\n", + "callviz: Rendering in inline in Jupyter Notebook\n" + ] + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "%3\n", + "\n", + "nodes=9\n", + "\n", + "\n", + "52456296\n", + "\n", + "fibo(4)\n", + "\n", + "ret: 3\n", + "\n", + "\n", + "\n", + "50666760\n", + "\n", + "fibo(3)\n", + "\n", + "ret: 2\n", + "\n", + "\n", + "\n", + "52456296->50666760\n", + "\n", + "\n", + "1 (⇑5)\n", + "\n", + "\n", + "\n", + "49738120\n", + "\n", + "fibo(2)\n", + "\n", + "ret: 1\n", + "\n", + "\n", + "\n", + "52456296->49738120\n", + "\n", + "\n", + "6 (⇑8)\n", + "\n", + "\n", + "\n", + "51084392\n", + "\n", + "fibo(2)\n", + "\n", + "ret: 1\n", + "\n", + "\n", + "\n", + "50666760->51084392\n", + "\n", + "\n", + "2 (⇑3)\n", + "\n", + "\n", + "\n", + "52434920\n", + "\n", + "fibo(1)\n", + "\n", + "ret: 1\n", + "\n", + "\n", + "\n", + "50666760->52434920\n", + "\n", + "\n", + "5 (⇑4)\n", + "\n", + "\n", + "\n", + "50598744\n", + "\n", + "fibo(1)\n", + "\n", + "ret: 1\n", + "\n", + "\n", + "\n", + "51084392->50598744\n", + "\n", + "\n", + "3 (⇑1)\n", + "\n", + "\n", + "\n", + "52216536\n", + "\n", + "fibo(0)\n", + "\n", + "ret: 0\n", + "\n", + "\n", + "\n", + "51084392->52216536\n", + "\n", + "\n", + "4 (⇑2)\n", + "\n", + "\n", + "\n", + "51227256\n", + "\n", + "fibo(1)\n", + "\n", + "ret: 1\n", + "\n", + "\n", + "\n", + "49738120->51227256\n", + "\n", + "\n", + "7 (⇑6)\n", + "\n", + "\n", + "\n", + "52430152\n", + "\n", + "fibo(0)\n", + "\n", + "ret: 0\n", + "\n", + "\n", + "\n", + "49738120->52430152\n", + "\n", + "\n", + "8 (⇑7)\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 291, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "cg = rcviz.CallGraph()\n", + "\n", + "@rcviz.viz(cg)\n", + "def fibo(n):\n", + " if n <= 0: return 0\n", + " elif n == 1: return 1\n", + " else: return fibo(n-1) + fibo(n-2)\n", + " \n", + "n = 4\n", + "print(f\"{n}! = {fibo(n)}\")\n", + "\n", + "cg.render()" + ] + }, + { + "cell_type": "code", + "execution_count": 292, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T22:37:10.580366Z", + "start_time": "2021-02-22T22:37:10.425776Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4! = 3\n", + "callviz: Rendering in inline in Jupyter Notebook\n" + ] + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "%3\n", + "\n", + "nodes=7\n", + "\n", + "\n", + "51835400\n", + "\n", + "fibo2(4)\n", + "\n", + "ret: 3\n", + "\n", + "\n", + "\n", + "52085992\n", + "\n", + "fibo2(3)\n", + "\n", + "ret: 2\n", + "\n", + "\n", + "\n", + "51835400->52085992\n", + "\n", + "\n", + "1 (⇑5)\n", + "\n", + "\n", + "\n", + "52900488\n", + "\n", + "fibo2(2)\n", + "\n", + "ret: 1\n", + "\n", + "\n", + "\n", + "51835400->52900488\n", + "\n", + "\n", + "6 (⇑6)\n", + "\n", + "\n", + "\n", + "52262952\n", + "\n", + "fibo2(2)\n", + "\n", + "ret: 1\n", + "\n", + "\n", + "\n", + "52085992->52262952\n", + "\n", + "\n", + "2 (⇑3)\n", + "\n", + "\n", + "\n", + "53127960\n", + "\n", + "fibo2(1)\n", + "\n", + "ret: 1\n", + "\n", + "\n", + "\n", + "52085992->53127960\n", + "\n", + "\n", + "5 (⇑4)\n", + "\n", + "\n", + "\n", + "52906936\n", + "\n", + "fibo2(1)\n", + "\n", + "ret: 1\n", + "\n", + "\n", + "\n", + "52262952->52906936\n", + "\n", + "\n", + "3 (⇑1)\n", + "\n", + "\n", + "\n", + "53134024\n", + "\n", + "fibo2(0)\n", + "\n", + "ret: 0\n", + "\n", + "\n", + "\n", + "52262952->53134024\n", + "\n", + "\n", + "4 (⇑2)\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 292, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from functools import lru_cache as memoize\n", + "cg = rcviz.CallGraph()\n", + "\n", + "@rcviz.viz(cg)\n", + "@memoize(maxsize=None)\n", + "def fibo2(n):\n", + " if n <= 0: return 0\n", + " elif n == 1: return 1\n", + " else: return fibo2(n-1) + fibo2(n-2)\n", + " \n", + "n = 4\n", + "print(f\"{n}! = {fibo2(n)}\")\n", + "\n", + "cg.render()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### More experiments on a \"triple\" recursive function\n", + "\n", + "Just to complicate things more, let's write a \"fibonnaci\" like recursive function that calls three sub-terms:" + ] + }, + { + "cell_type": "code", + "execution_count": 338, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T22:53:02.777902Z", + "start_time": "2021-02-22T22:53:02.772273Z" + } + }, + "outputs": [], + "source": [ + "cg = rcviz.CallGraph()\n", + "\n", + "@rcviz.viz(cg)\n", + "def fibo_three(n):\n", + " if n <= 0: return 0\n", + " elif n == 1: return 1\n", + " elif n == 2: return 1\n", + " else: return fibo_three(n-1) + fibo_three(n-2) + fibo_three(n-3)" + ] + }, + { + "cell_type": "code", + "execution_count": 339, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T22:53:03.378629Z", + "start_time": "2021-02-22T22:53:03.182031Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "5! = 7\n", + "callviz: Rendering in inline in Jupyter Notebook\n" + ] + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "%3\n", + "\n", + "nodes=13\n", + "\n", + "\n", + "54048328\n", + "\n", + "fibo_three(5)\n", + "\n", + "ret: 7\n", + "\n", + "\n", + "\n", + "54048888\n", + "\n", + "fibo_three(4)\n", + "\n", + "ret: 4\n", + "\n", + "\n", + "\n", + "54048328->54048888\n", + "\n", + "\n", + "1 (⇑7)\n", + "\n", + "\n", + "\n", + "54052808\n", + "\n", + "fibo_three(3)\n", + "\n", + "ret: 2\n", + "\n", + "\n", + "\n", + "54048328->54052808\n", + "\n", + "\n", + "8 (⇑11)\n", + "\n", + "\n", + "\n", + "54055048\n", + "\n", + "fibo_three(2)\n", + "\n", + "ret: 1\n", + "\n", + "\n", + "\n", + "54048328->54055048\n", + "\n", + "\n", + "12 (⇑12)\n", + "\n", + "\n", + "\n", + "54049448\n", + "\n", + "fibo_three(3)\n", + "\n", + "ret: 2\n", + "\n", + "\n", + "\n", + "54048888->54049448\n", + "\n", + "\n", + "2 (⇑4)\n", + "\n", + "\n", + "\n", + "54051688\n", + "\n", + "fibo_three(2)\n", + "\n", + "ret: 1\n", + "\n", + "\n", + "\n", + "54048888->54051688\n", + "\n", + "\n", + "6 (⇑5)\n", + "\n", + "\n", + "\n", + "54052248\n", + "\n", + "fibo_three(1)\n", + "\n", + "ret: 1\n", + "\n", + "\n", + "\n", + "54048888->54052248\n", + "\n", + "\n", + "7 (⇑6)\n", + "\n", + "\n", + "\n", + "54050008\n", + "\n", + "fibo_three(2)\n", + "\n", + "ret: 1\n", + "\n", + "\n", + "\n", + "54049448->54050008\n", + "\n", + "\n", + "3 (⇑1)\n", + "\n", + "\n", + "\n", + "54050568\n", + "\n", + "fibo_three(1)\n", + "\n", + "ret: 1\n", + "\n", + "\n", + "\n", + "54049448->54050568\n", + "\n", + "\n", + "4 (⇑2)\n", + "\n", + "\n", + "\n", + "54051128\n", + "\n", + "fibo_three(0)\n", + "\n", + "ret: 0\n", + "\n", + "\n", + "\n", + "54049448->54051128\n", + "\n", + "\n", + "5 (⇑3)\n", + "\n", + "\n", + "\n", + "54053368\n", + "\n", + "fibo_three(2)\n", + "\n", + "ret: 1\n", + "\n", + "\n", + "\n", + "54052808->54053368\n", + "\n", + "\n", + "9 (⇑8)\n", + "\n", + "\n", + "\n", + "54053928\n", + "\n", + "fibo_three(1)\n", + "\n", + "ret: 1\n", + "\n", + "\n", + "\n", + "54052808->54053928\n", + "\n", + "\n", + "10 (⇑9)\n", + "\n", + "\n", + "\n", + "54054488\n", + "\n", + "fibo_three(0)\n", + "\n", + "ret: 0\n", + "\n", + "\n", + "\n", + "54052808->54054488\n", + "\n", + "\n", + "11 (⇑10)\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 339, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "n = 5\n", + "print(f\"{n}! = {fibo_three(n)}\")\n", + "\n", + "cg.render()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Using this non-memoized function leads to already 13 nodes for just $n=5$!" + ] + }, + { + "cell_type": "code", + "execution_count": 340, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T22:53:21.885101Z", + "start_time": "2021-02-22T22:53:21.878371Z" + } + }, + "outputs": [], + "source": [ + "cg = rcviz.CallGraph()\n", + "\n", + "@rcviz.viz(cg)\n", + "@memoize(maxsize=None)\n", + "def fibo_three_memo(n):\n", + " if n <= 0: return 0\n", + " elif n == 1: return 1\n", + " elif n == 2: return 1\n", + " else: return fibo_three_memo(n-1) + fibo_three_memo(n-2) + fibo_three_memo(n-3)" + ] + }, + { + "cell_type": "code", + "execution_count": 341, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T22:53:22.524190Z", + "start_time": "2021-02-22T22:53:22.371895Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "5! = 7\n", + "callviz: Rendering in inline in Jupyter Notebook\n" + ] + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "%3\n", + "\n", + "nodes=10\n", + "\n", + "\n", + "54081128\n", + "\n", + "fibo_three_memo(5)\n", + "\n", + "ret: 7\n", + "\n", + "\n", + "\n", + "53618600\n", + "\n", + "fibo_three_memo(4)\n", + "\n", + "ret: 4\n", + "\n", + "\n", + "\n", + "54081128->53618600\n", + "\n", + "\n", + "1 (⇑7)\n", + "\n", + "\n", + "\n", + "54046648\n", + "\n", + "fibo_three_memo(3)\n", + "\n", + "ret: 2\n", + "\n", + "\n", + "\n", + "54081128->54046648\n", + "\n", + "\n", + "8 (⇑8)\n", + "\n", + "\n", + "\n", + "54045528\n", + "\n", + "fibo_three_memo(2)\n", + "\n", + "ret: 1\n", + "\n", + "\n", + "\n", + "54081128->54045528\n", + "\n", + "\n", + "9 (⇑9)\n", + "\n", + "\n", + "\n", + "54044968\n", + "\n", + "fibo_three_memo(3)\n", + "\n", + "ret: 2\n", + "\n", + "\n", + "\n", + "53618600->54044968\n", + "\n", + "\n", + "2 (⇑4)\n", + "\n", + "\n", + "\n", + "54080568\n", + "\n", + "fibo_three_memo(2)\n", + "\n", + "ret: 1\n", + "\n", + "\n", + "\n", + "53618600->54080568\n", + "\n", + "\n", + "6 (⇑5)\n", + "\n", + "\n", + "\n", + "54056248\n", + "\n", + "fibo_three_memo(1)\n", + "\n", + "ret: 1\n", + "\n", + "\n", + "\n", + "53618600->54056248\n", + "\n", + "\n", + "7 (⇑6)\n", + "\n", + "\n", + "\n", + "54046088\n", + "\n", + "fibo_three_memo(2)\n", + "\n", + "ret: 1\n", + "\n", + "\n", + "\n", + "54044968->54046088\n", + "\n", + "\n", + "3 (⇑1)\n", + "\n", + "\n", + "\n", + "54047208\n", + "\n", + "fibo_three_memo(1)\n", + "\n", + "ret: 1\n", + "\n", + "\n", + "\n", + "54044968->54047208\n", + "\n", + "\n", + "4 (⇑2)\n", + "\n", + "\n", + "\n", + "54047768\n", + "\n", + "fibo_three_memo(0)\n", + "\n", + "ret: 0\n", + "\n", + "\n", + "\n", + "54044968->54047768\n", + "\n", + "\n", + "5 (⇑3)\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 341, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "n = 5\n", + "print(f\"{n}! = {fibo_three_memo(n)}\")\n", + "\n", + "cg.render()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As before, we can see that the ternary tree is reduced: there is recursion only on the most lefty branch, thanks to memoization." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##### About `rcviz`\n", + "It's an awesome module!\n", + "Thanks to [@DamnedFacts/](https://github.com/DamnedFacts/) for having [his up-to-date fork](https://github.com/DamnedFacts/rcviz)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### String" + ] + }, + { + "cell_type": "code", + "execution_count": 294, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T22:39:03.163523Z", + "start_time": "2021-02-22T22:39:03.160418Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'0123456789abcdefABCDEF'" + ] + }, + "execution_count": 294, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import string\n", + "string.hexdigits" + ] + }, + { + "cell_type": "code", + "execution_count": 295, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T22:39:03.691286Z", + "start_time": "2021-02-22T22:39:03.630532Z" + } + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "G\n", + "\n", + "\n", + "\n", + "node139755555686920\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "2\n", + "\n", + "\n", + "3\n", + "\n", + "\n", + "4\n", + "\n", + "\n", + "5\n", + "\n", + "\n", + "6\n", + "\n", + "\n", + "7\n", + "\n", + "\n", + "8\n", + "\n", + "\n", + "9\n", + "\n", + "\n", + "10\n", + "\n", + "\n", + "11\n", + "\n", + "\n", + "12\n", + "\n", + "\n", + "13\n", + "\n", + "\n", + "14\n", + "\n", + "\n", + "15\n", + "\n", + "\n", + "16\n", + "\n", + "\n", + "17\n", + "\n", + "\n", + "18\n", + "\n", + "\n", + "19\n", + "\n", + "\n", + "20\n", + "\n", + "\n", + "21\n", + "'\n", + "\n", + "0\n", + "\n", + "1\n", + "\n", + "2\n", + "\n", + "3\n", + "\n", + "4\n", + "\n", + "5\n", + "\n", + "6\n", + "\n", + "7\n", + "\n", + "8\n", + "\n", + "9\n", + "\n", + "a\n", + "\n", + "b\n", + "\n", + "c\n", + "\n", + "d\n", + "\n", + "e\n", + "\n", + "f\n", + "\n", + "A\n", + "\n", + "B\n", + "\n", + "C\n", + "\n", + "D\n", + "\n", + "E\n", + "\n", + "F\n", + "'\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 295, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "viz(string.hexdigits)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Interactive test of all the modes\n", + "\n", + "Using [IPyWidgets](https://ipywidgets.readthedocs.io/en/stable/examples/Using%20Interact.html#Widget-abbreviations):" + ] + }, + { + "cell_type": "code", + "execution_count": 317, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T22:45:00.140799Z", + "start_time": "2021-02-22T22:45:00.138473Z" + } + }, + "outputs": [], + "source": [ + "from pprint import pprint\n", + "from ipywidgets import interact" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Trying on all the objects used above:" + ] + }, + { + "cell_type": "code", + "execution_count": 321, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T22:48:23.256693Z", + "start_time": "2021-02-22T22:48:23.248867Z" + } + }, + "outputs": [], + "source": [ + "objs = [\n", + " string.ascii_lowercase,\n", + " lolviz,\n", + " data,\n", + " squares,\n", + " example_matrix,\n", + " example_3D_matrix,\n", + " anakin,\n", + " anakin_rec,\n", + " leia_rec,\n", + " luke_rec,\n", + " root,\n", + " z,\n", + "]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "And the different modes, except for \"call\" and \"calls\" which only work inside functions:" + ] + }, + { + "cell_type": "code", + "execution_count": 326, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T22:49:21.928607Z", + "start_time": "2021-02-22T22:49:21.924722Z" + } + }, + "outputs": [], + "source": [ + "partial_modes = ['str', 'matrix', 'obj', 'tree', 'lol', 'list']" + ] + }, + { + "cell_type": "code", + "execution_count": 329, + "metadata": { + "ExecuteTime": { + "end_time": "2021-02-22T22:51:32.422620Z", + "start_time": "2021-02-22T22:51:32.339270Z" + } + }, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "cd1bb696c23f48c29d47c63868b1c1ad", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "interactive(children=(Dropdown(description='obj', options=('abcdefghijklmnopqrstuvwxyz',