Der Anlass war messbar. Der Live-Stand vor dem Skript:
/OR/ 200
/OR/anhang-glossar-literatur.html 200 <- Leiche des vorigen Stands
/OR/anhang-glossar.html 404
/OR/notebooks.html 404
/OR/Notebooks_04.zip 404
/OR/Notebooks_04/ 403
scp -r ueberschreibt nur, es loescht nie - die alte Glossar-Seite bliebe
dauerhaft erreichbar. Das Zielverzeichnis vorher zu leeren waere die grobe
Antwort: Bricht die Uebertragung von 23 MB in 213 Dateien ab, ist die Website
tot. rsync --delete uebertraegt nur Geaendertes und entfernt genau das, was
verschwunden ist.
Der zweite Grund wiegt schwerer: Die Website hing wochenlang einen Bau
zurueck, ohne dass es auffiel. Vier Schritte:
1. Vorpruefung - ist eine Quelldatei neuer als die gebaute Website, Abbruch.
Ebenso: PDF der Website byte-genau wie das gebaute, Verzeichnis-
Weiterleitungen vorhanden (der Grund fuer den 403).
2. Probelauf - zaehlt Uebertragungen und Loeschungen. Mehr als 30 Loeschungen
brechen ab; das ist der Schutz gegen einen falschen Zielpfad, mit dem
--delete sonst ein fremdes Verzeichnis ausraeumt. --loeschgrenze hebt an.
3. Uebertragung (rsync -rltz --chmod=D755,F644 ueber ssh).
4. Nachpruefung - 14 Adressen per HTTP, Statuscode gegen Erwartung. Darunter
die Probe, dass die entfernte Seite wirklich 404 liefert.
Anmeldung per SSH-Schluessel, nicht per Passwort in der .env: rsync und scp
haben keine Passwort-Option, ein Passwort braeuchte sshpass und staende
waehrend der Uebertragung in der Prozessliste. Die .env (in .gitignore,
Vorlage .env.beispiel) enthaelt nur Host, Benutzer, Zielpfad und URL.
Beim ersten Test lief die Pruefung in eine irrefuehrende Meldung ("kein rsync
installiert"), waehrend in Wahrheit schon die Anmeldung fehlschlug. Die
Pruefung unterscheidet die Faelle jetzt am ssh-Rueckgabewert 255 und nennt
ssh-copy-id.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
276 lines
13 KiB
Markdown
276 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 |
|
|
| `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 |
|
|
| `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, 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
|
|
|
|
# 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; acht 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.** Vierzehn Adressen werden abgerufen und ihr Statuscode mit der
|
|
Erwartung verglichen — einschließlich der Probe, dass eine entfernte Seite wirklich 404
|
|
liefert.
|
|
|
|
`--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*.
|