From adc4b104cd9600377efbada9c8212083bf87ca17 Mon Sep 17 00:00:00 2001 From: Andrew Straw Date: Fri, 29 Nov 2024 09:11:15 +0100 Subject: [PATCH] exercise-08 --- .../release/exercise-08/1__numpy-basics.ipynb | 1361 +++++++++++++++++ .../2__Optimization_first_steps.ipynb | 542 +++++++ 2 files changed, 1903 insertions(+) create mode 100644 exercises/release/exercise-08/1__numpy-basics.ipynb create mode 100644 exercises/release/exercise-08/2__Optimization_first_steps.ipynb diff --git a/exercises/release/exercise-08/1__numpy-basics.ipynb b/exercises/release/exercise-08/1__numpy-basics.ipynb new file mode 100644 index 0000000..603b250 --- /dev/null +++ b/exercises/release/exercise-08/1__numpy-basics.ipynb @@ -0,0 +1,1361 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "b8a591f5e43fe66ddaf506c4afbac6b5", + "grade": false, + "grade_id": "cell-654bd336ff003835", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "outputs": [], + "source": [ + "# You must run this cell, but you can ignore its contents.\n", + "\n", + "import hashlib\n", + "\n", + "def ads_hash(ty):\n", + " \"\"\"Return a unique string for input\"\"\"\n", + " ty_str = str(ty).encode()\n", + " m = hashlib.sha256()\n", + " m.update(ty_str)\n", + " return m.hexdigest()[:10]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "markdown", + "checksum": "0ace91955d048ca2dad2a2fd7fd23b13", + "grade": false, + "grade_id": "cell-7f7c9f7f55486e9b", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "source": [ + "# numpy" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "e8f57f43c9d18b610d47e028e6cd28bd", + "grade": false, + "grade_id": "cell-e630f56f923f6053", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "outputs": [], + "source": [ + "import numpy as np" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "markdown", + "checksum": "c88374b41163058dcfb2d5307b0db2d7", + "grade": false, + "grade_id": "cell-da0a17e5d1fbe62c", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + }, + "tags": [] + }, + "source": [ + "## Q1 Create a 1 dimensional numpy array named `x` with 20 elements from 0 to 19.\n", + "\n", + "Hint: use the `arange` function of numpy." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "852192edc9b51f8cbd01be49c694f3a4", + "grade": false, + "grade_id": "cell-1502b7b220c53c56", + "locked": false, + "schema_version": 3, + "solution": true, + "task": false + }, + "tags": [] + }, + "outputs": [], + "source": [ + "# YOUR CODE HERE\n", + "raise NotImplementedError()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "d12ac5f0875993c39a482e79089db6d3", + "grade": true, + "grade_id": "cell-f67a7b35435b525c", + "locked": true, + "points": 0, + "schema_version": 3, + "solution": false, + "task": false + }, + "tags": [] + }, + "outputs": [], + "source": [ + "# If this runs without error, it means the answer in your previous cell was correct.\n", + "assert ads_hash(x)=='7a150607a7'" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "markdown", + "checksum": "195c5c3c99efa4e8100572968a6ac996", + "grade": false, + "grade_id": "cell-64d2210f9a71e242", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + }, + "tags": [] + }, + "source": [ + "## Q2 Create a 1 dimensional numpy array named `x` with 20 elements from 0 to 38 with an increment of 2.\n", + "\n", + "Hint: use the `arange` function of numpy." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "a92d385dd3e887d40bc84b01db422cfa", + "grade": false, + "grade_id": "cell-cff3a5e50b06014a", + "locked": false, + "schema_version": 3, + "solution": true, + "task": false + }, + "tags": [] + }, + "outputs": [], + "source": [ + "# YOUR CODE HERE\n", + "raise NotImplementedError()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "5ea3420f20c13566a89e9e2f9e24d452", + "grade": true, + "grade_id": "cell-64723536c462a2d1", + "locked": true, + "points": 1, + "schema_version": 3, + "solution": false, + "task": false + }, + "tags": [] + }, + "outputs": [], + "source": [ + "# If this runs without error, it means the answer in your previous cell was correct.\n", + "assert ads_hash(x)=='8bc0a3b6c4'" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "markdown", + "checksum": "3baffdf43eb0dd45219fba107dbdb539", + "grade": false, + "grade_id": "cell-f439954fdaef75da", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "source": [ + "## Q3 Create a 2 dimensional numpy array named `x` of shape 5,6." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "0d0f5fc61512a2356922219f33d9582f", + "grade": false, + "grade_id": "cell-15f8e74190eecaf8", + "locked": false, + "schema_version": 3, + "solution": true, + "task": false + } + }, + "outputs": [], + "source": [ + "# YOUR CODE HERE\n", + "raise NotImplementedError()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "6d683f118d9eb97c8068c189b2f73188", + "grade": true, + "grade_id": "cell-38a672b790c362eb", + "locked": true, + "points": 1, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "outputs": [], + "source": [ + "# If this runs without error, it means the answer in your previous cell was correct.\n", + "assert ads_hash(x.shape)=='6510380315'" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "markdown", + "checksum": "2a1cf3d973361fa8f60c6c15bae08706", + "grade": false, + "grade_id": "cell-681527231f43677f", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "source": [ + "## Q4 Consider the first 100 integers starting with 0. What is their mean value? Put this in a variable `mean100`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "3014f7556d69336f39c1bf0a51d4105b", + "grade": false, + "grade_id": "cell-34f66fe8d8b001fb", + "locked": false, + "schema_version": 3, + "solution": true, + "task": false + } + }, + "outputs": [], + "source": [ + "# YOUR CODE HERE\n", + "raise NotImplementedError()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "dcc4c6d18784c72102da8af214db89d4", + "grade": true, + "grade_id": "cell-9ef246cf9714c370", + "locked": true, + "points": 1, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "outputs": [], + "source": [ + "# If this runs without error, it means the answer in your previous cell was correct.\n", + "assert ads_hash(round(mean100*1000))=='bc8d4a4d1e'" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "markdown", + "checksum": "3887513d944274daef5b5860c23e77bc", + "grade": false, + "grade_id": "cell-b4c0d9ce0a0e3ec7", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "source": [ + "## Q5 Create an array named `x` with every 4th value of the first 100000 integers." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "def98d3a4ff5a4444e78d6884b16a34b", + "grade": false, + "grade_id": "cell-6b4ee0992aa506c5", + "locked": false, + "schema_version": 3, + "solution": true, + "task": false + } + }, + "outputs": [], + "source": [ + "# YOUR CODE HERE\n", + "raise NotImplementedError()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "6fa450c5d140a4ab2c21dcce3a621435", + "grade": true, + "grade_id": "cell-6833bfed10c7430c", + "locked": true, + "points": 1, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "outputs": [], + "source": [ + "# If this runs without error, it means the answer in your previous cell was correct.\n", + "assert ads_hash(len(x))=='0812a4ef4e' \n", + "assert ads_hash(x)=='17e101b2ef'" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "markdown", + "checksum": "3047231b1742b9a7f70d6335eb0fc54f", + "grade": false, + "grade_id": "cell-34c0aed2a2c992a4", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "source": [ + "## Q6 set the shape of `x` to be (5, 5000)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "2c82b4ab20f94362a6d24a4d808a0691", + "grade": false, + "grade_id": "cell-e07f245d339e6328", + "locked": false, + "schema_version": 3, + "solution": true, + "task": false + } + }, + "outputs": [], + "source": [ + "# YOUR CODE HERE\n", + "raise NotImplementedError()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "aee8fd1dd13562ee0917a50a259aa42e", + "grade": true, + "grade_id": "cell-190e11601c41f920", + "locked": true, + "points": 1, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "outputs": [], + "source": [ + "# If this runs without error, it means the answer in your previous cell was correct.\n", + "assert ads_hash(len(x))=='ef2d127de3' \n", + "assert ads_hash(x)=='3331e0302b'" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "markdown", + "checksum": "8d588e43438e0ad079169fd7f7474666", + "grade": false, + "grade_id": "cell-1802e3087f27de21", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "source": [ + "## Q7 Create the variable `y` from the first 3 rows and the first 8 columns of `x`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "bf27135b61c26a05aea91e1f01349726", + "grade": false, + "grade_id": "cell-ef33bd87060e2253", + "locked": false, + "schema_version": 3, + "solution": true, + "task": false + } + }, + "outputs": [], + "source": [ + "# YOUR CODE HERE\n", + "raise NotImplementedError()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "8c0873922759ff509513beaece8a2d83", + "grade": true, + "grade_id": "cell-38599e5840dfe50f", + "locked": true, + "points": 0, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "outputs": [], + "source": [ + "# If this runs without error, it means the answer in your previous cell was correct.\n", + "assert ads_hash(len(y))=='4e07408562' \n", + "assert ads_hash(y)=='b39d640ca0'" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "markdown", + "checksum": "6962a55d45696646cb66150fb17292a7", + "grade": false, + "grade_id": "cell-c760334b1b549d83", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "source": [ + "## Plotting numpy arrays with matplotlib\n", + "\n", + "Let's start plotting numpy arrays. The `plot()` function in matplotlib's `pyplot` module works differently depending on the number of arguments it was called with. Like your `get_2D_coordinates()` function above, if only one argument is used, it is treated as the `y` coordinates. The `x` coordinates are the integers starting with `0`. If two arguments are used, they are treated as the `x` and `y` coordinates.\n", + "\n", + "Here we are also going to label our axes to keep track of what we are plotting. We will use the `plt.xlabel()` and `plt.ylabel()` functions." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "181bbd6b82abfdb3eb5c059aadb65133", + "grade": false, + "grade_id": "cell-022fd8735aa958ba", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "markdown", + "checksum": "6a4775d495f1a5512fa5dae7549ea9f2", + "grade": false, + "grade_id": "cell-efcd917dafccd54c", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "source": [ + "We are going to generate some \"toy\" (artificial, false, fake, made-up) positions of a bee over time. First, we need the times where we have tracking data. We are going to track the bee for 10 seconds. Over these 10 seconds, we have 100 measurements." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "c519aba9a18e96655ad371783599635b", + "grade": false, + "grade_id": "cell-3acd919556155f8f", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "outputs": [], + "source": [ + "time_values = np.linspace(0,10,100)\n", + "plt.plot(time_values)\n", + "plt.ylabel('time (seconds)');" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "markdown", + "checksum": "7721645f3a1dd2463328aed14ca9bd53", + "grade": false, + "grade_id": "cell-54aa9b963835b42f", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "source": [ + "Now we will get the `y` coordinate of the bee over these 10 seconds. Instead of real data, we generate toy data by using the `np.sin()` function. We take the sine of the time value as the `y` coordinate of the bee." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "baa830db90f60c4aa74699f4b97be765", + "grade": false, + "grade_id": "cell-d8eefc7a088ab564", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "outputs": [], + "source": [ + "y = np.sin(time_values)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "markdown", + "checksum": "657471fb5d9fe09f5063b8ad763f51b0", + "grade": false, + "grade_id": "cell-44143dbd92ac071d", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "source": [ + "Now let's plot the `y` coordinate of the bee over time." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "958eea9bacbfb559c136f6cd30287279", + "grade": false, + "grade_id": "cell-e1a3bbf4c1b1618c", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "outputs": [], + "source": [ + "plt.plot(time_values,y)\n", + "plt.xlabel('time (seconds)');\n", + "plt.ylabel('y (meters)');" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "markdown", + "checksum": "882e42c3d072439e1ed1ad4060ac55ca", + "grade": false, + "grade_id": "cell-de601837bd41103a", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "source": [ + "So our bee was oscillating in `y` over time.\n", + "\n", + "In addition to a `y` coordinate, our tracking system also gives us `x` coordinates. Let's make some toy data for this, too." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "b0ebba9258ed9c6e02de101ad481179f", + "grade": false, + "grade_id": "cell-9a46e6754a91f190", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "outputs": [], + "source": [ + "x = 0.5*np.sin(time_values*3.2)+1.1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "ede756e28026500ee3dffa5744a78c88", + "grade": false, + "grade_id": "cell-153b385adbe59ec2", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "outputs": [], + "source": [ + "plt.plot(time_values,x)\n", + "plt.xlabel('time (seconds)');\n", + "plt.ylabel('x (meters)');" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "markdown", + "checksum": "ace790d5cadd15eb9e38000bfcabfd7b", + "grade": false, + "grade_id": "cell-d5670c1510ca17ff", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "source": [ + "So the bee was also oscillating in `x`, and even faster than in `y`." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "markdown", + "checksum": "0f19a80dae475aaca9a80d4e76dab504", + "grade": false, + "grade_id": "cell-65c1964e62b88a11", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "source": [ + "## Storing multiple dimensions data in single array\n", + "\n", + "We might want to store our coordinates in a single multi-dimensional numpy array where the columns are time and the rows are the different coordinates (`x`, and `y`).\n", + "\n", + "```\n", + "x0, x1, x2, ..., xn\n", + "y0, y1, y2, ..., yn\n", + "```\n", + "\n", + "We can use the `np.vstack()` (\"vertical stack\") function for this. It will return a new array whose rows are the given in its input argument." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "c0a41e2d3055d4a8d46dc08148090189", + "grade": false, + "grade_id": "cell-6e94a8443b27f2bf", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "outputs": [], + "source": [ + "bee_coords = np.vstack((x,y))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "markdown", + "checksum": "6e4a851ef99bd3eecee7ac10e7fca08c", + "grade": false, + "grade_id": "cell-de3884dcd3459ef6", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "source": [ + "By doing these, we can keep the different measurements together. Of course, we can still plot just a single dimension. Here is `x` over time again. In this case, the x axis is simply the index of the array passed to `plot()`:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "f9fba2927a0e61aea16248bc91a7f367", + "grade": false, + "grade_id": "cell-5f3a313fa88f20be", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "outputs": [], + "source": [ + "plt.plot(bee_coords[0])\n", + "plt.ylabel('x (meters)');" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "markdown", + "checksum": "d0ac2bfcddf131514f0af04ddc3a0cb8", + "grade": false, + "grade_id": "cell-765b4dd8839b4076", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "source": [ + "Of course, we can also plot the time value as the x axis and label it correctly:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "17c6db774136c7bdd01d470a7bcff60c", + "grade": false, + "grade_id": "cell-b2b1ea1720798043", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "outputs": [], + "source": [ + "plt.plot(time_values, bee_coords[0])\n", + "plt.xlabel('time (seconds)');\n", + "plt.ylabel('x (meters)');" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "markdown", + "checksum": "5a299e560d66a4acfd84839cc037db22", + "grade": false, + "grade_id": "cell-c92b5b7235df5958", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "source": [ + "If `x` and `y` are horizontal positions, we can plot a \"top view\" of the bee position by plotting x against y:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "cb952d36ae3050e5408a9eb8d1d1dc02", + "grade": false, + "grade_id": "cell-8a08ee9348762caf", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "outputs": [], + "source": [ + "plt.plot(bee_coords[0], bee_coords[1])\n", + "plt.xlabel('x (meters)')\n", + "plt.ylabel('y (meters)');" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "markdown", + "checksum": "a608d6fec980934b711d6e6333715291", + "grade": false, + "grade_id": "cell-e2889206cd341445", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "source": [ + "Let's now calculate how far the bee is in any moment in time from a particular location. Remember the distance function we made in lecture:\n", + "\n", + "```python\n", + "def compute_dist(a,b):\n", + " \"\"\"compute distance between two points, `a` and `b`\n", + " \n", + " `a` and `b` are each 2D sequences representing the coordinates of the point.\"\"\"\n", + " dx = b[0] - a[0]\n", + " dy = b[1] - a[1]\n", + " return np.sqrt( dx**2 + dy**2 )\n", + "```\n", + "\n", + "We wrote this function with the idea that `a` and `b` are each a 2D point. With `a = (xa, ya)` and `b = (xb, yb)`.\n", + "\n", + "Now we want a a function which returns the distance between a single input point `a` with coordinates `(xa, ya)` and each and every point in an array `bee_coords` which has shape `(2, n)`. So column `i` of `bee_coords` is thus a coordinate `(xi, yi)`.\n", + "\n", + "Let's build up to this function piece-by-piece.\n", + "\n", + "## Q8\n", + "\n", + "First write a function called `compute_dx_squared` with the signature:\n", + "\n", + "```python\n", + "def compute_dx_squared(a,b):\n", + " \"\"\"return the x distance squared between `a` and all points in `b`.\n", + " \n", + " `a` is a length 2 sequence with coordinates `(xa, ya)` and `b` is a numpy array of shape `(2, n)`.\n", + " \"\"\"\n", + "```\n", + "\n", + "This function returns the squared `x` distance between point `a` (a length 2 sequence of the `x`,`y` coordinates of point `a`) and each coordinate in the 2D array `b` with shape `(2,n)`. Thus, for `a=[1.0,2.1]` and `b=np.array([[1,2,3],[4,5,6]])`, this will return `np.array([0., 1., 4.])`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "c62b867a4dbcfe7515a1943db943bb31", + "grade": false, + "grade_id": "cell-68e7d25afb2f1765", + "locked": false, + "schema_version": 3, + "solution": true, + "task": false + } + }, + "outputs": [], + "source": [ + "# YOUR CODE HERE\n", + "raise NotImplementedError()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "9ab00230a2f278b346751df2cd8bd515", + "grade": true, + "grade_id": "cell-917fe5138adc3d85", + "locked": true, + "points": 1, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "outputs": [], + "source": [ + "# If this runs without error, it means the answer in your previous cell was correct.\n", + "assert ads_hash(compute_dx_squared([1.0,2.1],np.array([[1,2,3],[4,5,6]])))=='1bacf727ce'\n", + "assert ads_hash(compute_dx_squared([1.0,2.1],np.array([[1,2,3,4.2],[4,5,6,8.2]])))=='c9c0596224'" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "markdown", + "checksum": "053967690bf5d021be99d4f204731a64", + "grade": false, + "grade_id": "cell-18f7f59d96101f0c", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "source": [ + "## Q9\n", + "\n", + "Now write a function called `compute_dy_squared` with the signature:\n", + "\n", + "```python\n", + "def compute_dy_squared(a,b):\n", + " \"\"\"return the y distance squared between `a` and all points in `b`.\n", + " \n", + " `a` is a length 2 sequence with coordinates `(xa, ya)` and `b` is a numpy array of shape `(2, n)`.\n", + " \"\"\"\n", + "```\n", + "\n", + "This function returns the squared `y` distance between point `a` (a length 2 sequence of the `x`,`y` coordinates of point `a`) and each coordinate in the 2D array `b` with shape `(2,n)`. Thus, for `a=[1.0,2.1]` and `b=np.array([[1,2,3],[4,5,6]])`, this will return `array([ 3.61, 8.41, 15.21])`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "d187a8201410e5f44975535430ba0ed7", + "grade": false, + "grade_id": "cell-e74d9319eda293c6", + "locked": false, + "schema_version": 3, + "solution": true, + "task": false + } + }, + "outputs": [], + "source": [ + "# YOUR CODE HERE\n", + "raise NotImplementedError()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "684ce2fcf426e29c83c3b74a4f734d7b", + "grade": true, + "grade_id": "cell-52b68c1bd8f83a48", + "locked": true, + "points": 1, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "outputs": [], + "source": [ + "# If this runs without error, it means the answer in your previous cell was correct.\n", + "assert ads_hash(compute_dy_squared([1.0, 2.1], np.array([[1,2,3],[4,5,6]])))=='759d96c1e4'\n", + "assert ads_hash(compute_dy_squared([1.0, 2.1], np.array([[1,2,3,1.2],[4,5,6,-3]])))=='cb574f3c8e'" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "markdown", + "checksum": "e74e0813d1790618b60dbd94003a0d22", + "grade": false, + "grade_id": "cell-3360812bc0c687c5", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "source": [ + "## Q10\n", + "\n", + "Now write a function called `compute_distance` with the signature:\n", + "\n", + "```python\n", + "def compute_distance(a,b):\n", + " \"\"\"return the distance between `a` and all points in `b`.\n", + " \n", + " `a` is a length 2 sequence with coordinates `(xa, ya)` and `b` is a numpy array of shape `(2, n)`.\n", + " \"\"\"\n", + "```\n", + "\n", + "This function returns the distance between point `a` (a length 2 sequence of the `x`,`y` coordinates of point `a`) and each coordinate in the 2D array `b` with shape `(2,n)`. Thus, for `a=[1.0,2.1]` and `b=np.array([[1,2,3],[4,5,6]])`, this will return `array([1.9 , 3.06757233, 4.3829214 ])`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "e3ad5869bba054247db559e212ff3a59", + "grade": false, + "grade_id": "cell-cbbcbdf110a030b2", + "locked": false, + "schema_version": 3, + "solution": true, + "task": false + } + }, + "outputs": [], + "source": [ + "# YOUR CODE HERE\n", + "raise NotImplementedError()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "d61620c804e2942937dc11a4b2f94c8f", + "grade": true, + "grade_id": "cell-eb44de204d241fa6", + "locked": true, + "points": 1, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "outputs": [], + "source": [ + "# If this runs without error, it means the answer in your previous cell was correct.\n", + "assert ads_hash(compute_distance([1.0, 2.1], np.array([[1,2,3],[4,5,6]])))=='1e2fc6c5fd'\n", + "assert ads_hash(compute_distance([1.0, 2.1], np.array([[1,2,3,10.1],[4,5,6,-2.2]])))=='b7ef5a80ae'" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "markdown", + "checksum": "a25e6c52be197ecbbcd3019ffd4b68a0", + "grade": false, + "grade_id": "cell-b084804c3c32a977", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "source": [ + "## Q11\n", + "\n", + "Now let's imagine you upgraded your tracking system to work in 3 dimensions and now you collect data in `x`, `y` and `z`. Write a function called `compute_distance_3d` with the signature:\n", + "\n", + "```python\n", + "def compute_distance_3d(a,b):\n", + " \"\"\"return the distance between `a` and all points in `b`.\n", + " \n", + " `a` is a length 3 sequence with coordinates `(xa, ya, za)` and `b` is a numpy array of shape `(3, n)`.\n", + " \"\"\"\n", + "```\n", + "\n", + "This function returns the distance between point `a` (a length 3 sequence of the `x`,`y`,`z` coordinates of point `a`) and each coordinate in the 2D array `b` with shape `(3,n)`. Thus, for `a=[1.0,2.1,0.0]` and `b=np.array([[1,2,3],[4,5,6],[7,8,9]])`, this will return `np.array([ 7.25327512, 8.56796359, 10.01049449])`.\n", + "\n", + "Remember that the formula for distance in 3D is:\n", + "\n", + "```\n", + "distance = sqrt( dx**2 + dy**2 + dz**2 )\n", + "```\n", + "\n", + "where `dx` is the distance along the `x` direction, `dy` is the distance along the `y` direction, and `dz` is the distance along the `z` direction, " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "3a9d790b24c98c5b0f23899ca9446375", + "grade": false, + "grade_id": "cell-d3cd40a661182621", + "locked": false, + "schema_version": 3, + "solution": true, + "task": false + } + }, + "outputs": [], + "source": [ + "# YOUR CODE HERE\n", + "raise NotImplementedError()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "c3133f6c56e721f29f92c2b9a5f29857", + "grade": true, + "grade_id": "cell-f0538c2e9972a4ba", + "locked": true, + "points": 1, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "outputs": [], + "source": [ + "# If this runs without error, it means the answer in your previous cell was correct.\n", + "assert ads_hash(compute_distance_3d([1.0,2.1,0.0], np.array([[1,2,3],[4,5,6],[7,8,9]])))=='6f84b17de0'\n", + "assert ads_hash(compute_distance_3d([1.0,2.1,0.1], np.array([[1,2,3,0.0],[4,5,6,1.0],[7,8,9.2,0.0]])))=='0b9c9c17b1'" + ] + } + ], + "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.10" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/exercises/release/exercise-08/2__Optimization_first_steps.ipynb b/exercises/release/exercise-08/2__Optimization_first_steps.ipynb new file mode 100644 index 0000000..2867b63 --- /dev/null +++ b/exercises/release/exercise-08/2__Optimization_first_steps.ipynb @@ -0,0 +1,542 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "29874499fd2a20779e162626f76f6776", + "grade": false, + "grade_id": "cell-e894ec2378fa46eb", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "outputs": [], + "source": [ + "# You must run this cell, but you can ignore its contents.\n", + "\n", + "import hashlib\n", + "\n", + "def ads_hash(ty):\n", + " \"\"\"Return a unique string for input\"\"\"\n", + " ty_str = str(ty).encode()\n", + " m = hashlib.sha256()\n", + " m.update(ty_str)\n", + " return m.hexdigest()[:10]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "6f1fee68b047ccaf945f9998a29d8651", + "grade": false, + "grade_id": "cell-ada87b3b188b2d39", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "outputs": [], + "source": [ + "# You must also run this cell.\n", + "\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "markdown", + "checksum": "bd84ae4c048d756b33d0fd85d55f1aec", + "grade": false, + "grade_id": "cell-d7462f8b0f718bef", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "source": [ + "# Exercise - Optimization first steps\n", + "\n", + "We are going to take our first steps towards optimization by returning to a bumblebee example.\n", + "\n", + "We are going to define the positions of a flower and the flight path of a bumblebee." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "13882d6eb738408b7520368a4b5e8ff5", + "grade": false, + "grade_id": "cell-78cb75cddd4fc5ef", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "outputs": [], + "source": [ + "flower = np.array([7.5, 10.3])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "5f73a413f4a03726e882c755a3430c17", + "grade": false, + "grade_id": "cell-ab9736432799913b", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "outputs": [], + "source": [ + "def make_bee_track(t):\n", + " pos0 = (-10,3)\n", + " velocity = (4.0, 0.2)\n", + " pos_x = pos0[0] + t*velocity[0]\n", + " pos_y = pos0[1] + t*velocity[1]\n", + " return np.array([pos_x,pos_y])\n", + "\n", + "t = np.linspace(0,15,20)\n", + "bee_track = make_bee_track(t)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "markdown", + "checksum": "6aa761a551cb0142afbfe7e7d81947ed", + "grade": false, + "grade_id": "cell-08928dcd585933a7", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "source": [ + "Here we plot these positions." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "c8e52b43cbe861d8eddacccc87aeb1e2", + "grade": false, + "grade_id": "cell-4b58d56276437c3a", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "outputs": [], + "source": [ + "fig, ax = plt.subplots(nrows=1, ncols=1)\n", + "ax.plot( [flower[0]], [flower[1]], 'or', label='flower' )\n", + "ax.plot( bee_track[0], bee_track[1], '.-k', label='bee')\n", + "ax.axis('equal')\n", + "ax.legend();" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "markdown", + "checksum": "0f3a53f8323083b2effbac78689c09d7", + "grade": false, + "grade_id": "cell-701acd6a5b4a9581", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "source": [ + "## Q1 Draw a figure as above with, additionally, a blue line between each point on `bee_track` and `flower`.\n", + "\n", + "When complete, your figure should look like this:\n", + "\n", + "\n", + "\n", + "\n", + "Hint, draw the flower first. Then, make a for loop which steps through each position of the bee. Inside the for loop, draw a line segment between the bee and the flower." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "38fbad4ec96d8ade393535b625140003", + "grade": true, + "grade_id": "cell-43f8774b1a82b15b", + "locked": false, + "points": 1, + "schema_version": 3, + "solution": true, + "task": false + } + }, + "outputs": [], + "source": [ + "# YOUR CODE HERE\n", + "raise NotImplementedError()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "markdown", + "checksum": "89805e9c9678ff01669528f20a596bf6", + "grade": false, + "grade_id": "cell-45a057824a59090e", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "source": [ + "## Q2 write a function called `my_distance` which takes two arguments, each of which is a length 2 sequence of `x`, `y` position and returns the Euclidean distance between these points." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "9bd3bd0fb3a886f4696138c95e0058ab", + "grade": false, + "grade_id": "cell-9d86e35ff582bf8f", + "locked": false, + "schema_version": 3, + "solution": true, + "task": false + } + }, + "outputs": [], + "source": [ + "# YOUR CODE HERE\n", + "raise NotImplementedError()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "b359ea8e38a47e5320e08ce6158dc39c", + "grade": true, + "grade_id": "cell-d96cb3c1a49758db", + "locked": true, + "points": 0, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "outputs": [], + "source": [ + "assert my_distance((0,0),(3,4)) == 5\n", + "assert my_distance((3,4), (0,0)) == 5\n", + "assert my_distance((13,14), (10,10)) == 5\n", + "assert my_distance((10,10), (13,14)) == 5" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "markdown", + "checksum": "5220e92a49ceb61457be556c246b28ce", + "grade": false, + "grade_id": "cell-9426c238469156ae", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "source": [ + "## Q3 compute the distance between each point on `bee_track` and `flower`. Put the results in a 1D numpy array called `distance`.\n", + "\n", + "Hint: recall the function you wrote in the \"numpy basics\" exercise called `compute_distance`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "922ea2de206db155b31c1b6020e50c27", + "grade": false, + "grade_id": "cell-bf78a3429e48b28d", + "locked": false, + "schema_version": 3, + "solution": true, + "task": false + } + }, + "outputs": [], + "source": [ + "# YOUR CODE HERE\n", + "raise NotImplementedError()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "0304ff76ac1ade2c3221a53c5df5fbb2", + "grade": true, + "grade_id": "cell-70fd1e669decb646", + "locked": true, + "points": 1, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "outputs": [], + "source": [ + "# If this runs without error, it means the answer in your previous cell was correct.\n", + "assert ads_hash(np.round(distance*1000).astype(np.int32))=='54f4f2edcb'" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Q4 make a plot of the bee track parameter `t` on the X axis and `distance` on the Y axis.\n", + "\n", + "It should look like this:\n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "c03c9f9064ad82267ed7ad1ff2274116", + "grade": true, + "grade_id": "cell-acdc61a7b1539944", + "locked": false, + "points": 1, + "schema_version": 3, + "solution": true, + "task": false + } + }, + "outputs": [], + "source": [ + "# YOUR CODE HERE\n", + "raise NotImplementedError()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Q5 Using `calc_distance_func` from the lecture, find the value of `t` that minimizes the distance between the bee and the flower. Save the result in `best_t`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "ea188c9450758aa26fecfdc16042a9f2", + "grade": false, + "grade_id": "cell-23d19427610d2072", + "locked": false, + "schema_version": 3, + "solution": true, + "task": false + } + }, + "outputs": [], + "source": [ + "# YOUR CODE HERE\n", + "raise NotImplementedError()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "7a33eaaaaca8781f883635cee037a71d", + "grade": true, + "grade_id": "cell-0a3594afd2952a33", + "locked": true, + "points": 1, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "outputs": [], + "source": [ + "# If this runs without error, it means the answer in your previous cell was correct.\n", + "assert ads_hash(np.round(best_t*1000).astype(np.int32))=='dec1ab2f6d'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "make_bee_track(best_t)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Q6 What is the position of the bee when it is closest to the flower? Save the result as a numpy array in `best_pos`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "20073a563548884f84b927f1c1f154eb", + "grade": false, + "grade_id": "cell-cac598c7f739d146", + "locked": false, + "schema_version": 3, + "solution": true, + "task": false + } + }, + "outputs": [], + "source": [ + "# YOUR CODE HERE\n", + "raise NotImplementedError()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "4e73e4a1310b052d0bd683f8e5b40fd3", + "grade": true, + "grade_id": "cell-9d882991838f0996", + "locked": true, + "points": 1, + "schema_version": 3, + "solution": false, + "task": false + } + }, + "outputs": [], + "source": [ + "# If this runs without error, it means the answer in your previous cell was correct.\n", + "assert type(best_pos)==np.ndarray\n", + "assert best_pos.ndim==1\n", + "assert best_pos.shape==(2,)\n", + "assert ads_hash(np.round(best_pos[0]*1000).astype(np.int32))=='e33b9415bc'\n", + "assert ads_hash(np.round(best_pos[1]*1000).astype(np.int32))=='f71cbfce4c'" + ] + } + ], + "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.7" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +}