Compare commits

..

37 Commits

Author SHA1 Message Date
955a442c60 master > master: handschrift - woche 15 aktualisiert 2023-02-04 15:16:01 +01:00
995f86831f master > master: handschrift - woche 15 2023-02-02 20:29:06 +01:00
f742235573 master > master: handschrift - wochen 10–14 2023-02-02 15:09:07 +01:00
050dde99f6 master > master: nb - plotformatierung 2023-01-05 16:23:25 +01:00
b94b763cf1 master > master: justfile - export rezept 2022-12-15 07:35:21 +01:00
672968bdfb master > master: notebook - wk10 - cleanup 2022-12-15 07:35:09 +01:00
7115e3ce7a master > master: notebook - wk10 2022-12-15 07:14:02 +01:00
76a6564a3e master > master: requirements 2022-12-15 07:06:01 +01:00
847e7744ff master > master: src - für notebook wk10 2022-12-15 07:05:50 +01:00
0384334ce0 master > master: notes - woche 9
- 2 Beweise für Sem 9.2a)
- Lsg für Sem 9.2b)+c)
2022-12-09 16:37:11 +01:00
1830ccb5c7 master > master: notes - woche 9
- was im Unterricht besprochen wurde
- Lsg zu HA 8 wurden anhand des Blatts diskutiert
2022-12-09 10:31:06 +01:00
452d363235 master > master: notes - woche 8 2022-12-02 18:11:35 +01:00
c0cfd59beb master > master: notes - woche 7 2022-11-24 22:39:39 +01:00
60f8f11c83 master > master: notes - woche 6 korrigiert 2022-11-18 12:52:18 +01:00
cf5c8b213e master > master: notes 2022-11-17 21:35:29 +01:00
04fe01eb35 master > master: wochen 2+3 2022-10-27 21:39:38 +02:00
078e28903c master > master: requirements - versions up 2022-10-24 18:09:25 +02:00
32663124a5 master > master: minor 2022-10-24 18:09:06 +02:00
c2ac8e4c13 master > master: notebook - cleanup 2022-10-23 14:13:30 +02:00
dc5918682c master > master: src - cleanup 2022-10-23 14:13:02 +02:00
8d585f96c7 master > master: justfile - logs 2022-10-23 14:12:36 +02:00
240c673762 master > master: notebook - dynamische Anpassung
- optionen für Fkt-Eigenschaften beschränkt durch Kardinalitäten der Mengen
2022-10-22 18:39:01 +02:00
011fe1d9d9 master > master: src - fct properties als radiobuttons 2022-10-22 10:24:11 +02:00
cbee2b33dd master > master: notebook - minor 2022-10-22 09:18:36 +02:00
1d627623c7 master > master: src - clean up
- enums für Alphabete
- button layout
- refresh Knopf
- aspect ratio
2022-10-22 09:15:34 +02:00
56744bd389 master > master: notebook - widgets 2022-10-21 22:10:11 +02:00
6f24f4f635 master > master: src - widgets 2022-10-21 22:08:09 +02:00
f9186f0464 master > master: justfile
issue mit jupyter widgets
2022-10-21 22:07:35 +02:00
9a2c87def3 master > master: requirements
issue mit jupyter widgets
2022-10-21 22:07:26 +02:00
a54f71a848 master > master: notebook cleanup 2022-10-20 22:23:41 +02:00
8ece98121d master > master: src - Formatierung von Plots 2022-10-20 22:15:58 +02:00
55562889eb master > master: notebook woche 2 2022-10-20 22:04:15 +02:00
96684d30a8 master > master: src - methoden funktionieren 2022-10-20 22:04:06 +02:00
7b237246da master > master: notebook woche 2 2022-10-20 16:22:22 +02:00
bad02def40 master > master: justfile - gen models param 2022-10-20 16:22:10 +02:00
e6f2d8afea master > master: requirements 2022-10-20 16:21:57 +02:00
5e307eb355 master > master: src 2022-10-20 16:21:50 +02:00
47 changed files with 1459 additions and 145 deletions

4
.gitignore vendored
View File

@@ -28,6 +28,10 @@
!/templates
!/templates/template*
!/notes/
!/notes/week*.pdf
!/notes/README.md
!/src
!/src/**/
!/src/**/*.py

View File

