From 24fdc16a7604ebf774b9d972b7473db718b3bd71 Mon Sep 17 00:00:00 2001 From: Tom Pike Date: Fri, 25 Oct 2024 07:00:26 -0400 Subject: [PATCH] Tutorial Improvements (#2415) * update_tutorial envirnment - Adds a Binder link in intro for non-google account holders - Removes Colab link for visual as Solara does not render properly - Adds py.cafe link for visualization tutorial - Adds binder link for visualization tutorial --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Jan Kwakkel --- docs/index.md | 20 +++++--- docs/tutorials/intro_tutorial.ipynb | 56 ++++++++++----------- docs/tutorials/visualization_tutorial.ipynb | 53 ++++--------------- 3 files changed, 53 insertions(+), 76 deletions(-) diff --git a/docs/index.md b/docs/index.md index b866ffbc913..edf4c44d955 100644 --- a/docs/index.md +++ b/docs/index.md @@ -44,17 +44,25 @@ To install our latest stable release (2.4.x), run: pip install -U mesa ``` -To install our latest pre-release (3.0 alpha), run: +Mesa >= 3.0 beta includes several installations options: ``` bash -pip install -U --pre mesa +pip install -U --pre mesa[rec] ``` +**mesa[rec]** (recommend install) installs - mesa, [networkx](https://networkx.org/), [matplotlib](https://matplotlib.org/stable/install/index.html) +and [solara](https://solara.dev/) -To launch an example model, clone the [repository](https://github.com/projectmesa/mesa) folder and invoke `mesa runserver` for one of the `examples/` subdirectories: +### Other installation options include: -```bash -mesa runserver examples/wolf_sheep -``` +- **mesa[network]** installs mesa and [networkx](https://networkx.org/) +- **mesa[viz]** installs, mesa, [matplotlib](https://matplotlib.org/stable/install/index.html) and [solara](https://solara.dev/) +- **mesa[dev]** installs mesa[rec], [ruff](https://docs.astral.sh/ruff/), [pytest](https://docs.pytest.org/en/stable/), [pytest-cov](https://pytest-cov.readthedocs.io/en/latest/), [sphinx](https://www.sphinx-doc.org/en/master/man/sphinx-build.html#cmdoption-sphinx-build-e), [pytest-mock](https://pytest-mock.readthedocs.io/en/latest/), [cookiecutter](https://cookiecutter.readthedocs.io/en/stable/) +- **mesa[examples]** installs mesa[rec], [pytest](https://docs.pytest.org/en/stable/), and [scipy](https://scipy.org/) +- **mesa[docs]** installs mesa[rec], [sphinx](https://www.sphinx-doc.org/en/master/man/sphinx-build.html#cmdoption-sphinx-build-e), [ipython](https://ipython.readthedocs.io/en/stable/install/kernel_install.html), [pydata_sphinx_theme](https://pydata-sphinx-theme.readthedocs.io/en/stable/), +[seaborn](https://seaborn.pydata.org/), [myst-nb](https://myst-nb.readthedocs.io/en/latest/), [myst-parser](https://myst-parser.readthedocs.io/en/latest/) + +Then mesa[all] installs all these sub installation options: +**mesa[all]** = mesa[network,viz,dev,examples,docs] For more help on using Mesa, check out the following resources: diff --git a/docs/tutorials/intro_tutorial.ipynb b/docs/tutorials/intro_tutorial.ipynb index 632246b4528..10988d6a680 100644 --- a/docs/tutorials/intro_tutorial.ipynb +++ b/docs/tutorials/intro_tutorial.ipynb @@ -82,13 +82,13 @@ "Install Mesa:\n", "\n", "```bash\n", - "pip install --upgrade mesa\n", + "pip install --upgrade mesa[rec] \n", "```\n", "\n", "If you want to use our newest features, you can also opt to install our latest pre-release version:\n", "\n", "```bash\n", - "pip install --upgrade --pre mesa\n", + "pip install --upgrade --pre mesa[rec]\n", "```\n", "\n", "Install Jupyter notebook (optional):\n", @@ -115,10 +115,10 @@ ] }, { - "cell_type": "markdown", + "cell_type": "raw", "metadata": {}, "source": [ - "pip install --quiet --upgrade --pre mesa #installs Mesa 3.0" + "pip install --quiet --upgrade --pre mesa[rec] #installs Mesa 3.0" ] }, { @@ -706,18 +706,14 @@ " self.model.grid.move_agent(self, new_position)\n", "\n", " def give_money(self):\n", - " cellmates = self.model.grid.get_cell_list_contents([self.pos])\n", - " if len(cellmates) > 1:\n", - " other_agent = self.random.choice(cellmates)\n", - " other_agent.wealth += 1\n", - " self.wealth -= 1\n", - "\n", - " def step(self):\n", - " self.move()\n", - " if self.wealth > 0:\n", - " self.give_money()\n", - "\n", + " if self.wealth > 0: \n", + " cellmates = self.model.grid.get_cell_list_contents([self.pos])\n", + " if len(cellmates) > 1:\n", + " other_agent = self.random.choice(cellmates)\n", + " other_agent.wealth += 1\n", + " self.wealth -= 1\n", "\n", + " \n", "class MoneyModel(mesa.Model):\n", " \"\"\"A model with some number of agents.\"\"\"\n", "\n", @@ -735,7 +731,8 @@ " self.grid.place_agent(a, (x, y))\n", "\n", " def step(self):\n", - " self.agents.shuffle_do(\"step\")" + " self.agents.shuffle_do(\"move\")\n", + " self.agents.shuffle_do(\"give_money\")" ] }, { @@ -858,7 +855,8 @@ " if other == self:\n", " print(\"I JUST GAVE MOnEY TO MYSELF HEHEHE!\")\n", "\n", - " def step(self):\n", + " # There are several ways in which one can combine functions to execute the model\n", + " def agent_act(self): \n", " self.move()\n", " if self.wealth > 0:\n", " self.give_money()\n", @@ -870,7 +868,12 @@ " def __init__(self, n, width, height):\n", " super().__init__()\n", " self.num_agents = n\n", + " # create the space\n", " self.grid = mesa.space.MultiGrid(width, height, True)\n", + " # collect the output\n", + " self.datacollector = mesa.DataCollector(\n", + " model_reporters={\"Gini\": compute_gini}, agent_reporters={\"Wealth\": \"wealth\"}\n", + " )\n", "\n", " # Create agents\n", " for _ in range(self.num_agents):\n", @@ -880,13 +883,10 @@ " y = self.random.randrange(self.grid.height)\n", " self.grid.place_agent(a, (x, y))\n", "\n", - " self.datacollector = mesa.DataCollector(\n", - " model_reporters={\"Gini\": compute_gini}, agent_reporters={\"Wealth\": \"wealth\"}\n", - " )\n", - "\n", + " \n", " def step(self):\n", " self.datacollector.collect(self)\n", - " self.agents.shuffle_do(\"step\")" + " self.agents.shuffle_do(\"agent_act\")" ] }, { @@ -998,7 +998,7 @@ "metadata": {}, "outputs": [], "source": [ - "# Get the wealth of agent 14 over time\n", + "# Get the wealth of agent 7 over time\n", "one_agent_wealth = agent_wealth.xs(7, level=\"AgentID\")\n", "\n", "# Plot the wealth of agent 7 over time\n", @@ -1336,7 +1336,7 @@ " def step(self):\n", " self.datacollector.collect(self)\n", " # groupby returns a dictionary of the different ethnicities with a list of agents\n", - " grouped_agents = grouped_agents = model.agents.groupby(\"ethnicity\")\n", + " grouped_agents = model.agents.groupby(\"ethnicity\")\n", "\n", " for ethnic, similars in grouped_agents: \n", " if ethnic != \"Mixed\": \n", @@ -1445,7 +1445,7 @@ "\n", " def give_money(self):\n", " cellmates = self.model.grid.get_cell_list_contents([self.pos])\n", - " if len(cellmates) > 1:\n", + " if len(cellmates) > 1 and self.wealth > 0:\n", " other = self.random.choice(cellmates)\n", " other.wealth += 1\n", " self.wealth -= 1\n", @@ -1513,7 +1513,7 @@ "results = mesa.batch_run(\n", " MoneyModel,\n", " parameters=params,\n", - " iterations=7,\n", + " iterations=5,\n", " max_steps=100,\n", " number_processes=1,\n", " data_collection_period=1,\n", @@ -1687,8 +1687,8 @@ "results_5s = mesa.batch_run(\n", " MoneyModel,\n", " parameters=params,\n", - " iterations=100,\n", - " max_steps=120,\n", + " iterations=25,\n", + " max_steps=100,\n", " number_processes=1,\n", " data_collection_period=1, # Important, otherwise the datacollector will only collect data of the last time step\n", " display_progress=True,\n", diff --git a/docs/tutorials/visualization_tutorial.ipynb b/docs/tutorials/visualization_tutorial.ipynb index 777cca33943..7460ca30a19 100644 --- a/docs/tutorials/visualization_tutorial.ipynb +++ b/docs/tutorials/visualization_tutorial.ipynb @@ -14,8 +14,8 @@ "*This version of the visualisation tutorial is updated for Mesa 3.0, and works with Mesa `3.0.0a4` and above. If you are using Mesa 2.3.x, check out the [stable version](https://mesa.readthedocs.io/stable/tutorials/visualization_tutorial.html) of this tutorial on Readthedocs.*\n", "\n", "**Important:** \n", - "- If you are just exploring Mesa and want the fastest way to the the dashboard and code checkout [![py.cafe](https://img.shields.io/badge/launch-py.cafe-blue)](https://py.cafe/app/maartenbreddels/mesa-example-wealth) (click \"Editor\" to see the code)\n", - "- If you want to see the dashboard in an interactive notebook try [[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/projectmesa/mesa/main?labpath=docs%2Ftutorials%2Fvisualization_tutorial.ipynb)\n", + "- If you are just exploring Mesa and want the fastest way to the the dashboard and code checkout [![py.cafe](https://img.shields.io/badge/launch-py.cafe-blue)](https://py.cafe/app/tpike3/boltzmann-wealth-model) (click \"Editor\" to see the code)\n", + "- If you want to see the dashboard in an interactive notebook try [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/projectmesa/mesa/main?labpath=docs%2Ftutorials%2Fvisualization_tutorial.ipynb)\n", "- If you have installed mesa and are running locally, please ensure that your [Mesa version](https://pypi.org/project/Mesa/) is up-to-date in order to run this tutorial.\n", "\n", "### Adding visualization\n", @@ -256,7 +256,10 @@ "source": [ "import mesa\n", "print(f\"Mesa version: {mesa.__version__}\")\n", + "import solara\n", + "from matplotlib.figure import Figure\n", "\n", + "from mesa.visualization.utils import update_counter\n", "from mesa.visualization import SolaraViz, make_plot_measure, make_space_matplotlib\n", "# Import the local MoneyModel.py\n", "from MoneyModel import MoneyModel\n" @@ -291,18 +294,10 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "from mesa.visualization import SolaraViz, make_plot_measure, make_space_matplotlib\n", - "\n", - "# Create initial model instance\n", - "model1 = MoneyModel(50, 10, 10)\n", - "\n", - "SpaceGraph = make_space_matplotlib(agent_portrayal)\n", - "GiniPlot = make_plot_measure(\"Gini\")" + "Next, we update our solara frontend to use this new component" ] }, { @@ -311,10 +306,6 @@ "metadata": {}, "outputs": [], "source": [ - "import solara\n", - "from matplotlib.figure import Figure\n", - "from mesa.visualization.utils import update_counter\n", - "\n", "@solara.component\n", "def Histogram(model):\n", " update_counter.get() # This is required to update the counter\n", @@ -335,33 +326,11 @@ "metadata": {}, "outputs": [], "source": [ - "def agent_portrayal(agent):\n", - " size = 10\n", - " color = \"tab:red\"\n", - " if agent.wealth > 0:\n", - " size = 50\n", - " color = \"tab:blue\"\n", - " return {\"size\": size, \"color\": color}\n", + "# Create initial model instance\n", + "model1 = MoneyModel(50, 10, 10)\n", "\n", - "model_params = {\n", - " \"n\": {\n", - " \"type\": \"SliderInt\",\n", - " \"value\": 50,\n", - " \"label\": \"Number of agents:\",\n", - " \"min\": 10,\n", - " \"max\": 100,\n", - " \"step\": 1,\n", - " },\n", - " \"width\": 10,\n", - " \"height\": 10,\n", - "}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we update our solara frontend to use this new component" + "SpaceGraph = make_space_matplotlib(agent_portrayal)\n", + "GiniPlot = make_plot_measure(\"Gini\")" ] }, {