Glossar: Sprungleiste, Abkürzungen ausschreiben, CLAUDE.md-Regel

Sprungleiste (A B C ... Z) im Glossar — wie im Stichwortverzeichnis:
ein Klick je Buchstabe springt zur '## <Buchstabe>'-Überschrift.
Eingebaut in erzeuge_glossar_04.py als {=html}-Rohblock (nur HTML,
im PDF bedeutungslos).

Abkürzungen beim ersten Mal ausschreiben: 'VaR' → 'VaR (Value at Risk)',
'EVPI' → 'EVPI (Expected Value of Perfect Information)' als Link-Text
bei der ersten Nennung je Datei; danach nur die Abkürzung. 19 Abkürzungen
erfasst (VaR, CVaR, KKT, NLP, MILP, EVPI, LP, QP, ...).

CLAUDE.md: Regel 'Glossar-Links: Fachbegriffe im Fließtext automatisch
verlinkt' dokumentiert — resolve_glossar(), LINK_TEXTE,
ABBREV_ERSTE_NENNUNG, _NICHT_AUTO_LINKEN, _ZU_KURZ_ABK, .glossar-link,
{gl:}-Marke, Sprungleiste, {#gloss:<slug>}-Anchor.
This commit is contained in:
dschlueter 2026-09-10 17:52:49 +02:00
commit 0e2c011732
47 changed files with 545 additions and 561 deletions

View file

@ -26,7 +26,7 @@ Autor / Herausgeber: Dieter Schlüter
<dieter(dot)schlueter(atsign)linix(dot)de>
Stand: 10. September 2026 v17.38
Stand: 10. September 2026 v17.50
---
@ -300,14 +300,14 @@ Suchen Sie sich einen aus. Sie können auch alle vier überspringen; nötig sind
**Woran es scheitert.** Nicht am Modell, sondern an der Einführung — das ist der meistgenannte Befund in [Kapitel 22](#kap-praxisfallen). 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](#gloss:evpi-expected-value-of-perfect-information){.glossar-link}** in [Kapitel 12](#kap-unsicherheit) (was eine perfekte Prognose überhaupt wert wäre — eine Obergrenze für jedes Prognoseprojekt) und die Kostenzurechnung aus [Abschnitt 22.4](#sec:praxisfallen-attribution).
> **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 (Expected Value of Perfect Information)](#gloss:evpi-expected-value-of-perfect-information){.glossar-link}** in [Kapitel 12](#kap-unsicherheit) (was eine perfekte Prognose überhaupt wert wäre — eine Obergrenze für jedes Prognoseprojekt) und die Kostenzurechnung aus [Abschnitt 22.4](#sec:praxisfallen-attribution).
### 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](#sec:praxisfallen-attribution) 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](#gloss:schattenpreis){.glossar-link}`\index{Schattenpreis}`{=latex} 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](#kap-cpsat) modelliert Maschinenbelegung mit Intervallvariablen, [Kapitel 9](#kap-metaheuristiken) zeigt am selben Fall das Gesamtbild: Faustregel 2 497 Minuten [Rüstzeit](#gloss:ruestzeit){.glossar-link}`\index{Rüstzeit}`{=latex}, [CP](#gloss:constraint-programming-cp){.glossar-link}-[SAT](#gloss:sat-boolean-satisfiability){.glossar-link} allein 2 628, [Simulated Annealing](#gloss:simulated-annealing){.glossar-link}`\index{Simulated Annealing}`{=latex} 2 343, Annealing plus [LNS](#gloss:large-neighborhood-search-lns){.glossar-link} **2 289** — und die untere Schranke bei 1 768, damit sichtbar bleibt, wie viel Luft noch da ist.
* **Rüstzeiten, Reihenfolgen, Taktzeiten sind der Kern, nicht die Ausnahme.** [Kapitel 7](#kap-cpsat) modelliert Maschinenbelegung mit Intervallvariablen, [Kapitel 9](#kap-metaheuristiken) zeigt am selben Fall das Gesamtbild: Faustregel 2 497 Minuten [Rüstzeit](#gloss:ruestzeit){.glossar-link}`\index{Rüstzeit}`{=latex}, [CP (Constraint Programming)](#gloss:constraint-programming-cp){.glossar-link}-[SAT (Boolean Satisfiability)](#gloss:sat-boolean-satisfiability){.glossar-link} allein 2 628, [Simulated Annealing](#gloss:simulated-annealing){.glossar-link}`\index{Simulated Annealing}`{=latex} 2 343, Annealing plus [LNS (Large Neighborhood Search)](#gloss:large-neighborhood-search-lns){.glossar-link} **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](#sec:cpsat-parallele-suche) misst, was mehrere Suchstränge bringen (hier Faktor 12,3) — und ab wo mehr Arbeiter wieder schaden.
**Ihr Weg.** Pfad B bis [Kapitel 7](#kap-cpsat), dann Projekt **P5** (Produktionsplanung mit Rüstkosten). Wenn Ihre echten Instanzen den Solver stehen lassen: [Kapitel 9](#kap-metaheuristiken) und Projekt **P9**.
@ -319,7 +319,7 @@ Suchen Sie sich einen aus. Sie können auch alle vier überspringen; nötig sind
> *„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](#kap-finanzdaten), nicht in [Kapitel 19](#kap-markowitz).** Eine aus kurzen Zeitreihen geschätzte [Kovarianzmatrix](#gloss:kovarianzmatrix){.glossar-link}`\index{Kovarianzmatrix}`{=latex} ist schlecht konditioniert; der Optimierer setzt dann auf Schätzrauschen. Shrinkage nach Ledoit-Wolf ist das Gegenmittel; ihre Wirkung wird an **Eigenwertspektrum und [Konditionszahl](#gloss:konditionszahl){.glossar-link}**`\index{Konditionszahl}`{=latex} gemessen, nicht behauptet.
* **Der [VaR](#gloss:value-at-risk-var){.glossar-link} verschweigt genau das, worauf es ankommt.** In der Stichprobe aus [Kapitel 20](#kap-cvar) sagt der VaR: „an 95 % der Tage höchstens **1,86 %** Verlust“. Der [CVaR](#gloss:conditional-value-at-risk-cvar){.glossar-link} 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.
* **Der [VaR (Value at Risk)](#gloss:value-at-risk-var){.glossar-link} verschweigt genau das, worauf es ankommt.** In der Stichprobe aus [Kapitel 20](#kap-cvar) sagt der VaR: „an 95 % der Tage höchstens **1,86 %** Verlust“. Der [CVaR (Conditional Value at Risk)](#gloss:conditional-value-at-risk-cvar){.glossar-link} 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](#gloss:transaktionskosten){.glossar-link}`\index{Transaktionskosten}`{=latex} und [Rebalancing](#gloss:rebalancing){.glossar-link} sind Teil des Modells, nicht ein Abzug danach.** [Kapitel 20](#kap-cvar) nimmt sie in die [Zielfunktion](#gloss:zielfunktion){.glossar-link}`\index{Zielfunktion}`{=latex}, [Kapitel 21](#kap-handelsmaschine) setzt den [Backtest](#gloss:backtest){.glossar-link} daneben — samt der Fallen, die einen guten Backtest wertlos machen.
**Ihr Weg.** Pfad D, und zwar **mit** [Kapitel 18](#kap-finanzdaten). Danach Projekt **P6** (Portfolio-Rebalancer) oder **P7** (Risikoreport mit CVaR und Stresstests).
@ -350,19 +350,19 @@ Sie müssen nicht alles lesen, um etwas Nützliches bauen zu können.
### Pfad B — Planung, Disposition, Personaleinsatz (ca. 25 Stunden) {-}
[Kapitel 1](#kap-einfuehrung) (Bausteine) → [Kapitel 2](#kap-fundament) (bis [Abschnitt 2.5](#sec:fundament-konvexitaet-die-grenze-zwischen-leicht-und)) → [Kapitel 4](#kap-modellierung) (vom Wunsch zum Modell) → [Kapitel 5](#kap-lp) ([LP](#gloss:lineare-programmierung-lp){.glossar-link}, Schattenpreise) → [Kapitel 6](#kap-milp) (Ja/Nein-Entscheidungen) → [Kapitel 7](#kap-cpsat) (CP-SAT, Scheduling) → Projekt **P1** (Vertretungsplaner) oder **P2** (Schichtplanung). Das ist der kürzeste Weg zu einem einsetzbaren Dienstplan-Optimierer.
[Kapitel 1](#kap-einfuehrung) (Bausteine) → [Kapitel 2](#kap-fundament) (bis [Abschnitt 2.5](#sec:fundament-konvexitaet-die-grenze-zwischen-leicht-und)) → [Kapitel 4](#kap-modellierung) (vom Wunsch zum Modell) → [Kapitel 5](#kap-lp) ([LP (Lineare Programmierung)](#gloss:lineare-programmierung-lp){.glossar-link}, Schattenpreise) → [Kapitel 6](#kap-milp) (Ja/Nein-Entscheidungen) → [Kapitel 7](#kap-cpsat) (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](#kap-metaheuristiken) und Projekt **P9**.
### Pfad C — Logistik und Tourenplanung (ca. 25 Stunden) {-}
[Kapitel 1](#kap-einfuehrung) → [Kapitel 2](#kap-fundament) (bis [Abschnitt 2.4](#sec:fundament-der-zulaessige-loesungsraum-und-das-polyeder)) → [Kapitel 5](#kap-lp) → [Kapitel 6](#kap-milp) → [Kapitel 8](#kap-graphen) ([Graphen](#gloss:graphen){.glossar-link}, [VRP](#gloss:vehicle-routing-problem-vrp){.glossar-link}) → Projekt **P3** (Liefertouren) oder **P4** (Lagernetzwerk).
[Kapitel 1](#kap-einfuehrung) → [Kapitel 2](#kap-fundament) (bis [Abschnitt 2.4](#sec:fundament-der-zulaessige-loesungsraum-und-das-polyeder)) → [Kapitel 5](#kap-lp) → [Kapitel 6](#kap-milp) → [Kapitel 8](#kap-graphen) ([Graphen](#gloss:graphen){.glossar-link}, [VRP (Vehicle Routing Problem)](#gloss:vehicle-routing-problem-vrp){.glossar-link}) → Projekt **P3** (Liefertouren) oder **P4** (Lagernetzwerk).
*Wenn die Instanzen zu groß werden:* [Kapitel 9](#kap-metaheuristiken) (gute Lösung in fester Zeit) und [Kapitel 10](#kap-dekomposition) (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](#kap-einfuehrung) → [Kapitel 2](#kap-fundament) → [Kapitel 11](#kap-qp-nlp) ([QP](#gloss:quadratische-programmierung-qp){.glossar-link}, [KKT](#gloss:karush-kuhn-tucker-bedingungen-kkt){.glossar-link}) → [Kapitel 18](#kap-finanzdaten) (Daten, Shrinkage) → [Kapitel 19](#kap-markowitz) (Markowitz) → [Kapitel 20](#kap-cvar) (CVaR) → [Kapitel 21](#kap-handelsmaschine) (Backtest) → Projekt **P6** (Portfolio-Rebalancer) oder **P7** (Risikoreport). **Wichtig:** Überspringen Sie [Kapitel 18](#kap-finanzdaten) nicht. Wer direkt bei Markowitz einsteigt, optimiert Schätzrauschen und wundert sich über absurde Gewichte.
[Kapitel 1](#kap-einfuehrung) → [Kapitel 2](#kap-fundament) → [Kapitel 11](#kap-qp-nlp) ([QP (Quadratische Programmierung)](#gloss:quadratische-programmierung-qp){.glossar-link}, [KKT (Karush-Kuhn-Tucker-Bedingungen)](#gloss:karush-kuhn-tucker-bedingungen-kkt){.glossar-link}) → [Kapitel 18](#kap-finanzdaten) (Daten, Shrinkage) → [Kapitel 19](#kap-markowitz) (Markowitz) → [Kapitel 20](#kap-cvar) (CVaR) → [Kapitel 21](#kap-handelsmaschine) (Backtest) → Projekt **P6** (Portfolio-Rebalancer) oder **P7** (Risikoreport). **Wichtig:** Überspringen Sie [Kapitel 18](#kap-finanzdaten) nicht. Wer direkt bei Markowitz einsteigt, optimiert Schätzrauschen und wundert sich über absurde Gewichte.
### Pfad E — Ich habe morgen ein konkretes Problem (24 Stunden) {-}
@ -420,9 +420,9 @@ Alle Beispielprogramme dieses Buchs im Überblick, sortiert nach Kapitel — pra
| `Metaheuristik_vs_Exakt.py` | Der Umschlagpunkt, und die Schranke | [Kapitel 9](#kap-metaheuristiken) |
| `Large_Neighborhood_Search.py` | Zerstören und exakt reparieren | [Kapitel 9](#kap-metaheuristiken) |
| `Spaltengenerierung.py` | Muster statt Stücke, Master und Pricing | [Kapitel 10](#kap-dekomposition) |
| `QP_Grundlagen.py` | [Konvexität](#gloss:konvexitaet){.glossar-link}`\index{Konvexität}`{=latex}, [DCP](#gloss:dcp-disciplined-convex-programming){.glossar-link}-Check | [Kapitel 11](#kap-qp-nlp) |
| `QP_Grundlagen.py` | [Konvexität](#gloss:konvexitaet){.glossar-link}`\index{Konvexität}`{=latex}, [DCP (Disciplined Convex Programming)](#gloss:dcp-disciplined-convex-programming){.glossar-link}-Check | [Kapitel 11](#kap-qp-nlp) |
| `KKT_Nachweis.py` | KKT numerisch prüfen | [Kapitel 11](#kap-qp-nlp) |
| `Entropie_Maximierte_Allokation.py` | [NLP](#gloss:nichtlineare-programmierung-nlp){.glossar-link} mit Entropie | [Kapitel 11](#kap-qp-nlp) |
| `Entropie_Maximierte_Allokation.py` | [NLP (Nichtlineare Programmierung)](#gloss:nichtlineare-programmierung-nlp){.glossar-link} mit Entropie | [Kapitel 11](#kap-qp-nlp) |
| `Lokale_Optima_Multistart.py` | Lokale Optima, Multistart | [Kapitel 11](#kap-qp-nlp) |
| `Fluch_des_Durchschnitts.py` | Optimum ≠ Mittelwert | [Kapitel 12](#kap-unsicherheit) |
| `Monte_Carlo.py` | Monte-Carlo-Bewertung | [Kapitel 12](#kap-unsicherheit) |
@ -439,7 +439,7 @@ Alle Beispielprogramme dieses Buchs im Überblick, sortiert nach Kapitel — pra
| `Schaetzrauschen_Demo.py` | Error-Maximizer messen | [Kapitel 18](#kap-finanzdaten) |
| `Finanzdaten_Ledoit_Wolf.py` | Datenpipeline, Shrinkage | [Kapitel 18](#kap-finanzdaten) |
| `Kovarianz_Falle.py` | Singuläre Kovarianz, Error-Maximizer | [Kapitel 18](#kap-finanzdaten) |
| `Markowitz_CVXPY.py` | [GMV](#gloss:global-minimum-variance-portfolio-gmv){.glossar-link}, Max Sharpe, Frontier | [Kapitel 19](#kap-markowitz) |
| `Markowitz_CVXPY.py` | [GMV (Global Minimum Variance Portfolio)](#gloss:global-minimum-variance-portfolio-gmv){.glossar-link}, Max Sharpe, Frontier | [Kapitel 19](#kap-markowitz) |
| `Diversifikation_Demo.py` | Korrelation und Portfoliorisiko | [Kapitel 19](#kap-markowitz) |
| `Renditeschaetzung_Falle.py` | Schätzfehler in erwarteten Renditen | [Kapitel 19](#kap-markowitz) |
| `VaR_CVaR_Demo.py` | [Fat Tails](#gloss:fat-tails){.glossar-link}`\index{Fat Tails}`{=latex}, [Subadditivität](#gloss:subadditivitaet){.glossar-link}`\index{Subadditivität}`{=latex} | [Kapitel 20](#kap-cvar) |
@ -528,9 +528,9 @@ Dieses Kapitel ist zum Nachschlagen gedacht, nicht zum Durchlesen. Schlagen Sie
| Symbol | Bedeutung | Praktische Folge |
| --- | --- | --- |
| $\mathbb{R}$ | Reelle Zahlen (beliebig teilbar) | Variable darf 3,7 sein — **[LP](#gloss:lineare-programmierung-lp){.glossar-link}**, schnell lösbar |
| $\mathbb{R}$ | Reelle Zahlen (beliebig teilbar) | Variable darf 3,7 sein — **[LP (Lineare Programmierung)](#gloss:lineare-programmierung-lp){.glossar-link}**, schnell lösbar |
| $\mathbb{R}^n$ | $n$-Tupel reeller Zahlen | Der Raum, in dem $\mathbf{x}$ lebt |
| $\mathbb{Z}$ | Ganze Zahlen | Variable muss 3 oder 4 sein — **[MILP](#gloss:gemischt-ganzzahlige-optimierung-milp){.glossar-link}**, [NP-schwer](#gloss:np-schwer){.glossar-link}`\index{NP-schwer}`{=latex} |
| $\mathbb{Z}$ | Ganze Zahlen | Variable muss 3 oder 4 sein — **[MILP (Gemischt-ganzzahlige Optimierung)](#gloss:gemischt-ganzzahlige-optimierung-milp){.glossar-link}**, [NP-schwer](#gloss:np-schwer){.glossar-link}`\index{NP-schwer}`{=latex} |
| $\mathbb{N}_0$ | Natürliche Zahlen einschließlich 0 | Stückzahlen, nie negativ |
| $\{0, 1\}$ | Nur zwei Werte | Ja/Nein-Entscheidung |
| $\in$ | „ist Element von“ | $x \in \mathbb{Z}$: „$x$ ist ganzzahlig“ |
@ -578,7 +578,7 @@ Dieses Kapitel ist zum Nachschlagen gedacht, nicht zum Durchlesen. Schlagen Sie
| $r_{i,t}$ | **[Logarithmische Rendite](#gloss:logarithmische-rendite){.glossar-link}**`\index{Logarithmische Rendite}`{=latex} (stetige Rendite) | $\ln(P_t/P_{t-1})$ |
| $P_{i,t}$ | **Kurs** (bereinigter Schlusskurs) von Titel $i$ | in Währungseinheiten |
| $\lambda$ | Risikoaversion / Gewichtung des Risikoterms | Modellparameter, frei wählbar |
| $\alpha$ | Konfidenzniveau bei [VaR](#gloss:value-at-risk-var){.glossar-link}/[CVaR](#gloss:conditional-value-at-risk-cvar){.glossar-link} | $0{,}95$ = „schlechteste 5 % der Tage“ |
| $\alpha$ | Konfidenzniveau bei [VaR (Value at Risk)](#gloss:value-at-risk-var){.glossar-link}/[CVaR (Conditional Value at Risk)](#gloss:conditional-value-at-risk-cvar){.glossar-link} | $0{,}95$ = „schlechteste 5 % der Tage“ |
| $\gamma$ | Hilfsvariable, schätzt den VaR ([Kapitel 20](#kap-cvar)); Diskontfaktor ([Kapitel 13](#kap-dynamische-programmierung)) | kontextabhängig |
| $\eta$ | „eta“ — Marktimpact-Koeffizient | [Kapitel 13](#kap-dynamische-programmierung), Almgren-Chriss |
| $X_t$ | Verbleibender Aktienbestand zum Zeitpunkt $t$ | [Kapitel 13](#kap-dynamische-programmierung) |
@ -623,32 +623,32 @@ Diese Zeichen kommen erst in den Kapiteln vor, die über das klassische LP hinau
| **MILP** | Mixed-Integer Linear Program(ming) | Gemischt-ganzzahlige lineare Optimierung | [Kapitel 6](#kap-milp) |
| **MIP** | Mixed-Integer Program(ming) | Oberbegriff, meist synonym zu MILP | [Kapitel 6](#kap-milp) |
| **IP** | Integer Program(ming) | Rein ganzzahlige Optimierung | [Kapitel 6](#kap-milp) |
| **[QP](#gloss:quadratische-programmierung-qp){.glossar-link}** | Quadratic Program(ming) | Quadratische Optimierung | [Kapitel 11](#kap-qp-nlp) |
| **[QP (Quadratische Programmierung)](#gloss:quadratische-programmierung-qp){.glossar-link}** | Quadratic Program(ming) | Quadratische Optimierung | [Kapitel 11](#kap-qp-nlp) |
| **[MIQP](#gloss:miqp){.glossar-link}** | Mixed-Integer Quadratic Program(ming) | Ganzzahlig-quadratische Optimierung | [Kapitel 19](#kap-markowitz) |
| **[NLP](#gloss:nichtlineare-programmierung-nlp){.glossar-link}** | Nonlinear Program(ming) | Nichtlineare Optimierung | [Kapitel 11](#kap-qp-nlp) |
| **[NLP (Nichtlineare Programmierung)](#gloss:nichtlineare-programmierung-nlp){.glossar-link}** | Nonlinear Program(ming) | Nichtlineare Optimierung | [Kapitel 11](#kap-qp-nlp) |
| **[MINLP](#gloss:minlp){.glossar-link}**`\index{MINLP}`{=latex} | Mixed-Integer Nonlinear Program(ming) | Ganzzahlig-nichtlineare Optimierung | [Kapitel 3](#kap-oekosystem) |
| **[CP](#gloss:constraint-programming-cp){.glossar-link}** | Constraint Programming | Bedingungsprogrammierung | [Kapitel 7](#kap-cpsat) |
| **[SAT](#gloss:sat-boolean-satisfiability){.glossar-link}** | Boolean **Sat**isfiability Problem | Erfüllbarkeitsproblem der Aussagenlogik | [Kapitel 7](#kap-cpsat) |
| **[CP (Constraint Programming)](#gloss:constraint-programming-cp){.glossar-link}** | Constraint Programming | Bedingungsprogrammierung | [Kapitel 7](#kap-cpsat) |
| **[SAT (Boolean Satisfiability)](#gloss:sat-boolean-satisfiability){.glossar-link}** | Boolean **Sat**isfiability Problem | Erfüllbarkeitsproblem der Aussagenlogik | [Kapitel 7](#kap-cpsat) |
| **[CP-SAT](#gloss:cp-sat){.glossar-link}**`\index{CP-SAT}`{=latex} | Constraint Programming über SAT-Techniken | Solver-Name von Google [OR-Tools](#gloss:or-tools){.glossar-link}`\index{OR-Tools}`{=latex} | [Kapitel 7](#kap-cpsat) |
| **[CDCL](#gloss:cdcl){.glossar-link}**`\index{CDCL}`{=latex} | Conflict-Driven Clause Learning | konfliktgetriebenes Klausellernen | [Kapitel 7](#kap-cpsat) |
| **[DP](#gloss:dynamische-programmierung-dp){.glossar-link}** | Dynamic Programming | Dynamische Programmierung | [Kapitel 13](#kap-dynamische-programmierung) |
| **[DP (Dynamische Programmierung)](#gloss:dynamische-programmierung-dp){.glossar-link}** | Dynamic Programming | Dynamische Programmierung | [Kapitel 13](#kap-dynamische-programmierung) |
| **B&B** | Branch and Bound | Verzweigen und Beschränken | [Kapitel 6](#kap-milp) |
| **B&C** | Branch and Cut | Verzweigen mit Schnittebenen | [Kapitel 6](#kap-milp) |
| **[KKT](#gloss:karush-kuhn-tucker-bedingungen-kkt){.glossar-link}** | KarushKuhnTucker (Bedingungen) | Optimalitätsbedingungen bei Restriktionen | [Kapitel 11](#kap-qp-nlp) |
| **[KKT (Karush-Kuhn-Tucker-Bedingungen)](#gloss:karush-kuhn-tucker-bedingungen-kkt){.glossar-link}** | KarushKuhnTucker (Bedingungen) | Optimalitätsbedingungen bei Restriktionen | [Kapitel 11](#kap-qp-nlp) |
| **[SLSQP](#gloss:slsqp){.glossar-link}**`\index{SLSQP}`{=latex} | Sequential Least Squares Programming | sequentielle quadratische Optimierung | [Kapitel 11](#kap-qp-nlp) |
| **RMT** | Random Matrix Theory | [Zufallsmatrizentheorie](#gloss:zufallsmatrizentheorie){.glossar-link}`\index{Zufallsmatrizentheorie}`{=latex} | [Kapitel 18](#kap-finanzdaten) |
| **SA** | Simulated Annealing | Simulierte Abkühlung — [Metaheuristik](#gloss:metaheuristik){.glossar-link}`\index{Metaheuristik}`{=latex}, die Verschlechterungen mit fallender Wahrscheinlichkeit zulässt | [Kapitel 9](#kap-metaheuristiken) |
| **[LNS](#gloss:large-neighborhood-search-lns){.glossar-link}** | Large Neighborhood Search | Große Nachbarschaftssuche: Teil der Lösung verwerfen, Rest exakt neu bauen | [Kapitel 9](#kap-metaheuristiken) |
| **[LNS (Large Neighborhood Search)](#gloss:large-neighborhood-search-lns){.glossar-link}** | Large Neighborhood Search | Große Nachbarschaftssuche: Teil der Lösung verwerfen, Rest exakt neu bauen | [Kapitel 9](#kap-metaheuristiken) |
| **CG** | [Column Generation](#gloss:column-generation){.glossar-link}`\index{Column Generation}`{=latex} | Spaltengenerierung — Variablen erst erzeugen, wenn sie sich lohnen | [Kapitel 10](#kap-dekomposition) |
| **[IIS](#gloss:iis-irreducible-infeasible-subset){.glossar-link}** | Irreducible Infeasible Subset | Kleinste widersprüchliche Teilmenge von Bedingungen | [Anhang C](#anhang-fehlerdiagnose) |
| **[IIS (Irreducible Infeasible Subset)](#gloss:iis-irreducible-infeasible-subset){.glossar-link}** | Irreducible Infeasible Subset | Kleinste widersprüchliche Teilmenge von Bedingungen | [Anhang C](#anhang-fehlerdiagnose) |
| **[MSE](#gloss:mse){.glossar-link}** | Mean Squared Error | Mittlerer quadratischer Fehler — das Standardmaß für Prognosegüte | [Kapitel 15](#kap-prognose) |
### 2.2 Probleme mit Eigennamen
| Kürzel | Ausgeschrieben | Deutsch | Kapitel |
| --- | --- | --- | --- |
| **[TSP](#gloss:tsp-traveling-salesperson-problem){.glossar-link}** | Traveling Salesperson Problem | Problem des Handlungsreisenden | [Kapitel 8](#kap-graphen) |
| **[VRP](#gloss:vehicle-routing-problem-vrp){.glossar-link}** | Vehicle Routing Problem | Tourenplanungsproblem | [Kapitel 8](#kap-graphen) |
| **[TSP (Traveling Salesperson Problem)](#gloss:tsp-traveling-salesperson-problem){.glossar-link}** | Traveling Salesperson Problem | Problem des Handlungsreisenden | [Kapitel 8](#kap-graphen) |
| **[VRP (Vehicle Routing Problem)](#gloss:vehicle-routing-problem-vrp){.glossar-link}** | Vehicle Routing Problem | Tourenplanungsproblem | [Kapitel 8](#kap-graphen) |
| **CVRP** | **C**apacitated VRP | VRP mit Fahrzeugkapazitäten | [Kapitel 8](#kap-graphen) |
| **VRPTW** | VRP with **T**ime **W**indows | VRP mit Zeitfenstern | [Kapitel 8](#kap-graphen) |
| **[CVRPTW](#gloss:cvrptw){.glossar-link}**`\index{CVRPTW}`{=latex} | Capacitated VRP with Time Windows | mit Kapazitäten *und* Zeitfenstern | [Kapitel 8](#kap-graphen) |
@ -661,7 +661,7 @@ Diese Zeichen kommen erst in den Kapiteln vor, die über das klassische LP hinau
| Kürzel | Ausgeschrieben | Deutsch / Bedeutung | Kapitel |
| --- | --- | --- | --- |
| **MPT** | Modern Portfolio Theory | Moderne Portfoliotheorie (Markowitz) | [Kapitel 19](#kap-markowitz) |
| **[GMV](#gloss:global-minimum-variance-portfolio-gmv){.glossar-link}** | Global Minimum Variance (Portfolio) | Portfolio kleinstmöglicher Varianz | [Kapitel 19](#kap-markowitz) |
| **[GMV (Global Minimum Variance Portfolio)](#gloss:global-minimum-variance-portfolio-gmv){.glossar-link}** | Global Minimum Variance (Portfolio) | Portfolio kleinstmöglicher Varianz | [Kapitel 19](#kap-markowitz) |
| **MVO** | Mean-Variance Optimization | Erwartungswert-Varianz-Optimierung | [Kapitel 19](#kap-markowitz) |
| **SR** | [Sharpe Ratio](#gloss:sharpe-ratio){.glossar-link}`\index{Sharpe-Ratio}`{=latex} | Überrendite je Einheit Volatilität | [Kapitel 19](#kap-markowitz) |
| **VaR** | Value at Risk | Verlustschwelle bei gegebener Wahrscheinlichkeit | [Kapitel 20](#kap-cvar) |
@ -693,7 +693,7 @@ Diese Zeichen kommen erst in den Kapiteln vor, die über das klassische LP hinau
| **API** | Application Programming Interface | Programmierschnittstelle | — |
| **DSL** | Domain-Specific Language | fachspezifische Sprache (hier: Modellierungssprache) | — |
| **CSR** | Compressed Sparse Row | Speicherformat für dünnbesetzte Matrizen | — |
| **[GIL](#gloss:gil-global-interpreter-lock){.glossar-link}** | Global Interpreter Lock | Pythons Sperre, die echte Parallelität von Python-Code verhindert — Solverbibliotheken in C++ geben sie frei ([Kapitel 23](#kap-testing)) | — |
| **[GIL (Global Interpreter Lock)](#gloss:gil-global-interpreter-lock){.glossar-link}** | Global Interpreter Lock | Pythons Sperre, die echte Parallelität von Python-Code verhindert — Solverbibliotheken in C++ geben sie frei ([Kapitel 23](#kap-testing)) | — |
| **JSON** | JavaScript Object Notation | Textformat für strukturierte Daten; Austauschformat des Optimierungsdienstes | — |
| **RHS** | Right-Hand Side | rechte Seite einer (Un-)Gleichung, der Vektor $\mathbf{b}$ | — |
| **FFI** | Foreign Function Interface | Aufruf von C/C++-Code aus Python | — |
@ -1071,8 +1071,8 @@ Die **Stellschrauben**`\index{Entscheidungsvariable}`{=latex} des Modells: Werte
| Typ | Notation | Beispiel | Problemklasse |
| -------------- | ------------------ | -------------------------------------------------------- | ------------- |
| Kontinuierlich | $x \in \mathbb{R}$ | Investitionsbetrag in Euro, Fördermenge in Litern | [LP](#gloss:lineare-programmierung-lp){.glossar-link} — leicht |
| Ganzzahlig | $x \in \mathbb{Z}$ | Anzahl produzierter Maschinen, Anzahl Mitarbeiter | [MILP](#gloss:gemischt-ganzzahlige-optimierung-milp){.glossar-link} — schwer |
| Kontinuierlich | $x \in \mathbb{R}$ | Investitionsbetrag in Euro, Fördermenge in Litern | [LP (Lineare Programmierung)](#gloss:lineare-programmierung-lp){.glossar-link} — leicht |
| Ganzzahlig | $x \in \mathbb{Z}$ | Anzahl produzierter Maschinen, Anzahl Mitarbeiter | [MILP (Gemischt-ganzzahlige Optimierung)](#gloss:gemischt-ganzzahlige-optimierung-milp){.glossar-link} — schwer |
| Binär | $x \in \{0, 1\}$ | „Aktie $i$ kaufen: ja/nein“, „Schicht zuweisen: ja/nein“ | MILP — schwer |
> **Die Leitfrage:** *Worüber darf ich überhaupt entscheiden?* Alles, was feststeht, ist kein Variable, sondern Parameter. Die häufigste Ursache für unbrauchbare Modelle ist eine falsch gewählte Variablendefinition — nicht ein falscher Solver.
@ -1680,7 +1680,7 @@ Ergebnis geschrieben nach: produktionsmix_ergebnis.xlsx
**Aufgabe 1.4 ⭐⭐ — Modell lesen.** Gegeben sei das Modell $$\max\ 3x_1 + 5x_2 \quad \text{u. d. N.} \quad x_1 \le 4,\ \ 2x_2 \le 12,\ \ 3x_1 + 2x_2 \le 18,\ \ x_1, x_2 \ge 0.$$ (a) Benennen Sie die vier Bausteine. (b) Ist $(2, 6)$ zulässig? Ist $(4, 3)$ zulässig? Berechnen Sie jeweils $Z$. (c) Finden Sie durch Probieren die beste ganzzahlige Lösung.
**Aufgabe 1.5 ⭐⭐⭐ — Die Bäckerei programmieren.** Setzen Sie das Bäckerei-Problem der Handrechnung *Zerlegen Sie dieses Problem* mit [CP](#gloss:constraint-programming-cp){.glossar-link}-[SAT](#gloss:sat-boolean-satisfiability){.glossar-link} um. Geben Sie die optimale Produktionsmenge, den Deckungsbeitrag und die Auslastung von Mehl und Ofen aus. Prüfen Sie Ihr Ergebnis mit `assert`-Anweisungen.
**Aufgabe 1.5 ⭐⭐⭐ — Die Bäckerei programmieren.** Setzen Sie das Bäckerei-Problem der Handrechnung *Zerlegen Sie dieses Problem* mit [CP (Constraint Programming)](#gloss:constraint-programming-cp){.glossar-link}-[SAT (Boolean Satisfiability)](#gloss:sat-boolean-satisfiability){.glossar-link} um. Geben Sie die optimale Produktionsmenge, den Deckungsbeitrag und die Auslastung von Mehl und Ofen aus. Prüfen Sie Ihr Ergebnis mit `assert`-Anweisungen.
**Aufgabe 1.6 ⭐⭐⭐ — Sensitivität durch Ausprobieren.** Erweitern Sie `Bot_Allokation.py` so, dass es das Modell in einer Schleife für RAM-Kapazitäten von 54 bis 72 GB (in Schritten von 2) löst und eine Tabelle `RAM | x_A | x_B | Gewinn | Gewinnzuwachs pro zusätzlichem GB` ausgibt. (a) Ab welcher RAM-Menge steigt der Gewinn nicht mehr? Warum? (b) Was sagt Ihnen der „Gewinnzuwachs pro GB“ intuitiv? (Der Begriff dafür — *Schattenpreis* — folgt in [Kapitel 5](#kap-lp).)
@ -2131,11 +2131,11 @@ $$
| Problemtyp | Konvex? | Konsequenz |
| --- | --- | --- |
| Lineares Programm ([LP](#gloss:lineare-programmierung-lp){.glossar-link}) | **ja** | Globales Optimum, Sekunden bis Minuten selbst bei $10^6$ Variablen |
| Lineares Programm ([LP (Lineare Programmierung)](#gloss:lineare-programmierung-lp){.glossar-link}) | **ja** | Globales Optimum, Sekunden bis Minuten selbst bei $10^6$ Variablen |
| Quadratisches Programm mit $\mathbf{P} \succeq 0$ | **ja** | Globales Optimum, effizient ([Kapitel 11](#kap-qp-nlp), [Kapitel 19](#kap-markowitz)) |
| Ganzzahlige Variablen ([MILP](#gloss:gemischt-ganzzahlige-optimierung-milp){.glossar-link}) | **nein** | Der zulässige Bereich ist ein Punktgitter, keine zusammenhängende Menge — [NP-schwer](#gloss:np-schwer){.glossar-link}`\index{NP-schwer}`{=latex} ([Kapitel 6](#kap-milp)) |
| Ganzzahlige Variablen ([MILP (Gemischt-ganzzahlige Optimierung)](#gloss:gemischt-ganzzahlige-optimierung-milp){.glossar-link}) | **nein** | Der zulässige Bereich ist ein Punktgitter, keine zusammenhängende Menge — [NP-schwer](#gloss:np-schwer){.glossar-link}`\index{NP-schwer}`{=latex} ([Kapitel 6](#kap-milp)) |
| Quadratisches Programm mit indefinitem $\mathbf{P}$ | **nein** | Nur lokale Optima; eine ungültige [Kovarianzmatrix](#gloss:kovarianzmatrix){.glossar-link}`\index{Kovarianzmatrix}`{=latex} ist ein typischer Auslöser (siehe [Abschnitt 11.5](#sec:qp-nlp-nichtlineare-optimierung-mit-scipy-optimize-minimize)) |
| Allgemeines [NLP](#gloss:nichtlineare-programmierung-nlp){.glossar-link} mit beliebigen Funktionen | meist **nein** | `scipy.optimize` liefert nur ein lokales Optimum, abhängig vom Startpunkt |
| Allgemeines [NLP (Nichtlineare Programmierung)](#gloss:nichtlineare-programmierung-nlp){.glossar-link} mit beliebigen Funktionen | meist **nein** | `scipy.optimize` liefert nur ein lokales Optimum, abhängig vom Startpunkt |
### Konvexität sichtbar machen
@ -2923,7 +2923,7 @@ und runden Sie Solver-Ergebnisse NIE ohne Toleranzpruefung.
## 3.1 In 5 Minuten gelöst {#sec:oekosystem-schnellstart}
> **🚀 In 5 Minuten gelöst: Ein [LP](#gloss:lineare-programmierung-lp){.glossar-link} ohne jede Installation**
> **🚀 In 5 Minuten gelöst: Ein [LP (Lineare Programmierung)](#gloss:lineare-programmierung-lp){.glossar-link} ohne jede Installation**
>
> Ein Futtermittelhersteller mischt zwei Rohstoffe zu möglichst geringen Kosten. Jeder Kilogramm Mischung muss mindestens 20 g Protein und 5 g Fett enthalten.
>
@ -2987,7 +2987,7 @@ Nach diesem Kapitel können Sie …
Im modernen Operations Research schreibt man Optimierungsalgorithmen nicht selbst. Man nutzt eine **zweischichtige Architektur**`\index{Zweischichtige Architektur}`{=latex}:
1. **Modellierungsschicht (*Frontend*, DSL):** Python-Bibliotheken, mit denen Entscheidungsvariablen, Zielfunktion und Nebenbedingungen in mathematiknaher Syntax formuliert werden. Hier arbeiten Sie.
2. **Solver-Schicht (*Backend*, Engine):** Hochoptimierte C++- oder Fortran-Bibliotheken, die das Modell in Matrixstrukturen übersetzen und mit spezialisierten Algorithmen lösen ([Dual Simplex](#gloss:dual-simplex){.glossar-link}`\index{Dual Simplex}`{=latex}, Interior-Point`\index{Interior-Point-Verfahren}`{=latex}, [Branch-and-Cut](#gloss:branch-and-cut){.glossar-link}`\index{Branch-and-Cut}`{=latex}, [CDCL](#gloss:cdcl){.glossar-link}-[SAT](#gloss:sat-boolean-satisfiability){.glossar-link}-Suche`\index{CDCL}`{=latex}).
2. **Solver-Schicht (*Backend*, Engine):** Hochoptimierte C++- oder Fortran-Bibliotheken, die das Modell in Matrixstrukturen übersetzen und mit spezialisierten Algorithmen lösen ([Dual Simplex](#gloss:dual-simplex){.glossar-link}`\index{Dual Simplex}`{=latex}, Interior-Point`\index{Interior-Point-Verfahren}`{=latex}, [Branch-and-Cut](#gloss:branch-and-cut){.glossar-link}`\index{Branch-and-Cut}`{=latex}, [CDCL](#gloss:cdcl){.glossar-link}-[SAT (Boolean Satisfiability)](#gloss:sat-boolean-satisfiability){.glossar-link}-Suche`\index{CDCL}`{=latex}).
![Abb. 3.1: Modellierungsschicht und Solver-Engines](bilder_04/kap03_solver_architektur.svg)
@ -3002,9 +3002,9 @@ Im modernen Operations Research schreibt man Optimierungsalgorithmen nicht selbs
| Bibliothek | Stärken & Problemklassen | Wann einsetzen? | Typische Backends |
| --- | --- | --- | --- |
| `scipy.optimize` | Standard-LPs, kontinuierliche nichtlineare Optimierung, Wurzelsuche | Für elementare LPs und schnelle Prototypen ohne zusätzliche schwere Abhängigkeiten | HiGHS (`highs-ds`, `highs-ipm`) |
| `ortools` (Google) | Diskrete Planung, Schichten, Vertretungspläne, Routing ([VRP](#gloss:vehicle-routing-problem-vrp){.glossar-link}/[TSP](#gloss:tsp-traveling-salesperson-problem){.glossar-link}), kombinatorische Logik | Wenn diskrete Ja/Nein-Entscheidungen, Zeitfenster und Wenn-Dann-Regeln dominieren | [CP-SAT](#gloss:cp-sat){.glossar-link}`\index{CP-SAT}`{=latex}, [GLOP](#gloss:glop){.glossar-link}, Routing Engine |
| `cvxpy` | Konvexe Optimierung, quadratische Programme, Risikomodelle, Portfolios | **Erste Wahl für Finanzoptimierung**, Markowitz, [CVaR](#gloss:conditional-value-at-risk-cvar){.glossar-link}, $L_1$-[Transaktionskosten](#gloss:transaktionskosten){.glossar-link}`\index{Transaktionskosten}`{=latex} | Clarabel, OSQP, ECOS, SCS, HiGHS |
| `highspy` | Direkte Solver-Steuerung für LP/[MILP](#gloss:gemischt-ganzzahlige-optimierung-milp){.glossar-link}, maximale Kontrolle | Wenn Sie Modelle wiederholt und schnell aufbauen oder Solver-Details steuern müssen | HiGHS |
| `ortools` (Google) | Diskrete Planung, Schichten, Vertretungspläne, Routing ([VRP (Vehicle Routing Problem)](#gloss:vehicle-routing-problem-vrp){.glossar-link}/[TSP (Traveling Salesperson Problem)](#gloss:tsp-traveling-salesperson-problem){.glossar-link}), kombinatorische Logik | Wenn diskrete Ja/Nein-Entscheidungen, Zeitfenster und Wenn-Dann-Regeln dominieren | [CP-SAT](#gloss:cp-sat){.glossar-link}`\index{CP-SAT}`{=latex}, [GLOP](#gloss:glop){.glossar-link}, Routing Engine |
| `cvxpy` | Konvexe Optimierung, quadratische Programme, Risikomodelle, Portfolios | **Erste Wahl für Finanzoptimierung**, Markowitz, [CVaR (Conditional Value at Risk)](#gloss:conditional-value-at-risk-cvar){.glossar-link}, $L_1$-[Transaktionskosten](#gloss:transaktionskosten){.glossar-link}`\index{Transaktionskosten}`{=latex} | Clarabel, OSQP, ECOS, SCS, HiGHS |
| `highspy` | Direkte Solver-Steuerung für LP/[MILP (Gemischt-ganzzahlige Optimierung)](#gloss:gemischt-ganzzahlige-optimierung-milp){.glossar-link}, maximale Kontrolle | Wenn Sie Modelle wiederholt und schnell aufbauen oder Solver-Details steuern müssen | HiGHS |
| `Pyomo` | Universelle Modellierungssprache (LP, MILP, [MINLP](#gloss:minlp){.glossar-link}`\index{MINLP}`{=latex}) | Industrielle Großmodelle mit strikter Trennung von Daten und Modell | HiGHS, Gurobi, CPLEX, [SCIP](#gloss:scip){.glossar-link}`\index{SCIP}`{=latex}, IPOPT |
| `Linopy` | LP/MILP über beschriftete Arrays (`xarray`) | Modelle mit zehntausenden gleichartigen Nebenbedingungen (Energie, Netze, Zeitreihen) | HiGHS, GLPK, CBC, Gurobi |
@ -3012,7 +3012,7 @@ Im modernen Operations Research schreibt man Optimierungsalgorithmen nicht selbs
Statt die Tabelle auswendig zu lernen, beantworten Sie drei Fragen:
> **Frage 1: Gibt es Ja/Nein-Entscheidungen oder Reihenfolgen?****Ja:** [OR-Tools](#gloss:or-tools){.glossar-link}`\index{OR-Tools}`{=latex} ([CP](#gloss:constraint-programming-cp){.glossar-link}-SAT) bei Zuweisung/[Scheduling](#gloss:scheduling){.glossar-link}, oder MILP über HiGHS bei ökonomischen Fixkostenmodellen. → **Nein:** weiter zu Frage 2.
> **Frage 1: Gibt es Ja/Nein-Entscheidungen oder Reihenfolgen?****Ja:** [OR-Tools](#gloss:or-tools){.glossar-link}`\index{OR-Tools}`{=latex} ([CP (Constraint Programming)](#gloss:constraint-programming-cp){.glossar-link}-SAT) bei Zuweisung/[Scheduling](#gloss:scheduling){.glossar-link}, oder MILP über HiGHS bei ökonomischen Fixkostenmodellen. → **Nein:** weiter zu Frage 2.
>
> **Frage 2: Ist die Zielfunktion linear?****Ja:** `scipy.optimize.linprog` (klein) oder `highspy` (groß, wiederholt). → **Nein, aber konvex** (Quadrate, Normen, `log`, `exp` in konvexer Kombination): **CVXPY**. → **Nein und nicht konvex:** `scipy.optimize.minimize` — im Bewusstsein, dass nur ein lokales Optimum herauskommt.
>
@ -3170,7 +3170,7 @@ Tragfähig ist stattdessen: **jeder Solver eine gewöhnliche Funktion`\index{Kon
> **⚠️ `max_tasks_per_child=1` ist nicht optional** Ein Pool ohne diese Angabe ist der **Normalfall** — er soll seine Arbeiter ja wiederverwenden. Wer die Isolation über einen Pool herstellt und das vergisst, hat einen Prozesswechsel programmiert, aber keine Isolation gewonnen: Die zweite Aufgabe landet im selben Interpreter wie die erste. Der Absturz kommt dann nicht beim ersten Solver, sondern beim zweiten — und sieht aus wie ein Problem des zweiten.
Denselben Aufbau verwenden `Solverwechsel_CPSAT_HiGHS.py` ([Kapitel 22](#kap-praxisfallen)) und `Benchmark_Skalierung.py` ([Kapitel 23](#kap-testing)). Dort wandern zusätzlich **Datenobjekte** über die Prozessgrenze statt Zeichenketten — möglich, weil Domänenmodell und Lösungs-[DTO](#gloss:dto-data-transfer-object){.glossar-link} keinen Solver kennen ([Abschnitt 22.6](#sec:praxisfallen-or-kern)).
Denselben Aufbau verwenden `Solverwechsel_CPSAT_HiGHS.py` ([Kapitel 22](#kap-praxisfallen)) und `Benchmark_Skalierung.py` ([Kapitel 23](#kap-testing)). Dort wandern zusätzlich **Datenobjekte** über die Prozessgrenze statt Zeichenketten — möglich, weil Domänenmodell und Lösungs-[DTO (Data Transfer Object)](#gloss:dto-data-transfer-object){.glossar-link} keinen Solver kennen ([Abschnitt 22.6](#sec:praxisfallen-or-kern)).
```python
#!/usr/bin/env python3
@ -3389,7 +3389,7 @@ Bei kleinen Modellen wirkt das umständlich. Bei realen Modellen mit 100 000 Var
| Fahrzeugtouren | **OR-Tools Routing** | Fertige Metaheuristiken, jahrzehntelang optimiert |
| MILP mit Fixkosten, Kardinalität | `highspy` oder CP-SAT | Branch-and-Cut auf ökonomischer Struktur |
| 50 000+ Variablen, wiederholte Läufe | `highspy` oder Pyomo | Modellaufbau wird sonst zum Engpass |
| Nichtkonvexes [NLP](#gloss:nichtlineare-programmierung-nlp){.glossar-link} | `scipy.optimize.minimize` | Bewusst mit mehreren Startpunkten arbeiten |
| Nichtkonvexes [NLP (Nichtlineare Programmierung)](#gloss:nichtlineare-programmierung-nlp){.glossar-link} | `scipy.optimize.minimize` | Bewusst mit mehreren Startpunkten arbeiten |
> **🎯 Merksatz** Wählen Sie den Solver nach der **Struktur des Modells**, nicht nach Gewohnheit. Ein Zuweisungsproblem in CVXPY zu quälen oder ein Portfolio mit CP-SAT nachzubauen kostet Laufzeit und Nerven — und meist auch Lösungsqualität.
@ -4655,8 +4655,8 @@ Dieselbe Barriere gibt es rückwärts. Diese Sätze haben sich bewährt, wenn ei
| bindende Bedingung mit Dualwert 0 | „Die Regel berührt den Plan, kostet uns aber nichts — dort zu verhandeln bringt nichts." |
| `INFEASIBLE` | „Ihre Regeln widersprechen sich." **Nicht:** „Der Computer schafft es nicht." |
| Optimalitätslücke von 2 % | „Besser als das hier geht es höchstens um 2 % — und die liegen unter unserer Datenungenauigkeit." |
| [CVaR](#gloss:conditional-value-at-risk-cvar){.glossar-link} | „Wenn es schiefgeht, verlieren wir im Mittel so viel." (Der [VaR](#gloss:value-at-risk-var){.glossar-link} sagt nur, **ob** es schiefgeht.) |
| [EVPI](#gloss:evpi-expected-value-of-perfect-information){.glossar-link} | „Selbst eine perfekte Prognose wäre uns höchstens so viel wert." |
| [CVaR (Conditional Value at Risk)](#gloss:conditional-value-at-risk-cvar){.glossar-link} | „Wenn es schiefgeht, verlieren wir im Mittel so viel." (Der [VaR (Value at Risk)](#gloss:value-at-risk-var){.glossar-link} sagt nur, **ob** es schiefgeht.) |
| [EVPI (Expected Value of Perfect Information)](#gloss:evpi-expected-value-of-perfect-information){.glossar-link} | „Selbst eine perfekte Prognose wäre uns höchstens so viel wert." |
| [Relaxation](#gloss:relaxation){.glossar-link}`\index{Relaxation}`{=latex} | „Wir haben die Regel probeweise gelockert, um zu sehen, was sie kostet." |
| Chance Constraint | „Der Plan hält in 95 von 100 Fällen — und der nächste Prozentpunkt kostet …" |
@ -4769,7 +4769,7 @@ Vier Kapitel, vier Werkzeugkästen. Welcher zu Ihrem Problem passt, entscheiden
![Entscheidungsdiagramm: Welches Werkzeug passt zu meinem Problem? (Teil II)](bilder_04/teil2_solverwahl.svg)
> **🎯 Merksatz zum Diagramm** Die erste Frage ist die wichtigste — und sie lautet **nicht** „welcher [Solver](#gloss:solver){.glossar-link} ist der schnellste?“, sondern „welche **Struktur** hat mein Problem?“. Ein [Zuordnungsproblem](#gloss:zuordnungsproblem){.glossar-link}`\index{Zuordnungsproblem (1:1)}`{=latex} braucht keinen [MILP](#gloss:gemischt-ganzzahlige-optimierung-milp){.glossar-link}-Solver, sondern eine Zeile `linear_sum_assignment`. Ein Dienstplan gehört nicht in ein [LP](#gloss:lineare-programmierung-lp){.glossar-link}, sondern zu [CP-SAT](#gloss:cp-sat){.glossar-link}`\index{CP-SAT}`{=latex}. Wer die Struktur erkennt, hat die halbe Laufzeit gespart, bevor die erste Zeile Code geschrieben ist.
> **🎯 Merksatz zum Diagramm** Die erste Frage ist die wichtigste — und sie lautet **nicht** „welcher [Solver](#gloss:solver){.glossar-link} ist der schnellste?“, sondern „welche **Struktur** hat mein Problem?“. Ein [Zuordnungsproblem](#gloss:zuordnungsproblem){.glossar-link}`\index{Zuordnungsproblem (1:1)}`{=latex} braucht keinen [MILP (Gemischt-ganzzahlige Optimierung)](#gloss:gemischt-ganzzahlige-optimierung-milp){.glossar-link}-Solver, sondern eine Zeile `linear_sum_assignment`. Ein Dienstplan gehört nicht in ein [LP (Lineare Programmierung)](#gloss:lineare-programmierung-lp){.glossar-link}, sondern zu [CP-SAT](#gloss:cp-sat){.glossar-link}`\index{CP-SAT}`{=latex}. Wer die Struktur erkennt, hat die halbe Laufzeit gespart, bevor die erste Zeile Code geschrieben ist.
Fällt Ihr Problem durch das Diagramm hindurch — nichtlineare [Zielfunktion](#gloss:zielfunktion){.glossar-link}`\index{Zielfunktion}`{=latex}, unsichere Daten, Entscheidungen über mehrere Zeitstufen —, dann ist [Teil III](#teil-nichtlinear) der richtige Ort. Dort steht ein zweites Diagramm für genau diese Fälle.
@ -5615,7 +5615,7 @@ Solver rechnen mit endlicher Genauigkeit und brechen ab, sobald ihre eigene Tole
| Toleranz | Was sie steuert | Typischer Standardwert |
| --- | --- | --- |
| **Primale Zulässigkeit** | Wie weit darf $\mathbf{A}\mathbf{x}$ die Schranke $\mathbf{b}$ überschreiten? | $10^{-7}$ (HiGHS), $10^{-6}$ ([CP](#gloss:constraint-programming-cp){.glossar-link}-[SAT](#gloss:sat-boolean-satisfiability){.glossar-link}) |
| **Primale Zulässigkeit** | Wie weit darf $\mathbf{A}\mathbf{x}$ die Schranke $\mathbf{b}$ überschreiten? | $10^{-7}$ (HiGHS), $10^{-6}$ ([CP (Constraint Programming)](#gloss:constraint-programming-cp){.glossar-link}-[SAT (Boolean Satisfiability)](#gloss:sat-boolean-satisfiability){.glossar-link}) |
| **Duale Zulässigkeit** (Optimalität) | Wie weit dürfen die reduzierten Kosten das falsche Vorzeichen haben? | $10^{-7}$ |
| **Ganzzahligkeit** | Wie weit darf eine Ganzzahlvariable von der nächsten ganzen Zahl abweichen? | $10^{-6}$ ([Kapitel 6](#kap-milp)) |
@ -5990,9 +5990,9 @@ brauchbare Aussage. Ein erfundener Einzelwert ist es nicht.
>
> **Worum geht es?** Um Entscheidungen, die nicht teilbar sind: ganze Maschinen, Ja/Nein, „höchstens fünf davon“. Wir zeigen mit einem konkreten Gegenbeispiel, warum Runden **falsch** ist, und lernen die Modellierungstricks, mit denen sich logische Regeln in lineare Ungleichungen übersetzen lassen.
>
> **Voraussetzungen:** [Kapitel 5](#kap-lp) ([LP](#gloss:lineare-programmierung-lp){.glossar-link}, [Relaxation](#gloss:relaxation){.glossar-link}`\index{Relaxation}`{=latex}, Schranken).
> **Voraussetzungen:** [Kapitel 5](#kap-lp) ([LP (Lineare Programmierung)](#gloss:lineare-programmierung-lp){.glossar-link}, [Relaxation](#gloss:relaxation){.glossar-link}`\index{Relaxation}`{=latex}, Schranken).
>
> **Danach können Sie:** Fixkosten, Entweder-Oder, Wenn-Dann und Kardinalitätsgrenzen modellieren, ein [MILP](#gloss:gemischt-ganzzahlige-optimierung-milp){.glossar-link} mit [CP-SAT](#gloss:cp-sat){.glossar-link}`\index{CP-SAT}`{=latex} oder [HiGHS](#gloss:highs){.glossar-link} lösen, den [MIP-Gap](#gloss:mip-gap){.glossar-link}`\index{MIP-Gap}`{=latex} als Zusage an den Auftraggeber lesen — und ein Ergebnis erkennen, das nur deshalb gut aussieht, weil das Big-M zu groß gewählt war.
> **Danach können Sie:** Fixkosten, Entweder-Oder, Wenn-Dann und Kardinalitätsgrenzen modellieren, ein [MILP (Gemischt-ganzzahlige Optimierung)](#gloss:gemischt-ganzzahlige-optimierung-milp){.glossar-link} mit [CP-SAT](#gloss:cp-sat){.glossar-link}`\index{CP-SAT}`{=latex} oder [HiGHS](#gloss:highs){.glossar-link} lösen, den [MIP-Gap](#gloss:mip-gap){.glossar-link}`\index{MIP-Gap}`{=latex} als Zusage an den Auftraggeber lesen — und ein Ergebnis erkennen, das nur deshalb gut aussieht, weil das Big-M zu groß gewählt war.
>
> **Zeitbedarf:** ca. 6,5 Stunden.
>
@ -7258,7 +7258,7 @@ Hier wirkt der Hinweis: Faktor 2,2 bzw. 1,4. Beachten Sie aber, dass der Faktor
> * **`if status == OPTIMAL: ... else: return None`.** Wirft eine Lösung weg, die 9 % vom Optimum entfernt und damit vollkommen brauchbar ist. Werten Sie den Gap aus, nicht nur den Status.
> * **Zeitlimit ohne Gap-Auswertung.** Ein Limit erzwingt ein Ende, sagt aber nichts über die Qualität. Ohne den Gap wissen Sie nicht, ob Sie 0,1 % oder 60 % danebenliegen.
> * **Warm-Start als Selbstverständlichkeit.** Messen Sie ihn — auf Ihrer Instanzklasse, gegen den kalten Lauf. In der Hälfte der Fälle bringt er nichts.
> * **Einen Hinweis für eine unzulässige Lösung geben.** [CP](#gloss:constraint-programming-cp){.glossar-link}-[SAT](#gloss:sat-boolean-satisfiability){.glossar-link} und HiGHS verwerfen ihn dann stillschweigend. Prüfen Sie Ihre Startlösung vorher auf Zulässigkeit — sonst messen Sie einen Effekt, den es gar nicht gibt.
> * **Einen Hinweis für eine unzulässige Lösung geben.** [CP (Constraint Programming)](#gloss:constraint-programming-cp){.glossar-link}-[SAT (Boolean Satisfiability)](#gloss:sat-boolean-satisfiability){.glossar-link} und HiGHS verwerfen ihn dann stillschweigend. Prüfen Sie Ihre Startlösung vorher auf Zulässigkeit — sonst messen Sie einen Effekt, den es gar nicht gibt.
> **🎯 Merksatz** Ein Warm-Start kann das Ergebnis nie verfälschen — im schlimmsten Fall kostet er Zeit. Genau deshalb darf man ihn ausprobieren. Aber man muss ihn auch **messen**, statt an ihn zu glauben.
@ -7668,7 +7668,7 @@ funktioniert immer.
> Fr -> Abel
> ```
**Elf Zeilen Modell, und der Plan steht.** Beachten Sie besonders die Zeile `m.AddExactlyOne(...)`. Sie sagt wörtlich, was gemeint ist: *genau eine* Person je Tag. In [MILP](#gloss:gemischt-ganzzahlige-optimierung-milp){.glossar-link} hätte man dafür eine Gleichung $\sum_p x_{p,d} = 1$ aufgestellt — machbar, aber schon eine Übersetzungsleistung. Bei Regeln wie „diese beiden Dienste nicht direkt hintereinander“ oder „höchstens eine Nachtschicht pro Woche“ wächst dieser Übersetzungsaufwand rasch; in [CP](#gloss:constraint-programming-cp){.glossar-link}-[SAT](#gloss:sat-boolean-satisfiability){.glossar-link} bleibt er eine Zeile.
**Elf Zeilen Modell, und der Plan steht.** Beachten Sie besonders die Zeile `m.AddExactlyOne(...)`. Sie sagt wörtlich, was gemeint ist: *genau eine* Person je Tag. In [MILP (Gemischt-ganzzahlige Optimierung)](#gloss:gemischt-ganzzahlige-optimierung-milp){.glossar-link} hätte man dafür eine Gleichung $\sum_p x_{p,d} = 1$ aufgestellt — machbar, aber schon eine Übersetzungsleistung. Bei Regeln wie „diese beiden Dienste nicht direkt hintereinander“ oder „höchstens eine Nachtschicht pro Woche“ wächst dieser Übersetzungsaufwand rasch; in [CP (Constraint Programming)](#gloss:constraint-programming-cp){.glossar-link}-[SAT (Boolean Satisfiability)](#gloss:sat-boolean-satisfiability){.glossar-link} bleibt er eine Zeile.
**Und jetzt sehen Sie sich das Ergebnis genau an.** *Cor bekommt keinen einzigen Dienst.* Dane arbeitet Montag **und** Dienstag hintereinander. Ist das ein Fehler?
@ -7695,7 +7695,7 @@ Nach diesem Kapitel können Sie …
## 7.3 Ein anderes Denkmodell {#sec:cpsat-ein-anderes-denkmodell}
Während [LP](#gloss:lineare-programmierung-lp){.glossar-link} und MILP auf algebraischen Gleichungen und Simplex-Matrizen beruhen, kommt **Constraint Programming (CP)**`\index{Constraint Programming (CP)}`{=latex} aus der künstlichen Intelligenz:
Während [LP (Lineare Programmierung)](#gloss:lineare-programmierung-lp){.glossar-link} und MILP auf algebraischen Gleichungen und Simplex-Matrizen beruhen, kommt **Constraint Programming (CP)**`\index{Constraint Programming (CP)}`{=latex} aus der künstlichen Intelligenz:
| | MILP | Constraint Programming |
| --- | --- | --- |
@ -7823,7 +7823,7 @@ CP-SAT stellt mächtige Makros`\index{Globale Constraints}`{=latex} bereit, die
| `NewIntervalVar(start, size, end, name)` | Zeitintervall mit Start, Dauer, Ende | Aufträge, Operationen, Belegungen |
| `AddNoOverlap(intervals)` | Intervalle überschneiden sich **nicht** | Eine Maschine, ein Raum, eine Person |
| `AddCumulative(intervals, bedarfe, kapazitaet)` | Zu **keinem Zeitpunkt** übersteigt der Parallelverbrauch die Kapazität | Personalstärke, Stromlast, Kranstunden |
| `AddCircuit(arcs)` | Die gewählten Kanten bilden **einen** Rundweg | [TSP](#gloss:tsp-traveling-salesperson-problem){.glossar-link}-artige Reihenfolgeprobleme |
| `AddCircuit(arcs)` | Die gewählten Kanten bilden **einen** Rundweg | [TSP (Traveling Salesperson Problem)](#gloss:tsp-traveling-salesperson-problem){.glossar-link}-artige Reihenfolgeprobleme |
| `.OnlyEnforceIf(bool)` | Bedingung gilt **nur wenn** | Reifizierung: Regel an-/abschaltbar machen |
> **🔤 Formel-Übersetzer: was ein globales Constraint zusichert**
@ -9314,7 +9314,7 @@ Nach diesem Kapitel können Sie …
2. … den **Flusserhaltungssatz**`\index{Flusserhaltung}`{=latex} aufstellen und seine Bedeutung erklären.
3. … begründen, warum Zuordnungsprobleme **ohne** Ganzzahligkeitsbedingung ganzzahlig lösbar sind (totale Unimodularität`\index{Totale Unimodularität}`{=latex}).
4. … ein Vehicle Routing Problem mit Kapazitäten und Zeitfenstern mit [OR-Tools](#gloss:or-tools){.glossar-link}`\index{OR-Tools}`{=latex} lösen.
5. … einschätzen, wann ein spezialisierter Algorithmus einem allgemeinen [MILP](#gloss:gemischt-ganzzahlige-optimierung-milp){.glossar-link} überlegen ist.
5. … einschätzen, wann ein spezialisierter Algorithmus einem allgemeinen [MILP (Gemischt-ganzzahlige Optimierung)](#gloss:gemischt-ganzzahlige-optimierung-milp){.glossar-link} überlegen ist.
6. … begründen, warum eine gierige Zuordnung systematisch schlechter ist als eine gemeinsame Optimierung.
7. … einen Tourenplan gegen die Wirklichkeit prüfen — unabhängig von den Bausteinen, aus denen das Modell gebaut wurde.
@ -9513,7 +9513,7 @@ $$
> **Satz.** Die Extrempunkte der Menge`\index{Konvexität!Menge}`{=latex} aller doppelt-stochastischen Matrizen (alle Zeilensummen $= 1$, alle Spaltensummen $= 1$, $x_{ij} \ge 0$) sind **genau** die Permutationsmatrizen (alle $x_{ij} \in \{0,1\}$).
**Warum das praktisch enorm wichtig ist:**`\index{Satz von Birkhoff und von Neumann}`{=latex} Nach dem Fundamentalsatz aus [Kapitel 2](#kap-fundament) liegt das [LP](#gloss:lineare-programmierung-lp){.glossar-link}-Optimum in einer Ecke. Die Ecken sind hier laut Satz automatisch 0/1-wertig. Also gilt:
**Warum das praktisch enorm wichtig ist:**`\index{Satz von Birkhoff und von Neumann}`{=latex} Nach dem Fundamentalsatz aus [Kapitel 2](#kap-fundament) liegt das [LP (Lineare Programmierung)](#gloss:lineare-programmierung-lp){.glossar-link}-Optimum in einer Ecke. Die Ecken sind hier laut Satz automatisch 0/1-wertig. Also gilt:
> **🎯 Merksatz** Beim Zuordnungsproblem müssen Sie die Ganzzahligkeit **nicht** fordern — ein gewöhnlicher LP-Solver liefert von selbst eine 0/1-Lösung. Sie sparen sich damit die NP-Schwere von Branch-and-Bound vollständig.
@ -9651,7 +9651,7 @@ if __name__ == "__main__":
## 8.5 Das Vehicle Routing Problem mit Zeitfenstern {#sec:graphen-das-vehicle-routing-problem-mit-zeitfenstern}
Das **Traveling Salesperson Problem ([TSP](#gloss:tsp-traveling-salesperson-problem){.glossar-link})**`\index{TSP (Traveling Salesperson Problem)}`{=latex}, deutsch *Problem des Handlungsreisenden*, fragt nach der kürzesten Rundreise durch $N$ Städte. Das **Capacitated Vehicle Routing Problem with Time Windows ([CVRPTW](#gloss:cvrptw){.glossar-link})**`\index{CVRPTW}`{=latex} erweitert es auf eine **Flotte** mit Kapazitätsgrenzen und Kundenzeitfenstern $[e_i, l_i]$.
Das **Traveling Salesperson Problem ([TSP (Traveling Salesperson Problem)](#gloss:tsp-traveling-salesperson-problem){.glossar-link})**`\index{TSP (Traveling Salesperson Problem)}`{=latex}, deutsch *Problem des Handlungsreisenden*, fragt nach der kürzesten Rundreise durch $N$ Städte. Das **Capacitated Vehicle Routing Problem with Time Windows ([CVRPTW](#gloss:cvrptw){.glossar-link})**`\index{CVRPTW}`{=latex} erweitert es auf eine **Flotte** mit Kapazitätsgrenzen und Kundenzeitfenstern $[e_i, l_i]$.
![Abb. 8.2: Die Lösung der Instanz aus `VRP_Flotten_Routing.py`: 16 Kunden, vier Fahrzeuge, 619 km.
**Beachten Sie, dass sich die Touren kreuzen.** Bei einem reinen Tourenproblem wäre das ein sicheres Zeichen für eine verbesserbare Lösung — hier ist es keines: Die Zeitfenster erzwingen die Reihenfolge, und wer die Kreuzungen auflöst, kommt zu spät. Erzeugt von `bilder_04/erzeuge_vrp_touren.py`.](bilder_04/kap_graphen_vrp_touren.svg)
@ -9851,7 +9851,7 @@ if __name__ == "__main__":
loese_cvrptw()
```
> **⚠️ Typische Fehler beim [VRP](#gloss:vehicle-routing-problem-vrp){.glossar-link}**
> **⚠️ Typische Fehler beim [VRP (Vehicle Routing Problem)](#gloss:vehicle-routing-problem-vrp){.glossar-link}**
>
> * **`Min(CumulVar)` mit „Ankunftszeit“ verwechseln.** Der Solver liefert ein *Intervall* möglicher Zeiten. `Min()` ist die früheste, `Max()` die späteste zulässige Zeit — die tatsächliche Fahrt kann irgendwo dazwischen starten.
> * **Servicezeit im Depot mitzählen.** Beim Start am Depot fällt keine Servicezeit an, sonst verschiebt sich der ganze Plan.
@ -10165,7 +10165,7 @@ plausibel aussieht.
* **Totale Unimodularität ist zerbrechlich.** Eine einzige zusätzliche Bedingung, die nicht ins Schema passt — Kardinalität, Fixkosten, Mindestmenge —, zerstört sie. Prüfen Sie das, bevor Sie sich auf die Struktur verlassen.
* **Der beste erste Zug ist selten Teil der besten Gesamtlösung.** Gierige Regeln kosten schon bei vier Zuordnungen 8 %.
**Ausblick.** [Teil III](#teil-nichtlinear) verlässt die lineare Welt. [Kapitel 11](#kap-qp-nlp) führt quadratische Zielfunktionen und die [KKT](#gloss:karush-kuhn-tucker-bedingungen-kkt){.glossar-link}-Bedingungen ein — das mathematische Fundament der Portfoliooptimierung.
**Ausblick.** [Teil III](#teil-nichtlinear) verlässt die lineare Welt. [Kapitel 11](#kap-qp-nlp) führt quadratische Zielfunktionen und die [KKT (Karush-Kuhn-Tucker-Bedingungen)](#gloss:karush-kuhn-tucker-bedingungen-kkt){.glossar-link}-Bedingungen ein — das mathematische Fundament der Portfoliooptimierung.
---
@ -11039,7 +11039,7 @@ Drei Größen, drei völlig verschiedene Empfehlungen:
| Aufträge | Empfehlung |
| ---: | --- |
| 60 | **Exakt.** [CP](#gloss:constraint-programming-cp){.glossar-link}-[SAT](#gloss:sat-boolean-satisfiability){.glossar-link} beweist das Optimum in 2 Sekunden. Die Metaheuristik liegt 3,8 % daneben — und wüsste es nicht. |
| 60 | **Exakt.** [CP (Constraint Programming)](#gloss:constraint-programming-cp){.glossar-link}-[SAT (Boolean Satisfiability)](#gloss:sat-boolean-satisfiability){.glossar-link} beweist das Optimum in 2 Sekunden. Die Metaheuristik liegt 3,8 % daneben — und wüsste es nicht. |
| 200 | **Exakt.** Kein Beweis mehr, aber der Gap liegt unter 1 %, und der Wert ist rund 11 % besser als der heuristische. |
| 500 | **Heuristisch.** CP-SAT liefert eine Lösung, die 5,2 % **schlechter** ist als die Faustregel eines Meisters. |
@ -11059,7 +11059,7 @@ Das ist der Unterschied zwischen *besser als vorher* und *gut*. Eine Metaheurist
Die Tabelle oben endet mit einem Widerspruch. Bei 500 Aufträgen scheitert der exakte Solver an der **Größe**; die Metaheuristik scheitert an der **Kleinheit ihrer Züge** — sie verschiebt jeweils einen einzigen Auftrag und kann eine ganze Passage nicht auf einmal umbauen.
**Large Neighborhood Search**`\index{Large Neighborhood Search}`{=latex} ([LNS](#gloss:large-neighborhood-search-lns){.glossar-link}) setzt beide ein, jeden für das, was er kann:
**Large Neighborhood Search**`\index{Large Neighborhood Search}`{=latex} ([LNS (Large Neighborhood Search)](#gloss:large-neighborhood-search-lns){.glossar-link}) setzt beide ein, jeden für das, was er kann:
| Schritt | Was passiert |
| --- | --- |
@ -11623,7 +11623,7 @@ Nach diesem Kapitel können Sie …
1. … erklären, warum das naheliegende Zuordnungsmodell an **Symmetrie** scheitert.
2. … ein Problem in **Master** und **Pricing-Teilproblem** zerlegen.
3. … die Schleife schreiben: Master-[LP](#gloss:lineare-programmierung-lp){.glossar-link} lösen, Dualwerte auslesen, Teilproblem lösen, Spalte hinzufügen.
3. … die Schleife schreiben: Master-[LP (Lineare Programmierung)](#gloss:lineare-programmierung-lp){.glossar-link} lösen, Dualwerte auslesen, Teilproblem lösen, Spalte hinzufügen.
4. … das Abbruchkriterium über die **reduzierten Kosten** begründen.
5. … an einer Kennzahl der Instanz abschätzen, ob sich das Verfahren lohnt.
@ -12198,7 +12198,7 @@ Und selbst dort, wo die Ersparnis null ist, liefert das Verfahren etwas, das die
## 10.10 Selbsttest {#sec:dekomposition-selbsttest}
1. Erklären Sie Symmetrie in einem [MILP](#gloss:gemischt-ganzzahlige-optimierung-milp){.glossar-link} an einem Beispiel aus Ihrem Arbeitsumfeld.
1. Erklären Sie Symmetrie in einem [MILP (Gemischt-ganzzahlige Optimierung)](#gloss:gemischt-ganzzahlige-optimierung-milp){.glossar-link} an einem Beispiel aus Ihrem Arbeitsumfeld.
2. Was ist beim Zuschnitt eine „Spalte", und was steht darin?
3. Woher kommen die Preise, mit denen das Teilproblem rechnet?
4. Warum ist das Verfahren exakt, obwohl es fast alle Muster nie ansieht?
@ -12226,8 +12226,8 @@ Sechs Kapitel, sechs Werkzeuge. Jedes einzelne wurde im Zusammenhang gezeigt; hi
| Verfahren | Wofür es gebaut ist | Was Sie bekommen | Wo es aufhört | Kapitel |
| --- | --- | --- | --- | --- |
| **[LP](#gloss:lineare-programmierung-lp){.glossar-link}** | teilbare Mengen, lineare Zusammenhänge | beweisbares Optimum **plus Schattenpreise** | sobald etwas ganzzahlig sein muss | [Kapitel 5](#kap-lp) |
| **[MILP](#gloss:gemischt-ganzzahlige-optimierung-milp){.glossar-link}** | Ja/Nein-Entscheidungen, Fixkosten, Logik | beweisbares Optimum, Gap als Fortschrittsmaß | Laufzeit wächst mit der Zahl der Binärvariablen | [Kapitel 6](#kap-milp) |
| **[LP (Lineare Programmierung)](#gloss:lineare-programmierung-lp){.glossar-link}** | teilbare Mengen, lineare Zusammenhänge | beweisbares Optimum **plus Schattenpreise** | sobald etwas ganzzahlig sein muss | [Kapitel 5](#kap-lp) |
| **[MILP (Gemischt-ganzzahlige Optimierung)](#gloss:gemischt-ganzzahlige-optimierung-milp){.glossar-link}** | Ja/Nein-Entscheidungen, Fixkosten, Logik | beweisbares Optimum, Gap als Fortschrittsmaß | Laufzeit wächst mit der Zahl der Binärvariablen | [Kapitel 6](#kap-milp) |
| **[CP-SAT](#gloss:cp-sat){.glossar-link}**`\index{CP-SAT}`{=latex} | Zuweisung, Reihenfolge, Kalender, harte Logik | beweisbares Optimum, sehr ausdrucksstarke Bedingungen | keine Schattenpreise, keine stetigen Größen | [Kapitel 7](#kap-cpsat) |
| **Graphenalgorithmen** | Flüsse, Zuordnung, Touren | oft **polynomiell** statt exponentiell | nur, wenn die Struktur wirklich passt | [Kapitel 8](#kap-graphen) |
| **Metaheuristiken** | wenn der exakte [Solver](#gloss:solver){.glossar-link} aussteigt | eine gute Lösung in **fester Zeit** | keine Garantie, kein Beweis, keine Schranke | [Kapitel 9](#kap-metaheuristiken) |
@ -12239,8 +12239,8 @@ Sechs Kapitel, sechs Werkzeuge. Jedes einzelne wurde im Zusammenhang gezeigt; hi
| Behauptung | Gemessen | Wo |
| --- | --- | --- |
| „Der exakte Solver ist immer besser." | Bei 500 Aufträgen liefert [CP](#gloss:constraint-programming-cp){.glossar-link}-[SAT](#gloss:sat-boolean-satisfiability){.glossar-link} eine Lösung, die **5,2 % schlechter** ist als die Faustregel eines Meisters | [Kapitel 9](#kap-metaheuristiken) |
| „Metaheuristiken sind ungenau." | Faustregel 2 497 → Annealing 2 343 → Annealing plus [LNS](#gloss:large-neighborhood-search-lns){.glossar-link} **2 289** Minuten [Rüstzeit](#gloss:ruestzeit){.glossar-link}`\index{Rüstzeit}`{=latex}; untere Schranke 1 768 | [Kapitel 9](#kap-metaheuristiken) |
| „Der exakte Solver ist immer besser." | Bei 500 Aufträgen liefert [CP (Constraint Programming)](#gloss:constraint-programming-cp){.glossar-link}-[SAT (Boolean Satisfiability)](#gloss:sat-boolean-satisfiability){.glossar-link} eine Lösung, die **5,2 % schlechter** ist als die Faustregel eines Meisters | [Kapitel 9](#kap-metaheuristiken) |
| „Metaheuristiken sind ungenau." | Faustregel 2 497 → Annealing 2 343 → Annealing plus [LNS (Large Neighborhood Search)](#gloss:large-neighborhood-search-lns){.glossar-link} **2 289** Minuten [Rüstzeit](#gloss:ruestzeit){.glossar-link}`\index{Rüstzeit}`{=latex}; untere Schranke 1 768 | [Kapitel 9](#kap-metaheuristiken) |
| „Man muss alle Variablen aufschreiben." | 28 erzeugte Muster von **46 408** möglichen — und die Lösung ist beweisbar optimal | [Kapitel 10](#kap-dekomposition) |
| „Dekomposition lohnt sich immer." | Bei drei Stücken je Rolle **11 %** Ersparnis, bei sechs **nichts** | [Kapitel 10](#kap-dekomposition) |
| „Mit Seed ist der Lauf reproduzierbar." | Schon **zwei** Arbeiter liefern bei identischem Seed drei verschiedene Pläne zum selben Zielwert | [Abschnitt 7.7](#sec:cpsat-parallele-suche) |
@ -12282,7 +12282,7 @@ Zwei weitere Kapitel schließen sich an, weil sie dieselbe Voraussetzung aufgebe
>
> **Voraussetzungen:** [Kapitel 2](#kap-fundament) (Konvexität, Eigenwerte), [Kapitel 5](#kap-lp) (Dualität, Schattenpreise). Gradienten werden in [Abschnitt 11.2](#sec:qp-nlp-lernziele) wiederholt.
>
> **Danach können Sie:** Ein quadratisches Programm aufstellen, die [KKT](#gloss:karush-kuhn-tucker-bedingungen-kkt){.glossar-link}-Bedingungen anwenden, den Zusammenhang zwischen [Lagrange-Multiplikator](#gloss:lagrange-multiplikator){.glossar-link}`\index{Lagrange-Multiplikator}`{=latex} und [Schattenpreis](#gloss:schattenpreis){.glossar-link} erklären, eine gültige [Kovarianzmatrix](#gloss:kovarianzmatrix){.glossar-link}`\index{Kovarianzmatrix}`{=latex} konstruieren — und mit nicht-konvexen Problemen umgehen, ohne ein lokales Optimum für das Optimum zu halten.
> **Danach können Sie:** Ein quadratisches Programm aufstellen, die [KKT (Karush-Kuhn-Tucker-Bedingungen)](#gloss:karush-kuhn-tucker-bedingungen-kkt){.glossar-link}-Bedingungen anwenden, den Zusammenhang zwischen [Lagrange-Multiplikator](#gloss:lagrange-multiplikator){.glossar-link}`\index{Lagrange-Multiplikator}`{=latex} und [Schattenpreis](#gloss:schattenpreis){.glossar-link} erklären, eine gültige [Kovarianzmatrix](#gloss:kovarianzmatrix){.glossar-link}`\index{Kovarianzmatrix}`{=latex} konstruieren — und mit nicht-konvexen Problemen umgehen, ohne ein lokales Optimum für das Optimum zu halten.
>
> **Zeitbedarf:** ca. 6,5 Stunden.
>
@ -12364,7 +12364,7 @@ Der letzte Term ist der entscheidende: Bei negativer Korrelation ist er **negati
Nach diesem Kapitel können Sie …
1. … ein **quadratisches Programm ([QP](#gloss:quadratische-programmierung-qp){.glossar-link})** aufstellen und von einem allgemeinen nichtlinearen Programm abgrenzen.
1. … ein **quadratisches Programm ([QP (Quadratische Programmierung)](#gloss:quadratische-programmierung-qp){.glossar-link})** aufstellen und von einem allgemeinen nichtlinearen Programm abgrenzen.
2. … die **KKT-Bedingungen** herleiten und auf ein Optimierungsproblem anwenden.
3. … den Zusammenhang zwischen **Lagrange-Multiplikator** und **Schattenpreis**`\index{Schattenpreis}`{=latex} erklären.
4. … zwischen **konvex**`\index{Konvexität}`{=latex} und **streng konvex**`\index{Konvexität!streng konvex}`{=latex} unterscheiden und eine gültige, positiv semidefinite **Kovarianzmatrix**`\index{Kovarianzmatrix}`{=latex} konstruieren.
@ -12576,7 +12576,7 @@ lässt nur $x \le 3$ zu, und $\lambda^* = 4$ ist genau die Steigung von $f$ am R
> | $g_i(\mathbf{x}^*) \le 0$ | „Der Plan hält alle Regeln ein.“ |
> | $\lambda_i^* \ge 0$ | „Eine Grenze kann nur bremsen, nie antreiben.“ Ein negativer Preis wäre widersinnig. |
> | $\lambda_i^* \cdot g_i(\mathbf{x}^*) = 0$ | „Was Reserve hat, ist nichts wert. Was etwas wert ist, ist ausgereizt.“ Nie beides. |
> | $\lambda_i^*$ selbst | Der **Schattenpreis** von Bedingung $i$ — dieselbe Größe wie im [LP](#gloss:lineare-programmierung-lp){.glossar-link} ([Kapitel 5](#kap-lp)), nur für krumme Ränder. |
> | $\lambda_i^*$ selbst | Der **Schattenpreis** von Bedingung $i$ — dieselbe Größe wie im [LP (Lineare Programmierung)](#gloss:lineare-programmierung-lp){.glossar-link} ([Kapitel 5](#kap-lp)), nur für krumme Ränder. |
>
> **Alle vier zusammen in einem Satz:** *Wir stehen an einer Stelle, an der jede Verbesserung an eine Grenze stößt — und wir wissen für jede dieser Grenzen, was ihre Lockerung wert wäre.*
>
@ -13243,7 +13243,7 @@ Wird zusätzlich noch ganzzahlig entschieden — „welche Anlage läuft überha
| Werkzeug | Art | Was es leistet |
| --- | --- | --- |
| **Ipopt** (über `cyipopt` oder [Pyomo](#gloss:pyomo){.glossar-link}`\index{Pyomo}`{=latex}) | lokaler [NLP](#gloss:nichtlineare-programmierung-nlp){.glossar-link}-Solver | Innere-Punkte-Verfahren für große, glatte NLPs mit tausenden Variablen — deutlich leistungsfähiger als `scipy`, aber ebenfalls **nur lokal** |
| **Ipopt** (über `cyipopt` oder [Pyomo](#gloss:pyomo){.glossar-link}`\index{Pyomo}`{=latex}) | lokaler [NLP (Nichtlineare Programmierung)](#gloss:nichtlineare-programmierung-nlp){.glossar-link}-Solver | Innere-Punkte-Verfahren für große, glatte NLPs mit tausenden Variablen — deutlich leistungsfähiger als `scipy`, aber ebenfalls **nur lokal** |
| **Bonmin**, **Couenne** | MINLP | Bonmin lokal, Couenne mit globaler Garantie für viele Klassen |
| **[SCIP](#gloss:scip){.glossar-link}**`\index{SCIP}`{=latex}, **BARON**, **[Gurobi](#gloss:gurobi){.glossar-link}**`\index{Gurobi}`{=latex} | global | Beweisbar globales Optimum, mit entsprechendem Rechenaufwand |
| **Pyomo** ([Abschnitt 3.7](#sec:oekosystem-pyomo-linopy)) | Modellierungsschicht | Bindet alle oben genannten an, ohne dass das Modell umgeschrieben werden muss |
@ -13311,7 +13311,7 @@ else:
> Sein erster Versuch mit CVXPY bricht ab:
>
> ```
> [DCPError](#gloss:dcperror){.glossar-link}: Problem does not follow [DCP](#gloss:dcp-disciplined-convex-programming){.glossar-link} rules.
> [DCPError](#gloss:dcperror){.glossar-link}: Problem does not follow [DCP (Disciplined Convex Programming)](#gloss:dcp-disciplined-convex-programming){.glossar-link} rules.
> The objective is not DCP. Its following subexpressions are not: QuadForm(...)
> ```
>
@ -13968,7 +13968,7 @@ deutlich teurer ist als Leerlauf (5 EUR).
**Lesen Sie die Vergleichstabelle von unten nach oben.** Die beiden extremen Haltungen sind die teuersten: Wer den Worst Case abdeckt (500 Einheiten), zahlt 5 000 € zu viel für Kapazität, die in 80 % der Fälle brachliegt. Wer optimistisch plant (100), zahlt 2 625 € Strafe für ständige Notzukäufe. Die naive Mittelwertplanung liegt dazwischen — aber eben auch nicht optimal.
Der **[EVPI](#gloss:evpi-expected-value-of-perfect-information){.glossar-link} von 7 375 €** ist bemerkenswert hoch: 45 % der Gesamtkosten entstehen allein daraus, dass man die Zukunft nicht kennt. In so einem Fall lohnt sich Investition in bessere Prognosen tatsächlich — anders als in dem Beispiel aus der Aufgabe *EVPI interpretieren* ([Abschnitt 12.8](#sec:unsicherheit-uebungsaufgaben)).
Der **[EVPI (Expected Value of Perfect Information)](#gloss:evpi-expected-value-of-perfect-information){.glossar-link} von 7 375 €** ist bemerkenswert hoch: 45 % der Gesamtkosten entstehen allein daraus, dass man die Zukunft nicht kennt. In so einem Fall lohnt sich Investition in bessere Prognosen tatsächlich — anders als in dem Beispiel aus der Aufgabe *EVPI interpretieren* ([Abschnitt 12.8](#sec:unsicherheit-uebungsaufgaben)).
> **💡 Was ist der EVPI?** Der **Expected Value of Perfect Information**`\index{EVPI}`{=latex} beziffert, wie viel eine perfekte Prognose wert wäre: die Differenz zwischen den Kosten unter Unsicherheit und den Kosten bei vollständigem Wissen. Er ist eine **Obergrenze für jedes Prognoseprojekt**. Wenn der EVPI bei 12 000 € pro Jahr liegt, lohnt sich keine Prognosesoftware für 50 000 € — selbst wenn sie perfekt wäre. Diese Zahl bewahrt Projekte vor teuren Fehlinvestitionen.
@ -14154,7 +14154,7 @@ z_s &\in \{0,1\}
\end{aligned}
$$
Aus dem Kegelproblem wird ein [MILP](#gloss:gemischt-ganzzahlige-optimierung-milp){.glossar-link} mit $S$ Binärvariablen. Für $M$ gilt, was [Kapitel 6](#kap-milp) über die Big-M-Falle sagt: **so klein wie möglich**. Hier ist $M = b$ die kleinste gültige Schranke, denn $\mathbf{a}_s^\top\mathbf{x} \ge 0$ — größer kann eine Verletzung gar nicht ausfallen.
Aus dem Kegelproblem wird ein [MILP (Gemischt-ganzzahlige Optimierung)](#gloss:gemischt-ganzzahlige-optimierung-milp){.glossar-link} mit $S$ Binärvariablen. Für $M$ gilt, was [Kapitel 6](#kap-milp) über die Big-M-Falle sagt: **so klein wie möglich**. Hier ist $M = b$ die kleinste gültige Schranke, denn $\mathbf{a}_s^\top\mathbf{x} \ge 0$ — größer kann eine Verletzung gar nicht ausfallen.
### Der Fall: ein Kraftwerkspark mit 500 MW Zusage
@ -14488,7 +14488,7 @@ Der szenariobasierte Weg kennt diese Fälle, weil sie in den Daten stehen. Er ko
**Aufgabe 12.4 ⭐⭐ — EVPI interpretieren.** Ihr Modell liefert EVPI = 8 400 € pro Jahr. Ein Anbieter verlangt 15 000 € jährlich für eine Prognoselösung, die „80 % Treffsicherheit“ verspricht. Wie argumentieren Sie?
**Aufgabe 12.5 ⭐⭐⭐ — Monte-Carlo erweitern.** Erweitern Sie `Monte_Carlo.py`: (a) Fügen Sie ein Servicelevel-Kriterium hinzu: „Die Unterdeckung darf höchstens in 5 % der Fälle auftreten.“ Welche Kapazität ist dafür nötig, und was kostet sie zusätzlich? (b) Berechnen Sie den [CVaR](#gloss:conditional-value-at-risk-cvar){.glossar-link} der Kosten (Mittelwert der schlechtesten 5 %). (c) Zeichnen Sie ein Histogramm der Kosten für drei Kapazitäten.
**Aufgabe 12.5 ⭐⭐⭐ — Monte-Carlo erweitern.** Erweitern Sie `Monte_Carlo.py`: (a) Fügen Sie ein Servicelevel-Kriterium hinzu: „Die Unterdeckung darf höchstens in 5 % der Fälle auftreten.“ Welche Kapazität ist dafür nötig, und was kostet sie zusätzlich? (b) Berechnen Sie den [CVaR (Conditional Value at Risk)](#gloss:conditional-value-at-risk-cvar){.glossar-link} der Kosten (Mittelwert der schlechtesten 5 %). (c) Zeichnen Sie ein Histogramm der Kosten für drei Kapazitäten.
**Aufgabe 12.6 ⭐⭐ — Den Preis der Zusage selbst bestimmen.** `Chance_Constraints.py` beziffert die Kosten für 80, 90, 95 und 99 %. (a) Ergänzen Sie die Stufen 99,5 % und 99,9 % und setzen Sie die Kosten je Prozentpunkt fort. Was passiert mit dem Anlagenmix? (b) Drosseln Sie die Ausbaugrenze der Biomasse von 350 auf 200 MW. Das **szenariobasierte** Modell meldet dann bei 95 % `infeasible`, das **analytische** dagegen `optimal`. Erklären Sie den Unterschied. Welchem der beiden würden Sie glauben? (c) Ein Vorstand fordert „99,99 % Versorgungssicherheit“. Formulieren Sie in drei Sätzen, was Sie ihm mit dieser Kurve antworten.
@ -14667,7 +14667,7 @@ Nach diesem Kapitel können Sie …
2. … Zustand, Stufe, Aktion und Wertfunktion für ein gegebenes Problem benennen.
3. … eine Rückwärtsinduktion`\index{Rückwärtsinduktion}`{=latex} von Hand für ein kleines Problem durchführen.
4. … das Almgren-Chriss-Ausführungsproblem lösen und die Lösung interpretieren.
5. … einschätzen, wann [DP](#gloss:dynamische-programmierung-dp){.glossar-link} funktioniert und wann der „[Fluch der Dimensionalität](#gloss:fluch-der-dimensionalitaet){.glossar-link}`\index{Fluch der Dimensionalität}`{=latex}“ zuschlägt.
5. … einschätzen, wann [DP (Dynamische Programmierung)](#gloss:dynamische-programmierung-dp){.glossar-link} funktioniert und wann der „[Fluch der Dimensionalität](#gloss:fluch-der-dimensionalitaet){.glossar-link}`\index{Fluch der Dimensionalität}`{=latex}“ zuschlägt.
6. … die Wertfunktion als **Nachschlagetabelle** lesen: Sie liefert keine Planfolge, sondern eine Regel, die auch bei Abweichungen gilt.
7. … einen [Zustandsraum](#gloss:zustandsraum){.glossar-link}`\index{Zustandsraum}`{=latex} auf Vollständigkeit prüfen und erkennen, wann eine Kostenart Vorgeschichte erfordert.
@ -15209,7 +15209,7 @@ Das Problem entsteht, sobald der Zustand **mehrere Dimensionen** hat:
**Aufgabe 13.3 ⭐⭐ — Rückwärtsinduktion von Hand.** 5 Einheiten in 3 Perioden, Kosten $C(n) = n^2 + 2n$. Erstellen Sie die vollständige Wertfunktionstabelle und bestimmen Sie den optimalen Pfad. Prüfen Sie mit `Bellman_Minimalbeispiel.py` (angepasst).
**Aufgabe 13.4 ⭐⭐ — [Rucksackproblem](#gloss:rucksackproblem){.glossar-link}`\index{Rucksackproblem}`{=latex} als DP.** Lösen Sie das Rucksackproblem aus [Kapitel 6](#kap-milp) mit dynamischer Programmierung statt [MILP](#gloss:gemischt-ganzzahlige-optimierung-milp){.glossar-link}. (Zustand: verbleibende Kapazität; Stufe: betrachteter Gegenstand.) Vergleichen Sie Laufzeit und Ergebnis mit dem MILP-[Solver](#gloss:solver){.glossar-link}.
**Aufgabe 13.4 ⭐⭐ — [Rucksackproblem](#gloss:rucksackproblem){.glossar-link}`\index{Rucksackproblem}`{=latex} als DP.** Lösen Sie das Rucksackproblem aus [Kapitel 6](#kap-milp) mit dynamischer Programmierung statt [MILP (Gemischt-ganzzahlige Optimierung)](#gloss:gemischt-ganzzahlige-optimierung-milp){.glossar-link}. (Zustand: verbleibende Kapazität; Stufe: betrachteter Gegenstand.) Vergleichen Sie Laufzeit und Ergebnis mit dem MILP-[Solver](#gloss:solver){.glossar-link}.
**Aufgabe 13.5 ⭐⭐⭐ — Risikoaversion kalibrieren.** Untersuchen Sie mit `Mehrperiodige_Order_Execution.py`: (a) Bei welchem $\lambda$ verkauft das Modell in der ersten Periode mehr als 50 %? (b) Stellen Sie den Zusammenhang zwischen $\lambda$ und den erwarteten Gesamtkosten dar. (c) Ein Händler sagt: „Ich will höchstens 20 % Marktauswirkungskosten und den Rest an Risiko.“ Welches $\lambda$ setzen Sie?
@ -15833,7 +15833,7 @@ Das Programm rechnet diese Hülle in `untere_huelle()` unabhängig aus und vergl
> **⚠️ Der Grund liegt in der Ganzzahligkeit**
>
> Bei einem reinen [LP](#gloss:lineare-programmierung-lp){.glossar-link} ist der zulässige Bereich konvex, und die Pareto-Front liegt vollständig auf ihrer eigenen konvexen Hülle — dort findet die gewichtete Summe alles. Sobald Entscheidungen **ganzzahlig** werden (welcher Träger, welches Lager, welche Schicht), zerfällt der Bereich in einzelne Punkte, und zwischen ihnen entstehen Einbuchtungen.
> Bei einem reinen [LP (Lineare Programmierung)](#gloss:lineare-programmierung-lp){.glossar-link} ist der zulässige Bereich konvex, und die Pareto-Front liegt vollständig auf ihrer eigenen konvexen Hülle — dort findet die gewichtete Summe alles. Sobald Entscheidungen **ganzzahlig** werden (welcher Träger, welches Lager, welche Schicht), zerfällt der Bereich in einzelne Punkte, und zwischen ihnen entstehen Einbuchtungen.
>
> Deshalb betrifft dieses Problem praktisch jedes betriebliche Mehrzielmodell. Wer mit Gewichten arbeitet, verliert nicht ein paar Nachkommastellen, sondern **ganze Alternativen** — im Beispiel 40 % der Front.
@ -15953,7 +15953,7 @@ Diese Zahl ist mit etwas vergleichbar, das das Unternehmen ohnehin kennt: dem in
## 14.12 Selbsttest {#sec:mehrziel-selbsttest}
1. Erklären Sie Pareto-Dominanz an einem Beispiel aus Ihrem Arbeitsumfeld.
2. Warum ist „gewichtete Summe" bei einem reinen LP unproblematisch und bei einem [MILP](#gloss:gemischt-ganzzahlige-optimierung-milp){.glossar-link} nicht?
2. Warum ist „gewichtete Summe" bei einem reinen LP unproblematisch und bei einem [MILP (Gemischt-ganzzahlige Optimierung)](#gloss:gemischt-ganzzahlige-optimierung-milp){.glossar-link} nicht?
3. Ein Kollege sagt: „Ich nehme $w = 0{,}5$, das ist neutral." Was ist daran falsch?
4. Beschreiben Sie das ε-Constraint-Verfahren in drei Sätzen, ohne Formeln.
5. Sie legen einer Geschäftsführung eine Front mit zwölf Punkten vor. Welche Spalte brauchen Sie, damit die Entscheidung fallen kann?
@ -16584,7 +16584,7 @@ Hier war es ein einziger [Parameter](#gloss:parameter){.glossar-link}`\index{Par
| Was nicht gilt | Woran Sie es merken | Werkzeug | Kapitel |
| --- | --- | --- | --- |
| **Linearität** | Risiko wächst quadratisch, Kosten degressiv, Sättigung | [QP](#gloss:quadratische-programmierung-qp){.glossar-link}, konvexe Optimierung, [KKT](#gloss:karush-kuhn-tucker-bedingungen-kkt){.glossar-link} | [Kapitel 11](#kap-qp-nlp) |
| **Linearität** | Risiko wächst quadratisch, Kosten degressiv, Sättigung | [QP (Quadratische Programmierung)](#gloss:quadratische-programmierung-qp){.glossar-link}, konvexe Optimierung, [KKT (Karush-Kuhn-Tucker-Bedingungen)](#gloss:karush-kuhn-tucker-bedingungen-kkt){.glossar-link} | [Kapitel 11](#kap-qp-nlp) |
| **Feste Daten** | Nachfrage, Wind, Rendite stehen erst morgen fest | Monte-Carlo, Zweistufigkeit, Robustheit, Chance Constraints | [Kapitel 12](#kap-unsicherheit) |
| **Eine Periode** | die Entscheidung heute verändert, was übermorgen möglich ist | [Bellman-Gleichung](#gloss:bellman-gleichung){.glossar-link}`\index{Bellman-Gleichung}`{=latex}, [Rückwärtsinduktion](#gloss:rueckwaertsinduktion){.glossar-link}`\index{Rückwärtsinduktion}`{=latex} | [Kapitel 13](#kap-dynamische-programmierung) |
| **Ein Ziel** | zwei Kennzahlen sollen gleichzeitig stimmen | [Pareto-Front](#gloss:pareto-front){.glossar-link}`\index{Pareto-Front}`{=latex}, ε-Constraint | [Kapitel 14](#kap-mehrziel) |
@ -16640,7 +16640,7 @@ Er hat drei Abschnitte, und Sie können nach jedem aufhören:
>
> **Worum geht es?** Um den Nachweis, dass die Verfahren aus Teil II und III unverändert in der Finanzwelt funktionieren — und um die drei Stellen, an denen die Analogie endet.
>
> **Voraussetzungen:** [Kapitel 1](#kap-einfuehrung) (Allokation als [LP](#gloss:lineare-programmierung-lp){.glossar-link}), [Kapitel 12](#kap-unsicherheit) (Szenarien) und [Abschnitt 22.6](#sec:praxisfallen-or-kern) (`or_kern.py`).
> **Voraussetzungen:** [Kapitel 1](#kap-einfuehrung) (Allokation als [LP (Lineare Programmierung)](#gloss:lineare-programmierung-lp){.glossar-link}), [Kapitel 12](#kap-unsicherheit) (Szenarien) und [Abschnitt 22.6](#sec:praxisfallen-or-kern) (`or_kern.py`).
>
> **Danach können Sie:** ein betriebswirtschaftliches Modell in die andere Domäne übersetzen, ohne den Modellcode anzufassen; Schattenpreise in beiden Welten lesen; und benennen, welche Annahmen dabei **nicht** mitwandern.
>
@ -16712,7 +16712,7 @@ Nach diesem Kapitel können Sie …
1. … ein Allokationsproblem aus der einen Domäne in die andere übersetzen, indem Sie die Daten austauschen statt des Codes.
2. … den Schattenpreis in beiden Welten deuten — als Wert einer Ressource und als Preis des Risikos.
3. … erklären, warum die [CVaR](#gloss:conditional-value-at-risk-cvar){.glossar-link}-Formulierung aus [Kapitel 20](#kap-cvar) auf Lieferverzüge genauso passt wie auf Kursverluste.
3. … erklären, warum die [CVaR (Conditional Value at Risk)](#gloss:conditional-value-at-risk-cvar){.glossar-link}-Formulierung aus [Kapitel 20](#kap-cvar) auf Lieferverzüge genauso passt wie auf Kursverluste.
4. … die drei Stellen benennen, an denen die Analogie **nicht** trägt — und begründen, warum das Übertragen von Methoden dort gefährlich wird.
---
@ -17148,7 +17148,7 @@ steht im Programm genau einmal und wird zweimal aufgerufen.
> | --- | --- | --- |
> | $w$ | Anteil je Anlageklasse | Bestellanteil je Lieferant |
> | $\ell_s$ | Verlust in Szenario $s$, in Prozentpunkten | Verzug in Szenario $s$, in Tagen |
> | $\gamma$ | der [VaR](#gloss:value-at-risk-var){.glossar-link}: „so schlimm wird es an 95 % der Tage höchstens" | „so viele Tage Verzug höchstens bei 95 % der Bestellungen" |
> | $\gamma$ | der [VaR (Value at Risk)](#gloss:value-at-risk-var){.glossar-link}: „so schlimm wird es an 95 % der Tage höchstens" | „so viele Tage Verzug höchstens bei 95 % der Bestellungen" |
> | $u_s$ | Überschuss über diese Schwelle | dasselbe |
> | Zielwert | CVaR: Mittelwert der schlechtesten 5 % | dasselbe |
>
@ -17174,7 +17174,7 @@ Eine Analogie ist nur so nützlich wie die Grenzen, die man ihr zieht. Drei Ding
| --- | --- | --- |
| **Woher die Zahlen kommen** | gemessen: drei Montagestunden sind drei Montagestunden | geschätzt: die erwartete Rendite hat einen Fehler, der größer sein kann als die Unterschiede zwischen den Anlagen ([Kapitel 19](#kap-markowitz)) |
| **Ob die Vergangenheit trägt** | Lieferzeiten haben physikalische Ursachen und ändern sich langsam | Kurse entstehen aus dem Verhalten von Marktteilnehmern, die auf Modelle reagieren — ein erkanntes Muster verschwindet oft deshalb, weil es erkannt wurde ([Kapitel 21](#kap-handelsmaschine)) |
| **Ob Teilbarkeit erlaubt ist** | 37,4 % eines Lieferanten gibt es nicht: Verträge, Mindestabnahmen, Rüstzeiten → [MILP](#gloss:gemischt-ganzzahlige-optimierung-milp){.glossar-link} | 37,4 % eines Fonds sind ein normaler Auftrag → LP/[QP](#gloss:quadratische-programmierung-qp){.glossar-link} genügt |
| **Ob Teilbarkeit erlaubt ist** | 37,4 % eines Lieferanten gibt es nicht: Verträge, Mindestabnahmen, Rüstzeiten → [MILP (Gemischt-ganzzahlige Optimierung)](#gloss:gemischt-ganzzahlige-optimierung-milp){.glossar-link} | 37,4 % eines Fonds sind ein normaler Auftrag → LP/[QP (Quadratische Programmierung)](#gloss:quadratische-programmierung-qp){.glossar-link} genügt |
> **⚠️ Der Fehler, vor dem diese Tabelle schützt**
>
@ -17315,7 +17315,7 @@ Eine Analogie ist nur so nützlich wie die Grenzen, die man ihr zieht. Drei Ding
Die Merit-Order — Kraftwerke nach Grenzkosten sortieren und von unten auffüllen — ist damit nur für einen **einzelnen** Zeitpunkt richtig. Sobald ein Tag geplant wird, hängt jede Stunde an allen anderen: Ein Block, der um 8 Uhr angefahren wird, muss bis mindestens 16 Uhr laufen, und diese Entscheidung fällt am Vorabend.
> **🎯 Merksatz** Anfahrkosten und Mindestlaufzeiten machen aus 24 unabhängigen Stundenentscheidungen **ein** Problem. Genau deshalb ist die Kraftwerkseinsatzplanung ein [MILP](#gloss:gemischt-ganzzahlige-optimierung-milp){.glossar-link} und keine Sortierung.
> **🎯 Merksatz** Anfahrkosten und Mindestlaufzeiten machen aus 24 unabhängigen Stundenentscheidungen **ein** Problem. Genau deshalb ist die Kraftwerkseinsatzplanung ein [MILP (Gemischt-ganzzahlige Optimierung)](#gloss:gemischt-ganzzahlige-optimierung-milp){.glossar-link} und keine Sortierung.
**Warum funktioniert das?** Der Umschlagpunkt ist eine einfache Rechnung: Die Anfahrkostendifferenz (38 500 €) geteilt durch die Grenzkostendifferenz je Stunde (83 €/MWh × 120 MW = 9 960 €/h) ergibt 3,9 Stunden. Bei zwei Kraftwerken kann man das im Kopf ausrechnen — bei fünf Blöcken und 24 Stunden nicht mehr.
@ -17328,7 +17328,7 @@ Nach diesem Kapitel können Sie …
1. … ein Unit-Commitment-Modell mit Anfahrkosten und Mindestlaufzeiten aufstellen.
2. … erklären, warum eine **binäre erste Stufe** das zweistufige Modell aus [Kapitel 12](#kap-unsicherheit) verschärft.
3. … zeigen, dass eine Planung auf den Erwartungswert nicht nur ungenau, sondern **systematisch zu knapp** ist.
4. … eine [CVaR](#gloss:conditional-value-at-risk-cvar){.glossar-link}-Schranke auf eine physikalische Größe (nicht gedeckte Energie) legen.
4. … eine [CVaR (Conditional Value at Risk)](#gloss:conditional-value-at-risk-cvar){.glossar-link}-Schranke auf eine physikalische Größe (nicht gedeckte Energie) legen.
5. … begründen, wann eine Risikoschranke etwas ändert — und wann sie überflüssig ist.
---
@ -18520,7 +18520,7 @@ if __name__ == "__main__":
**Aufgabe 18.4 ⭐⭐ — Spaltenreihenfolge prüfen.** Laden Sie fünf Ticker in einer bewusst unsortierten Reihenfolge. Zeigen Sie, dass `raw["Close"].columns` abweicht, und dass `raw["Close"][tickers]` das behebt. Was passiert, wenn ein Ticker nicht existiert?
**Aufgabe 18.5 ⭐⭐⭐ — Beide Shrinkage-Ziele vergleichen.** Implementieren Sie das Konstant-Korrelations-Ziel vollständig (inklusive eigener Berechnung von $\delta$ nach Ledoit/Wolf 2003 oder per Kreuzvalidierung). Vergleichen Sie mit `sklearn` anhand: (a) der Konditionszahl, (b) der Out-of-Sample-Volatilität eines [GMV](#gloss:global-minimum-variance-portfolio-gmv){.glossar-link}-Portfolios (nach dem Muster von `Schaetzrauschen_Demo.py`), (c) der Stabilität der Gewichte über rollierende Fenster.
**Aufgabe 18.5 ⭐⭐⭐ — Beide Shrinkage-Ziele vergleichen.** Implementieren Sie das Konstant-Korrelations-Ziel vollständig (inklusive eigener Berechnung von $\delta$ nach Ledoit/Wolf 2003 oder per Kreuzvalidierung). Vergleichen Sie mit `sklearn` anhand: (a) der Konditionszahl, (b) der Out-of-Sample-Volatilität eines [GMV (Global Minimum Variance Portfolio)](#gloss:global-minimum-variance-portfolio-gmv){.glossar-link}-Portfolios (nach dem Muster von `Schaetzrauschen_Demo.py`), (c) der Stabilität der Gewichte über rollierende Fenster.
**Aufgabe 18.6 ⭐⭐⭐ — Error-Maximizer selbst messen.** Erweitern Sie `Schaetzrauschen_Demo.py` um eine dritte Variante: die **Gleichgewichtung** ($w_i = 1/N$), die überhaupt keine Schätzung benötigt. (a) Ab welchem $T/N$ schlägt die Stichproben-Optimierung die Gleichgewichtung? (b) Ab welchem $T/N$ schlägt Ledoit-Wolf sie? (c) Was folgt daraus für die Praxis?
@ -18769,7 +18769,7 @@ e 0: \mathbf{w}^ op\mathbf{S}\mathbf{w} = 0$ | „In genau diesen Richtungen mis
>
> **Worum geht es?** Um das Modell, das 1952 die quantitative Finanzwirtschaft begründete — und um die Restriktionen, ohne die es in der Praxis unbrauchbar bleibt.
>
> **Voraussetzungen:** [Kapitel 11](#kap-qp-nlp) ([QP](#gloss:quadratische-programmierung-qp){.glossar-link}, [KKT](#gloss:karush-kuhn-tucker-bedingungen-kkt){.glossar-link}), [Kapitel 18](#kap-finanzdaten) (Kovarianz, Shrinkage).
> **Voraussetzungen:** [Kapitel 11](#kap-qp-nlp) ([QP (Quadratische Programmierung)](#gloss:quadratische-programmierung-qp){.glossar-link}, [KKT (Karush-Kuhn-Tucker-Bedingungen)](#gloss:karush-kuhn-tucker-bedingungen-kkt){.glossar-link}), [Kapitel 18](#kap-finanzdaten) (Kovarianz, Shrinkage).
>
> **Danach können Sie:** Die Effizienzgrenze berechnen, das Maximum-Sharpe-Portfolio über die [Korn-Transformation](#gloss:korn-transformation){.glossar-link}`\index{Korn-Transformation}`{=latex} bestimmen, institutionelle Nebenbedingungen einbauen — und beurteilen, wann eine Renditeschätzung das Ergebnis wertlos macht.
>
@ -18990,7 +18990,7 @@ $$
>
> | $\lambda$ | Verhalten | Ergebnis |
> | --- | --- | --- |
> | $0$ | Risiko zählt allein | **[GMV](#gloss:global-minimum-variance-portfolio-gmv){.glossar-link}** — Global Minimum Variance Portfolio |
> | $0$ | Risiko zählt allein | **[GMV (Global Minimum Variance Portfolio)](#gloss:global-minimum-variance-portfolio-gmv){.glossar-link}** — Global Minimum Variance Portfolio |
> | mittel | Abwägung | ein Punkt auf der Effizienzgrenze |
> | $\to\infty$ | Rendite zählt allein | alles in den Titel mit höchstem $\mu$ |
>
@ -19664,9 +19664,9 @@ Drei praktische Konsequenzen:
>
> **Worum geht es?** Um zwei Schwächen des Markowitz-Modells: Es unterschätzt Extremverluste und ignoriert die Kosten des Umschichtens. Beide lassen sich mit konvexen Mitteln beheben.
>
> **Voraussetzungen:** [Kapitel 19](#kap-markowitz), [Kapitel 5](#kap-lp) ([LP](#gloss:lineare-programmierung-lp){.glossar-link}-Formulierungen).
> **Voraussetzungen:** [Kapitel 19](#kap-markowitz), [Kapitel 5](#kap-lp) ([LP (Lineare Programmierung)](#gloss:lineare-programmierung-lp){.glossar-link}-Formulierungen).
>
> **Danach können Sie:** [VaR](#gloss:value-at-risk-var){.glossar-link} und [CVaR](#gloss:conditional-value-at-risk-cvar){.glossar-link} unterscheiden, den CVaR nach Rockafellar/Uryasev als lineares Programm formulieren, Turnover über die $L_1$-Norm bestrafen — und begründen, warum VaR-Kennzahlen nicht über Einheiten addiert werden dürfen.
> **Danach können Sie:** [VaR (Value at Risk)](#gloss:value-at-risk-var){.glossar-link} und [CVaR (Conditional Value at Risk)](#gloss:conditional-value-at-risk-cvar){.glossar-link} unterscheiden, den CVaR nach Rockafellar/Uryasev als lineares Programm formulieren, Turnover über die $L_1$-Norm bestrafen — und begründen, warum VaR-Kennzahlen nicht über Einheiten addiert werden dürfen.
>
> **Zeitbedarf:** ca. 5 Stunden.
>
@ -20217,7 +20217,7 @@ if __name__ == "__main__":
> risiko = cp.norm2(L.T @ w) # = sqrt(w' sigma w)
> ```
>
> und **nicht** als das Naheliegende, `cp.sqrt(cp.quad_form(w, sigma))`. Der naheliegende Ausdruck ist nicht [DCP](#gloss:dcp-disciplined-convex-programming){.glossar-link} und wird von CVXPY mit einem `DCPError` abgelehnt: `cp.sqrt` ist konkav und verlangt deshalb ein **konkaves** Argument, `quad_form` ist aber konvex. Die Regel wird verletzt, obwohl die Funktion`\index{Konvexität!Funktion}`{=latex} als ganze mathematisch völlig harmlos ist — $\sqrt{w^\top \Sigma w}$ ist konvex, DCP kann es nur nicht *sehen*.
> und **nicht** als das Naheliegende, `cp.sqrt(cp.quad_form(w, sigma))`. Der naheliegende Ausdruck ist nicht [DCP (Disciplined Convex Programming)](#gloss:dcp-disciplined-convex-programming){.glossar-link} und wird von CVXPY mit einem `DCPError` abgelehnt: `cp.sqrt` ist konkav und verlangt deshalb ein **konkaves** Argument, `quad_form` ist aber konvex. Die Regel wird verletzt, obwohl die Funktion`\index{Konvexität!Funktion}`{=latex} als ganze mathematisch völlig harmlos ist — $\sqrt{w^\top \Sigma w}$ ist konvex, DCP kann es nur nicht *sehen*.
>
> Wichtig ist die Fehlerdiagnose dahinter, weil sie leicht in die Irre geht: `cp.psd_wrap(sigma)` sieht nach der Lösung aus und ist keine. Es unterdrückt die **numerische** Beanstandung, dass $\Sigma$ nicht als positiv semidefinit erkannt wird — gegen die **strukturelle** Regelverletzung im Aufbau hilft es nicht.
>
@ -21256,7 +21256,7 @@ Sechs Kapitel, zwei Branchen, die sich für unvergleichbar halten. Die Werkstatt
| --- | --- | --- |
| „Planen mit der Prognose ist gut genug." | Der Erwartungswert-Plan kostet **149 % mehr** (874 870 € statt 351 356 €) und wirft in **28 von 40** Szenarien Last ab | [Kapitel 17](#kap-supplychain) |
| „Dann sparen wir eben beim Brennstoff." | Genau das tut er: 12 725 € gespart, **536 239 €** Lastabwurf bezahlt — das 42-fache. Die Anfahrkosten sind in beiden Plänen gleich | [Kapitel 17](#kap-supplychain) |
| „Der [VaR](#gloss:value-at-risk-var){.glossar-link} sagt, wie riskant es ist." | VaR **1,86 %**, [CVaR](#gloss:conditional-value-at-risk-cvar){.glossar-link} **2,99 %** — und der schlechteste Tag der Stichprobe (**23,0 %**) ändert am VaR **nichts** | [Kapitel 20](#kap-cvar) |
| „Der [VaR (Value at Risk)](#gloss:value-at-risk-var){.glossar-link} sagt, wie riskant es ist." | VaR **1,86 %**, [CVaR (Conditional Value at Risk)](#gloss:conditional-value-at-risk-cvar){.glossar-link} **2,99 %** — und der schlechteste Tag der Stichprobe (**23,0 %**) ändert am VaR **nichts** | [Kapitel 20](#kap-cvar) |
| „Die [Kovarianzmatrix](#gloss:kovarianzmatrix){.glossar-link}`\index{Kovarianzmatrix}`{=latex} ist eine Eingabe wie jede andere." | Aus kurzen Reihen geschätzt ist sie schlecht konditioniert; die Optimierung setzt dann auf Schätzrauschen | [Kapitel 18](#kap-finanzdaten) |
## Drei Fehler, die dieser Teil verhindert
@ -21355,7 +21355,7 @@ Nach diesem Kapitel können Sie …
6. … die Architektur einer produktionsreifen OR-Plattform skizzieren.
7. … eine **modellunabhängige Abnahmeprüfung** schreiben, die eine Lösung gegen die Anforderungen prüft statt gegen das Modell.
8. … Status, Gap und Zeitausschöpfung protokollieren und begründen, warum eine konstante Laufzeit bei Zeitlimit ein Warnsignal ist.
9. … ein Modell in Domänenschicht, Modellbauer und Lösungs-[DTO](#gloss:dto-data-transfer-object){.glossar-link} trennen — und begründen, warum sich das nicht wegen des Solverwechsels lohnt, sondern wegen der Prüfbarkeit.
9. … ein Modell in Domänenschicht, Modellbauer und Lösungs-[DTO (Data Transfer Object)](#gloss:dto-data-transfer-object){.glossar-link} trennen — und begründen, warum sich das nicht wegen des Solverwechsels lohnt, sondern wegen der Prüfbarkeit.
10. … die Statuswerte verschiedener Solverbibliotheken auf eine gemeinsame Sprache abbilden.
---
@ -21633,7 +21633,7 @@ Ausführlich in [Kapitel 21](#kap-handelsmaschine) behandelt. Die Kurzfassung: B
### Falle 5 — Laufzeitexplosion`\index{Laufzeitexplosion (Fehlerbild)}`{=latex}
Exakte Optimalität kann bei [MILP](#gloss:gemischt-ganzzahlige-optimierung-milp){.glossar-link} oder [CP-SAT](#gloss:cp-sat){.glossar-link}`\index{CP-SAT}`{=latex} Minuten bis Stunden dauern — und die Laufzeit wächst nicht linear mit der Problemgröße.
Exakte Optimalität kann bei [MILP (Gemischt-ganzzahlige Optimierung)](#gloss:gemischt-ganzzahlige-optimierung-milp){.glossar-link} oder [CP-SAT](#gloss:cp-sat){.glossar-link}`\index{CP-SAT}`{=latex} Minuten bis Stunden dauern — und die Laufzeit wächst nicht linear mit der Problemgröße.
| Einsatzszenario | Empfohlenes Zeitlimit | Akzeptabler [MIP-Gap](#gloss:mip-gap){.glossar-link}`\index{MIP-Gap}`{=latex} |
| --- | --- | --- |
@ -22072,7 +22072,7 @@ aus.
### Drei Befunde, und keiner steht im Solverergebnis
**Erstens: bindend heißt nicht teuer.** Fünf Bedingungen binden, aber „Lackierbudget Schicht 2“ tut es mit einem Schattenpreis von **0,00 €**. Sie berührt den Plan, ohne ihn zu verteuern — wer sie nachverhandelt, gewinnt nichts. Das ist derselbe Unterschied, den `Erklaerbarkeit.py` oben an einer einzelnen Zuweisung zeigt, hier im Dualwert eines [LP](#gloss:lineare-programmierung-lp){.glossar-link}.
**Erstens: bindend heißt nicht teuer.** Fünf Bedingungen binden, aber „Lackierbudget Schicht 2“ tut es mit einem Schattenpreis von **0,00 €**. Sie berührt den Plan, ohne ihn zu verteuern — wer sie nachverhandelt, gewinnt nichts. Das ist derselbe Unterschied, den `Erklaerbarkeit.py` oben an einer einzelnen Zuweisung zeigt, hier im Dualwert eines [LP (Lineare Programmierung)](#gloss:lineare-programmierung-lp){.glossar-link}.
**Zweitens: Der Schattenpreis ist eine Momentaufnahme.** Er gilt für die **nächste** Einheit. Ein Planer kauft aber keine Einheit, sondern eine Schicht. Für die Lackiererei verspricht die Hochrechnung $4{,}00 \cdot 30 = 120$ €; gemessen kommen **60 €**. Der Preis von 4,00 € gilt exakt bis **+15 Stunden**, danach begrenzt etwas anderes — **die zweite Hälfte der Sonderschicht wäre bezahlt und wirkungslos.**
@ -22162,7 +22162,7 @@ zeigt nach innen auf die Domäne, und die Domäne zeigt auf nichts. Erzeugt von
Der unscheinbarste, aber wirksamste Teil ist die Statusübersetzung. Dieselbe Aussage heißt in den fünf im Buch verwendeten Bibliotheken:
| Bedeutung | pywraplp | [CP](#gloss:constraint-programming-cp){.glossar-link}-[SAT](#gloss:sat-boolean-satisfiability){.glossar-link} | HiGHS`\index{HiGHS}`{=latex} | [SciPy](#gloss:scipy){.glossar-link} | CVXPY`\index{CVXPY}`{=latex} |
| Bedeutung | pywraplp | [CP (Constraint Programming)](#gloss:constraint-programming-cp){.glossar-link}-[SAT (Boolean Satisfiability)](#gloss:sat-boolean-satisfiability){.glossar-link} | HiGHS`\index{HiGHS}`{=latex} | [SciPy](#gloss:scipy){.glossar-link} | CVXPY`\index{CVXPY}`{=latex} |
| --- | --- | --- | --- | --- | --- |
| beweisbar optimal | `Solver.OPTIMAL` | `cp_model.OPTIMAL` | `"Optimal"` | `status == 0` | `"optimal"` |
| zulässig, nicht bewiesen | `Solver.FEASIBLE` | `cp_model.FEASIBLE` | `"Time limit reached"` | — | `"optimal_inaccurate"` |
@ -23615,7 +23615,7 @@ sichtbar wird, und gibt Zeit zum Handeln.
> AssertionError: Plan [31. 48.] braucht [141. 234.], verfuegbar sind [140. 232.]
> ```
**Und jetzt der Punkt.** Der Solver hat richtig gerechnet: 30,67 Tische und 48 Stühle sind das Optimum des [LP](#gloss:lineare-programmierung-lp){.glossar-link}. Das Runden hat den Plan kaputt gemacht — 31 Tische brauchen eine Montagestunde mehr, als es gibt. Ohne die drei Zeilen wäre dieser Plan in die Fertigung gegangen, und dort hätte am Monatsende eine Stunde gefehlt, die niemand einer Zeile Python zugeordnet hätte.
**Und jetzt der Punkt.** Der Solver hat richtig gerechnet: 30,67 Tische und 48 Stühle sind das Optimum des [LP (Lineare Programmierung)](#gloss:lineare-programmierung-lp){.glossar-link}. Das Runden hat den Plan kaputt gemacht — 31 Tische brauchen eine Montagestunde mehr, als es gibt. Ohne die drei Zeilen wäre dieser Plan in die Fertigung gegangen, und dort hätte am Monatsende eine Stunde gefehlt, die niemand einer Zeile Python zugeordnet hätte.
Bemerkenswert ist, **was** der Test prüft. Er prüft nicht, ob 30,67 das Optimum ist — das könnte er gar nicht, dafür bräuchte er einen zweiten Solver. Er prüft die Eigenschaft, die jede brauchbare Lösung haben muss: *Sie hält die Kapazität ein.* Diese Verschiebung — **von der Frage nach dem richtigen Wert zur Frage nach den notwendigen Eigenschaften** — ist der Schlüssel zum ganzen Kapitel.
@ -24562,7 +24562,7 @@ Die zweite unbequeme Zahl steht ganz rechts: **[CVXPY](#gloss:cvxpy){.glossar-li
> **⚠️ Was diese Tabelle nicht sagt**
>
> Sie sagt **nicht** „ortools ist langsamer als scipy". Gemessen wurde *ein* Problemtyp in *einer* Formulierung auf *einer* Maschine. Ein [MILP](#gloss:gemischt-ganzzahlige-optimierung-milp){.glossar-link} statt eines LP, eine andere Modellierung desselben Problems oder ein anderer Rechner können die Reihenfolge umdrehen — und bei MILPs tun sie es regelmäßig.
> Sie sagt **nicht** „ortools ist langsamer als scipy". Gemessen wurde *ein* Problemtyp in *einer* Formulierung auf *einer* Maschine. Ein [MILP (Gemischt-ganzzahlige Optimierung)](#gloss:gemischt-ganzzahlige-optimierung-milp){.glossar-link} statt eines LP, eine andere Modellierung desselben Problems oder ein anderer Rechner können die Reihenfolge umdrehen — und bei MILPs tun sie es regelmäßig.
>
> Übertragbar ist der **Trend**, nicht der Absolutwert: dass der Aufbauanteil mit der Größe wächst, dass CVXPY einen konstanten Speichersockel hat. Der Zweck des Programms ist, dass Sie es auf Ihrer Maschine mit Ihrem Problem laufen lassen.
@ -24987,13 +24987,13 @@ Das zugehoerige Dockerfile ist kurz genug, um es ganz zu zeigen:
>
> **1. Das Domänenmodell ist das API-Schema.** Der [Parameter](#gloss:parameter){.glossar-link} heißt `problem: Produktionsproblem` — mehr steht nicht da. FastAPI validiert die Anfrage damit gegen dieselben Pydantic-Regeln wie der Excel-Import aus [Kapitel 1](#kap-einfuehrung) und antwortet bei Unsinn mit `422`, **bevor** ein Solver startet. Die drei abgewiesenen Anfragen im Selbsttest sind genau die drei Fälle, die `or_kern.py` schon beim Einlesen abfängt.
>
> **2. Die Antwort enthält Status und Gap, nicht nur Zahlen.** Ein Aufrufer, der nur die Mengen bekommt, kann nicht unterscheiden, ob er ein bewiesenes Optimum oder einen Zeitlimit-Abbruch in der Hand hält. Das `Loesung`-Objekt geht deshalb vollständig durch die Schnittstelle — dasselbe [DTO](#gloss:dto-data-transfer-object){.glossar-link}, das in [Abschnitt 22.7](#sec:praxisfallen-solverwechsel) schon eine Prozessgrenze überlebt hat.
> **2. Die Antwort enthält Status und Gap, nicht nur Zahlen.** Ein Aufrufer, der nur die Mengen bekommt, kann nicht unterscheiden, ob er ein bewiesenes Optimum oder einen Zeitlimit-Abbruch in der Hand hält. Das `Loesung`-Objekt geht deshalb vollständig durch die Schnittstelle — dasselbe [DTO (Data Transfer Object)](#gloss:dto-data-transfer-object){.glossar-link}, das in [Abschnitt 22.7](#sec:praxisfallen-solverwechsel) schon eine Prozessgrenze überlebt hat.
>
> **3. Die Abnahmeprüfung läuft auch hier.** `pruefe_loesung()` steht im Arbeiter, nicht nur im Skript. Ein Dienst ohne sie liefert Fehler schneller aus, als ein Mensch sie finden könnte.
### Threads oder Prozesse? Eine Messung, keine Meinung
Punkt 6 des Selbsttests misst, ob vier Solverläufe in Threads sich überlappen. Das Ergebnis ist ein Faktor von rund 3,5 bei vier Threads: **OR-Tools rechnet in C++ und gibt den [GIL](#gloss:gil-global-interpreter-lock){.glossar-link} während `Solve()` frei.** Ein Threadpool genügt also, es braucht keine eigenen Prozesse.
Punkt 6 des Selbsttests misst, ob vier Solverläufe in Threads sich überlappen. Das Ergebnis ist ein Faktor von rund 3,5 bei vier Threads: **OR-Tools rechnet in C++ und gibt den [GIL (Global Interpreter Lock)](#gloss:gil-global-interpreter-lock){.glossar-link} während `Solve()` frei.** Ein Threadpool genügt also, es braucht keine eigenen Prozesse.
Das gilt aber nicht allgemein. Eine in reinem Python geschriebene Heuristik ([Kapitel 9](#kap-metaheuristiken)) hält den GIL die ganze Zeit — für sie braucht derselbe Dienst einen `ProcessPoolExecutor`. Die Entscheidung gehört gemessen, nicht angenommen.
@ -25193,7 +25193,7 @@ Halten Sie sich an diese Reihenfolge — sie ist aus vielen gescheiterten und ei
* Variablen: $x_{p,t,s} \in \{0,1\}$ — Person, Tag, Schicht.
* Hart: Mindestbesetzung je Schicht **und** Qualifikationsmix (mindestens eine examinierte Kraft); nach Nachtschicht ≥ 2 freie Tage; höchstens 6 Arbeitstage in Folge; monatliche Sollstunden ± 10 %.
* Weich: Wunschfrei, gleichmäßige Wochenendverteilung, ungeteilte Dienste, stabile Schichtfolgen (nicht FrühNachtFrüh).
* Solver: [CP](#gloss:constraint-programming-cp){.glossar-link}-[SAT](#gloss:sat-boolean-satisfiability){.glossar-link} mit Intervall- und Cumulative-Constraints.
* Solver: [CP (Constraint Programming)](#gloss:constraint-programming-cp){.glossar-link}-[SAT (Boolean Satisfiability)](#gloss:sat-boolean-satisfiability){.glossar-link} mit Intervall- und Cumulative-Constraints.
**Abnahmekriterien.**
- [ ] Alle gesetzlichen Regeln nachweislich eingehalten (per `assert` geprüft).
@ -25298,7 +25298,7 @@ Halten Sie sich an diese Reihenfolge — sie ist aus vielen gescheiterten und ei
**Ausgangslage.** Für ein bestehendes Portfolio soll ein monatlicher Risikobericht entstehen.
**Inhalte des Berichts.**
* [VaR](#gloss:value-at-risk-var){.glossar-link} und [CVaR](#gloss:conditional-value-at-risk-cvar){.glossar-link} auf 95 % und 99 %, historisch **und** Monte-Carlo-simuliert.
* [VaR (Value at Risk)](#gloss:value-at-risk-var){.glossar-link} und [CVaR (Conditional Value at Risk)](#gloss:conditional-value-at-risk-cvar){.glossar-link} auf 95 % und 99 %, historisch **und** Monte-Carlo-simuliert.
* Risikobeiträge je Position (*marginal CVaR*): Wer treibt das Risiko?
* Stresstests: Was passiert bei 20 % Aktienmarkt, +200 Basispunkten Zins, Korrelationsanstieg auf 0,9?
* Historische Szenarien nachspielen (2008, März 2020).
@ -25320,7 +25320,7 @@ Halten Sie sich an diese Reihenfolge — sie ist aus vielen gescheiterten und ei
**Ausgangslage.** P3 hat funktioniert — mit 30 Kunden. Der Auftraggeber kommt mit 400 zurück, und derselbe Code liefert nach zwanzig Minuten noch keine Lösung. Das ist keine Panne, sondern der erwartbare Umschlagpunkt.
**Modellskizze.** Zwei Verfahren am **selben** Problem, verglichen unter **gleichem Zeitbudget**:
* Exakt: [MILP](#gloss:gemischt-ganzzahlige-optimierung-milp){.glossar-link} oder CP-SAT wie in P3, mit Zeitlimit und protokolliertem Gap.
* Exakt: [MILP (Gemischt-ganzzahlige Optimierung)](#gloss:gemischt-ganzzahlige-optimierung-milp){.glossar-link} oder CP-SAT wie in P3, mit Zeitlimit und protokolliertem Gap.
* Heuristisch: Startlösung mit einer Faustregel, dann Verbesserung durch Simulated Annealing oder Large Neighborhood Search ([Kapitel 9](#kap-metaheuristiken)).
* Messgröße ist nicht „wer gewinnt", sondern **ab welcher Instanzgröße** sich das Blatt wendet.
@ -25390,7 +25390,7 @@ Halten Sie sich an diese Reihenfolge — sie ist aus vielen gescheiterten und ei
| Trainingsplan eines Sportvereins (Hallen, Trainer, Altersgruppen) | CP-SAT | [Kapitel 7](#kap-cpsat) |
| Budgetaufteilung auf Projekte mit Abhängigkeiten | MILP | [Kapitel 6](#kap-milp) |
| Schnittoptimierung für Zuschnitt (Holz, Blech, Stoff) | MILP / Spaltengenerierung | [Kapitel 10](#kap-dekomposition) |
| Speiseplan unter Nährwert- und Budgetgrenzen | [LP](#gloss:lineare-programmierung-lp){.glossar-link} | [Kapitel 5](#kap-lp) |
| Speiseplan unter Nährwert- und Budgetgrenzen | [LP (Lineare Programmierung)](#gloss:lineare-programmierung-lp){.glossar-link} | [Kapitel 5](#kap-lp) |
| Prüfungsplanung (keine Kollisionen, Erholungspausen) | CP-SAT | [Kapitel 7](#kap-cpsat) |
| Ladeplanung für E-Fahrzeugflotte (Lastspitzen vermeiden) | MILP + Cumulative | [Kapitel 6](#kap-milp), [Kapitel 7](#kap-cpsat) |
| Bewässerungsplan im Kleingarten (Wasser, Wetterprognose) | Stochastisch | [Kapitel 12](#kap-unsicherheit) |
@ -25525,7 +25525,7 @@ Für $\mathbf{P}_2$ ergibt sich eine PSD-Matrix mit Korrelation exakt $1{,}0$
### Finde den Denkfehler — Die unauffällige Transposition
(a) **Warum nichts auffällt.** $\mathbf{A}$ ist quadratisch, also passen die Dimensionen auch transponiert. [NumPy](#gloss:numpy){.glossar-link} prüft Formen, nicht Bedeutungen; der Solver bekommt ein vollkommen zulässiges [LP](#gloss:lineare-programmierung-lp){.glossar-link} vorgelegt und löst es korrekt — nur eben ein **anderes**. Eine Transposition ist genau dann gefährlich, wenn sie folgenlos *aussieht*: Wäre die Matrix $2 \times 3$ gewesen, hätte NumPy sofort einen Dimensionsfehler geworfen.
(a) **Warum nichts auffällt.** $\mathbf{A}$ ist quadratisch, also passen die Dimensionen auch transponiert. [NumPy](#gloss:numpy){.glossar-link} prüft Formen, nicht Bedeutungen; der Solver bekommt ein vollkommen zulässiges [LP (Lineare Programmierung)](#gloss:lineare-programmierung-lp){.glossar-link} vorgelegt und löst es korrekt — nur eben ein **anderes**. Eine Transposition ist genau dann gefährlich, wenn sie folgenlos *aussieht*: Wäre die Matrix $2 \times 3$ gewesen, hätte NumPy sofort einen Dimensionsfehler geworfen.
(b) **Der Plan an den echten Restriktionen.** Mit $\mathbf{A} = \begin{pmatrix} 1 & 2 \\ 3 & 1\end{pmatrix}$ und $\mathbf{x} = (5{,}6;\ 0{,}8)$:
@ -25565,7 +25565,7 @@ Vorbeugend hilft außerdem, Matrizen nie positionsweise abzutippen, sondern übe
## A.3 Lösungen zu Kapitel „Das Python-Ökosystem für OR — Solver, Bindings und Modellierungsschichten“ {#sec:loesungen-oekosystem}
**3.1 — Solverwahl.** (a) [CP-SAT](#gloss:cp-sat){.glossar-link}`\index{CP-SAT}`{=latex} (diskrete Zuordnung mit Zeitfenstern). (b) `scipy.optimize.linprog` (klassisches Mischungs-LP, klein). (c) [CVXPY](#gloss:cvxpy){.glossar-link}`\index{CVXPY}`{=latex} (konvexes [QP](#gloss:quadratische-programmierung-qp){.glossar-link}). (d) [MIQP](#gloss:miqp){.glossar-link} — CVXPY mit Binärvariablen und MIQP-fähigem Solver, oder Heuristik. (e) [MILP](#gloss:gemischt-ganzzahlige-optimierung-milp){.glossar-link} über `highspy` oder [CP](#gloss:constraint-programming-cp){.glossar-link}-[SAT](#gloss:sat-boolean-satisfiability){.glossar-link} (Standortproblem mit Fixkosten). (f) `scipy.optimize.minimize` mit Multistart (nicht konvex).
**3.1 — Solverwahl.** (a) [CP-SAT](#gloss:cp-sat){.glossar-link}`\index{CP-SAT}`{=latex} (diskrete Zuordnung mit Zeitfenstern). (b) `scipy.optimize.linprog` (klassisches Mischungs-LP, klein). (c) [CVXPY](#gloss:cvxpy){.glossar-link}`\index{CVXPY}`{=latex} (konvexes [QP (Quadratische Programmierung)](#gloss:quadratische-programmierung-qp){.glossar-link}). (d) [MIQP](#gloss:miqp){.glossar-link} — CVXPY mit Binärvariablen und MIQP-fähigem Solver, oder Heuristik. (e) [MILP (Gemischt-ganzzahlige Optimierung)](#gloss:gemischt-ganzzahlige-optimierung-milp){.glossar-link} über `highspy` oder [CP (Constraint Programming)](#gloss:constraint-programming-cp){.glossar-link}-[SAT (Boolean Satisfiability)](#gloss:sat-boolean-satisfiability){.glossar-link} (Standortproblem mit Fixkosten). (f) `scipy.optimize.minimize` mit Multistart (nicht konvex).
**3.2 — Bäckerei viermal.** Alle vier müssen $Z = 448$ (ganzzahlig) bzw. $450$ (kontinuierlich) liefern. Denken Sie an die Prozesstrennung, falls `ortools` und `highspy` kollidieren.
@ -25957,9 +25957,9 @@ Beachten Sie, dass Werk 3 seine günstigste Verbindung (L4 zu 5) voll ausschöpf
**8.5 — Engpass finden.** Die Dualwerte der Kapazitätsschranken (`res.upper.marginals` bei `linprog`) zeigen es direkt; alternativ jede Kapazität einzeln um 1 erhöhen und neu rechnen. Im Beispiel ist die Kante `Werk_A → Umschlag` der Engpass (voll ausgelastet, günstigster Weg).
**8.6 — [VRP](#gloss:vehicle-routing-problem-vrp){.glossar-link} variieren.** (a) Mit 3 Fahrzeugen werden die Touren länger, die Gesamtfahrzeit steigt leicht, die Auslastung deutlich. (b) Unlösbar, sobald $\text{Kapazität} \times \text{Fahrzeuge} < \text{Gesamtbedarf}$ (hier: bei 3 Fahrzeugen à 10 sind 30 < 37 → unlösbar) **oder** wenn Zeitfenster nicht mehr eingehalten werden können. (c) 1 s liefert meist eine brauchbare, 30 s eine spürbar bessere Lösung — die [Metaheuristik](#gloss:metaheuristik){.glossar-link}`\index{Metaheuristik}`{=latex} verbessert kontinuierlich. (d) Doppelte Servicezeit kann Zeitfenster verletzen → möglicherweise unlösbar.
**8.6 — [VRP (Vehicle Routing Problem)](#gloss:vehicle-routing-problem-vrp){.glossar-link} variieren.** (a) Mit 3 Fahrzeugen werden die Touren länger, die Gesamtfahrzeit steigt leicht, die Auslastung deutlich. (b) Unlösbar, sobald $\text{Kapazität} \times \text{Fahrzeuge} < \text{Gesamtbedarf}$ (hier: bei 3 Fahrzeugen à 10 sind 30 < 37 → unlösbar) **oder** wenn Zeitfenster nicht mehr eingehalten werden können. (c) 1 s liefert meist eine brauchbare, 30 s eine spürbar bessere Lösung — die [Metaheuristik](#gloss:metaheuristik){.glossar-link}`\index{Metaheuristik}`{=latex} verbessert kontinuierlich. (d) Doppelte Servicezeit kann Zeitfenster verletzen → möglicherweise unlösbar.
**8.7 — [TSP](#gloss:tsp-traveling-salesperson-problem){.glossar-link} mit MTZ.** Erwartetes Ergebnis: Bei 8 Städten löst das MILP in Sekunden. Ab etwa 1215 Städten wird die schwache MTZ-Relaxation zum Problem, und die Laufzeit steigt stark — während [OR-Tools](#gloss:or-tools){.glossar-link}`\index{OR-Tools}`{=latex} weiterhin in Sekundenbruchteilen sehr gute Touren liefert.
**8.7 — [TSP (Traveling Salesperson Problem)](#gloss:tsp-traveling-salesperson-problem){.glossar-link} mit MTZ.** Erwartetes Ergebnis: Bei 8 Städten löst das MILP in Sekunden. Ab etwa 1215 Städten wird die schwache MTZ-Relaxation zum Problem, und die Laufzeit steigt stark — während [OR-Tools](#gloss:or-tools){.glossar-link}`\index{OR-Tools}`{=latex} weiterhin in Sekundenbruchteilen sehr gute Touren liefert.
### Finde den Denkfehler — Die vergessene Dimension
@ -26033,7 +26033,7 @@ Alles, was der Kollege sagt, stimmt. Der Fehler liegt darin, was er *nicht* sagt
`Metaheuristik_vs_Exakt.py` liefert die fehlende Zahl in der Spalte *Schranke*: **1 768 Minuten**. Der Abstand der vorgestellten Lösung zum Bestmöglichen beträgt also bis zu 25 %, nicht 0 %. In derselben Nacht, in der 640 Stunden gefeiert werden, liegen möglicherweise weitere 2 000 Stunden ungenutzt herum.
Die Konsequenz ist keine Absage an das Projekt — 6,2 % sind echt und werden verdient. Die Konsequenz ist eine ehrliche Fortschreibung: „Wir heben 6,2 % und wissen, dass bis zu einem Viertel noch offen ist. Der nächste Schritt ist [LNS](#gloss:large-neighborhood-search-lns){.glossar-link}.“ Wer die Schranke verschweigt, erklärt das Projekt für abgeschlossen und lässt den größeren Teil liegen.
Die Konsequenz ist keine Absage an das Projekt — 6,2 % sind echt und werden verdient. Die Konsequenz ist eine ehrliche Fortschreibung: „Wir heben 6,2 % und wissen, dass bis zu einem Viertel noch offen ist. Der nächste Schritt ist [LNS (Large Neighborhood Search)](#gloss:large-neighborhood-search-lns){.glossar-link}.“ Wer die Schranke verschweigt, erklärt das Projekt für abgeschlossen und lässt den größeren Teil liegen.
> Dasselbe Muster in anderer Verkleidung: Kapitel Handelsmaschine, `Data_Snooping.py` — dort fehlt nicht die Schranke, sondern die Zahl der Versuche. Beide Male macht eine weggelassene Kennzahl aus einem korrekten Ergebnis eine irreführende Aussage.
@ -26128,7 +26128,7 @@ Die Schranke sagt: *Weniger als 73 Rollen sind unmöglich.* Sie sagt **nicht**:
**11.2 — [Komplementärer Schlupf](#gloss:komplementaerer-schlupf){.glossar-link}`\index{Komplementärer Schlupf}`{=latex}.** Ja, verträglich: $\lambda_i w_i = 0$ gilt für alle $i$ ($w_2 = 0$ mit $\lambda_2 > 0$; die anderen mit $\lambda = 0$). $\lambda_2 = 0{,}03$ bedeutet: Würde man Titel 2 zwingen, ein kleines positives Gewicht zu tragen, verschlechterte sich der Zielwert um 0,03 je Einheit — die Nichtnegativitätsschranke ist dort **bindend**.
**11.3 — [KKT](#gloss:karush-kuhn-tucker-bedingungen-kkt){.glossar-link} von Hand.** $\mathcal{L} = x_1^2 + x_2^2 + \lambda(4 - x_1 - x_2)$. Stationarität: $2x_1 = \lambda$, $2x_2 = \lambda$ → $x_1 = x_2$. Bindend ($\lambda > 0$): $x_1 + x_2 = 4$ → $x_1 = x_2 = 2$, $\lambda = 4$. Prüfung: $\lambda = 4 > 0$ ✓, $f = 8$. **Interpretation:** Würde die Forderung auf $\ge 4{,}1$ steigen, stiege $f$ um etwa $4 \cdot 0{,}1 = 0{,}4$. Probe: $2\cdot(2{,}05)^2 = 8{,}405$ ✓.
**11.3 — [KKT (Karush-Kuhn-Tucker-Bedingungen)](#gloss:karush-kuhn-tucker-bedingungen-kkt){.glossar-link} von Hand.** $\mathcal{L} = x_1^2 + x_2^2 + \lambda(4 - x_1 - x_2)$. Stationarität: $2x_1 = \lambda$, $2x_2 = \lambda$ → $x_1 = x_2$. Bindend ($\lambda > 0$): $x_1 + x_2 = 4$ → $x_1 = x_2 = 2$, $\lambda = 4$. Prüfung: $\lambda = 4 > 0$ ✓, $f = 8$. **Interpretation:** Würde die Forderung auf $\ge 4{,}1$ steigen, stiege $f$ um etwa $4 \cdot 0{,}1 = 0{,}4$. Probe: $2\cdot(2{,}05)^2 = 8{,}405$ ✓.
**11.4 — Unmögliche Korrelationsmatrix.** Eigenwerte $\approx (-0{,}62;\ 1{,}0;\ 2{,}62)$ → **nicht PSD**, also unmöglich. Anschaulich: Wenn A stark **positiv** mit B korreliert und B stark positiv mit C, kann A nicht gleichzeitig stark **negativ** mit C korrelieren — Korrelation ist eingeschränkt transitiv. Formal: $\rho_{AC} \ge \rho_{AB}\rho_{BC} - \sqrt{(1-\rho_{AB}^2)(1-\rho_{BC}^2)} = 0{,}81 - 0{,}19 = 0{,}62$; verlangt waren $-0{,}9$.
@ -26198,7 +26198,7 @@ Der Ausweg auf `scipy` hat das Warnsystem umgangen, nicht das Problem gelöst. R
**12.3 — Zweistufig rechnen.** (a) Mit Spot = 60: Ableitung bei $x \in (100,250)$: $40 - 60\cdot0{,}5 + 5\cdot0{,}5 = 40-30+2{,}5 = +12{,}5 > 0$ → Kapazität **senken**. Bei $x < 100$: $40 - 60 = -20 < 0$ → erhöhen. Optimum daher $x^* = 100$. (b) Billige Nachbesserung macht Vorhalten unattraktiv. (c) Bei $x = 225$ optimal müsste die Ableitung dort das Vorzeichen wechseln — das ist bei diskreten Szenarien nur zufällig der Fall; der Mittelwert ist nur bei symmetrischen Kosten und stetiger Verteilung optimal.
**12.4 — [EVPI](#gloss:evpi-expected-value-of-perfect-information){.glossar-link} interpretieren.** Selbst eine **perfekte** Prognose wäre nur 8 400 € pro Jahr wert. Eine Lösung für 15 000 € kann sich also **niemals** rechnen — unabhängig von ihrer Güte. Argument: „Der theoretische Maximalnutzen liegt unter dem Preis.“
**12.4 — [EVPI (Expected Value of Perfect Information)](#gloss:evpi-expected-value-of-perfect-information){.glossar-link} interpretieren.** Selbst eine **perfekte** Prognose wäre nur 8 400 € pro Jahr wert. Eine Lösung für 15 000 € kann sich also **niemals** rechnen — unabhängig von ihrer Güte. Argument: „Der theoretische Maximalnutzen liegt unter dem Preis.“
**12.5 — Monte-Carlo erweitern.** (a) Servicelevel 95 %: Kapazität = 95 %-Quantil des Bedarfs (ca. 485). Die Zusatzkosten gegenüber dem Kostenoptimum (180) betragen ein Vielfaches — Servicelevel ist teuer, und genau diese Zahl braucht die Geschäftsleitung für die Entscheidung. (b) `cvar = kosten[kosten >= np.quantile(kosten, 0.95)].mean()`. (c) Erwartetes Bild: Bei kleiner Kapazität ist die Kostenverteilung stark rechtsschief (seltene, teure Notzukäufe); bei großer Kapazität schmal und nach rechts verschoben.
@ -26281,7 +26281,7 @@ Und die Formulierung gegenüber dem Auftraggeber lautet nicht „der Umbau dauer
**13.3 — [Rückwärtsinduktion](#gloss:rueckwaertsinduktion){.glossar-link}`\index{Rückwärtsinduktion}`{=latex}.** Mit $C(n) = n^2 + 2n$ und 5 Einheiten in 3 Perioden ergibt sich als optimaler Pfad $2 \to 2 \to 1$ (oder eine Permutation davon) mit Gesamtkosten $8 + 8 + 3 = 19$. Alles auf einmal kostet $25 + 10 = 35$.
**13.4 — Rucksack als [DP](#gloss:dynamische-programmierung-dp){.glossar-link}.**
**13.4 — Rucksack als [DP (Dynamische Programmierung)](#gloss:dynamische-programmierung-dp){.glossar-link}.**
```python
V = np.zeros((n + 1, kapazitaet + 1))
for i in range(1, n + 1):
@ -26488,7 +26488,7 @@ Bei 40 Lieferanten hat die Kovarianzmatrix 820 zu schätzende Einträge. Wer daf
Benötigt würden: Lieferzeit-Zeitreihen je Lieferant über denselben Zeitraum, gleich getaktet. Genau daran scheitert es in der Praxis meist — die Daten liegen in Bestellvorgängen, nicht in einer Matrix.
**16.4 — [CVaR](#gloss:conditional-value-at-risk-cvar){.glossar-link} mit Ganzzahligkeit.** Man ergänzt Binärvariablen $y_j$ je Lieferant und die Kopplung $w_j \le y_j$ sowie $\sum_j y_j \le 3$. Da CVXPY gemischt-ganzzahlige Probleme unterstützt, genügt `cp.Variable(n, boolean=True)`.
**16.4 — [CVaR (Conditional Value at Risk)](#gloss:conditional-value-at-risk-cvar){.glossar-link} mit Ganzzahligkeit.** Man ergänzt Binärvariablen $y_j$ je Lieferant und die Kopplung $w_j \le y_j$ sowie $\sum_j y_j \le 3$. Da CVXPY gemischt-ganzzahlige Probleme unterstützt, genügt `cp.Variable(n, boolean=True)`.
Zu erwarten ist ein **höherer** CVaR: Der zulässige Bereich wird kleiner, und die Feinabstimmung über sechs Lieferanten fällt weg. Der Aufschlag ist der Preis der Vertragswirklichkeit — und genau die Zahl, die man dem Einkauf vorlegt, wenn dort jemand sagt, drei Lieferanten seien genug.
@ -26649,7 +26649,7 @@ Und immer: **außerhalb des Schätzzeitraums prüfen.** Ein Modell, das nur im e
### Selbsttest {#selbsttest-loesung-finanzdaten}
1. Log-Renditen sind Differenzen von Logarithmen — die addieren sich über die Zeit. Diskrete Renditen sind lineare Anteile am Kapital — die addieren sich über gewichtete Positionen.
2. Die Optimierung sucht die Richtungen kleinster geschätzter Varianz — genau jene, deren Eigenwerte am stärksten nach unten verzerrt sind. Sie optimiert dadurch in das Schätzrauschen hinein.
3. Der Rang von $\mathbf{X}^\top\mathbf{X}$ ist höchstens $T < N$ — die Matrix ist nicht invertierbar, das [GMV](#gloss:global-minimum-variance-portfolio-gmv){.glossar-link}-Problem hat unendlich viele Lösungen.
3. Der Rang von $\mathbf{X}^\top\mathbf{X}$ ist höchstens $T < N$ — die Matrix ist nicht invertierbar, das [GMV (Global Minimum Variance Portfolio)](#gloss:global-minimum-variance-portfolio-gmv){.glossar-link}-Problem hat unendlich viele Lösungen.
4. Stichprobenmatrix (unverzerrt, verrauscht) mit strukturiertem Ziel (verzerrt, stabil). $\delta$ wird analytisch so bestimmt, dass der erwartete quadratische Fehler minimal wird.
5. Skalierte Einheitsmatrix (sklearn) und Konstant-Korrelations-Ziel (LW 2003).
@ -26738,7 +26738,7 @@ Zusammen ergibt das das beobachtete Bild: 38 % Konzentration in einer Anlage, ob
## A.20 Lösungen zu Kapitel „Tail-Risiko, CVaR und Transaktionskosten`\index{Transaktionskosten}`{=latex}“ {#sec:loesungen-cvar}
**20.1 — [VaR](#gloss:value-at-risk-var){.glossar-link} und CVaR von Hand.** Sortierte Verluste: $-2{,}0; -1{,}2; -0{,}8; -0{,}4; 0{,}3; 0{,}6; 1{,}1; 2{,}1; 5{,}4; 8{,}9$. Das 80 %-Quantil ist der 8. Wert: $\text{VaR}_{80\%} = 2{,}1$. $\text{CVaR}_{80\%} = $ Mittel der schlechtesten 20 % $= (5{,}4+8{,}9)/2 = \mathbf{7{,}15}$.
**20.1 — [VaR (Value at Risk)](#gloss:value-at-risk-var){.glossar-link} und CVaR von Hand.** Sortierte Verluste: $-2{,}0; -1{,}2; -0{,}8; -0{,}4; 0{,}3; 0{,}6; 1{,}1; 2{,}1; 5{,}4; 8{,}9$. Das 80 %-Quantil ist der 8. Wert: $\text{VaR}_{80\%} = 2{,}1$. $\text{CVaR}_{80\%} = $ Mittel der schlechtesten 20 % $= (5{,}4+8{,}9)/2 = \mathbf{7{,}15}$.
**20.2 — [Subadditivität](#gloss:subadditivitaet){.glossar-link}`\index{Subadditivität}`{=latex}.** Ein Risikomaß sollte Diversifikation nie bestrafen: Das Risiko eines zusammengelegten Portfolios darf nicht größer sein als die Summe der Einzelrisiken. Wird das verletzt, hätte eine Bank einen Anreiz, Portfolios künstlich aufzuspalten, um Eigenkapitalanforderungen zu senken — ökonomisch unsinnig.
@ -27002,7 +27002,7 @@ Was geholfen hätte — drei Dinge, keines davon ein Unit-Test:
3. „Grün" heißt nur, dass kein Test fehlgeschlagen ist — das gilt auch für eine Suite aus lauter `assert True`. „Prüft etwas" heißt, dass die Tests bei einem eingebauten Fehler rot würden; genau das misst der Mutationstest.
4. Weil sonst nicht erkennbar ist, welche Hälfte die Zeit kostet. Im Kapitel gehen bei OR-Tools 78 % in den Aufbau — wer nur die Gesamtzeit sieht, wechselt den Solver und ändert damit fast nichts.
5. Weil die Rechnung Sekunden bis Minuten dauert. Eine synchrone Antwort läuft in den Timeout des Reverse Proxy und blockiert währenddessen einen Arbeiter. `202` heißt „angenommen, noch nicht fertig" — genau die richtige Aussage.
6. Ein Threadpool genügt, wenn der Solver den [GIL](#gloss:gil-global-interpreter-lock){.glossar-link} freigibt — das tun die C++-Bibliotheken (OR-Tools, HiGHS) während `Solve()`, im Kapitel mit Faktor 3,5 bei vier Threads gemessen. Eine in reinem Python geschriebene Heuristik hält den GIL; für sie braucht es Prozesse.
6. Ein Threadpool genügt, wenn der Solver den [GIL (Global Interpreter Lock)](#gloss:gil-global-interpreter-lock){.glossar-link} freigibt — das tun die C++-Bibliotheken (OR-Tools, HiGHS) während `Solve()`, im Kapitel mit Faktor 3,5 bei vier Threads gemessen. Eine in reinem Python geschriebene Heuristik hält den GIL; für sie braucht es Prozesse.
---
@ -27221,7 +27221,7 @@ for topf, grenze in BUDGETS.items():
if TOPF[i] == topf) <= grenze)
```
> 💡 **Der [Schattenpreis](#gloss:schattenpreis){.glossar-link}`\index{Schattenpreis}`{=latex} des Budgets ist die Zahl, nach der die Geschäftsführung fragt:** „Was bringt der nächste Euro?“ Bei einem **[LP](#gloss:lineare-programmierung-lp){.glossar-link}** ist er direkt ablesbar. Bei **Ganzzahligkeit gibt es ihn nicht** — die Dualwerte der [Relaxation](#gloss:relaxation){.glossar-link}`\index{Relaxation}`{=latex} sind keine gültige Antwort. Rechnen Sie stattdessen mit erhöhtem Budget neu und vergleichen Sie die Zielwerte ([Abschnitt 5.9](#sec:lp-entartung)).
> 💡 **Der [Schattenpreis](#gloss:schattenpreis){.glossar-link}`\index{Schattenpreis}`{=latex} des Budgets ist die Zahl, nach der die Geschäftsführung fragt:** „Was bringt der nächste Euro?“ Bei einem **[LP (Lineare Programmierung)](#gloss:lineare-programmierung-lp){.glossar-link}** ist er direkt ablesbar. Bei **Ganzzahligkeit gibt es ihn nicht** — die Dualwerte der [Relaxation](#gloss:relaxation){.glossar-link}`\index{Relaxation}`{=latex} sind keine gültige Antwort. Rechnen Sie stattdessen mit erhöhtem Budget neu und vergleichen Sie die Zielwerte ([Abschnitt 5.9](#sec:lp-entartung)).
> ⚠️ **Die LP-Relaxation verspricht zu viel.** Sie darf die letzte Maßnahme anteilig kaufen und liefert deshalb eine Schranke, die spürbar über dem tatsächlich Erreichbaren liegen kann. Wer sie als Prognose berichtet, verspricht Geld, das nicht kommt.
@ -27245,7 +27245,7 @@ Mit Mindestwartezeit $w$: $\text{start}_B \ge \text{ende}_A + w$.
modell.AddNoOverlap([intervall_1, intervall_2, ...])
```
In [MILP](#gloss:gemischt-ganzzahlige-optimierung-milp){.glossar-link} bräuchte man je Paar eine Disjunktion (B4) — bei $k$ Jobs sind das $\binom{k}{2}$ Konstruktionen. **Nehmen Sie hier [CP-SAT](#gloss:cp-sat){.glossar-link}`\index{CP-SAT}`{=latex}.**
In [MILP (Gemischt-ganzzahlige Optimierung)](#gloss:gemischt-ganzzahlige-optimierung-milp){.glossar-link} bräuchte man je Paar eine Disjunktion (B4) — bei $k$ Jobs sind das $\binom{k}{2}$ Konstruktionen. **Nehmen Sie hier [CP-SAT](#gloss:cp-sat){.glossar-link}`\index{CP-SAT}`{=latex}.**
### B15 — Kumulative Ressource
@ -27370,7 +27370,7 @@ $$\sum_j x_{ij} = 1\ \forall i,\qquad \sum_i x_{ij} = 1\ \forall j,\qquad x_{ij}
**MTZ (einfach, aber schwach):**`\index{MTZ-Formulierung}`{=latex} $$u_i - u_j + C x_{ij} \le C - d_j \qquad \forall i\ne j$$
**Besser in der Praxis:**`\index{Subtour!Eliminierung}`{=latex} `AddCircuit` in [CP](#gloss:constraint-programming-cp){.glossar-link}-[SAT](#gloss:sat-boolean-satisfiability){.glossar-link} oder die [Routing-Bibliothek](#gloss:routing-bibliothek){.glossar-link}`\index{Routing-Bibliothek}`{=latex} von [OR-Tools](#gloss:or-tools){.glossar-link}.
**Besser in der Praxis:**`\index{Subtour!Eliminierung}`{=latex} `AddCircuit` in [CP (Constraint Programming)](#gloss:constraint-programming-cp){.glossar-link}-[SAT (Boolean Satisfiability)](#gloss:sat-boolean-satisfiability){.glossar-link} oder die [Routing-Bibliothek](#gloss:routing-bibliothek){.glossar-link}`\index{Routing-Bibliothek}`{=latex} von [OR-Tools](#gloss:or-tools){.glossar-link}.
---
@ -27458,7 +27458,7 @@ for kunde, (frueh, spaet) in enumerate(zeitfenster):
> Nimm eine Bedingung versuchsweise heraus. Bleibt der Rest unlösbar, wurde sie nicht gebraucht: weg damit, endgültig. Wird der Rest lösbar, war sie beteiligt: sie bleibt.
Nach genau einem Durchlauf über alle $n$ Bedingungen ist die übrig gebliebene Menge`\index{Konvexität!Menge}`{=latex} **unreduzierbar** — entfernt man aus ihr irgendeine Bedingung, ist der Rest lösbar. Das ist ein *Irreducible Infeasible Subset*`\index{IIS (Irreducible Infeasible Subset)}`{=latex}, kurz [IIS](#gloss:iis-irreducible-infeasible-subset){.glossar-link}. Kommerzielle Solver bieten das als fertige Funktion`\index{Konvexität!Funktion}`{=latex} an (`computeIIS` bei [Gurobi](#gloss:gurobi){.glossar-link}`\index{Gurobi}`{=latex}, der Conflict Refiner bei CPLEX); im Open-Source-Werkzeugkasten dieses Buchs gibt es sie nicht — sie ist aber in zwanzig Zeilen selbst geschrieben, und sie kostet $n$ Aufrufe des Solvers statt $2^n$ durchprobierter Teilmengen.
Nach genau einem Durchlauf über alle $n$ Bedingungen ist die übrig gebliebene Menge`\index{Konvexität!Menge}`{=latex} **unreduzierbar** — entfernt man aus ihr irgendeine Bedingung, ist der Rest lösbar. Das ist ein *Irreducible Infeasible Subset*`\index{IIS (Irreducible Infeasible Subset)}`{=latex}, kurz [IIS (Irreducible Infeasible Subset)](#gloss:iis-irreducible-infeasible-subset){.glossar-link}. Kommerzielle Solver bieten das als fertige Funktion`\index{Konvexität!Funktion}`{=latex} an (`computeIIS` bei [Gurobi](#gloss:gurobi){.glossar-link}`\index{Gurobi}`{=latex}, der Conflict Refiner bei CPLEX); im Open-Source-Werkzeugkasten dieses Buchs gibt es sie nicht — sie ist aber in zwanzig Zeilen selbst geschrieben, und sie kostet $n$ Aufrufe des Solvers statt $2^n$ durchprobierter Teilmengen.
```python
#!/usr/bin/env python3
@ -27848,11 +27848,11 @@ print(f"Aufbau {t1-t0:.2f}s | Loesen {t2-t1:.2f}s")
```
Bei CVXPY und bei Schleifen über Szenarien ist oft der **Aufbau** der Engpass, nicht der Solver (siehe [Abschnitt 20.6](#sec:cvar-implementierung-cvar-portfolio-mit-reibung)).
**2. Big-M zu groß?** Der häufigste Grund für explodierende [MILP](#gloss:gemischt-ganzzahlige-optimierung-milp){.glossar-link}-Laufzeiten. Setzen Sie $M$ auf die kleinste gültige Schranke ([Abschnitt 6.5](#sec:milp-modellierungstricks-big-m-und-logische-bedingungen)).
**2. Big-M zu groß?** Der häufigste Grund für explodierende [MILP (Gemischt-ganzzahlige Optimierung)](#gloss:gemischt-ganzzahlige-optimierung-milp){.glossar-link}-Laufzeiten. Setzen Sie $M$ auf die kleinste gültige Schranke ([Abschnitt 6.5](#sec:milp-modellierungstricks-big-m-und-logische-bedingungen)).
**3. Symmetrie im Modell?** Identische Maschinen, austauschbare Mitarbeitende, gleichwertige Fahrzeuge — der Solver durchsucht alle Vertauschungen. Abhilfe: Ordnungsbedingungen (Muster B20).
**4. Falsche Solverfamilie?** Zuordnungsprobleme mit MILP, Routing mit [CP](#gloss:constraint-programming-cp){.glossar-link}-[SAT](#gloss:sat-boolean-satisfiability){.glossar-link} von Hand nachgebaut, konvexe Probleme mit `scipy.optimize.minimize` — jeweils Größenordnungen langsamer als das passende Werkzeug ([Abschnitt 3.6](#sec:oekosystem-wann-lohnt-sich-welche-ebene)).
**4. Falsche Solverfamilie?** Zuordnungsprobleme mit MILP, Routing mit [CP (Constraint Programming)](#gloss:constraint-programming-cp){.glossar-link}-[SAT (Boolean Satisfiability)](#gloss:sat-boolean-satisfiability){.glossar-link} von Hand nachgebaut, konvexe Probleme mit `scipy.optimize.minimize` — jeweils Größenordnungen langsamer als das passende Werkzeug ([Abschnitt 3.6](#sec:oekosystem-wann-lohnt-sich-welche-ebene)).
**5. Wird vektorisiert?**
```python
@ -27990,9 +27990,9 @@ cvxpy.error.DCPError: Problem does not follow DCP rules.
| Problematischer Ausdruck | Warum | Lösung |
| ------------------------------------------------------------------------------------------------- | -------------------------------------------- | ------------------------------------------------------------------------------- |
| `x * y` (beide Variablen) | bilinear | umformulieren oder MILP/[NLP](#gloss:nichtlineare-programmierung-nlp){.glossar-link} |
| `x * y` (beide Variablen) | bilinear | umformulieren oder MILP/[NLP (Nichtlineare Programmierung)](#gloss:nichtlineare-programmierung-nlp){.glossar-link} |
| `a / x` | nicht konvex | `cp.inv_pos(x)` bei $x>0$ |
| `cp.sqrt(cp.quad_form(w, S))` | `cp.sqrt` ist **konkav** und verlangt ein konkaves Argument — `quad_form` ist konvex. Der Ausdruck ist nie [DCP](#gloss:dcp-disciplined-convex-programming){.glossar-link}, egal wie sauber $S$ ist | Cholesky $S = LL^\top$, dann `cp.norm2(L.T @ w)`: die 2-Norm eines **affinen** Ausdrucks (siehe `CVaR_Portfolio.py`) |
| `cp.sqrt(cp.quad_form(w, S))` | `cp.sqrt` ist **konkav** und verlangt ein konkaves Argument — `quad_form` ist konvex. Der Ausdruck ist nie [DCP (Disciplined Convex Programming)](#gloss:dcp-disciplined-convex-programming){.glossar-link}, egal wie sauber $S$ ist | Cholesky $S = LL^\top$, dann `cp.norm2(L.T @ w)`: die 2-Norm eines **affinen** Ausdrucks (siehe `CVaR_Portfolio.py`) |
| `cp.quad_form(w, S)` bei numerisch unsauberem $S$ | Eigenwerte knapp unter null durch Rundung — CVXPY erkennt $S$ nicht als PSD | `cp.psd_wrap(S)`, **wenn** $S$ nachweislich PSD ist (z. B. eine Kovarianzmatrix). Behebt nur diese numerische Beanstandung, keine Regelverletzung im Aufbau |
| Quotient (z. B. [Sharpe Ratio](#gloss:sharpe-ratio){.glossar-link}`\index{Sharpe-Ratio}`{=latex}) | nicht konvex | [Korn-Transformation](#gloss:korn-transformation){.glossar-link}`\index{Korn-Transformation}`{=latex} ([Abschnitt 19.4](#sec:markowitz-das-mean-variance-modell)) |
| `cp.log(x)` maximieren | konkav — das ist **erlaubt** | in `cp.Maximize` verwenden |
@ -28083,7 +28083,7 @@ tech_indices = [0, 1, 2, 3] # SCHLECHT
$$\max\; 10x_1 + 15x_2 + 25x_3 \quad\text{u.d.N.}\quad x_1 + x_2 + 2x_3 \le 40,\;\; 2x_1 + 3x_2 + x_3 \le 50,\;\; x \ge 0$$
Damit ist jeder Schnipsel selbstprüfend: Kommt bei Ihnen etwas anderes als 530 heraus, liegt es an der Übertragung, nicht am Modell. (Die Ausnahme ist [CP-SAT](#gloss:cp-sat){.glossar-link}`\index{CP-SAT}`{=latex} — ein rein stetiges [LP](#gloss:lineare-programmierung-lp){.glossar-link} ist dort das falsche Werkzeug; die Seite zeigt stattdessen die [CP](#gloss:constraint-programming-cp){.glossar-link}-[SAT](#gloss:sat-boolean-satisfiability){.glossar-link}-eigenen Bausteine.)
Damit ist jeder Schnipsel selbstprüfend: Kommt bei Ihnen etwas anderes als 530 heraus, liegt es an der Übertragung, nicht am Modell. (Die Ausnahme ist [CP-SAT](#gloss:cp-sat){.glossar-link}`\index{CP-SAT}`{=latex} — ein rein stetiges [LP (Lineare Programmierung)](#gloss:lineare-programmierung-lp){.glossar-link} ist dort das falsche Werkzeug; die Seite zeigt stattdessen die [CP (Constraint Programming)](#gloss:constraint-programming-cp){.glossar-link}-[SAT (Boolean Satisfiability)](#gloss:sat-boolean-satisfiability){.glossar-link}-eigenen Bausteine.)
> **Was dieser Anhang *nicht* ist.** Kein Vergleich und keine Empfehlung. Welche Bibliothek für welche Aufgabe taugt, steht in [Abschnitt 3.6](#sec:oekosystem-wann-lohnt-sich-welche-ebene); denselben Fall in vier Bibliotheken *nebeneinander* zeigt `Ein_System_Vier_Ansaetze.py`, die beiden Modellierungssprachen `Modellierungsschichten.py`. Hier geht es allein ums Nachschlagen.
@ -28207,7 +28207,7 @@ else:
## D3 — OR-Tools`\index{OR-Tools}`{=latex}: `pywraplp`
**Wofür.** Bequeme algebraische Schreibweise für LP und [MILP](#gloss:gemischt-ganzzahlige-optimierung-milp){.glossar-link} mit umschaltbarem Backend (`GLOP`, `SCIP`, `CBC`, `SAT`). **Wofür nicht:** [Scheduling](#gloss:scheduling){.glossar-link} und kombinatorische Bedingungen — dafür ist CP-SAT (D4) da.
**Wofür.** Bequeme algebraische Schreibweise für LP und [MILP (Gemischt-ganzzahlige Optimierung)](#gloss:gemischt-ganzzahlige-optimierung-milp){.glossar-link} mit umschaltbarem Backend (`GLOP`, `SCIP`, `CBC`, `SAT`). **Wofür nicht:** [Scheduling](#gloss:scheduling){.glossar-link} und kombinatorische Bedingungen — dafür ist CP-SAT (D4) da.
```python
from ortools.linear_solver import pywraplp
@ -28299,7 +28299,7 @@ print(f"Laufzeit {loeser.WallTime():.3f}s, {loeser.NumBranches()} Verzweigungen"
## D5 — CVXPY`\index{CVXPY}`{=latex}
**Wofür.** Konvexe Probleme: quadratische Ziele, Normen, [CVaR](#gloss:conditional-value-at-risk-cvar){.glossar-link}, alles mit Regularisierungstermen. **Wofür nicht:** große kombinatorische Modelle — der Aufbau der Ausdrücke wird dann selbst zum Engpass.
**Wofür.** Konvexe Probleme: quadratische Ziele, Normen, [CVaR (Conditional Value at Risk)](#gloss:conditional-value-at-risk-cvar){.glossar-link}, alles mit Regularisierungstermen. **Wofür nicht:** große kombinatorische Modelle — der Aufbau der Ausdrücke wird dann selbst zum Engpass.
```python
import numpy as np
@ -28332,7 +28332,7 @@ else:
### Die drei häufigsten Stolpersteine
1. **[DCP](#gloss:dcp-disciplined-convex-programming){.glossar-link}-Regeln vor dem Lösen prüfen.** `problem.is_dcp()` und dann die einzelnen Bedingungen — das nennt die Schuldige, statt einen `DCPError` ohne Ort zu werfen ([Anhang C](#anhang-fehlerdiagnose), C8).
1. **[DCP (Disciplined Convex Programming)](#gloss:dcp-disciplined-convex-programming){.glossar-link}-Regeln vor dem Lösen prüfen.** `problem.is_dcp()` und dann die einzelnen Bedingungen — das nennt die Schuldige, statt einen `DCPError` ohne Ort zu werfen ([Anhang C](#anhang-fehlerdiagnose), C8).
2. **`OPTIMAL_INACCURATE` ist kein Erfolg.** Der Solver hat aufgegeben und meldet das leise. Diesen Fall immer eigens behandeln.
3. **Der Aufbau kann teurer sein als das Lösen.** Schleifen über Szenarien durch Vektorausdrücke ersetzen; `Parameter` statt Neuaufbau, wenn sich nur Zahlen ändern.
@ -28437,6 +28437,11 @@ Alle sechs Seiten haben denselben längsten Abschnitt: die **Statusauswertung**.
Nachschlagewerk zu allen Fachbegriffen, Abkürzungen, Algorithmen und Bibliotheken dieses Buchs. Jeder Eintrag nennt am Ende den Abschnitt, in dem der Begriff eingeführt wird — ein Klick dorthin führt in der Online-Fassung direkt zur Erklärung im Zusammenhang. Wer einen Begriff an *allen* Fundstellen sucht, benutzt das Stichwortverzeichnis.
```{=html}
<nav class="register-sprungleiste"><a href="#a">A</a> <a href="#b">B</a> <a href="#c">C</a> <a href="#d">D</a> <a href="#e">E</a> <a href="#f">F</a> <a href="#g">G</a> <a href="#h">H</a> <a href="#i">I</a> <a href="#j">J</a> <a href="#k">K</a> <a href="#l">L</a> <a href="#m">M</a> <a href="#n">N</a> <a href="#o">O</a> <a href="#p">P</a> <a href="#q">Q</a> <a href="#r">R</a> <a href="#s">S</a> <a href="#t">T</a> <a href="#u">U</a> <a href="#v">V</a> <a href="#w">W</a> <a href="#y">Y</a> <a href="#z">Z</a></nav>
```
## A
::: {#gloss:absolutbetrag}
@ -29484,7 +29489,7 @@ Frei zugängliche Fassungen sind vermerkt. Wo eine DOI angegeben ist, führt sie
* ★★★ **Wolsey, L. A. (2020):** *Integer Programming* (2. Aufl.). Wiley, Hoboken. DOI: 10.1002/9781119606475 [Ganzzahlige Optimierung] *[Branch-and-Bound](#gloss:branch-and-bound){.glossar-link}, [Branch-and-Cut](#gloss:branch-and-cut){.glossar-link}, Polyedertheorie, Formulierungsstärke. Die Begründung dafür, warum ein kleines $M$ besser ist als ein großes.*
* ★★★ **Conforti, M., Cornuéjols, G. & Zambelli, G. (2014):** *Integer Programming.* Springer, Cham. DOI: 10.1007/978-3-319-11008-0 [Ganzzahlige Optimierung] *Modernere Darstellung als Wolsey, mit ausführlicher Behandlung von Schnittebenen und totaler Unimodularität.*
* ★★ **Klotz, E. & Newman, A. M. (2013):** *Practical guidelines for solving difficult mixed integer linear programs.* In: *Surveys in Operations Research and Management Science* 18(12), S. 1832. DOI: 10.1016/j.sorms.2012.12.001 [Ganzzahlige Optimierung] *Was zu tun ist, wenn ein Modell nicht fertig rechnet — Skalierung, Formulierung, Symmetrie. Die Literaturgrundlage von [Anhang C](#anhang-fehlerdiagnose).*
* ★★ **Achterberg, T. (2009):** *[SCIP](#gloss:scip){.glossar-link}: solving constraint integer programs.* In: *Mathematical Programming Computation* 1(1), S. 141. DOI: 10.1007/s12532-008-0001-1 [[Solver](#gloss:solver){.glossar-link}: SCIP] *Beschreibt die Verbindung von [MILP](#gloss:gemischt-ganzzahlige-optimierung-milp){.glossar-link} und Constraint Programming in einem Solver.*
* ★★ **Achterberg, T. (2009):** *[SCIP](#gloss:scip){.glossar-link}: solving constraint integer programs.* In: *Mathematical Programming Computation* 1(1), S. 141. DOI: 10.1007/s12532-008-0001-1 [[Solver](#gloss:solver){.glossar-link}: SCIP] *Beschreibt die Verbindung von [MILP (Gemischt-ganzzahlige Optimierung)](#gloss:gemischt-ganzzahlige-optimierung-milp){.glossar-link} und Constraint Programming in einem Solver.*
## Moderne Solver: Implementierung, Vergleich und Benchmarks
@ -29492,7 +29497,7 @@ Frei zugängliche Fassungen sind vermerkt. Wo eine DOI angegeben ist, führt sie
* ★★★ **Huangfu, Q. & Hall, J. A. J. (2018):** *Parallelizing the dual revised simplex method.* In: *Mathematical Programming Computation* 10(1), S. 119142. DOI: 10.1007/s12532-017-0130-5 [Solver: [HiGHS](#gloss:highs){.glossar-link}] *Die vom HiGHS-Projekt selbst benannte Zitierquelle. HiGHS ist das Backend von `scipy.optimize.linprog` und CVXPY. [highs.dev](https://highs.dev)*
* ★★★ **Gleixner, A., Hendel, G., Gamrath, G. et al. (2021):** *MIPLIB 2017: data-driven compilation of the 6th mixed-integer programming library.* In: *Mathematical Programming Computation* 13(3), S. 443490. DOI: 10.1007/s12532-020-00194-3 [Benchmarks] *Die Testmenge, auf der praktisch jeder Solververgleich beruht: 1065 Instanzen, davon 240 als Benchmark-Teilmenge. Frei zugänglich; Daten unter [miplib.zib.de](https://miplib.zib.de).*
* ★★★ **Mittelmann, H. D.:** *Benchmarks for Optimization Software.* Arizona State University. [plato.asu.edu/bench.html](https://plato.asu.edu/bench.html) [Benchmarks] *Die laufend aktualisierte Referenzmessung für [LP](#gloss:lineare-programmierung-lp){.glossar-link}-, MILP- und [QP](#gloss:quadratische-programmierung-qp){.glossar-link}-Solver. **Wichtige Einschränkung:** Seit 2024 sind die kommerziellen Solver auf eigenen Wunsch nicht mehr enthalten; ein direkter Vergleich [Gurobi](#gloss:gurobi){.glossar-link} gegen HiGHS ist dort nicht mehr möglich.*
* ★★★ **Mittelmann, H. D.:** *Benchmarks for Optimization Software.* Arizona State University. [plato.asu.edu/bench.html](https://plato.asu.edu/bench.html) [Benchmarks] *Die laufend aktualisierte Referenzmessung für [LP (Lineare Programmierung)](#gloss:lineare-programmierung-lp){.glossar-link}-, MILP- und [QP (Quadratische Programmierung)](#gloss:quadratische-programmierung-qp){.glossar-link}-Solver. **Wichtige Einschränkung:** Seit 2024 sind die kommerziellen Solver auf eigenen Wunsch nicht mehr enthalten; ein direkter Vergleich [Gurobi](#gloss:gurobi){.glossar-link} gegen HiGHS ist dort nicht mehr möglich.*
* ★★ **Bolusani, S., Besançon, M., Bestuzheva, K. et al. (2024):** *The SCIP Optimization Suite 9.0.* Technischer Bericht, Zuse-Institut Berlin. arXiv:2402.17702 [Solver: SCIP] *Beschreibt Aufbau und Komponenten der Suite. Die Reihe wird fortgeschrieben — die jeweils aktuelle Fassung steht unter [scipopt.org](https://www.scipopt.org); beim Zitieren die tatsächlich benutzte Version angeben.*
* ★★ **Perron, L. & Furnon, V.:** *[OR-Tools](#gloss:or-tools){.glossar-link}.* Google. [developers.google.com/optimization](https://developers.google.com/optimization) · Quellcode: [github.com/google/or-tools](https://github.com/google/or-tools) [Solver: OR-Tools] *Die Sammlung, aus der das Buch [CP-SAT](#gloss:cp-sat){.glossar-link} und die [Routing-Bibliothek](#gloss:routing-bibliothek){.glossar-link} benutzt.*
@ -29501,7 +29506,7 @@ Frei zugängliche Fassungen sind vermerkt. Wo eine DOI angegeben ist, führt sie
*Zu [Kapitel 7](#kap-cpsat).*
* ★★★ **Rossi, F., van Beek, P. & Walsh, T. (Hrsg., 2006):** *Handbook of Constraint Programming.* Foundations of Artificial Intelligence, Bd. 2. Elsevier, Amsterdam. [Constraint Programming] *Nach wie vor das Referenzwerk zu Propagation, globalen Constraints und Suchstrategien.*
* ★★★ **Perron, L. & Furnon, V.:** *OR-Tools [CP](#gloss:constraint-programming-cp){.glossar-link}-[SAT](#gloss:sat-boolean-satisfiability){.glossar-link} Solver Documentation.* Google. [developers.google.com/optimization/cp](https://developers.google.com/optimization/cp) [Solver: CP-SAT] *Die einzige vollständige Beschreibung des im Buch benutzten Solvers. Der Abschnitt zu `AddNoOverlap` und `AddCumulative` deckt sich mit [Kapitel 7](#kap-cpsat).*
* ★★★ **Perron, L. & Furnon, V.:** *OR-Tools [CP (Constraint Programming)](#gloss:constraint-programming-cp){.glossar-link}-[SAT (Boolean Satisfiability)](#gloss:sat-boolean-satisfiability){.glossar-link} Solver Documentation.* Google. [developers.google.com/optimization/cp](https://developers.google.com/optimization/cp) [Solver: CP-SAT] *Die einzige vollständige Beschreibung des im Buch benutzten Solvers. Der Abschnitt zu `AddNoOverlap` und `AddCumulative` deckt sich mit [Kapitel 7](#kap-cpsat).*
* ★★ **Laborie, P., Rogerie, J., Shaw, P. & Vilím, P. (2018):** *IBM ILOG CP Optimizer for scheduling.* In: *Constraints* 23(2), S. 210250. DOI: 10.1007/s10601-018-9281-x [[Scheduling](#gloss:scheduling){.glossar-link}] *Intervallvariablen und Ressourcenprofile aus Sicht des konkurrierenden Solvers — lehrreich für das Verständnis der Modellierungsprimitive.*
* ★★ **Biere, A., Heule, M., van Maaren, H. & Walsh, T. (Hrsg., 2021):** *Handbook of Satisfiability* (2. Aufl.). Frontiers in Artificial Intelligence and Applications, Bd. 336. IOS Press, Amsterdam. DOI: 10.3233/FAIA336 [SAT] *Die Grundlage dessen, was CP-SAT unter der Haube tut: Conflict-Driven Clause Learning, Klausellernen, Neustarts.*
@ -29510,7 +29515,7 @@ Frei zugängliche Fassungen sind vermerkt. Wo eine DOI angegeben ist, führt sie
*Zu [Kapitel 8](#kap-graphen). Neuer Abschnitt.*
* ★★★ **Ahuja, R. K., Magnanti, T. L. & Orlin, J. B. (1993):** *Network Flows: Theory, Algorithms, and Applications.* Prentice Hall, Englewood Cliffs. [Netzwerkflüsse] *Das Standardwerk zu Min-Cost-Flow, Matching und totaler Unimodularität — der Grund, warum diese Modelle schon als LP ganzzahlig lösen.*
* ★★★ **Toth, P. & Vigo, D. (Hrsg., 2014):** *Vehicle Routing: Problems, Methods, and Applications* (2. Aufl.). SIAM, Philadelphia. DOI: 10.1137/1.9781611973594 [[VRP](#gloss:vehicle-routing-problem-vrp){.glossar-link}] *Das Referenzwerk zur Tourenplanung, einschließlich Kapazitäten, Zeitfenstern und [Subtour](#gloss:subtour){.glossar-link}-Eliminierung.*
* ★★★ **Toth, P. & Vigo, D. (Hrsg., 2014):** *Vehicle Routing: Problems, Methods, and Applications* (2. Aufl.). SIAM, Philadelphia. DOI: 10.1137/1.9781611973594 [[VRP (Vehicle Routing Problem)](#gloss:vehicle-routing-problem-vrp){.glossar-link}] *Das Referenzwerk zur Tourenplanung, einschließlich Kapazitäten, Zeitfenstern und [Subtour](#gloss:subtour){.glossar-link}-Eliminierung.*
* ★★ **Vidal, T., Laporte, G. & Matl, P. (2020):** *A concise guide to existing and emerging vehicle routing problem variants.* In: *European Journal of Operational Research* 286(2), S. 401416. DOI: 10.1016/j.ejor.2019.10.010 [VRP] *Übersicht über die Variantenvielfalt — hilfreich, um die eigene Aufgabe einzuordnen, bevor man modelliert. Frei zugänglich als arXiv:1906.06750.*
* ★ **Kuhn, H. W. (1955):** *The Hungarian method for the assignment problem.* In: *Naval Research Logistics Quarterly* 2(12), S. 8397. DOI: 10.1002/nav.3800020109 [[Zuordnungsproblem](#gloss:zuordnungsproblem){.glossar-link}] *Das Originalverfahren hinter `scipy.optimize.linear_sum_assignment`.*
@ -29518,7 +29523,7 @@ Frei zugängliche Fassungen sind vermerkt. Wo eine DOI angegeben ist, führt sie
*Zu [Kapitel 9](#kap-metaheuristiken). Neuer Abschnitt.*
* ★★★ **Gendreau, M. & Potvin, J.-Y. (Hrsg., 2019):** *Handbook of Metaheuristics* (3. Aufl.). Springer, Cham. DOI: 10.1007/978-3-319-91086-4 [Metaheuristiken] *Sammelband zu [Tabu-Suche](#gloss:tabu-suche){.glossar-link}, [Simulated Annealing](#gloss:simulated-annealing){.glossar-link}, [LNS](#gloss:large-neighborhood-search-lns){.glossar-link}, genetischen Verfahren — jeweils von den Urhebern geschrieben.*
* ★★★ **Gendreau, M. & Potvin, J.-Y. (Hrsg., 2019):** *Handbook of Metaheuristics* (3. Aufl.). Springer, Cham. DOI: 10.1007/978-3-319-91086-4 [Metaheuristiken] *Sammelband zu [Tabu-Suche](#gloss:tabu-suche){.glossar-link}, [Simulated Annealing](#gloss:simulated-annealing){.glossar-link}, [LNS (Large Neighborhood Search)](#gloss:large-neighborhood-search-lns){.glossar-link}, genetischen Verfahren — jeweils von den Urhebern geschrieben.*
* ★★★ **Pisinger, D. & Ropke, S. (2010):** *Large Neighborhood Search.* In: Gendreau, M. & Potvin, J.-Y. (Hrsg.): *Handbook of Metaheuristics*, S. 399419. Springer. DOI: 10.1007/978-1-4419-1665-5_13 [Metaheuristiken] *Die Darstellung des Verfahrens, das im Buch die exakte Suche auf Teilproblemen mit heuristischem Zerstören verbindet.*
* ★★ **Kirkpatrick, S., Gelatt, C. D. & Vecchi, M. P. (1983):** *Optimization by Simulated Annealing.* In: *Science* 220(4598), S. 671680. DOI: 10.1126/science.220.4598.671 [Metaheuristiken] *Die Originalarbeit; die Abkühlungsanalogie stammt von hier.*
* ★★ **Sörensen, K. (2015):** *Metaheuristics — the metaphor exposed.* In: *International Transactions in Operational Research* 22(1), S. 318. DOI: 10.1111/itor.12001 [Metaheuristiken] *Kritik an der Flut naturanaloger „neuer" Verfahren. Vor der Auswahl einer [Metaheuristik](#gloss:metaheuristik){.glossar-link} zu lesen — sie erspart viel Zeit.*
@ -29535,7 +29540,7 @@ Frei zugängliche Fassungen sind vermerkt. Wo eine DOI angegeben ist, führt sie
*Zu [Kapitel 11](#kap-qp-nlp).*
* ★★★ **Boyd, S. & Vandenberghe, L. (2004):** *Convex Optimization.* Cambridge University Press. DOI: 10.1017/CBO9780511804441 [Konvexe Optimierung] *Referenzwerk für konvexe Mengen, [KKT](#gloss:karush-kuhn-tucker-bedingungen-kkt){.glossar-link}-Bedingungen, QP und SDP; die theoretische Basis von CVXPY. Frei verfügbar unter [stanford.edu/~boyd/cvxbook](https://web.stanford.edu/~boyd/cvxbook/).*
* ★★★ **Boyd, S. & Vandenberghe, L. (2004):** *Convex Optimization.* Cambridge University Press. DOI: 10.1017/CBO9780511804441 [Konvexe Optimierung] *Referenzwerk für konvexe Mengen, [KKT (Karush-Kuhn-Tucker-Bedingungen)](#gloss:karush-kuhn-tucker-bedingungen-kkt){.glossar-link}-Bedingungen, QP und SDP; die theoretische Basis von CVXPY. Frei verfügbar unter [stanford.edu/~boyd/cvxbook](https://web.stanford.edu/~boyd/cvxbook/).*
* ★★ **Kraft, D. (1988):** *A Software Package for Sequential Quadratic Programming.* DFVLR-FB 88-28, Deutsche Forschungs- und Versuchsanstalt für Luft- und Raumfahrt, Köln. [Nichtlineare Optimierung] *Die Originalarbeit zu [SLSQP](#gloss:slsqp){.glossar-link} — dem Verfahren hinter `scipy.optimize.minimize`.*
* ★★ **Lobo, M. S., Vandenberghe, L., Boyd, S. & Lebret, H. (1998):** *Applications of second-order cone programming.* In: *Linear Algebra and its Applications* 284(13), S. 193228. DOI: 10.1016/S0024-3795(98)10032-0 [[Konische Optimierung](#gloss:konische-optimierung){.glossar-link}] *Warum sich Risikoschranken und Normbedingungen als SOCP schreiben lassen — die Grundlage der Chance-Constraints-Formulierung in [Kapitel 12](#kap-unsicherheit).*
@ -29543,7 +29548,7 @@ Frei zugängliche Fassungen sind vermerkt. Wo eine DOI angegeben ist, führt sie
*Zu [Kapitel 12](#kap-unsicherheit) und [Kapitel 17](#kap-supplychain). Aus dem früheren Block „Konvexe, nichtlineare und robuste Optimierung" herausgelöst und erweitert.*
* ★★★ **Birge, J. R. & Louveaux, F. (2011):** *Introduction to Stochastic Programming* (2. Aufl.). Springer, New York. DOI: 10.1007/978-1-4614-0237-4 [Stochastische Optimierung] *Das Standardwerk zur zweistufigen Optimierung, Szenariobäumen und dem Wert perfekter Information ([EVPI](#gloss:evpi-expected-value-of-perfect-information){.glossar-link}).*
* ★★★ **Birge, J. R. & Louveaux, F. (2011):** *Introduction to Stochastic Programming* (2. Aufl.). Springer, New York. DOI: 10.1007/978-1-4614-0237-4 [Stochastische Optimierung] *Das Standardwerk zur zweistufigen Optimierung, Szenariobäumen und dem Wert perfekter Information ([EVPI (Expected Value of Perfect Information)](#gloss:evpi-expected-value-of-perfect-information){.glossar-link}).*
* ★★★ **Ben-Tal, A., El Ghaoui, L. & Nemirovski, A. (2009):** *Robust Optimization.* Princeton University Press. DOI: 10.1515/9781400831050 [[Robuste Optimierung](#gloss:robuste-optimierung){.glossar-link}] *Die geschlossene Darstellung der robusten Gegenstücke und ihrer konischen Umformung.*
* ★★★ **Bertsimas, D. & Sim, M. (2004):** *The Price of Robustness.* In: *Operations Research* 52(1), S. 3553. DOI: 10.1287/opre.1030.0065 [Robuste Optimierung] *Quelle des Budgeted-Uncertainty-Ansatzes: Der [Parameter](#gloss:parameter){.glossar-link} $\Gamma$ regelt stufenlos, wie vorsichtig die Lösung wird.*
* ★★ **Nemirovski, A. & Shapiro, A. (2007):** *Convex Approximations of Chance Constrained Programs.* In: *SIAM Journal on Optimization* 17(4), S. 969996. DOI: 10.1137/050622328 [Chance Constraints] *Zeigt, wann sich eine Wahrscheinlichkeitsbedingung konvex annähern lässt — und wann nicht.*
@ -29590,7 +29595,7 @@ Frei zugängliche Fassungen sind vermerkt. Wo eine DOI angegeben ist, führt sie
*Zu [Kapitel 18](#kap-finanzdaten), [Kapitel 19](#kap-markowitz), [Kapitel 20](#kap-cvar) und [Kapitel 21](#kap-handelsmaschine).*
* ★★★ **Markowitz, H. (1952):** *Portfolio Selection.* In: *The Journal of Finance* 7(1), S. 7791. DOI: 10.2307/2975974 [Portfoliotheorie] *Die Arbeit, die das Zusammenspiel von Rendite und Kovarianz zum Optimierungsproblem gemacht hat.*
* ★★★ **Rockafellar, R. T. & Uryasev, S. (2000):** *Optimization of Conditional Value-at-Risk.* In: *Journal of Risk* 2(3), S. 2141. DOI: 10.21314/JOR.2000.038 [Risikomaße] *Der Satz, der die [CVaR](#gloss:conditional-value-at-risk-cvar){.glossar-link}-Minimierung in ein lineares Programm überführt.*
* ★★★ **Rockafellar, R. T. & Uryasev, S. (2000):** *Optimization of Conditional Value-at-Risk.* In: *Journal of Risk* 2(3), S. 2141. DOI: 10.21314/JOR.2000.038 [Risikomaße] *Der Satz, der die [CVaR (Conditional Value at Risk)](#gloss:conditional-value-at-risk-cvar){.glossar-link}-Minimierung in ein lineares Programm überführt.*
* ★★★ **Ledoit, O. & Wolf, M. (2004):** *A well-conditioned estimator for large-dimensional covariance matrices.* In: *Journal of Multivariate Analysis* 88(2), S. 365411. DOI: 10.1016/S0047-259X(03)00096-4 [Kovarianzschätzung] *Quelle des von `scikit-learn` verwendeten Shrinkage-Ziels (skalierte Einheitsmatrix).*
* ★★★ **Cornuéjols, G., Peña, J. & Tütüncü, R. (2018):** *Optimization Methods in Finance* (2. Aufl.). Cambridge University Press. DOI: 10.1017/9781107297340 [Finanzoptimierung] *Die Brücke zwischen Optimierungstheorie und Finanzanwendung; deckt QP, SOCP und robuste Portfolios ab.*
* ★★★ **Almgren, R. & Chriss, N. (2001):** *Optimal Execution of Portfolio Transactions.* In: *Journal of Risk* 3(2), S. 539. DOI: 10.21314/jor.2001.041 [Orderausführung] *Das Modell hinter dem Beispiel zur optimalen Orderausführung in [Kapitel 13](#kap-dynamische-programmierung).*
@ -29603,7 +29608,7 @@ Frei zugängliche Fassungen sind vermerkt. Wo eine DOI angegeben ist, führt sie
*Zu [Kapitel 22](#kap-praxisfallen) und [Kapitel 23](#kap-testing). Neuer Abschnitt.*
* ★★★ **Chinneck, J. W. (2008):** *Feasibility and [Infeasibility](#gloss:infeasibility){.glossar-link} in Optimization: Algorithms and Computational Methods.* Springer, New York. DOI: 10.1007/978-0-387-74932-7 [Fehlerdiagnose] *Das Standardwerk zur Unlösbarkeitsdiagnose, einschließlich des Deletion Filters und der irreduziblen unlösbaren Teilmengen ([IIS](#gloss:iis-irreducible-infeasible-subset){.glossar-link}). Direkte Grundlage von [Anhang C](#anhang-fehlerdiagnose).*
* ★★★ **Chinneck, J. W. (2008):** *Feasibility and [Infeasibility](#gloss:infeasibility){.glossar-link} in Optimization: Algorithms and Computational Methods.* Springer, New York. DOI: 10.1007/978-0-387-74932-7 [Fehlerdiagnose] *Das Standardwerk zur Unlösbarkeitsdiagnose, einschließlich des Deletion Filters und der irreduziblen unlösbaren Teilmengen ([IIS (Irreducible Infeasible Subset)](#gloss:iis-irreducible-infeasible-subset){.glossar-link}). Direkte Grundlage von [Anhang C](#anhang-fehlerdiagnose).*
* ★★ **Sculley, D., Holt, G., Golovin, D. et al. (2015):** *Hidden Technical Debt in Machine Learning Systems.* In: *Advances in Neural Information Processing Systems* 28, S. 25032511. [Betrieb] *Über Systeme, deren Modell nur ein kleiner Teil ist — überträgt sich unmittelbar auf den Betrieb von Optimierungsdiensten. Frei zugänglich.*
* ★★ **Kleppmann, M. (2017):** *Designing Data-Intensive Applications.* O'Reilly, Sebastopol. [Betrieb] *[Snapshot-Prinzip](#gloss:snapshot-prinzip){.glossar-link}, [Zustandslosigkeit](#gloss:zustandslosigkeit){.glossar-link}, Versionierung und Reproduzierbarkeit — die Architekturfragen hinter der OR-Plattform in [Kapitel 22](#kap-praxisfallen).*
* ★★ **Ramírez, S.:** *FastAPI Documentation.* [fastapi.tiangolo.com](https://fastapi.tiangolo.com) [Betrieb] *Die Grundlage des Optimierungsdienstes in [Kapitel 23](#kap-testing), einschließlich der Eingabevalidierung über `pydantic`.*