{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "*This notebook contains material from [cbe30338-2021](https://jckantor.github.io/cbe30338-2021);\n", "content is available [on Github](https://github.com/jckantor/cbe30338-2021.git).*\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "< [7.1 Introduction to Simpy](https://jckantor.github.io/cbe30338-2021/07.01-Introduction-to-Simpy.html) | [Contents](toc.html) | [Tag Index](tag_index.html) | [7.3 Chemotaxis](https://jckantor.github.io/cbe30338-2021/07.03-Chemotaxis.html) >

\"Open

\"Download\"" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 1, "link": "[7.2 Agent Based Models](https://jckantor.github.io/cbe30338-2021/07.02-Agent-Based-Models.html#7.2-Agent-Based-Models)", "section": "7.2 Agent Based Models" } }, "source": [ "# 7.2 Agent Based Models" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "nbpages": { "level": 1, "link": "[7.2 Agent Based Models](https://jckantor.github.io/cbe30338-2021/07.02-Agent-Based-Models.html#7.2-Agent-Based-Models)", "section": "7.2 Agent Based Models" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Requirement already satisfied: simpy in /Users/jeff/opt/anaconda3/lib/python3.8/site-packages (4.0.1)\n" ] } ], "source": [ "!pip install simpy" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 2, "link": "[7.2.1 Simpy: What we have learned so far](https://jckantor.github.io/cbe30338-2021/07.02-Agent-Based-Models.html#7.2.1-Simpy:-What-we-have-learned-so-far)", "section": "7.2.1 Simpy: What we have learned so far" } }, "source": [ "## 7.2.1 Simpy: What we have learned so far\n", "\n", "* Simpy provides a simulation environment for discrete-event simulation\n", "* Python generators model \"agents\" in a larger system.\n", "\n", "What we will learn in this unit:\n", "\n", "* Modeling multiple units\n", "* Modeling a shared resource\n", "* Extracting data from a data log" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 2, "link": "[7.2.2 3.3.2 Example: A room full of Roombas](https://jckantor.github.io/cbe30338-2021/07.02-Agent-Based-Models.html#7.2.2-3.3.2-Example:-A-room-full-of-Roombas)", "section": "7.2.2 3.3.2 Example: A room full of Roombas" } }, "source": [ "## 7.2.2 3.3.2 Example: A room full of Roombas\n", "\n", "Let's imagine a large facility that is being cleaned by a collection of Roomba-type robotic cleaning units. Each unit is characterized by time required to charge, and an amount of time it can clean before needing to be recharged. The facility must be cleaned during a 16 hour overnight shift. On average, 3 units must be operating continuously to meet the cleaning requirements, i.e., 3 x 16 = 48 hours machine cleaning each night. We would like to determine how many charging stations will be required.\n", "\n", "| Unit | Charge Time (hrs) | Clean Time (hrs) |\n", "| :--: | :--: | :--: |\n", "| A | 1.0 | 2.5 |\n", "| B | 0.5 | 1.5 |\n", "| C | 0.8 | 2.0 |\n", "| D | 1.4 | 3.5 |\n", "| E | 0.5 | 1.2 |\n", "| F | 1.0 | 3.0 |" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 2, "link": "[7.2.2 3.3.2 Example: A room full of Roombas](https://jckantor.github.io/cbe30338-2021/07.02-Agent-Based-Models.html#7.2.2-3.3.2-Example:-A-room-full-of-Roombas)", "section": "7.2.2 3.3.2 Example: A room full of Roombas" } }, "source": [ "![roomba](https://upload.wikimedia.org/wikipedia/commons/2/27/%D0%A0%D0%BE%D0%B1%D0%BE%D1%82_%D0%BF%D1%8B%D0%BB%D0%B5%D1%81%D0%BE%D1%81_Roomba_780.jpg)" ] }, { "cell_type": "code", "execution_count": 35, "metadata": { "nbpages": { "level": 2, "link": "[7.2.2 3.3.2 Example: A room full of Roombas](https://jckantor.github.io/cbe30338-2021/07.02-Agent-Based-Models.html#7.2.2-3.3.2-Example:-A-room-full-of-Roombas)", "section": "7.2.2 3.3.2 Example: A room full of Roombas" } }, "outputs": [ { "data": { "text/html": [ "

\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
idcharge_timeclean_time
0A1.02.5
1B0.51.5
2C0.82.0
3D1.43.5
4E0.51.2
5F1.03.0
\n", "
" ], "text/plain": [ " id charge_time clean_time\n", "0 A 1.0 2.5\n", "1 B 0.5 1.5\n", "2 C 0.8 2.0\n", "3 D 1.4 3.5\n", "4 E 0.5 1.2\n", "5 F 1.0 3.0" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import pandas as pd\n", "\n", "roomba_data = [\n", " [\"A\", 1.0, 2.5],\n", " [\"B\", 0.5, 1.5],\n", " [\"C\", 0.8, 2.0],\n", " [\"D\", 1.4, 3.5],\n", " [\"E\", 0.5, 1.2],\n", " [\"F\", 1.0, 3.0],\n", "]\n", "\n", "roomba_df = pd.DataFrame(roomba_data, columns=[\"id\", \"charge_time\", \"clean_time\"])\n", "roomba_df" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 2, "link": "[7.2.3 One Roomba](https://jckantor.github.io/cbe30338-2021/07.02-Agent-Based-Models.html#7.2.3-One-Roomba)", "section": "7.2.3 One Roomba" } }, "source": [ "## 7.2.3 One Roomba\n", "\n", "The first challenge is to model the performance of a single Roomba. Our first attempt at a model consists of a simple Python generator. The data log consists of start and finish of each charge and cleaning cycle. For this first attempt, we'll assume a charging station is always available when needed, and we'll create just one instance of a Roomba to get started." ] }, { "cell_type": "code", "execution_count": 36, "metadata": { "nbpages": { "level": 2, "link": "[7.2.3 One Roomba](https://jckantor.github.io/cbe30338-2021/07.02-Agent-Based-Models.html#7.2.3-One-Roomba)", "section": "7.2.3 One Roomba" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[['A', 'cleaning', 0, 2.5], ['A', 'charging', 2.5, 3.5], ['A', 'cleaning', 3.5, 6.0], ['A', 'charging', 6.0, 7.0], ['A', 'cleaning', 7.0, 9.5], ['A', 'charging', 9.5, 10.5], ['A', 'cleaning', 10.5, 13.0], ['A', 'charging', 13.0, 14.0]]\n" ] } ], "source": [ "import simpy \n", "import pandas as pd\n", "\n", "# create an empty data log\n", "data_log = []\n", "\n", "# The Roomba model isa Python generator. The id, charge_time, and clean_time\n", "# parameters are the information needed to specify a particular instance of a Roomba.\n", "# The model will log the begin and end of each charge and clean cycle.\n", "\n", "def roomba(id, charge_time, clean_time):\n", " while True:\n", " # cleaning phase\n", " tic = env.now\n", " yield env.timeout(clean_time)\n", " toc = env.now\n", " data_log.append([id, \"cleaning\", tic, toc])\n", " \n", " # charging phase\n", " tic = env.now\n", " yield env.timeout(charge_time)\n", " toc = env.now\n", " data_log.append([id, \"charging\", tic, toc])\n", "\n", "# create the simulation environment\n", "env = simpy.Environment()\n", "\n", "# create the processes being simuulated\n", "env.process(roomba(\"A\", 1.0, 2.5))\n", "\n", "# run the simulation\n", "env.run(until=16)\n", "\n", "print(data_log)" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 2, "link": "[7.2.4 Processing the data log with Pandas](https://jckantor.github.io/cbe30338-2021/07.02-Agent-Based-Models.html#7.2.4-Processing-the-data-log-with-Pandas)", "section": "7.2.4 Processing the data log with Pandas" } }, "source": [ "## 7.2.4 Processing the data log with Pandas" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 3, "link": "[7.2.4.1 Convert nested list to a Pandas Dataframe](https://jckantor.github.io/cbe30338-2021/07.02-Agent-Based-Models.html#7.2.4.1-Convert-nested-list-to-a-Pandas-Dataframe)", "section": "7.2.4.1 Convert nested list to a Pandas Dataframe" } }, "source": [ "### 7.2.4.1 Convert nested list to a Pandas Dataframe" ] }, { "cell_type": "code", "execution_count": 37, "metadata": { "nbpages": { "level": 3, "link": "[7.2.4.1 Convert nested list to a Pandas Dataframe](https://jckantor.github.io/cbe30338-2021/07.02-Agent-Based-Models.html#7.2.4.1-Convert-nested-list-to-a-Pandas-Dataframe)", "section": "7.2.4.1 Convert nested list to a Pandas Dataframe" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
idactivitybeginendtime
0Acleaning0.02.52.5
1Acharging2.53.51.0
2Acleaning3.56.02.5
3Acharging6.07.01.0
4Acleaning7.09.52.5
5Acharging9.510.51.0
6Acleaning10.513.02.5
7Acharging13.014.01.0
\n", "
" ], "text/plain": [ " id activity begin end time\n", "0 A cleaning 0.0 2.5 2.5\n", "1 A charging 2.5 3.5 1.0\n", "2 A cleaning 3.5 6.0 2.5\n", "3 A charging 6.0 7.0 1.0\n", "4 A cleaning 7.0 9.5 2.5\n", "5 A charging 9.5 10.5 1.0\n", "6 A cleaning 10.5 13.0 2.5\n", "7 A charging 13.0 14.0 1.0" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "df = pd.DataFrame(data_log, columns=[\"id\", \"activity\", \"begin\", \"end\"])\n", "df[\"time\"] = df[\"end\"] - df[\"begin\"]\n", "display(df)" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 3, "link": "[7.2.4.2 Aggregating data with pivot tables](https://jckantor.github.io/cbe30338-2021/07.02-Agent-Based-Models.html#7.2.4.2-Aggregating-data-with-pivot-tables)", "section": "7.2.4.2 Aggregating data with pivot tables" } }, "source": [ "### 7.2.4.2 Aggregating data with pivot tables\n", "\n", "Among the many great reasons to use a Pandas dataframe for manipulating data are pivot tables. Pivot tables aggregate data using labels that appear in selected columns. In this case, we seek to aggregate data using labels appearing in the \"id\" and \"activity\" columns. The type of aggregation is to sum entries appearing in the \"time\"." ] }, { "cell_type": "code", "execution_count": 38, "metadata": { "nbpages": { "level": 3, "link": "[7.2.4.2 Aggregating data with pivot tables](https://jckantor.github.io/cbe30338-2021/07.02-Agent-Based-Models.html#7.2.4.2-Aggregating-data-with-pivot-tables)", "section": "7.2.4.2 Aggregating data with pivot tables" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
time
activity
charging4.0
cleaning10.0
\n", "
" ], "text/plain": [ " time\n", "activity \n", "charging 4.0\n", "cleaning 10.0" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.pivot_table(df, index=[\"activity\"], aggfunc={\"time\":sum} )" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 2, "link": "[7.2.5 Adding the full complement of Roombas](https://jckantor.github.io/cbe30338-2021/07.02-Agent-Based-Models.html#7.2.5-Adding-the-full-complement-of-Roombas)", "section": "7.2.5 Adding the full complement of Roombas" } }, "source": [ "## 7.2.5 Adding the full complement of Roombas\n", "\n", "The next step is to include all of the available Roombas to the simulation. We do this by looping over the data set that describes the available devices. For each interation, an instance of the Roomba model is created and an associated process added to the simulation environment." ] }, { "cell_type": "code", "execution_count": 39, "metadata": { "nbpages": { "level": 2, "link": "[7.2.5 Adding the full complement of Roombas](https://jckantor.github.io/cbe30338-2021/07.02-Agent-Based-Models.html#7.2.5-Adding-the-full-complement-of-Roombas)", "section": "7.2.5 Adding the full complement of Roombas" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
idactivitybeginendtime
0Ecleaning0.01.21.2
1Bcleaning0.01.51.5
2Echarging1.21.70.5
3Ccleaning0.02.02.0
4Bcharging1.52.00.5
..................
59Dcharging13.314.71.4
60Ecleaning13.614.81.2
61Fcleaning12.015.03.0
62Echarging14.815.30.5
63Bcleaning14.015.51.5
\n", "

64 rows × 5 columns

\n", "
" ], "text/plain": [ " id activity begin end time\n", "0 E cleaning 0.0 1.2 1.2\n", "1 B cleaning 0.0 1.5 1.5\n", "2 E charging 1.2 1.7 0.5\n", "3 C cleaning 0.0 2.0 2.0\n", "4 B charging 1.5 2.0 0.5\n", ".. .. ... ... ... ...\n", "59 D charging 13.3 14.7 1.4\n", "60 E cleaning 13.6 14.8 1.2\n", "61 F cleaning 12.0 15.0 3.0\n", "62 E charging 14.8 15.3 0.5\n", "63 B cleaning 14.0 15.5 1.5\n", "\n", "[64 rows x 5 columns]" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import simpy \n", "import pandas as pd\n", "\n", "# create an empty data log\n", "data_log = []\n", "\n", "# The Roomba model isa Python generator. The id, charge_time, and clean_time\n", "# parameters are the information needed to specify a particular instance of a Roomba.\n", "# The model will log the begin and end of each charge and clean cycle.\n", "\n", "def roomba(id, charge_time, clean_time):\n", " while True:\n", " # cleaning phase\n", " tic = env.now\n", " yield env.timeout(clean_time)\n", " toc = env.now\n", " data_log.append([id, \"cleaning\", tic, toc])\n", " \n", " # charging phase\n", " tic = env.now\n", " yield env.timeout(charge_time)\n", " toc = env.now\n", " data_log.append([id, \"charging\", tic, toc])\n", "\n", "# create the simulation environment\n", "env = simpy.Environment()\n", "\n", "for r in roomba_df.index:\n", " env.process(roomba(roomba_df[\"id\"][r], roomba_df[\"charge_time\"][r], roomba_df[\"clean_time\"][r]))\n", "\n", "# run the simulation\n", "env.run(until=16)\n", "\n", "df = pd.DataFrame(data_log, columns=[\"id\", \"activity\", \"begin\", \"end\"])\n", "df[\"time\"] = df[\"end\"] - df[\"begin\"]\n", "display(df)" ] }, { "cell_type": "code", "execution_count": 40, "metadata": { "nbpages": { "level": 2, "link": "[7.2.5 Adding the full complement of Roombas](https://jckantor.github.io/cbe30338-2021/07.02-Agent-Based-Models.html#7.2.5-Adding-the-full-complement-of-Roombas)", "section": "7.2.5 Adding the full complement of Roombas" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
time
activity
charging23.2
cleaning65.3
\n", "
" ], "text/plain": [ " time\n", "activity \n", "charging 23.2\n", "cleaning 65.3" ] }, "execution_count": 40, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df[\"time\"] = df[\"end\"] - df[\"begin\"]\n", "pd.pivot_table(df, index=[\"activity\"], aggfunc={\"time\":sum} )" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 2, "link": "[7.2.5 Adding the full complement of Roombas](https://jckantor.github.io/cbe30338-2021/07.02-Agent-Based-Models.html#7.2.5-Adding-the-full-complement-of-Roombas)", "section": "7.2.5 Adding the full complement of Roombas" } }, "source": [ "
\n", "\n", "**Study Question:** Change the pivot table to report total time spent charging and cleaning. The warehouse requires 48 hours of cleaning time. Is this requirement satisfied?\n", "\n", "**Study Question:** Demonstrate that the warehouse requirements can be met by one less Roomba.\n", "\n", "
" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 3, "link": "[7.2.5.1 Gantt Charts](https://jckantor.github.io/cbe30338-2021/07.02-Agent-Based-Models.html#7.2.5.1-Gantt-Charts)", "section": "7.2.5.1 Gantt Charts" } }, "source": [ "### 7.2.5.1 Gantt Charts\n", "\n", "Create a function that accepts df (the data log after converting to a pandas DataFrame) and, for every Roomba, shows a time line of events." ] }, { "cell_type": "code", "execution_count": 41, "metadata": { "nbpages": { "level": 3, "link": "[7.2.5.1 Gantt Charts](https://jckantor.github.io/cbe30338-2021/07.02-Agent-Based-Models.html#7.2.5.1-Gantt-Charts)", "section": "7.2.5.1 Gantt Charts" } }, "outputs": [ { "data": { "image/png": "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O2/dhozOFxLO8AIAAKBFd91119D77rtvSLrHnTRp0ph0j3kmBF4AAABk1MaNG1u8h29QCLwAAACQJC1evHjg6NGjS0tKSkpnzpxZ3Hzb1q1be02bNm1UWVnZ2PLy8pKNGzfmS9Ly5csLL7roojFjx44tnTp16ujdu3fnSfGzw9dee+3IyZMnlwwfPnz8t771rXOSY/Xp02eSJD333HN9J0+eXFJZWXlBcXFx2YwZM4qbmpokSStXriwsLi4uKy8vL/na17424vLLL/9MR98XgRcAAAB67bXX8hcuXFi0bt26t3bs2LFtyZIlu5pvnzNnzvkPP/zwrq1bt25/8MEH99xyyy3nSdKVV15Zv2nTpje3b9++bdasWR/cf//95yZfs3Pnzvx169a99bvf/W77woULhx4/ftxOn3f79u29v//97+/euXPn1l27dvV68cUXCxoaGuyOO+44//nnn397w4YNOw4dOtSp6864aA0AAABau3Ztv+nTp39YVFTUKElDhgw5ldxWV1eXs3HjxoJrr732wuRzJ06cMEl69913e86cOXP4wYMHe5w4cSJnxIgRx5P7fOlLX/qod+/e3rt378YBAwac3LNnT96FF154svm848eP/zj5XFlZWcM777zTs2/fvqdGjBhxfMyYMSck6frrr//gkUceGdzR90bgBQAAgNxdZuYtbTt16pT69u3b+Oabb37qU89uu+228+64447aG2+8se65557re//99w9NbuvVq9cn4+Xm5qqxsfFTZ3hb2se9xTI6jCUNAAAAUGVl5eHVq1cPqK2tzZWk/fv35ya3DRgwoGn48OEnHn300bMlqampSevXr+8tSUeOHMk977zzTkrSsmXLBqajlgkTJhzbvXt3rx07dvSUpJUrVw7ozHgEXgAAAOjiiy8+dvfdd++bNm3amJKSktJbb711RPPtK1as+MNjjz02qKSkpHTUqFFlq1at6i9J9957794bbrjhwvLy8pKBAwc2pqOWgoICf+ihh/5YWVk5qry8vOScc8452bdv31Ntv7JlaT9l3ExgA39ifmHgU3TGyGPLO/X6mvzZaaok/Tr73qRov78ovzcp2u+vK783Kdrvj2PzzLrye5PS8P4WXJWmSj4tFoupoqKird0+9av2jJpfGHxuanHervvBE3V1dTmFhYVNTU1N+upXv3reqFGjjs2bN+9A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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "%matplotlib inline\n", "import matplotlib.pyplot as plt\n", "from matplotlib.lines import Line2D\n", "\n", "def gantt(df, lw=10):\n", " \n", " # create sorted lists of the unique ids and activities appearing in the data log\n", " ids = sorted(list(set(df[\"id\"])))\n", " activities = sorted(list(set(df[\"activity\"])))\n", " \n", " # create list of unique colors for each event\n", " colors = [f\"C{i}\" for i in range(len(activities))]\n", " \n", " # create plot window\n", " fig, ax = plt.subplots(1, 1, figsize=(10, 3))\n", " \n", " # for each event and id, find entries in the data log and plot the begin and end points\n", " for i, activity in enumerate(activities):\n", " for j, id in enumerate(ids): \n", " for k in df[(df[\"id\"]==id) & (df[\"activity\"]==activity)].index:\n", " ax.plot([df[\"begin\"][k], df[\"end\"][k]], [j, j], colors[i], solid_capstyle=\"butt\", lw=lw)\n", " \n", " # create legend\n", " lines = [Line2D([0], [0], lw=lw, color=colors[i]) for i in range(len(activities))]\n", " ax.legend(lines, activities, bbox_to_anchor=(1.05, 1.0), loc=\"upper left\")\n", " \n", " # annotate the axes\n", " ax.set_yticks(range(len(ids)))\n", " ax.set_yticklabels(ids)\n", " ax.grid(True)\n", " ax.set_xlabel(\"Time\")\n", " ax.set_title(\"Gannt Chart\")\n", " for sp in ['top', 'bottom', 'right', 'left']:\n", " ax.spines[sp].set_visible(False)\n", " \n", "gantt(df)" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 2, "link": "[7.2.6 Charging stations as shared resources](https://jckantor.github.io/cbe30338-2021/07.02-Agent-Based-Models.html#7.2.6-Charging-stations-as-shared-resources)", "section": "7.2.6 Charging stations as shared resources" } }, "source": [ "## 7.2.6 Charging stations as shared resources\n", "\n", "A charging station is an example of a **shared resource**. There are three types of resources that can be modeled in Simpy:\n", "\n", "* **Resource** Resources that can only used by a limited number of processes at a time.\n", "* **Stores** Resources that can store or release Python objects.\n", "* **Containers** Resources that model the production and consumption of bulk goods.\n", "\n", "In this example, charging stations are an example of `Resources`. " ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 2, "link": "[7.2.6 Charging stations as shared resources](https://jckantor.github.io/cbe30338-2021/07.02-Agent-Based-Models.html#7.2.6-Charging-stations-as-shared-resources)", "section": "7.2.6 Charging stations as shared resources" } }, "source": [ "The next cell shows how a charging station can be incorporated into the simulation as a shared resource. Three changes required:\n", "\n", "* Create a simpy.Resource() by specifying the simulation environment and resource capacity. \n", "* The Roomba model must create request for use of a charger. The request is specified in a subsequent `yield` statement. Execution resumes once a charger becomes available.\n", "* When finished with a charger, the model must release the charger so that it is available for use in other model instances.\n", "\n", "The following cell implements charger system with a capacity of 1. Examine the data log to verify that only one Roomba is charging at any point in time." ] }, { "cell_type": "code", "execution_count": 34, "metadata": { "nbpages": { "level": 2, "link": "[7.2.6 Charging stations as shared resources](https://jckantor.github.io/cbe30338-2021/07.02-Agent-Based-Models.html#7.2.6-Charging-stations-as-shared-resources)", "section": "7.2.6 Charging stations as shared resources" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " time\n", "activity \n", "charging 14.7\n", "cleaning 43.5\n" ] }, { "data": { "image/png": "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e4ZI/370eNiwYRO+/e1vD21ub9OmTT0lad++fUXTpk0bXVZWNm7u3LnnDh06dML+/fs7PWCb9BvcvbizjQctHnsukvN4khXVeUyZUlM9M+QIUrurUr7v/6jmn0y/DDb37L/bV1T3PRC21157refixYtLNmzY8GZJSUnDgQMHCm+55ZYRBw4c6Pbaa6+9uXnz5p5XX331F771rW992Lt378Y1a9bsGjBgQOP+/fuLLrroorFz5879SJJqamp6/vjHP655/PHHd7/88su9V69efebWrVu3nzx50iZNmlQ2efLko61tf9CgQQ3bt2/fUV1dPbi6unrIU0899acFCxYMvfTSS4/cd999tU8//XTfFStWDOpKbkxpAAAAgNatW9f3yiuv/LCkpKRBkoYMGXJKkmbNmvVRYWGhKioqPj18+HA3qelSYHfcccfwV155pbigoEAHDx7svnfv3iJJKikpOXH55Zd/IknxeLy4srLyo+LiYpfkV1xxxUdtbX/u3LkfStKUKVOOrlq16kxJevXVV4ufffbZXZI0Z86cj/v27XuqK7lR8AIAAEDuLjP73FW2evbs6S3XkaRly5YNOHz4cNHWrVt39OjRw4cNGzbh2LFjBZLUu3fvxtPXT0bzdoqKiryhocE6+/72MIcXAAAAmjFjxserVq0aUFtbWyhJBw4caP1sM0l1dXWFgwYNOtmjRw9fvXp1n3379nVvbb1YLFa/bt26fkePHrW6urqCl156qX9nYpoyZUr9Y489NkCSnnnmmb4ff/xxmzG1hxFeAAAA6MILL/z0rrvu2j99+vSxBQUFPn78+Fbn2krSvHnzPqisrPzC+PHjx5WXlx8dNWrUp62td+mllx6dMWNGXVlZWfmwYcOOX3DBBZ/069cv6WkJ1dXV++bMmXNeWVnZmVOnTq0fPHjwyf79+3d6WgMFLwAAACRJt9122+HbbrvtcFvLjx49ukmSSkpKGjZv3vxma+u8/fbb21o+X7hwYe0DDzyw78iRIwVTp04traqqOiBJK1eurGle57333tva/PiSSy45+uqrr+6UpAEDBpx6+eWX3+rWrZteeumlM37729/26dWrV6fnOVDwAgAAhKymeqZt2bKlZuLEie+HHUu63Xjjjee+/fbbvY4fP27XXXfd4YsvvrjNkePT7dq1q/u11157fmNjo7p16+bLli2r6UoMFLwAAAAIzOrVq9/t6nsnTJhwfMeOHdtTjYGT1gAAABBpFLwAAACINApeAAAARBpzeAEAAMK2qJ9PlKRf6NzMbrduY0a3FxJGeAEAANCqO++8c+g999wzJN3tTp48eWy622wPBS8AAAAyatOmTa1ewzcoFLwAAACQJC1dunTgmDFjykpLS8tmz549quWybdu29Zg+ffro8vLycRUVFaWbNm3qKUlPPPFEvwsuuGDsuHHjyqZNmzZmz549RVLT6PA111wzcsqUKaXDhw+f8N3vfves5rZ69+49WZKef/75PlOmTCmdMWPGeaNGjSqfNWvWqMbGRknSU0891W/UqFHlFRUVpd/85jdHXHbZZV/oal4UvAAAANBrr73Wc/HixSXr169/a+fOnduXLVu2u+XyefPmnfvggw/u3rZt2477779/780333yOJF1xxRX1mzdvfnPHjh3b58yZ88G99957dvN7du3a1XP9+vVv/f73v9+xePHiocePH7fTt7tjx45eP/zhD/fs2rVr2+7du3u8+OKLxUePHrXbb7/93BdeeOHtjRs37jx8+HBK551x0hoAAAC0bt26vldeeeWHJSUlDZI0ZMiQU83L6urqCjZt2lR8zTXXnN/82okTJ0yS3n333e6zZ88efujQoW4nTpwoGDFixPHmdb761a9+1KtXL+/Vq1fDgAEDTu7du7fo/PPPP9lyuxMmTPik+bXy8vKj77zzTvc+ffqcGjFixPGxY8eekKTrrrvug4ceemhwV3Oj4AUAAIDcXWbmrS07deqU+vTp0/Dmm29+7q5nt9566zm333577Q033FD3/PPP97n33nuHNi/r0aPHZ+0VFhaqoaHhcyO8ra3j3moYXcaUBgAAAGjGjBkfr1q1akBtbW2hJB04cKCwedmAAQMahw8ffuLhhx8+U5IaGxu1YcOGXpJ05MiRwnPOOeekJD366KMD0xHLxIkTP92zZ0+PnTt3dpekp556akAq7VHwAgAAQBdeeOGnd9111/7p06ePLS0tLbvllltGtFy+YsWKPz7yyCODSktLy0aPHl2+cuXK/pJ0991377v++uvPr6ioKB04cGBDOmIpLi72Bx544E8zZswYXVFRUXrWWWed7NOnz6mO39m6tA8ZtxBYw59Z1C/wTXTVyE+fSOn9NT3npimSNFtUF3YEnxm5YE1K78/1zzgejysW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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "import simpy \n", "import pandas as pd\n", "\n", "data_log = []\n", "\n", "def roomba_model(id, charge_time, clean_time):\n", " while True:\n", " tic = env.now\n", " yield env.timeout(clean_time)\n", " toc = env.now\n", " data_log.append([id, \"cleaning\", tic, toc])\n", " \n", " request = chargers.request()\n", " yield request\n", " tic = env.now\n", " yield env.timeout(charge_time)\n", " chargers.release(request)\n", " toc = env.now\n", " data_log.append([id, \"charging\", tic, toc])\n", " \n", "env = simpy.Environment()\n", "chargers = simpy.Resource(env, capacity=1)\n", "\n", "for r in roomba_df.index:\n", " env.process(roomba_model(roomba_df[\"id\"][r], roomba_df[\"charge_time\"][r], roomba_df[\"clean_time\"][r]))\n", "\n", "env.run(until=16)\n", "\n", "df = pd.DataFrame(data_log, columns=[\"id\", \"activity\", \"begin\", \"end\"])\n", "df[\"time\"] = df[\"end\"] - df[\"begin\"]\n", "pivot_table = pd.pivot_table(df, index=[\"activity\"], aggfunc={\"time\":sum} )\n", "\n", "print(pivot_table)\n", "gantt(df)" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 2, "link": "[7.2.7 How many charging stations are required?](https://jckantor.github.io/cbe30338-2021/07.02-Agent-Based-Models.html#7.2.7-How-many-charging-stations-are-required?)", "section": "7.2.7 How many charging stations are required?" } }, "source": [ "## 7.2.7 How many charging stations are required?\n", "\n", "The following cell uses the Python `with` statement to request a changer and release it upon completion of a code block. The advantage of this construction is that it handles the release automatically, thereby avoiding a potential source of coding errors, and also provides a visual demarcation of the code block where the charger is being use.\n", "\n", "The cell also uses the Pandas `pivot_table` to report the total amount of charging used and cleaning time provided. Find the minimum number of chargers required to produce 48 hours of cleaning time in a 16 hour shift." ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "nbpages": { "level": 2, "link": "[7.2.7 How many charging stations are required?](https://jckantor.github.io/cbe30338-2021/07.02-Agent-Based-Models.html#7.2.7-How-many-charging-stations-are-required?)", "section": "7.2.7 How many charging stations are required?" } }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "import simpy \n", "import pandas as pd\n", "import numpy as np\n", "\n", "data_log = []\n", "\n", "def roomba_model(id, charge_time, clean_time):\n", " while True:\n", " with chargers.request() as request:\n", " yield request\n", " tic = env.now\n", " yield env.timeout(charge_time)\n", " toc = env.now\n", " data_log.append([id, \"charging\", tic, toc])\n", " \n", " tic = env.now\n", " yield env.timeout(clean_time)\n", " toc = env.now\n", " data_log.append([id, \"cleaning\", tic, toc])\n", " \n", "env = simpy.Environment()\n", "chargers = simpy.Resource(env, capacity=4)\n", "\n", "for r in roomba_df.index:\n", " env.process(roomba_model(roomba_df[\"id\"][r], roomba_df[\"charge_time\"][r], roomba_df[\"clean_time\"][r]))\n", "\n", "env.run(until=16)\n", "df = pd.DataFrame(data_log, columns=[\"id\", \"activity\", \"begin\", \"end\"])\n", "\n", "df[\"time\"] = df[\"end\"] - df[\"begin\"]\n", "pd.pivot_table(df, index=[\"activity\"], aggfunc={\"time\":sum} )\n", "\n", "gantt(df)" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 2, "link": "[7.2.7 How many charging stations are required?](https://jckantor.github.io/cbe30338-2021/07.02-Agent-Based-Models.html#7.2.7-How-many-charging-stations-are-required?)", "section": "7.2.7 How many charging stations are required?" } }, "source": [ "---\n", "\n", "**Study Question:** Rerun the simulation to determine the minimum number of chargers required to meet the requirement for 48 hours of cleaning in a 16 hour shift.\n", "\n", "**Study Question:** Modify the model to assume the changers are not charged at the start of the cleaning shift. Does that change the number of chargers required to meet the cleaning requirement?\n", "\n", "**Study Question:** Assume each Roomba needs to dispose of waste after 20 minutes of cleaning, that it takes 5 minutes to dispose of the waste, and requires access to a waste disposal station. \n", "\n", "Hints:\n", "* You will need to create a log a new event called 'waste disposal'. \n", "* Model the waste disposal station as a shared resource.\n", "* You may need to make some decisions on how to handle the waste at the end of a cleaning cycle.\n", "\n", "\n", "---" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 2, "link": "[7.2.8 Adding a reporter process](https://jckantor.github.io/cbe30338-2021/07.02-Agent-Based-Models.html#7.2.8-Adding-a-reporter-process)", "section": "7.2.8 Adding a reporter process" } }, "source": [ "## 7.2.8 Adding a reporter process" ] }, { "cell_type": "code", "execution_count": 61, "metadata": { "nbpages": { "level": 2, "link": "[7.2.8 Adding a reporter process](https://jckantor.github.io/cbe30338-2021/07.02-Agent-Based-Models.html#7.2.8-Adding-a-reporter-process)", "section": "7.2.8 Adding a reporter process" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " time\n", "activity \n", "charging 22.7\n", "cleaning 62.6\n" ] }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAArwAAADgCAYAAADhabXmAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8vihELAAAACXBIWXMAAAsTAAALEwEAmpwYAAAdUElEQVR4nO3df3xV9Z3n8fcnCRAwEEQQww8FLQQTEGgcHGjRWGsnGUbELXYVbW13WB6rq6vVaYYZ9yGM265s5eHSLnULddRWC9qHWgWtUO304k4Ha0WgCIhiTQEhgKiByM+Qz/5xbpwIN8lNcs89ycnr+XjwIPeec8/3k09Obt45+Z5zzN0FAAAAxFVO1AUAAAAAYSLwAgAAINYIvAAAAIg1Ai8AAABijcALAACAWCPwAgAAINYIvABiz8yqzezLUdcBAIgGgRdAq8zsOjP7vZl9Ymb7kh/fYmaWhbFbDatm1s/MFpnZDjOrM7PtyccDQ6opYWazw9g2ACDzCLwAWmRmd0n6gaT7JZ0jabCk/yLpC5J6RliaJMnMekr6jaRSSRWS+kmaIumApEkZHsvMjPdNAOhieOMG0CwzK5R0r6Rb3P0pdz/kgfXufoO7H0uuN83M1pvZQTPbaWbzm2xjhJm5md2UPAL7gZnd3WT5fDP7hZn9zMwOmdlmM7s4uewxSedKWpk8cluVosxvJNe5xt23uHuDu+9z9//h7r9qst4EM/ujmdWa2ZNmlp8c40wze97M9pvZR8mPhzWpL2Fm3zOz30k6LOkxSVMlLU7WtDgjzQYAhIbAC6AlkyX1kvRcK+t9oiB49pc0TdLNZjbjlHW+KKlY0hWS7jGzC5ssmy7pieTrV0haLEnu/nVJOyRd5e4F7v79FGN/WdIqd69rpcavKTgCPFLSRZK+mXw+R9Ijks5TEJyPNI7fxNclzZHUN/m6/yfp1mRNt7YyLgAgYgReAC0ZKOkDd69vfMLM/s3MPjazI2Z2qSS5e8LdNyWPrv5R0nJJl52yrX9y9yPuvlHSRknjmyz7V3f/lbufVHAEdbzSd5akPWms90N33+3uH0paKWlCsvYD7v60ux9290OSvpei9kfdfbO717v7iTbUBgDoBAi8AFpyQNJAM8trfMLdp7h7/+SyHEkys0vM7LfJaQG1Cub4nnrCWE2Tjw9LKmhhWX7TMdOosSiN9VKOb2Z9zGyJmf3ZzA5KekVSfzPLbbL+zjRrAQB0QgReAC1ZK+mYpKtbWW+ZgqkIw929UNKPJWXqCg7eyvKXJf2VmZ3Rzu3fpWCqxSXu3k/Spcnnm9Z/ag2t1QQA6EQIvACa5e4fS/onSQ+a2UwzKzCzHDObIKlpwOwr6UN3P2pmkyTNymAZeyWd38LyxxQcgX3azMYk6zvLzP7RzP46je33VTBv92MzGyBpXgZqAgB0IgReAC1Knih2p6QqSfsUhL0lkv5e0r8lV7tF0r1mdkjSPZJ+kcES7pP035Pzhv8uRX3HFJy49paklyQdlPSagikVv09j+4sk9Zb0gaRXJa1K4zU/kDQzeVWHH6bzSQAAomPu/GUOAAAA8cURXgAAAMQagRcAAACxRuAFAABArBF4AQAAEGsEXgAAAMRamIHXw/63du3a0MfoCv/oA32gD/SBPtAHetDhPiDGuvQR3mPHjkVdQqdAHwL0IUAfAvQhQB8C9IEeNKIP3VOY1+EN/7el+YWhD4E0za9t80tGzH0hhELapjo/kzcEQ0eMOLos6hLYHzoR9gd8Rjt+xjQnkUiovLw81aJM3Q4dnVCXPsILAAAAtCYv3RXN7KSkTU2emuHu1RmvCAAAAMigtAOvpCPuPiGsQgAAALqzdevWnZ2Xl/eQpLHir/Bt0SDpzfr6+tllZWX7Uq3QlsALAACAkOTl5T10zjnnXDho0KCPcnJyuHJEmhoaGmz//v0lNTU1D0manmqdtgTe3ma2Ifnxe+5+zakrmNkcSXMkqaqqSpWVlW0suW3KQ9062iKRSERdAgAgpjL5M6auri7l9po5kS3bxhJ22y4nJ8cHDRpUW1NTM7a5dTI6pcHdl0pa2viwDdtun0ToIyBN7XqjWBX9VRoAAJ1fJsNoC1dpiNSIuS8EuWn5rpHZHLd6wbR12RwvLMlfEpqdBsL8EAAAAKT01a9+dcQjjzxyZhjbvuOOO4Y8++yzfcPY9qmYwwsAAICMa2hokLsrNzc35fJFixbtzlYtHOEFAACAJGnx4sVnjR49uqS4uLhkxowZIyVpzZo1BRMnThwzbNiwcY1He2tra3MmT548uqSk5MLRo0eXPP744/0ladu2bT3PP//80htvvPHc0tLSknfffbfnd77znaKRI0eWTpkyZdRVV1018p577hksffbo8dChQ8d9+9vfHtK4vfXr1+dL0u7du/OmTJkyqqSk5MJZs2adN2TIkHF79uxp8wHbtF/g7gVt3XjYEuXPdcp5ONnWWecjtaZ6wbSMbq99fcjc3Xs6iy67P2R4e+wPAfaHAPtD190XkD2vv/56/sKFC4vWrl37VlFRUf3evXtzb7nlluF79+7t8frrr7+1YcOG/GuuueZz3/rWtz7q06dPwwsvvLB9wIABDXv27Mm75JJLxsyaNetjSaqurs7/yU9+Uv3444/veOWVV/qsXLnyzE2bNm05ceKETZgwoWTixImHU40/cODA+i1btmxdsGDBoAULFgx+8skn/zx37twhl1122aH77ruv5qmnnuq3fPnyge353JjSAAAAAK1evbrfVVdd9VFRUVG9JA0ePPikJE2fPv3j3NxclZWVHT1w4EAPKbgU2B133DHs1VdfLcjJydG+fft67tq1K0+SioqKjl9xxRWfSFIikSiorKz8uKCgwCX5lVde+XFz48+aNesjSZo0adLhFStWnClJr732WsGzzz67XZJmzpx5sF+/fifb87kReAEAACB3l5mddpWt/Px8b7qOJC1ZsmTAgQMH8jZt2rS1V69ePnTo0HFHjhzJkaQ+ffo0nLp+OhrHycvL8/r6emvr61vCHF4AAACooqLi4IoVKwbU1NTkStLevXtTn20mqba2NnfgwIEnevXq5StXruy7e/funqnWKy8vr1u9enXh4cOHrba2Nufll1/u35aaJk2aVPfYY48NkKRnnnmm38GDB5utqSUc4QUAAIAuvvjio3fdddeeqVOnjsnJyfGxY8emnGsrSbNnz/6wsrLyc2PHjr2wtLT08MiRI4+mWu+yyy47XFFRUVtSUlI6dOjQYxdddNEnhYWFaU9LWLBgwe6ZM2eeX1JScubkyZPrBg0adKJ///5tntZA4AUAAIAk6bbbbjtw2223HWhu+eHDh9dLUlFRUf2GDRveSrXOO++8s7np43nz5tU88MADuw8dOpQzefLk4qqqqr2S9PTTT1c3rvP+++9vavz40ksvPfzaa69tk6QBAwacfOWVV97u0aOHXn755TN+97vf9e3du3eb5zkQeAEAACJWvWCabdy4sXr8+PEfRF1Lpt14443nvfPOO72PHTtm11133YEvfvGLzR45PtX27dt7fu1rX7ugoaFBPXr08CVLllS3pwYCLwAAAEKzcuXK99r72nHjxh3bunXrlo7WwElrAAAAiDUCLwAAAGKNwAsAAIBYYw4vAABA1OYX+nhJ+qXOy+64teuyOl5EOMILAACAlO68884h99xzz+BMb3fixIljMr3NlhB4AQAAkFXr169PeQ3fsBB4AQAAIElavHjxWaNHjy4pLi4umTFjxsimyzZv3txr6tSpo0pLSy8sKysrXr9+fb4kLVu2rPCiiy4ac+GFF5ZMmTJl9M6dO/Ok4OjwtddeO2LSpEnFw4YNG/fd73737MZt9enTZ6IkPf/8830nTZpUXFFRcf7IkSNLp0+fPrKhoUGS9OSTTxaOHDmytKysrPib3/zm8Msvv/xz7f28CLwAAADQ66+/nr9w4cKiNWvWvL1t27YtS5Ys2dF0+ezZs8978MEHd2zevHnr/fffv+vmm28+V5KuvPLKug0bNry1devWLTNnzvzw3nvvPafxNdu3b89fs2bN23/4wx+2Lly4cMixY8fs1HG3bt3a+0c/+tHO7du3b96xY0evl156qeDw4cN2++23n/fiiy++s27dum0HDhzo0HlnnLQGAAAArV69ut9VV131UVFRUb0kDR48+GTjstra2pz169cXXHvttRc0Pnf8+HGTpPfee6/njBkzhu3fv7/H8ePHc4YPH36scZ2vfOUrH/fu3dt79+5dP2DAgBO7du3Ku+CCC040HXfcuHGfND5XWlp6+N133+3Zt2/fk8OHDz82ZsyY45J03XXXffjQQw8Nau/nRuAFAACA3F1m5qmWnTx5Un379q1/6623Trvr2a233nru7bffXnPDDTfUPv/8833vvffeIY3LevXq9en2cnNzVV9ff9oR3lTruKcso92Y0gAAAABVVFQcXLFixYCamppcSdq7d29u47IBAwY0DBs27PjDDz98piQ1NDRo7dq1vSXp0KFDueeee+4JSXr00UfPykQt48ePP7pz585e27Zt6ylJTz755ICObI/ACwAAAF188cVH77rrrj1Tp04dU1xcXHLLLbcMb7p8+fLlf3rkkUcGFhcXl4waNar06aef7i9Jd9999+7rr7/+grKysuKzzjqrPhO1FBQU+AMPPPDnioqKUWVlZcVnn332ib59+55s/ZWpZfyQcROhbfhT8wtDH6IjRhxd1qHXV+fPylAl4Yj756f5tWmtNmLuCx0ahj4E4tKHpuhJIO594L0w0OGv84JpHXp9uhKJhMrLy1MtOu1P7Vk1vzD83JRy3M5744na2tqcwsLChoaGBn3jG984d9SoUUfnzZu3r7n1N27cOHD8+PEjUi1Lew6vmZ2UtKnJU0+4+4K0qwYAAEBq82tt48aN1ePHj/8g6lI6i0WLFg1cvnz5wBMnTlhpaenhO++8s929actJa0fcfUJ7BwIAAADSNW/evH0tHdFtC+bwAgAAINbaEnh7m9mGJv/+Y2hVAQAAdD8NDQ0N0c4l7qKSfWtobnlGpzSY2RxJcySpqqpKlZWVbdh825WHunV0d4lEIuoSOgX6EKAPp6Mn3UO2vs7ZGqeuri7lWM2cyJZtb+7fv79k0KBBtTk5OdGcxNYFNTQ02P79+wslvdncOhm98YS7L5W0tPFhJredUiL0EdCNpf3mt6pjZyZ3dvQh0K4fhvQkEPM+xF22vs7ZCpwtXKUhcvX19bNramoeqqmpGSumnbZFg6Q36+vrZze3AndaAwAA6ATKysr2SZoedR1x1JbA29vMNjR5vMrd52a4HgAAACCj0g687p7b+loAAABA59Kl77TWmefhZBN9CNCHAH0I0IcAfQjQB3rQqNPeaQ2hYkI0AAAAYo3ACwAAgFgj8AIAACDWCLwAAACINQIvAAAAYo3ACwAAgFgj8AIAACDWCLwAAACINQIvAAAAYo3ACwAAgFgj8AIAACDWCLwAAACINQIvAAAAYo3ACwAAgFgj8AIAACDWCLwAAACINQIvAAAAYo3ACwAAgFgzdw9r26Ft+FPzC0MfAtkz4uiyqEtol+r8WVGXgAxhH0TUuuo+KEnVC6ZFXUJaEomEysvLUy2yLJeCLOIILwAAAGItr7UVzOykpE2Sekiql/RTSYvcvSHk2gAAAIAOazXwSjri7hMkyczOlrRMUqGkeSHWBQAAAGREm6Y0uPs+SXMk3WpmzHUBAABAp5fOEd7PcPc/mVmOpLMl7W26zMzmKAjEqqqqUmVlZUaKbE55qFsHAADpSiQSUZeQlrq6upS1NnMiG2KizYE3KeXRXXdfKmlp48N2bjt9idBHAAAAaegqgbGFqzQgxtp8lQYzO1/SSUn7Ml8OAAAAkFltCrxmNkjSjyUt9hAv4AsAAABkSjpTGnqb2Qb9+2XJHpP0QJhFAQAAAJnSauB199xsFNIeifLnmIej+MxHqu7g66PrQ20EYzYvLvtDR7WnD9WhVJINze+D7A+BrtKH6hC33VV6AISBO60BAAAg1gi8AAAAiDUCLwAAAGKNwAsAAIBYI/ACAAAg1gi8AAAAiDUCLwAAAGKNwAsAAIBYI/ACAAAg1gi8AAAAiDUCLwAAAGKNwAsAAIBYI/ACAAAg1gi8AAAAiDUCLwAAAGKNwAsAAIBYI/ACAAAg1gi8AAAAiDUCLwAAAGLN3D2sbYe24U/NLwx9iK5gxNFlWRurOn9W1sbqtObXfubhiLkvZGVYeh/I1v5OvwO8v2TZKe8vmZSt9ypJql4wLWtjtVUikVB5eXmqRZblUpBFHOEFAABArKUdeM3sHDN7wszeNbMtZvYrMxsdZnEAAABAR6UVeM3MJP1SUsLdL3D3Ekn/KGlwmMUBAAAAHZWX5nqXSzrh7j9ufMLdN4RSEQAAAJBB6QbesZLWtbaSmc2RNEeSqqqqVFlZ2YHSWlce6taB1BKJRNQlAIipuLy/dObPo66uLmV9zZzIhphIN/Cmxd2XSlra+DCT204pEfoIwGlOe1Nclb0znwHEW6ihK4vvVZ05PLZwlQbEWLonrW2WVBZmIQAAAEAY0g28/yKpl5n958YnzOwvzOyycMoCAAAAMiOtwOvB3SmukXRl8rJkmyXNl7Q7xNoAAACADuvSd1pjHk6APgToQ4A+BOhDgD4E6AM9aMSd1ron7rQGAACAWCPwAgAAINYIvAAAAIg1Ai8AAABijcALAACAWCPwAgAAINYIvAAAAIg1Ai8AAABijcALAACAWCPwAgAAINYIvAAAAIg1Ai8AAABijcALAACAWCPwAgAAINYIvAAAAIg1Ai8AAABijcALAACAWCPwAgAAINYIvAAAAIg1c/ewth3ahj81vzD0IbJhxNFlHXp9df6sDFUSsfm1HXp5IpFQeXl5m14zYu4LHRpTikf/O7oPSvHoQ9N9kH0jwL4RoA9Jab5Pd/T7p3rBtA69viUt/Kyw0AZF5NI6wmtmJ81sg5ltNLM3zGxK2IUBAAAAmZCX5npH3H2CJJnZX0m6T9JlYRUFAAAAZEp75vD2k/RRpgsBAAAAwpDuEd7eZrZBUr6kIklfCq0iAAAAIIPaM6VhsqSfmdlYP+WMNzObI2mOJFVVVamysjKTtZ6mPNStI9sSiUSHXl9XV9fhbaB7Y/8BWpat75Ewx2nuZ0VbT3pG15Ju4P2Uu681s4GSBknad8qypZKWNj7seHmtSIQ+ArKoo2827blKg1Z1/Ex8xMdn9h/2DeA0ab/HdvD7J8zw2a6fFejy2jyH18zGSMqVdCDz5QAAAACZ1dY5vFJwnbqb3P1kOCUBAAAAmZNW4HX33LALAQAAAMLQpe+0xjycAH0I0IcAfQjQhwB9CNAHetCIO611T+25Di8AAADQZRB4AQAAEGsEXgAAAMQagRcAAACxRuAFAABArBF4AQAAEGsEXgAAAMQagRcAAACxRuAFAABArBF4AQAAEGsEXgAAAMQagRcAAACxRuAFAABArBF4AQAAEGsEXgAAAMQagRcAAACxRuAFAABArBF4AQAAEGvm7mFtO7QNf2p+YehDdBcjji6LugRV58+KuoRY4GsZH3wt4yXqr+ejFWeovLw80ho6g0Qi0VwfLMulIIs4wgsAAIBYSzvwmtk1ZuZmNibMggAAAIBMassR3usl/auk60KqBQAAAMi4tAKvmRVI+oKkvxWBFwAAAF1IXprrzZC0yt3fNrMPzezz7v7GqSuZ2RxJcySpqqpKlZWVmas0hfJQtw4AQHzU1dUpkUhEXUbkmusDJ/TFW7qB93pJi5IfP5F8fFrgdfelkpY2Puxoca1KhD4CAACxUFBQQKhTi1dpQIy1GnjN7CxJX5I01sxcUq4kN7MqD/GaZgAAAEAmpDOHd6akn7n7ee4+wt2HS3pP0hfDLQ0AAADouHQC7/WSfnnKc09L4mrkAAAA6PRandLg7uUpnvthKNW0UaL8OebhKDPzkaozUklH1Xbo1czLCjzaKfrQsa9lJsRhf6jOwDY63ofov5aZ0Bn2h+pIRxcnrKFb405rAAAAiDUCLwAAAGLNuvKFFsxsTvJSaN0afQjQhwB9CNCHAH0I0Ad60Ig+dE9d/QjvnKgL6CToQ4A+BOhDgD4E6EOAPtCDRvShG+rqgRcAAABoEYEXAAAAsdbVAy9zcAL0IUAfAvQhQB8C9CFAH+hBI/rQDXXpk9YAAACA1nT1I7wAAABAi7ps4DWzCjPbZmbbzWxu1PVEwcyGm9lvzWyrmW02s9ujrikqZpZrZuvN7Pmoa4mSmfU3s6fM7K3kfjE56pqyzcy+nfx+eNPMlptZftQ1ZYOZPWxm+8zszSbPDTCzl8zsneT/Z0ZZYzY004f7k98TfzSzX5pZ/whLzIpUfWiy7O/MzM1sYBS1ZVNzfTCz25IZYrOZfT+q+pA9XTLwmlmupB9JqpRUIul6MyuJtqpI1Eu6y90vlPSXkv5rN+2DJN0uaWvURXQCP5C0yt3HSBqvbtYTMxsq6b9Jutjdx0rKlXRdtFVlzaOSKk55bq6k37j7KEm/ST6Ou0d1eh9ekjTW3S+S9Lakf8h2URF4VKf3QWY2XNKVknZku6CIPKpT+mBml0u6WtJF7l4qaWEEdSHLumTglTRJ0nZ3/5O7H5f0hIKdt1tx9z3u/kby40MKws3QaKvKPjMbJmmapIeiriVKZtZP0qWS/lmS3P24u38caVHRyJPU28zyJPWRtDvierLC3V+R9OEpT18t6afJj38qaUY2a4pCqj64+6/dvT758FVJw7JeWJY1sz9I0v+WVCWpW5zA00wfbpa0wN2PJdfZl/XCkHVdNfAOlbSzyeNd6oZBrykzGyFpoqTfR1xKFBYpeANviLiOqJ0vab+kR5LTOx4yszOiLiqb3P19BUdrdkjaI6nW3X8dbVWRGuzue6TgF2RJZ0dcT2fwnyS9GHURUTCz6ZLed/eNUdcSsdGSpprZ781sjZn9RdQFIXxdNfBaiue6xW+rqZhZgaSnJd3h7gejriebzOxvJO1z93VR19IJ5En6vKT/6+4TJX2i7vEn7E8l56heLWmkpCGSzjCzG6OtCp2Fmd2tYCrYz6OuJdvMrI+kuyXdE3UtnUCepDMVTAX8jqRfmFmqXIEY6aqBd5ek4U0eD1M3+bPlqcysh4Kw+3N3fybqeiLwBUnTzaxawdSWL5nZ49GWFJldkna5e+NR/qcUBODu5MuS3nP3/e5+QtIzkqZEXFOU9ppZkSQl/++2f7o1s5sk/Y2kG7x7Xo/zAgW/CG5Mvl8Ok/SGmZ0TaVXR2CXpGQ+8puCvg7E/ga+766qB9w+SRpnZSDPrqeCklBUR15R1yd9I/1nSVnd/IOp6ouDu/+Duw9x9hIL94F/cvVse0XP3Gkk7zaw4+dQVkrZEWFIUdkj6SzPrk/z+uELd7MS9U6yQdFPy45skPRdhLZExswpJfy9pursfjrqeKLj7Jnc/291HJN8vd0n6fPJ9o7t5VtKXJMnMRkvqKemDKAtC+Lpk4E2efHCrpNUKfpj9wt03R1tVJL4g6esKjmpuSP7766iLQqRuk/RzM/ujpAmS/me05WRX8uj2U5LekLRJwXtct7irkpktl7RWUrGZ7TKzv5W0QNKVZvaOgjPzF0RZYzY004fFkvpKein5PvnjSIvMgmb60O0004eHJZ2fvFTZE5Ju6qZH/bsV7rQGAACAWOuSR3gBAACAdBF4AQAAEGsEXgAAAMQagRcAAACxRuAFAABArBF4AUTKzM5qclm9GjN7P/lxnZk9GHV9AICuj8uSAeg0zGy+pDp3Xxh1LQCA+OAIL4BOyczKzez55MfzzeynZvZrM6s2s/9gZt83s01mtip5i22ZWZmZrTGzdWa2uvG2ugCA7o3AC6CruEDSNElXS3pc0m/dfZykI5KmJUPv/5E0093LFNxN6XtRFQsA6Dzyoi4AANL0orufMLNNknIlrUo+v0nSCEnFksYquH2skuvsiaBOAEAnQ+AF0FUckyR3bzCzE/7vJyA0KHgvM0mb3X1yVAUCADonpjQAiIttkgaZ2WRJMrMeZlYacU0AgE6AwAsgFtz9uKSZkv6XmW2UtEHSlEiLAgB0ClyWDAAAALHGEV4AAADEGoEXAAAAsUbgBQAAQKwReAEAABBrBF4AAADEGoEXAAAAsUbgBQAAQKwReAEAABBr/x/Icx/h9prNmgAAAABJRU5ErkJggg==\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "import simpy \n", "import pandas as pd\n", "import numpy as np\n", "\n", "data_log = []\n", "\n", "def roomba_model(id, charge_time, clean_time):\n", " while True:\n", " tic = env.now\n", " yield env.timeout(clean_time)\n", " toc = env.now\n", " data_log.append([id, \"cleaning\", tic, toc])\n", " \n", " with chargers.request() as request:\n", " yield request\n", " tic = env.now\n", " yield env.timeout(charge_time)\n", " toc = env.now\n", " data_log.append([id, \"charging\", tic, toc])\n", " \n", "reporter_log = []\n", "def reporter(dt):\n", " while True:\n", " reporter_log.append([env.now, chargers.count])\n", " yield env.timeout(dt)\n", " \n", "env = simpy.Environment()\n", "chargers = simpy.Resource(env, capacity=2)\n", "\n", "for r in roomba_df.index:\n", " env.process(roomba_model(roomba_df[\"id\"][r], roomba_df[\"charge_time\"][r], roomba_df[\"clean_time\"][r]))\n", " \n", "env.process(reporter(0.1))\n", "\n", "env.run(until=16)\n", "df = pd.DataFrame(data_log, columns=[\"id\", \"activity\", \"begin\", \"end\"])\n", "\n", "df[\"time\"] = df[\"end\"] - df[\"begin\"]\n", "print(pd.pivot_table(df, index=[\"activity\"], aggfunc={\"time\":sum}))\n", "\n", "gantt(df)" ] }, { "cell_type": "code", "execution_count": 62, "metadata": { "nbpages": { "level": 2, "link": "[7.2.8 Adding a reporter process](https://jckantor.github.io/cbe30338-2021/07.02-Agent-Based-Models.html#7.2.8-Adding-a-reporter-process)", "section": "7.2.8 Adding a reporter process" } }, "outputs": [ { "data": { "text/plain": [ "(array([17., 0., 0., 54., 0., 90.]),\n", " array([0. , 0.33333333, 0.66666667, 1. , 1.33333333,\n", " 1.66666667, 2. ]),\n", " )" ] }, "execution_count": 62, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "data = np.array(reporter_log)\n", "plt.hist(data[:,1], 6)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "nbpages": { "level": 2, "link": "[7.2.8 Adding a reporter process](https://jckantor.github.io/cbe30338-2021/07.02-Agent-Based-Models.html#7.2.8-Adding-a-reporter-process)", "section": "7.2.8 Adding a reporter process" } }, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": { "nbpages": { "level": 2, "link": "[7.2.8 Adding a reporter process](https://jckantor.github.io/cbe30338-2021/07.02-Agent-Based-Models.html#7.2.8-Adding-a-reporter-process)", "section": "7.2.8 Adding a reporter process" } }, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "< [7.1 Introduction to Simpy](https://jckantor.github.io/cbe30338-2021/07.01-Introduction-to-Simpy.html) | [Contents](toc.html) | [Tag Index](tag_index.html) | [7.3 Chemotaxis](https://jckantor.github.io/cbe30338-2021/07.03-Chemotaxis.html) >

\"Open

\"Download\"" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.5" } }, "nbformat": 4, "nbformat_minor": 4 }