j1-template 2022.2.2 → 2022.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (149) hide show
  1. checksums.yaml +4 -4
  2. data/_includes/themes/j1/blocks/footer/boxes/contacts_box.proc +46 -18
  3. data/_includes/themes/j1/blocks/footer/boxes/links_box.proc +1 -0
  4. data/assets/data/fab.html +2 -2
  5. data/assets/data/footer.html +2 -2
  6. data/assets/themes/j1/adapter/js/analytics.js +13 -13
  7. data/assets/themes/j1/adapter/js/cookieConsent.js +1 -1
  8. data/assets/themes/j1/adapter/js/nbinteract.js +366 -120
  9. data/assets/themes/j1/core/css/themes/unodark/bootstrap.css +30 -40
  10. data/assets/themes/j1/core/css/themes/unodark/bootstrap.min.css +1 -1
  11. data/assets/themes/j1/core/css/themes/unolight/bootstrap.css +85 -216
  12. data/assets/themes/j1/core/css/themes/unolight/bootstrap.min.css +2 -2
  13. data/assets/themes/j1/core/js/template.js +1 -1
  14. data/assets/themes/j1/core/js/template.min.js +1 -1
  15. data/assets/themes/j1/core/js/template.min.js.map +1 -1
  16. data/assets/themes/j1/modules/carousel/css/theme/uno.css +5 -0
  17. data/assets/themes/j1/modules/carousel/css/theme/uno.min.css +1 -1
  18. data/assets/themes/j1/modules/cookieConsent/js/cookieConsent.js +1 -0
  19. data/assets/themes/j1/modules/justifiedGallery/css/justifiedGallery.css +6 -0
  20. data/assets/themes/j1/modules/justifiedGallery/css/justifiedGallery.min.css +1 -1
  21. data/assets/themes/j1/modules/mmenuLight/css/mmenu-light.css +2 -2
  22. data/assets/themes/j1/modules/mmenuLight/css/mmenu-light.min.css +1 -2
  23. data/assets/themes/j1/modules/nbInteract/README.md +169 -0
  24. data/assets/themes/j1/modules/nbInteract/css/nbinteract-core.css +4 -0
  25. data/assets/themes/j1/modules/nbInteract/css/nbinteract-core.min.css +4 -0
  26. data/assets/themes/j1/modules/nbInteract/css/theme/uno/nbinteract-core.css +33 -33
  27. data/assets/themes/j1/modules/nbInteract/css/theme/uno/nbinteract-core.min.css +1 -1
  28. data/assets/themes/j1/modules/nbInteract/js/requireJS/require.js +2068 -0
  29. data/assets/themes/j1/modules/nbInteract/js/requireJS/require.min.js +36 -0
  30. data/assets/themes/j1/modules/plotly/LICENSE +21 -0
  31. data/assets/themes/j1/modules/plotly/README.md +32 -0
  32. data/assets/themes/j1/modules/plotly/js/plotly.js +265345 -0
  33. data/assets/themes/j1/modules/plotly/js/plotly.min.js +65 -0
  34. data/assets/themes/j1/modules/requirejs/LICENSE +45 -0
  35. data/assets/themes/j1/modules/requirejs/README.md +79 -0
  36. data/assets/themes/j1/modules/requirejs/js/require.js +2068 -0
  37. data/assets/themes/j1/modules/requirejs/js/require.min.js +36 -0
  38. data/lib/j1/version.rb +1 -1
  39. data/lib/starter_web/Gemfile +1 -1
  40. data/lib/starter_web/_config.yml +1 -1
  41. data/lib/starter_web/_data/blocks/defaults/footer.yml +25 -17
  42. data/lib/starter_web/_data/blocks/footer.yml +78 -65
  43. data/lib/starter_web/_data/modules/analytics.yml +8 -23
  44. data/lib/starter_web/_data/modules/defaults/analytics.yml +1 -1
  45. data/lib/starter_web/_data/modules/defaults/cookieconsent.yml +4 -1
  46. data/lib/starter_web/_data/modules/justifiedGallery.yml +14 -8
  47. data/lib/starter_web/_data/modules/navigator_menu.yml +6 -3
  48. data/lib/starter_web/_data/modules/nbinteract.yml +12 -48
  49. data/lib/starter_web/_data/resources.yml +52 -18
  50. data/lib/starter_web/_includes/attributes.asciidoc +25 -0
  51. data/lib/starter_web/_plugins/lunr_index.rb +1 -1
  52. data/lib/starter_web/assets/images/pages/nbinteract/mandelbrot-menge-1920x1200.jpg +0 -0
  53. data/lib/starter_web/assets/images/pages/nbinteract/mandelbrot-menge.png +0 -0
  54. data/lib/starter_web/assets/images/pages/nbinteract/manual/nbi_bar.jpg +0 -0
  55. data/lib/starter_web/assets/images/pages/nbinteract/manual/nbi_hist.jpg +0 -0
  56. data/lib/starter_web/assets/images/pages/nbinteract/manual/nbi_line.jpg +0 -0
  57. data/lib/starter_web/assets/images/pages/nbinteract/manual/nbi_multiple_choice.jpg +0 -0
  58. data/lib/starter_web/assets/images/pages/nbinteract/manual/nbi_scatter.jpg +0 -0
  59. data/lib/starter_web/assets/images/pages/nbinteract/manual/nbi_scatter_drag.jpg +0 -0
  60. data/lib/starter_web/assets/images/pages/nbinteract/manual/nbi_short_answer.jpg +0 -0
  61. data/lib/starter_web/assets/images/pages/nbinteract/nbi-textbook-example.jpg +0 -0
  62. data/lib/starter_web/assets/videos/gallery/kick-it-old-school-poster.jpg +0 -0
  63. data/lib/starter_web/assets/videos/gallery/nye-party-shop-poster.jpg +0 -0
  64. data/lib/starter_web/assets/videos/gallery/stay-colorful-poster.jpg +0 -0
  65. data/lib/starter_web/collections/posts/public/series/_posts/2020-01-01-post-wiki-series.adoc +1 -0
  66. data/lib/starter_web/collections/posts/public/series/_posts/2020-01-02-post-wiki-series.adoc +1 -0
  67. data/lib/starter_web/collections/posts/public/series/_posts/2020-01-03-post-wiki-series.adoc +1 -0
  68. data/lib/starter_web/package.json +1 -2
  69. data/lib/starter_web/pages/public/jupyter/docs/_includes/documents/j1_docs_example_static.asciidoc +232 -232
  70. data/lib/starter_web/pages/public/jupyter/docs/j1-nbinteract-doc.adoc +165 -149
  71. data/lib/starter_web/pages/public/jupyter/docs/nbi-widget-manual.adoc +156 -11
  72. data/lib/starter_web/pages/public/jupyter/docs/nbinteract-doc.adoc +11 -6
  73. data/lib/starter_web/pages/public/jupyter/examples/j1-circular-times-table.adoc +136 -0
  74. data/lib/starter_web/pages/public/jupyter/examples/j1-interactive-widgets.adoc +9 -5
  75. data/lib/starter_web/pages/public/jupyter/examples/j1-odes-in-python.adoc +16 -7
  76. data/lib/starter_web/pages/public/jupyter/examples/j1-testing-plotly.adoc +95 -0
  77. data/lib/starter_web/pages/public/jupyter/examples/j1_climate-change-forecast.adoc +4 -4
  78. data/lib/starter_web/pages/public/jupyter/notebooks/j1/.ipynb_checkpoints/{algebra_with_sympy-checkpoint.ipynb → j1_circular_times_table-checkpoint.ipynb} +5190 -7291
  79. data/lib/starter_web/pages/public/jupyter/notebooks/j1/.ipynb_checkpoints/j1_climate_change_forecast-checkpoint.ipynb +2 -2
  80. data/lib/starter_web/pages/public/jupyter/notebooks/j1/.ipynb_checkpoints/j1_docs_example_dynamic-checkpoint.ipynb +1 -1
  81. data/lib/starter_web/pages/public/jupyter/notebooks/j1/.ipynb_checkpoints/j1_interactive_widgets-checkpoint.ipynb +170 -15
  82. data/lib/starter_web/pages/public/jupyter/notebooks/j1/.ipynb_checkpoints/j1_ode_selected-checkpoint.ipynb +1 -1
  83. data/lib/starter_web/pages/public/jupyter/notebooks/j1/.ipynb_checkpoints/j1_odes_in_python-checkpoint.ipynb +520 -111
  84. data/lib/starter_web/pages/public/jupyter/notebooks/j1/factor_by_factor.mp4 +0 -0
  85. data/lib/starter_web/pages/public/jupyter/notebooks/j1/{.ipynb_checkpoints/j1_algebra_with_sympy-checkpoint.ipynb → j1_circular_times_table.ipynb} +5178 -7308
  86. data/lib/starter_web/pages/public/jupyter/notebooks/j1/j1_climate_change_forecast.ipynb +2 -2
  87. data/lib/starter_web/pages/public/jupyter/notebooks/j1/j1_docs_example_dynamic.ipynb +1 -1
  88. data/lib/starter_web/pages/public/jupyter/notebooks/j1/j1_interactive_widgets.ipynb +170 -15
  89. data/lib/starter_web/pages/public/jupyter/notebooks/j1/{j1_ode_selected.ipynb → j1_odes_in_python.ipynb} +783 -34
  90. data/lib/starter_web/pages/public/jupyter/notebooks/j1/line_by_line.mp4 +0 -0
  91. data/lib/starter_web/pages/public/jupyter/notebooks/j1/point_by_point.mp4 +0 -0
  92. data/lib/starter_web/pages/public/jupyter/notebooks/nbi-docs/.ipynb_checkpoints/nbi_docs_recipes_interactive_questions-checkpoint.ipynb +185 -0
  93. data/lib/starter_web/pages/public/jupyter/notebooks/nbi-docs/.ipynb_checkpoints/nbi_docs_tutorial_interact-checkpoint.ipynb +254 -0
  94. data/lib/starter_web/pages/public/jupyter/notebooks/nbi-docs/.ipynb_checkpoints/nbi_docs_tutorial_monty_hall-checkpoint.ipynb +732 -0
  95. data/lib/starter_web/pages/public/jupyter/notebooks/nbi-docs/nbi_docs_recipes_interactive_questions.ipynb +19 -22
  96. data/lib/starter_web/pages/public/jupyter/notebooks/nbi-docs/nbi_docs_tutorial_monty_hall.ipynb +25 -26
  97. data/lib/starter_web/pages/public/jupyter/notebooks/textbooks/j1_circular_times_table.html +746 -0
  98. data/lib/starter_web/pages/public/jupyter/notebooks/textbooks/j1_climate_change_forecast.html +2 -2
  99. data/lib/starter_web/pages/public/jupyter/notebooks/textbooks/j1_interactive_widgets.html +217 -0
  100. data/lib/starter_web/pages/public/jupyter/notebooks/textbooks/j1_odes_in_python.html +955 -0
  101. data/lib/starter_web/pages/public/jupyter/notebooks/textbooks/nbi_docs_recipes_interactive_questions.html +1 -2
  102. data/lib/starter_web/pages/public/jupyter/{apis/binderhub-api.adoc → services/binderhub.adoc} +25 -28
  103. data/lib/starter_web/pages/public/jupyter/{apis/jupyterhub-api.adoc → services/jupyterhub.adoc} +8 -9
  104. data/lib/starter_web/pages/public/learn/roundtrip/100_present_images.adoc +1 -1
  105. data/lib/starter_web/pages/public/learn/roundtrip/100_present_videos.adoc +9 -15
  106. data/lib/starter_web/pages/public/learn/roundtrip/200_typography.adoc +1 -1
  107. data/lib/starter_web/pages/public/learn/roundtrip/300_icon_fonts.adoc +12 -1
  108. data/lib/starter_web/pages/public/learn/roundtrip/400_asciidoc_extensions.adoc +1 -1
  109. data/lib/starter_web/pages/public/learn/roundtrip/410_bs_modals_extentions.adoc +1 -1
  110. data/lib/starter_web/pages/public/learn/roundtrip/420_responsive_tables_extensions.adoc +1 -1
  111. data/lib/starter_web/pages/public/legal/en/300_privacy.adoc +117 -12
  112. data/lib/starter_web/pages/public/se/se-fake.adoc +47 -0
  113. data/lib/starter_web/utilsrv/_defaults/package.json +1 -1
  114. data/lib/starter_web/utilsrv/package.json +1 -1
  115. metadata +41 -41
  116. data/lib/starter_web/_data/_resources.yml +0 -1668
  117. data/lib/starter_web/assets/images/pages/nbinteract/binderhub-architecture.png +0 -0
  118. data/lib/starter_web/assets/videos/gallery/adriana-lima-poster.jpg +0 -0
  119. data/lib/starter_web/pages/public/jupyter/notebooks/binder/binder-launches.ipynb +0 -385
  120. data/lib/starter_web/pages/public/jupyter/notebooks/j1/.ipynb_checkpoints/Untitled-checkpoint.ipynb +0 -6
  121. data/lib/starter_web/pages/public/jupyter/notebooks/j1/.ipynb_checkpoints/binder-launches-checkpoint.ipynb +0 -385
  122. data/lib/starter_web/pages/public/jupyter/notebooks/j1/.ipynb_checkpoints/climate-change-forecast-checkpoint.ipynb +0 -916
  123. data/lib/starter_web/pages/public/jupyter/notebooks/j1/.ipynb_checkpoints/google_altair-checkpoint.ipynb +0 -33
  124. data/lib/starter_web/pages/public/jupyter/notebooks/j1/.ipynb_checkpoints/ipympl_test_plots-checkpoint.ipynb +0 -14517
  125. data/lib/starter_web/pages/public/jupyter/notebooks/j1/.ipynb_checkpoints/j1_altair_interactive-checkpoint.ipynb +0 -16493
  126. data/lib/starter_web/pages/public/jupyter/notebooks/j1/.ipynb_checkpoints/j1_altair_interactive_test-checkpoint.ipynb +0 -14697
  127. data/lib/starter_web/pages/public/jupyter/notebooks/j1/.ipynb_checkpoints/j1_altair_visualization-checkpoint.ipynb +0 -15358
  128. data/lib/starter_web/pages/public/jupyter/notebooks/j1/.ipynb_checkpoints/j1_altair_visualization_full-checkpoint.ipynb +0 -2576
  129. data/lib/starter_web/pages/public/jupyter/notebooks/j1/.ipynb_checkpoints/j1_climate_change_forecast.ipynb +0 -1060
  130. data/lib/starter_web/pages/public/jupyter/notebooks/j1/.ipynb_checkpoints/j1_docs_hist-checkpoint.ipynb +0 -98
  131. data/lib/starter_web/pages/public/jupyter/notebooks/j1/.ipynb_checkpoints/j1_interactive-checkpoint.ipynb +0 -560
  132. data/lib/starter_web/pages/public/jupyter/notebooks/j1/.ipynb_checkpoints/j1_ipympl_test_plots-checkpoint.ipynb +0 -14511
  133. data/lib/starter_web/pages/public/jupyter/notebooks/j1/.ipynb_checkpoints/j1_pandas_creating_reading_and_writing-checkpoint.ipynb +0 -328
  134. data/lib/starter_web/pages/public/jupyter/notebooks/j1/.ipynb_checkpoints/j1_recipes_layout-checkpoint.ipynb +0 -341
  135. data/lib/starter_web/pages/public/jupyter/notebooks/j1/.ipynb_checkpoints/nbi_docs_recipes_graphing-checkpoint.ipynb +0 -98
  136. data/lib/starter_web/pages/public/jupyter/notebooks/j1/binder-launches.ipynb +0 -411
  137. data/lib/starter_web/pages/public/jupyter/notebooks/nbi-docs/.ipynb_checkpoints/nbi_docs_examples_correlation-checkpoint.ipynb +0 -651
  138. data/lib/starter_web/pages/public/jupyter/notebooks/textbooks/binder-launches.html +0 -546
  139. data/lib/starter_web/pages/public/jupyter/notebooks/textbooks/j1_ode_selected.html +0 -186
  140. data/lib/starter_web/pages/public/jupyter/notebooks/themes/altair/excel.py +0 -55
  141. data/lib/starter_web/pages/public/jupyter/notebooks/themes/altair/ggplot.py +0 -108
  142. data/lib/starter_web/pages/public/jupyter/notebooks/themes/altair/ggplot2.py +0 -108
  143. data/lib/starter_web/pages/public/jupyter/notebooks/themes/altair/husky.py +0 -121
  144. data/lib/starter_web/pages/public/jupyter/notebooks/themes/altair/latimes.py +0 -149
  145. data/lib/starter_web/pages/public/jupyter/notebooks/themes/altair/pcolor.py +0 -6
  146. data/lib/starter_web/pages/public/jupyter/notebooks/themes/altair/quartz.py +0 -55
  147. data/lib/starter_web/pages/public/jupyter/notebooks/themes/altair/spacy_base.py +0 -94
  148. data/lib/starter_web/pages/public/jupyter/notebooks/themes/altair/spacy_mono.py +0 -158
  149. data/lib/starter_web/pages/public/jupyter/notebooks/themes/altair/sunsentinel.py +0 -125
