{ "cells": [ { "cell_type": "markdown", "id": "04598fd5-c190-479e-a252-457a3ed02c52", "metadata": {}, "source": [ "# Stochastik programmieren" ] }, { "cell_type": "markdown", "id": "9b4163a3-d84b-42ec-b927-6888e3bc159b", "metadata": {}, "source": [ "Wir wollen uns nun kurz damit beschäftigen, wie sich mit Python Stichproben von Zufallsexperimenten simulieren lassen.\n", "\n", "## Wahrscheinlichkeitsmaß implementieren" ] }, { "cell_type": "code", "execution_count": 1, "id": "1b9aa059-0486-4d8b-aff3-37a5f9cbb5d8", "metadata": {}, "outputs": [], "source": [ "from fractions import Fraction\n", "\n", "def P(A, Omega):\n", " \"\"\"Die Wahrscheinlichkeit für das Ereignis A,\n", " gegeben gleich wahrscheinliche Ergebnisse aus einem Ergebnisraum Ω.\"\"\"\n", " return Fraction(len(A & Omega), len(Omega))" ] }, { "cell_type": "markdown", "id": "2080149c-7800-4728-acb3-579a89f46971", "metadata": {}, "source": [ "Wir werden damit nun einen Würfelwurf programmieren:" ] }, { "cell_type": "code", "execution_count": 2, "id": "a03a347d-86fb-4098-98ba-c7c1cd3ed715", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Gerade Würfelaugen: {2, 4, 6}\n", "Wahrscheinlichkeit für gerade Augenzahl: 1/2\n" ] } ], "source": [ "W = {1, 2, 3, 4, 5, 6}\n", "gerade = set((x*2 for x in range(1,4)))\n", "print(\"Gerade Würfelaugen:\",gerade)\n", "\n", "print(\"Wahrscheinlichkeit für gerade Augenzahl:\", P(gerade, W))" ] }, { "cell_type": "markdown", "id": "1a17807c-4adb-4482-8836-1a892b6af8d6", "metadata": {}, "source": [ "Damit haben wir nun das Wahrscheinlichkeitsmaß. Wenn wir eine Stichprobe ziehen wollen, müssen wir noch irgendwo den \"Zufall\" her bekommen.\n", "\n", "## Zufall importieren\n", "\n", "Python bietet mit dem `random`-Modul eine Schnittstelle zu Pseudozufallszahlen. Die Methode `random.random` ist ein direkt in C implementierter Mersenne Twister. Wenn man \"echte\" Zufallszahlen braucht, etwa für kryptografische Zwecke, gibt es dazu das `secrets`-Modul. Den Seed für den Mersenne Twister kann man angeben, und sollte man auch, um Zufallssimulationen reproduzierbar zu machen." ] }, { "cell_type": "code", "execution_count": 3, "id": "05a3b6f7-e7b6-4034-b3f9-807b20b47d6c", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on built-in function random:\n", "\n", "random() method of random.Random instance\n", " random() -> x in the interval [0, 1).\n", "\n", "0.7803255204450154\n", "0.13436424411240122\n" ] } ], "source": [ "from random import random as r\n", "help(r)\n", "print(r())\n", "\n", "import random\n", "random.seed(1)\n", "very_random = r()\n", "print(very_random)\n", "assert very_random == 0.13436424411240122" ] }, { "cell_type": "markdown", "id": "c862bd54-0c4f-4100-8654-4e86a6e3d3e1", "metadata": {}, "source": [ "\n", "\n", "[Link zum Comic (Randall Munroe, CC-BY-NC 2.5)](https://xkcd.com/221)\n", "\n", "Aus einer (Pseudo)zufallszahl zwischen $0$ und $1$ (man beachte: evtl. $0$ aber nie $1$) lassen sich zufällige Würfelwürfe erzeugen:" ] }, { "cell_type": "code", "execution_count": 4, "id": "c453b1a1-9693-401c-ab9e-fb39a13c81a2", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[6, 5, 2, 3, 3, 4, 5, 1, 1, 6, 3, 5, 1, 3, 5, 2, 6, 6, 1, 1, 4, 6, 3, 2, 3, 1, 2, 3, 3, 2, 2, 2, 3, 2, 1, 6, 4, 4, 2, 6, 6, 1, 2, 5, 5, 6, 3, 5, 5, 2, 4, 6, 6, 4, 4, 1, 2, 5, 3, 2, 4, 5, 5, 3, 3, 4, 5, 4, 3, 3, 1, 1, 5, 6, 4, 3, 2, 4, 6, 5, 4, 6, 2, 4, 6, 4, 3, 2, 4, 6, 1, 5, 5, 6, 5, 5, 4, 4, 3, 1]\n" ] } ], "source": [ "from math import floor\n", "def transform_unit_to_dice(x):\n", " return floor(1 + 6*x)\n", "\n", "assert list(range(1,7)) == [transform_unit_to_dice((x-1)/6)\n", " for x in range(1,7)]\n", "\n", "print([transform_unit_to_dice(r()) for n in range(100)])\n", " " ] }, { "cell_type": "markdown", "id": "beac5e48-9b2d-410b-9ddd-a9898347d71b", "metadata": {}, "source": [ "Damit man solche Transformationen nicht andauernd programmieren muss, kann man hier auch auf `random.randint(1,6)` oder auch auf `random.choice(range(1,7))` oder `random.randrange(1,7)` zurückgreifen. Dabei ist `randint` ein Kürzel für das entsprechende `randrange` und `choice` ist etwas allgemeiner.\n", "\n", "Wir wollen aber festhalten: gegeben eine gleichverteilte \"Zufallsvariable\" $X=$`random.random` mit Werten in $[0,1)$ haben wir eine Abbildung $t =$`transform_unit_to_dice` konstruiert und implementiert, die Werte in $\\{1,2,3,4,5,6\\}$ hat und $t(X)$ ist gleichverteilt. Die mathematische Abbildung $t$ ist eine Zufallsvariable, wir behandeln die Verknüpfung $t \\circ X$ als Zufallsvariable, die den Würfel modelliert.\n", "\n", "Nun könnte man sich beschweren: `random.random()` nimmt gar keinen Parameter, ist also keine mathematische Abbildung von einem Definitionsbereich in die Menge $[0,1)$. Tatsächlich müssen wir uns vorstellen, dass es eine Abbildung $X \\colon \\Omega \\to [0,1)$ ist, und auf $\\Omega$ ein irgendwie geartetes Wahrscheinlichkeitsmaß definiert ist, sodass durch $X$ auf $[0,1)$ die Gleichverteilung induziert wird. Die Menge $\\Omega$ spielt für uns keine konkrete Rolle - da \"kommt der Zufall her\" und in der Notation `random.random()` sehen wir schon, dass wir eben kein konkretes Element von $\\Omega$ einsetzen, sondern pseudozufällig eins ziehen und das in $X$ einsetzen." ] }, { "cell_type": "markdown", "id": "77aab03c-2b4f-4e83-bf3c-bc7b8cb3d5f4", "metadata": {}, "source": [ "## Größere Stichproben" ] }, { "cell_type": "markdown", "id": "d2571d1b-b44c-436d-a72f-f8385a1e4255", "metadata": {}, "source": [ "Die Methode `random.sample(population, k)` erlaubt es eine Stichprobe der Größe $k$ aus einer Population (einer Urne) zu ziehen - ziehen mit Zurücklegen. Für $k=1$ entspricht das einer Gleichverteilung auf der Population.\n", "Mit der Methode `random.choices(population, weights=None, *, cum_weights=None, k=1)` kann man das ziehen aus der Population $k$-mal sampeln (und dabei anstelle einer geeigneten Population auch Gewichte vergeben)." ] } ], "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.9.12" } }, "nbformat": 4, "nbformat_minor": 5 }