Phase 6.1: Chance Constraints - die Zusage "mit 95 % Sicherheit"

Neuer Abschnitt im Kapitel Unsicherheit plus Chance_Constraints.py (74.
Programm). Das Kapitel hatte Monte-Carlo, Zweistufigkeit und
Worst-Case-Robustheit; die Wahrscheinlichkeitszusage war die fehlende vierte
Antwort - und die, nach der das Management tatsaechlich fragt. Setzt Paket 4
aus Verbesserungen_02.md um.

Beide Wege an DERSELBEN Instanz (Kraftwerkspark, 500 MW gesicherte Zusage):
analytisch als Second-Order-Cone-Bedingung (CLARABEL) und szenariobasiert als
Big-M-MILP (SciPy/HiGHS) - beides in einem Prozess, ohne ortools- oder
highspy-Import.

Drei gemessene Befunde:

* Der Mittelwertplan haelt 50,08 %. Kein Fehler, sondern die Definition des
  Erwartungswerts.
* Sicherheit ist konvex bepreist: 56.289 EUR je Prozentpunkt auf dem Weg zu
  80 %, 253.848 EUR zwischen 95 und 99 % - das 4,5-fache. Das Programm
  rechnet die Tabelle selbst aus, statt sie zu behaupten.
* Die Zusage gilt nur fuer die unterstellte Verteilung: Der 95-%-Plan haelt
  gemessen 87,44 %, sobald die Testverteilung eine Kaeltewelle mit
  Dunkelflaute enthaelt, in der alles zugleich einbricht - auch das
  Gaskraftwerk. In einer reinen Normalwelt liefert derselbe Plan 94,97 %.

Zwei eigene Fehlgriffe, beide durch Messen aufgefallen und korrigiert: Die
erste Kostentarierung ergab eine entartete Loesung (alles ins Gaskraftwerk),
womit die Kovarianzmatrix wirkungslos war - und gerade sie begruendet die
Kegelform. Und der erste Kaelteeinbruch traf nur Wind und Sonne; der SOC-Plan
hatte die ohnehin herausgehalten und war zufaellig robust, das Argument trug
nicht.

Ehrlich berichtet statt geglaettet: Die Szenariomethode ueberanpasst. Ueber
zwoelf Laeufe (S = 200, 400, 800) lag die tatsaechliche Quote zwischen
93,14 % und 96,71 %, und die Spanne wurde von S = 400 auf 800 wieder
breiter. Beide Solver bestaetigen optimal bei identischen Kosten - echte
Ueberanpassung, kein Solverartefakt. Steht als Warnkasten im Abschnitt.

Die Laufzeitmessung ist aus der Ausgabe entfernt: Eine Wanduhrzeit ist nie
byteidentisch reproduzierbar (2,2 s / 2,3 s zwischen zwei Laeufen) und haette
Regel 4 dauerhaft gebrochen. Danach drei Laeufe zeichengleich, und die
abgedruckte Ausgabe stimmt mit dem Lauf des extrahierten Programms ueberein.

Mitgezogen: Kapitelkopf, Lernziele, Uebersichtstabelle (drei -> vier
Ansaetze), Selbsttest, Zusammenfassung, Vorwort-Programmverzeichnis, eine
neue Uebungsaufgabe und ihre Loesung in Anhang A.

pyproject.toml korrigiert: cvxpy lag in [finance], wird aber von 13
Programmen gebraucht, darunter dreien in diesem Kapitel - jetzt in der
Grundausstattung. Es zieht kein highspy nach, der Solverkonflikt bleibt auf
[large-scale] beschraenkt.

Stand: 293 Abschnitte, 712 Querverweise, 327 Indexmarken, 74 Programme (0
Fehler), 33 pytest-Tests, PDF 725 Seiten.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
dschlueter 2026-09-08 01:57:19 +02:00
commit 6c67e126dd
23 changed files with 9089 additions and 6419 deletions

View file