@@ -9,7 +9,7 @@
9
9
  }
10
10
  },
11
11
  "source": [
12
- "### Initial Configuration"
12
+ "## Library Settings"
13
13
  ]
14
14
  },
15
15
  {
@@ -26,12 +26,12 @@
26
26
  "import warnings\n",
27
27
  "warnings.filterwarnings(\"ignore\")\n",
28
28
  "\n",
29
- "### General Purpose\n",
29
+ "# General Purpose\n",
30
30
  "import numpy as np\n",
31
31
  "from matplotlib import pyplot as plt\n",
32
32
  "from scipy.integrate import odeint\n",
33
33
  "\n",
34
- "### Jupyter Specifics\n",
34
+ "# Jupyter Specifics\n",
35
35
  "from IPython.display import HTML\n",
36
36
  "from ipywidgets.widgets import interact, IntSlider, FloatSlider, Layout\n",
37
37
  "\n",
@@ -45,7 +45,66 @@
45
45
  "cell_type": "markdown",
46
46
  "metadata": {},
47
47
  "source": [
48
- "### Familiar Economy"
48
+ "## Economy of a Home\n",
49
+ "\n",
50
+ "A home economy, a family, has a fixed income at the beginning of some periodic interval; usually a month. There are two kind of spendings:\n",
51
+ "\n",
52
+ "* Fixed costs \n",
53
+ "* Extraordinary expenses\n",
54
+ "\n",
55
+ "which are proportional to the money at the moment. Additionally, the family decides to set apart some proportion of the income just for fixed costs. This way, when the capital of the family is **below** this amount, the extraordinary **expenses are 0**.\n",
56
+ "\n",
57
+ "The model has the following variables:\n",
58
+ "\n",
59
+ "* *initial_salary*, the amount of money for the income\n",
60
+ "* *savings_ratio*, Proportion of the income that will be the keep just for fixed costs\n",
61
+ "* *fixed_costs*, The amount of money of fixed costs distributed per day\n",
62
+ "* *extraordinary_expenses*, Proportion of money that will be spend in extraordinary expenses.\n",
63
+ "* *days*, The time interval until the next income\n",
64
+ "\n",
65
+ "Notation for the equation:\n",
66
+ "\n",
67
+ "* $x(t)$: Capital over time\n",
68
+ "* $x(0)$ = *initial_salary*\n",
69
+ "* s= savings_ratio * initial_salary\n",
70
+ "* a = *fixed_costs*\n",
71
+ "* b = *extraordinary_expenses*\n"
72
+ ]
73
+ },
74
+ {
75
+ "cell_type": "markdown",
76
+ "metadata": {},
77
+ "source": [
78
+ "With the previously defined notation, the ordinary differential equation is as follows:\n",
79
+ "\n",
80
+ "$$\n",
81
+ "\\frac{\\mathrm{d} x}{\\mathrm{d} t} = \\left\\{\\begin{matrix} - a & x \\leq s \\\\ - b (x - s) & x > s \\end{matrix}\\right.\n",
82
+ "$$\n",
83
+ "\n",
84
+ "First, we defined a function called main for easier use of interact which will produce the interactive widget. After that, all the constants are calculated, in this case saving_limit which is analogous to s in the equation.\n"
85
+ ]
86
+ },
87
+ {
88
+ "cell_type": "markdown",
89
+ "metadata": {},
90
+ "source": [
91
+ "A nested function is defined, this function is the differential equation, it should take two parameters and return the value of $\\frac{\\mathrm{d} x}{\\mathrm{d} t}$. The first parameter can be used as the current value of x for a given t. For the numerical integration _scipy.integrate.odeint_ is used and that's why this format is required. Using a nested function has the advantage that its name doesn't conflict with the outer scope of the function containing it and that it has access to all the parameters the outer function has, avoiding unnecessary indirection due to reference.\n",
92
+ "\n",
93
+ "Then the time variable is defined and initialized, this will be the t steps. We have basically two options here:\n",
94
+ "\n",
95
+ "* Define the **start**, the **end** and the **number of steps**\n",
96
+ "* Define the **start**, the **end** and the **step**\n",
97
+ "\n",
98
+ "**Note**: It is important to note that this will determined how smooth the resulting function will be. Although at first it might seem that the integration step (usually denoted with h) is implicitly defined here, that's not the case since, as you can see in the docs of scipy.integrate.odeint, h is determined by the solver in each iteration.\n",
99
+ "\n",
100
+ "Then the _scipy.integrate.odeint_ function is called with the function defined as a first parameter, the initial conditions as the second and the window time as the third. This function returns the solution array which will be later used for the plotting."
101
+ ]
102
+ },
103
+ {
104
+ "cell_type": "markdown",
105
+ "metadata": {},
106
+ "source": [
107
+ "### Equation (Home Economy)"
49
108
  ]
50
109
  },
