diff --git a/book/_toc.yml b/book/_toc.yml index 17ebf32850e43599db649aa095b71f5c8835c0b4..32719929f6bc5cb501bcb8db98ac25a470df7c52 100644 --- a/book/_toc.yml +++ b/book/_toc.yml @@ -67,6 +67,7 @@ parts: - file: cookbook/benchmarks/benchmark_load_dont_execute.ipynb - file: cookbook/widgets_dont_execute.ipynb - file: cookbook/exercise_checking_dont_execute.ipynb + - file: cookbook/example_gumbel_dont_execute.ipynb - caption: Old Material chapters: - file: old/blank diff --git a/book/cookbook/example_gumbel.py b/book/cookbook/example_gumbel.py new file mode 100644 index 0000000000000000000000000000000000000000..e8fa8cf322649f6d95a9205ec715860f97eac673 --- /dev/null +++ b/book/cookbook/example_gumbel.py @@ -0,0 +1,35 @@ +from grading import check +from math import isclose + +tolerance = 0.001 + +# Using rel_tol is more reliable in the face of aliasing, but to fit the instructions give we use abs_total +check_float = lambda a, b: isclose(a, b, rel_tol=0, abs_tol=tolerance) + +# We have to pass in the globals object since we need to have access to changes as well +@check +def check_example(glob): + mu, beta = glob["mu"], glob["beta"] + if (check_float(mu, 5.0) and check_float(beta, 3.0)): + print(f"You got the parameters right, well done! (checked with tolerance {tolerance})") + else: + print(f"Your parameters are incorrect, your inverse won't be graded until these are right. (checked with tolerance {tolerance})") + return + + function = glob["find_x_with_probability_p"] + + test_inputs = [(0.1, 2.49790266426), (0.2, 3.57234501402), (0.9, 11.7511019819)] + failed = [] + + for x, out in test_inputs: + result = function(x) + if not check_float(result, out): + failed.append((x, out, result)) + + if len(failed) == 0: + print(f"Well done, your inverse function is correct! (checked with tolerance {tolerance})") + else: + print(f"Your function failed some tests. Keep in mind the tolerance is {tolerance}") + print("Failed inputs:") + for case in failed: + print(f"{case[0]} gave {case[2]}, expected {case[1]}") \ No newline at end of file diff --git a/book/cookbook/example_gumbel_dont_execute.ipynb b/book/cookbook/example_gumbel_dont_execute.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..023869937a18e0f5c950e4189ee7b89d35b101b5 --- /dev/null +++ b/book/cookbook/example_gumbel_dont_execute.ipynb @@ -0,0 +1,143 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Gumbel Distribution Exercise" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "thebe-init" + ] + }, + "outputs": [], + "source": [ + "%pip install ipywidgets\n", + "\n", + "import matplotlib.pyplot as plt\n", + "from math import log, e\n", + "import numpy as np\n", + "from example_gumbel import check_example" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "thebe-init" + ] + }, + "outputs": [], + "source": [ + "x_1 = 4\n", + "p_e_1 = 0.7523186963342055\n", + "x_2 = 10\n", + "p_e_2 = 0.17211051260760846" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "def gumbel_2_points(x_1, p_e_1, x_2, p_e_2): \n", + " \"\"\"Compute Gumbel distribution parameters from two points of the CDF.\n", + " Arguments:\n", + " x_1 (float): point one\n", + " p_e_1 (float): probability of exceedance for point one\n", + " x_2 (float): point two\n", + " p_e_2 (float): probability of exceedance for point two\n", + " \"\"\"\n", + "\n", + " # YOUR CODE GOES HERE #\n", + " beta = _\n", + " mu = _\n", + " #######################\n", + " return mu, beta" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mu, beta = gumbel_2_points(x_1, p_e_1, x_2, p_e_2)\n", + "\n", + "print(f\"Your mu: {mu}\\nYour beta: {beta}\")\n", + "\n", + "gumbel_distribution = lambda x: e**(-e**(-(x-mu)/beta))\n", + "\n", + "plt.title(\"Gumbel distribution\")\n", + "plt.ylabel(\"Cumulative probability\")\n", + "plt.grid(color='black', linestyle='-', linewidth=0.1)\n", + "plt.plot(x_1, 1-p_e_1, 'ro')\n", + "plt.annotate(\"Point 1\", (x_1 + 0.4, 1-p_e_1-0.03))\n", + "plt.plot(x_2, 1-p_e_2, 'ro')\n", + "plt.annotate(\"Point 2\", (x_2 + 0.4, 1-p_e_2-0.03))\n", + "x_axis = np.arange(0, 20, 0.1)\n", + "plt.plot(x_axis, np.vectorize(gumbel_distribution)(x_axis))\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def find_x_with_probability_p(p): \n", + " \"\"\" Compute point in the gumbel distribution for which the CDF is p\n", + " Use the global variables mu and beta defined above!\n", + " \"\"\"\n", + " # YOUR CODE GOES HERE #\n", + " p = _\n", + " #######################\n", + " return p" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "thebe-remove-input-init" + ] + }, + "outputs": [], + "source": [ + "check_example(globals())" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.11.2" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/book/cookbook/grading.py b/book/cookbook/grading.py new file mode 100644 index 0000000000000000000000000000000000000000..a4c16360d38ae02c082c7103503958ceba948d7a --- /dev/null +++ b/book/cookbook/grading.py @@ -0,0 +1,13 @@ +import ipywidgets as widgets +from IPython.display import display + +def check(f): + def wrapper(*args, **kwargs): + output = widgets.Output() + button = widgets.Button(description="Check answer") + @output.capture(clear_output=True,wait=True) + def _inner_check(button): + f(*args, **kwargs) + button.on_click(_inner_check) + display(button, output) + return wrapper \ No newline at end of file