Optimierte Entscheidungsfindung mit Python
Von der mathematischen Modellierung zu praktischen intelligenten Lösungen für Betrieb, Technik und Finanzmärkte
Ein praxisorientiertes Kompendium für Entscheider mit Constraint Programming, Vektor- und Matrixmethoden sowie HiGHS, SciPy, Google OR-Tools und CVXPY.
Von Personaleinsatz-, Schicht- und Vertretungsplänen, Fahrtrouten, Logistik und Maschinen- und Netzwerkauslastung über Energieverteilung und Ressourcenplanung bis zur Portfoliooptimierung und besseren Entscheidungen an den Finanzmärkten — mit Python modellieren, optimieren und belegbar fundierte Entscheidungen treffen.
Autor / Herausgeber: Dieter Schlüter
<dieter(dot)schlueter(atsign)linix(dot)de>
Stand: 8. September 2026
Vorwort
Dieses Buch hat ein einziges Ziel: Sie sollen am Ende in der Lage sein, ein reales Entscheidungsproblem aus Ihrem eigenen Umfeld in ein mathematisches Modell zu übersetzen, es in Python zu lösen und das Ergebnis jemandem zu erklären, der kein Mathematiker ist.
Dieses Kompendium versteht sich als Arbeitsbuch. Das zeigt sich an drei Stellen:
Erstens: Formeln werden übersetzt. Zu jeder nicht-trivialen Formel gehört in dieser Ausgabe eine Lesehilfe, die jedes Symbol einzeln benennt, und eine Umschreibung in Alltagssprache. Formeln sind eine Abkürzung für Menschen, die den Inhalt schon kennen — wer ihn erst lernt, braucht den ausgeschriebenen Text daneben. Niemand sollte an der Notation scheitern, wenn er den Gedanken versteht.
Zweitens: Es wird geübt. Über 130 Aufgaben mit vollständigen Lösungen begleiten die Kapitel. Sie sind gestaffelt: von Verständnisfragen, die man im Kopf beantwortet, über Handrechnungen bis zu Programmieraufgaben, die auf den Kapitelbeispielen aufbauen. Wer Optimierung nur liest, kann anschließend über Optimierung reden. Wer die Aufgaben rechnet, kann optimieren.
Drittens: Der Weg zur eigenen Anwendung ist ausgeschildert. Die Projektwerkstatt am Ende enthält elf vollständig ausgearbeitete Projektaufträge — vom Schul-Vertretungsplaner über die Tourenoptimierung eines Lieferdienstes bis zum eigenen Portfolio-Rebalancer. Jeder Auftrag nennt Datenquellen, Modellskizze, Abnahmekriterien und Stolperfallen. Sie sind so zugeschnitten, dass sie in 10 bis 25 Stunden zu einem vorzeigbaren Ergebnis führen.
Ziel der Masterclass
Ein umfassendes, didaktisch von Grund auf aufgebautes Lehrbuch zur mathematischen Entscheidungsoptimierung (Operations Research, OR) mit praktischer Umsetzung in Python. Dieser Kurs der mathematischen Optimierung setzt kein Vorwissen in OR voraus und führt schrittweise von den algebraischen und kombinatorischen Grundlagen über Scheduling- und Constraint-Modelle bis hin zur professionellen Anwendung im quantitativen Aktienhandel, Portfoliomanagement und Risikocontrolling.
Vorausgesetzte Kenntnisse
Vorausgesetzt werden sichere Python-Kenntnisse (Funktionen, Klassen, NumPy, pandas) sowie Mathematik auf Grundstudiumsniveau:
| Gebiet | Was Sie können sollten | Wo im Buch gebraucht |
|---|---|---|
| Lineare Algebra | Vektoren, Matrizen, Matrix-Vektor-Produkt, Eigenwerte | ab Kapitel 2, zentral in Kapitel 11, Kapitel 18, Kapitel 19 |
| Analysis | Ableitung, Gradient, notwendige Bedingung erster Ordnung | Kapitel 11 |
| Statistik | Erwartungswert, Varianz, Standardabweichung, Quantil | Kapitel 12, 11–14 |
| Python | Listen, Dictionaries, Schleifen, Funktionen, Klassen, NumPy-Arrays | durchgängig |
Wenn Ihnen Mathematik-Bausteine fehlen: Kapitel 2 fasst die benötigte lineare Algebra vollständig zusammen, Abschnitt 11.2 wiederholt Gradienten. Sie können also einsteigen und die Lücken unterwegs schließen. Nur die Statistik ab Teil IV setzt wirklich Vorwissen voraus — dort hilft ein Blick in ein Einführungswerk zur Wahrscheinlichkeitsrechnung.
Benötigte Ressourcen
Ein Rechner mit Python 3.10 oder neuer genügt. Spezial-Hardware (GPU) ist nicht nötig — sämtliche Beispiele laufen auf einem gewöhnlichen Notebook, die meisten in unter zehn Sekunden. Die Kapitel 18 bis 14 benötigen einen Internetzugang, da sie aktuelle Kursdaten über yfinance laden.
Setup & Installation
Alle Beispielprogramme sind unter Python 3.10+ lauffähig. Legen Sie zunächst eine virtuelle Umgebung an — so bleiben die Kurspakete von Ihrer Systeminstallation getrennt:
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install --upgrade pip
pip install ortools highspy cvxpy scikit-learn yfinance matplotlib pandas numpy scipy \
openpyxl polars plotly pyomo linopy pymoo pydanticAlternativ liegt im Ordner Operations_Research_mit_Python_Version_04_Programme/ eine requirements.txt:
pip install -r Operations_Research_mit_Python_Version_04_Programme/requirements.txtInstallationstest
Prüfen Sie mit diesem Skript, ob alles bereitsteht, bevor Sie mit Kapitel 1 beginnen. Es meldet für jedes Paket Version und Status und löst ein Mini-Optimierungsproblem.
Eine Besonderheit dabei — die Import-Reihenfolge ist bewusst gewählt: highspy und cvxpy werden in der Paketübersicht nur auf Anwesenheit geprüft, und ortools lädt seine native Bibliothek zuerst. Der Grund: ortools und highspy bringen jeweils eine eigene HiGHS-Kopie mit, die sich nicht im selben Python-Prozess verträgt — und cvxpy importiert ein installiertes highspy bei der Solver-Erkennung selbst mit. Lädt deren HiGHS-Kopie zuerst, bricht der Test beim CP-SAT-Funktionstest mit einem kryptischen ImportError: undefined symbol ab; so gewinnt die Kopie von ortools, und CVXPY verzichtet lediglich auf sein HIGHS-Interface (für alle Buchprogramme folgenlos). Details und Abhilfen: Abschnitt 3.5 und Anhang C.
#!/usr/bin/env python3
# Installationstest.py
"""
Vorspann: Prüft die vollständige Kurs-Installation.
Ausgabe: eine Zeile pro Paket plus ein gelöstes Mini-Modell je Solver-Familie.
"""
import importlib.metadata
import importlib.util
import logging
import sys
PAKETE = [
("numpy", "Numerische Basis (Vektoren, Matrizen)"),
("scipy", "Wissenschaftliche Algorithmen, linprog/minimize"),
("pandas", "Tabellen und Zeitreihen"),
("matplotlib", "Diagramme"),
("ortools", "Google OR-Tools: CP-SAT und Routing"),
("highspy", "HiGHS-Solver, direkte Steuerung"),
("cvxpy", "Konvexe Optimierung (Portfolio, CVaR)"),
("sklearn", "Ledoit-Wolf-Shrinkage der Kovarianzmatrix"),
("yfinance", "Kursdatenbezug (nur die Finanzkapitel)"),
]
# Nur auf Anwesenheit prüfen, NICHT importieren (siehe Kapitel Ökosystem):
# - highspy: seine HiGHS-Bibliothek verträgt sich nicht mit der Kopie von
# ortools im selben Prozess.
# - cvxpy: importiert bei der Solver-Erkennung ein installiertes highspy
# selbst mit und löst so denselben Konflikt aus. Importiert wird cvxpy
# erst im Funktionstest, nachdem ortools bereits geladen ist.
NUR_PRUEFEN = {"highspy", "cvxpy"}
def paket_version(name: str) -> str:
"""Liefert die installierte Version; ImportError, falls das Paket fehlt."""
if name in NUR_PRUEFEN:
if importlib.util.find_spec(name) is None:
raise ImportError(name) # nicht installiert
try:
# Version aus den Metadaten — das Modul wird ja nicht geladen
return importlib.metadata.version(name)
except importlib.metadata.PackageNotFoundError:
return "unbekannt" # installiert, aber ohne Metadaten
modul = importlib.import_module(name)
return getattr(modul, "__version__", "unbekannt")
def pruefe_pakete() -> list[str]:
"""Prüft jedes Paket und meldet Version oder Fehlgrund."""
fehlend = []
print(f"Python-Version: {sys.version.split()[0]}\n")
print(f"{'Paket':<12} {'Version':<12} {'Zweck'}")
print("-" * 78)
for name, zweck in PAKETE:
try:
print(f"{name:<12} {paket_version(name):<12} {zweck}")
except ImportError:
print(f"{name:<12} {'FEHLT':<12} {zweck}")
fehlend.append(name)
return fehlend
def teste_cp_sat() -> bool:
"""Löst 'maximiere x+y unter x+2y<=10, x<=4' mit CP-SAT. Erwartet: x=4, y=3."""
from ortools.sat.python import cp_model
modell = cp_model.CpModel()
x = modell.NewIntVar(0, 4, "x")
y = modell.NewIntVar(0, 10, "y")
modell.Add(x + 2 * y <= 10)
modell.Maximize(x + y)
loeser = cp_model.CpSolver()
status = loeser.Solve(modell)
ok = status == cp_model.OPTIMAL and loeser.Value(x) == 4 and loeser.Value(y) == 3
print(f"CP-SAT : x={loeser.Value(x)}, y={loeser.Value(y)} -> {'OK' if ok else 'FEHLER'}")
return ok
def teste_scipy_linprog() -> bool:
"""Löst dasselbe Problem kontinuierlich mit HiGHS über SciPy. Erwartet: x=4, y=3."""
from scipy.optimize import linprog
# linprog minimiert -> Zielfunktion negieren, um zu maximieren
ergebnis = linprog(c=[-1, -1], A_ub=[[1, 2]], b_ub=[10],
bounds=[(0, 4), (0, 10)], method="highs")
ok = ergebnis.success and abs(ergebnis.x[0] - 4) < 1e-6 and abs(ergebnis.x[1] - 3) < 1e-6
print(f"SciPy/HiGHS : x={ergebnis.x[0]:.2f}, y={ergebnis.x[1]:.2f} -> {'OK' if ok else 'FEHLER'}")
return ok
def teste_cvxpy() -> bool:
"""Minimiert (x-2)^2 unter x<=1 mit CVXPY. Erwartet: x=1."""
# CVXPY warnt beim Import, wenn sein HIGHS-Interface wegen der
# HiGHS-Kollision (siehe Kapitel Ökosystem) nicht lädt — für diesen Test
# folgenlos, deshalb die Warnung kurz stillstellen.
logging.disable(logging.WARNING)
import cvxpy as cp
logging.disable(logging.NOTSET)
x = cp.Variable()
problem = cp.Problem(cp.Minimize(cp.square(x - 2)), [x <= 1])
problem.solve()
ok = problem.status == "optimal" and abs(x.value - 1.0) < 1e-6
print(f"CVXPY : x={x.value:.4f} -> {'OK' if ok else 'FEHLER'}")
return ok
if __name__ == "__main__":
# ortools' native Bibliothek zuerst laden (Kapitel Ökosystem): die zuerst
# geladene HiGHS-Kopie gewinnt — und das soll die von ortools sein.
if importlib.util.find_spec("ortools") is not None:
from ortools.sat.python import cp_model
fehlend = pruefe_pakete()
print("\nSolver-Funktionstest")
print("-" * 78)
if fehlend:
print(f"Abbruch: Es fehlen {len(fehlend)} Pakete: {', '.join(fehlend)}")
print("Installation: pip install " + " ".join(
"scikit-learn" if p == "sklearn" else p for p in fehlend))
sys.exit(1)
alle_ok = all([teste_cp_sat(), teste_scipy_linprog(), teste_cvxpy()])
print("-" * 78)
print("Alles bereit — Sie können mit dem ersten Kapitel beginnen."
if alle_ok else "Mindestens ein Solver arbeitet fehlerhaft.")
sys.exit(0 if alle_ok else 1)Erwartete Ausgabe (Versionsnummern können abweichen):
Python-Version: 3.12.3
Paket Version Zweck
------------------------------------------------------------------------------
numpy 2.1.3 Numerische Basis (Vektoren, Matrizen)
scipy 1.14.1 Wissenschaftliche Algorithmen, linprog/minimize
...
Solver-Funktionstest
------------------------------------------------------------------------------
CP-SAT : x=4, y=3 -> OK
SciPy/HiGHS : x=4.00, y=3.00 -> OK
CVXPY : x=1.0000 -> OK
------------------------------------------------------------------------------
Alles bereit — Sie können mit dem ersten Kapitel beginnen.
Hinweis zur Reproduzierbarkeit: Die Programme aus Teil IV (Kapitel 18 bis Kapitel 21) laden aktuelle Kursdaten live über
yfinance. Die im Buchtext abgedruckten Zahlen dienen daher nur zur Illustration — bei eigenem Ausführen weichen sie je nach Abrufdatum und gewähltem Zeitfenster ab. Das ist beabsichtigt und selbst Teil der Lektion über die Instabilität empirischer Schätzungen (Kapitel 18).
Wie dieses Buch aufgebaut ist
Jedes Kapitel folgt derselben Struktur. Wenn Sie wissen, wie die Bausteine funktionieren, können Sie gezielt springen.
Die Lernelemente
Kapitel auf einen Blick Zu Beginn jedes Kapitels: Worum geht es, was wird vorausgesetzt, was können Sie danach, wie lange dauert es. Nutzen Sie diese Box, um zu entscheiden, ob Sie das Kapitel gerade brauchen.
📐 Formel-Lesehilfe Steht unter jeder wichtigen Formel und benennt jedes Symbol einzeln, gefolgt von einer Umschreibung in Alltagssprache („Ohne Formel gesagt: …“). Wer die Formel schon versteht, überspringt die Box.
✏️ Handrechnung Ein kleines Zahlenbeispiel, das Sie mit Papier und Bleistift nachvollziehen können — ohne Computer. Diese Rechnungen sind bewusst winzig gehalten, damit der Mechanismus sichtbar wird, den der Solver später millionenfach ausführt.
💻 Code-Durchgang Nach jedem längeren Programm eine Tabelle, die die entscheidenden Zeilen erklärt. Vollständige Programme sind bewusst am Stück abgedruckt und nicht in Fragmente zerlegt — Sie sollen sie kopieren und laufen lassen können.
⚠️ Typische Fehler Die Fallen, in die erfahrungsgemäß viele tappen — mit dem Symptom, das sie erzeugen, und der Korrektur.
🎯 Merksatz Die eine Aussage, die vom Abschnitt hängen bleiben soll.
📝 Übungsaufgaben Am Kapitelende, gestaffelt nach Schwierigkeit: ⭐ Verständnis (im Kopf oder in zwei Sätzen) · ⭐⭐ Handrechnung oder kleine Modelländerung · ⭐⭐⭐ Eigenständige Programmieraufgabe. Alle Lösungen stehen in
90_Anhang_Loesungen.md.
✅ Selbsttest Fünf Fragen mit Kurzantworten zur schnellen Selbstkontrolle.
Der Dreischritt jedes Kapitels
- Problemstellung — eine konkrete Entscheidungssituation, kein abstraktes Beispiel.
- Mathematische Formulierung — mit Lesehilfe und, wo möglich, Handrechnung.
- Lauffähiges Python-Programm — vollständig abgedruckt, mit erwarteter Ausgabe.
Für wen dieses Buch geschrieben ist
Die Lernpfade weiter unten sind nach Themen geschnitten. Dieser Abschnitt ist nach Rollen geschnitten: vier Einstiege für vier Arten, mit Optimierung zu tun zu haben. Jeder nennt den Schmerzpunkt, drei Dinge, die das Buch dafür wirklich liefert — mit den Zahlen, die es dazu misst —, den passenden Lernpfad und die Frage, an der es in dieser Rolle am häufigsten scheitert.
Suchen Sie sich einen aus. Sie können auch alle vier überspringen; nötig sind sie nicht.
Für Entscheider und Manager — der Geschäftsfall
„Wir planen seit Jahren mit Erfahrungswerten, und es funktioniert. Warum sollte ein Modell das besser können — und was kostet mich der Irrtum, wenn ich es nicht tue?“
- Was Planen mit Durchschnitten kostet, wird hier beziffert, nicht behauptet. Im Kraftwerkseinsatz aus Kapitel 17 kostet ein Plan, der mit dem Wind-Erwartungswert rechnet, in der Wirklichkeit 149 % mehr als einer, der 40 Szenarien berücksichtigt — 874 870 € statt 351 356 € — und führt in 28 von 40 Szenarien zum Lastabwurf statt in keinem.
- „Wie sicher soll es sein?“ wird eine Preisfrage. Abschnitt 12.7 rechnet aus, was ein Prozentpunkt Versorgungssicherheit kostet: rund 56 000 € auf dem Weg zu 80 %, rund 254 000 € zwischen 95 und 99 %. Das 4,5-fache. Wer 99,9 % fordert, ohne diese Kurve gesehen zu haben, fordert ins Blaue.
- Für die Sitzung gibt es einen Bericht, keine Tabelle. Abschnitt 22.4 beziffert je Nebenbedingung, was sie den Plan kostet, und formuliert daraus Sätze in Alltagssprache. Für die Frage des Betriebsrats — „warum ausgerechnet ich?“ — liefert Kapitel 22 den Constraint-Trace, der die einzelne Zuweisung begründet.
Ihr Weg. Zuerst Pfad E (2–4 Stunden): Abschnitt 1.5 und Anhang B. Wenn Sie danach wissen wollen, was in Ihrem Betrieb geht, Pfad B und Projekt P1 oder P2.
Woran es scheitert. Nicht am Modell, sondern an der Einführung — das ist der meistgenannte Befund in Kapitel 22. Und an einer Verwechslung, die dieses Buch Ihnen nicht abnehmen kann: Ein Bericht erklärt das Modell, nicht die Wirklichkeit. Ist ein Deckungsbeitrag falsch geschätzt, ist er überzeugend und falsch. Fragen Sie deshalb jedes Mal, worauf eine Zahl beruht.
Eine Erwartung, die dieses Buch enttäuscht: Es nennt keine ROI-Kennzahl und keine Amortisationsdauer. Beide hängen an Ihrem Betrieb, und jede Zahl hier wäre erfunden. Was es stattdessen liefert, ist das Werkzeug, Ihre eigene auszurechnen: den EVPI in Kapitel 12 (was eine perfekte Prognose überhaupt wert wäre — eine Obergrenze für jedes Prognoseprojekt) und die Kostenzurechnung aus Abschnitt 22.4.
Für Ingenieure und Produktionsplaner — die Physik des Systems
„Der Engpass wandert. Kaum ist eine Maschine entlastet, steht die nächste — und niemand kann mir vorher sagen, welche.“
- Der Engpass lässt sich benennen und bepreisen. Abschnitt 22.4 rechnet für jede Kapazität aus, was die nächste Stunde wert ist — und wie weit dieser Wert trägt. Im Beispiel gilt der Schattenpreis der Lackiererei exakt bis +15 Stunden; eine ganze Sonderschicht von 30 Stunden bringt deshalb 60 € statt der rechnerischen 120 €. Die zweite Hälfte wäre bezahlt und wirkungslos.
- Rüstzeiten, Reihenfolgen, Taktzeiten sind der Kern, nicht die Ausnahme. Kapitel 7 modelliert Maschinenbelegung mit Intervallvariablen, Kapitel 9 zeigt am selben Fall das Gesamtbild: Faustregel 2 497 Minuten Rüstzeit, CP-SAT allein 2 628, Simulated Annealing 2 343, Annealing plus LNS 2 289 — und die untere Schranke bei 1 768, damit sichtbar bleibt, wie viel Luft noch da ist.
- Wenn der Solver zu lange braucht, gibt es Zahlen statt Ratschläge. Abschnitt 7.7 misst, was mehrere Suchstränge bringen (hier Faktor 12,3) — und ab wo mehr Arbeiter wieder schaden.
Ihr Weg. Pfad B bis Kapitel 7, dann Projekt P5 (Produktionsplanung mit Rüstkosten). Wenn Ihre echten Instanzen den Solver stehen lassen: Kapitel 9 und Projekt P9.
Woran es scheitert. An der Verwechslung von bindend und teuer. Eine Bedingung kann den Plan berühren und trotzdem nichts kosten — im Beispiel von Abschnitt 22.4 gilt das für eine von fünf bindenden. Wer sie nachverhandelt, gewinnt nichts und hält das Verfahren für nutzlos.
Für Investoren und Finanzanalysten — Risiko und Ertrag
„Die Optimierung liefert mir Gewichte, die kein Mensch halten würde: 60 % in einem Titel, null in fünf anderen. Und im nächsten Quartal sieht sie völlig anders aus.“
- Der Grund dafür steht in Kapitel 18, nicht in Kapitel 19. Eine aus kurzen Zeitreihen geschätzte Kovarianzmatrix ist schlecht konditioniert; der Optimierer setzt dann auf Schätzrauschen. Shrinkage nach Ledoit-Wolf ist das Gegenmittel; ihre Wirkung wird an Eigenwertspektrum und Konditionszahl gemessen, nicht behauptet.
- Der VaR verschweigt genau das, worauf es ankommt. In der Stichprobe aus Kapitel 20 sagt der VaR: „an 95 % der Tage höchstens 1,86 % Verlust“. Der CVaR sagt: „und wenn doch, dann im Mittel 2,99 %“. Der schlechteste Tag der Stichprobe liegt bei −23,0 % — am VaR ändert dieser eine Tag nichts, am CVaR sehr wohl. Deshalb ist der CVaR die Größe, die man optimiert.
- Transaktionskosten und Rebalancing sind Teil des Modells, nicht ein Abzug danach. Kapitel 20 nimmt sie in die Zielfunktion, Kapitel 21 setzt den Backtest daneben — samt der Fallen, die einen guten Backtest wertlos machen.
Ihr Weg. Pfad D, und zwar mit Kapitel 18. Danach Projekt P6 (Portfolio-Rebalancer) oder P7 (Risikoreport mit CVaR und Stresstests).
Woran es scheitert. An der Reihenfolge. Wer bei Markowitz einsteigt und die Datenkapitel überspringt, bekommt ein Modell, das seine eigenen Schätzfehler maximiert — und merkt es erst im Echtgeldbetrieb.
Für Studierende und Data Scientists — die Methodik
„Ich kann ein Modell trainieren und den Fehler senken. Aber wie wird aus einer Prognose eine Entscheidung — und woher weiß ich, dass sie gut ist?“
- Die unbequemste Erkenntnis zuerst. Kapitel 15 zeigt an einem gerechneten Fall, dass das Modell mit dem schlechteren MSE die günstigere Entscheidung trifft. Prognosegüte und Entscheidungsqualität sind zwei verschiedene Größen; wer die eine optimiert, bekommt die andere nicht geschenkt.
- Dieselbe Mathematik, zwei Welten. Kapitel 16 lässt denselben Code einmal über eine Werkstatt und einmal über ein Depot laufen — und benennt die drei Stellen, an denen die Analogie endet. Struktur zu erkennen ist die eigentliche Fähigkeit, nicht Bibliothekskenntnis; zu wissen, wo eine Analogie aufhört, gehört dazu.
- Es wird gerechnet, nicht nacherzählt. Zu jedem Kapitel gehören Aufgaben mit vollständigen Lösungen, Handrechnungen und ein „Finde den Denkfehler“ — und jedes abgedruckte Ergebnis stammt aus einem echten Lauf des danebenstehenden Programms.
Ihr Weg. Pfad A, wenn Sie Zeit haben. Sonst Pfad B oder D bis zum ersten Projekt und von dort zurück in die Grundlagen. Für eigene Fragestellungen: Projekt P8.
Woran es scheitert. An der Annahme, ein Solver sei eine Bibliothek wie jede andere. Die schwierige Arbeit steckt in der Formulierung — Kapitel 4 ist deshalb kein Vorgeplänkel, sondern das Kapitel, auf das alle anderen aufbauen.
Lernpfade
Sie müssen nicht alles lesen, um etwas Nützliches bauen zu können.
Pfad A — Vollständiger Lehrgang (100–140 Stunden)
Kapitel 1 bis Kapitel 23 in Reihenfolge, danach ein Projekt aus der Projektwerkstatt. Empfohlen, wenn Sie OR systematisch lernen wollen. Rechnen Sie mit 4–6 Stunden je Kapitel inklusive Übungen.
Pfad B — Planung, Disposition, Personaleinsatz (ca. 25 Stunden)
Kapitel 1 (Bausteine) → Kapitel 2 (bis Abschnitt 2.5) → Kapitel 4 (vom Wunsch zum Modell) → Kapitel 5 (LP, Schattenpreise) → Kapitel 6 (Ja/Nein-Entscheidungen) → Kapitel 7 (CP-SAT, Scheduling) → Projekt P1 (Vertretungsplaner) oder P2 (Schichtplanung). Das ist der kürzeste Weg zu einem einsetzbaren Dienstplan-Optimierer.
Wenn der Solver bei Ihrer echten Instanz stehen bleibt: Kapitel 9 und Projekt P9.
Pfad C — Logistik und Tourenplanung (ca. 25 Stunden)
Kapitel 1 → Kapitel 2 (bis Abschnitt 2.4) → Kapitel 5 → Kapitel 6 → Kapitel 8 (Graphen, VRP) → Projekt P3 (Liefertouren) oder P4 (Lagernetzwerk).
Wenn die Instanzen zu groß werden: Kapitel 9 (gute Lösung in fester Zeit) und Kapitel 10 (das Modell umbauen statt die Lösung raten) — dazu Projekt P9, das beide Wege am selben Problem vergleicht.
Pfad D — Quantitative Finance (ca. 30 Stunden)
Kapitel 1 → Kapitel 2 → Kapitel 11 (QP, KKT) → Kapitel 18 (Daten, Shrinkage) → Kapitel 19 (Markowitz) → Kapitel 20 (CVaR) → Kapitel 21 (Backtest) → Projekt P6 (Portfolio-Rebalancer) oder P7 (Risikoreport). Wichtig: Überspringen Sie Kapitel 18 nicht. Wer direkt bei Markowitz einsteigt, optimiert Schätzrauschen und wundert sich über absurde Gewichte.
Pfad E — Ich habe morgen ein konkretes Problem (2–4 Stunden)
Lesen Sie Abschnitt 1.5 (die vier Bausteine), dann Anhang B (Modellierungsmuster) und suchen Sie dort das Muster, das zu Ihrem Problem passt. Von jedem Muster führt ein Verweis in das zuständige Kapitel. Wie die gewählte Bibliothek es schreibt, steht in Anhang D (Spickzettel); wenn etwas nicht läuft, in Anhang C (Fehlerdiagnose).
Pfad F — Vom Prototyp in den Betrieb (ca. 15 Stunden)
Für alle, deren Modell rechnet und die es jetzt jemand anderem übergeben müssen: Kapitel 22 (die fünf Praxisfallen, or_kern.py, Erklärbarkeit) → Kapitel 23 (Testsuite, Mutationstest, Benchmark, HTTP-Dienst) → Anhang C als Nachschlagewerk für den Ernstfall, dann Projekt P11 (Vom Skript zum Dienst). Setzt voraus, dass Sie mindestens einen der Pfade B, C oder D hinter sich haben — P11 baut auf einem Modell auf, das Sie schon haben.
Der Kern in einem Satz: Ein Modell, das nur auf Ihrem Rechner und nur mit Ihren Daten läuft, ist ein Prototyp — kein System.
Verzeichnis der Beispielprogramme
Alle Beispielprogramme dieses Buchs im Überblick, sortiert nach Kapitel — praktisch für Pfad E oder um gezielt nach einem Thema zu suchen:
| Programm | Thema | Kapitel |
|---|---|---|
Installationstest.py |
Installationsprüfung | Vorspann |
Bot_Allokation.py |
Erstes CP-SAT-Modell | Kapitel 1 |
Brute_Force_Vergleich.py |
Kombinatorische Explosion | Kapitel 1 |
Bausteine_Vorlage.py |
Vorlage für eigene Modelle | Kapitel 1 |
Excel_Bruecke.py |
Excel-Mappe lesen, lösen, zurückschreiben | Kapitel 1 |
Matrixform.py |
Matrixform und Zulässigkeit | Kapitel 2 |
Konvexitaet_Demo.py |
Sehnen-Test, lokale Optima | Kapitel 2 |
Visualisierung_Loesungsraum.py |
Polyeder mit Ecken | Kapitel 2 |
Skalierung_Kondition.py |
Konditionszahl, Ruiz, Toleranzen | Kapitel 2 |
Solver_Wahl.py |
Entscheidungshilfe | Kapitel 3 |
Ein_System_Vier_Ansaetze.py |
Vier Bibliotheken | Kapitel 3 |
Modellierungsschichten.py |
Pyomo und Linopy | Kapitel 3 |
Vektorisierte_Modellgenerierung.py |
Aufbauzeit vs. Lösezeit | Kapitel 3 |
Vom_Wunsch_zum_Modell.py |
Fünf Modelle auf denselben Daten | Kapitel 4 |
Simplex_Tableau_LP.py |
Simplex von Grund auf | Kapitel 5 |
Sensitivitaetsanalyse.py |
Schattenpreise | Kapitel 5 |
Dualitaet_Nachweis.py |
Primal-dual, starke Dualität | Kapitel 5 |
Toleranzen_und_Entartung.py |
Entartung, Toleranzen, Dualspannen | Kapitel 5 |
Runden_Gegenbeispiel.py |
Warum Runden scheitert | Kapitel 6 |
Rucksack.py |
Knapsack, LP-Schranke | Kapitel 6 |
MILP_Portfolio_Fixgebuehren.py |
Fixkosten, Kardinalität | Kapitel 6 |
Solverstatus_und_Gap.py |
MIP-Gap, Zeitlimit, Statusfälle | Kapitel 6 |
Warmstart_Effekt.py |
LPT-Hinweis für CP-SAT | Kapitel 6 |
Big_M_Falle.py |
Trickle Flow bei zu großem M | Kapitel 6 |
Propagation_Demo.py |
Propagation messbar | Kapitel 7 |
CP_SAT_Vertretungssystem.py |
Vertretungsplan | Kapitel 7 |
JobShop_Intervalle.py |
Job-Shop-Scheduling | Kapitel 7 |
Parallele_Suche.py |
num_workers: Tempo gegen Reproduzierbarkeit | Kapitel 7 |
CP_SAT_Statusfaelle.py |
Die fünf Solver-Antworten | Kapitel 7 |
Strafgewichte.py |
Gewichte als Wechselkurse | Kapitel 7 |
Min_Cost_Flow.py |
Netzwerkfluss | Kapitel 8 |
Zuordnung_Ungarisch.py |
Zuordnung, Unimodularität | Kapitel 8 |
VRP_Flotten_Routing.py |
CVRPTW | Kapitel 8 |
VRP_Kapazitaetsfalle.py |
Vergessene Dimension im Routing | Kapitel 8 |
Simulated_Annealing.py |
Lokale Suche, Temperatur kalibrieren | Kapitel 9 |
Metaheuristik_vs_Exakt.py |
Der Umschlagpunkt, und die Schranke | Kapitel 9 |
Large_Neighborhood_Search.py |
Zerstören und exakt reparieren | Kapitel 9 |
Spaltengenerierung.py |
Muster statt Stücke, Master und Pricing | Kapitel 10 |
QP_Grundlagen.py |
Konvexität, DCP-Check | Kapitel 11 |
KKT_Nachweis.py |
KKT numerisch prüfen | Kapitel 11 |
Entropie_Maximierte_Allokation.py |
NLP mit Entropie | Kapitel 11 |
Lokale_Optima_Multistart.py |
Lokale Optima, Multistart | Kapitel 11 |
Fluch_des_Durchschnitts.py |
Optimum ≠ Mittelwert | Kapitel 12 |
Monte_Carlo.py |
Monte-Carlo-Bewertung | Kapitel 12 |
Stochastische_Optimierung.py |
Two-Stage mit Recourse | Kapitel 12 |
Robuste_Optimierung.py |
Worst-Case-Absicherung | Kapitel 12 |
Chance_Constraints.py |
Zusage „mit 95 % Sicherheit“, SOC und Big-M | Kapitel 12 |
Bellman_Minimalbeispiel.py |
Rückwärtsinduktion | Kapitel 13 |
Mehrziel_Pareto.py |
Pareto-Front, ε-Constraint, Gewichtslücke | Kapitel 14 |
Predict_then_Optimize.py |
MSE gegen Entscheidungskosten | Kapitel 15 |
Strukturbruecke.py |
Derselbe Code über Werkstatt und Depot | Kapitel 16 |
Kraftwerkseinsatz.py |
Unit Commitment unter Windunsicherheit | Kapitel 17 |
Mehrperiodige_Order_Execution.py |
Almgren-Chriss | Kapitel 13 |
Renditen_Vergleich.py |
Diskret vs. logarithmisch | Kapitel 18 |
Schaetzrauschen_Demo.py |
Error-Maximizer messen | Kapitel 18 |
Finanzdaten_Ledoit_Wolf.py |
Datenpipeline, Shrinkage | Kapitel 18 |
Kovarianz_Falle.py |
Singuläre Kovarianz, Error-Maximizer | Kapitel 18 |
Markowitz_CVXPY.py |
GMV, Max Sharpe, Frontier | Kapitel 19 |
Diversifikation_Demo.py |
Korrelation und Portfoliorisiko | Kapitel 19 |
Renditeschaetzung_Falle.py |
Schätzfehler in erwarteten Renditen | Kapitel 19 |
VaR_CVaR_Demo.py |
Fat Tails, Subadditivität | Kapitel 20 |
CVaR_Portfolio.py |
CVaR mit Reibung | Kapitel 20 |
QuantitativeTradingEngine.py |
Walk-Forward-Backtest | Kapitel 21 |
Backtest_Fallen.py |
Fünf Selbsttäuschungen | Kapitel 21 |
Data_Snooping.py |
Bestes aus N Versuchen auf Rauschen | Kapitel 21 |
Infeasibility_Diagnose.py |
Notfallplan statt Fehler | Kapitel 22 |
Erklaerbarkeit.py |
Constraint-Trace, Was-wäre-wenn | Kapitel 22 |
Constraint_Attribution.py |
Was kostet welche Bedingung? Managementbericht | Kapitel 22 |
Betriebsueberwachung.py |
Status, Gap und Zeitausschöpfung | Kapitel 22 |
or_kern.py |
Gemeinsamer Unterbau: Domäne, Status, Prüfung | Kapitel 22 |
Solverwechsel_CPSAT_HiGHS.py |
Derselbe Fall in zwei Solvern | Kapitel 22 |
test_or_kern.py |
Testsuite für ein Optimierungsmodell | Kapitel 23 |
Mutationstest.py |
Findet die Lücken der eigenen Tests | Kapitel 23 |
Benchmark_Skalierung.py |
Aufbau gegen Lösen, vier Bibliotheken | Kapitel 23 |
Optimierungsdienst.py |
Das Modell als HTTP-Dienst | Kapitel 23 |
Konfliktsuche.py |
Deletion Filter: den Widerspruch einkreisen | Anhang C |
Was dieses Buch nicht ist
Es ist keine Anleitung zum Bau eigener Solver — wir nutzen ausgereifte Implementierungen und investieren die Zeit stattdessen in die Modellierung. Die einzige Ausnahme ist der Simplex-Algorithmus in Kapitel 5, den wir von Grund auf programmieren, weil man ihn verstanden haben muss, um Dualität und Schattenpreise zu begreifen.
Es ist kein Buch über maschinelles Lernen. Prognosen kommen nur so weit vor, wie sie als Eingangsdaten einer Optimierung nötig sind.
Und der vierte Teil ist ausdrücklich keine Anlageberatung. Die Finanzbeispiele demonstrieren Methodik an realen Daten, nicht handelbare Strategien. Kapitel 22 erklärt ausführlich, warum ein gut aussehender Backtest noch keine funktionierende Strategie ist.
Ein Wort zur Arbeitsweise
Die wirksamste Art, mit diesem Buch zu arbeiten, ist unbequem: Lesen Sie die Problemstellung, schließen Sie das Buch und versuchen Sie, das Modell selbst aufzuschreiben — Variablen, Zielfunktion, Nebenbedingungen. Vergleichen Sie erst dann. Die Abweichungen zwischen Ihrem Entwurf und dem Text sind genau die Stellen, an denen Sie etwas lernen. Wer stattdessen mitliest und nickt, hat am Ende des Kapitels das angenehme Gefühl, es verstanden zu haben — und steht beim eigenen Problem vor einem leeren Blatt.
Zweitens: Lassen Sie jedes Programm laufen und verändern Sie danach eine Zahl. Was passiert mit dem Vertretungsplan, wenn eine Lehrkraft ausfällt? Was mit dem Portfolio, wenn die Obergrenze von 20 % auf 10 % sinkt? Diese Experimente kosten Sekunden und bauen genau die Intuition auf, die man später beim Modellieren braucht.
Und drittens: Nehmen Sie die Übungen ernst. Sie sind nicht Beiwerk, sondern der Ort, an dem aus Kenntnis Können wird.
Weiter mit: 01_Notation_und_Abkuerzungen.md — oder direkt zu [Kapitel 1](einfuehrung.html#kap-einfuehrung), wenn Sie die Notation lieber nachschlagen, sobald sie auftaucht.