{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "*This notebook contains material from [CBE40455-2020](https://jckantor.github.io/CBE40455-2020);\n", "content is available [on Github](https://github.com/jckantor/CBE40455-2020.git).*\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "< [3.0 Introduction to Discrete Event Simulation](https://jckantor.github.io/CBE40455-2020/03.00-Introduction-to-Discrete-Event-Modeling.html) | [Contents](toc.html) | [3.2 Introduction to Simpy](https://jckantor.github.io/CBE40455-2020/03.02-Introduction-to-Simpy.html) >

\"Open

\"Download\"" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 1, "link": "[3.1 Python Generators](https://jckantor.github.io/CBE40455-2020/03.01-Python-Generators.html#3.1-Python-Generators)", "section": "3.1 Python Generators" } }, "source": [ "# 3.1 Python Generators" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 2, "link": "[3.1.1 A simple simulation model](https://jckantor.github.io/CBE40455-2020/03.01-Python-Generators.html#3.1.1-A-simple-simulation-model)", "section": "3.1.1 A simple simulation model" } }, "source": [ "## 3.1.1 A simple simulation model\n", "\n", "As a simple demonstration, let's consider the task of modeling the progess of a disease in a single person. The person will go through several stages of the disease\n", "\n", "$$\\text{Uninfected} \\quad \\longrightarrow \\quad \\text{Exposed} \\quad \\longrightarrow \\quad \\text{Infectious} \\quad \\longrightarrow \\quad \\text{Recovered}$$" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 3, "link": "[3.1.1.1 Python generators](https://jckantor.github.io/CBE40455-2020/03.01-Python-Generators.html#3.1.1.1-Python-generators)", "section": "3.1.1.1 Python generators" } }, "source": [ "### 3.1.1.1 Python generators\n", "\n", "Python generators are the basic building block for discrete event simulation in Python. Python generators are similar to functions with three profound differences:\n", "\n", "1. They return values using the `yield` statement rather than a `return` statement. They don't disappear from memory until all statements have been executed.\n", "2. Because they don't disappear, they can start and be restarted with a `next` statement.\n", "3. Multiple instances of a generator may be working at the same time." ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "nbpages": { "level": 3, "link": "[3.1.1.1 Python generators](https://jckantor.github.io/CBE40455-2020/03.01-Python-Generators.html#3.1.1.1-Python-generators)", "section": "3.1.1.1 Python generators" } }, "outputs": [ { "data": { "text/plain": [ "3" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def a_function():\n", " return 3\n", "\n", "a_function()" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "nbpages": { "level": 3, "link": "[3.1.1.1 Python generators](https://jckantor.github.io/CBE40455-2020/03.01-Python-Generators.html#3.1.1.1-Python-generators)", "section": "3.1.1.1 Python generators" } }, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def a_generator():\n", " yield 3\n", " \n", "a_generator()" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 3, "link": "[3.1.1.1 Python generators](https://jckantor.github.io/CBE40455-2020/03.01-Python-Generators.html#3.1.1.1-Python-generators)", "section": "3.1.1.1 Python generators" } }, "source": [ "Using a generator is different from a function because they don't disappear from memory" ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "nbpages": { "level": 3, "link": "[3.1.1.1 Python generators](https://jckantor.github.io/CBE40455-2020/03.01-Python-Generators.html#3.1.1.1-Python-generators)", "section": "3.1.1.1 Python generators" } }, "outputs": [ { "data": { "text/plain": [ "3" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a = a_generator()\n", "next(a)" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 3, "link": "[3.1.1.1 Python generators](https://jckantor.github.io/CBE40455-2020/03.01-Python-Generators.html#3.1.1.1-Python-generators)", "section": "3.1.1.1 Python generators" } }, "source": [ "Let's create a generator that can return multiple values." ] }, { "cell_type": "code", "execution_count": 34, "metadata": { "nbpages": { "level": 3, "link": "[3.1.1.1 Python generators](https://jckantor.github.io/CBE40455-2020/03.01-Python-Generators.html#3.1.1.1-Python-generators)", "section": "3.1.1.1 Python generators" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n" ] } ], "source": [ "def my_first_generator():\n", " yield 1\n", " yield 2\n", " yield 3\n", " yield 4\n", "\n", "a = my_first_generator()\n", "print(next(a))" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 3, "link": "[3.1.1.1 Python generators](https://jckantor.github.io/CBE40455-2020/03.01-Python-Generators.html#3.1.1.1-Python-generators)", "section": "3.1.1.1 Python generators" } }, "source": [ "Let's get the next value." ] }, { "cell_type": "code", "execution_count": 35, "metadata": { "nbpages": { "level": 3, "link": "[3.1.1.1 Python generators](https://jckantor.github.io/CBE40455-2020/03.01-Python-Generators.html#3.1.1.1-Python-generators)", "section": "3.1.1.1 Python generators" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2\n" ] } ], "source": [ "print(next(a))" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 3, "link": "[3.1.1.1 Python generators](https://jckantor.github.io/CBE40455-2020/03.01-Python-Generators.html#3.1.1.1-Python-generators)", "section": "3.1.1.1 Python generators" } }, "source": [ "Let's create a second instance of the same generator." ] }, { "cell_type": "code", "execution_count": 36, "metadata": { "nbpages": { "level": 3, "link": "[3.1.1.1 Python generators](https://jckantor.github.io/CBE40455-2020/03.01-Python-Generators.html#3.1.1.1-Python-generators)", "section": "3.1.1.1 Python generators" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n" ] } ], "source": [ "b = my_first_generator()\n", "print(next(b))" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 3, "link": "[3.1.1.1 Python generators](https://jckantor.github.io/CBE40455-2020/03.01-Python-Generators.html#3.1.1.1-Python-generators)", "section": "3.1.1.1 Python generators" } }, "source": [ "Note how the instances each retain a unique state." ] }, { "cell_type": "code", "execution_count": 38, "metadata": { "nbpages": { "level": 3, "link": "[3.1.1.1 Python generators](https://jckantor.github.io/CBE40455-2020/03.01-Python-Generators.html#3.1.1.1-Python-generators)", "section": "3.1.1.1 Python generators" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "4\n", "2\n" ] } ], "source": [ "print(next(a))\n", "print(next(b))" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 4, "link": "[3.1.1.1.1 Exercise](https://jckantor.github.io/CBE40455-2020/03.01-Python-Generators.html#3.1.1.1.1-Exercise)", "section": "3.1.1.1.1 Exercise" } }, "source": [ "#### 3.1.1.1.1 Exercise\n", "\n", "Create a generator that produces a sequence of successive squares." ] }, { "cell_type": "code", "execution_count": 41, "metadata": { "nbpages": { "level": 4, "link": "[3.1.1.1.1 Exercise](https://jckantor.github.io/CBE40455-2020/03.01-Python-Generators.html#3.1.1.1.1-Exercise)", "section": "3.1.1.1.1 Exercise" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n", "1\n", "4\n", "9\n" ] } ], "source": [ "def succ_sq():\n", " k = 0\n", " while True:\n", " yield k**2\n", " k = k + 1\n", " \n", "a = succ_sq()\n", "print(next(a))\n", "print(next(a))\n", "print(next(a))\n", "print(next(a))" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 4, "link": "[3.1.1.1.2 Exercise](https://jckantor.github.io/CBE40455-2020/03.01-Python-Generators.html#3.1.1.1.2-Exercise)", "section": "3.1.1.1.2 Exercise" } }, "source": [ "#### 3.1.1.1.2 Exercise\n", "\n", "Create generator that creates the Fibonacci sequence\n", "\n", "$$\\begin{align*}\n", "F_0 & = 0 \\\\\n", "F_1 & = 1 \\\\\n", "F_{n} &= F_{n-1} + F_{n-2}\n", "\\end{align*}$$" ] }, { "cell_type": "code", "execution_count": 45, "metadata": { "nbpages": { "level": 4, "link": "[3.1.1.1.2 Exercise](https://jckantor.github.io/CBE40455-2020/03.01-Python-Generators.html#3.1.1.1.2-Exercise)", "section": "3.1.1.1.2 Exercise" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n", "1\n", "1\n", "2\n", "3\n", "5\n", "8\n", "13\n", "21\n", "34\n", "55\n", "89\n", "144\n", "233\n", "377\n", "610\n", "987\n", "1597\n", "2584\n", "4181\n" ] } ], "source": [ "def fib():\n", " a = 0\n", " b = 1\n", " yield a\n", " yield b\n", " while True:\n", " a, b = b, a+b\n", " yield b\n", " \n", "f = fib()\n", "for k in range(0, 20):\n", " print(next(f))" ] }, { "cell_type": "markdown", "metadata": { "nbpages": { "level": 4, "link": "[3.1.1.1.3 Exercise](https://jckantor.github.io/CBE40455-2020/03.01-Python-Generators.html#3.1.1.1.3-Exercise)", "section": "3.1.1.1.3 Exercise" } }, "source": [ "#### 3.1.1.1.3 Exercise\n", "\n", "Write a Python generator that simulates the response of a differential equation describing concentration in a stirred tank reactor.\n", "\n", "$$\\frac{dC}{dt} = -k C + q(t)$$\n", "\n", "where k = 1.0, C(0) = 1.0 and q(t) = 0.5. Use Euler's approximation." ] }, { "cell_type": "code", "execution_count": 73, "metadata": { "nbpages": { "level": 4, "link": "[3.1.1.1.3 Exercise](https://jckantor.github.io/CBE40455-2020/03.01-Python-Generators.html#3.1.1.1.3-Exercise)", "section": "3.1.1.1.3 Exercise" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0.0 1.0\n", "0.2 0.9\n", "0.4 0.82\n", "0.6 0.756\n", "0.8 0.705\n", "1.0 0.664\n", "1.2 0.631\n", "1.4 0.605\n", "1.6 0.584\n", "1.8 0.567\n", "2.0 0.554\n", "2.2 0.543\n", "2.4 0.534\n", "2.6 0.527\n", "2.8 0.522\n", "3.0 0.518\n", "3.2 0.514\n", "3.4 0.511\n", "3.6 0.509\n", "3.8 0.507\n", "4.0 0.506\n", "4.2 0.505\n", "4.4 0.504\n", "4.6 0.503\n", "4.8 0.502\n" ] } ], "source": [ "q = 0.5\n", "\n", "def reactor(dt, k):\n", " C = 1.0\n", " t = 0.0\n", " while t <= 5.0:\n", " yield t, C\n", " t = t + dt\n", " C = C - k*C*dt + q*dt\n", " \n", "a = reactor(0.2, 1.0)\n", "for t, C in a:\n", " print(round(t, 2), round(C, 3))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "< [3.0 Introduction to Discrete Event Simulation](https://jckantor.github.io/CBE40455-2020/03.00-Introduction-to-Discrete-Event-Modeling.html) | [Contents](toc.html) | [3.2 Introduction to Simpy](https://jckantor.github.io/CBE40455-2020/03.02-Introduction-to-Simpy.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.7.4" } }, "nbformat": 4, "nbformat_minor": 4 }