@ -359,6 +359,7 @@ Alle Beispielprogramme dieses Buchs im Überblick, sortiert nach Kapitel — pra
| `Monte_Carlo.py` | Monte-Carlo-Bewertung | [Kapitel 12](#kap-unsicherheit) |
| `Stochastische_Optimierung.py` | Two-Stage mit Recourse | [Kapitel 12](#kap-unsicherheit) |
| `Robuste_Optimierung.py` | Worst-Case-Absicherung | [Kapitel 12](#kap-unsicherheit) |
| `Chance_Constraints.py` | Zusage „mit 95 % Sicherheit“, SOC und Big-M | [Kapitel 12](#kap-unsicherheit) |
| `Bellman_Minimalbeispiel.py` | Rückwärtsinduktion | [Kapitel 13](#kap-dynamische-programmierung) |
| `Mehrziel_Pareto.py` | Pareto-Front, ε-Constraint, Gewichtslücke | [Kapitel 14](#kap-mehrziel) |
| `Predict_then_Optimize.py` | MSE gegen Entscheidungskosten | [Kapitel 15](#kap-prognose) |
@ -12773,19 +12774,20 @@ else:
> **📌 Kapitel auf einen Blick**
>
> **Worum geht es?** Bisher waren alle Parameter bekannt. In der Realität sind Nachfrage, Rendite und Fahrzeit **Zufallsgrößen**. Dieses Kapitel zeigt drei Wege, damit umzugehen — und warum „einfach den Mittelwert einsetzen“ der schlechteste davon ist.
> **Worum geht es?** Bisher waren alle Parameter bekannt. In der Realität sind Nachfrage, Rendite und Fahrzeit **Zufallsgrößen**. Dieses Kapitel zeigt vier Wege, damit umzugehen — und warum „einfach den Mittelwert einsetzen“ der schlechteste davon ist.
>
> **Voraussetzungen:** [Kapitel 5](#kap-lp), [Kapitel 11](#kap-qp-nlp). Grundbegriffe der Statistik (Erwartungswert, Quantil).
>
> **Danach können Sie:** Ein zweistufiges stochastisches Modell aufstellen, Monte-Carlo zur Risikomessung einsetzen, ein robustes Modell für den Worst Case formulieren — und erkennen, wann Rechnen mit Mittelwerten zulässig ist und wann es systematisch danebengeht.
> **Danach können Sie:** Ein zweistufiges stochastisches Modell aufstellen, Monte-Carlo zur Risikomessung einsetzen, ein robustes Modell für den Worst Case formulieren, eine Wahrscheinlichkeitszusage („mit 95 % Sicherheit“) als lösbare Nebenbedingung schreiben — und erkennen, wann Rechnen mit Mittelwerten zulässig ist und wann es systematisch danebengeht.
>
> **Zeitbedarf:** ca. 5,5 Stunden.
> **Zeitbedarf:** ca. 6,5 Stunden.
>
> **Programme:**\
> `Fluch_des_Durchschnitts.py`\
> `Monte_Carlo.py`\
> `Stochastische_Optimierung.py`\
> `Robuste_Optimierung.py`
> `Robuste_Optimierung.py`\
> `Chance_Constraints.py`
>
> **Notebook:** `Notebooks_04/unsicherheit.ipynb`\
> [In Google Colab öffnen](https://colab.research.google.com/github/dschlueter/or-mit-python/blob/main/Notebooks_04/unsicherheit.ipynb)
@ -12867,9 +12869,10 @@ Nach diesem Kapitel können Sie …
2. … ein **zweistufiges stochastisches Programm** mit Recourse formulieren.
3. … Monte-Carlo einsetzen, um Verteilungen statt Punktschätzungen zu bewerten.
4. … ein **robustes** Modell mit Unsicherheitsmenge aufstellen und seinen Preis beziffern.
5. … begründen, welcher der drei Ansätze für ein gegebenes Problem passt.
6. … das **kritische Verhältnis** eines Newsvendor-Problems aufstellen und daraus die optimale Bestellmenge als Quantil ablesen.
7. … eine Terminzusage als Quantil formulieren statt als Mittelwert.
5. … eine **Wahrscheinlichkeitszusage** („mit 95 % Sicherheit“) als Chance Constraint schreiben — analytisch als Kegelbedingung oder szenariobasiert mit Big-M — und den Preis eines Prozentpunkts Sicherheit beziffern.
6. … begründen, welcher der vier Ansätze für ein gegebenes Problem passt.
7. … das **kritische Verhältnis** eines Newsvendor-Problems aufstellen und daraus die optimale Bestellmenge als Quantil ablesen.
8. … eine Terminzusage als Quantil formulieren statt als Mittelwert.
---
@ -12993,18 +12996,20 @@ Kein Rechentrick, sondern brute-force über alle ganzzahligen $x$ von 0 bis 500
> **🎯 Merksatz** Der Durchschnittskunde kauft nie. Das Durchschnittsszenario tritt nie ein. Wer mit Mittelwerten plant, optimiert eine Welt, die es nicht gibt.
### Die drei Ansätze im Überblick
### Die vier Ansätze im Überblick
![Abb. 12.1: Ansätze für Optimierung unter Unsicherheit](bilder_04/kap09_unsicherheit_ansaetze.svg)
| | **Monte-Carlo** | **Stochastische Programmierung** | **Robuste Optimierung** |
| --- | --- | --- | --- |
| Braucht | Verteilung | Szenarien **mit Wahrscheinlichkeiten** | nur eine **Menge** möglicher Werte |
| Optimiert | nichts (bewertet nur) | **Erwartungswert** über Szenarien | **Worst Case** in der Menge |
| Typische Frage | „Wie riskant ist dieser Plan?“ | „Was ist im Mittel am besten?“ | „Was hält auch im schlimmsten Fall?“ |
| Stärke | beliebige Kennzahlen, sehr flexibel | nutzt Wahrscheinlichkeiten voll aus | keine Verteilungsannahme nötig |
| Schwäche | keine Optimierung | Wahrscheinlichkeiten müssen stimmen | oft übervorsichtig, kostet Ertrag |
| Kapitel | 9.2 | 9.3 | 9.4 |
| | **Monte-Carlo** | **Stochastische Programmierung** | **Robuste Optimierung** | **Chance Constraints** |
| --- | --- | --- | --- | --- |
| Braucht | Verteilung | Szenarien **mit Wahrscheinlichkeiten** | nur eine **Menge** möglicher Werte | Verteilung **oder** Szenarien |
| Optimiert | nichts (bewertet nur) | **Erwartungswert** über Szenarien | **Worst Case** in der Menge | Kosten bei **zugesicherter Quote** |
| Typische Frage | „Wie riskant ist dieser Plan?“ | „Was ist im Mittel am besten?“ | „Was hält auch im schlimmsten Fall?“ | „Was hält in 95 % der Fälle?“ |
| Stärke | beliebige Kennzahlen, sehr flexibel | nutzt Wahrscheinlichkeiten voll aus | keine Verteilungsannahme nötig | die Zusage steht **im Modell** |
| Schwäche | keine Optimierung | Wahrscheinlichkeiten müssen stimmen | oft übervorsichtig, kostet Ertrag | Zusage gilt nur für die unterstellte Verteilung |
| Nachzulesen in | [Abschnitt 12.4](#sec:unsicherheit-monte-carlo-simulation) | [Abschnitt 12.5](#sec:unsicherheit-zweistufige-stochastische-programmierung) | [Abschnitt 12.6](#sec:unsicherheit-robuste-optimierung-gegen-den-worst-case) | [Abschnitt 12.7](#sec:unsicherheit-chance-constraints) |
**Der Unterschied zwischen den letzten beiden** ist der, an dem die meisten Diskussionen hängenbleiben. Die robuste Optimierung sagt: *„Es darf **nie** schiefgehen“* — und zahlt dafür. Die Chance Constraint sagt: *„Es darf in höchstens 5 % der Fälle schiefgehen“* — und macht damit verhandelbar, was die Sicherheit kosten darf.
---
@ -13477,13 +13482,382 @@ if __name__ == "__main__":
---
## 12.7 Übungsaufgaben {#sec:unsicherheit-uebungsaufgaben}
## 12.7 Wahrscheinlichkeitsbeschränkungen: „mit 95 % Sicherheit“ {#sec:unsicherheit-chance-constraints}
Die drei bisherigen Ansätze beantworten Fragen, die im Sitzungssaal selten so gestellt werden. „Was ist im Mittel am besten?“ hört ein Vorstand als Ausflucht; „was hält auch im schlimmsten Fall?“ als Einladung, zu viel Geld auszugeben. Gefragt wird fast immer nach einer **Wahrscheinlichkeit**: *Mit welcher Sicherheit hält der Plan?*
Die **Wahrscheinlichkeitsbeschränkung**`\index{Chance Constraint}`{=latex} schreibt genau das ins Modell:
$$
\mathbb{P}\!\left(\mathbf{a}^\top\mathbf{x} \ge b\right) \ge 1 - \alpha
$$
> **📐 Formel-Lesehilfe**
> * $\mathbf{a}$ — der **unsichere** Vektor: Verfügbarkeiten, Erträge, Fahrzeiten. Er ist keine Zahl, sondern eine Zufallsgröße.
> * $\mathbf{x}$ — Ihre Entscheidung. Sie fällt, **bevor** $\mathbf{a}$ sich zeigt.
> * $\alpha$ — die Ausfallwahrscheinlichkeit, die Sie akzeptieren. $\alpha = 0{,}05$ heißt „in höchstens 5 % der Fälle darf es schiefgehen“.
>
> **Ohne Formel gesagt:** „Plane so, dass die Zusage in 95 von 100 Fällen hält — und sag mir, was das kostet.“
**Das Problem daran.** So aufgeschrieben ist die Bedingung nicht lösbar: Ein Solver kann nichts mit einem Wahrscheinlichkeitsoperator anfangen. Es braucht einen Weg, sie in etwas zu übersetzen, das ein Optimierer versteht. Es gibt zwei, und sie unterscheiden sich in dem, was sie über die Verteilung voraussetzen.
### Weg 1: Normalverteilung — die Bedingung wird ein Kegel
Ist $\mathbf{a} \sim \mathcal{N}(\hat{\mathbf{a}}, \boldsymbol{\Sigma})$, dann ist $\mathbf{a}^\top\mathbf{x}$ für festes $\mathbf{x}$ selbst normalverteilt, mit Erwartungswert $\hat{\mathbf{a}}^\top\mathbf{x}$ und Standardabweichung $\sqrt{\mathbf{x}^\top\boldsymbol{\Sigma}\mathbf{x}}$. Damit lässt sich die Wahrscheinlichkeit durch ein Quantil ersetzen:
$$
\hat{\mathbf{a}}^\top\mathbf{x} \;-\; z_{1-\alpha}\,\lVert \mathbf{L}^\top\mathbf{x}\rVert_2
\;\ge\; b
\qquad\text{mit}\qquad
\boldsymbol{\Sigma} = \mathbf{L}\mathbf{L}^\top,\quad
z_{1-\alpha} = \Phi^{-1}(1-\alpha)
$$
Das ist eine **Second-Order-Cone-Bedingung**`\index{Konische Optimierung (SOCP, SDP)}`{=latex} — dieselbe Bauform, die [Kapitel 11](#kap-qp-nlp) eingeführt hat, und CVXPY löst sie ohne Umstände.
> **🎯 Warum eine Norm und keine Summe** Der Sicherheitszuschlag $\lVert\mathbf{L}^\top\mathbf{x}\rVert_2$ ist **keine** Summe von Einzelzuschlägen je Anlage. Genau darin steckt der Nutzen der Mischung: Zwei gegenläufige Quellen schwanken **gemeinsam** weniger als jede für sich, und die Norm rechnet das automatisch mit. Ein fester Aufschlag je Anlage könnte das nicht — er wäre linear und würde Diversifikation nicht belohnen.
### Weg 2: Szenarien — Big-M ohne Verteilungsannahme
Liegen statt einer Verteilung nur $S$ beobachtete Szenarien vor, bekommt jedes eine Binärvariable $z_s$, die sagt, ob es verletzt werden **darf**:
$$
\begin{aligned}
\mathbf{a}_s^\top\mathbf{x} &\ge b - M z_s && \forall s\\
\sum_{s} z_s &\le \alpha S\\
z_s &\in \{0,1\}
\end{aligned}
$$
Aus dem Kegelproblem wird ein MILP 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
```python
#!/usr/bin/env python3
# Chance_Constraints.py
"""
Kapitel Unsicherheit: Wahrscheinlichkeitsbeschraenkungen.
Das Management fragt selten "was ist im Mittel am besten?", sondern "mit
welcher Sicherheit haelt der Plan?". Genau das formuliert eine Chance
Constraint: P(Versorgung >= Bedarf) >= 1 - alpha.
Gezeigt werden beide Wege dorthin, an derselben Instanz:
(a) analytisch - unter Normalverteilungsannahme wird daraus eine
Second-Order-Cone-Bedingung, loesbar mit CVXPY
(b) szenariobasiert - Big-M mit Binaervariablen, fuer beliebige
empirische Verteilungen
Und die beiden Messungen, auf die es ankommt: Was kostet ein Prozentpunkt
Versorgungssicherheit - und haelt die Zusage auch dann, wenn die Verteilung
nicht normal ist?
Solver: CLARABEL (Kegel) und SciPy/HiGHS (gemischt-ganzzahlig). Weder ortools
noch ein direkter highspy-Import, damit alles in einem Prozess laeuft.
"""
import cvxpy as cp
import numpy as np
from scipy.stats import norm
# --- Der Kraftwerkspark ----------------------------------------------------
# Die Verfuegbarkeit ist der Anteil, den eine installierte MW im Mittel
# wirklich liefert: bei Wind und Sonne klein und stark schwankend, bei Gas und
# Biomasse gross und stabil. Die Ausbaugrenze ist der Standort - Flaeche,
# Genehmigung, Brennstoffversorgung.
TECHNIK = ["Gaskraftwerk", "Windpark", "Solarpark", "Biomasse"]
KOSTEN = np.array([65_000.0, 24_000.0, 12_000.0, 60_000.0]) # EUR je MW und Jahr
VERFUEGBAR = np.array([0.92, 0.35, 0.18, 0.85])
STREUUNG = np.array([0.05, 0.16, 0.10, 0.04])
GRENZE = np.array([400.0, 250.0, 600.0, 350.0]) # MW
# Wind und Sonne sind leicht gegenlaeufig: Ein Tiefdruckgebiet bringt Wind und
# Wolken zugleich. Genau diese Korrelation macht die Bedingung zu einem Kegel
# und nicht zu einer Summe unabhaengiger Einzelzuschlaege.
KORRELATION = np.array([
[1.00, 0.00, 0.00, 0.05],
[0.00, 1.00, -0.25, 0.00],
[0.00, -0.25, 1.00, 0.00],
[0.05, 0.00, 0.00, 1.00],
])
SIGMA = np.diag(STREUUNG) @ KORRELATION @ np.diag(STREUUNG)
WURZEL = np.linalg.cholesky(SIGMA) # L mit L @ L.T == SIGMA
BEDARF = 500.0 # MW, die gesichert bereitstehen muessen
N = len(TECHNIK)
# Die Kaeltewelle mit Dunkelflaute: selten, aber sie trifft alles zugleich.
# Wind und Sonne brechen fast vollstaendig weg - und, das ist der Punkt, das
# Gaskraftwerk liefert ebenfalls weniger, weil bei Frost der Netzdruck faellt.
# Eine Kovarianzmatrix mit Korrelationen um null kann das nicht ausdruecken.
P_KAELTEWELLE = 0.08
EINBRUCH = np.array([0.72, 0.10, 0.15, 0.88])
def mittelwertplan():
"""Plant mit den Erwartungswerten - ignoriert die Streuung vollstaendig."""
x = cp.Variable(N, nonneg=True)
problem = cp.Problem(cp.Minimize(KOSTEN @ x),
[VERFUEGBAR @ x >= BEDARF, x <= GRENZE])
problem.solve(solver=cp.CLARABEL)
return problem.value, x.value
def chance_constraint_analytisch(alpha):
"""
P(a^T x >= BEDARF) >= 1 - alpha unter a ~ N(VERFUEGBAR, SIGMA).
Aequivalent zu: VERFUEGBAR^T x - z * ||L^T x||_2 >= BEDARF
mit z = Phi^-1(1 - alpha). Das ist eine Second-Order-Cone-Bedingung: Der
Sicherheitszuschlag ist eine Norm ueber x, kein fester Aufschlag je Anlage.
Deshalb belohnt sie Mischung - zwei gegenlaeufige Quellen schwanken
gemeinsam weniger als jede fuer sich.
"""
x = cp.Variable(N, nonneg=True)
z = norm.ppf(1 - alpha)
bedingung = VERFUEGBAR @ x - z * cp.norm(WURZEL.T @ x, 2) >= BEDARF
problem = cp.Problem(cp.Minimize(KOSTEN @ x), [bedingung, x <= GRENZE])
problem.solve(solver=cp.CLARABEL)
return problem.value, x.value
def chance_constraint_szenarien(a, alpha):
"""
Dieselbe Zusage ohne Verteilungsannahme: Fuer jedes Szenario s sagt eine
Binaervariable z_s, ob es verletzt werden darf.
a_s^T x >= BEDARF - M * z_s fuer alle s
sum_s z_s <= alpha * S
M = BEDARF ist die kleinstmoegliche gueltige Schranke, denn a_s^T x >= 0:
Groesser kann eine Verletzung gar nicht ausfallen. Ein unnoetig grosses M
wuerde die LP-Relaxierung aufweichen und die Suche verlangsamen - die
Big-M-Falle aus dem Kapitel Gemischt-ganzzahlige Optimierung.
"""
S = len(a)
x = cp.Variable(N, nonneg=True)
z = cp.Variable(S, boolean=True)
problem = cp.Problem(
cp.Minimize(KOSTEN @ x),
[a @ x >= BEDARF - BEDARF * z, cp.sum(z) <= alpha * S, x <= GRENZE])
problem.solve(solver=cp.SCIPY)
return problem.value, x.value
def ziehe_wetter(anzahl, seed):
"""Mischverteilung: normales Wetter, mit P_KAELTEWELLE ein Einbruch."""
rng = np.random.default_rng(seed)
a = rng.multivariate_normal(VERFUEGBAR, SIGMA, size=anzahl)
getroffen = rng.random(anzahl) < P_KAELTEWELLE
a[getroffen] *= EINBRUCH
return np.clip(a, 0.0, 1.0)
def sicherheit(x, a):
"""Anteil der Szenarien, in denen der Plan den Bedarf deckt."""
return float(np.mean(a @ x >= BEDARF))
KOPF = (f"{'Plan':<20} {'Kosten (EUR)':>13} {'Gas':>4} {'Wind':>4} "
f"{'Sol':>4} {'Bio':>4} {'Normalwelt':>11} {'echte Welt':>11}")
def zeile(name, kosten, x, in_normal, in_echt):
mix = " ".join(f"{w:4.0f}" for w in x)
return (f"{name:<20} {kosten:>13,.0f} {mix} "
f"{in_normal * 100:>9.2f} % {in_echt * 100:>9.2f} %")
if __name__ == "__main__":
print("=" * 78)
print(" WAHRSCHEINLICHKEITSBESCHRAENKUNGEN IM KRAFTWERKSPARK")
print("=" * 78)
print(f"Gesichert bereitzustellen: {BEDARF:.0f} MW\n")
print(f"{'Technologie':<14} {'EUR/MW':>8} {'verfuegbar':>11} {'Streuung':>9} "
f"{'Grenze':>8} {'EUR je erw. MW':>15}")
print("-" * 78)
for i, name in enumerate(TECHNIK):
print(f"{name:<14} {KOSTEN[i]:>8,.0f} {VERFUEGBAR[i]:>10.2f} "
f"{STREUUNG[i]:>8.2f} {GRENZE[i]:>7.0f} "
f"{KOSTEN[i] / VERFUEGBAR[i]:>15,.0f}")
print(f"\nVollausbau liefert im Mittel {VERFUEGBAR @ GRENZE:.0f} MW, "
f"in der Kaeltewelle {(VERFUEGBAR * EINBRUCH) @ GRENZE:.0f} MW.")
# Zwei grosse, unabhaengige Testmengen. An ihnen wird JEDER Plan gemessen -
# einmal in der unterstellten Normalwelt, einmal in der echten Verteilung.
echt = ziehe_wetter(200_000, seed=771)
normalwelt = np.random.default_rng(4711).multivariate_normal(
VERFUEGBAR, SIGMA, size=200_000)
print("\n" + "=" * 78)
print(" (1) Mittelwertplan und Chance Constraints im Vergleich")
print("=" * 78)
print(KOPF)
print("-" * 78)
k_mittel, x_mittel = mittelwertplan()
stufen = [("Mittelwert", k_mittel, sicherheit(x_mittel, normalwelt))]
print(zeile("Mittelwert", k_mittel, x_mittel,
sicherheit(x_mittel, normalwelt), sicherheit(x_mittel, echt)))
plaene = {}
for alpha in (0.20, 0.10, 0.05, 0.01):
kosten, x = chance_constraint_analytisch(alpha)
plaene[alpha] = (kosten, x)
quote_normal = sicherheit(x, normalwelt)
stufen.append((f"Zusage {(1 - alpha) * 100:.0f} %", kosten, quote_normal))
print(zeile(f"Zusage {(1 - alpha) * 100:.0f} %", kosten, x,
quote_normal, sicherheit(x, echt)))
print("\n In der Normalwelt trifft jede Zusage ihren Wert - das Verfahren")
print(" rechnet richtig. Die Spalte 'echte Welt' kommt in Teil (3).")
print("\n" + "=" * 78)
print(" (2) Was kostet ein Prozentpunkt Versorgungssicherheit?")
print("=" * 78)
print(f"{'von -> nach':<26} {'Prozentpunkte':>13} {'Mehrkosten':>13} "
f"{'EUR je Punkt':>13}")
print("-" * 78)
for (n1, k1, q1), (n2, k2, q2) in zip(stufen, stufen[1:]):
d_punkte = (q2 - q1) * 100
d_kosten = k2 - k1
print(f"{n1 + ' -> ' + n2:<26} {d_punkte:>13.2f} {d_kosten:>13,.0f} "
f"{d_kosten / d_punkte:>13,.0f}")
erst = (stufen[1][1] - stufen[0][1]) / ((stufen[1][2] - stufen[0][2]) * 100)
letzt = (stufen[-1][1] - stufen[-2][1]) / ((stufen[-1][2] - stufen[-2][2]) * 100)
print(f"\n Der letzte Prozentpunkt kostet das {letzt / erst:.1f}-fache des ersten.")
print(" Sicherheit ist konvex bepreist - genau deshalb muss jemand")
print(" entscheiden, wie viel davon das Unternehmen kaufen will.")
print("\n" + "=" * 78)
print(" (3) Und wenn die Verteilung nicht normal ist?")
print("=" * 78)
k_soc, x_soc = plaene[0.05]
print(f"Die echte Welt kennt die Kaeltewelle mit Dunkelflaute: in "
f"{P_KAELTEWELLE * 100:.0f} % der Faelle liefern")
print(f"Wind {EINBRUCH[1] * 100:.0f} %, Sonne {EINBRUCH[2] * 100:.0f} % "
f"und - entscheidend - auch das Gaskraftwerk nur "
f"{EINBRUCH[0] * 100:.0f} %")
print("des Ueblichen. Alles bricht gleichzeitig ein.\n")
a_bau = ziehe_wetter(400, seed=20260908)
k_sz, x_sz = chance_constraint_szenarien(a_bau, 0.05)
print(KOPF)
print("-" * 78)
print(zeile("SOC, Zusage 95 %", k_soc, x_soc,
sicherheit(x_soc, normalwelt), sicherheit(x_soc, echt)))
print(zeile("Szenarien, 95 %", k_sz, x_sz,
sicherheit(x_sz, normalwelt), sicherheit(x_sz, echt)))
print(f"\n Der SOC-Plan verspricht 95 % und haelt "
f"{sicherheit(x_soc, echt) * 100:.1f} %. Nicht das Verfahren ist")
print(f" falsch, sondern die Annahme: In der Normalwelt liefert derselbe")
print(f" Plan {sicherheit(x_soc, normalwelt) * 100:.1f} %.")
print(f"\n Der Szenarioplan ({len(a_bau)} Szenarien, {len(a_bau)} "
f"Binaervariablen) kommt auf")
print(f" {sicherheit(x_sz, echt) * 100:.1f} % - und kostet dafuer "
f"{(k_sz / k_soc - 1) * 100:+.1f} %. Er kauft keine Windkraft mehr:")
print(" Was im Ernstfall ausfaellt, hilft der Zusage nicht.")
print("=" * 78)
```
**Ausgabe:**
```
==============================================================================
WAHRSCHEINLICHKEITSBESCHRAENKUNGEN IM KRAFTWERKSPARK
==============================================================================
Gesichert bereitzustellen: 500 MW
Technologie EUR/MW verfuegbar Streuung Grenze EUR je erw. MW
------------------------------------------------------------------------------
Gaskraftwerk 65,000 0.92 0.05 400 70,652
Windpark 24,000 0.35 0.16 250 68,571
Solarpark 12,000 0.18 0.10 600 66,667
Biomasse 60,000 0.85 0.04 350 70,588
Vollausbau liefert im Mittel 861 MW, in der Kaeltewelle 552 MW.
==============================================================================
(1) Mittelwertplan und Chance Constraints im Vergleich
==============================================================================
Plan Kosten (EUR) Gas Wind Sol Bio Normalwelt echte Welt
------------------------------------------------------------------------------
Mittelwert 34,694,565 8 250 600 350 50.08 % 46.18 %
Zusage 80 % 36,382,277 226 25 44 343 80.06 % 73.61 %
Zusage 90 % 36,994,777 233 20 35 349 89.99 % 82.82 %
Zusage 95 % 37,514,307 241 19 31 350 94.97 % 87.44 %
Zusage 99 % 38,529,698 258 18 28 350 98.97 % 91.05 %
In der Normalwelt trifft jede Zusage ihren Wert - das Verfahren
rechnet richtig. Die Spalte 'echte Welt' kommt in Teil (3).
==============================================================================
(2) Was kostet ein Prozentpunkt Versorgungssicherheit?
==============================================================================
von -> nach Prozentpunkte Mehrkosten EUR je Punkt
------------------------------------------------------------------------------
Mittelwert -> Zusage 80 % 29.98 1,687,712 56,289
Zusage 80 % -> Zusage 90 % 9.93 612,500 61,685
Zusage 90 % -> Zusage 95 % 4.98 519,530 104,365
Zusage 95 % -> Zusage 99 % 4.00 1,015,390 253,848
Der letzte Prozentpunkt kostet das 4.5-fache des ersten.
Sicherheit ist konvex bepreist - genau deshalb muss jemand
entscheiden, wie viel davon das Unternehmen kaufen will.
==============================================================================
(3) Und wenn die Verteilung nicht normal ist?
==============================================================================
Die echte Welt kennt die Kaeltewelle mit Dunkelflaute: in 8 % der Faelle liefern
Wind 10 %, Sonne 15 % und - entscheidend - auch das Gaskraftwerk nur 72 %
des Ueblichen. Alles bricht gleichzeitig ein.
Plan Kosten (EUR) Gas Wind Sol Bio Normalwelt echte Welt
------------------------------------------------------------------------------
SOC, Zusage 95 % 37,514,307 241 19 31 350 94.97 % 87.44 %
Szenarien, 95 % 43,760,709 350 0 0 350 100.00 % 94.84 %
Der SOC-Plan verspricht 95 % und haelt 87.4 %. Nicht das Verfahren ist
falsch, sondern die Annahme: In der Normalwelt liefert derselbe
Plan 95.0 %.
Der Szenarioplan (400 Szenarien, 400 Binaervariablen) kommt auf
94.8 % - und kostet dafuer +16.7 %. Er kauft keine Windkraft mehr:
Was im Ernstfall ausfaellt, hilft der Zusage nicht.
==============================================================================
```
**Drei Befunde, die man dem Plan nicht ansieht.**
**Erstens: Der Mittelwertplan fällt in der Hälfte aller Fälle aus.** Das ist kein Fehler, sondern die Definition des Erwartungswerts — und dieselbe Falle wie in [Abschnitt 12.3](#sec:unsicherheit-der-fluch-des-durchschnitts), nur teurer. Er kauft die billigsten Quellen je *erwarteter* Megawattstunde und maximiert Wind und Sonne bis an die Ausbaugrenze. Sobald die Zusage im Modell steht, dreht sich das Bild: Gas und Biomasse tragen den Plan, Wind und Sonne schrumpfen auf einen Rest.
**Zweitens: Sicherheit ist konvex bepreist.** Die ersten dreißig Prozentpunkte kosten rund 56 000 € pro Punkt, die letzten vier rund 254 000 € — das **4,5-fache**. Das ist die Zahl, die in die Vorlage gehört: Nicht „was kostet Versorgungssicherheit“, sondern „was kostet der *nächste* Prozentpunkt“. Wer 99,9 % fordert, ohne diese Kurve gesehen zu haben, fordert ins Blaue.
**Drittens — und das ist der unangenehme Befund: Die Zusage gilt nur für die unterstellte Verteilung.** Der Plan verspricht 95 % und hält **87,4 %**. Nicht weil das Verfahren falsch rechnet: In einer reinen Normalwelt liefert derselbe Plan exakt seine 95,0 %. Sondern weil die Normalverteilung eine Kältewelle mit Dunkelflaute nicht kennt. In der bricht **alles zugleich** ein — auch das Gaskraftwerk, weil bei Frost der Netzdruck fällt. Eine Kovarianzmatrix mit Korrelationen um null kann so etwas nicht ausdrücken.
Der szenariobasierte Weg kennt diese Fälle, weil sie in den Daten stehen. Er kommt auf 94,8 %, kostet dafür 16,7 % mehr — und kauft **keine Windkraft mehr**. Die Logik dahinter ist hart und richtig: Was im Ernstfall ausfällt, hilft der Zusage nicht.
> **⚠️ Die Szenariomethode überanpasst — und mehr Szenarien helfen nicht verlässlich** Bei $S$ Szenarien und $\alpha = 5\,\%$ darf das Modell genau $0{,}05 \cdot S$ davon ignorieren — und es sucht sich die **teuersten** aus. In der Stichprobe trifft es seine Quote dadurch immer; außerhalb streut sie.
>
> Gemessen an zwölf Läufen dieses Modells (je vier Ziehungen bei $S = 200$, $400$, $800$, geprüft an 200 000 unabhängigen Szenarien): Die tatsächliche Quote lag zwischen **93,1 % und 96,7 %**. Die Spanne wurde von $S = 200$ auf $400$ enger (3,5 → 1,2 Prozentpunkte), bei $S = 800$ aber wieder breiter (3,1) — die Zahl der Szenarien allein schließt die Lücke also nicht.
>
> **Konsequenz für die Praxis:** Eine mit Szenarien erkaufte Zusage immer an einer **zurückgehaltenen** Stichprobe nachmessen, so wie es das Programm oben tut. Wer nur die Trefferquote in den Baudaten berichtet, berichtet eine Tautologie — dieselbe Falle wie beim Backtest in [Kapitel 21](#kap-handelsmaschine).
> **🎯 Merksatz** Die robuste Optimierung fragt „was, wenn alles schiefgeht?“, die Chance Constraint „wie oft darf es schiefgehen?“. Nur die zweite Frage hat eine Antwort, über die man verhandeln kann — und nur sie zwingt dazu, den Preis eines Prozentpunkts Sicherheit zu beziffern.
---
## 12.8 Übungsaufgaben {#sec:unsicherheit-uebungsaufgaben}
> Lösungen: [Abschnitt A.12](#sec:loesungen-unsicherheit).
**Aufgabe 12.1 ⭐ — Fluch des Durchschnitts erkennen.** Ein Bauunternehmer plant mit der *durchschnittlichen* Bauzeit von 8 Monaten. Warum ist die *erwartete* Fertigstellung trotzdem später als 8 Monate, wenn Verzögerungen wahrscheinlicher sind als Beschleunigungen? Nennen Sie zwei weitere Alltagsbeispiele.
**Aufgabe 12.2 ⭐ — Ansatz wählen.** Welcher der drei Ansätze passt? Begründen Sie: (a) Wie viele Notstromaggregate für ein Krankenhaus? (b) Wie viel Weizen einkaufen bei bekannter Preisverteilung? (c) Wie hoch ein Deich gebaut werden muss? (d) Wie viele Saisonkräfte einstellen bei bekannten Nachfrageszenarien?
**Aufgabe 12.2 ⭐ — Ansatz wählen.** Welcher der vier Ansätze passt? Begründen Sie: (a) Wie viele Notstromaggregate für ein Krankenhaus? (b) Wie viel Weizen einkaufen bei bekannter Preisverteilung? (c) Wie hoch ein Deich gebaut werden muss? (d) Wie viele Saisonkräfte einstellen bei bekannten Nachfrageszenarien? (e) Wie viel Speicherkapazität, damit ein Gasnetz an 99 % aller Wintertage hält?
**Aufgabe 12.3 ⭐⭐ — Zweistufiges Modell rechnen.** Wiederholen Sie die Handrechnung *Warum der Mittelwert in die Irre führt* mit geänderten Kosten: Spot 60 € statt 120 €. (a) Wie ändert sich die optimale Kapazität? (b) Erklären Sie die Richtung der Änderung. (c) Bei welchem Spot-Preis wäre die Mittelwert-Planung optimal?
@ -13491,11 +13865,13 @@ if __name__ == "__main__":
**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 der Kosten (Mittelwert der schlechtesten 5 %). (c) Zeichnen Sie ein Histogramm der Kosten für drei Kapazitäten.
**Aufgabe 12.6 ⭐⭐⭐ — Budgeted Uncertainty.** Erweitern Sie `Robuste_Optimierung.py` um den Ansatz von Bertsimas/Sim: Höchstens $\Gamma$ Titel nehmen gleichzeitig ihren Worst Case an. Variieren Sie $\Gamma \in \{0, 1, 2, 3, 4\}$ und stellen Sie den Verlauf von Ertrag und Absicherung dar. (Hinweis: Bei $\Gamma$ ganzzahlig genügt es, die $\Gamma$ größten $\delta_i w_i$ abzuziehen — das lässt sich in CVXPY mit `cp.sum_largest` formulieren.)
**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.
**Aufgabe 12.7 ⭐⭐⭐ — Budgeted Uncertainty.** Erweitern Sie `Robuste_Optimierung.py` um den Ansatz von Bertsimas/Sim: Höchstens $\Gamma$ Titel nehmen gleichzeitig ihren Worst Case an. Variieren Sie $\Gamma \in \{0, 1, 2, 3, 4\}$ und stellen Sie den Verlauf von Ertrag und Absicherung dar. (Hinweis: Bei $\Gamma$ ganzzahlig genügt es, die $\Gamma$ größten $\delta_i w_i$ abzuziehen — das lässt sich in CVXPY mit `cp.sum_largest` formulieren.)
---
## 12.8 Finde den Denkfehler {#sec:unsicherheit-denkfehler}
## 12.9 Finde den Denkfehler {#sec:unsicherheit-denkfehler}
> **🐛 Finde den Denkfehler 9.1: Warum jedes Projekt zu spät fertig wird**
>
@ -13535,7 +13911,7 @@ if __name__ == "__main__":
---
## 12.9 Micro-Quiz {#sec:unsicherheit-quiz}
## 12.10 Micro-Quiz {#sec:unsicherheit-quiz}
> **❓ Micro-Quiz 9: Drei Fragen zum Selbstcheck**
>
@ -13549,7 +13925,7 @@ if __name__ == "__main__":
---
## 12.10 Selbsttest {#sec:unsicherheit-selbsttest}
## 12.11 Selbsttest {#sec:unsicherheit-selbsttest}
> Antworten: [Anhang A](#selbsttest-loesung-unsicherheit).
@ -13558,10 +13934,12 @@ if __name__ == "__main__":
3. Was misst der EVPI, und wofür ist er praktisch nützlich?
4. Warum braucht robuste Optimierung keine Wahrscheinlichkeiten?
5. Wie macht man ein Min-Max-Problem mit Box-Unsicherheit lösbar?
6. Warum wird aus $\mathbb{P}(\mathbf{a}^\top\mathbf{x} \ge b) \ge 1-\alpha$ unter Normalverteilung eine **Norm** und nicht ein fester Zuschlag je Variable?
7. Ein Plan mit Chance Constraint verspricht 95 % und hält gemessen 87 %. Woran liegt das — und was ändert die szenariobasierte Formulierung daran?
---
## 12.11 Zusammenfassung {#sec:unsicherheit-zusammenfassung}
## 12.12 Zusammenfassung {#sec:unsicherheit-zusammenfassung}
* **Der Fluch des Durchschnitts** ist kein Randphänomen und hat zwei Gesichter. Bei asymmetrischen **Kosten** liegt das Optimum systematisch neben dem Mittelwert — das Newsvendor-Verhältnis $c_{-}/(c_{-}+c_{+})$ sagt, wie weit. Bei asymmetrischer **Verknüpfung** (Maximum über parallele Vorgänge) ist der Erwartungswert des Ganzen größer als das Ganze der Erwartungswerte. Beide Male gilt: Der Mittelwert einer Funktion ist nicht die Funktion des Mittelwerts (Jensensche Ungleichung).
* **Eine Terminzusage ist ein Quantil, kein Mittelwert.** Wer den Erwartungswert zusagt, reißt den Termin bei fünf parallelen Vorgängen in 95 % der Fälle.
@ -13569,6 +13947,9 @@ if __name__ == "__main__":
* **Zweistufige stochastische Programme** trennen die Festlegung von der Reaktion — ein $\mathbf{x}$, aber je Szenario ein $\mathbf{y}_s$.
* **Der EVPI** begrenzt, was eine perfekte Prognose wert sein darf.
* **Robuste Optimierung** braucht keine Wahrscheinlichkeiten, nur eine Unsicherheitsmenge — und wird für einfache Mengen zu einem gewöhnlichen Problem mit Abzugsterm.
* **Chance Constraints** schreiben die Zusage selbst ins Modell. Unter Normalverteilung wird daraus eine **Kegelbedingung** (der Sicherheitszuschlag ist eine Norm, deshalb belohnt sie Mischung), szenariobasiert ein **MILP mit Big-M** ohne jede Verteilungsannahme.
* **Sicherheit ist konvex bepreist.** Im Beispiel kostet der letzte Prozentpunkt das 4,5-fache des ersten. Die richtige Managementfrage lautet nicht „was kostet Sicherheit“, sondern „was kostet der *nächste* Prozentpunkt“.
* **Eine Zusage gilt nur für die unterstellte Verteilung.** Ein Plan, der unter Normalverteilung 95 % verspricht, hielt gemessen 87 %, weil das Modell die Kältewelle nicht kannte, in der *alles* zugleich ausfällt. Szenariobasierte Zusagen wiederum überanpassen — beide müssen an zurückgehaltenen Daten nachgemessen werden.
* **Beziffern Sie immer Preis und Nutzen der Absicherung.** Ohne beide Zahlen ist die Entscheidung nicht begründbar.
**Ausblick.** [Kapitel 13](#kap-dynamische-programmierung) fügt die Zeitdimension hinzu: Entscheidungen, die über viele Perioden aufeinander aufbauen — gelöst mit der Bellman-Gleichung.
@ -24556,7 +24937,7 @@ Der Ausweg auf `scipy` hat das Warnsystem umgangen, nicht das Problem gelöst. R
**9.1 — Fluch des Durchschnitts.** Weil sich Verzögerungen **fortpflanzen** und die Verteilung rechtsschief ist: Ein Gewerk, das früher fertig wird, beschleunigt selten den Gesamtablauf (der nächste Schritt ist noch nicht bereit), ein verspätetes verzögert alles. Weitere Beispiele: Wartezeiten in Warteschlangen (nichtlinear in der Auslastung), Projektkosten mit Nachträgen.
**9.2 — Ansatz wählen.** (a) robust (Ausfall ist existenziell, Wahrscheinlichkeiten unzuverlässig). (b) stochastisch (Verteilung bekannt). (c) robust bzw. Extremwertstatistik (seltene Ereignisse, katastrophale Folgen). (d) stochastisch (Szenarien mit Wahrscheinlichkeiten liegen vor).
**9.2 — Ansatz wählen.** (a) robust (Ausfall ist existenziell, Wahrscheinlichkeiten unzuverlässig). (b) stochastisch (Verteilung bekannt). (c) robust bzw. Extremwertstatistik (seltene Ereignisse, katastrophale Folgen). (d) stochastisch (Szenarien mit Wahrscheinlichkeiten liegen vor). (e) Chance Constraint — die Zusage ist bereits als Quote formuliert („an 99 % aller Wintertage“). Robust wäre hier zu teuer (es gibt immer einen kälteren Tag), der Erwartungswert zu schwach (er sagt nichts über die Zusage).
**9.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.
@ -24564,7 +24945,9 @@ Der Ausweg auf `scipy` hat das Warnsystem umgangen, nicht das Problem gelöst. R
**9.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.
**9.6 — Budgeted Uncertainty.**
**9.6 — Den Preis der Zusage selbst bestimmen.** (a) Die Kosten je Prozentpunkt steigen weiter steil an; der Mix verschiebt sich dabei fast nur noch zugunsten des Gaskraftwerks, weil Biomasse längst an ihrer Ausbaugrenze liegt. Wind und Sonne bleiben bei einem kleinen Rest — sie senken über ihre Gegenläufigkeit die Norm, tragen zur gesicherten Leistung aber kaum bei. (b) Der Unterschied ist **nicht** numerisch, sondern inhaltlich. Bei 200 MW Biomasse liefert selbst der **Vollausbau** in der Kältewelle nur rund 440 MW — 7,5 % der Szenarien sind schlicht nicht bedienbar, egal wie viel Geld man ausgibt. Das Szenariomodell sieht diese Fälle in den Daten und meldet korrekt `infeasible`, sobald die Zusage über 92 % steigt. Das analytische Modell kennt sie nicht: Für eine Normalverteilung ist jede Zusage unter 100 % erfüllbar, wenn man nur genug Streuung wegkauft. Es meldet `optimal` — und der Plan hält gemessen 87,4 %. Glauben sollte man dem Szenariomodell: Ein `infeasible` ist hier die **richtige** Antwort. Es sagt, dass die Zusage nicht am Budget scheitert, sondern am Kraftwerkspark, und dass nicht mehr Geld hilft, sondern nur eine andere Anlage oder eine kleinere Zusage. (c) Sinngemäß: „99,99 % kosten nicht 5 % mehr als 99 %, sondern ein Vielfaches — der letzte Prozentpunkt ist bereits 4,5-mal so teuer wie der erste. Sagen Sie mir, was ein Ausfalltag das Unternehmen kostet, dann rechne ich aus, welche Quote sich lohnt. Und die Zusage gilt nur für die Wetterlagen, die wir modelliert haben — die Kältewelle gehört hinein.“
**9.7 — Budgeted Uncertainty.**
```python
abzug = cp.sum_largest(cp.multiply(UNSICHERHEIT, w), Gamma)
ziel = cp.Maximize(MU_SCHAETZUNG @ w - abzug - 0.5*LAMBDA*cp.quad_form(w, SIGMA))
@ -24628,6 +25011,8 @@ Und die Formulierung gegenüber dem Auftraggeber lautet nicht „der Umbau dauer
3. Die Differenz zwischen Kosten unter Unsicherheit und Kosten bei perfektem Wissen — eine **Obergrenze** für den Wert jeder Prognoseverbesserung.
4. Weil sie nur eine **Menge** möglicher Werte braucht, nicht deren Verteilung — sie optimiert gegen das schlechteste Element dieser Menge.
5. Für einfache Mengen (Box, Ellipsoid) lässt sich das innere Maximum geschlossen ausrechnen und wird zu einem Abzugsterm; das Gesamtproblem bleibt konvex.
6. Weil die Streuung der Summe $\mathbf{a}^\top\mathbf{x}$ nicht die Summe der Streuungen ist: $\sqrt{\mathbf{x}^\top\boldsymbol{\Sigma}\mathbf{x}}$ enthält die **Kovarianzen**. Ein fester Zuschlag je Variable wäre linear und würde deshalb übersehen, dass sich gegenläufige Größen teilweise aufheben — die Norm belohnt Mischung, ein linearer Aufschlag nicht.
7. Weil die Zusage nur so gut ist wie die unterstellte Verteilung. Die Normalverteilung kennt keine Ereignisse, in denen alle Quellen **gleichzeitig** ausfallen; ihre schwachen Korrelationen unterschätzen genau den Fall, der die Zusage bricht. Die szenariobasierte Formulierung hat diese Fälle in den Daten und trifft die Quote — erkauft mit Mehrkosten und mit dem Risiko, sich an die verwendete Stichprobe anzupassen.
---