@@ -1,6 +1,7 @@
# Mathematik für Physiker I, WiSe 2022-23 #
Der Inhalt dieses Repository ist keineswegs verpflichtend, sondern dient dem Zweck, „Handnotizen“ anzubieten.
Der Inhalt dieses Repository ist keineswegs verpflichtend,
sondern dient dem Zweck, „Handnotizen“ anzubieten (siehe insbesondere den [./notes/](notes/) Ordner).
Es besteht hier kein Anspruch auf Vollständigkeit.
Es werden hier keine offiziellen Lösungen für die Übungsblätter gespeichert.
@@ -11,6 +12,7 @@ findet man ausschließlich auf der **Moodle**-Seite.
```text
.
├── ./notes # Handschrift aus ÜG
├── ./notebooks # Python/Jupyter Notebooks
│ ├── ...
│ └── ... *.ipynb Dateien

View File

@@ -68,6 +68,7 @@ _generate-models path name:
--encoding "UTF-8" \
--disable-timestamp \
--use-schema-description \
--set-default-enum-member \
--allow-population-by-field-name \
--snake-case-field \
--strict-nullable \
@@ -103,6 +104,7 @@ build-misc:
@just _copy-file-if-not-exists "templates/template.env" ".env"
build-requirements:
@{{PYTHON}} -m pip install --disable-pip-version-check -r requirements.txt
@{{PYTHON}} -m jupyter nbextension enable --py widgetsnbextension
build-models:
@echo "Generate data models from schemata."
@just _delete-if-folder-exists "models/generated"
@@ -119,6 +121,17 @@ dist:
@just build
@just build-documentation
# exports notebook to format: html, markdown, pdf, latex.
export name format="pdf" theme="light":
@{{PYTHON}} -m jupyter nbconvert \
--allow-chromium-download \
--HTMLExporter.theme={{theme}} \
--TemplateExporter.exclude_input=false \
--to {{format}} \
--output-dir notes \
--ouput "notebook-{{name}}.{{format}}" \
notebooks/{{name}}.ipynb
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# TARGETS: run
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -222,6 +235,9 @@ _display-logs:
@- cat logs/debug.log
@echo ""
@echo "----------------"
logs:
@just _create-logs
@tail -f logs/debug.log &
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# TARGETS: processes

12
main.py
View File

@@ -1,9 +1,9 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
import os;
import sys;
@@ -11,17 +11,17 @@ import sys;
os.chdir(os.path.dirname(__file__));
sys.path.insert(0, os.getcwd());
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# MAIN
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def enter():
print('Not yet implemented.');
return;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXECUTION
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if __name__ == '__main__':
# sys.tracebacklimit = 0;

View File

@@ -1,67 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Woche 0 - 10.-16. Oktober 2022 #\n",
"\n",
"Herzlich willkommen zur 0. Woche!"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import os;\n",
"import sys;\n",
"\n",
"# NOTE: need this to force jupyter to reload imports:\n",
"for key in list(sys.modules.keys()):\n",
" if key.startswith('src.'):\n",
" del sys.modules[key];\n",
"\n",
"os.chdir(os.path.dirname(_dh[0]));\n",
"sys.path.insert(0, os.getcwd());\n",
"\n",
"from src.thirdparty.maths import *;\n",
"from src.thirdparty.render import *;\n",
"\n",
"np.random.seed(8007253); # zur Wiederholbarkeit"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"A = np.random.randint(-100, 100, size=(4, 7));\n",
"display(array_to_latex(A, precision=3));"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.10.6 64-bit",
"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.10.6"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

265
notebooks/week-10.ipynb Normal file
View File

@@ -0,0 +1,265 @@
{
"cells": [
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"# Woche 10 #\n",
"\n",
"Diese Wochen beschäftigen wir uns mit Matrizen und Vektoren.\n",
"In diesem Notebook rechnen wir ein paar (Teil)aufgaben aus dem ÜB."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"'''IMPORTS'''\n",
"import os;\n",
"import sys; \n",
"\n",
"# NOTE: need this to force jupyter to reload imports:\n",
"for key in list(sys.modules.keys()):\n",
" if key.startswith('src.'):\n",
" del sys.modules[key];\n",
"\n",
"os.chdir(os.path.dirname(_dh[0]));\n",
"sys.path.insert(0, os.getcwd());\n",
"\n",
"from src.thirdparty.maths import *;\n",
"from src.thirdparty.misc import *;\n",
"from src.thirdparty.render import *;\n",
"from src.maths.diagrams import *;\n",
"\n",
"np.random.seed(8007253); # zur Wiederholbarkeit"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"'''BEISPIEL-SIGNAL'''\n",
"n = 100;\n",
"u = np.zeros((n,), dtype=complex);\n",
"u[8] = -0.7\n",
"u[58] = 1j * sqrt(2);\n",
"\n",
"display_signal(u, 'Beispiel eines Vektors in $\\mathbb{C}^{100}$ als Signal über $\\{0,1,2,\\ldots,99\\}$ dargestellt');"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"'''SEMINARAUFGABE 10.4 a)'''\n",
"n = 3;\n",
"t = linspace(0, n-1, n);\n",
"i, j = np.meshgrid(t, t);\n",
"theta = 2*pi * i * j / n;\n",
"\n",
"# definiere die Matrix F_n + die Vektoren u_nk\n",
"F_n = (1/sqrt(n)) * exp(-1j * theta);\n",
"u_n = [ (1/sqrt(n)) * exp(1j * theta[:, k]) for k in range(n) ];\n",
"\n",
"print(dedent(\n",
" f'''\n",
" Matrix:\n",
"\n",
" F_{n} = \\n{np.round(F_n, 3)}\n",
" '''\n",
"));\n",
"print('');\n",
"\n",
"# NOTE: Programmiersprachen können nicht exakt berechnen.\n",
"# Darum entstehen winzige Fehler, die sich durch Runden entfernen lassen.\n",
"print('Matrix-Vektor-Produkte:');\n",
"for k in range(n):\n",
" result = F_n @ u_n[k];\n",
" print(dedent(\n",
" f'''\n",
"\n",
" u_{{n {k}}} = {np.round(u_n[k], 3)}\n",
" F_n · u_{{n {k}}} = {np.round(result, 3)}\n",
" '''\n",
" ));"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## Seminaraufgabe 10.4 b) ##\n",
"\n",
"Für $i\\in\\{0,1,\\ldots,n-1\\}$ ist die $i$-te von $\\mathcal{F}_{n}\\,u_{n,k}$\n",
"\n",
"$$\n",
" \\begin{array}{rcl}\n",
" (\\mathcal{F}_{n}\\,u_{n,k})_{i}\n",
" &= &\\displaystyle\\sum_{j=0}^{n-1}\n",
" (\\mathcal{F}_{n})_{ij}\\,(u_{n,k})_{j}\\\\\n",
" &= &\\displaystyle\\sum_{j=0}^{n-1}\n",
" \\tfrac{1}{\\sqrt{n}}\n",
" \\exp(-\\imath\\tfrac{2\\pi\\,ij}{n})\n",
" \\cdot\n",
" \\tfrac{1}{\\sqrt{n}}\n",
" \\exp(\\imath\\tfrac{2\\pi\\,kj}{n})\\\\\n",
" &= &\\frac{1}{n}\\displaystyle\\sum_{j=0}^{n-1}\n",
" \\underbrace{\n",
" \\exp(\\imath\\tfrac{2\\pi\\,(k-i)j}{n})\n",
" }_{= r^{j}}\\\\\n",
" \\end{array}\n",
"$$\n",
"\n",
"wobei $r := \\exp(\\imath\\tfrac{2\\pi\\,(k-i)}{n})$.\n",
"Wir haben, dass\n",
" $r = 1$\n",
" $\\Leftrightarrow$\n",
" $\\tfrac{k-i}{n} \\in \\mathbb{Z}$\n",
" $\\Leftrightarrow$\n",
" $i = k$,\n",
"da $0\\leq i,k \\leq n-1$.\n",
"<br>\n",
"Es gilt außerdem $r^{n} = \\exp(\\imath 2\\pi\\,(k-i)) = 1$.\n",
"<br>\n",
"Aus der o.s. Berechnung erhält man also\n",
"\n",
"$$\n",
" \\begin{array}{rcl}\n",
" (\\mathcal{F}_{n}\\,u_{n,k})_{i}\n",
" &= &\\tfrac{1}{n}\\displaystyle\\sum_{j=0}^{n-1}r^{j}\\\\\n",
" &= &\\tfrac{1}{n}\n",
" \\left\\{\n",
" \\begin{array}{lcl}\n",
" \\displaystyle\\sum_{j=0}^{n-1}1 &: &i = k\\\\\n",
" \\dfrac{1 - r^{n}}{1 - r} &: &\\text{sonst}\\\\\n",
" \\end{array}\n",
" \\right.\\\\\n",
" &= &\\tfrac{1}{n}\n",
" \\left\\{\n",
" \\begin{array}{lcl}\n",
" n &: &i = k\\\\\n",
" \\dfrac{1 - 1}{1 - r} &: &\\text{sonst}\\\\\n",
" \\end{array}\n",
" \\right.\\\\\n",
" &= &\\left\\{\n",
" \\begin{array}{lcl}\n",
" 1 &: &i = k\\\\\n",
" 0 &: &\\text{sonst}\\\\\n",
" \\end{array}\n",
" \\right.\\\\\n",
" &= &\\delta_{ik}.\\\\\n",
" \\end{array}\n",
"$$\n",
"\n",
"Darum $\\mathcal{F}_{n}\\,u_{n,k}\n",
" = \\left(\\begin{matrix}\n",
" 0\\\\\n",
" 0\\\\\n",
" \\vdots\\\\\n",
" 1\\\\\n",
" \\vdots\\\\\n",
" 0\\\\\n",
" \\end{matrix}\\right)\n",
" \\begin{matrix}\n",
" \\\\\n",
" \\\\\n",
" \\\\\n",
" \\leftarrow k\\\\\n",
" \\\\\n",
" \\\\\n",
" \\end{matrix}\n",
" = \\mathbf{e}_{k}$.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"'''SEMINARAUFGABE 10.4 d)'''\n",
"n = 4;\n",
"t = linspace(0, n-1, n);\n",
"i, j = np.meshgrid(t, t);\n",
"theta = 2*pi * i * j / n;\n",
"\n",
"# definiere die Matrix F_n + die Vektoren u_nk\n",
"F_n = (1/sqrt(n)) * exp(-1j * theta);\n",
"u_n = [ (1/sqrt(n)) * exp(1j * theta[:, k]) for k in range(n) ];\n",
"\n",
"# Eingabe des Vektors:\n",
"F_mal_u = np.asarray([100, -3, 0, -3]); # = F_n @ u\n",
"\n",
"'''\n",
"NOTE: Folgende Koeffizienten wurden falsch erraten.\n",
"TODO: Wie lauten die richtigen Werte? -> Aufgabe!\n",
"'''\n",
"c = [10,10,40,50];\n",
"\n",
"# Aufschreibung des Signals »bzgl. der harmonischen Basis«:\n",
"# u = c[0]u_n[0] + c[1]u_n[1] + c[2]u_n[2] + c[3]u_n[3]\n",
"u_guess = sum([ c[k] * u_n[k] for k in range(n) ]);\n",
"\n",
"# Anzeige der Lösung:\n",
"display_signal(u_guess, 'Geschätztes Signal');\n",
"\n",
"# Verifizierung der Lösung:\n",
"display_latex(\n",
" f'''\n",
" $$\n",
" \\\\begin{{array}}{{rcl}}\n",
" \\\\%\\\\text{{error}}\n",
" &\\colonequals\n",
" &\\\\dfrac{{\\\\|u_{{\\\\text{{guess}}}} - u\\\\|}}{{\\\\|u\\\\|}}\\\\\\\\\n",
" &=\n",
" &\\\\dfrac{{\n",
" \\\\|\\\\mathcal{{F}}_{{n}}\\\\,(u_{{\\\\text{{guess}}}} - u)\\\\|\n",
" }}{{\n",
" \\\\|\\\\mathcal{{F}}_{{n}}\\\\,u\\\\|\n",
" }}\n",
" \\\\quad\\\\text{{\\\\ldots wieso?? [Stichwort: unitär!]}}\\\\\\\\\n",
" &= &\\\\dfrac{{\n",
" \\\\|\\\\mathcal{{F}}_{{n}}\\\\,u_{{\\\\text{{guess}}}} - \\\\mathcal{{F}}_{{n}}\\\\,u\\\\|\n",
" }}{{\n",
" \\\\|\\\\mathcal{{F}}_{{n}}\\\\,u\\\\|\n",
" }}\\\\\\\\\n",
" &= &{linalg.norm(F_n @ u_guess - F_mal_u)/linalg.norm(F_mal_u):.2%}\n",
" \\\\%\n",
" \\\\\\\\\n",
" \\\\end{{array}}\n",
" $$\n",
" '''\n",
");\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"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.10.8"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

116
notebooks/week-2.ipynb Normal file
View File

@@ -0,0 +1,116 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Woche 2 - 17.-23. Oktober 2022 #\n",
"\n",
"Herzlich willkommen zur 2. Woche!\n",
"\n",
"## Agenda ##\n",
"\n",
"- [x] Struktur\n",
"- [x] Aufwärme\n",
"- [x] Seminaraufgaben 2.x\n",
"- ~~[ ] Besprechung von HA 1.x~~\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# imports\n",
"import os;\n",
"import sys; \n",
"\n",
"# NOTE: need this to force jupyter to reload imports:\n",
"for key in list(sys.modules.keys()):\n",
" if key.startswith('src.'):\n",
" del sys.modules[key];\n",
"\n",
"os.chdir(os.path.dirname(_dh[0]));\n",
"sys.path.insert(0, os.getcwd());\n",
"\n",
"from src.thirdparty.maths import *;\n",
"from src.thirdparty.render import *;\n",
"\n",
"from src.maths.diagrams import *;\n",
"from src.maths.sets import *;\n",
"from src.widgets import *;\n",
"\n",
"np.random.seed(8007253); # zur Wiederholbarkeit"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Userinput - Anzahl der Funktionen\n",
"fnames = ['f', 'g', 'h', 'i', 'j'];\n",
"setnames = ['X', 'Y', 'Z', 'U', 'V', 'W'];\n",
"ctrl = widgets.IntSlider(value=1, description=f'# Funktionen', min=1, max=len(fnames));\n",
"display(ctrl);"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Widget - Mengen und Funktionen\n",
"FunctionDiagramWidget(N=ctrl.value, fnames=fnames, setnames=setnames).run();"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# ohne Zufallserzeugung:\n",
"X = ['a', 'b', 'c', 'd', 'e'];\n",
"Y = [2, 3, 5, 7, 11, 13, 17];\n",
"Z = ['α', 'β', 'γ', 'δ'];\n",
"f = [('a', 5), ('b', 5), ('c', 17), ('d', 2), ('e', 5)]\n",
"g = [(2, 'γ'), (3, 'α'), (5, 'β'), (7, 'δ'), (11, 'β'), (13, 'γ'), (17, 'β')];\n",
"comp = Functions(\n",
" Function(name=('f', 'X', 'Y'), domain=X, codomain=Y, fct=f),\n",
" Function(name=('g', 'Y', 'Z'), domain=Y, codomain=Z, fct=g),\n",
");\n",
"comp.draw(show_labels=True);"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.10.8 64-bit",
"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.10.8"
},
"vscode": {
"interpreter": {
"hash": "98590ff4fe04c8543246b2a01debd3de3c5ca9b666f43f1fa87d5110c692004c"
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}

36
notebooks/week-3.ipynb Normal file
View File

@@ -0,0 +1,36 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Woche 3 - 24.-30. Oktober 2022 #\n",
"\n",
"Herzlich willkommen zur 3. Woche!\n",
"\n",
"## Agenda ##\n",
"\n",
"- [x] Besprechung von HA 2.x\n",
"- [x] Seminaraufgaben 3.x"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.10.8 64-bit",
"language": "python",
"name": "python3"
},
"language_info": {
"name": "python",
"version": "3.10.8"
},
"vscode": {
"interpreter": {
"hash": "98590ff4fe04c8543246b2a01debd3de3c5ca9b666f43f1fa87d5110c692004c"
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}

9
notes/README.md Normal file
View File

@@ -0,0 +1,9 @@
# Handnotizen #
Diese Notizen sollen _nicht_ als Musterlösungen verstanden werden.
Während der ÜG interagieren wir mit dem Stoff + den Aufgaben.
Wir besprechen **Konzepte** und **Ansätze**.
Diese Schrift ist also eine Abbildung dieser Diskussionen und Präsentationen.
Teilweise werden sie nur für die Leute Sinn ergeben, die daran teilgenommen haben und eigene Notizen machen.
Die Dokumente sind nicht vollständig, da einiges während der Stunden im Raum und an der Tafel erörtert wird.

BIN
notes/week10.pdf Normal file

Binary file not shown.

BIN
notes/week11.pdf Normal file

Binary file not shown.

BIN
notes/week12.pdf Normal file

Binary file not shown.

BIN
notes/week13.pdf Normal file

Binary file not shown.

BIN
notes/week14.pdf Normal file

Binary file not shown.

BIN
notes/week15.pdf Normal file

Binary file not shown.

BIN
notes/week2.pdf Normal file

Binary file not shown.

BIN
notes/week3.pdf Normal file

Binary file not shown.

BIN
notes/week4.pdf Normal file

Binary file not shown.

BIN
notes/week5.pdf Normal file

Binary file not shown.

BIN
notes/week6.pdf Normal file

Binary file not shown.

BIN
notes/week7.pdf Normal file

Binary file not shown.

BIN
notes/week8.pdf Normal file

Binary file not shown.

BIN
notes/week9.pdf Normal file

Binary file not shown.

View File

@@ -1,16 +1,22 @@
pip>=22.2.2
pip>=22.3.1
wheel>=0.37.1
# jupyter
ipython>=8.3.0
jupyter>=1.0.0
widgetsnbextension>=3.6.1
# FIXME
# according to https://github.com/microsoft/vscode-jupyter/issues/8552
# need to use v 7.7.2 for now
# ipywidgets>=8.0.2
ipywidgets==7.7.2
# running
codetiming>=1.3.0
# testing + dev
coverage[toml]>=6.4
pytest>=7.1.1
pytest>=7.2.0
pytest-asyncio>=0.18.3
pytest-cov>=3.0.0
pytest-lazy-fixture>=0.6.3
@@ -27,20 +33,19 @@ lorem>=0.1.1
safetywrap>=1.5.0
typing>=3.7.4.3
nptyping>=2.1.1
typing-extensions>=3.10.0.2
# config
python-dotenv>=0.20.0
jsonschema>=4.4.0
lazy-load>=0.8.2
pyyaml>=5.4.1
pyyaml>=6.0
pydantic>=1.9.1
datamodel-code-generator>=0.12.0
# maths
fraction>=2.2.0
numpy>=1.22.4
matplotlib>=3.5.1
matplotlib>=3.6.1
# tables, data frames
pandas>=1.4.2

View File

@@ -1,9 +1,9 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from __future__ import annotations;
@@ -13,32 +13,30 @@ from src.thirdparty.types import *;
from src.core.utils import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'CallState',
'GetState',
'CallValue',
'CallError',
'keep_calm_and_carry_on',
'run_safely',
'to_async',
];
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# CONSTANTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# local usage only
T = TypeVar('T');
V = TypeVar('V');
ARGS = ParamSpec('ARGS');
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Class State for keeping track of results in the course of a computation
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@dataclass
class CallState(Generic[V]):
@@ -153,9 +151,9 @@ def CallError(
x = list(map(str, x));
return CallState(tag=tag, errors=x, has_action=has_action, has_error=True);
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# DECORATOR - forces methods to run safely
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def run_safely(tag: str | None = None, error_message: str | None = None):
'''

View File

@@ -1,18 +1,18 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from src.thirdparty.code import *;
from src.thirdparty.config import *;
from src.thirdparty.system import *;
from src.thirdparty.types import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'get_env_string',
@@ -23,9 +23,9 @@ __all__ = [
'get_env_optional_float',
];
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# AUXILIARY METHODS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def get_env_value(env: dict, key: str, default: Any = None) -> Any: # pragma: no cover
return env[key] if key in env else default;

View File

@@ -1,9 +1,9 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from src.thirdparty.code import *;
from src.thirdparty.io import *;
@@ -13,9 +13,9 @@ from src.thirdparty.types import *;
from src.core.calls import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'LOG_LEVELS',
@@ -33,9 +33,9 @@ __all__ = [
'prompt_confirmation',
];
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# CONSTANTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class LOG_LEVELS(Enum): # pragma: no cover
INFO = logging.INFO;
@@ -45,9 +45,9 @@ class LOG_LEVELS(Enum): # pragma: no cover
_LOGGING_DEBUG_FILE: str = 'logs/debug.log';
T = TypeVar('T');
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# METHODS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def configure_logging(level: LOG_LEVELS): # pragma: no cover
logging.basicConfig(
@@ -73,9 +73,9 @@ def log_fatal(*messages: Any):
logging.fatal(*messages);
exit(1);
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Special Methods
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Intercept fatal errors
def catch_fatal(method: Callable[[], T]) -> T:
@@ -105,9 +105,9 @@ def log_result(result: Result[CallState, CallState], debug: bool = False):
log_error(e);
return;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# DEBUG LOGGING FOR DEVELOPMENT
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def log_dev(*messages: Any): # pragma: no cover
with open(_LOGGING_DEBUG_FILE, 'a') as fp:

View File

@@ -1,26 +1,26 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from src.thirdparty.code import *;
from src.thirdparty.misc import *;
from src.thirdparty.types import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'flatten',
'get_timestamp_string',
];
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# METHODS - date, time
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def get_timestamp() -> datetime: # pragma: no cover
return datetime.now();
@@ -28,9 +28,9 @@ def get_timestamp() -> datetime: # pragma: no cover
def get_timestamp_string() -> str: # pragma: no cover
return str(get_timestamp());
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# METHODS arrays
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def flatten(X: list[list[Any]]) -> list[Any]:
return list(itertools_chain.from_iterable(X));

0
src/maths/__init__.py Normal file
View File

View File

@@ -0,0 +1,19 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from src.maths.diagrams.sets import *;
from src.maths.diagrams.signal import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'Function',
'Functions',
'display_signal',
];

211
src/maths/diagrams/sets.py Normal file
View File

@@ -0,0 +1,211 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from __future__ import annotations;
from src.thirdparty.code import *;
from src.thirdparty.types import *;
from src.thirdparty.maths import *;
from src.thirdparty.plots import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'Function',
'Functions',
];
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# CONSTANTS / VARIABLES
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
T1 = TypeVar('T1');
T2 = TypeVar('T2');
SCALE = (1., 1.5);
OFFSET = (3., 0.);
HMARGIN = 0.1;
VMARGIN = 0.2;
N_RESOLUTION = 100;
ANNOTATE_OFFSET = (0, 10);
FONTSIZE_PTS = 10;
FONTSIZE_FCT = 14;
FONTSIZE_SETS = 14;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Classes
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@dataclass
class Function(Generic[T1,T2]):
name: tuple[str, str, str] = field();
domain: list[T1] = field();
codomain: list[T2] = field();
fct: list[tuple[T1,T2]] = field();
@property
def range(self) -> list[T2]:
return [y for x, y in self.fct];
@property
def indexes(self) -> list[tuple[int, int]]:
# prevent repeated computation:
if not hasattr(self, '_indexes'):
self._indexes = [
(self.domain.index(x), self.codomain.index(y))
for x, y in self.fct
];
return getattr(self, '_indexes');
def draw(self) -> tuple[Figure, Axes]:
return Functions(self).draw();
class Functions:
name: str;
fcts: list[Function];
def __init__(self, *f: Function):
self.fcts = list(f);
self.name = r' \circ '.join([ fct.name[0] for fct in self.fcts ][::-1]);
def draw(self, show_labels: bool = True) -> tuple[Figure, Axes]:
N = len(self.fcts);
obj = mplot.subplots(1, 1, constrained_layout=True);
fig: Figure = obj[0];
axs: Axes = obj[1];
axs.tick_params(axis='both', which='both', labelbottom=False, labelleft=False);
mplot.title(f'Darstellung von ${self.name}$', fontdict={
'fontsize': 16,
'horizontalalignment': 'center',
'color': 'forestgreen',
});
axs.set_facecolor((0.9,0.9,0.9))
mplot.xlabel('');
mplot.ylabel('');
mplot.margins(x=HMARGIN, y=VMARGIN);
origin = np.asarray((0., 0.));
offset = np.asarray(OFFSET);
p_set = oval(nr_points=N_RESOLUTION, scale=SCALE, centre=origin);
for k in range(N+1):
axs.plot(p_set[:, 0] + k*offset[0], p_set[:, 1] + k*offset[1], label='', color='blue');
p_domain = [];
p_codomain = [];
comp_range = [];
anchors = [
[
# function name
origin + (k + 0.5)*offset + (0, -1.1*SCALE[1]),
# sets
origin + k * offset + (0, 1.1 * SCALE[1]),
origin + (k + 1) * offset + (0, 1.1 * SCALE[1]),
# arrow start -> end
origin + (k + 0.05) * offset + (0, -1.1 * SCALE[1]),
origin + (k + 1 - 0.05) * offset + (0, -1.1 * SCALE[1]),
]
for k in range(N)
];
for k, f in enumerate(self.fcts):
if k == 0:
comp_range = f.domain;
p_domain = random_points(nr_points=len(f.domain), scale=SCALE, centre=origin + k*offset, tol=0.5);
else:
p_domain = p_codomain;
p_codomain = random_points(nr_points=len(f.codomain), scale=SCALE, centre=origin + (k+1)*offset, tol=0.5);
# range of composition so far:
comp_range_next = [y for x, y in f.fct if x in comp_range];
if k == 0:
axs.scatter(p_domain[:, 0], p_domain[:, 1], label='', color='blue', marker='o');
if show_labels:
for i, p in enumerate(p_domain):
x_name = f.domain[i];
axs.annotate(text=f'{x_name}', xy = p, textcoords='offset points', xytext=ANNOTATE_OFFSET, ha='center', size=FONTSIZE_PTS);
for j, p in enumerate(p_codomain):
y = f.codomain[j];
marker = 'o' if (y in comp_range_next) else '.';
axs.scatter([p[0]], [p[1]], label='', color='blue', marker=marker);
y_name = f.codomain[j];
if show_labels:
axs.annotate(text=f'{y_name}', xy=p, textcoords='offset points', xytext=ANNOTATE_OFFSET, ha='center', size=FONTSIZE_PTS);
for i, j in f.indexes:
p = p_domain[i];
q = p_codomain[j];
x = f.domain[i];
if k == 0 or (x in comp_range):
axs.plot([p[0], q[0]], [p[1], q[1]], label='', color='blue', linewidth=1);
else:
axs.plot([p[0], q[0]], [p[1], q[1]], label='', color='red', linestyle='--', linewidth=1);
anchor = anchors[k];
fct_name, X_name, Y_name = f.name;
axs.annotate(text=f'${fct_name}$', xy=anchor[0], ha='center', size=FONTSIZE_FCT);
if k == 0:
axs.annotate(text=f'${X_name}$', xy=anchor[1], ha='center', size=FONTSIZE_FCT);
axs.annotate(text=f'${Y_name}$', xy=anchor[2], ha='center', size=FONTSIZE_FCT);
axs.add_patch(FancyArrowPatch(
anchor[3], anchor[4],
connectionstyle = 'arc3,rad=0.5',
arrowstyle = 'Simple, tail_width=0.5, head_width=4, head_length=8',
color = 'black',
));
# update range of composition:
comp_range = comp_range_next;
axs.set_aspect('equal')
return fig, axs;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# AUXILIARY
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def oval(
nr_points: int,
scale: tuple[float, float] = (1., 1.),
centre: tuple[float, float] = (0., 0.),
) -> NDArray[Shape['*, 2'], Float]:
theta = np.linspace(start=0, stop=2*np.pi, num=nr_points, endpoint=True);
P = np.zeros(shape=(nr_points, 2), dtype=float);
P[:, 0] = centre[0] + scale[0] * np.cos(theta);
P[:, 1] = centre[1] + scale[1] * np.sin(theta);
P[-1, :] = P[0, :];
return P;
def random_points(
nr_points: int,
scale: tuple[float, float] = (1., 1.),
centre: tuple[float, float] = (0., 0.),
force: bool = False,
tol: float = 0.1,
) -> NDArray[Shape['*, 2'], Float]:
theta = np.linspace(start=0, stop=2*np.pi, num=nr_points, endpoint=False);
r_min = 0.25;
r_max = 1;
while True:
u = np.random.random(size=(nr_points,));
u_max = max(u);
if u_max == 0.:
continue;
if force:
u = np.minimum((1 + tol) * u / u_max, 1);
else:
u = (1 - tol) * u / u_max;
break;
r = r_min + (r_max - r_min) * u;
P = np.zeros(shape=(nr_points, 2), dtype=float);
P[:, 0] = centre[0] + scale[0] * r * np.cos(theta);
P[:, 1] = centre[1] + scale[1] * r * np.sin(theta);
return P;

View File

@@ -0,0 +1,48 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from __future__ import annotations;
from src.thirdparty.code import *;
from src.thirdparty.types import *;
from src.thirdparty.maths import *;
from src.thirdparty.plots import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'display_signal',
];
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# CONSTANTS / VARIABLES
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def display_signal(
u: np.ndarray,
title: str,
max_labels = 10,
):
n = len(u);
if n <= max_labels:
x_axis = list(range(n));
else:
skip = int(n/max_labels);
x_axis = [ k*skip for k in range(max_labels) ];
fig, axs = mplot.subplots(1, 1, constrained_layout=True);
mplot.title(title);
mplot.xlabel('»Zeit« [=Indizes]');
mplot.ylabel('Werte [=Einträge]');
axs.stem(linspace(0,n-1,n), np.real(u), label='reeller Teil', linefmt='red');
axs.stem(linspace(0,n-1,n) + 0.05, np.imag(u), label='imaginärer Teil', linefmt='lime');
mplot.legend();
axs.set_xticks(x_axis, labels=[ str(index) for index in x_axis]);
mplot.show();
return;

View File

@@ -0,0 +1,19 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from src.maths.sets.random import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'Letters',
'random_function',
'randomset_alphabet',
'randomset_integers',
];

142
src/maths/sets/random.py Normal file
View File

@@ -0,0 +1,142 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from __future__ import annotations;
from src.thirdparty.types import *;
from src.thirdparty.maths import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'Letters',
'randomset_integers',
'randomset_alphabet',
'random_function',
];
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# CONSTANTS / VARIABLES
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# local usage only
T1 = TypeVar('T1');
T2 = TypeVar('T2');
class Letters(Enum):
# 'abcdefghijklmnopqrstuvwxyz'
ROMAN = [chr(97 + n) for n in range(26)];
# 'αβγδεζηθικλμνξοπρςτυφχψω'
GREEK = [chr(945 + n) for n in range(25)]
# 'אבגדהוזחטיךכלםמןנסעףפץצקרשת' (but <—)
HEBREW = [chr(1488 + n) for n in range(27)];
SYMBOLS = [
r'$|0\rangle$',
r'$|\uparrow\rangle$',
r'$|\downarrow\rangle$',
r'$\sqrt{2}$',
r'$\pi$',
r'$e$',
r'$\frac{1}{137}$',
r'$\infty$',
# r'$-\infty$',
r'$\clubsuit$',
# r'$\diamondsuit$',
r'$\heartsuit$',
# r'$\spadesuit$',
r'$\hbar$',
];
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# METHODS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def randomset_integers(
N: int = -1,
low: int = 1,
high: int = 1,
shuffle: bool = False,
) -> list[int]:
if N == -1:
N = random.randint(low, high);
values = list(range(1, N+1));
if shuffle:
return sample(values, size=N, replace=False);
return values;
def randomset_alphabet(
mode: Letters,
N: int = -1,
low: int = 1,
high: int = 1,
shuffle: bool = False,
full: bool = False,
) -> list[str]:
letters: list[str] = mode.value;
if full:
N = len(letters);
elif N == -1:
high = min(low+1, high)
N = random.randint(low, high);
if shuffle:
return sample(letters, size=N, replace=False);
return letters[:N];
def random_function(
X: list[T1],
Y: list[T2],
injective: Optional[bool] = None,
surjective: Optional[bool] = None,
force: bool = False,
) -> list[tuple[T1, T2]]:
m = len(X);
n = len(Y);
if m == 0:
return [];
if n == 0:
raise Exception(f'Impossible to create a function with {m} elements in the domain and {n} in the codomain.');
if not force:
if injective and m > n:
injective = None;
if surjective and m < n:
surjective = None;
if not injective and m == 1:
injective = None;
if not surjective and n == 1:
surjective = None;
match (injective, surjective):
case (True, _):
assert m <= n, f'Impossible to create an injective function with {m} elements in the domain and {n} in the codomain.';
Y = random.sample(Y, m);
return [(x, y) for x, y in zip(X, Y)];
case (_, True):
assert m >= n, f'Impossible to create an surjective function with {m} elements in the domain and {n} in the codomain.';
indexes = random.sample(list(range(m)), n);
g = [ (indexes[j], Y[j]) for j in range(n) ] \
+ [
(i, random.choice(Y))
for i in range(m)
if not i in indexes
];
g = sorted(g, key=lambda o: o[0]);
return [ (X[i], y) for (i, y) in g ];
case (False, _):
assert m > 1, f'Impossible to create a non-injective function with {m} elements in the domain.';
indexes = random.sample(list(range(m)), m);
g = random_function(indexes, Y);
[(i0, y0), (i1, y1)] = g[:2];
g[0] = (i0, y1);
g = sorted(g, key=lambda o: o[0]);
return [ (X[i], y) for (i, y) in g ];
case (_, False):
assert n > 1, f'Impossible to create a non-surjective function with {n} elements in the codomain.';
Y = random.sample(Y, n-1);
return random_function(X, Y);
case _:
return [ (x, random.choice(Y)) for x in X ];

View File

@@ -25,9 +25,9 @@ from safetywrap import Result;
from safetywrap import Option;
from safetywrap import Some;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'partial',

View File

@@ -15,9 +15,9 @@ from yaml import load as yaml_load;
from yaml import FullLoader as yaml_FullLoader;
from yaml import add_path_resolver as yaml_add_path_resolver;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'load_dotenv',

View File

@@ -7,9 +7,9 @@
from getpass import getpass;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'getpass',

View File

@@ -8,9 +8,9 @@
import logging;
from logging import LogRecord;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'logging',

View File

@@ -6,17 +6,55 @@
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from fractions import Fraction;
from numpy import cos;
from numpy import exp;
from numpy import linalg;
from numpy import linspace;
from numpy import pi;
from numpy import sin;
from numpy import sqrt;
from typing import TypeVar;
import math;
import numpy as np;
import random;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# MODIFICATIONS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# local usage only
T = TypeVar('T');
def sample(
X: list[T],
size: int = 1,
replace: bool = True,
) -> list[T]:
'''
@inputs
- `X` - a list
- `size` <int> - desired sample size
- `replace` <bool> - optional replacement
@returns a sample from an uniformly distributed set.
'''
return np.random.choice(X, size=size, replace=replace).tolist();
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'Fraction',
'cos',
'exp',
'linalg',
'linspace',
'math',
'np',
'pi',
'random',
'sample',
'sin',
'sqrt',
];

View File

@@ -7,13 +7,66 @@
from datetime import datetime;
from datetime import timedelta;
from functools import wraps;
import lorem;
import re;
from textwrap import dedent;
from textwrap import dedent as textwrap_dedent;
from typing import Callable;
from typing import TypeVar;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# MODIFICATIONS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def prestrip(first: bool = True, last: bool = True, all: bool = False):
'''
Returns a decorator that modifies string -> string methods
'''
T = TypeVar('T');
def dec(method: Callable[[str], T]) -> Callable[[str], T]:
'''
Performs method but first strips initial/final (empty) lines.
'''
@wraps(method)
def wrapped_method(text: str) -> T:
lines = re.split(pattern=r'\n', string=text);
if all:
if first:
while len(lines) > 0 and lines[0].strip() == '':
lines = lines[1:];
if last:
while len(lines) > 0 and lines[-1].strip() == '':
lines = lines[:-1];
else:
if first:
lines = lines[1:];
if last:
lines = lines[:-1];
text = '\n'.join(lines);
return method(text);
return wrapped_method;
return dec;
@prestrip(all=False)
def dedent(text: str) -> str:
'''
Remove any common leading whitespace from every line in `text`.
This can be used to make triple-quoted strings line up with the left
edge of the display, while still presenting them in the source code
in indented form.
Note that tabs and spaces are both treated as whitespace, but they
are not equal: the lines " hello" and "\\thello" are
considered to have no common leading whitespace.
Entirely blank lines are normalized to a newline character.
'''
return textwrap_dedent(text);
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'lorem',

24
src/thirdparty/plots.py vendored Normal file
View File

@@ -0,0 +1,24 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from matplotlib import pyplot as mplot;
from matplotlib import colors as mcolours;
from matplotlib.figure import Figure;
from matplotlib.axes import Axes;
from matplotlib.patches import FancyArrowPatch;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'mplot',
'mcolours',
'Figure',
'Axes',
'FancyArrowPatch',
];

View File

@@ -6,22 +6,57 @@
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from IPython.display import Latex;
from IPython.display import display_latex;
from IPython.display import display_png;
from IPython.display import display_markdown;
from IPython.display import display;
from IPython.display import display_png;
from IPython.display import display as display_text_ipython;
from IPython.display import display_latex as display_latex_ipython;
from IPython.display import display_markdown as display_md_ipython;
import ipywidgets as widgets;
# from array_to_latex import to_ltx as array_to_latex; # <- has issues
from qiskit.visualization import array_to_latex;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from functools import wraps;
from typing import Callable;
from typing import TypeVar;
from src.thirdparty.misc import dedent;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# MODIFICATIONS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
T1 = TypeVar('T1');
T2 = TypeVar('T2');
def display_with_dedent(pre_process: Callable[[str], T1] = lambda x: x):
'''
Returns a decorator that modifies string -> string methods
'''
def dec(method: Callable[[T1], T2]) -> Callable[[str], T2]:
'''
Performs method but dedents first.
'''
@wraps(method)
def wrapped_method(text: str) -> T2:
return method(pre_process(dedent(text)));
return wrapped_method;
return dec;
display_latex = display_with_dedent(Latex)(display_latex_ipython);
display_text = display_with_dedent()(display_text_ipython);
display_markdown = display_with_dedent()(display_md_ipython);
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'Latex',
'array_to_latex',
'display',
'display_latex',
'display_png',
'display_markdown',
'array_to_latex',
'display_png',
'widgets',
];

View File

@@ -7,9 +7,9 @@
from codetiming import Timer;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'Timer',

View File

@@ -9,9 +9,9 @@ import os;
from pathlib import Path;
import sys;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'os',

View File

@@ -38,12 +38,12 @@ from typing import Generic;
from typing import Optional;
from typing import Type;
from typing import TypeVar;
from typing_extensions import Concatenate;
from typing_extensions import ParamSpec;
from typing import Concatenate;
from typing import ParamSpec;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'Enum',

16
src/widgets/__init__.py Normal file
View File

@@ -0,0 +1,16 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from src.widgets.function_diagrams import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'FunctionDiagramWidget',
];

View File

@@ -0,0 +1,325 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from __future__ import annotations;
from src.thirdparty.code import *;
from src.thirdparty.types import *;
from src.thirdparty.plots import *;
from src.thirdparty.maths import *;
from src.thirdparty.render import *;
from src.maths.diagrams import *;
from src.maths.sets import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__all__ = [
'FunctionDiagramWidget',
];
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class FunctionProperty(Enum):
NOTHING = '';
INJECTIVE = 'injektiv';
NOT_INJECTIVE = '¬ injektiv';
SURJECTIVE = 'surjektiv';
NOT_SURJECTIVE = '¬ surjektiv';
BOTH = 'injektiv + surjektiv';
INJECTIVE_NOT_SURJECTIVE = 'injektiv + ¬ surjektiv';
NOT_INJECTIVE_SURJECTIVE = '¬ injektiv + surjektiv';
NEITHER = '¬ injektiv + ¬ surjektiv';
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Class
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class FunctionDiagramWidget():
state: Optional[widgets.Output];
N: Optional[int];
N_max: int;
fnames: list[str];
setnames: list[str];
setsfrom: list[list[Any]];
card: list[int];
ctrl_nr: widgets.IntSlider;
btn_refresh: widgets.ToggleButton;
ctrls_card: list[widgets.IntSlider];
ctrls_property: list[widgets.IntSlider];
fcts: Functions;
def __init__(
self,
fnames: list[str],
setnames: list[str],
setsfrom: dict[str, list[Any]] | list[list[Any]] = [],
N: Optional[int] = None,
):
self.state = None;
self.N = N or 1;
self.N_max = len(fnames);
assert len(setnames) == len(fnames) + 1, f'The number of sets must be {self.N_max+1}.';
self.fnames = fnames;
self.setnames = setnames;
# fix set contents:
if isinstance(setsfrom, dict):
default = randomset_alphabet(mode=Letters.ROMAN, shuffle=True, full=True);
setsfrom = [ setsfrom.get(name, default) for name in setnames ];
if len(setsfrom) == 0:
setsfrom = [
randomset_alphabet(mode=Letters.SYMBOLS, shuffle=True, full=True),
randomset_alphabet(mode=Letters.ROMAN, shuffle=True, full=True),
randomset_alphabet(mode=Letters.HEBREW, shuffle=True, full=True),
randomset_alphabet(mode=Letters.GREEK, shuffle=True, full=True),
];
n = len(setsfrom);
self.setsfrom = [ setsfrom[k % n] for k, name in enumerate(setnames) ];
self.card = [ min(3, len(XX)) for XX in self.setsfrom ];
def run(self):
'''
Runs the widget.
'''
self.create_widgets();
display(widgets.interactive_output(
f = self.handler_main,
controls = {'N': self.ctrl_nr},
));
return;
def create_widgets(self):
'''
Initialises the widgets.
'''
N = self.N_max;
self.btn_refresh = widgets.ToggleButton(description='Neu laden');
self.btn_show_labels = widgets.Checkbox(
description = 'Labels anzeigen?',
value = True,
style = {
'description_width': 'initial',
},
visible = True
);
self.ctrl_nr = widgets.IntSlider(value=self.N, description=f'# Funktionen', min=1, max=self.N_max);
cards_max = [ len(XX) for XX in self.setsfrom ];
card_max_max = max(cards_max);
self.ctrls_card = [
widgets.IntSlider(
value = card,
description = f'|{setname}|',
min = 1,
max = card_max,
layout = {
'width': 'initial',
# FIXME: scales wrong:
# 'width': f'{100*cards_max/card_max_max}%',
},
)
for setname, XX, card, card_max in zip(
self.setnames[:(N+1)],
self.setsfrom[:(N+1)],
self.card[:(N+1)],
cards_max[:(N+1)],
)
];
self.ctrls_property = [
widgets.RadioButtons(
options = [ e.value for e in possible_properties(self.card[k], self.card[k+1]) ],
value = FunctionProperty.NOTHING.value,
layout = {
'description_width': 'initial',
'width': 'initial',
},
disabled = False,
)
for k in range(N)
];
for k, ctrl_card in enumerate(self.ctrls_card):
ctrl_card.observe(partial(self.handler_upd_card, k=k), names='value');
# FIXME: this does not behave correctly:
self.btn_show_labels.observe(partial(self.handler_plot, create=False));
return;
def handler_main(self, *_, **__):
'''
Main handler for updating widgets.
'''
N = self.N = self.ctrl_nr.value;
ui = widgets.VBox([] \
+ [ self.btn_refresh ] \
+ [ self.btn_show_labels ] \
+ [ widgets.Text(f'Größen den Mengen:') ] \
+ self.ctrls_card[:(N+1)] \
+ [widgets.HBox(
[
widgets.VBox(
[
widgets.Text(f'Eigenschaften von {fname}'),
ctrl_property
],
layout = {
'description_width': 'initial',
'width': 'initial',
'display': 'flex',
'align_items': 'stretch',
'overflow': 'hidden',
}
)
for fname, ctrl_property in zip(self.fnames[:N], self.ctrls_property[:N])
],
)],
);
display(ui);
display(widgets.interactive_output(
f = self.handler_plot,
controls = dict(
N = self.ctrl_nr,
refresh = self.btn_refresh,
# FIXME: shoud not have to rely on this:
show_labels = self.btn_show_labels,
**{
f'card[{k}]': ctrl_card
for k, ctrl_card in enumerate(self.ctrls_card)
},
**{
f'property[{k}]': ctrl_property
for k, ctrl_property in enumerate(self.ctrls_property)
},
),
));
return;
def handler_plot(self, *_, create: bool = True, **__):
'''
Method to create sets, functions, and plot.
'''
self.card = [ ctrl_card.value for ctrl_card in self.ctrls_card ];
if create:
N = self.N;
options = list(map(lambda ctrl: ctrl.value, self.ctrls_property[:N]));
properties = list(map(option_to_property, options));
injective = list(map(is_injective, properties));
surjective = list(map(is_surjective, properties));
sets = [ XX[:card] for XX, card in zip(self.setsfrom[:(N+1)], self.card[:(N+1)]) ];
self.fcts = Functions(*[
Function(
name = (fname, nameX, nameY),
domain = X,
codomain = Y,
fct = random_function(X, Y, injective=inj, surjective=surj, force=False),
)
for fname, nameX, nameY, X, Y, inj, surj in zip(
self.fnames,
self.setnames,
self.setnames[1:],
sets,
sets[1:],
injective,
surjective,
)
]);
# FIXME:
# upon toggling show labels button, this even triggers multiple times,
# and only the old value registers.
show_labels = self.btn_show_labels.value;
fig, axs = self.fcts.draw(show_labels=show_labels);
return;
def handler_upd_card(self, change, k: int):
'''
Handler for altering function property options
upon change of set cardinality.
'''
self.card[k] = change['new'];
def upd(j: int):
m = self.card[j];
n = self.card[j+1];
value = self.ctrls_property[j].value;
options = [ e.value for e in possible_properties(m, n) ];
if value not in options:
value = FunctionProperty.NOTHING.value;
self.ctrls_property[j].options = options;
self.ctrls_property[j].value = value;
return;
if k > 0:
upd(k-1);
if k < self.N:
upd(k);
return;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# AUXILIARY METHODS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def option_to_property(option: str) -> Optional[FunctionProperty]:
try:
return FunctionProperty(option);
except:
return None;
def possible_properties(m: int = 1, n: int = 1) -> list[FunctionProperty]:
if m == n:
if m == 1:
return [
e for e in FunctionProperty
if (is_injective(e) not in [False])
and (is_surjective(e) not in [False])
];
else:
return [
e for e in FunctionProperty
if not (is_surjective(e) in [True] and is_injective(e) in [False])
and not (is_surjective(e) in [False] and is_injective(e) in [True])
];
elif m == 1 and n > 1:
return [
e for e in FunctionProperty
if (is_injective(e) not in [False])
and (is_surjective(e) not in [True])
];
elif n == 1 and m > 1:
return [
e for e in FunctionProperty
if (is_surjective(e) not in [False])
and (is_injective(e) not in [True])
];
elif m > n:
return [
e for e in FunctionProperty
if (is_injective(e) not in [True])
];
elif n > m:
return [
e for e in FunctionProperty
if (is_surjective(e) not in [True])
];
return [ e for e in FunctionProperty ];
def is_injective(property: Optional[FunctionProperty]) -> Optional[bool]:
match property:
case FunctionProperty.INJECTIVE | FunctionProperty.INJECTIVE_NOT_SURJECTIVE | FunctionProperty.BOTH:
return True;
case FunctionProperty.NOT_INJECTIVE | FunctionProperty.NOT_INJECTIVE_SURJECTIVE | FunctionProperty.NEITHER:
return False;
return None;
def is_surjective(property: Optional[FunctionProperty]) -> Optional[bool]:
match property:
case FunctionProperty.SURJECTIVE | FunctionProperty.NOT_INJECTIVE_SURJECTIVE | FunctionProperty.BOTH:
return True;
case FunctionProperty.NOT_SURJECTIVE | FunctionProperty.INJECTIVE_NOT_SURJECTIVE | FunctionProperty.NEITHER:
return False;
return None;