51
110
  {
@@ -57,24 +116,11 @@
57
116
  "start_time": "2017-08-15T00:19:29.885794Z"
58
117
  }
59
118
  },
60
- "outputs": [
61
- {
62
- "data": {
63
- "application/vnd.jupyter.widget-view+json": {
64
- "model_id": "f7e311e060664e82aa549a076e782cc7",
65
- "version_major": 2,
66
- "version_minor": 0
67
- },
68
- "text/plain": [
69
- "interactive(children=(IntSlider(value=15000, description='Initial Salary', layout=Layout(width='99%'), max=250…"
70
- ]
71
- },
72
- "metadata": {},
73
- "output_type": "display_data"
74
- }
75
- ],
119
+ "outputs": [],
76
120
  "source": [
77
- "def main(initial_salary, savings_ration, extraordinary_expenses, fixed_costs, days):\n",
121
+ "def main(initial_salary, savings_ration, \n",
122
+ " extraordinary_expenses, fixed_costs, days):\n",
123
+ "\n",
78
124
  " saving_limit = savings_ration * initial_salary\n",
79
125
  " \n",
80
126
  " def function(capital, time):\n",
@@ -104,7 +150,7 @@
104
150
  " step = 10\n",
105
151
  " rotation = \"vertical\"\n",
106
152
  " \n",
107
- " ax.set_xticklabels(np.arange(0, days + 1, step, dtype=int), rotation=rotation)\n",
153
+ " ax.set_xticklabels(np.arange(0, days + 1, step, dtype=np.int), rotation=rotation)\n",
108
154
  " ax.set_xticks(np.arange(0, days + 1, step))\n",
109
155
  " \n",
110
156
  " ax.set_yticks(np.arange(0, initial_salary * 1.1, initial_salary / 20))\n",
@@ -116,48 +162,125 @@
116
162
  " ax.legend(loc='best')\n",
117
163
  " ax.grid()\n",
118
164
  " \n",
119
- " plt.show()\n",
165
+ " plt.show()\n"
166
+ ]
167
+ },
168
+ {
169
+ "cell_type": "markdown",
170
+ "metadata": {},
171
+ "source": [
172
+ "Next, the graphics part, here matplotlib is used and this snipped is specific to this library but I will explain it in order to be self-contained.\n",
173
+ "\n",
174
+ "**Note**: I know there are plenty of plotting libraries, and many even more elegant and powerful than matplotlib but for this use case, where the complexity lies in the differential equation and not in the graphic itself, I believe it is more than enough. For complex graphics such as statistics or big data, I would recommend another library such as bqplot.\n",
175
+ "\n",
176
+ "First we define a *figure* and an *axes* object, explicitly initializing the figure size through *figsize*. Then a horizontal line with the label *Saving Limit* is plot at the heigh of the *saving_limit* and after that the solution is plot with the label *Capital(t)*.\n",
120
177
  "\n",
121
- "interact(main, initial_salary=IntSlider(min=0, max=25000, step=500, value=15000, description='Initial Salary', style=style, layout=slider_layout),\n",
122
- " savings_ration=FloatSlider(min=0, max=1, step=0.01, value=0.2, description='Savings Ratio', style=style, layout=slider_layout),\n",
123
- " extraordinary_expenses=FloatSlider(min=0, max=1, step=0.005, description='Extraordinary Expenses', style=style, value=0.3, layout=slider_layout),\n",
124
- " fixed_costs=IntSlider(min=1, max=1000, step=1, value=100, description='Fixed Costs', style=style, layout=slider_layout),\n",
125
- " days=IntSlider(min=1, max=600, step=5, value=30, description='Total Number of Days', style=style, layout=slider_layout)\n",
126
- " );"
178
+ "The if-elif-else structure defines how many sticks there will be in the x-axis and if they should be place horizontal or vertically. Then the said sticks are plotted, the same occurs with the yticks. Then the limits for each axis and the labels for each axis are set and finally, the legend position is defined and the grid is added.\n",
179
+ "\n",
180
+ "Then when *plt.show()* is called the figure is generated and showed in the screen.\n"
127
181
  ]
128
182
  },
