Veroeffentlichung: Lizenzen, README, Colab-Entscheidung, JupyterLab im Image

Sechs Dinge, alle fuer das jetzt oeffentliche Repository.

LIZENZEN. LICENSE traegt die MIT-Lizenz fuer den Programmcode (alle .py,
Notebooks, Dockerfile, pyproject.toml), LICENSE-TEXT.md die CC BY-SA 4.0 fuer
Buchtext, PDF, Website und Diagramme. Beide Dateien nennen ausdruecklich, was
sie abdecken und was nicht - ein Codeblock im Buchtext bleibt Programmcode und
steht unter MIT. Vorher hatte das Repository gar keine Lizenz, womit
standardmaessig "alle Rechte vorbehalten" galt und niemand die 76 Programme
haette weiterverwenden duerfen.

COLAB. COLAB_BASIS_URL steht jetzt auf "". Der Platzhalter zeigte auf GitHub,
das Repository liegt auf einer eigenen Forgejo-Instanz - und Colab oeffnet
Notebooks NUR aus GitHub, Google Drive oder einem Upload. Die URL-Form
colab.research.google.com/github/... ist fest auf GitHub verdrahtet; eine
selbstgehostete Adresse dort einzusetzen ergaebe keinen Link zum eigenen
Server, sondern einen toten GitHub-Link. Der Kommentar im Quelltext ging von
GitHub aus und war damit selbst irrefuehrend; er ist ersetzt.

Verloren geht nichts: Die 25 Notebooks liegen neben der Website und bekommen
einen echten Download-Link, jetzt mit dem Hinweis, was man damit tut -
"herunterladen und in Jupyter oeffnen, in Colab hochladen oder mit dem
Kurs-Image starten".

JUPYTERLAB IM KURS-IMAGE. Neue pyproject-Gruppe [notebook] mit jupyterlab,
die Notebooks werden ins Image kopiert, und ein kleiner Startbefehl macht
beide Betriebsarten ohne --entrypoint moeglich: ohne Argument JupyterLab, mit
Argument ein einzelnes Programm. Gebaut und geprueft - Rucksack.py laeuft,
JupyterLab antwortet mit HTTP 200 und zeigt alle 25 Notebooks. Image 1,31 ->
1,46 GB. Es laeuft ohne Token, deshalb im README die Portfreigabe an
127.0.0.1 gebunden.

README KOMPLETT NEU. Es war die Bau-Anleitung eines privaten Verzeichnisses
und ist jetzt die Visitenkarte eines oeffentlichen Repositorys: was das Buch
ist, wo man es liest, drei Wege die Beispiele auszufuehren (Container,
schlanke Installation, alles auf einmal), was hier liegt, wie man baut, die
Colab-Frage, die Lizenzen und wie man mitwirkt. Alle relativen Links
geprueft: 0 tot.

.gitattributes. Ohne die Datei entschied core.autocrlf des jeweiligen
Rechners, was beim Klonen passiert - ein Windows-Leser bekam CRLF-Rauschen in
jedem Diff. Jetzt: im Repository immer LF, im Arbeitsverzeichnis passend zum
System, Binaerdateien ausdruecklich ausgenommen. Der Bestand war bereits
sauber (git add --renormalize aendert null Dateien). Zusaetzlich sind die
erzeugten Verzeichnisse als linguist-generated markiert, sonst zaehlt die
Sprachstatistik das Repository als HTML-Projekt.

PROGRESS.md: Remote-Repository als erledigt markiert, der Colab-Befund
festgehalten. CLAUDE.md um Veroeffentlichung, Lizenzen und die neuen Dateien
ergaenzt.

Geprueft: --check ohne Fehler, 0 tote README-Links, 76 Programme unveraendert,
33 pytest-Tests, pyproject baut mit acht Gruppen, PDF 759 Seiten (eine
weniger - die Colab-Zeile entfaellt in 25 Kapiteln).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
dschlueter 2026-09-08 14:54:04 +02:00
commit 4fa4e20b04
37 changed files with 467 additions and 258 deletions

290
README.md
View file

