{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "839f9f95-d3ea-477f-96b6-b23eea60be3c",
   "metadata": {
    "editable": true,
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-94f52a4a45c90a6a",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    },
    "slideshow": {
     "slide_type": ""
    },
    "tags": []
   },
   "source": [
    "# 6. Programmierübung: Monte Carlo Simulationen\n",
    "\n",
    "<div style=\"display:flex;\">\n",
    "    <div style=\"text-align: left\">\n",
    "        Willkommen zur sechsten Programmierübung Einführung in Python 3.\n",
    "    </div>\n",
    "    <img style=\"float: right; margin: 0px 15px 15px 0px\" src=\"https://www.python.org/static/img/python-logo-large.c36dccadd999.png?1576869008\" width=\"100\" />\n",
    "</div>\n",
    "\n",
    "Wenn Sie Fragen oder Verbesserungsvorschläge zum Inhalt oder Struktur der Notebooks haben, dann können sie eine E-Mail an Phil Keier ([p.keier@hbk-bs.de](mailto:p.keier@hbk-bs.de?subject=[SigSys]%20Feedback%20Programmierübung&amp)) oder Martin Le ([martin.le@tu-bs.de](mailto:martin.le@tu-bs.de?subject=[SigSys]%20Feedback%20Programmierübung&amp)) schreiben.\n",
    "\n",
    "Link zu einem Python Spickzettel: [hier](https://s3.amazonaws.com/assets.datacamp.com/blog_assets/PythonForDataScience.pdf)\n",
    "\n",
    "Der Großteil des Python-Tutorials stammt aus der Veranstaltung _Deep Learning Lab_ und von [www.python-kurs.eu](https://www.python-kurs.eu/python3_kurs.php) und wurde für _Signale und Systeme_, sowie _Einführung in die Programmierung für Nicht Informatiker_ angepasst.\n",
    "\n",
    "---"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "53c75485-1cd4-4ac7-9092-e14b3c400980",
   "metadata": {
    "editable": true,
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-107d356336d8d991",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    },
    "slideshow": {
     "slide_type": ""
    },
    "tags": []
   },
   "source": [
    "## (Continues) Uniform Distribution\n",
    "\n",
    "Die gleichmäßige Verteilung zeigt sich durch ihre Charakteristische Form eines Rechteckes mit Flächeninhalt 1 = 100%. \n",
    "Technisch gesehen ist diese Form der Verteilung bereits bekannt da PCGs dieser folgen.\n",
    "\n",
    "Eine Uniform Distribution setzt sich aus den selben zwei Parametern zusammen wie die Normalverteilung, $\\mu$ der Mittelwert und $\\sigma$ die Standardabweichung vom Mittelwert. \n",
    "\n",
    "Jedoch nehmen die Libraries NumPy & SciPy die Werte anders auf, $\\mu$ ist hierbei der kleinste Wert und $\\sigma$ der Größte Wert.\n",
    "\n",
    "Folgende Grafik verdeutlicht die Verteilung mit $\\mu=0$ & $\\sigma=1$:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "id": "52d292d3-66ee-4d00-b5eb-e65497839fba",
   "metadata": {
    "editable": true,
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-654d073e308d12e3",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    },
    "slideshow": {
     "slide_type": ""
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 23012 characters]",
      "text/plain": [
       "<Figure size 800x500 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import numpy as np\n",
    "from scipy.stats import uniform # Import scipys uniform\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "# Define the distribution parameters to be plotted\n",
    "sigma = 1\n",
    "mu = 0\n",
    "x = np.linspace(-0.5, 1.5, 1000)\n",
    "\n",
    "\n",
    "# plot the distributions\n",
    "fig, ax = plt.subplots(figsize=(8, 5))\n",
    "\n",
    "dist = uniform(mu, sigma)\n",
    "\n",
    "plt.plot(x, dist.pdf(x), c='black', label=r'$\\mu=%i,\\ \\sigma=%i$' % (mu, sigma))\n",
    "\n",
    "plt.xlim(-0.5, 1.5)\n",
    "plt.ylim(0, 1.2)\n",
    "\n",
    "plt.xlabel('$x$')\n",
    "plt.ylabel(r'$p(x|\\mu, \\sigma)$')\n",
    "plt.title('Uniform Distribution')\n",
    "\n",
    "plt.legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "55a561f8-46dc-4a72-a4e3-c7711aede96b",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-0ccc61b247199a19",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "## Random Sampling\n",
    "\n",
    "Wie man von Verteilungen sampled ist bereits bekannt aus dem Kapitel zu den PCGs diese sind uniformiert verteilt.\n",
    "\n",
    "Folgendes Beispiel zieht 3 zufällige Zahlen aus einer PCG uniformierten Verteilung mittels NumPy:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 115,
   "id": "a312483e-058b-4efc-a92a-bc9e370a3559",
   "metadata": {
    "editable": true,
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-c4c29720ffba7a48",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    },
    "slideshow": {
     "slide_type": ""
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 30008 characters]",
      "text/plain": [
       "<Figure size 800x500 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Parameters\n",
    "mu = 0\n",
    "sigma = 1\n",
    "\n",
    "# Get a 3 random samples\n",
    "rand = np.random.default_rng(5000)\n",
    "uniform_samples = rand.uniform(mu, sigma, 3)\n",
    "\n",
    "# Linespace\n",
    "x = np.linspace(-0.5, 2, 1000)\n",
    "\n",
    "# Get uniform from linespace\n",
    "dist = uniform(mu, sigma)\n",
    "\n",
    "# Plot Uniform\n",
    "fig, ax = plt.subplots(figsize=(8, 5))\n",
    "plt.plot(x, dist.pdf(x), c='black', label=r'$\\mu=%i,\\ \\sigma=%i$' % (mu, sigma))\n",
    "\n",
    "# Plot samples\n",
    "step = 0.1\n",
    "for u in uniform_samples:\n",
    "    u = np.round(u, decimals=2)\n",
    "    plt.axvline(u, color='r')\n",
    "    plt.text(u, .5+step, u, color='g')\n",
    "    step += 0.1\n",
    "\n",
    "# Cosmetics\n",
    "plt.xlim(-0.5, 1.5)\n",
    "plt.ylim(0, 1.2)\n",
    "\n",
    "plt.xlabel('$x$')\n",
    "plt.ylabel(r'$p(x|\\mu, \\sigma)$')\n",
    "plt.title('3 Samples from a Uniform Distribution')\n",
    "\n",
    "plt.legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a87b1a90-adff-4eb4-b91b-2de5284f64d3",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-42065ce8f33baff7",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "Random sampling funktioniert auch auf Normalverteilungen. Beispiel:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 126,
   "id": "f1981ddf-87e1-4010-a39c-8a89d172d771",
   "metadata": {
    "editable": true,
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-d87cc7a18f64858f",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    },
    "slideshow": {
     "slide_type": ""
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 41392 characters]",
      "text/plain": [
       "<Figure size 800x500 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Import scipys norm\n",
    "from scipy.stats import norm \n",
    "\n",
    "#Parameters\n",
    "mu = 0\n",
    "sigma = 1\n",
    "\n",
    "# Get a 3 random samples\n",
    "rand = np.random.default_rng(5000)\n",
    "uniform_samples = rand.normal(mu, sigma, 3)\n",
    "\n",
    "# Linespace\n",
    "x = np.linspace(-4, 4, 1000)\n",
    "\n",
    "# Get uniform from linespace\n",
    "dist = norm(mu, sigma)\n",
    "\n",
    "# Plot Uniform\n",
    "fig, ax = plt.subplots(figsize=(8, 5))\n",
    "plt.plot(x, dist.pdf(x), c='black', label=r'$\\mu=%i,\\ \\sigma=%i$' % (mu, sigma))\n",
    "\n",
    "# Plot samples\n",
    "step = 0.1\n",
    "for u in uniform_samples:\n",
    "    u = np.round(u, decimals=2)\n",
    "    plt.axvline(u, color='r')\n",
    "    plt.text(u, .1+step, u, color='g')\n",
    "    step += 0.1\n",
    "\n",
    "# Cosmetics\n",
    "plt.xlim(-4, 4)\n",
    "plt.ylim(0, .5)\n",
    "\n",
    "plt.xlabel('$x$')\n",
    "plt.ylabel(r'$p(x|\\mu, \\sigma)$')\n",
    "plt.title('3 Samples from a Normal Distribution')\n",
    "\n",
    "plt.legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "541dd4a5-8849-43fe-8e8c-305b3b99a350",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-de3ef99af1cebfe1",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "## Monte Carlo Simulationen\n",
    "\n",
    "Monte Carlo Simulationen werden in viel Wissenschaftlichen & Finzanziellen (Forschungs-)Feldern angewandt um Stochhastisch relevante Ergebnisse einfach zu lösen. Damit lassen sich insbesondere Zufallsereignisse verschiedenster Verteilungen mit einander Kombinieren. So lässt sich Beispielweise die Zahl $\\pi$ approximieren.\n",
    "\n",
    "Dazu betrachte folgende Darstellung:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 156,
   "id": "cd6000b8-cb79-4513-8cae-dc9752e47f93",
   "metadata": {
    "editable": true,
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-3b11e71ec9f993b5",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    },
    "slideshow": {
     "slide_type": ""
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 34840 characters]",
      "text/plain": [
       "<Figure size 500x500 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "circle = plt.Circle((0, 0), 1, color='black', fill=False)\n",
    "fig, ax = plt.subplots(figsize=(5,5))\n",
    "ax.add_patch(circle)\n",
    "ax.plot(np.linspace(0,1), np.zeros(50), color='black')\n",
    "ax.text(0.5, 0.05, \"$r = 1$\")\n",
    "\n",
    "plt.xlim(-1, 1)\n",
    "plt.ylim(-1, 1)\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ad96fd0a-3e95-4670-966b-6defe5dbade4",
   "metadata": {
    "editable": true,
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-c67a16c39ab32478",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    },
    "slideshow": {
     "slide_type": ""
    },
    "tags": []
   },
   "source": [
    "Vorliegend der Einheitskreis mit Radius=1 dieser hat den Flächeninhalt $A_{circle} = \\pi$. Das Umgebende Rechteck hat die Seitenlänge $a=r*2=2$ darauß ergibt sich ein Flächeninhalt $A_{square}=2*2=4$. Daraus ergibt sich die Differenz $$\\frac{A_{circle}}{A_{square}} = \\frac{\\pi}{4}$$\n",
    "\n",
    "Jeder Punkt $(x,y)$ in dem Diagramm ist gleichwahrscheinlich, also uniform Verteilt. Mittels Monte Carlo können wir nun den Wert von $\\pi$ bestimmen. Nach Umstellen ergibt sich: $$\\pi = 4 \\cdot \\frac{A_{circle}}{A_{square}}$$\n",
    "\n",
    "Nacheinander werden folgend zufällig gleichverteilte x,y Werte gezogen.\n",
    "\n",
    "Für das Beispiel nutzen wir sehr wenig Werte um die Darstellung nicht zu verunstalten:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 159,
   "id": "082ce292-4b01-4b93-abaa-c810232f0d0a",
   "metadata": {
    "editable": true,
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-1c33d4a20d47764c",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    },
    "slideshow": {
     "slide_type": ""
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 51600 characters]",
      "text/plain": [
       "<Figure size 500x500 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Get Uniform x, y samples\n",
    "rand = np.random.default_rng(42) # Set fixed Value\n",
    "x_rand = rand.uniform(-1, 1, 100)\n",
    "y_rand = rand.uniform(-1, 1, 100)\n",
    "\n",
    "# Plot \n",
    "circle = plt.Circle((0, 0), 1, color='black', fill=False)\n",
    "fig, ax = plt.subplots(figsize=(5,5))\n",
    "ax.add_patch(circle)\n",
    "ax.plot(np.linspace(0,1), np.zeros(50), color='black')\n",
    "ax.text(0.5, 0.05, \"$r = 1$\")\n",
    "plt.xlim(-1, 1)\n",
    "plt.ylim(-1, 1)\n",
    "\n",
    "# Plot samples as small circles\n",
    "for x, y in zip(x_rand, y_rand):\n",
    "    c = plt.Circle((x,y), 0.01, color='green')\n",
    "    ax.add_patch(c)\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "162d35ab-bd1d-4304-8302-cf96b493740d",
   "metadata": {
    "editable": true,
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-102b588af1bbdfe3",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    },
    "slideshow": {
     "slide_type": ""
    },
    "tags": []
   },
   "source": [
    "Um zu bestimmen ob einer der Werte im Kreis liegt Nutzen wir die parametrisierte Kreisgleichung: $$x^2+y^2=r,\\quad r=1$$\n",
    "Mittels dieser lassen sich die Werte sortieren nach \"im Kreis `circle`\" & \"im Rechteck `square`\":"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 170,
   "id": "400c3fb5-6e2b-48c1-9b0b-9b4aa4504da2",
   "metadata": {
    "editable": true,
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-856462e1221faa4c",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    },
    "slideshow": {
     "slide_type": ""
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "# reserve two arrays\n",
    "circle_coords = []\n",
    "square_coords = []\n",
    "\n",
    "for x,y in zip(x_rand, y_rand):\n",
    "    # calculate distance from origin\n",
    "    dist_from_origin = x**2 + y**2\n",
    "\n",
    "    # if distance smaller or equal than 1, the point is in the circle\n",
    "    if dist_from_origin <= 1:\n",
    "        circle_coords.append((x,y))\n",
    "\n",
    "    # by definition is every point in the square\n",
    "    square_coords.append((x,y))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fcdc0830-f68f-4b28-b5d8-3c15271900ad",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-19f6113a9887beef",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "Mittels der länge der Listen lässt sich dementsprechend $\\pi$ approxiemieren:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 171,
   "id": "86d96bbb-9877-4fcc-af03-8b5b1898dda5",
   "metadata": {
    "editable": true,
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-f8c1f8a2e8c65aae",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    },
    "slideshow": {
     "slide_type": ""
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Pi = 3.12\n",
      "Difference to real Value 0.02159265358979301\n"
     ]
    }
   ],
   "source": [
    "pi = 4 * len(circle_coords) / len(square_coords)\n",
    "print(f\"Pi = {pi}\")\n",
    "print(f\"Difference to real Value {np.pi - pi}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9f83c18b-189b-4090-9080-c3bb74207418",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-204384254c42936a",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "Plotten wir im folgenden die 100 zufällig gleichverteilten Werte:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 172,
   "id": "18862b4a-cdb5-4799-9c32-68b411da3d58",
   "metadata": {
    "editable": true,
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-cb4b3ecde6b0ab70",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    },
    "slideshow": {
     "slide_type": ""
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 50756 characters]",
      "text/plain": [
       "<Figure size 500x500 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Plot \n",
    "circle = plt.Circle((0, 0), 1, color='black', fill=False)\n",
    "fig, ax = plt.subplots(figsize=(5,5))\n",
    "ax.add_patch(circle)\n",
    "ax.plot(np.linspace(0,1), np.zeros(50), color='black')\n",
    "ax.text(0.5, 0.05, \"$r = 1$\")\n",
    "plt.xlim(-1, 1)\n",
    "plt.ylim(-1, 1)\n",
    "\n",
    "# Plot samples not in the circle\n",
    "for coord in square_coords:\n",
    "    c = plt.Circle(coord, 0.01, color='blue')\n",
    "    ax.add_patch(c)\n",
    "\n",
    "# Plot samples in the circle\n",
    "for coord in circle_coords:\n",
    "    c = plt.Circle(coord, 0.01, color='red')\n",
    "    ax.add_patch(c)\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "704b68d6-4210-4f90-a1ae-9a0078fc8796",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-b0626976cd84b809",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "Um einen genaueren Wert für $\\pi$ zu erhalten muss dementsprechend nur die Anzahl an Samples erhöht werden (Hier 1 Million).\n",
    "\n",
    "Da im folgenden auf einen Plot verzichtet wird lässt sich die Berechnung darauf vereinfachen, dass nur gezählt werden muss welche Punkte im Kreis liegen die koordinaten sind nicht mehr vom Nutzen:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 174,
   "id": "38ca2a0d-3198-48c2-8af0-26516a01c9d9",
   "metadata": {
    "editable": true,
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-0512fe6559228e5c",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    },
    "slideshow": {
     "slide_type": ""
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Pi = 3.14178\n",
      "Difference to real Value -0.00018734641020667908\n"
     ]
    }
   ],
   "source": [
    "# Get Uniform x, y samples\n",
    "sample_size = 1_000_000\n",
    "rand = np.random.default_rng(42) # Set fixed Value\n",
    "x_rand = rand.uniform(-1, 1, sample_size)\n",
    "y_rand = rand.uniform(-1, 1, sample_size)\n",
    "\n",
    "# reserve two arrays\n",
    "in_circle = 0\n",
    "in_square = 0\n",
    "\n",
    "for x,y in zip(x_rand, y_rand):\n",
    "    # calculate distance from origin\n",
    "    dist_from_origin = x**2 + y**2\n",
    "\n",
    "    # if distance smaller or equal than 1, the point is in the circle\n",
    "    if dist_from_origin <= 1:\n",
    "        in_circle += 1\n",
    "\n",
    "    # by definition is every point in the square\n",
    "    in_square += 1\n",
    "\n",
    "pi = 4 * in_circle / in_square\n",
    "print(f\"Pi = {pi}\")\n",
    "print(f\"Difference to real Value {np.pi - pi}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "167e5e63-254b-4158-9e14-f3c9ddf0259f",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-95ca10cecf8fe36e",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "### Aufgabe - Arbeitszeit abschätzen\n",
    "\n",
    "*7 Punkte*\n",
    "\n",
    "Du befindest dich in der Situation wieder das dein Chef dich damit Beauftragt zwei wichtige Aufgaben bis zum Ende des Arbeitstages zu bearbeiten. Im Gegennsatz dazu bist du Abends auf einem Grillfest mit deinen Freunden verabredet. Dieses findet um 18 Uhr statt. Da du dich nun im zwiespalt befindest deinen Beruflichen Aufgaben nachzukommen und auf dem Grillfest zu erscheinen, fragst du dich im nächsten Schritt wie hoch die Chance ist, dass in 9 Stunden anstehende Grillfest pünktlich zu erreichen und gleichzeitig deinen Beruflichen Verpflichtungen nachzukommen.\n",
    "\n",
    "Nach einigen gut durchdachten Überlegungen stellst du folgendes fest:\n",
    "\n",
    "- An der ersten Aufgabe sitzt du zwischen 1-5 Stunden.\n",
    "- An der zweiten Aufgabe sitzt du zwischen 2-6 Stunden.\n",
    "- Egal wie schnell du eine Aufgabe löst es gibt keine Auswirkungen auf die andere Aufgabe. (Sie sind unabhängig voneinander)\n",
    "\n",
    "Stell im folgenden fest wie hoch die Warscheinlichkeit ist das du pünktlich beim Grillfest angelangst.\n",
    "\n",
    "Gehe dabei wie folgt vor:\n",
    "\n",
    "- Nehme an das beide Aufgaben gleichmäßig Verteilt sind, und speichere die Verteilungen in den Variablen `exc1` & `exc2`.\n",
    "- Verwende eine geeignete Anzahl an samples. Speichere den gewählten Wert in der variablen `sims`.\n",
    "- Speichere die Wahrscheinlichkeit mit der du es zum Grillfest schaffst in der Variablen `chance`, mit einer genauigkeit von zwei nachkommmastellen.\n",
    "- Plotte geeignet. Beziehe auch die Variable `chance` mit ein."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "cb2bda83-a3f7-4c46-a2be-f809ec55558c",
   "metadata": {
    "editable": true,
    "nbgrader": {
     "grade": true,
     "grade_id": "cell-65cc1054d6bb7253",
     "locked": false,
     "points": 2,
     "schema_version": 3,
     "solution": true,
     "task": false
    },
    "slideshow": {
     "slide_type": ""
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 12896 characters]",
      "text/plain": [
       "<Figure size 1000x500 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import numpy as np\n",
    "rand = np.random.default_rng(42) # Use this rng!\n",
    "# BEGIN SOLUTION\n",
    "import matplotlib.pyplot as plt\n",
    "sims = 1_000 # 1 Punkt\n",
    "\n",
    "# 2 Punkte\n",
    "exc1 = rand.uniform(1,5,sims) \n",
    "exc2 = rand.uniform(2,6,sims)\n",
    "\n",
    "duration = exc1 + exc2 # 1 Punkt\n",
    "chance = float(np.round((duration > 9).sum()/sims, decimals=2)) # 1 Punkt\n",
    "\n",
    "plt.figure(figsize=(10,5))\n",
    "plt.hist(duration, density=True) # 1 Punkt\n",
    "plt.axvline(9, color='r') # 1 Punkt\n",
    "plt.show()\n",
    "# END SOLUTION"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "id": "0910695e-4c60-4608-9152-519db84687d9",
   "metadata": {
    "nbgrader": {
     "grade": true,
     "grade_id": "cell-9fd6737ce69879f1",
     "locked": true,
     "points": 5,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [],
   "source": [
    "# Hier werden ihre Lösungen getestet...\n",
    "import math\n",
    "assert math.isclose(chance, 0.13, rel_tol=0.1)\n",
    "\n",
    "### BEGIN HIDDEN TESTS\n",
    "assert sims > 999\n",
    "assert sims < 10_000_000\n",
    "\n",
    "trand = np.random.default_rng(42)\n",
    "\n",
    "texc1 = trand.uniform(1,5,sims) \n",
    "texc2 = trand.uniform(2,6,sims)\n",
    "\n",
    "assert np.array_equal(exc1, texc1)\n",
    "assert np.array_equal(exc2, texc2)\n",
    "### END HIDDEN TESTS"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "aaaf624d-63ed-4645-a793-0ef2aebcb44d",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-8eb45ec252910d85",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "### Aufgabe - Simulation einer Körpergewichtszunahme\n",
    "\n",
    "*13 Punkte*\n",
    "\n",
    "Gegeben sind die nach Altersgruppe aufgeschlüsselten Durschnittskörpergewichte (in kg) von Männern in Deutschland. (Zu finden beim [Statistischen Bundesamt](https://www.destatis.de/DE/Themen/Gesellschaft-Umwelt/Gesundheit/Gesundheitszustand-Relevantes-Verhalten/Tabellen/koerpermasse-maenner.html))\n",
    "\n",
    "Nutze die Monte Carlo Methode um den mittleren Gewichtszuwachs der Bezugsgrößen zu bestimmen.\n",
    "Die mittlere Gewichtsschwankung eines Durschnittsmannes beträgt 2.5kg über den Tag verteilt. \n",
    "Finde die Wahrscheinlichkeit mit der ein Durchschnittsmann pro Woche (7 Tage) 3 kilogramm abnimmt und speichere das Ergebniss in der Variablen `gain_percent`.\n",
    "\n",
    "Beachte:\n",
    "\n",
    "- Bestimmt das arithmetische Mittel der Durchschnittsgewichte über die Altersgruppen. Speichere den Wert in `avg_weight` mit einer Präsizion von 1 Dezimalstelle.\n",
    "- Verwende eine geeignete Anzahl an samples. Speichere den gewählten Wert in der variablen `sims`.\n",
    "- Nehme an das das Durchschnittsgewicht Normal Verteilt ist und mit einer Standardabweichung von 5% zum Durschnittswert. Speichere deine Samples in der Variablen `men_normal`.\n",
    "- Nehme an das die Gewichtsschwankung pro Tag Gleich Verteilt ist. Speichere die simulierten zunahmen für eine Woche in der Liste `gain_week`.\n",
    "- Berechne die Durschnittliche Gewichtszunahme/abnahme und speichere das Ergebnis in der Variablen `duration`.\n",
    "- Plotte Angemessen. Beziehe dabei alle relevanten Werte mit ein.\n",
    "- Begründe mit einem kurzen Text dein Vorgehen und erkläre dein Ergebnis, beschreibe als letztes die Aussage deines Plottes."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 93,
   "id": "b8b21830-be8e-43f2-ae68-7e1867aa46e4",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-a9d02e6e26d7f2eb",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [],
   "source": [
    "# Given\n",
    "avg_weight_per_men = {\n",
    "    \"18 - 20\": 77.9,\n",
    "    \"20 - 25\": 80.5,\n",
    "    \"25 - 30\": 83.3,\n",
    "    \"30 - 35\": 85.6,\n",
    "    \"35 - 40\": 86.7,\n",
    "    \"40 - 45\": 88.1,\n",
    "    \"45 - 50\": 89.8,\n",
    "    \"50 - 55\": 89.0,\n",
    "    \"55 - 60\": 88.8,\n",
    "    \"60 - 65\": 87.9,\n",
    "    \"65 - 70\": 86.7,\n",
    "    \"70 - 75\": 85.3,\n",
    "    \"75+\": 81.0\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 88,
   "id": "926897fc-25a8-470c-b06b-946f7370a048",
   "metadata": {
    "nbgrader": {
     "grade": true,
     "grade_id": "cell-ef59ae554f2f4540",
     "locked": false,
     "points": 2,
     "schema_version": 3,
     "solution": true,
     "task": false
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 15724 characters]",
      "text/plain": [
       "<Figure size 1000x500 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.31\n"
     ]
    }
   ],
   "source": [
    "rand = np.random.default_rng(420) # Use this rng!\n",
    "\n",
    "# BEGIN SOLUTION\n",
    "avg_weight = np.round(np.mean(list(avg_weight_per_men.values())), decimals=1) # 1 Punkt\n",
    "\n",
    "sims = 1_000 # 1 Punkt\n",
    "\n",
    "# 3 Punkte\n",
    "sigma = np.round(avg_weight * 0.05, decimals=1)\n",
    "men = rand.normal(avg_weight, sigma, sims)\n",
    "gain_week = [\n",
    "    rand.uniform(-2.5, 2.5, sims)\n",
    "    for _ in range(7)\n",
    "]\n",
    "\n",
    "# Sum up 2 Punkte\n",
    "duration = np.zeros(sims)\n",
    "for gain in gain_week:\n",
    "    duration += gain\n",
    "duration += men\n",
    "\n",
    "gain_percent = float(np.round((duration < avg_weight-3).sum()/sims, decimals=2)) # 1 Punkt\n",
    "\n",
    "plt.figure(figsize=(10,5))\n",
    "plt.hist(duration, density=True) # 1 Punkt\n",
    "plt.axvline(avg_weight-3, color='r') # 1 Punkt\n",
    "plt.show()\n",
    "print(gain_percent)\n",
    "# END SOLUTION"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "01d0d2ee-af6a-46b4-8cdf-652024bb468d",
   "metadata": {
    "nbgrader": {
     "grade": true,
     "grade_id": "cell-089ff54f3c3db43b",
     "locked": false,
     "points": 3,
     "schema_version": 3,
     "solution": true,
     "task": false
    }
   },
   "source": [
    "**Begründe dein Vorgehen:**\n",
    "\n",
    "**Erkläre dein Ergebnis:**\n",
    "\n",
    "**Interpretiere & Erkläre deinen Plot:**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 94,
   "id": "dfe81dfc-5096-4c5b-8e84-81267e212cfa",
   "metadata": {
    "nbgrader": {
     "grade": true,
     "grade_id": "cell-87149b330de46548",
     "locked": true,
     "points": 8,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [],
   "source": [
    "# Hier werden ihre Lösungen getestet...\n",
    "import math\n",
    "assert math.isclose(float(gain_percent), 0.3, rel_tol=0.1)\n",
    "\n",
    "### BEGIN HIDDEN TESTS\n",
    "assert sims > 499\n",
    "assert sims < 2_001\n",
    "\n",
    "trand = np.random.default_rng(420)\n",
    "\n",
    "t_sigma = np.round(avg_weight * 0.05, decimals=1)\n",
    "t_men = trand.normal(avg_weight, sigma, sims)\n",
    "t_gain_week = [\n",
    "    trand.uniform(-2.5, 2.5, sims)\n",
    "    for _ in range(7)\n",
    "]\n",
    "\n",
    "assert math.isclose(sigma, t_sigma, rel_tol=0.1)\n",
    "\n",
    "for el1, el2 in zip(gain_week, t_gain_week):\n",
    "    assert np.array_equal(el1, el2)\n",
    "\n",
    "assert np.array_equal(t_men, men)\n",
    "\n",
    "t_duration = np.zeros(sims)\n",
    "for gain in t_gain_week:\n",
    "    t_duration += gain\n",
    "t_duration += t_men\n",
    "\n",
    "assert np.array_equal(t_duration, duration)\n",
    "### END HIDDEN TESTS"
   ]
  }
 ],
 "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.12.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