129
183
  {
130
184
  "cell_type": "markdown",
131
185
  "metadata": {},
132
186
  "source": [
133
- "### House and Air Conditionings"
187
+ "### Evaluation (Home Economy)\n",
188
+ "\n",
189
+ "Finally, the code for the interaction, here the *interact* function from *ipywidgets* is used. A separate slider is used for each parameter with the default parameters set for a nice default visualization, with a description and the style and layout is used from the initialization cells.\n"
134
190
  ]
135
191
  },
136
192
  {
137
193
  "cell_type": "code",
138
194
  "execution_count": 3,
139
- "metadata": {
140
- "ExecuteTime": {
141
- "end_time": "2017-08-15T00:19:31.822512Z",
142
- "start_time": "2017-08-15T00:19:30.842869Z"
143
- }
144
- },
195
+ "metadata": {},
145
196
  "outputs": [
146
197
  {
147
198
  "data": {
148
199
  "application/vnd.jupyter.widget-view+json": {
149
- "model_id": "ea26e30b2de14065ab410b106377b62a",
200
+ "model_id": "398bded40362405f887c34e1e5a286c2",
150
201
  "version_major": 2,
151
202
  "version_minor": 0
152
203
  },
153
204
  "text/plain": [
154
- "interactive(children=(IntSlider(value=0, description='Initial sold Houses', layout=Layout(width='99%'), max=20…"
205
+ "interactive(children=(IntSlider(value=15000, description='Initial Salary', layout=Layout(width='99%'), max=250…"
155
206
  ]
156
207
  },
157
208
  "metadata": {},
158
209
  "output_type": "display_data"
159
210
  }
160
211
  ],
212
+ "source": [
213
+ "interact(main,\n",
214
+ " initial_salary=IntSlider(min=0, max=25000, step=500, value=15000,\n",
215
+ " description='Initial Salary', style=style, layout=slider_layout),\n",
216
+ " savings_ration=FloatSlider(min=0, max=1, step=0.01, value=0.2,\n",
217
+ " description='Savings Ratio', style=style, layout=slider_layout),\n",
218
+ " extraordinary_expenses=FloatSlider(min=0, max=1, step=0.005,\n",
219
+ " description='Extraordinary Expenses', style=style, value=0.3, layout=slider_layout),\n",
220
+ " fixed_costs=IntSlider(min=1, max=1000, step=1, value=100,\n",
221
+ " description='Fixed Costs', style=style, layout=slider_layout),\n",
222
+ " days=IntSlider(min=1, max=60, step=1, value=30,\n",
223
+ " description='Total Number of Days', style=style, layout=slider_layout)\n",
224
+ ");"
225
+ ]
226
+ },
227
+ {
228
+ "cell_type": "markdown",
229
+ "metadata": {},
230
+ "source": [
231
+ "## Sales of Houses and Air Conditionings\n",
232
+ "\n",
233
+ "In a city there are houses and air conditionings (AC) for sale and it's known that these are complementary goods, which means that if the sales of one increase the sales of the other will also increase. The number of houses sales is proportional to the number of houses that weren't sold yet and the number of AC sales is proportional to the houses sold that doesn't yet have an AC.\n",
234
+ "\n",
235
+ "The model has the following variables:\n",
236
+ "\n",
237
+ "* _initial_houses_: Number of Houses initially sold, could be 0\n",
238
+ "* _initial_ac_: Number of air conditionings sold, could be 0 and\n",
239
+ " should be less than initial_houses\n",
240
+ "* _avg_time_house_: Average number of days to sell a **house**\n",
241
+ "* _avg_time_ac_: Average number of days to sell an **AC**\n",
242
+ "* _total_houses_: Total number of **Houses for sale**\n",
243
+ "* _days_: The time interval until the **next income**\n",
244
+ "\n",
245
+ "Notation for the equation:\n",
246
+ "\n",
247
+ "* $x(t)$: Number of sold Houses\n",
248
+ "* $y(t)$: Number of sold Air Conditionings\n",
249
+ "* $x(0)$= _initial_houses_\n",
250
+ "* $y(0)$= _initial_ac_\n",
251
+ "* h = _total_houses_\n",
252
+ "* a = _avg_time_house_\n",
253
+ "* b = _avg_time_ac_\n",
254
+ "\n",
255
+ "With the previously defined notation, the ordinary differential equation is as follows:\n"
256
+ ]
257
+ },
258
+ {
259
+ "cell_type": "markdown",
260
+ "metadata": {},
261
+ "source": [
262
+ "$$\n",
263
+ "\\left\\{\\begin{matrix} \\frac{\\mathrm{d} x}{\\mathrm{d} t} =\\frac{1}{a} (h - x) \\\\\\\\ \\frac{\\mathrm{d} y}{\\mathrm{d} t} =\\frac{1}{b} (x - y) \\end{matrix}\\right.\n",
264
+ "$$"
265
+ ]
266
+ },
267
+ {
268
+ "cell_type": "markdown",
269
+ "metadata": {},
270
+ "source": [
271
+ "### Equation (Homes and ACs)"
272
+ ]
273
+ },
274
+ {
275
+ "cell_type": "code",
276
+ "execution_count": 4,
277
+ "metadata": {
278
+ "ExecuteTime": {
279
+ "end_time": "2017-08-15T00:19:31.822512Z",
280
+ "start_time": "2017-08-15T00:19:30.842869Z"
281
+ }
282
+ },
283
+ "outputs": [],
161
284
  "source": [
162
285
  "def main(initial_houses, initial_ac, avg_time_house, avg_time_ac, total_houses, days):\n",
163
286
  "\n",
@@ -190,7 +313,7 @@
190
313
  " step = 10\n",
191
314
  " rotation = \"vertical\"\n",
192
315
  " \n",
193
- " ax.set_xticklabels(np.arange(0, days + 1, step, dtype=int), rotation=rotation)\n",
316
+ " ax.set_xticklabels(np.arange(0, days + 1, step, dtype=np.int), rotation=rotation)\n",
194
317
  " ax.set_xticks(np.arange(0, days + 1, step))\n",
195
318
  " \n",
196
319
  " ax.set_yticks(np.arange(0, total_houses * 1.1, total_houses / 20))\n",
@@ -202,43 +325,41 @@
202
325
  " ax.legend(loc='best')\n",
203
326
  " ax.grid()\n",
204
327
  " \n",
205
- " plt.show()\n",
328
+ " plt.show()\n"
329
+ ]
330
+ },
331
+ {
332
+ "cell_type": "markdown",
333
+ "metadata": {},
334
+ "source": [
335
+ "In this scenario and the followings the code will be explain where it differs from the first example to avoid unnecesary repetition.\n",
336
+ "\n",
337
+ "In this case the constants *avg_time_house* and *avg_time_ac* are used directly inside the function since it is much clearer this way. To define a system of ODEs, first the initial condition should be a list, each element of the list represents the initial condition for each of the variables. The nested function also changes a bit, in order to work, the first parameter would also be a list so it is necessary to unpack it into the variables and then a variable *dydt* is used to represent the system where each element is the left side of each equation in canonical form.\n",
206
338
  "\n",
207
- "interact(main, initial_houses=IntSlider(min=0, max=2000, step=10, value=0, description='Initial sold Houses', style=style, layout=slider_layout),\n",
208
- " initial_ac=IntSlider(min=0, max=2000, step=10, value=0, description='Initial sold AC', style=style, layout=slider_layout),\n",
209
- " total_houses=IntSlider(min=1, max=2000, step=100, value=1000, description='Total Houses', style=style, layout=slider_layout),\n",
210
- " avg_time_house=FloatSlider(min=0.1, max=24, step=0.1, value=2, description='Time for House', style=style, layout=slider_layout),\n",
211
- " avg_time_ac=FloatSlider(min=0.1, max=24, step=0.1, value=4, description='Time for AC', style=style, layout=slider_layout),\n",
212
- " days=IntSlider(min=1, max=360, step=10, value=30, description='Total Number of Days', style=style, layout=slider_layout),\n",
213
- " );"
339
+ "Finally the *dydt* variable is returned. The definition of *time* is the same as previously seen and the solution variable is now a nested array containing the solution for both variables. This is specially useful when plotting."
214
340
  ]
215
341
  },