@ -1,12 +1,108 @@
# Optimierte Entscheidungsfindung mit Python — Version 04
# Optimierte Entscheidungsfindung mit Python
Quellen, Build-Werkzeuge und Ausgaben des Lehrbuchs *Optimierte Entscheidungsfindung mit Python*
(Autor: Dieter Schlüter). Dieses Verzeichnis ist die Wurzel: Alle Skripte leiten ihre Pfade
daraus ab, und alle Befehle unten werden **hier** ausgeführt.
*Von der mathematischen Modellierung zu praktischen intelligenten Lösungen für Betrieb,
Technik und Finanzmärkte*
> Dies ist die Bau-Anleitung für das Repository. Der Wegweiser **für Leserinnen und Leser des
> Buchs** — Aufbau, Lernpfade, Voraussetzungen — steht in
> [`Operations_Research_mit_Python_Version_04/README.md`](Operations_Research_mit_Python_Version_04/README.md).
Ein Lehrbuch über Operations Research mit Python: **23 Kapitel in 5 Teilen, 5 Anhänge,
141 Aufgaben mit vollständigen Lösungen, 76 lauffähige Beispielprogramme, 25 Jupyter-Notebooks,
33 Diagramme — 760 PDF-Seiten.** Von der linearen Programmierung über Constraint Programming
und Metaheuristiken bis zu Portfoliooptimierung, CVaR und dem Weg vom Prototyp in den Betrieb.
Autor: **Dieter Schlüter** · Lizenz: MIT (Code) und CC BY-SA 4.0 (Text)
> **Der Grundsatz des Buchs:** Jede abgedruckte Ausgabe stammt aus einem echten Lauf des
> danebenstehenden Programms, jede Zahl im Text ist gerechnet und nicht geschätzt. Allein
> beim Nachbauen von zehn Diagrammen kamen so sieben Fehler ans Licht, die beim Hinsehen
> niemand bemerkt hatte.
---
## Das Buch lesen
| Format | Wo |
| --- | --- |
| **PDF**, 760 Seiten | [`Operations_Research_mit_Python_Version_04.pdf`](Operations_Research_mit_Python_Version_04.pdf) |
| **Website** — eine Seite je Kapitel, mit Volltextsuche, Stichwortverzeichnis und vier interaktiven Plotly-Figuren | `OR_HTML_04/index.html` im Browser öffnen |
| **Ein einziges HTML-Dokument** | `OR_HTML_04/gesamtdokument.html` |
Die Website ist selbstgenügsam — alle Verweise zeigen auf Unterverzeichnisse (`assets/`,
`bilder_04/`, `katex/`, `Notebooks_04/`). Der Ordner lässt sich unverändert auf einen
Webserver kopieren, ohne Konfiguration.
**Wegweiser durch den Inhalt** — Aufbau, Lernpfade, Voraussetzungen:
[`Operations_Research_mit_Python_Version_04/README.md`](Operations_Research_mit_Python_Version_04/README.md).
Vier rollenbezogene Einstiege (Entscheider, Ingenieure, Investoren, Studierende) stehen im
Vorwort des Buchs.
---
## Die Beispiele ausführen — drei Wege
### 1. Im Container, ohne etwas zu installieren
Der empfohlene Weg zum Ausprobieren. Das Kurs-Image bringt alle Solver in geprüften
Versionen mit.
```bash
docker build -t or-mit-python .
# JupyterLab mit allen 25 Kapitel-Notebooks -> http://127.0.0.1:8888
docker run --rm -p 127.0.0.1:8888:8888 or-mit-python
# oder ein einzelnes Programm
docker run --rm or-mit-python Installationstest.py
docker run --rm or-mit-python Rucksack.py
# Ergebnisdateien behalten (Excel-Mappen, Diagramme)
docker run --rm -v "$PWD/ausgabe:/buch/output" or-mit-python Excel_Bruecke.py
```
JupyterLab läuft im Image **ohne Zugangstoken** — für den eigenen Rechner richtig, und
deshalb steht oben `127.0.0.1:8888:8888` statt `8888:8888`: So ist der Dienst nur lokal
erreichbar. Stellen Sie den Container nicht ins offene Netz.
Das Image führt die Programme aus, **es baut das Buch nicht**: pandoc, xelatex und inkscape
wären zusammen über ein Gigabyte ohne Nutzen für jemanden, der rechnen will.
### 2. Schlanke lokale Installation
Über [`pyproject.toml`](pyproject.toml) und seine Gruppen — die Grundausstattung trägt den
Großteil des Buchs:
```bash
python3 -m venv .venv && source .venv/bin/activate
pip install -e . # numpy, scipy, pandas, matplotlib, openpyxl, pydantic, ortools, cvxpy
pip install -e ".[finance]" # scikit-learn, yfinance — Teil IV
pip install -e ".[large-scale]" # highspy, Pyomo, linopy, polars
pip install -e ".[api]" # fastapi, uvicorn, httpx — Kapitel Testen
pip install -e ".[notebook]" # jupyterlab
pip install -e ".[figures]" # plotly, graphviz — nur zum Neuerzeugen der Diagramme
pip install -e ".[dev]" # pytest
```
**`ortools` steht in der Grundausstattung, `highspy` erst in `[large-scale]`.** Das ist
Absicht: Beide bringen eine eigene HiGHS-Kopie mit und vertragen sich nicht im selben
Prozess. Wer nur die Grundausstattung installiert, kann in den Konflikt gar nicht geraten.
Die drei Programme, die beide brauchen, isolieren sie zur Laufzeit in getrennten Prozessen —
`ProcessPoolExecutor` mit `spawn` und `max_tasks_per_child=1`, erklärt im Kapitel „Das
Python-Ökosystem für OR".
### 3. Alles auf einen Schlag
So wie im Buch abgedruckt, über
[`requirements.txt`](Operations_Research_mit_Python_Version_04_Programme/requirements.txt):
```bash
pip install -r Operations_Research_mit_Python_Version_04_Programme/requirements.txt
```
> **Prüfen Sie die Installation, bevor Sie anfangen:**
> `python3 Operations_Research_mit_Python_Version_04_Programme/Installationstest.py`
> meldet für jedes Paket Version und Status und löst je Solver-Familie ein Mini-Modell.
**Vier der 76 Programme brauchen Internet** (Kursdaten über `yfinance`):
`CVaR_Portfolio.py`, `Finanzdaten_Ledoit_Wolf.py`, `Markowitz_CVXPY.py`,
`QuantitativeTradingEngine.py`. Alle übrigen laufen offline.
---
@ -15,29 +111,31 @@ daraus ab, und alle Befehle unten werden **hier** ausgeführt.
| Pfad | Rolle |
| --- | --- |
| `Operations_Research_mit_Python_Version_04/` | **Quelle**: 36 Kapiteldateien (inkl. 5 Teil-Synthesen) + Build-Skripte |
| `bilder_04/` | **Quelle**: Diagramme (SVG/PNG) + `erzeuge_*.py`-Generatoren |
| `bilder_04/` | **Quelle**: 33 Diagramme (SVG) + 16 `erzeuge_*.py`-Generatoren |
| `Kritik_und_Verbesserungsvorschlaege/` | **Quelle**: die Rezensionen und Vorschläge, die den Umbau ausgelöst haben |
| `pyproject.toml`, `Dockerfile`, `.dockerignore` | **Quelle**: Abhängigkeitsgruppen und Kurs-Image |
| `pandoc-defaults-*.yaml`, `pandoc/` | **Quelle**: Konfiguration des PDF-Baus |
| `PLAN.md` / `PROGRESS.md` | **Quelle**: Ziel des Umbaus und erreichter Stand |
| `Operations_Research_mit_Python_Version_04.md` | generiert: Gesamtdokument (Pandoc-Eingabe) |
| `Operations_Research_mit_Python_Version_04.pdf` | generiert: PDF, 760 Seiten |
| `OR_HTML_04/` | generiert: **Mehrseiten-Website** — dieser Ordner wird veröffentlicht |
| `Operations_Research_mit_Python_Version_04_Programme/` | generiert: 76 lauffähige Beispielprogramme |
| `Operations_Research_mit_Python_Version_04_Programme/` | generiert: 76 Beispielprogramme |
| `Notebooks_04/` | generiert: ein Jupyter-Notebook je Kapitel |
| `PLAN.md` / `PROGRESS.md` | das Ziel des Umbaus und der erreichte Stand |
| `pyproject.toml` | Abhängigkeiten in Gruppen (`finance`, `large-scale`, `api`, …) |
| `Dockerfile`, `.dockerignore` | zweistufiges Kurs-Image (führt die Programme aus, baut nicht das Buch) |
| `pandoc-defaults-*.yaml`, `pandoc/` | Konfiguration des PDF-Baus |
**Nur die als *Quelle* markierten Verzeichnisse werden von Hand bearbeitet.** Alles andere
wird erzeugt und bei jeder inhaltlichen Änderung neu gebaut — insbesondere gehören
Programmänderungen in den Kapitel-Codeblock, nicht in das Programme-Verzeichnis.
wird erzeugt und bei jeder inhaltlichen Änderung neu gebaut. Insbesondere gehören
**Programmänderungen in den Kapitel-Codeblock**, nicht in das Programme-Verzeichnis — sonst
gehen sie beim nächsten Bau verloren.
---
## Bauen
## Das Buch selbst bauen
Alle Befehle werden **in diesem Verzeichnis** ausgeführt; die Skripte leiten ihre Pfade aus
der eigenen Position ab.
```bash
cd Version_04
# nur prüfen: Struktur, Querverweise, Codezäune, harte Nummern
# nur prüfen: Struktur, Querverweise, Codezäune, harte Nummern, Lesekette
python3 Operations_Research_mit_Python_Version_04/build_version_04.py --check
# Gesamtdokument, PDF und Website
@ -45,115 +143,89 @@ python3 Operations_Research_mit_Python_Version_04/build_version_04.py --pdf --ht
# Beispielprogramme aus den Kapiteln extrahieren
python3 Operations_Research_mit_Python_Version_04/extract_programme_04.py
# ein Diagramm neu erzeugen (braucht die Gruppe [figures], teils 'dot')
python3 bilder_04/erzeuge_kondition.py
```
Die Website ist danach in `OR_HTML_04/` vollständig und **selbstgenügsam** — alle Verweise
zeigen auf Unterverzeichnisse (`assets/`, `bilder_04/`, `katex/`, `Notebooks_04/`). Der Ordner
lässt sich unverändert auf einen Webserver kopieren.
`--check` prüft mehr als die Struktur: fehlende Codezäune, tote Dateilinks, eine gebrochene
Lesekette, Lösungsabschnitte mit falscher Aufgabenzahl — und **jede von Hand geschriebene
Nummer**, die der Build selbst vergeben müsste. Diese Regel ist die in diesem Projekt am
häufigsten verletzte; acht Fälle wurden nachträglich gefunden, und jeder hat eine eigene
Prüfung hinterlassen.
---
### Externe Werkzeuge
## Voraussetzungen
**Python-Pakete** — alles auf einen Schlag, wie im Buch abgedruckt
([`requirements.txt`](Operations_Research_mit_Python_Version_04_Programme/requirements.txt)):
```bash
python3 -m venv .venv && source .venv/bin/activate
pip install -r Operations_Research_mit_Python_Version_04_Programme/requirements.txt
```
Wer eine schlanke Umgebung möchte, nimmt stattdessen [`pyproject.toml`](pyproject.toml) mit
seinen Gruppen — die Grundausstattung trägt den Großteil des Buchs:
```bash
pip install -e . # numpy, scipy, pandas, matplotlib, openpyxl, pydantic, ortools, cvxpy
pip install -e ".[finance]" # scikit-learn, yfinance
pip install -e ".[large-scale]" # highspy, Pyomo, linopy, polars
pip install -e ".[api]" # fastapi, uvicorn, httpx
pip install -e ".[figures]" # plotly, graphviz — nur zum Neuerzeugen der Diagramme
pip install -e ".[dev]" # pytest
```
**`ortools` steht in der Grundausstattung, `highspy` erst in `[large-scale]`.** Das ist
Absicht: Beide bringen eine eigene HiGHS-Kopie mit und vertragen sich nicht im selben
Prozess. Wer die Grundausstattung installiert, kann in den Konflikt gar nicht geraten —
`cvxpy` zieht `highspy` **nicht** nach, erkennt es aber, sobald `[large-scale]` es
mitgebracht hat.
`graphviz` fehlt in der `requirements.txt` — es wird allein von
`bilder_04/erzeuge_architektur_diagramme.py` gebraucht, nicht von den Beispielprogrammen,
und steht darum nur in `[figures]`.
### Oder im Container
Wer nichts installieren will, baut das Kurs-Image:
```bash
docker build -t or-mit-python .
docker run --rm or-mit-python Installationstest.py
docker run --rm or-mit-python Rucksack.py
docker run --rm -it or-mit-python # Python-Eingabe
docker run --rm -v "$PWD/ausgabe:/buch/output" or-mit-python Excel_Bruecke.py
```
Zweistufiger Bau: Die erste Stufe übersetzt die Abhängigkeiten in eine virtuelle Umgebung
und braucht dafür einen Compiler, die zweite kopiert nur das Ergebnis — die Bauumgebung
landet nicht im Image. Enthalten sind die Gruppen `finance`, `large-scale`, `api` und `dev`;
`figures` fehlt bewusst, weil es zusätzlich Graphviz verlangt und nur dem Neuerzeugen der
Diagramme dient.
**Das Image führt die Programme aus, es baut das Buch nicht.** Für PDF und Website braucht
es pandoc, xelatex und inkscape — zusammen über ein Gigabyte, ohne Nutzen für jemanden, der
die Beispiele durchrechnen will.
Zwei Punkte, die nicht offensichtlich sind: Das Image enthält `ortools` **und** `highspy`,
obwohl sie sich nicht gemeinsam importieren lassen — der Konflikt wird zur Laufzeit durch
getrennte Prozesse gelöst, nicht durch Weglassen. Und `libgomp1` muss im schlanken
Basis-Image nachinstalliert werden, sonst scheitert der erste Solveraufruf mit
`libgomp.so.1: cannot open shared object file`.
**Externe Werkzeuge**, je nachdem, was gebaut werden soll:
| Werkzeug | wofür | ohne es |
| Werkzeug | Wofür | Ohne es |
| --- | --- | --- |
| `pandoc` (≥ 3.0) | PDF und Website | `--pdf`/`--html` scheitern; `--check` läuft |
| `xelatex` + `texindy` | PDF | kein PDF; Website unberührt |
| `inkscape` | SVG-Grafiken im PDF | LaTeX bricht bei `\includesvg` ab |
| `dot` (Graphviz) | 5 der 15 Bildgeneratoren | nur beim Neuerzeugen dieser Diagramme nötig |
| `dot` (Graphviz) | 5 der 16 Bildgeneratoren | nur beim Neuerzeugen dieser Diagramme nötig |
**`OR_HTML_04/katex/`** ist externes Material und wird von keinem Skript erzeugt. Fehlt es,
bleiben die Formeln auf der Website ungesetzt.
---
## Zwei Werte, die beim Veröffentlichen zu setzen sind
1. **`COLAB_BASIS_URL`** in `Operations_Research_mit_Python_Version_04/build_version_04.py`.
Sie trägt Kontoname und Repository-Name; die 25 Colab-Badges auf den Kapitelseiten hängen
daran. Der Pfadteil `Notebooks_04/…` wird relativ zur Repository-Wurzel aufgelöst und
stimmt bereits. Ein Leerstring schaltet die Badges ab.
2. Nichts weiter. Alle übrigen Pfade sind relativ.
**Warum die PDF-Konfiguration doppelt vorliegt:** `pandoc-defaults-basis.yaml` ist eine Kopie
der Benutzerdatei `~/.config/pandoc/defaults.yaml` — mit **relativem** Pfad auf
`pandoc/header-includes.tex` statt des absoluten, der dort steht. Ohne diese Kopie könnte ein
frischer Klon kein PDF bauen. `build_version_04.py` bevorzugt sie und fällt auf die
Benutzerdatei zurück, falls sie fehlt.
---
## Warum die PDF-Konfiguration doppelt vorliegt
## Notebooks und Google Colab
`pandoc-defaults-basis.yaml` ist eine Kopie der Benutzerdatei
`~/.config/pandoc/defaults.yaml` (Schriften, Geometrie, Seitenlayout) — mit **relativem**
Pfad auf `pandoc/header-includes.tex` statt des absoluten, der dort steht. Ohne diese Kopie
könnte ein frischer Klon kein PDF bauen. `build_version_04.py` bevorzugt sie und fällt auf
die Benutzerdatei zurück, falls sie fehlt.
Jedes Kapitel hat ein Notebook in `Notebooks_04/`, und die Website verlinkt es zum
Herunterladen. Einen **Colab-Knopf gibt es bewusst nicht**: Colab öffnet Notebooks nur aus
GitHub, aus Google Drive oder aus einem Upload — eine selbstgehostete Git-Instanz kann es
nicht lesen. Wer ohne eigene Installation rechnen will, nimmt das Kurs-Image (Weg 1); wer
Colab bevorzugt, lädt die `.ipynb` herunter und dort hoch.
`pandoc-defaults-buch.yaml` enthält die projektspezifischen Überschreibungen
(Inhaltsverzeichnis und Nummerierung werden im Markdown selbst erzeugt, `-shell-escape` für
`\includesvg`). Die eigentliche Buchtypografie steht in `bilder_04/or_pdf_header.tex`.
Sollte das Repository später zusätzlich auf GitHub gespiegelt werden, genügt **ein** Wert:
`COLAB_BASIS_URL` in `build_version_04.py`. Der Pfad dahinter stimmt bereits.
---
## Lizenz
Zwei Lizenzen, je nachdem, was Sie verwenden:
| Was | Lizenz | Datei |
| --- | --- | --- |
| **Programmcode** — alle `.py`, Notebooks, `Dockerfile`, `pyproject.toml` | MIT | [`LICENSE`](LICENSE) |
| **Buchtext und Abbildungen**`.md`-Kapitel, PDF, Website, Diagramme | CC BY-SA 4.0 | [`LICENSE-TEXT.md`](LICENSE-TEXT.md) |
Ein Codeblock, der im Buchtext abgedruckt ist, bleibt Programmcode: Für ihn gilt MIT.
Die verwendeten Bibliotheken (HiGHS, Google OR-Tools, CVXPY, SciPy, Pyomo, linopy und
andere) stehen unter ihren eigenen Lizenzen. Für die Inhalte gibt es **keine
Gewährleistung** — die Modelle sind Lehrbeispiele; wer auf ihrer Grundlage betriebliche oder
finanzielle Entscheidungen trifft, tut das in eigener Verantwortung.
---
## Mitwirken
Fehler, Unklarheiten und Verbesserungsvorschläge sind willkommen. Besonders hilfreich:
* **Eine Zahl, die nicht stimmt.** Jede abgedruckte Ausgabe soll aus einem echten Lauf
stammen — ergibt Ihrer etwas anderes, ist das ein Fund. Bitte mit Python- und
Paketversion.
* **Eine Stelle, an der das Buch etwas behauptet, statt es zu zeigen.**
* **Ein Beispiel aus Ihrem Arbeitsalltag**, das ein Muster besser erklärt als das im Buch.
Wer selbst etwas ändert: Programmänderungen gehören in den **Kapitel-Codeblock**, danach
`extract_programme_04.py` laufen lassen. Vor dem Absenden `--check`. Die Konventionen stehen
kurz in `CLAUDE.md` und ausführlich in `PLAN.md` Abschnitt 9.
---
## Verlauf
Version 04 baut das Werk vom Nachschlagewerk zum Kursbegleiter um; alle sechs Phasen sind
abgeschlossen. **Was geplant war, steht in [`PLAN.md`](PLAN.md); was erreicht ist und woran
man das nachprüft, in [`PROGRESS.md`](PROGRESS.md)** — einschließlich der Funde unterwegs und
der Regeln, die sich daraus ergeben haben. Wer hier weiterarbeitet, liest beide zuerst.
Version 04 baut das Werk vom Nachschlagewerk zum Kursbegleiter um. **Was geplant war, steht
in [`PLAN.md`](PLAN.md); was erreicht ist und woran man das nachprüft, in
[`PROGRESS.md`](PROGRESS.md)** — einschließlich aller Funde unterwegs und der Regeln, die
sich daraus ergeben haben. Wer hier weiterarbeitet, liest beide zuerst.
Bis Version 03 hieß das Buch *Operations Research mit Python*.