Der erste Anlauf schloss Kritik_und_Verbesserungsvorschlaege/ mit einer
Gegenausnahme aus, weil NEUER_TITEL.md darin lag und der Bau ohne diese Datei
abbricht:
Kritik_und_Verbesserungsvorschlaege/*
!Kritik_und_Verbesserungsvorschlaege/NEUER_TITEL.md
Das funktionierte, war aber die schlechtere Loesung: Eine Bauquelle blieb in
einem Verzeichnis liegen, das aus dem Repository verschwinden soll. Jetzt
steht sie als Operations_Research_mit_Python_Version_04/NEUER_TITEL.md bei den
uebrigen Quellen, und .gitignore braucht nur noch eine Zeile.
Eine Stelle im Build musste mit: pruefe_dateien() meldet jede .md im
Quellverzeichnis, die weder in DATEIEN steht noch mit README beginnt, als
"nicht eingebundene Datei". Die bis dahin leere Menge KEINE_KAPITELDATEIEN
fuehrt jetzt NEUER_TITEL.md - eine Quelle, aber keine Kapiteldatei.
Der Nachweis, dass der Umzug nichts veraendert hat, brauchte einen Umweg: Die
Pruefsumme von titelseite.svg aenderte sich - aber nur, weil das Fussband das
Tagesdatum traegt und inzwischen der 9. September war. Mit dem Datum des
Vortags erzeugt, ist die Datei byte-identisch zum committeten Stand
(1b076697...). Dass der Text unveraendert ist, zeigt schon der
Strukturvergleich: 721 Glyphenverweise und 81 Pfaddefinitionen in beiden
Fassungen.
Gegengeprueft mit einem simulierten Klon (git checkout-index in ein leeres
Verzeichnis): Das Kritik-Verzeichnis fehlt dort vollstaendig, NEUER_TITEL.md
liegt im Quellverzeichnis, und --check liefert dieselben Zahlen wie lokal.
Was das NICHT leistet: Die fuenf Dateien verschwinden aus kuenftigen Klons,
nicht aus der Historie. Wer einen alten Commit auscheckt, bekommt sie
weiterhin.
Veroeffentlicht: 5 Dateien uebertragen, PDF unveraendert 781 Seiten.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
277 lines
13 KiB
Markdown
277 lines
13 KiB
Markdown
# Optimierte Entscheidungsfindung mit Python
|
|
|
|
*Von der mathematischen Modellierung zu praktischen intelligenten Lösungen für Betrieb,
|
|
Technik und Finanzmärkte*
|
|
|
|
Ein Lehrbuch über Operations Research mit Python: **23 Kapitel in 5 Teilen, 6 Anhänge,
|
|
141 Aufgaben mit vollständigen Lösungen, 76 lauffähige Beispielprogramme, 25 Jupyter-Notebooks,
|
|
33 Diagramme — 759 PDF-Seiten.** Von der linearen Programmierung über Constraint Programming
|
|
und Metaheuristiken bis zu Portfoliooptimierung, CVaR und dem Weg vom Prototyp in den Betrieb.
|
|
|
|
**Online lesen: <https://jamulix.de/OR/>** · Repository: <https://kitux.de/forgejo/dschlueter/operations_research>
|
|
|
|
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 |
|
|
| --- | --- |
|
|
| **Website** — eine Seite je Kapitel, mit Volltextsuche, Stichwortverzeichnis und vier interaktiven Plotly-Figuren | **<https://jamulix.de/OR/>** — oder lokal `OR_HTML_04/index.html` |
|
|
| **PDF**, 759 Seiten | <https://jamulix.de/OR/Operations_Research_mit_Python_Version_04.pdf> — oder lokal [`…_Version_04.pdf`](Operations_Research_mit_Python_Version_04.pdf) |
|
|
| **Ein einziges HTML-Dokument** | <https://jamulix.de/OR/gesamtdokument.html> |
|
|
| **Notebooks**, eines je Kapitel, einzeln oder als ZIP | <https://jamulix.de/OR/notebooks.html> — oder lokal `Notebooks_04/` |
|
|
|
|
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.
|
|
|
|
---
|
|
|
|
## Was hier liegt
|
|
|
|
| Pfad | Rolle |
|
|
| --- | --- |
|
|
| `Operations_Research_mit_Python_Version_04/` | **Quelle**: 37 Kapiteldateien (inkl. 5 Teil-Synthesen), Build-Skripte und `NEUER_TITEL.md` — der Titeltext, aus dem PDF-Titelseite und Startseite entstehen |
|
|
| `bilder_04/` | **Quelle**: 33 Diagramme (SVG) + 16 `erzeuge_*.py`-Generatoren |
|
|
| `web_04/` | **Quelle**: `site.css`, `site.js`, `icons.svg`, `plotly.min.js`, `katex/` — die statischen Bestandteile der Website |
|
|
| `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, 759 Seiten |
|
|
| `OR_HTML_04/` | generiert: **Mehrseiten-Website** — dieser Ordner wird veröffentlicht |
|
|
| `Operations_Research_mit_Python_Version_04_Programme/` | generiert: 76 Beispielprogramme |
|
|
| `Notebooks_04/` | generiert: ein Jupyter-Notebook je Kapitel |
|
|
|
|
**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 — sonst
|
|
gehen sie beim nächsten Bau verloren.
|
|
|
|
---
|
|
|
|
## Das Buch selbst bauen
|
|
|
|
Alle Befehle werden **in diesem Verzeichnis** ausgeführt; die Skripte leiten ihre Pfade aus
|
|
der eigenen Position ab.
|
|
|
|
```bash
|
|
# 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
|
|
python3 Operations_Research_mit_Python_Version_04/build_version_04.py --pdf --html
|
|
|
|
# Beispielprogramme aus den Kapiteln extrahieren
|
|
python3 Operations_Research_mit_Python_Version_04/extract_programme_04.py
|
|
|
|
# Glossar (Anhang E) aus seiner Eintragsliste erzeugen
|
|
python3 Operations_Research_mit_Python_Version_04/erzeuge_glossar_04.py
|
|
|
|
# ein Diagramm neu erzeugen (braucht die Gruppe [figures], teils 'dot')
|
|
python3 bilder_04/erzeuge_kondition.py
|
|
```
|
|
|
|
`--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; zehn Fälle wurden nachträglich gefunden, und jeder hat eine eigene
|
|
Prüfung hinterlassen.
|
|
|
|
### Externe Werkzeuge
|
|
|
|
| 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 16 Bildgeneratoren | nur beim Neuerzeugen dieser Diagramme nötig |
|
|
|
|
**`web_04/katex/`** ist externes Material und wird von keinem Skript erzeugt — es liegt
|
|
deshalb als Quelle im Repository und wird bei jedem Bau nach `OR_HTML_04/katex/` kopiert.
|
|
Fehlt es, bleiben die Formeln auf der Website ungesetzt.
|
|
|
|
**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.
|
|
|
|
---
|
|
|
|
## Veröffentlichen
|
|
|
|
`OR_HTML_04/` ist selbstgenügsam: Der Ordner lässt sich direkt auf einen Webserver kopieren.
|
|
Für den regelmäßigen Fall gibt es ein Skript.
|
|
|
|
```bash
|
|
# einmalig: den eigenen SSH-Schlüssel auf den Server legen
|
|
ssh-copy-id benutzer@example.org
|
|
|
|
# einmalig: Ziel eintragen
|
|
cp .env.beispiel .env && chmod 600 .env # dann .env ausfüllen
|
|
|
|
# jedes Mal
|
|
python3 Operations_Research_mit_Python_Version_04/veroeffentliche_04.py
|
|
```
|
|
|
|
Das Skript benutzt **`rsync --delete`, nicht `scp`** — und das ist der entscheidende
|
|
Unterschied: `scp` überschreibt nur, es entfernt nie. Eine Seite, die aus dem Buch
|
|
verschwindet, bliebe sonst dauerhaft online erreichbar. `rsync` überträgt zudem nur, was sich
|
|
geändert hat; ein zweiter Lauf direkt danach überträgt nichts.
|
|
|
|
Vier Schritte, jeder mit einer eigenen Aufgabe:
|
|
|
|
1. **Vorprüfung.** Ist eine Quelldatei neuer als die gebaute Website, bricht das Skript ab —
|
|
ein alter Stand soll gar nicht erst hochgeladen werden. Ebenso geprüft: dass das PDF der
|
|
Website byte-genau dem gebauten entspricht und dass die Verzeichnis-Weiterleitungen da
|
|
sind.
|
|
2. **Probelauf.** Zählt und zeigt, was übertragen und was gelöscht würde. Über 30 Löschungen
|
|
ist der Lauf verdächtig (falscher Zielpfad, halb gebautes Verzeichnis) und bricht ab;
|
|
`--loeschgrenze N` hebt die Grenze an.
|
|
3. **Übertragung.**
|
|
4. **Nachprüfung per HTTP.** Dreizehn Adressen werden abgerufen und ihr Statuscode mit der
|
|
Erwartung verglichen.
|
|
|
|
`--probelauf` führt nur die Schritte 1 und 2 aus. In der `.env` steht **kein Geheimnis**:
|
|
`rsync` und `scp` haben keine Passwort-Option, die Anmeldung läuft über den SSH-Schlüssel.
|
|
|
|
---
|
|
|
|
## Notebooks und Google Colab
|
|
|
|
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.
|
|
|
|
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. **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*.
|