216
342
  {
217
343
  "cell_type": "markdown",
218
344
  "metadata": {},
219
345
  "source": [
220
- "### Stock Control"
346
+ "### Evaluation (Homes and ACs)"
221
347
  ]
222
348
  },
223
349
  {
224
350
  "cell_type": "code",
225
- "execution_count": 4,
226
- "metadata": {
227
- "ExecuteTime": {
228
- "end_time": "2017-08-15T00:19:31.822512Z",
229
- "start_time": "2017-08-15T00:19:30.842869Z"
230
- }
231
- },
351
+ "execution_count": 5,
352
+ "metadata": {},
232
353
  "outputs": [
233
354
  {
234
355
  "data": {
235
356
  "application/vnd.jupyter.widget-view+json": {
236
- "model_id": "35a5060ce6014c46ab98d7a55666f9e4",
357
+ "model_id": "7b2efc55994c46df96bc20ef70695541",
237
358
  "version_major": 2,
238
359
  "version_minor": 0
239
360
  },
240
361
  "text/plain": [
241
- "interactive(children=(IntSlider(value=4, description='Desired Stock', layout=Layout(width='99%'), min=1, style…"
362
+ "interactive(children=(IntSlider(value=0, description='Initial sold Houses', layout=Layout(width='99%'), max=20…"
242
363
  ]
243
364
  },
244
365
  "metadata": {},
@@ -246,13 +367,98 @@
246
367
  }
247
368
  ],
248
369
  "source": [
249
- "def main(desired_stock, initial_stock, initial_request, stock_control, market_demand, provider_delay, days):\n",
370
+ "interact(main,\n",
371
+ " initial_houses=IntSlider(min=0, max=2000, step=10, value=0,\n",
372
+ " description='Initial sold Houses', style=style, layout=slider_layout),\n",
373
+ " initial_ac=IntSlider(min=0, max=2000, step=10, value=0,\n",
374
+ " description='Initial sold AC', style=style, layout=slider_layout),\n",
375
+ " total_houses=IntSlider(min=1, max=2000, step=100, value=1000,\n",
376
+ " description='Total Houses', style=style, layout=slider_layout),\n",
377
+ " avg_time_house=FloatSlider(min=0.1, max=24, step=0.1, value=2,\n",
378
+ " description='Time for House', style=style, layout=slider_layout),\n",
379
+ " avg_time_ac=FloatSlider(min=0.1, max=24, step=0.1, value=4,\n",
380
+ " description='Time for AC', style=style, layout=slider_layout),\n",
381
+ " days=IntSlider(min=1, max=360, step=10, value=30,\n",
382
+ " description='Total Number of Days', style=style, layout=slider_layout),\n",
383
+ ");"
384
+ ]
385
+ },
386
+ {
387
+ "cell_type": "markdown",
388
+ "metadata": {},
389
+ "source": [
390
+ "## Stock Control\n",
391
+ "\n",
392
+ "A company wants a desired stock, they started with an initial stock and they work with a provider which sends deliveries goods through sales orders. The company asks the provider each day a sales order proportional to the missing or surplus quantity to the desired stock and the market demand. \n",
393
+ "\n",
394
+ "The provider deliver the goods according to the sales order with a constant delay. Finally, the market demand is consider constant. The company wants to know how their stock and their request to the provider will behave and they will try to avoid alternating behavior, a oscillation in stock.\n",
395
+ "\n",
396
+ "The model has the following variables:\n",
397
+ "\n",
398
+ "* _desired_stock_: Amount of stock the company wants to have.\n",
399
+ "* _initial_stock_: The initial amount of stock of the company.\n",
400
+ "* _initial_orders_: initial amount of goods asked in sales orders.\n",
401
+ "* _stock_control_: Proportion of the missing/surplus stock to ask to the provider.\n",
402
+ "* _market_demand_: The daily demand of the market\n",
403
+ "* _provider_delay_: The number of days of the provider delay.\n",
404
+ "* _days_: The total number of days the model will analyse.\n",
405
+ "\n",
406
+ "Notation for the equation:\n",
407
+ "\n",
408
+ "* $x(t)$: Number of goods in stock\n",
409
+ "* $y(t)$: Number of pending sales order sent to the provider\n",
410
+ "* $x(0)$ = _initial_stock_\n",
411
+ "* $y(0)$ = _initial_orders_\n",
412
+ "* s = _desired_stock_\n",
413
+ "* d = _market_demand_\n",
414
+ "* k = _stock_control_\n",
415
+ "* p = _provider_delay_\n"
416
+ ]
417
+ },
418
+ {
419
+ "cell_type": "markdown",
420
+ "metadata": {},
421
+ "source": [
422
+ "With the previously defined notation, the ordinary differential equation is as follows:\n",
423
+ "\n",
424
+ "$$\n",
425
+ "\\left\\{\\begin{matrix} \\frac{\\mathrm{d} x}{\\mathrm{d} t} =& \\frac{1}{p} y - d \\\\\\\\ \\frac{\\mathrm{d} y}{\\mathrm{d} t} =& - \\frac{1}{p} y + d + k ( s - x ) \\end{matrix}\\right.\n",
426
+ "$$\n",
427
+ "\n",
428
+ "This time the code is only changed in the variables names and the equations but it is very similar to the previous example, the particularity of this model doesn't lie in the code but rather in the behavior, since it can show the differences between an **oscillation** behavior and a damped one. Going through all kinds of possibilities such as underdamped, overdamped, critically damped and undamped. I encourage you to experiment with the parameters in the widget.\n"
429
+ ]
430
+ },
431
+ {
432
+ "cell_type": "markdown",
433
+ "metadata": {},
434
+ "source": [
435
+ "### Equation (Stock Control)"
436
+ ]
437
+ },
438
+ {
439
+ "cell_type": "code",
440
+ "execution_count": 6,
441
+ "metadata": {
442
+ "ExecuteTime": {
443
+ "end_time": "2017-08-15T00:19:31.822512Z",
444
+ "start_time": "2017-08-15T00:19:30.842869Z"
445
+ }
446
+ },
447
+ "outputs": [],
448
+ "source": [
449
+ "def main(desired_stock, initial_stock,\n",
450
+ " initial_request, stock_control, market_demand, \n",
451
+ " provider_delay, days):\n",
250
452
  " \n",
251
453
  " def function(v0, time):\n",
252
454
  " x, y = v0\n",
455
+ "\n",
456
+ " # dx/dt -> Change in Stock\n",
457
+ " # dy/dt -> Change in Requests\n",
458
+ " #\n",
253
459
  " dydt = [\n",
254
- " (1 / provider_delay) * y - market_demand, # dx/dt -> Change in Stock\n",
255
- " - (1 / provider_delay) * y + market_demand + stock_control * (desired_stock - x) # dy/dt -> Change in Requests\n",
460
+ " (1 / provider_delay) * y - market_demand,\n",
461
+ " - (1 / provider_delay) * y + market_demand + stock_control * (desired_stock - x)\n",
256
462
  " ]\n",
257
463
  " return dydt\n",
258
464
  " \n",
@@ -260,7 +466,8 @@
260
466
  " initial_conditions = [initial_stock, initial_request]\n",
261
467
  " solution = odeint(function, initial_conditions, time)\n",
262
468
  "\n",
263
- " #Graphic details\n",
469
+ " # Graphic details\n",
470
+ " #\n",
264
471
  " fig, ax = plt.subplots(figsize=(15, 10))\n",
265
472
  " \n",
266
473
  " ax.plot(time, solution[:, 0], label='Stock(t)')\n",
@@ -277,7 +484,7 @@
277
484
  " step = 10\n",
278
485
  " rotation = \"vertical\"\n",
279
486
  " \n",
280
- " ax.set_xticklabels(np.arange(0, days + 1, step, dtype=int), rotation=rotation)\n",
487
+ " ax.set_xticklabels(np.arange(0, days + 1, step, dtype=np.int), rotation=rotation)\n",
281
488
  " ax.set_xticks(np.arange(0, days + 1, step))\n",
282
489
  " \n",
283
490
  " ax.set_xlim([0, days])\n",
@@ -288,51 +495,109 @@
288
495
  " ax.grid()\n",
289
496
  " \n",
290
497
  " plt.show()\n",
291
- " \n",
292
- "\n",
293
- "interact(main,\n",
294
- " desired_stock=IntSlider(min=1, max=100, step=1, value=4, description='Desired Stock', style=style, layout=slider_layout),\n",
295
- " initial_stock=IntSlider(min=1, max=100, step=1, value=8, description='Initial Stock', style=style, layout=slider_layout),\n",
296
- " initial_request=IntSlider(min=1, max=100, step=1, value=14, description='Initial Requests', style=style, layout=slider_layout),\n",
297
- " stock_control=FloatSlider(min=0, max=2, step=0.001, value=1.5, description='Stock Control', style=style, layout=slider_layout),\n",
298
- " market_demand=FloatSlider(min=0, max=24, step=0.01, value=3, description='Market Demand', style=style, layout=slider_layout),\n",
299
- " provider_delay=FloatSlider(min=0, max=10, step=0.1, value=4, description='Provider Delay', style=style, layout=slider_layout),\n",
300
- " days=IntSlider(min=1, max=360, step=10, value=50, description='Total Number of Days', style=style, layout=slider_layout),\n",
301
- " );"
498
+ " "
302
499
  ]
303
500
  },
