From 7bc787972f115bf40548e12b2c459bd199a7ae40 Mon Sep 17 00:00:00 2001 From: Ivo Melse Date: Wed, 26 Jun 2024 14:05:01 +0200 Subject: [PATCH 1/6] Add poetry dependency --- notebooks/hi.html | 361 ---------------------------------------------- poetry.lock | 186 ++++++++++++++++++++++-- pyproject.toml | 1 + 3 files changed, 175 insertions(+), 373 deletions(-) delete mode 100644 notebooks/hi.html diff --git a/notebooks/hi.html b/notebooks/hi.html deleted file mode 100644 index cb4eb42..0000000 --- a/notebooks/hi.html +++ /dev/null @@ -1,361 +0,0 @@ - - - - - - - - - - - - - - - -
-

-
- - - - - - -
-

-
- - - - - -
- - -
-
- - - -
- - - - - \ No newline at end of file diff --git a/poetry.lock b/poetry.lock index 44ddb58..54e9c68 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,9 +1,10 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry and should not be changed by hand. [[package]] name = "anyio" version = "4.4.0" description = "High level compatibility layer for multiple asynchronous event loop implementations" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -24,6 +25,7 @@ trio = ["trio (>=0.23)"] name = "appnope" version = "0.1.4" description = "Disable App Nap on macOS >= 10.9" +category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -35,6 +37,7 @@ files = [ name = "argon2-cffi" version = "23.1.0" description = "Argon2 for Python" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -55,6 +58,7 @@ typing = ["mypy"] name = "argon2-cffi-bindings" version = "21.2.0" description = "Low-level CFFI bindings for Argon2" +category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -92,6 +96,7 @@ tests = ["pytest"] name = "arrow" version = "1.3.0" description = "Better dates & times for Python" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -105,12 +110,13 @@ types-python-dateutil = ">=2.8.10" [package.extras] doc = ["doc8", "sphinx (>=7.0.0)", "sphinx-autobuild", "sphinx-autodoc-typehints", "sphinx_rtd_theme (>=1.3.0)"] -test = ["dateparser (==1.*)", "pre-commit", "pytest", "pytest-cov", "pytest-mock", "pytz (==2021.1)", "simplejson (==3.*)"] +test = ["dateparser (>=1.0.0,<2.0.0)", "pre-commit", "pytest", "pytest-cov", "pytest-mock", "pytz (==2021.1)", "simplejson (>=3.0.0,<4.0.0)"] [[package]] name = "asttokens" version = "2.4.1" description = "Annotate AST trees with source code positions" +category = "main" optional = false python-versions = "*" files = [ @@ -129,6 +135,7 @@ test = ["astroid (>=1,<2)", "astroid (>=2,<4)", "pytest"] name = "async-lru" version = "2.0.4" description = "Simple LRU cache for asyncio" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -140,6 +147,7 @@ files = [ name = "attrs" version = "23.2.0" description = "Classes Without Boilerplate" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -159,6 +167,7 @@ tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "p name = "babel" version = "2.15.0" description = "Internationalization utilities" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -173,6 +182,7 @@ dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"] name = "beautifulsoup4" version = "4.12.3" description = "Screen-scraping library" +category = "dev" optional = false python-versions = ">=3.6.0" files = [ @@ -194,6 +204,7 @@ lxml = ["lxml"] name = "bleach" version = "6.1.0" description = "An easy safelist-based HTML-sanitizing tool." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -212,6 +223,7 @@ css = ["tinycss2 (>=1.1.0,<1.3)"] name = "certifi" version = "2024.6.2" description = "Python package for providing Mozilla's CA Bundle." +category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -223,6 +235,7 @@ files = [ name = "cffi" version = "1.16.0" description = "Foreign Function Interface for Python calling C code." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -287,6 +300,7 @@ pycparser = "*" name = "cfgv" version = "3.4.0" description = "Validate configuration and produce human readable error messages." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -298,6 +312,7 @@ files = [ name = "charset-normalizer" version = "3.3.2" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +category = "dev" optional = false python-versions = ">=3.7.0" files = [ @@ -397,6 +412,7 @@ files = [ name = "colorama" version = "0.4.6" description = "Cross-platform colored terminal text." +category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" files = [ @@ -408,6 +424,7 @@ files = [ name = "comm" version = "0.2.2" description = "Jupyter Python Comm implementation, for usage in ipykernel, xeus-python etc." +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -425,6 +442,7 @@ test = ["pytest"] name = "debugpy" version = "1.8.1" description = "An implementation of the Debug Adapter Protocol for Python" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -456,6 +474,7 @@ files = [ name = "decorator" version = "5.1.1" description = "Decorators for Humans" +category = "main" optional = false python-versions = ">=3.5" files = [ @@ -467,6 +486,7 @@ files = [ name = "defusedxml" version = "0.7.1" description = "XML bomb protection for Python stdlib modules" +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -478,6 +498,7 @@ files = [ name = "distlib" version = "0.3.8" description = "Distribution utilities" +category = "dev" optional = false python-versions = "*" files = [ @@ -489,6 +510,7 @@ files = [ name = "executing" version = "2.0.1" description = "Get the currently executing AST node of a frame, and other information" +category = "main" optional = false python-versions = ">=3.5" files = [ @@ -503,6 +525,7 @@ tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipyth name = "fastjsonschema" version = "2.20.0" description = "Fastest Python implementation of JSON schema" +category = "dev" optional = false python-versions = "*" files = [ @@ -517,6 +540,7 @@ devel = ["colorama", "json-spec", "jsonschema", "pylint", "pytest", "pytest-benc name = "filelock" version = "3.15.4" description = "A platform independent file lock." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -533,6 +557,7 @@ typing = ["typing-extensions (>=4.8)"] name = "fqdn" version = "1.5.1" description = "Validates fully-qualified domain names against RFC 1123, so that they are acceptable to modern bowsers" +category = "dev" optional = false python-versions = ">=2.7, !=3.0, !=3.1, !=3.2, !=3.3, !=3.4, <4" files = [ @@ -544,6 +569,7 @@ files = [ name = "h11" version = "0.14.0" description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -555,6 +581,7 @@ files = [ name = "httpcore" version = "1.0.5" description = "A minimal low-level HTTP client." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -569,13 +596,14 @@ h11 = ">=0.13,<0.15" [package.extras] asyncio = ["anyio (>=4.0,<5.0)"] http2 = ["h2 (>=3,<5)"] -socks = ["socksio (==1.*)"] +socks = ["socksio (>=1.0.0,<2.0.0)"] trio = ["trio (>=0.22.0,<0.26.0)"] [[package]] name = "httpx" version = "0.27.0" description = "The next generation HTTP client." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -586,20 +614,21 @@ files = [ [package.dependencies] anyio = "*" certifi = "*" -httpcore = "==1.*" +httpcore = ">=1.0.0,<2.0.0" idna = "*" sniffio = "*" [package.extras] brotli = ["brotli", "brotlicffi"] -cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] +cli = ["click (>=8.0.0,<9.0.0)", "pygments (>=2.0.0,<3.0.0)", "rich (>=10,<14)"] http2 = ["h2 (>=3,<5)"] -socks = ["socksio (==1.*)"] +socks = ["socksio (>=1.0.0,<2.0.0)"] [[package]] name = "identify" version = "2.5.36" description = "File identification library for Python" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -614,6 +643,7 @@ license = ["ukkonen"] name = "idna" version = "3.7" description = "Internationalized Domain Names in Applications (IDNA)" +category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -625,6 +655,7 @@ files = [ name = "iniconfig" version = "2.0.0" description = "brain-dead simple config-ini parsing" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -636,6 +667,7 @@ files = [ name = "ipykernel" version = "6.29.4" description = "IPython Kernel for Jupyter" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -649,7 +681,7 @@ comm = ">=0.1.1" debugpy = ">=1.6.5" ipython = ">=7.23.1" jupyter-client = ">=6.1.12" -jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +jupyter-core = ">=4.12,<5.0.0 || >=5.1.0" matplotlib-inline = ">=0.1" nest-asyncio = "*" packaging = "*" @@ -669,6 +701,7 @@ test = ["flaky", "ipyparallel", "pre-commit", "pytest (>=7.0)", "pytest-asyncio name = "ipython" version = "8.25.0" description = "IPython: Productive Interactive Computing" +category = "main" optional = false python-versions = ">=3.10" files = [ @@ -706,6 +739,7 @@ test-extra = ["curio", "ipython[test]", "matplotlib (!=3.2.0)", "nbformat", "num name = "ipywidgets" version = "8.1.3" description = "Jupyter interactive widgets" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -727,6 +761,7 @@ test = ["ipykernel", "jsonschema", "pytest (>=3.6.0)", "pytest-cov", "pytz"] name = "isoduration" version = "20.11.0" description = "Operations with ISO 8601 durations" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -741,6 +776,7 @@ arrow = ">=0.15.0" name = "jedi" version = "0.19.1" description = "An autocompletion tool for Python that can be used for text editors." +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -760,6 +796,7 @@ testing = ["Django", "attrs", "colorama", "docopt", "pytest (<7.0.0)"] name = "jinja2" version = "3.1.4" description = "A very fast and expressive template engine." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -777,6 +814,7 @@ i18n = ["Babel (>=2.7)"] name = "json5" version = "0.9.25" description = "A Python implementation of the JSON5 data format." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -784,10 +822,28 @@ files = [ {file = "json5-0.9.25.tar.gz", hash = "sha256:548e41b9be043f9426776f05df8635a00fe06104ea51ed24b67f908856e151ae"}, ] +[[package]] +name = "jsonpickle" +version = "3.2.2" +description = "Python library for serializing arbitrary object graphs into JSON" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "jsonpickle-3.2.2-py3-none-any.whl", hash = "sha256:87cd82d237fd72c5a34970e7222dddc0accc13fddf49af84111887ed9a9445aa"}, + {file = "jsonpickle-3.2.2.tar.gz", hash = "sha256:d425fd2b8afe9f5d7d57205153403fbf897782204437882a477e8eed60930f8c"}, +] + +[package.extras] +docs = ["furo", "rst.linker (>=1.9)", "sphinx"] +packaging = ["build", "twine"] +testing = ["bson", "ecdsa", "feedparser", "gmpy2", "numpy", "pandas", "pymongo", "pytest (>=3.5,!=3.7.3)", "pytest-benchmark", "pytest-benchmark[histogram]", "pytest-checkdocs (>=1.2.3)", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-ruff (>=0.2.1)", "scikit-learn", "scipy", "scipy (>=1.9.3)", "simplejson", "sqlalchemy", "ujson"] + [[package]] name = "jsonpointer" version = "3.0.0" description = "Identify specific nodes in a JSON document (RFC 6901)" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -799,6 +855,7 @@ files = [ name = "jsonschema" version = "4.22.0" description = "An implementation of JSON Schema validation for Python" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -828,6 +885,7 @@ format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339- name = "jsonschema-specifications" version = "2023.12.1" description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -842,6 +900,7 @@ referencing = ">=0.31.0" name = "jupyter-client" version = "8.6.2" description = "Jupyter protocol implementation and client libraries" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -850,7 +909,7 @@ files = [ ] [package.dependencies] -jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +jupyter-core = ">=4.12,<5.0.0 || >=5.1.0" python-dateutil = ">=2.8.2" pyzmq = ">=23.0" tornado = ">=6.2" @@ -864,6 +923,7 @@ test = ["coverage", "ipykernel (>=6.14)", "mypy", "paramiko", "pre-commit", "pyt name = "jupyter-core" version = "5.7.2" description = "Jupyter core package. A base package on which Jupyter projects rely." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -884,6 +944,7 @@ test = ["ipykernel", "pre-commit", "pytest (<8)", "pytest-cov", "pytest-timeout" name = "jupyter-events" version = "0.10.0" description = "Jupyter Event System library" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -909,6 +970,7 @@ test = ["click", "pre-commit", "pytest (>=7.0)", "pytest-asyncio (>=0.19.0)", "p name = "jupyter-lsp" version = "2.2.5" description = "Multi-Language Server WebSocket proxy for Jupyter Notebook/Lab server" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -923,6 +985,7 @@ jupyter-server = ">=1.1.2" name = "jupyter-server" version = "2.14.1" description = "The backend—i.e. core services, APIs, and REST endpoints—to Jupyter web applications." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -935,7 +998,7 @@ anyio = ">=3.1.0" argon2-cffi = ">=21.1" jinja2 = ">=3.0.3" jupyter-client = ">=7.4.4" -jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +jupyter-core = ">=4.12,<5.0.0 || >=5.1.0" jupyter-events = ">=0.9.0" jupyter-server-terminals = ">=0.4.4" nbconvert = ">=6.4.4" @@ -959,6 +1022,7 @@ test = ["flaky", "ipykernel", "pre-commit", "pytest (>=7.0,<9)", "pytest-console name = "jupyter-server-terminals" version = "0.5.3" description = "A Jupyter Server Extension Providing Terminals." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -978,6 +1042,7 @@ test = ["jupyter-server (>=2.0.0)", "pytest (>=7.0)", "pytest-jupyter[server] (> name = "jupyterlab" version = "4.2.2" description = "JupyterLab computational environment" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -1011,6 +1076,7 @@ upgrade-extension = ["copier (>=8,<10)", "jinja2-time (<0.3)", "pydantic (<2.0)" name = "jupyterlab-pygments" version = "0.3.0" description = "Pygments theme using JupyterLab CSS variables" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -1022,6 +1088,7 @@ files = [ name = "jupyterlab-server" version = "2.27.2" description = "A set of server components for JupyterLab and JupyterLab like applications." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -1047,6 +1114,7 @@ test = ["hatch", "ipykernel", "openapi-core (>=0.18.0,<0.19.0)", "openapi-spec-v name = "jupyterlab-widgets" version = "3.0.11" description = "Jupyter interactive widgets for JupyterLab" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1058,6 +1126,7 @@ files = [ name = "markupsafe" version = "2.1.5" description = "Safely add untrusted strings to HTML/XML markup." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1127,6 +1196,7 @@ files = [ name = "matplotlib-inline" version = "0.1.7" description = "Inline Matplotlib backend for Jupyter" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -1141,6 +1211,7 @@ traitlets = "*" name = "mistune" version = "3.0.2" description = "A sane and fast Markdown parser with useful plugins and renderers" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1152,6 +1223,7 @@ files = [ name = "nbclient" version = "0.10.0" description = "A client library for executing notebooks. Formerly nbconvert's ExecutePreprocessor." +category = "dev" optional = false python-versions = ">=3.8.0" files = [ @@ -1161,7 +1233,7 @@ files = [ [package.dependencies] jupyter-client = ">=6.1.12" -jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +jupyter-core = ">=4.12,<5.0.0 || >=5.1.0" nbformat = ">=5.1" traitlets = ">=5.4" @@ -1174,6 +1246,7 @@ test = ["flaky", "ipykernel (>=6.19.3)", "ipython", "ipywidgets", "nbconvert (>= name = "nbconvert" version = "7.16.4" description = "Converting Jupyter Notebooks (.ipynb files) to other formats. Output formats include asciidoc, html, latex, markdown, pdf, py, rst, script. nbconvert can be used both as a Python library (`import nbconvert`) or as a command line tool (invoked as `jupyter nbconvert ...`)." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -1211,6 +1284,7 @@ webpdf = ["playwright"] name = "nbformat" version = "5.10.4" description = "The Jupyter Notebook format" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -1221,7 +1295,7 @@ files = [ [package.dependencies] fastjsonschema = ">=2.15" jsonschema = ">=2.6" -jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +jupyter-core = ">=4.12,<5.0.0 || >=5.1.0" traitlets = ">=5.1" [package.extras] @@ -1232,6 +1306,7 @@ test = ["pep440", "pre-commit", "pytest", "testpath"] name = "nest-asyncio" version = "1.6.0" description = "Patch asyncio to allow nested event loops" +category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -1239,10 +1314,30 @@ files = [ {file = "nest_asyncio-1.6.0.tar.gz", hash = "sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe"}, ] +[[package]] +name = "networkx" +version = "3.3" +description = "Python package for creating and manipulating graphs and networks" +category = "main" +optional = false +python-versions = ">=3.10" +files = [ + {file = "networkx-3.3-py3-none-any.whl", hash = "sha256:28575580c6ebdaf4505b22c6256a2b9de86b316dc63ba9e93abde3d78dfdbcf2"}, + {file = "networkx-3.3.tar.gz", hash = "sha256:0c127d8b2f4865f59ae9cb8aafcd60b5c70f3241ebd66f7defad7c4ab90126c9"}, +] + +[package.extras] +default = ["matplotlib (>=3.6)", "numpy (>=1.23)", "pandas (>=1.4)", "scipy (>=1.9,!=1.11.0,!=1.11.1)"] +developer = ["changelist (==0.5)", "mypy (>=1.1)", "pre-commit (>=3.2)", "rtoml"] +doc = ["myst-nb (>=1.0)", "numpydoc (>=1.7)", "pillow (>=9.4)", "pydata-sphinx-theme (>=0.14)", "sphinx (>=7)", "sphinx-gallery (>=0.14)", "texext (>=0.6.7)"] +extra = ["lxml (>=4.6)", "pydot (>=2.0)", "pygraphviz (>=1.12)", "sympy (>=1.10)"] +test = ["pytest (>=7.2)", "pytest-cov (>=4.0)"] + [[package]] name = "nodeenv" version = "1.9.1" description = "Node.js virtual environment builder" +category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" files = [ @@ -1254,6 +1349,7 @@ files = [ name = "notebook-shim" version = "0.2.4" description = "A shim layer for notebook traits and config" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1271,6 +1367,7 @@ test = ["pytest", "pytest-console-scripts", "pytest-jupyter", "pytest-tornasync" name = "overrides" version = "7.7.0" description = "A decorator to automatically detect mismatch when overriding a method." +category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -1282,6 +1379,7 @@ files = [ name = "packaging" version = "24.1" description = "Core utilities for Python packages" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -1293,6 +1391,7 @@ files = [ name = "pandocfilters" version = "1.5.1" description = "Utilities for writing pandoc filters in python" +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -1304,6 +1403,7 @@ files = [ name = "parso" version = "0.8.4" description = "A Python Parser" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -1319,6 +1419,7 @@ testing = ["docopt", "pytest"] name = "pexpect" version = "4.9.0" description = "Pexpect allows easy control of interactive console applications." +category = "main" optional = false python-versions = "*" files = [ @@ -1333,6 +1434,7 @@ ptyprocess = ">=0.5" name = "platformdirs" version = "4.2.2" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -1349,6 +1451,7 @@ type = ["mypy (>=1.8)"] name = "pluggy" version = "1.5.0" description = "plugin and hook calling mechanisms for python" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -1364,6 +1467,7 @@ testing = ["pytest", "pytest-benchmark"] name = "pre-commit" version = "3.7.1" description = "A framework for managing and maintaining multi-language pre-commit hooks." +category = "dev" optional = false python-versions = ">=3.9" files = [ @@ -1382,6 +1486,7 @@ virtualenv = ">=20.10.0" name = "prometheus-client" version = "0.20.0" description = "Python client for the Prometheus monitoring system." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -1396,6 +1501,7 @@ twisted = ["twisted"] name = "prompt-toolkit" version = "3.0.47" description = "Library for building powerful interactive command lines in Python" +category = "main" optional = false python-versions = ">=3.7.0" files = [ @@ -1410,6 +1516,7 @@ wcwidth = "*" name = "psutil" version = "6.0.0" description = "Cross-platform lib for process and system monitoring in Python." +category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" files = [ @@ -1439,6 +1546,7 @@ test = ["enum34", "ipaddress", "mock", "pywin32", "wmi"] name = "ptyprocess" version = "0.7.0" description = "Run a subprocess in a pseudo terminal" +category = "main" optional = false python-versions = "*" files = [ @@ -1450,6 +1558,7 @@ files = [ name = "pure-eval" version = "0.2.2" description = "Safely evaluate AST nodes without side effects" +category = "main" optional = false python-versions = "*" files = [ @@ -1464,6 +1573,7 @@ tests = ["pytest"] name = "pycparser" version = "2.22" description = "C parser in Python" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -1475,6 +1585,7 @@ files = [ name = "pygments" version = "2.18.0" description = "Pygments is a syntax highlighting package written in Python." +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -1489,6 +1600,7 @@ windows-terminal = ["colorama (>=0.4.6)"] name = "pyright" version = "1.1.368" description = "Command line wrapper for pyright" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1507,6 +1619,7 @@ dev = ["twine (>=3.4.1)"] name = "pytest" version = "8.2.2" description = "pytest: simple powerful testing with Python" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -1527,6 +1640,7 @@ dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments name = "python-dateutil" version = "2.9.0.post0" description = "Extensions to the standard Python datetime module" +category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" files = [ @@ -1541,6 +1655,7 @@ six = ">=1.5" name = "python-json-logger" version = "2.0.7" description = "A python library adding a json log formatter" +category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -1548,10 +1663,28 @@ files = [ {file = "python_json_logger-2.0.7-py3-none-any.whl", hash = "sha256:f380b826a991ebbe3de4d897aeec42760035ac760345e57b812938dc8b35e2bd"}, ] +[[package]] +name = "pyvis" +version = "0.3.2" +description = "A Python network graph visualization library" +category = "main" +optional = false +python-versions = ">3.6" +files = [ + {file = "pyvis-0.3.2-py3-none-any.whl", hash = "sha256:5720c4ca8161dc5d9ab352015723abb7a8bb8fb443edeb07f7a322db34a97555"}, +] + +[package.dependencies] +ipython = ">=5.3.0" +jinja2 = ">=2.9.6" +jsonpickle = ">=1.4.1" +networkx = ">=1.11" + [[package]] name = "pywin32" version = "306" description = "Python for Window Extensions" +category = "dev" optional = false python-versions = "*" files = [ @@ -1575,6 +1708,7 @@ files = [ name = "pywinpty" version = "2.0.13" description = "Pseudo terminal support for Windows from Python." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -1590,6 +1724,7 @@ files = [ name = "pyyaml" version = "6.0.1" description = "YAML parser and emitter for Python" +category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -1650,6 +1785,7 @@ files = [ name = "pyzmq" version = "26.0.3" description = "Python bindings for 0MQ" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1750,6 +1886,7 @@ cffi = {version = "*", markers = "implementation_name == \"pypy\""} name = "referencing" version = "0.35.1" description = "JSON Referencing + Python" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -1765,6 +1902,7 @@ rpds-py = ">=0.7.0" name = "requests" version = "2.32.3" description = "Python HTTP for Humans." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -1786,6 +1924,7 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] name = "rfc3339-validator" version = "0.1.4" description = "A pure python RFC3339 validator" +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -1800,6 +1939,7 @@ six = "*" name = "rfc3986-validator" version = "0.1.1" description = "Pure python rfc3986 validator" +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -1811,6 +1951,7 @@ files = [ name = "rpds-py" version = "0.18.1" description = "Python bindings to Rust's persistent data structures (rpds)" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -1919,6 +2060,7 @@ files = [ name = "ruff" version = "0.4.10" description = "An extremely fast Python linter and code formatter, written in Rust." +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1945,6 +2087,7 @@ files = [ name = "send2trash" version = "1.8.3" description = "Send file to trash natively under Mac OS X, Windows and Linux" +category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" files = [ @@ -1961,6 +2104,7 @@ win32 = ["pywin32"] name = "setuptools" version = "70.1.1" description = "Easily download, build, install, upgrade, and uninstall Python packages" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -1976,6 +2120,7 @@ testing = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metad name = "six" version = "1.16.0" description = "Python 2 and 3 compatibility utilities" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -1987,6 +2132,7 @@ files = [ name = "sniffio" version = "1.3.1" description = "Sniff out which async library your code is running under" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1998,6 +2144,7 @@ files = [ name = "soupsieve" version = "2.5" description = "A modern CSS selector implementation for Beautiful Soup." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -2009,6 +2156,7 @@ files = [ name = "stack-data" version = "0.6.3" description = "Extract data from python stack frames and tracebacks for informative displays" +category = "main" optional = false python-versions = "*" files = [ @@ -2028,6 +2176,7 @@ tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"] name = "terminado" version = "0.18.1" description = "Tornado websocket backend for the Xterm.js Javascript terminal emulator library." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -2049,6 +2198,7 @@ typing = ["mypy (>=1.6,<2.0)", "traitlets (>=5.11.1)"] name = "tinycss2" version = "1.3.0" description = "A tiny CSS parser" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -2067,6 +2217,7 @@ test = ["pytest", "ruff"] name = "tornado" version = "6.4.1" description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -2087,6 +2238,7 @@ files = [ name = "traitlets" version = "5.14.3" description = "Traitlets Python configuration system" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -2102,6 +2254,7 @@ test = ["argcomplete (>=3.0.3)", "mypy (>=1.7.0)", "pre-commit", "pytest (>=7.0, name = "types-python-dateutil" version = "2.9.0.20240316" description = "Typing stubs for python-dateutil" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -2113,6 +2266,7 @@ files = [ name = "typing-extensions" version = "4.12.2" description = "Backported and Experimental Type Hints for Python 3.8+" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -2124,6 +2278,7 @@ files = [ name = "uri-template" version = "1.3.0" description = "RFC 6570 URI Template Processor" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2138,6 +2293,7 @@ dev = ["flake8", "flake8-annotations", "flake8-bandit", "flake8-bugbear", "flake name = "urllib3" version = "2.2.2" description = "HTTP library with thread-safe connection pooling, file post, and more." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -2155,6 +2311,7 @@ zstd = ["zstandard (>=0.18.0)"] name = "virtualenv" version = "20.26.3" description = "Virtual Python Environment builder" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2175,6 +2332,7 @@ test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess name = "wcwidth" version = "0.2.13" description = "Measures the displayed width of unicode strings in a terminal" +category = "main" optional = false python-versions = "*" files = [ @@ -2186,6 +2344,7 @@ files = [ name = "webcolors" version = "24.6.0" description = "A library for working with the color formats defined by HTML and CSS." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -2201,6 +2360,7 @@ tests = ["coverage[toml]"] name = "webencodings" version = "0.5.1" description = "Character encoding aliases for legacy web content" +category = "dev" optional = false python-versions = "*" files = [ @@ -2212,6 +2372,7 @@ files = [ name = "websocket-client" version = "1.8.0" description = "WebSocket client for Python with low level API options" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -2228,6 +2389,7 @@ test = ["websockets"] name = "widgetsnbextension" version = "4.0.11" description = "Jupyter interactive widgets for Jupyter Notebook" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2238,4 +2400,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "d603e5cb5f43d59da98dfd97f67d391df88b99ed0575d6c4b2e18d0eb7cb034d" +content-hash = "9b9949eeafc83375de11f73fe5e71e57bc145c377ffb8e56ea87e611a9d7a951" diff --git a/pyproject.toml b/pyproject.toml index a983153..8871530 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,6 +13,7 @@ readme = "README.md" [tool.poetry.dependencies] python = "^3.11" ipywidgets = "^8.1.3" +pyvis = "^0.3.2" [tool.poetry.group.test.dependencies] pytest = "^8.2.2" From 429ef18be94614d8887fd676f49433ea8ac73399 Mon Sep 17 00:00:00 2001 From: YouGuessedMyName Date: Wed, 26 Jun 2024 15:15:43 +0200 Subject: [PATCH 2/6] test --- stormvogel/visualization.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stormvogel/visualization.py b/stormvogel/visualization.py index 9fa6461..180986f 100644 --- a/stormvogel/visualization.py +++ b/stormvogel/visualization.py @@ -27,7 +27,7 @@ def __init__( self.model = model if ( name[-5:] != ".html" - ): # We do not require the user to explicitly type .html in their names. + ): # We do not require the user to explicitly type .html in their names name += ".html" self.name = name self.g = Network(notebook=notebook, directed=True, cdn_resources=cdn_resources) From 1472ac77b28bc818c965532b954126c9c9cd58b9 Mon Sep 17 00:00:00 2001 From: YouGuessedMyName Date: Fri, 28 Jun 2024 14:49:16 +0200 Subject: [PATCH 3/6] Added action visualization --- notebooks/die.ipynb | 223 +++++++++++++------------------- notebooks/diegraph.html | 56 ++++----- notebooks/monty.html | 56 ++++----- notebooks/monty_hall.ipynb | 245 ++++++++++++++++-------------------- stormvogel/visualization.py | 22 ++-- 5 files changed, 269 insertions(+), 333 deletions(-) diff --git a/notebooks/die.ipynb b/notebooks/die.ipynb index 7137aad..caca1dc 100644 --- a/notebooks/die.ipynb +++ b/notebooks/die.ipynb @@ -1,145 +1,102 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import stormvogel.model\n", - "import stormvogel.visualization" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "# Create a new model with the name \"Die\"\n", - "dtmc = stormvogel.model.new_dtmc(\"Die\")\n", - "\n", - "init = dtmc.get_initial_state()\n", - "\n", - "# From the initial state, add the transition to 6 new states with probability 1/6th.\n", - "init.set_transitions(\n", - " [(1 / 6, dtmc.new_state(f\"rolled{i}\", {\"rolled\": i})) for i in range(6)]\n", - ")\n", - "\n", - "# Print the resulting model in dot format.\n", - "# print(dtmc.to_dot())" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "scrolled": true - }, - "outputs": [ + "cells": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "diegraph.html\n" - ] + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import stormvogel.model\n", + "import stormvogel.visualization" + ] }, { - "data": { - "text/html": [ - "\n", - " \n", - " " - ], - "text/plain": [ - "" + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "# Create a new model with the name \"Die\"\n", + "dtmc = stormvogel.model.new_dtmc(\"Die\")\n", + "\n", + "init = dtmc.get_initial_state()\n", + "\n", + "# From the initial state, add the transition to 6 new states with probability 1/6th.\n", + "init.set_transitions(\n", + " [(1 / 6, dtmc.new_state(f\"rolled{i}\", {\"rolled\": i})) for i in range(6)]\n", + ")\n", + "\n", + "# Print the resulting model in dot format.\n", + "# print(dtmc.to_dot())" ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "stormvogel.visualization.show(model=dtmc, name=\"diegraph\")" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "hi.html\n" - ] }, { - "data": { - "text/html": [ - "\n", - " \n", - " " + "cell_type": "code", + "execution_count": 3, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "diegraph.html\n" + ] + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } ], - "text/plain": [ - "" + "source": [ + "stormvogel.visualization.show(model=dtmc, name=\"diegraph\")" ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "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.11.2" } - ], - "source": [ - "from pyvis.network import Network\n", - "\n", - "g = Network(notebook=True,cdn_resources=\"remote\")\n", - "g.show_buttons()\n", - "g.show(\"hi.html\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "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.11.2" - } - }, - "nbformat": 4, - "nbformat_minor": 4 + "nbformat": 4, + "nbformat_minor": 4 } diff --git a/notebooks/diegraph.html b/notebooks/diegraph.html index c317554..509d77e 100644 --- a/notebooks/diegraph.html +++ b/notebooks/diegraph.html @@ -1,7 +1,7 @@ - + - - - - - - - - + + + + + + + +

@@ -234,24 +234,24 @@

float: left; } - - - + + +
- - + +
- - + + - \ No newline at end of file + diff --git a/notebooks/monty.html b/notebooks/monty.html index e1628bb..55ce12e 100644 --- a/notebooks/monty.html +++ b/notebooks/monty.html @@ -1,7 +1,7 @@ - + - - - - - - - - + + + + + + + +

@@ -234,24 +234,24 @@

float: left; } - - - + + +
- - + +
- - + + - \ No newline at end of file + diff --git a/notebooks/monty_hall.ipynb b/notebooks/monty_hall.ipynb index 4137d2f..ea92976 100644 --- a/notebooks/monty_hall.ipynb +++ b/notebooks/monty_hall.ipynb @@ -1,145 +1,116 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "id": "bce64a65-ea2a-42b6-adac-0533b7541ca0", - "metadata": {}, - "outputs": [], - "source": [ - "import stormvogel.model\n", - "\n", - "mdp = stormvogel.model.new_mdp(\"Monty Hall\")\n", - "\n", - "init = mdp.get_initial_state()\n", - "\n", - "# first choose car position\n", - "init.set_transitions(\n", - " [(1 / 3, mdp.new_state(\"carchosen\", {\"car_pos\": i})) for i in range(3)]\n", - ")\n", - "\n", - "# we choose a door in each case\n", - "for s in mdp.get_states_with(\"carchosen\"):\n", - " s.set_transitions(\n", - " [\n", - " (\n", - " mdp.action(f\"open{i}\"),\n", - " mdp.new_state(\"open\", s.features | {\"chosen_pos\": i}),\n", - " )\n", - " for i in range(3)\n", - " ]\n", - " )\n", - "\n", - "# the other goat is revealed\n", - "for s in mdp.get_states_with(\"open\"):\n", - " car_pos = s.features[\"car_pos\"]\n", - " chosen_pos = s.features[\"chosen_pos\"]\n", - " other_pos = {0, 1, 2} - {car_pos, chosen_pos}\n", - " s.set_transitions(\n", - " [\n", - " (\n", - " 1 / len(other_pos),\n", - " mdp.new_state(\"goatrevealed\", s.features | {\"reveal_pos\": i}),\n", - " )\n", - " for i in other_pos\n", - " ]\n", - " )\n", - "\n", - "# we must choose whether we want to switch\n", - "for s in mdp.get_states_with(\"goatrevealed\"):\n", - " car_pos = s.features[\"car_pos\"]\n", - " chosen_pos = s.features[\"chosen_pos\"]\n", - " reveal_pos = s.features[\"reveal_pos\"]\n", - " other_pos = list({0, 1, 2} - {reveal_pos, chosen_pos})[0]\n", - " s.set_transitions(\n", - " [\n", - " (\n", - " mdp.action(\"stay\"),\n", - " mdp.new_state(\n", - " [\"done\"] + ([\"target\"] if chosen_pos == car_pos else []),\n", - " s.features | {\"chosen_pos\": chosen_pos},\n", - " ),\n", - " ),\n", - " (\n", - " mdp.action(\"switch\"),\n", - " mdp.new_state(\n", - " [\"done\"] + ([\"target\"] if other_pos == car_pos else []),\n", - " s.features | {\"chosen_pos\": other_pos},\n", - " ),\n", - " ),\n", - " ]\n", - " )\n" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "02b68164-00de-41b1-ba2b-65e12bef9032", - "metadata": {}, - "outputs": [ + "cells": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "monty.html\n" - ] + "cell_type": "code", + "execution_count": null, + "id": "bce64a65-ea2a-42b6-adac-0533b7541ca0", + "metadata": {}, + "outputs": [], + "source": [ + "import stormvogel.model\n", + "\n", + "mdp = stormvogel.model.new_mdp(\"Monty Hall\")\n", + "\n", + "init = mdp.get_initial_state()\n", + "\n", + "# first choose car position\n", + "init.set_transitions(\n", + " [(1 / 3, mdp.new_state(\"carchosen\", {\"car_pos\": i})) for i in range(3)]\n", + ")\n", + "\n", + "# we choose a door in each case\n", + "for s in mdp.get_states_with(\"carchosen\"):\n", + " s.set_transitions(\n", + " [\n", + " (\n", + " mdp.action(f\"open{i}\"),\n", + " mdp.new_state(\"open\", s.features | {\"chosen_pos\": i}),\n", + " )\n", + " for i in range(3)\n", + " ]\n", + " )\n", + "\n", + "# the other goat is revealed\n", + "for s in mdp.get_states_with(\"open\"):\n", + " car_pos = s.features[\"car_pos\"]\n", + " chosen_pos = s.features[\"chosen_pos\"]\n", + " other_pos = {0, 1, 2} - {car_pos, chosen_pos}\n", + " s.set_transitions(\n", + " [\n", + " (\n", + " 1 / len(other_pos),\n", + " mdp.new_state(\"goatrevealed\", s.features | {\"reveal_pos\": i}),\n", + " )\n", + " for i in other_pos\n", + " ]\n", + " )\n", + "\n", + "# we must choose whether we want to switch\n", + "for s in mdp.get_states_with(\"goatrevealed\"):\n", + " car_pos = s.features[\"car_pos\"]\n", + " chosen_pos = s.features[\"chosen_pos\"]\n", + " reveal_pos = s.features[\"reveal_pos\"]\n", + " other_pos = list({0, 1, 2} - {reveal_pos, chosen_pos})[0]\n", + " s.set_transitions(\n", + " [\n", + " (\n", + " mdp.action(\"stay\"),\n", + " mdp.new_state(\n", + " [\"done\"] + ([\"target\"] if chosen_pos == car_pos else []),\n", + " s.features | {\"chosen_pos\": chosen_pos},\n", + " ),\n", + " ),\n", + " (\n", + " mdp.action(\"switch\"),\n", + " mdp.new_state(\n", + " [\"done\"] + ([\"target\"] if other_pos == car_pos else []),\n", + " s.features | {\"chosen_pos\": other_pos},\n", + " ),\n", + " ),\n", + " ]\n", + " )\n" + ] }, { - "data": { - "text/html": [ - "\n", - " \n", - " " - ], - "text/plain": [ - "" + "cell_type": "code", + "execution_count": null, + "id": "02b68164-00de-41b1-ba2b-65e12bef9032", + "metadata": {}, + "outputs": [], + "source": [ + "from stormvogel.visualization import show\n", + "\n", + "show(mdp, \"monty\")" ] - }, - "metadata": {}, - "output_type": "display_data" + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3ec68bb5-2728-458e-8d11-6015f80d79f7", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "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.11.2" } - ], - "source": [ - "from stormvogel.visualization import show\n", - "\n", - "show(mdp, \"monty\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3ec68bb5-2728-458e-8d11-6015f80d79f7", - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "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.11.2" - } - }, - "nbformat": 4, - "nbformat_minor": 5 + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/stormvogel/visualization.py b/stormvogel/visualization.py index 180986f..8b8b14c 100644 --- a/stormvogel/visualization.py +++ b/stormvogel/visualization.py @@ -10,10 +10,12 @@ class Visualization: """Handles visualization of a Model using a pyvis Network.""" + ACTION_ID_OFFSET = 20**6 + def __init__( self, model: Model, - name: str, + name: str = "model", notebook: bool = True, cdn_resources: str = "remote", ) -> None: @@ -21,7 +23,7 @@ def __init__( Args: model (Model): The stormvogel model to be displayed. - name (str): The name of the resulting html file. + name (str): The name of the resulting html file. May or may not include .html extension. notebook (bool, optional): Leave to true if you are using in a notebook. Defaults to True. """ self.model = model @@ -43,9 +45,6 @@ def __set_layout(self): "background": "white", "border": "black" } - }, - "edge": { - "color": "blue" } }""") @@ -60,6 +59,7 @@ def __add_nodes(self): label=",".join(state.labels), color=None, # type: ignore borderWidth=borderWidth, + shape="circle", ) def __formatted_prob(self, prob: Number) -> str: @@ -67,6 +67,7 @@ def __formatted_prob(self, prob: Number) -> str: return str(Fraction(prob).limit_denominator(20)) def __add_transitions(self): + no_actions = 0 """For each transition in the model, add a transition in the graph.""" for state_id, transition in self.model.transitions.items(): for action, branch in transition.transition.items(): @@ -80,9 +81,16 @@ def __add_transitions(self): label=self.__formatted_prob(prob), ) else: - raise NotImplementedError( - "Non-empty actions are not supported yet." + self.g.add_node( + n_id=self.ACTION_ID_OFFSET + no_actions, + label=action.name, + shape="box", ) + print(action.name) + no_actions += 1 + # raise NotImplementedError( + # "Non-empty actions are not supported yet." + # ) def show(self): """Show the constructed model""" From 9957257b00f848e8c9710d889438892dc44b2e0a Mon Sep 17 00:00:00 2001 From: YouGuessedMyName Date: Mon, 1 Jul 2024 13:18:16 +0200 Subject: [PATCH 4/6] Improved action visualization --- notebooks/monty.html | 6 ++-- notebooks/monty_hall.ipynb | 37 ++++++++++++++++++--- stormvogel/model.py | 12 +++---- stormvogel/visualization.py | 65 +++++++++++++++++++++++++------------ 4 files changed, 86 insertions(+), 34 deletions(-) diff --git a/notebooks/monty.html b/notebooks/monty.html index 55ce12e..e502921 100644 --- a/notebooks/monty.html +++ b/notebooks/monty.html @@ -282,8 +282,8 @@

// parsing and collecting nodes and edges from the python - nodes = new vis.DataSet([{"borderWidth": 3, "color": null, "id": 0, "label": "init", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 1, "label": "carchosen", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 2, "label": "carchosen", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 3, "label": "carchosen", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 4, "label": "open", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 5, "label": "open", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 6, "label": "open", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 7, "label": "open", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 8, "label": "open", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 9, "label": "open", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 10, "label": "open", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 11, "label": "open", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 12, "label": "open", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 13, "label": "goatrevealed", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 14, "label": "goatrevealed", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 15, "label": "goatrevealed", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 16, "label": "goatrevealed", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 17, "label": "goatrevealed", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 18, "label": "goatrevealed", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 19, "label": "goatrevealed", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 20, "label": "goatrevealed", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 21, "label": "goatrevealed", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 22, "label": "goatrevealed", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 23, "label": "goatrevealed", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 24, "label": "goatrevealed", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 25, "label": "done,target", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 26, "label": "done", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 27, "label": "done,target", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 28, "label": "done", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 29, "label": "done", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 30, "label": "done,target", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 31, "label": "done", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 32, "label": "done,target", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 33, "label": "done", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 34, "label": "done,target", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 35, "label": "done,target", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 36, "label": "done", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 37, "label": "done,target", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 38, "label": "done", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 39, "label": "done", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 40, "label": "done,target", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 41, "label": "done", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 42, "label": "done,target", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 43, "label": "done", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 44, "label": "done,target", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 45, "label": "done,target", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 46, "label": "done", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 47, "label": "done,target", "shape": "circle"}, {"borderWidth": 1, "color": null, "id": 48, "label": "done", "shape": "circle"}, {"color": "#97c2fc", "id": 64000000, "label": "open0", "shape": "circle"}, {"color": "#97c2fc", "id": 64000001, "label": "open1", "shape": "circle"}, {"color": "#97c2fc", "id": 64000002, "label": "open2", "shape": "circle"}, {"color": "#97c2fc", "id": 64000003, "label": "open0", "shape": "circle"}, {"color": "#97c2fc", "id": 64000004, "label": "open1", "shape": "circle"}, {"color": "#97c2fc", "id": 64000005, "label": "open2", "shape": "circle"}, {"color": "#97c2fc", "id": 64000006, "label": "open0", "shape": "circle"}, {"color": "#97c2fc", "id": 64000007, "label": "open1", "shape": "circle"}, {"color": "#97c2fc", "id": 64000008, "label": "open2", "shape": "circle"}, {"color": "#97c2fc", "id": 64000009, "label": "stay", "shape": "circle"}, {"color": "#97c2fc", "id": 64000010, "label": "switch", "shape": "circle"}, {"color": "#97c2fc", "id": 64000011, "label": "stay", "shape": "circle"}, {"color": "#97c2fc", "id": 64000012, "label": "switch", "shape": "circle"}, {"color": "#97c2fc", "id": 64000013, "label": "stay", "shape": "circle"}, {"color": "#97c2fc", "id": 64000014, "label": "switch", "shape": "circle"}, {"color": "#97c2fc", "id": 64000015, "label": "stay", "shape": "circle"}, {"color": "#97c2fc", "id": 64000016, "label": "switch", "shape": "circle"}, {"color": "#97c2fc", "id": 64000017, "label": "stay", "shape": "circle"}, {"color": "#97c2fc", "id": 64000018, "label": "switch", "shape": "circle"}, {"color": "#97c2fc", "id": 64000019, "label": "stay", "shape": "circle"}, {"color": "#97c2fc", "id": 64000020, "label": "switch", "shape": "circle"}, {"color": "#97c2fc", "id": 64000021, "label": "stay", "shape": "circle"}, {"color": "#97c2fc", "id": 64000022, "label": "switch", "shape": "circle"}, {"color": "#97c2fc", "id": 64000023, "label": "stay", "shape": "circle"}, {"color": "#97c2fc", "id": 64000024, "label": "switch", "shape": "circle"}, {"color": "#97c2fc", "id": 64000025, "label": "stay", "shape": "circle"}, {"color": "#97c2fc", "id": 64000026, "label": "switch", "shape": "circle"}, {"color": "#97c2fc", "id": 64000027, "label": "stay", "shape": "circle"}, {"color": "#97c2fc", "id": 64000028, "label": "switch", "shape": "circle"}, {"color": "#97c2fc", "id": 64000029, "label": "stay", "shape": "circle"}, {"color": "#97c2fc", "id": 64000030, "label": "switch", "shape": "circle"}, {"color": "#97c2fc", "id": 64000031, "label": "stay", "shape": "circle"}, {"color": "#97c2fc", "id": 64000032, "label": "switch", "shape": "circle"}]); - edges = new vis.DataSet([{"arrows": "to", "color": "red", "from": 0, "label": "1/3", "to": 1}, {"arrows": "to", "color": "red", "from": 0, "label": "1/3", "to": 2}, {"arrows": "to", "color": "red", "from": 0, "label": "1/3", "to": 3}, {"arrows": "to", "color": "red", "from": 4, "label": "1/2", "to": 13}, {"arrows": "to", "color": "red", "from": 4, "label": "1/2", "to": 14}, {"arrows": "to", "color": "red", "from": 5, "label": "1", "to": 15}, {"arrows": "to", "color": "red", "from": 6, "label": "1", "to": 16}, {"arrows": "to", "color": "red", "from": 7, "label": "1", "to": 17}, {"arrows": "to", "color": "red", "from": 8, "label": "1/2", "to": 18}, {"arrows": "to", "color": "red", "from": 8, "label": "1/2", "to": 19}, {"arrows": "to", "color": "red", "from": 9, "label": "1", "to": 20}, {"arrows": "to", "color": "red", "from": 10, "label": "1", "to": 21}, {"arrows": "to", "color": "red", "from": 11, "label": "1", "to": 22}, {"arrows": "to", "color": "red", "from": 12, "label": "1/2", "to": 23}, {"arrows": "to", "color": "red", "from": 12, "label": "1/2", "to": 24}, {"arrows": "to", "color": "red", "from": 25, "label": "1", "to": 25}, {"arrows": "to", "color": "red", "from": 26, "label": "1", "to": 26}, {"arrows": "to", "color": "red", "from": 27, "label": "1", "to": 27}, {"arrows": "to", "color": "red", "from": 28, "label": "1", "to": 28}, {"arrows": "to", "color": "red", "from": 29, "label": "1", "to": 29}, {"arrows": "to", "color": "red", "from": 30, "label": "1", "to": 30}, {"arrows": "to", "color": "red", "from": 31, "label": "1", "to": 31}, {"arrows": "to", "color": "red", "from": 32, "label": "1", "to": 32}, {"arrows": "to", "color": "red", "from": 33, "label": "1", "to": 33}, {"arrows": "to", "color": "red", "from": 34, "label": "1", "to": 34}, {"arrows": "to", "color": "red", "from": 35, "label": "1", "to": 35}, {"arrows": "to", "color": "red", "from": 36, "label": "1", "to": 36}, {"arrows": "to", "color": "red", "from": 37, "label": "1", "to": 37}, {"arrows": "to", "color": "red", "from": 38, "label": "1", "to": 38}, {"arrows": "to", "color": "red", "from": 39, "label": "1", "to": 39}, {"arrows": "to", "color": "red", "from": 40, "label": "1", "to": 40}, {"arrows": "to", "color": "red", "from": 41, "label": "1", "to": 41}, {"arrows": "to", "color": "red", "from": 42, "label": "1", "to": 42}, {"arrows": "to", "color": "red", "from": 43, "label": "1", "to": 43}, {"arrows": "to", "color": "red", "from": 44, "label": "1", "to": 44}, {"arrows": "to", "color": "red", "from": 45, "label": "1", "to": 45}, {"arrows": "to", "color": "red", "from": 46, "label": "1", "to": 46}, {"arrows": "to", "color": "red", "from": 47, "label": "1", "to": 47}, {"arrows": "to", "color": "red", "from": 48, "label": "1", "to": 48}]); + nodes = new vis.DataSet([{"borderWidth": 3, "color": null, "id": 0, "label": "init", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 1, "label": "carchosen", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 2, "label": "carchosen", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 3, "label": "carchosen", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 4, "label": "open", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 5, "label": "open", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 6, "label": "open", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 7, "label": "open", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 8, "label": "open", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 9, "label": "open", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 10, "label": "open", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 11, "label": "open", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 12, "label": "open", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 13, "label": "goatrevealed", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 14, "label": "goatrevealed", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 15, "label": "goatrevealed", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 16, "label": "goatrevealed", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 17, "label": "goatrevealed", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 18, "label": "goatrevealed", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 19, "label": "goatrevealed", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 20, "label": "goatrevealed", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 21, "label": "goatrevealed", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 22, "label": "goatrevealed", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 23, "label": "goatrevealed", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 24, "label": "goatrevealed", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 25, "label": "done,target", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 26, "label": "done", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 27, "label": "done,target", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 28, "label": "done", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 29, "label": "done", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 30, "label": "done,target", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 31, "label": "done", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 32, "label": "done,target", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 33, "label": "done", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 34, "label": "done,target", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 35, "label": "done,target", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 36, "label": "done", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 37, "label": "done,target", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 38, "label": "done", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 39, "label": "done", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 40, "label": "done,target", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 41, "label": "done", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 42, "label": "done,target", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 43, "label": "done", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 44, "label": "done,target", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 45, "label": "done,target", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 46, "label": "done", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 47, "label": "done,target", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 48, "label": "done", "shape": "dot"}, {"color": null, "id": 100000000, "label": "open0", "shape": "box"}, {"color": null, "id": 100000001, "label": "open1", "shape": "box"}, {"color": null, "id": 100000002, "label": "open2", "shape": "box"}, {"color": null, "id": 100000003, "label": "open0", "shape": "box"}, {"color": null, "id": 100000004, "label": "open1", "shape": "box"}, {"color": null, "id": 100000005, "label": "open2", "shape": "box"}, {"color": null, "id": 100000006, "label": "open0", "shape": "box"}, {"color": null, "id": 100000007, "label": "open1", "shape": "box"}, {"color": null, "id": 100000008, "label": "open2", "shape": "box"}, {"color": null, "id": 100000009, "label": "stay", "shape": "box"}, {"color": null, "id": 100000010, "label": "switch", "shape": "box"}, {"color": null, "id": 100000011, "label": "stay", "shape": "box"}, {"color": null, "id": 100000012, "label": "switch", "shape": "box"}, {"color": null, "id": 100000013, "label": "stay", "shape": "box"}, {"color": null, "id": 100000014, "label": "switch", "shape": "box"}, {"color": null, "id": 100000015, "label": "stay", "shape": "box"}, {"color": null, "id": 100000016, "label": "switch", "shape": "box"}, {"color": null, "id": 100000017, "label": "stay", "shape": "box"}, {"color": null, "id": 100000018, "label": "switch", "shape": "box"}, {"color": null, "id": 100000019, "label": "stay", "shape": "box"}, {"color": null, "id": 100000020, "label": "switch", "shape": "box"}, {"color": null, "id": 100000021, "label": "stay", "shape": "box"}, {"color": null, "id": 100000022, "label": "switch", "shape": "box"}, {"color": null, "id": 100000023, "label": "stay", "shape": "box"}, {"color": null, "id": 100000024, "label": "switch", "shape": "box"}, {"color": null, "id": 100000025, "label": "stay", "shape": "box"}, {"color": null, "id": 100000026, "label": "switch", "shape": "box"}, {"color": null, "id": 100000027, "label": "stay", "shape": "box"}, {"color": null, "id": 100000028, "label": "switch", "shape": "box"}, {"color": null, "id": 100000029, "label": "stay", "shape": "box"}, {"color": null, "id": 100000030, "label": "switch", "shape": "box"}, {"color": null, "id": 100000031, "label": "stay", "shape": "box"}, {"color": null, "id": 100000032, "label": "switch", "shape": "box"}]); + edges = new vis.DataSet([{"arrows": "to", "color": "red", "from": 0, "label": "1/3", "to": 1}, {"arrows": "to", "color": "red", "from": 0, "label": "1/3", "to": 2}, {"arrows": "to", "color": "red", "from": 0, "label": "1/3", "to": 3}, {"arrows": "to", "color": "red", "from": 1, "to": 100000000}, {"arrows": "to", "color": "red", "from": 100000000, "label": "1", "to": 4}, {"arrows": "to", "color": "red", "from": 1, "to": 100000001}, {"arrows": "to", "color": "red", "from": 100000001, "label": "1", "to": 5}, {"arrows": "to", "color": "red", "from": 1, "to": 100000002}, {"arrows": "to", "color": "red", "from": 100000002, "label": "1", "to": 6}, {"arrows": "to", "color": "red", "from": 2, "to": 100000003}, {"arrows": "to", "color": "red", "from": 100000003, "label": "1", "to": 7}, {"arrows": "to", "color": "red", "from": 2, "to": 100000004}, {"arrows": "to", "color": "red", "from": 100000004, "label": "1", "to": 8}, {"arrows": "to", "color": "red", "from": 2, "to": 100000005}, {"arrows": "to", "color": "red", "from": 100000005, "label": "1", "to": 9}, {"arrows": "to", "color": "red", "from": 3, "to": 100000006}, {"arrows": "to", "color": "red", "from": 100000006, "label": "1", "to": 10}, {"arrows": "to", "color": "red", "from": 3, "to": 100000007}, {"arrows": "to", "color": "red", "from": 100000007, "label": "1", "to": 11}, {"arrows": "to", "color": "red", "from": 3, "to": 100000008}, {"arrows": "to", "color": "red", "from": 100000008, "label": "1", "to": 12}, {"arrows": "to", "color": "red", "from": 4, "label": "1/2", "to": 13}, {"arrows": "to", "color": "red", "from": 4, "label": "1/2", "to": 14}, {"arrows": "to", "color": "red", "from": 5, "label": "1", "to": 15}, {"arrows": "to", "color": "red", "from": 6, "label": "1", "to": 16}, {"arrows": "to", "color": "red", "from": 7, "label": "1", "to": 17}, {"arrows": "to", "color": "red", "from": 8, "label": "1/2", "to": 18}, {"arrows": "to", "color": "red", "from": 8, "label": "1/2", "to": 19}, {"arrows": "to", "color": "red", "from": 9, "label": "1", "to": 20}, {"arrows": "to", "color": "red", "from": 10, "label": "1", "to": 21}, {"arrows": "to", "color": "red", "from": 11, "label": "1", "to": 22}, {"arrows": "to", "color": "red", "from": 12, "label": "1/2", "to": 23}, {"arrows": "to", "color": "red", "from": 12, "label": "1/2", "to": 24}, {"arrows": "to", "color": "red", "from": 13, "to": 100000009}, {"arrows": "to", "color": "red", "from": 100000009, "label": "1", "to": 25}, {"arrows": "to", "color": "red", "from": 13, "to": 100000010}, {"arrows": "to", "color": "red", "from": 100000010, "label": "1", "to": 26}, {"arrows": "to", "color": "red", "from": 14, "to": 100000011}, {"arrows": "to", "color": "red", "from": 100000011, "label": "1", "to": 27}, {"arrows": "to", "color": "red", "from": 14, "to": 100000012}, {"arrows": "to", "color": "red", "from": 100000012, "label": "1", "to": 28}, {"arrows": "to", "color": "red", "from": 15, "to": 100000013}, {"arrows": "to", "color": "red", "from": 100000013, "label": "1", "to": 29}, {"arrows": "to", "color": "red", "from": 15, "to": 100000014}, {"arrows": "to", "color": "red", "from": 100000014, "label": "1", "to": 30}, {"arrows": "to", "color": "red", "from": 16, "to": 100000015}, {"arrows": "to", "color": "red", "from": 100000015, "label": "1", "to": 31}, {"arrows": "to", "color": "red", "from": 16, "to": 100000016}, {"arrows": "to", "color": "red", "from": 100000016, "label": "1", "to": 32}, {"arrows": "to", "color": "red", "from": 17, "to": 100000017}, {"arrows": "to", "color": "red", "from": 100000017, "label": "1", "to": 33}, {"arrows": "to", "color": "red", "from": 17, "to": 100000018}, {"arrows": "to", "color": "red", "from": 100000018, "label": "1", "to": 34}, {"arrows": "to", "color": "red", "from": 18, "to": 100000019}, {"arrows": "to", "color": "red", "from": 100000019, "label": "1", "to": 35}, {"arrows": "to", "color": "red", "from": 18, "to": 100000020}, {"arrows": "to", "color": "red", "from": 100000020, "label": "1", "to": 36}, {"arrows": "to", "color": "red", "from": 19, "to": 100000021}, {"arrows": "to", "color": "red", "from": 100000021, "label": "1", "to": 37}, {"arrows": "to", "color": "red", "from": 19, "to": 100000022}, {"arrows": "to", "color": "red", "from": 100000022, "label": "1", "to": 38}, {"arrows": "to", "color": "red", "from": 20, "to": 100000023}, {"arrows": "to", "color": "red", "from": 100000023, "label": "1", "to": 39}, {"arrows": "to", "color": "red", "from": 20, "to": 100000024}, {"arrows": "to", "color": "red", "from": 100000024, "label": "1", "to": 40}, {"arrows": "to", "color": "red", "from": 21, "to": 100000025}, {"arrows": "to", "color": "red", "from": 100000025, "label": "1", "to": 41}, {"arrows": "to", "color": "red", "from": 21, "to": 100000026}, {"arrows": "to", "color": "red", "from": 100000026, "label": "1", "to": 42}, {"arrows": "to", "color": "red", "from": 22, "to": 100000027}, {"arrows": "to", "color": "red", "from": 100000027, "label": "1", "to": 43}, {"arrows": "to", "color": "red", "from": 22, "to": 100000028}, {"arrows": "to", "color": "red", "from": 100000028, "label": "1", "to": 44}, {"arrows": "to", "color": "red", "from": 23, "to": 100000029}, {"arrows": "to", "color": "red", "from": 100000029, "label": "1", "to": 45}, {"arrows": "to", "color": "red", "from": 23, "to": 100000030}, {"arrows": "to", "color": "red", "from": 100000030, "label": "1", "to": 46}, {"arrows": "to", "color": "red", "from": 24, "to": 100000031}, {"arrows": "to", "color": "red", "from": 100000031, "label": "1", "to": 47}, {"arrows": "to", "color": "red", "from": 24, "to": 100000032}, {"arrows": "to", "color": "red", "from": 100000032, "label": "1", "to": 48}, {"arrows": "to", "color": "red", "from": 25, "label": "1", "to": 25}, {"arrows": "to", "color": "red", "from": 26, "label": "1", "to": 26}, {"arrows": "to", "color": "red", "from": 27, "label": "1", "to": 27}, {"arrows": "to", "color": "red", "from": 28, "label": "1", "to": 28}, {"arrows": "to", "color": "red", "from": 29, "label": "1", "to": 29}, {"arrows": "to", "color": "red", "from": 30, "label": "1", "to": 30}, {"arrows": "to", "color": "red", "from": 31, "label": "1", "to": 31}, {"arrows": "to", "color": "red", "from": 32, "label": "1", "to": 32}, {"arrows": "to", "color": "red", "from": 33, "label": "1", "to": 33}, {"arrows": "to", "color": "red", "from": 34, "label": "1", "to": 34}, {"arrows": "to", "color": "red", "from": 35, "label": "1", "to": 35}, {"arrows": "to", "color": "red", "from": 36, "label": "1", "to": 36}, {"arrows": "to", "color": "red", "from": 37, "label": "1", "to": 37}, {"arrows": "to", "color": "red", "from": 38, "label": "1", "to": 38}, {"arrows": "to", "color": "red", "from": 39, "label": "1", "to": 39}, {"arrows": "to", "color": "red", "from": 40, "label": "1", "to": 40}, {"arrows": "to", "color": "red", "from": 41, "label": "1", "to": 41}, {"arrows": "to", "color": "red", "from": 42, "label": "1", "to": 42}, {"arrows": "to", "color": "red", "from": 43, "label": "1", "to": 43}, {"arrows": "to", "color": "red", "from": 44, "label": "1", "to": 44}, {"arrows": "to", "color": "red", "from": 45, "label": "1", "to": 45}, {"arrows": "to", "color": "red", "from": 46, "label": "1", "to": 46}, {"arrows": "to", "color": "red", "from": 47, "label": "1", "to": 47}, {"arrows": "to", "color": "red", "from": 48, "label": "1", "to": 48}]); nodeColors = {}; allNodes = nodes.get({ returnType: "Object" }); @@ -294,7 +294,7 @@

// adding nodes and edges to the graph data = {nodes: nodes, edges: edges}; - var options = {"nodes": {"color": {"background": "white", "border": "black"}}}; + var options = {"nodes": {"color": {"background": "white", "border": "black"}}, "physics": {"barnesHut": {"gravitationalConstant": -22660, "centralGravity": 4.5, "springLength": 50, "springConstant": 0.08, "damping": 0.32, "avoidOverlap": 1}, "minVelocity": 0.75}}; diff --git a/notebooks/monty_hall.ipynb b/notebooks/monty_hall.ipynb index ea92976..e53ad94 100644 --- a/notebooks/monty_hall.ipynb +++ b/notebooks/monty_hall.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "id": "bce64a65-ea2a-42b6-adac-0533b7541ca0", "metadata": {}, "outputs": [], @@ -68,15 +68,44 @@ " ),\n", " ),\n", " ]\n", - " )\n" + " )" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "id": "02b68164-00de-41b1-ba2b-65e12bef9032", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "monty.html\n" + ] + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "from stormvogel.visualization import show\n", "\n", diff --git a/stormvogel/model.py b/stormvogel/model.py index 518dc11..34f8f71 100644 --- a/stormvogel/model.py +++ b/stormvogel/model.py @@ -161,13 +161,13 @@ def __init__(self, name: str | None, model_type: ModelType): self.states = {} # Initialize actions if those are supported by the model type - if self.__supports_actions(): + if self.supports_actions(): self.actions = {} # Add the initial state self.new_state(["init"]) - def __supports_actions(self): + def supports_actions(self): """Returns whether this model supports actions.""" return self.type in (ModelType.MDP, ModelType.MA) @@ -187,7 +187,7 @@ def set_transitions(self, s: State, transitions: Transition | TransitionShorthan def add_transitions(self, s: State, transitions: Transition | TransitionShorthand): """Add new transitions from a state.""" - if not self.__supports_actions(): + if not self.supports_actions(): raise RuntimeError( "In a model that does not support actions, you have to set transitions, not add them" ) @@ -198,7 +198,7 @@ def add_transitions(self, s: State, transitions: Transition | TransitionShorthan def new_action(self, name: str) -> Action: """Creates a new action and returns it.""" - if not self.__supports_actions(): + if not self.supports_actions(): raise RuntimeError( "Called new_action on a model that does not support actions" ) @@ -213,7 +213,7 @@ def new_action(self, name: str) -> Action: def get_action(self, name: str) -> Action: """Gets an existing action.""" - if not self.__supports_actions(): + if not self.supports_actions(): raise RuntimeError( "Called get_action on a model that does not support actions" ) @@ -226,7 +226,7 @@ def get_action(self, name: str) -> Action: def action(self, name: str) -> Action: """New action or get action if it exists.""" - if not self.__supports_actions(): + if not self.supports_actions(): raise RuntimeError( "Called get_action on a model that does not support actions" ) diff --git a/stormvogel/visualization.py b/stormvogel/visualization.py index 8b8b14c..5d52510 100644 --- a/stormvogel/visualization.py +++ b/stormvogel/visualization.py @@ -1,4 +1,4 @@ -"""Contains stuff for visualization""" +"""Contains the code responsible for model visualization.""" from pyvis.network import Network from stormvogel.model import Model, EmptyAction, Number @@ -10,7 +10,9 @@ class Visualization: """Handles visualization of a Model using a pyvis Network.""" - ACTION_ID_OFFSET = 20**6 + ACTION_ID_OFFSET = 10**8 + # In the visualization, both actions and states are nodes with an id. + # This offset is used to keep their ids from colliding. It should be some high constant. def __init__( self, @@ -23,7 +25,7 @@ def __init__( Args: model (Model): The stormvogel model to be displayed. - name (str): The name of the resulting html file. May or may not include .html extension. + name (str, optional): The name of the resulting html file. May or may not include .html extension. notebook (bool, optional): Leave to true if you are using in a notebook. Defaults to True. """ self.model = model @@ -33,7 +35,7 @@ def __init__( name += ".html" self.name = name self.g = Network(notebook=notebook, directed=True, cdn_resources=cdn_resources) - self.__add_nodes() + self.__add_states() self.__add_transitions() self.__set_layout() @@ -45,10 +47,21 @@ def __set_layout(self): "background": "white", "border": "black" } + }, + "physics": { + "barnesHut": { + "gravitationalConstant": -22660, + "centralGravity": 4.5, + "springLength": 50, + "springConstant": 0.08, + "damping": 0.32, + "avoidOverlap": 1 + }, + "minVelocity": 0.75 } }""") - def __add_nodes(self): + def __add_states(self): """For each state in the model, add a node to the graph.""" for state in self.model.states.values(): borderWidth = 1 @@ -59,16 +72,18 @@ def __add_nodes(self): label=",".join(state.labels), color=None, # type: ignore borderWidth=borderWidth, - shape="circle", + shape="dot", ) - def __formatted_prob(self, prob: Number) -> str: - """Take a probability value and format it nicely""" + def __formatted_probability(self, prob: Number) -> str: + """Take a probability value and format it nicely using a fraction.""" return str(Fraction(prob).limit_denominator(20)) def __add_transitions(self): - no_actions = 0 - """For each transition in the model, add a transition in the graph.""" + """For each transition in the model, add a transition in the graph. + Also handles actions by calling __add_action""" + action_id = self.ACTION_ID_OFFSET + # In the visualization, both actions and states are nodes, so we need to keep track of how many actions we already have. for state_id, transition in self.model.transitions.items(): for action, branch in transition.transition.items(): if action == EmptyAction: @@ -78,31 +93,39 @@ def __add_transitions(self): state_id, target.id, color="red", - label=self.__formatted_prob(prob), + label=self.__formatted_probability(prob), ) else: + # Add the action's node self.g.add_node( - n_id=self.ACTION_ID_OFFSET + no_actions, + n_id=action_id, + color=None, # type: ignore label=action.name, shape="box", ) - print(action.name) - no_actions += 1 - # raise NotImplementedError( - # "Non-empty actions are not supported yet." - # ) + # Add transition from this state TO the action. + self.g.add_edge(state_id, action_id, color="red") # type: ignore + # Add transition FROM the action to the values in its branch. + for prob, target in branch.branch: + self.g.add_edge( + action_id, + target.id, + color="red", + label=self.__formatted_probability(prob), + ) + action_id += 1 def show(self): - """Show the constructed model""" + """Show the constructed graph.""" display(self.g.show(name=self.name)) -def show(model: Model, name: str, notebook: bool = True): - """Create visualization of a Model using a pyvis Network +def show(model: Model, name: str = "model", notebook: bool = True): + """Create and show a visualization of a Model using a pyvis Network Args: model (Model): The stormvogel model to be displayed. - name (str): The name of the resulting html file. + name (str, optional): The name of the resulting html file. notebook (bool, optional): Leave to true if you are using in a notebook. Defaults to True. """ vis = Visualization(model, name, notebook) From be0793e6aeb2579d54ba8989171a7b082c36d0d6 Mon Sep 17 00:00:00 2001 From: YouGuessedMyName Date: Mon, 1 Jul 2024 13:50:40 +0200 Subject: [PATCH 5/6] Add study MDP example. --- notebooks/model.html | 321 ++++++++++++++++++++++++++++++++++++++++++ notebooks/study.ipynb | 101 +++++++++++++ 2 files changed, 422 insertions(+) create mode 100644 notebooks/model.html create mode 100644 notebooks/study.ipynb diff --git a/notebooks/model.html b/notebooks/model.html new file mode 100644 index 0000000..c163f89 --- /dev/null +++ b/notebooks/model.html @@ -0,0 +1,321 @@ + + + + + + + + + + + + + + + +
+

+
+ + + + + + +
+

+
+ + + + + +
+ + +
+
+ + + + + + + diff --git a/notebooks/study.ipynb b/notebooks/study.ipynb new file mode 100644 index 0000000..7f9183a --- /dev/null +++ b/notebooks/study.ipynb @@ -0,0 +1,101 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 13, + "id": "0df1511e-565d-45d0-93a8-adafbfaaaefa", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "model.html\n" + ] + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import stormvogel.model\n", + "import stormvogel.visualization\n", + "\n", + "mdp = stormvogel.model.new_mdp(\"Monty Hall\")\n", + "\n", + "init = mdp.get_initial_state()\n", + "study = mdp.action(\"study\")\n", + "not_study = mdp.action(\"don't study\")\n", + "\n", + "studied = mdp.new_state(\"studied\")\n", + "not_studied = mdp.new_state(\"didn't study\")\n", + "pass_test = mdp.new_state(\"pass test\")\n", + "fail_test = mdp.new_state(\"fail test\")\n", + "\n", + "init.set_transitions([\n", + " (study, studied),\n", + " (not_study, not_studied)\n", + "])\n", + "\n", + "studied.set_transitions([\n", + " (9/10, pass_test),\n", + " (1/10, fail_test)\n", + "])\n", + "\n", + "not_studied.set_transitions([\n", + " (4/10, pass_test),\n", + " (6/10, fail_test)\n", + "])\n", + "\n", + "stormvogel.visualization.show(mdp)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "45757061-9e76-4cfa-a374-9af02ba011ff", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "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.11.2" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From 9df743e4b28b17a7c7b8d677aebd925da9fc7539 Mon Sep 17 00:00:00 2001 From: YouGuessedMyName Date: Mon, 1 Jul 2024 13:54:12 +0200 Subject: [PATCH 6/6] Add study MDP example comments. --- notebooks/study.ipynb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/notebooks/study.ipynb b/notebooks/study.ipynb index 7f9183a..be5ee91 100644 --- a/notebooks/study.ipynb +++ b/notebooks/study.ipynb @@ -50,16 +50,19 @@ "pass_test = mdp.new_state(\"pass test\")\n", "fail_test = mdp.new_state(\"fail test\")\n", "\n", + "# From the initial state, you can choose to study, or not to study.\n", "init.set_transitions([\n", " (study, studied),\n", " (not_study, not_studied)\n", "])\n", "\n", + "# If you studied, then there is a 90% chance that you pass the test.\n", "studied.set_transitions([\n", " (9/10, pass_test),\n", " (1/10, fail_test)\n", "])\n", "\n", + "# If you did not study, then there is only a 40% chance that you pass the test.\n", "not_studied.set_transitions([\n", " (4/10, pass_test),\n", " (6/10, fail_test)\n",