{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": { "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "import numpy as np\n", "import plotly.graph_objects\n", "from ipywidgets import interactive_output, VBox, HBox, SelectionSlider\n" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "mydefault = plotly.graph_objects.layout.Template()\n", "mydefault.layout.xaxis.showgrid = False\n", "mydefault.layout.yaxis.showgrid = False\n", "mydefault.layout.xaxis.showline = True\n", "mydefault.layout.yaxis.showline = True\n", "mydefault.layout.yaxis.linewidth = 2\n", "mydefault.layout.xaxis.ticks = \"outside\"\n", "mydefault.layout.yaxis.ticks = \"outside\"\n", "mydefault.layout.hovermode = False\n", "mydefault.layout.dragmode = \"pan\"\n", "mydefault.layout.scene.hovermode = False\n", "mydefault.layout.xaxis.showspikes = False\n", "mydefault.layout.yaxis.showspikes = False\n", "mydefault.layout.scene.xaxis.showspikes = False\n", "mydefault.layout.scene.yaxis.showspikes = False\n", "mydefault.layout.scene.zaxis.showspikes = False\n", "plotly.io.templates[\"mydefault\"] = mydefault\n", "plotly.io.templates.default = \"mydefault\"\n" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "**Recall the concept of a *strange attractor***" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "
\n", " \n", " \n", " \n", "
\n", " \n", "
\n", "\n", "" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "state_vars = list(var(\"G, S, W\"))\n", "system = (\n", " G*(1 - G/3) - 2.5*G/(1 + G)*S, \n", " 2/3*2.5*G/(1 + G)*S - 0.4*S - 0.1*S/(1 + S)*W, \n", " 0.5*0.1*S/(1 + S)*W - 0.01*W, \n", ")\n", "vectorfield(G, S, W) = system\n", "delta_t = 0.1\n", "t_range = srange(0, 10000, delta_t)\n", "initial_state = (1, 1, 1)\n", "attractor = desolve_odeint(vectorfield, initial_state, t_range, state_vars)[int(2000/delta_t):]\n", "\n", "fig = plotly.graph_objects.Figure()\n", "fig.layout.showlegend = False\n", "fig.layout.scene.xaxis.title.text = \"G (grass)\"\n", "fig.layout.scene.yaxis.title.text = \"S (sheep)\"\n", "fig.layout.scene.zaxis.title.text = \"W (wolves)\"\n", "fig.layout.scene.xaxis.range = (0, 3.2)\n", "fig.layout.scene.yaxis.range = (0, 1.2)\n", "fig.layout.scene.zaxis.range = (7.3, 11.0)\n", "fig.layout.scene.aspectmode = \"cube\"\n", "fig.add_scatter3d(x=attractor[:,0], y=attractor[:,1], z=attractor[:,2], \n", " mode=\"lines\", line_color=\"purple\", opacity=0.5)\n", "fig.show()\n" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "# The discrete-time logistic model: \n", "\n", "$$ X_{t+1} = 4 X_t \\cdot ( 1 - X_t ) $$\n" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "def logistic_interactive():\n", " r_values = [round(r, 2) for r in srange(0.5, 3.4, 0.1) + srange(3.45, 4.001, 0.01)]\n", " t_range = srange(10000)\n", " discard = 200\n", " tmax = 500\n", "\n", " fig = plotly.subplots.make_subplots(rows=int(1), cols=int(2))\n", " fig = plotly.graph_objects.FigureWidget(fig)\n", " fig.layout.showlegend = False\n", " fig.layout.margin.update(t=30, r=0)\n", " fig.layout.xaxis.title.text = \"t\"\n", " fig.layout.yaxis.title.text = \"X\"\n", " fig.layout.xaxis2.title.text = \"Relative frequency\"\n", " fig.layout.yaxis2.title.text = \"X\"\n", " fig.layout.xaxis.range = (0, 50)\n", " fig.layout.yaxis.range = (0, 1.05)\n", " fig.layout.xaxis2.range = (0, 1)\n", " fig.layout.yaxis2.range = (0, 1.05)\n", " fig.add_scatter(row=int(1), col=int(1), x=t_range[:tmax], marker_color=\"blue\", line_color=\"gray\")\n", " timeseries = fig.data[-1]\n", " fig.add_bar(row=int(1), col=int(2), orientation=\"h\")\n", " bar_chart = fig.data[-1]\n", "\n", " X_min, X_max, X_bins = 0, 1, 50\n", " bin_width = (X_max - X_min) / (X_bins - 1)\n", " bin_edges = np.array(srange(X_min, X_max + bin_width/2, bin_width), dtype=float)\n", " bin_middles = (bin_edges[:-1] + bin_edges[1:]) / 2\n", " bar_chart.y = bin_middles\n", "\n", " def update(r, X0):\n", " X_next = fast_float(r*x*(1 - x), x)\n", " X = X0\n", " solution = np.zeros([len(t_range)], dtype=float)\n", " for t in t_range:\n", " solution[t] = X\n", " X = X_next(X)\n", " histogram = np.histogram(solution[discard:], bin_edges, density=True)[0]\n", " histogram /= histogram.max()\n", " with fig.batch_update():\n", " timeseries.y = solution[:tmax]\n", " bar_chart.x = histogram\n", "\n", " def show_lines(change):\n", " if connect.value:\n", " with fig.batch_update():\n", " timeseries.mode = \"markers+lines\"\n", " show_dist.value = False\n", " else:\n", " timeseries.mode = \"markers\"\n", "\n", " def show_histogram(change):\n", " with fig.batch_update():\n", " bar_chart.visible = show_dist.value\n", " fig.layout.xaxis2.visible = show_dist.value\n", " fig.layout.yaxis2.visible = show_dist.value\n", "\n", " X_values = [round(r, 2) for r in srange(0.01, 0.991, 0.01)]\n", " r = SelectionSlider(options=r_values, value=4, description=\"r\", continuous_update=False)\n", " X0 = SelectionSlider(options=X_values, description=\"Initial X:\", continuous_update=False)\n", " connect = checkbox(True, label=\"Connect the dots\")\n", " show_dist = checkbox(False, label=\"Show distribution\")\n", " connect.observe(show_lines, \"value\")\n", " show_dist.observe(show_histogram, \"value\")\n", " show_lines(None)\n", " show_histogram(None)\n", " output = interactive_output(update, dict(r=r, X0=X0))\n", " display(HBox((r, X0, connect, show_dist)), fig, output)\n", " return fig\n" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "984ef6bf4de442d0b9d61bda9401f257", "version_major": 2, "version_minor": 0 }, "text/plain": [ "HBox(children=(SelectionSlider(continuous_update=False, description='r', index=84, options=(0.5, 0.6, 0.7, 0.8…" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "e714ac90fa9a48c1b6401250fbebcd15", "version_major": 2, "version_minor": 0 }, "text/plain": [ "FigureWidget({\n", " 'data': [{'line': {'color': 'gray'},\n", " 'marker': {'color': 'blue'},\n", " …" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "238700a0a9304ecd94e819cd39ec1dc2", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Output()" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "logistic_widget = logistic_interactive()\n" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "# The discrete-time logistic model: \n", "\n", "$$ X_{t+1} = r X_t \\cdot ( 1 - X_t ) $$\n", "\n", "We have been only considering the case where $r = 4$. But what if we vary $r$? \n" ] } ], "metadata": { "celltoolbar": "Slideshow", "hide_input": true, "kernelspec": { "display_name": "SageMath (default)", "language": "sagemath", "name": "sagemath" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", "version": "2.7.15" } }, "nbformat": 4, "nbformat_minor": 4 }