304
501
  {
305
502
  "cell_type": "markdown",
306
503
  "metadata": {},
307
504
  "source": [
308
- "### Useful life"
505
+ "### Evaluation (Stock Control)"
309
506
  ]
310
507
  },
311
508
  {
312
509
  "cell_type": "code",
313
- "execution_count": 5,
314
- "metadata": {
315
- "ExecuteTime": {
316
- "end_time": "2017-08-15T00:19:35.290946Z",
317
- "start_time": "2017-08-15T00:19:31.830523Z"
318
- }
319
- },
510
+ "execution_count": 7,
511
+ "metadata": {},
320
512
  "outputs": [
321
513
  {
322
514
  "data": {
323
515
  "application/vnd.jupyter.widget-view+json": {
324
- "model_id": "51fca84599804ca3b25512d15c1ef2db",
516
+ "model_id": "10e1c36ac5624de29d44457eb99567a0",
325
517
  "version_major": 2,
326
518
  "version_minor": 0
327
519
  },
328
520
  "text/plain": [
329
- "interactive(children=(FloatSlider(value=3.8, description='Useful Life (hs)', layout=Layout(width='99%'), max=2…"
521
+ "interactive(children=(IntSlider(value=4, description='Desired Stock', layout=Layout(width='99%'), min=1, style…"
330
522
  ]
331
523
  },
332
524
  "metadata": {},
333
525
  "output_type": "display_data"
334
526
  }
335
527
  ],
528
+ "source": [
529
+ "interact(main,\n",
530
+ " desired_stock=IntSlider(min=1, max=100, step=1, value=4,\n",
531
+ " description='Desired Stock', style=style, layout=slider_layout),\n",
532
+ " initial_stock=IntSlider(min=1, max=100, step=1, value=8,\n",
533
+ " description='Initial Stock', style=style, layout=slider_layout),\n",
534
+ " initial_request=IntSlider(min=1, max=100, step=1, value=14,\n",
535
+ " description='Initial Requests', style=style, layout=slider_layout),\n",
536
+ " stock_control=FloatSlider(min=0, max=2, step=0.001, value=1.5,\n",
537
+ " description='Stock Control', style=style, layout=slider_layout),\n",
538
+ " market_demand=FloatSlider(min=0, max=24, step=0.01, value=3,\n",
539
+ " description='Market Demand', style=style, layout=slider_layout),\n",
540
+ " provider_delay=FloatSlider(min=0, max=10, step=0.1, value=4,\n",
541
+ " description='Provider Delay', style=style, layout=slider_layout),\n",
542
+ " days=IntSlider(min=1, max=360, step=10, value=50,\n",
543
+ " description='Total Number of Days', style=style, layout=slider_layout),\n",
544
+ ");"
545
+ ]
546
+ },
547
+ {
548
+ "cell_type": "markdown",
549
+ "metadata": {},
550
+ "source": [
551
+ "## Useful life\n",
552
+ "\n",
553
+ "A patient takes a certain drug with a recipe, the recipe says how many milligrams the patient should have per intake, how often the intakes should be and how many. Additionally the drug itself provides information about its useful life which helps to determine the optimal interval between intakes. It's also known that the useful life of the drug follows a natural decay.\n",
554
+ "\n",
555
+ "The model has the following variables:\n",
556
+ "\n",
557
+ "* _useful_life_: Duration of the useful life of the drug in hours\n",
558
+ "* _intake_mg_: Amount of milligrams per intake.\n",
559
+ "* _intake_interval_: Time interval in hours between intakes.\n",
560
+ "* _intake_number_: Number of intakes.\n",
561
+ "* _hours_: The total number of hours the model will analyse.\n",
562
+ "\n",
563
+ "Notation for the equation:\n",
564
+ "\n",
565
+ "* $x(t)$: Milligrams of drug in the body\n",
566
+ "* $x(0)$: _intake_mg_\n",
567
+ "* a = _useful_life_\n",
568
+ "\n",
569
+ "With the previously defined notation, the ordinary differential equation is as follows:\n",
570
+ "\n",
571
+ "$$\n",
572
+ "\\frac{\\mathrm{d} x}{\\mathrm{d} t} = - \\frac{1}{a} ln(2) y\n",
573
+ "$$\n"
574
+ ]
575
+ },
576
+ {
577
+ "cell_type": "markdown",
578
+ "metadata": {},
579
+ "source": [
580
+ "\n",
581
+ "**Note**: the expression $ln(2)$ is part of the **natural decay formula**.\n"
582
+ ]
583
+ },
584
+ {
585
+ "cell_type": "markdown",
586
+ "metadata": {},
587
+ "source": [
588
+ "### Equation (Useful life)"
589
+ ]
590
+ },
591
+ {
592
+ "cell_type": "code",
593
+ "execution_count": 8,
594
+ "metadata": {
595
+ "ExecuteTime": {
596
+ "end_time": "2017-08-15T00:19:35.290946Z",
597
+ "start_time": "2017-08-15T00:19:31.830523Z"
598
+ }
599
+ },
600
+ "outputs": [],
336
601
  "source": [
337
602
  "def main(useful_life, intake_mg, intake_interval, intake_number, hours):\n",
338
603
  " \n",
@@ -375,7 +640,7 @@
375
640
  " step = 10\n",
376
641
  " rotation = \"vertical\"\n",
377
642
  " \n",
378
- " ax.set_xticklabels(np.arange(0, hours + 1, step, dtype=int), rotation=rotation)\n",
643
+ " ax.set_xticklabels(np.arange(0, hours + 1, step, dtype=np.int), rotation=rotation)\n",
379
644
  " ax.set_xticks(np.arange(0, hours + 1, step))\n",
380
645
  " \n",
381
646
  " ax.set_xlim([0, hours])\n",
@@ -385,27 +650,152 @@
385
650
  " ax.legend(loc='best')\n",
386
651
  " ax.grid()\n",
387
652
  " \n",
388
- " plt.show()\n",
653
+ " plt.show()\n"
654
+ ]
655
+ },
656
+ {
657
+ "cell_type": "markdown",
658
+ "metadata": {},
659
+ "source": [
660
+ "This model doesn't introduces complexity in the ODE but rather in the way one can model the successive intakes. It is usually helpful to keep this 'iteration logic' independent from the ODE itself, that's why no particular changes are needed in the equations.\n",
661
+ "\n",
662
+ "There are many ways for achieving this but the one I used is the following:\n",
389
663
  "\n",
664
+ "1. Create a list with all the intake hours\n",
665
+ "2. Create an empty list, times, for the times\n",
666
+ "3. Create an empty list, solutions for the solutions\n",
667
+ "4. Iterate through that list\n",
668
+ " * Create a time array starting in the time iterated and ended in the time\n",
669
+ " iterated + the intake_interval\n",
670
+ " * Solve the ODE with the initial_condition and the previously created time\n",
671
+ " * Update the value of the initial_conditions with the final solution\n",
672
+ " * Append the solution list to the end of the solutions list\n",
673
+ " * Append the time list to the end of the times list\n",
674
+ "5. Create a time array starting from the last the last time of intakes\n",
675
+ " to 10 times the intake_interval\n",
676
+ "6. Solve the ODE again with a longer interval to see how it behaves\n",
677
+ " after the iterations\n",
678
+ "7. Append the solution list to the end of the solutions list\n",
679
+ "8. Append the time list to the end of the times list\n",
680
+ "9. Proceed to Plotting\n",
681
+ "\n",
682
+ "This approach consist in solving several ODEs, each of which receives the final solution of the previous as its initial conditions."
683
+ ]
684
+ },
685
+ {
686
+ "cell_type": "markdown",
687
+ "metadata": {},
688
+ "source": [
689
+ "### Evaluation (Useful life)"
690
+ ]
691
+ },
692
+ {
693
+ "cell_type": "code",
694
+ "execution_count": 9,
695
+ "metadata": {
696
+ "scrolled": true
697
+ },
698
+ "outputs": [
699
+ {
700
+ "data": {
701
+ "application/vnd.jupyter.widget-view+json": {
702
+ "model_id": "b99aec4c67464c42a75af50162cb6433",
703
+ "version_major": 2,
704
+ "version_minor": 0
705
+ },
706
+ "text/plain": [
707
+ "interactive(children=(FloatSlider(value=3.8, description='Useful Life', layout=Layout(width='99%'), max=24.0, …"
708
+ ]
709
+ },
710
+ "metadata": {},
711
+ "output_type": "display_data"
712
+ }
713
+ ],
714
+ "source": [
390
715
  "interact(main, \n",
391
- " useful_life=FloatSlider(min=0, max=24, step=0.01, value=3.8, description='Useful Life (hs)', style=style, layout=slider_layout),\n",
392
- " intake_mg=FloatSlider(min=0, max=1, step=0.001, value=0.01, description='Miligrams per Intake', style=style, layout=slider_layout),\n",
393
- " intake_interval=FloatSlider(min=0, max=24, step=0.1, value=6, description='Hours between Intakes', style=style, layout=slider_layout),\n",
394
- " intake_number=IntSlider(min=1, max=20, step=1, value=4, description='Number of Intakes', style=style, layout=slider_layout),\n",
395
- " hours=FloatSlider(min=1, max=240, step=0.5, value=40, description='Total number of Hours', style=style, layout=slider_layout),\n",
396
- " );"
716
+ " useful_life=FloatSlider(min=0, max=24, step=0.01, value=3.8,\n",
717
+ " description='Useful Life', style=style, layout=slider_layout),\n",
718
+ " intake_mg=FloatSlider(min=0, max=1, step=0.001, value=0.01,\n",
719
+ " description='Miligrams per Intake', style=style, layout=slider_layout),\n",
720
+ " intake_interval=FloatSlider(min=0, max=24, step=0.1, value=6,\n",
721
+ " description='Hours between Intakes', style=style, layout=slider_layout),\n",
722
+ " intake_number=IntSlider(min=1, max=20, step=1, value=4,\n",
723
+ " description='Number of Intakes', style=style, layout=slider_layout),\n",
724
+ " hours=FloatSlider(min=1, max=240, step=0.5, value=40,\n",
725
+ " description='Total number of Hours', style=style, layout=slider_layout),\n",
726
+ ");"
397
727
  ]
398
728
  },
399
729
  {
400
730
  "cell_type": "markdown",
401
731
  "metadata": {},
402
732
  "source": [
403
- "### Foxes and Rabbits"
733
+ "## Foxes and Rabbits\n",
734
+ "\n",
735
+ "This is the model known as *predator–prey* or *Lotka–Volterra* equations. There are two species, a predator and a prey, like foxes and rabbits. Each has a certain birthrate and a deathrate. The birthrate of the prey is proportional to its current population and the birthrate of the predator is proportional to both its population and the prey population. The deathrate of the prey is proportional to both its population and the predator population and the deathrate of the predator is proportional to its population.\n",
736
+ "\n",
737
+ "The model has the following variables:\n",
738
+ "\n",
739
+ "* *rabbits_birthrate*: Rabbits birthrate\n",
740
+ "* *rabbits_deathrate*: Rabbits deathrate\n",
741
+ "* *foxes_birthrate*: Foxes birthrate\n",
742
+ "* *initial_rabbits*: Initial rabbits\n",
743
+ "* *initial_foxes*: Initial foxes\n",
744
+ "* *days*: The total number of days the model will analyse\n",
745
+ "\n",
746
+ "Notation for the equation:\n",
747
+ "\n",
748
+ "* $x(t)$: Population of Rabbits over time\n",
749
+ "* $y(t)$: Population of Foxes over time\n",
750
+ "* $x(0)$ = *initial_rabbits*\n",
751
+ "* $y(0)$ = *initial_foxes*\n",
752
+ "* a = *rabbits_birthrate*\n",
753
+ "* b = *rabbits_deathrate*\n",
754
+ "* c = *foxes_birthrate*\n",
755
+ "* d = *foxes_deathrate*\n"
756
+ ]
757
+ },
758
+ {
759
+ "cell_type": "markdown",
760
+ "metadata": {},
761
+ "source": [
762
+ "With the previously defined notation, the ordinary differential equation is as follows:\n",
763
+ "\n",
764
+ "$$\n",
765
+ "\\left\\{\\begin{matrix} \\frac{\\mathrm{d} x}{\\mathrm{d} t} =& a x &-& bxy\\\\\\\\ \\frac{\\mathrm{d} y}{\\mathrm{d} t} =& cxy &-& dy \\end{matrix}\\right.\n",
766
+ "$$\n"
767
+ ]
768
+ },
769
+ {
770
+ "cell_type": "markdown",
771
+ "metadata": {},
772
+ "source": [
773
+ "Or more concisely:\n",
774
+ "\n",
775
+ "$$\n",
776
+ "\\left\\{\\begin{matrix} \\frac{\\mathrm{d} x}{\\mathrm{d} t} =& x (a - by)\\\\\\\\ \\frac{\\mathrm{d} y}{\\mathrm{d} t} =& y (cx - d) \\end{matrix}\\right.\n",
777
+ "$$\n"
778
+ ]
779
+ },
780
+ {
781
+ "cell_type": "markdown",
782
+ "metadata": {},
783
+ "source": [
784
+ "**Note**: The *Lotka-Volterra equations* are a pair of first-order nonlinear differential\n",
785
+ "equations, frequently used to describe the dynamics of biological systems in which\n",
786
+ "two species interact, one as a predator and the other as prey.\n"
787
+ ]
788
+ },
789
+ {
790
+ "cell_type": "markdown",
791
+ "metadata": {},
792
+ "source": [
793
+ "### Equation (Foxes and Rabbits)"
404
794
  ]
405
795
  },
406
796
  {
407
797
  "cell_type": "code",
408
- "execution_count": 6,
798
+ "execution_count": 10,
409
799
  "metadata": {
410
800
  "ExecuteTime": {
411
801
  "end_time": "2017-08-15T00:19:36.846923Z",
@@ -415,7 +805,9 @@
415
805
  },
416
806
  "outputs": [],
417
807
  "source": [
418
- "def main(rabbits_birthrate, rabbits_deathrate, foxes_birthrate, foxes_deathrate, initial_rabbits, foxes_inicial, days):\n",
808
+ "def main(rabbits_birthrate, rabbits_deathrate,\n",
809
+ " foxes_birthrate, foxes_deathrate, \n",
810
+ " initial_rabbits, initial_foxes, days):\n",
419
811
  "\n",
420
812
  " def function(s, t):\n",
421
813
  " x, y = s\n",
@@ -427,10 +819,11 @@
427
819
  " return dydt\n",
428
820
  " \n",
429
821
  " time = np.arange(0, days, 0.01)\n",
430
- " initial_conditions = [initial_rabbits, foxes_inicial]\n",
822
+ " initial_conditions = [initial_rabbits, initial_foxes]\n",
431
823
  " solution = odeint(function, initial_conditions, time)\n",
432
824
  "\n",
433
- " #Graphic details\n",
825
+ " # Graphic details\n",
826
+ " #\n",
434
827
  " fig, axes = plt.subplots(1, 2, figsize=(15, 10))\n",
435
828
  " \n",
436
829
  " ax = axes[0]\n",
@@ -448,7 +841,7 @@
448
841
  " step = 10\n",
449
842
  " rotation = \"vertical\"\n",
450
843
  " \n",
451
- " ax.set_xticklabels(np.arange(0, days + 1, step, dtype=int), rotation=rotation)\n",
844
+ " ax.set_xticklabels(np.arange(0, days + 1, step, dtype=np.int), rotation=rotation)\n",
452
845
  " ax.set_xticks(np.arange(0, days + 1, step))\n",
453
846
  " \n",
454
847
  " ax.set_xlim([0, days])\n",
@@ -457,8 +850,7 @@
457
850
  " ax.set_ylabel('Population')\n",
458
851
  " ax.legend(loc='best')\n",
459
852
  " ax.grid()\n",
460
- " \n",
461
- " \n",
853
+ " \n",
462
854
  " ax = axes[1]\n",
463
855
  " \n",
464
856
  " ax.plot(solution[:, 0], solution[:, 1], label='Foxes vs Rabbits')\n",
@@ -471,18 +863,27 @@
471
863
  " ax.grid()\n",
472
864
  " \n",
473
865
  " plt.tight_layout()\n",
474
- " plt.show()"
866
+ " plt.show()\n"
475
867
  ]
476
868
  },
477
869
  {
478
- "cell_type": "code",
479
- "execution_count": 7,
870
+ "cell_type": "markdown",
480
871
  "metadata": {},
872
+ "source": [
873
+ "### Evaluation (Foxes and Rabbits)"
874
+ ]
875
+ },
876
+ {
877
+ "cell_type": "code",
878
+ "execution_count": 11,
879
+ "metadata": {
880
+ "scrolled": true
881
+ },
481
882
  "outputs": [
482
883
  {
483
884
  "data": {
484
885
  "application/vnd.jupyter.widget-view+json": {
485
- "model_id": "56c139c989b14702be053bc986334ae5",
886
+ "model_id": "8432a49d585548b1841907d05dda3222",
486
887
  "version_major": 2,
487
888
  "version_minor": 0
488
889
  },
@@ -495,14 +896,22 @@
495
896
  }
496
897
  ],
497
898
  "source": [
498
- "interact(main, rabbits_birthrate=FloatSlider(min=0, max=25, step=1, value=1, description='Birth Rate of Rabbits', style=style, layout=slider_layout),\n",
499
- " rabbits_deathrate=FloatSlider(min=0, max=25, step=1, value=1, description='Death Rate of Rabbits', style=style, layout=slider_layout),\n",
500
- " foxes_birthrate=FloatSlider(min=0, max=25, step=1, value=1, description='Birth Rate of Foxes', style=style, layout=slider_layout),\n",
501
- " foxes_deathrate=FloatSlider(min=0, max=25, step=1, value=1, description='Death Rate of Foxes', style=style, layout=slider_layout),\n",
502
- " initial_rabbits=FloatSlider(min=0 , max=100, step=1, value=2, description='Initial Rabbits', style=style, layout=slider_layout),\n",
503
- " foxes_inicial=FloatSlider(min=0 , max=100, step=1, value=1, description='Initial Foxes', style=style, layout=slider_layout),\n",
504
- " days=FloatSlider(min=0 ,max=365 , step=10, value=15, description='Total number of Days', style=style, layout=slider_layout),\n",
505
- " );"
899
+ "interact(main,\n",
900
+ " rabbits_birthrate=FloatSlider(min=0, max=24, step=0.01, value=1,\n",
901
+ " description='Birth Rate of Rabbits', style=style, layout=slider_layout),\n",
902
+ " rabbits_deathrate=FloatSlider(min=0, max=24, step=0.01, value=1,\n",
903
+ " description='Death Rate of Rabbits', style=style, layout=slider_layout),\n",
904
+ " foxes_birthrate=FloatSlider(min=0, max=24, step=0.01, value=1,\n",
905
+ " description='Birth Rate of Foxes', style=style, layout=slider_layout),\n",
906
+ " foxes_deathrate=FloatSlider(min=0, max=24, step=0.01, value=1,\n",
907
+ " description='Death Rate of Foxes', style=style, layout=slider_layout),\n",
908
+ " initial_rabbits=FloatSlider(min=0 , max=100, step=1, value=2,\n",
909
+ " description='Initial Rabbits', style=style, layout=slider_layout),\n",
910
+ " initial_foxes=FloatSlider(min=0 , max=100, step=1, value=1,\n",
911
+ " description='Initial Foxes', style=style, layout=slider_layout),\n",
912
+ " days=FloatSlider(min=0 ,max=365 , step=10, value=15,\n",
913
+ " description='Total number of Days', style=style, layout=slider_layout),\n",
914
+ ");"
506
915
  ]
507
916
  }
508
917
  ],