Kapitel 12: Optimierung unter Unsicherheit — Monte-Carlo, Stochastik, Robustheit
📌 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.
Voraussetzungen: Kapitel 5, Kapitel 11. 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.
Zeitbedarf: ca. 5,5 Stunden.
Programme:
Fluch_des_Durchschnitts.py
Monte_Carlo.py
Stochastische_Optimierung.py
Robuste_Optimierung.pyNotebook: unsicherheit.ipynb
In Google Colab öffnen
12.1 In 5 Minuten gelöst
🚀 In 5 Minuten gelöst: Wie viele Ersatzteile bestellen?
Ein Betrieb bestellt vor der Wintersaison Ersatzteile — einmal, danach ist die Lieferkette bis zum Frühjahr zu. Der Bedarf schwankt, im Mittel werden 30 Stück gebraucht (Poisson-verteilt).
Fall Kosten je Stück Zu viel bestellt — Teil bleibt liegen und wird abgeschrieben 120 € Zu wenig bestellt — Maschine steht bis zur Nachlieferung 1 400 € Wie viele bestellen Sie?
import numpy as np KOSTEN_ZUVIEL, KOSTEN_ZUWENIG = 120.0, 1400.0 bedarf = np.random.default_rng(7).poisson(30, 200_000) # 200.000 Winter def kosten(menge): zuviel = np.maximum(menge - bedarf, 0) zuwenig = np.maximum(bedarf - menge, 0) return (KOSTEN_ZUVIEL * zuviel + KOSTEN_ZUWENIG * zuwenig).mean() kandidaten = np.arange(20, 61) werte = np.array([kosten(m) for m in kandidaten]) print("Optimum:", kandidaten[werte.argmin()], "Stueck,", f"{werte.min():,.0f} EUR") print("Mittlerer Bedarf 30:", f"{kosten(30):,.0f} EUR")Ausgabe:
Optimum: 38 Stueck, 1,270 EUR Mittlerer Bedarf 30: 3,306 EUR
Die naheliegende Antwort — „im Mittel brauchen wir 30, also bestellen wir 30“ — kostet das 2,6-Fache. 3 306 € statt 1 270 €, ein Aufschlag von 160 %.
Der Grund liegt in der Asymmetrie: Ein Teil zu viel kostet 120 €, ein Teil zu wenig kostet 1 400 €. Beides ist nicht gleich schlimm, also darf man auch nicht in der Mitte landen. Man muss sich bewusst auf die günstigere Seite des Fehlers stellen.
Wie weit? Dafür gibt es eine geschlossene Formel — das kritische Verhältnis:
q^{*} = \frac{c_{\text{zu wenig}}}{c_{\text{zu wenig}} + c_{\text{zu viel}}} = \frac{1400}{1400 + 120} = 0{,}921
🔤 Formel-Übersetzer
Mathematik Alltagssprache c_{\text{zu wenig}} „Was kostet mich ein Stück, das ich gebraucht hätte und nicht habe?“ c_{\text{zu viel}} „Was kostet mich ein Stück, das ich habe und nicht brauche?“ q^{*} = 0{,}921 „Bestelle so viel, dass der Bedarf in 92,1 % aller Winter gedeckt ist.“ Bestellmenge = F^{-1}(q^{*}) „Nimm das 92,1-%-Quantil der Bedarfsverteilung“ — hier 38 Stück. In einem Satz: Je teurer der Engpass gegenüber dem Überbestand, desto weiter über den Mittelwert hinaus muss man bestellen.
Das Quantil zu 0,921 liegt bei genau 38 Stück — dasselbe Ergebnis, das die Simulation oben gefunden hat. Zwei völlig verschiedene Wege, dieselbe Zahl.
🎯 Merksatz Die optimale Entscheidung unter Unsicherheit ist fast nie die Entscheidung, die für den Mittelwert optimal wäre. Sie hängt davon ab, welcher der beiden Fehler teurer ist — und verschiebt sich zu der Seite, auf der Irren billiger ist. Wer mit dem Mittelwert plant, hat diese Frage nie gestellt.
Dieses Muster heißt Newsvendor-Problem (deutsch: Zeitungsjungen-Problem) und taucht überall dort auf, wo einmal entschieden und danach beobachtet wird: Ersatzteile, Frischwaren, Saisonware, Personalreserve, Kraftwerksvorhaltung. Der Rest dieses Kapitels verallgemeinert es — von einer Zahl auf ganze Modelle, und von einer bekannten Verteilung auf den Fall, dass man nicht einmal die kennt.
12.2 Lernziele
Nach diesem Kapitel können Sie …
- … den Fluch des Durchschnitts (Flaw of Averages) an einem Beispiel erklären.
- … ein zweistufiges stochastisches Programm mit Recourse formulieren.
- … Monte-Carlo einsetzen, um Verteilungen statt Punktschätzungen zu bewerten.
- … ein robustes Modell mit Unsicherheitsmenge aufstellen und seinen Preis beziffern.
- … begründen, welcher der drei Ansätze für ein gegebenes Problem passt.
- … das kritische Verhältnis eines Newsvendor-Problems aufstellen und daraus die optimale Bestellmenge als Quantil ablesen.
- … eine Terminzusage als Quantil formulieren statt als Mittelwert.
12.3 Der Fluch des Durchschnitts
Der naheliegende Umgang mit Unsicherheit lautet: „Wir setzen den Erwartungswert ein und rechnen deterministisch.“ Das ist fast immer falsch — und zwar nicht ungenau, sondern systematisch verzerrt.
✏️ Handrechnung 12.1: Warum der Mittelwert in die Irre führt
Ein Betreiber braucht Serverkapazität. Der Bedarf ist:
Szenario Wahrscheinlichkeit Bedarf Ruhig 50 % 100 Volatil 30 % 250 Crash 20 % 500 Erwartungswert: 0{,}5\cdot100 + 0{,}3\cdot250 + 0{,}2\cdot500 = 50+75+100 = 225.
Kosten: Vorabkauf 40 €/Einheit; fehlende Kapazität muss kurzfristig für 120 € zugekauft werden; überschüssige Kapazität kostet 5 € Verwaltung.
Naive Planung mit x = 225: * Ruhig (Bedarf 100): 125 zu viel → 40\cdot225 + 5\cdot125 = 9000 + 625 = 9625 * Volatil (250): 25 zu wenig → 9000 + 120\cdot25 = 9000 + 3000 = 12\,000 * Crash (500): 275 zu wenig → 9000 + 120\cdot275 = 9000 + 33\,000 = 42\,000 * Erwartete Kosten: 0{,}5\cdot9625 + 0{,}3\cdot12\,000 + 0{,}2\cdot42\,000 = 4812{,}5 + 3600 + 8400 = \mathbf{16\,812{,}50}
Stochastisch optimale Planung mit x = 250: * Ruhig: 150 zu viel → 10\,000 + 750 = 10\,750 * Volatil: passt genau → 10\,000 * Crash: 250 zu wenig → 10\,000 + 30\,000 = 40\,000 * Erwartete Kosten: 0{,}5\cdot10\,750 + 0{,}3\cdot10\,000 + 0{,}2\cdot40\,000 = 5375 + 3000 + 8000 = \mathbf{16\,375{,}00}
Die naive Planung kostet 437,50 € mehr — rund 2,7 % Aufschlag für das Einsetzen eines Mittelwerts, den es als Szenario gar nicht gibt. Beachten Sie: Der Aufschlag wirkt klein, weil bei nur drei Szenarien 225 und 250 nahe beieinanderliegen. Entscheidend ist die Richtung: Das Optimum liegt systematisch über dem Mittelwert, und zwar bei genau jenem Szenariowert, an dem die Kostenbalance kippt.
Dass x = 250 tatsächlich das Minimum ist und nicht nur eine plausible Vermutung, zeigt ein vollständiger Scan über alle möglichen Kapazitäten:
#!/usr/bin/env python3
# Fluch_des_Durchschnitts.py
"""
Kapitel Unsicherheit: Der Fluch des Durchschnitts (die Handrechnung dazu) als Scan ueber alle
moeglichen Kapazitaeten - zeigt, dass das Optimum nicht beim Mittelwert liegt.
"""
import numpy as np
SZENARIEN = np.array([100, 250, 500])
WAHRSCHEINLICHKEITEN = np.array([0.5, 0.3, 0.2])
PREIS_VORAB = 40.0
PREIS_ZUKAUF = 120.0
PREIS_VERWALTUNG = 5.0
ERWARTUNGSWERT = float(SZENARIEN @ WAHRSCHEINLICHKEITEN)
def erwartete_kosten(x):
kosten = np.where(
SZENARIEN >= x,
PREIS_VORAB * x + PREIS_ZUKAUF * (SZENARIEN - x),
PREIS_VORAB * x + PREIS_VERWALTUNG * (x - SZENARIEN),
)
return float(kosten @ WAHRSCHEINLICHKEITEN)
if __name__ == "__main__":
print("=" * 70)
print(" DER FLUCH DES DURCHSCHNITTS")
print("=" * 70)
print(f"Erwarteter Bedarf (Mittelwert): {ERWARTUNGSWERT:.1f}")
print(f"Kosten bei naiver Planung x={ERWARTUNGSWERT:.0f}: "
f"{erwartete_kosten(ERWARTUNGSWERT):,.2f} EUR\n")
x_werte = np.arange(0, 501, 1)
kosten_werte = np.array([erwartete_kosten(x) for x in x_werte])
x_optimal = x_werte[np.argmin(kosten_werte)]
kosten_optimal = kosten_werte.min()
print(f"Optimales x (durch Scan gefunden): {x_optimal}")
print(f"Kosten beim Optimum: {kosten_optimal:,.2f} EUR")
print(f"Ersparnis gegenueber naiver Planung: "
f"{erwartete_kosten(ERWARTUNGSWERT) - kosten_optimal:,.2f} EUR\n")
print("Kosten fuer ausgewaehlte x zum Vergleich:")
for x in [100, 225, 250, 300, 500]:
markierung = " <- Mittelwert" if x == 225 else (" <- Optimum" if x == 250 else "")
print(f" x={x:4d}: {erwartete_kosten(x):>12,.2f} EUR{markierung}")
print("\nDas Optimum liegt exakt auf einem Szenariowert (250 = 'Volatil'),")
print("nicht beim Mittelwert 225 - typisch fuer asymmetrische Kostenfunktionen.")Erwartete Ausgabe:
======================================================================
DER FLUCH DES DURCHSCHNITTS
======================================================================
Erwarteter Bedarf (Mittelwert): 225.0
Kosten bei naiver Planung x=225: 16,812.50 EUR
Optimales x (durch Scan gefunden): 250
Kosten beim Optimum: 16,375.00 EUR
Ersparnis gegenueber naiver Planung: 437.50 EUR
Kosten fuer ausgewaehlte x zum Vergleich:
x= 100: 19,000.00 EUR
x= 225: 16,812.50 EUR <- Mittelwert
x= 250: 16,375.00 EUR <- Optimum
x= 300: 17,375.00 EUR
x= 500: 21,375.00 EUR
Das Optimum liegt exakt auf einem Szenariowert (250 = 'Volatil'),
nicht beim Mittelwert 225 - typisch fuer asymmetrische Kostenfunktionen.
Kein Rechentrick, sondern brute-force über alle ganzzahligen x von 0 bis 500 — das Optimum landet exakt dort, wo es die Handrechnung vorhersagt.
Warum? Die Kostenfunktion ist asymmetrisch: Unterdeckung kostet 120, Überdeckung nur 5. Bei asymmetrischen Kosten liegt das Optimum nie beim Mittelwert, sondern verschoben in die „billigere“ Richtung. Formal ist das die Jensensche Ungleichung: Für konvexe Kostenfunktionen gilt \mathbb{E}[f(X)] \ge f(\mathbb{E}[X]) — der Erwartungswert der Kosten ist größer als die Kosten des Erwartungswerts.
🎯 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
| 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 |
12.4 Monte-Carlo-Simulation
Monte-Carlo heißt schlicht: Ziehe sehr viele Zufallsszenarien, werte für jedes den Plan aus, und betrachte die Verteilung der Ergebnisse statt eines einzigen Werts.
#!/usr/bin/env python3
# Monte_Carlo.py
"""
Kapitel Unsicherheit: Monte-Carlo-Bewertung von Kapazitaetsplaenen.
Monte Carlo OPTIMIERT nicht - es BEWERTET. Der Nutzen liegt darin, dass man
beliebige Kennzahlen ablesen kann: Erwartungswert, Quantile, Ausfallwahr-
scheinlichkeit, Worst Case. Genau diese Groessen braucht man, um zwischen
Plaenen zu entscheiden.
"""
import numpy as np
KOSTEN_VORAB = 40.0 # EUR je Einheit, im Voraus gekauft
KOSTEN_SPOT = 120.0 # EUR je Einheit, kurzfristig zugekauft
KOSTEN_LEERLAUF = 5.0 # EUR je ungenutzter Einheit
ANZAHL_ZIEHUNGEN = 100_000
def ziehe_bedarf(rng, ziehungen):
"""
Bedarfsmodell: Mischverteilung aus Normalbetrieb und seltenen Lastspitzen.
Realistischer als eine reine Normalverteilung - Krisen sind selten,
aber extrem (fat tail).
"""
normal = rng.normal(loc=150, scale=40, size=ziehungen)
spitze = rng.normal(loc=450, scale=80, size=ziehungen)
ist_spitze = rng.random(ziehungen) < 0.15 # 15 % Lastspitzen
return np.maximum(np.where(ist_spitze, spitze, normal), 0.0)
def kosten_fuer(kapazitaet, bedarf):
"""Gesamtkosten je Szenario fuer eine gegebene Vorabkapazitaet."""
unterdeckung = np.maximum(bedarf - kapazitaet, 0.0)
ueberdeckung = np.maximum(kapazitaet - bedarf, 0.0)
return (KOSTEN_VORAB * kapazitaet
+ KOSTEN_SPOT * unterdeckung
+ KOSTEN_LEERLAUF * ueberdeckung)
if __name__ == "__main__":
rng = np.random.default_rng(2026)
bedarf = ziehe_bedarf(rng, ANZAHL_ZIEHUNGEN)
print("=" * 88)
print(f" MONTE-CARLO-BEWERTUNG ({ANZAHL_ZIEHUNGEN:,} Szenarien)")
print("=" * 88)
print(f"Bedarfsverteilung: Mittelwert {bedarf.mean():.1f} | "
f"Median {np.median(bedarf):.1f} | "
f"95%-Quantil {np.percentile(bedarf, 95):.1f} | "
f"Maximum {bedarf.max():.1f}")
print("Der Median liegt deutlich unter dem Mittelwert - die Verteilung ist")
print("rechtsschief. Genau hier fuehrt Planung mit dem Mittelwert in die Irre.\n")
print(f"{'Kapazitaet':>10} | {'Erw. Kosten':>12} | {'Median':>10} | "
f"{'95%-Quantil':>12} | {'Unterdeckung':>12}")
print("-" * 88)
kandidaten = [150, 200, 225, 250, 300, 350, 400]
ergebnisse = []
for kapazitaet in kandidaten:
kosten = kosten_fuer(kapazitaet, bedarf)
p_unterdeckung = float(np.mean(bedarf > kapazitaet))
ergebnisse.append((kapazitaet, kosten.mean(), p_unterdeckung))
print(f"{kapazitaet:>10} | {kosten.mean():>12,.0f} | "
f"{np.median(kosten):>10,.0f} | {np.percentile(kosten, 95):>12,.0f} | "
f"{p_unterdeckung*100:>11.1f} %")
beste = min(ergebnisse, key=lambda t: t[1])
print("-" * 88)
print(f"Bester Kandidat: Kapazitaet {beste[0]} mit erwarteten Kosten "
f"{beste[1]:,.0f} EUR")
# --- Feinsuche ueber ein Raster ---------------------------------------
raster = np.arange(100, 500, 5)
erwartete = np.array([kosten_fuer(k, bedarf).mean() for k in raster])
optimum = raster[int(np.argmin(erwartete))]
print(f"Feinsuche (Raster 100..500): Optimum bei Kapazitaet {optimum}, "
f"Kosten {erwartete.min():,.0f} EUR")
# --- Vergleich mit der naiven Mittelwertplanung ----------------------
naiv = int(round(bedarf.mean()))
kosten_naiv = kosten_fuer(naiv, bedarf).mean()
kosten_opt = kosten_fuer(optimum, bedarf).mean()
print("\n--- Fluch des Durchschnitts, gemessen ---")
print(f" Planung mit Mittelwert ({naiv}): {kosten_naiv:,.0f} EUR")
print(f" Monte-Carlo-Optimum ({optimum}): {kosten_opt:,.0f} EUR")
print(f" Mehrkosten der naiven Planung: {kosten_naiv - kosten_opt:,.0f} EUR "
f"({(kosten_naiv/kosten_opt - 1)*100:.1f} %)")
print("=" * 88)Erwartete Ausgabe (gekürzt):
========================================================================================
MONTE-CARLO-BEWERTUNG (100,000 Szenarien)
========================================================================================
Bedarfsverteilung: Mittelwert 195.7 | Median 159.2 | 95%-Quantil 485.2 | Maximum 753.3
Der Median liegt deutlich unter dem Mittelwert - die Verteilung ist
rechtsschief. Genau hier fuehrt Planung mit dem Mittelwert in die Irre.
Kapazitaet | Erw. Kosten | Median | 95%-Quantil | Unterdeckung
----------------------------------------------------------------------------------------
150 | 13,169 | 7,104 | 46,220 | 57.8 %
200 | 12,989 | 8,345 | 42,220 | 24.1 %
225 | 13,475 | 9,432 | 40,220 | 17.8 %
250 | 14,085 | 10,546 | 38,220 | 15.6 %
300 | 15,391 | 12,791 | 34,220 | 14.8 %
350 | 16,746 | 15,033 | 30,220 | 13.6 %
400 | 18,214 | 17,266 | 26,220 | 11.1 %
----------------------------------------------------------------------------------------
Bester Kandidat: Kapazitaet 200 mit erwarteten Kosten 12,989 EUR
Feinsuche (Raster 100..500): Optimum bei Kapazitaet 180, Kosten 12,810 EUR
--- Fluch des Durchschnitts, gemessen ---
Planung mit Mittelwert (196): 12,934 EUR
Monte-Carlo-Optimum (180): 12,810 EUR
Mehrkosten der naiven Planung: 124 EUR (1.0 %)
========================================================================================
🎯 Eine wichtige Einschränkung — und was man daraus lernt
Hier kostet die naive Mittelwertplanung nur 1 %. In der Handrechnung zum Fluch des Durchschnitts waren es 2,7 %, in Lehrbüchern liest man von 20 % und mehr. Wie groß der Effekt ist, hängt von der Verteilung ab — und das ist selbst die Lektion.
Bei dieser Mischverteilung liegt zwischen dem Normalbetrieb (um 150) und den Lastspitzen (um 450) ein Bereich, in dem kaum Wahrscheinlichkeitsmasse liegt. Zusätzliche Kapazität zwischen 200 und 400 nützt daher wenig: Sie ist im Normalfall Leerlauf und reicht im Krisenfall trotzdem nicht. Deshalb ist die Kostenkurve dort flach, und die Wahl zwischen 180 und 196 macht kaum einen Unterschied.
Was Sie mitnehmen sollten: Die Frage „Wie teuer ist Mittelwertplanung?“ hat keine allgemeine Antwort — rechnen Sie es aus. Genau dafür ist Monte-Carlo da. Und beachten Sie die Spalte „Unterdeckung“: Bei Kapazität 200 wird in 24 % der Fälle nachgekauft. Ob das akzeptabel ist, entscheidet kein Optimierer, sondern ein Servicelevel-Ziel (Übung 9.5).
💡 Wann Monte-Carlo das richtige Werkzeug ist Immer dann, wenn Sie eine Kennzahl brauchen, die keine Formel hat: die Wahrscheinlichkeit, ein Servicelevel zu verfehlen; der erwartete Verlust in den schlechtesten 5 % der Fälle; die Verteilung der Projektdauer. Der Preis ist, dass Monte-Carlo nur bewertet — die Optimierung müssen Sie durch Rastersuche oder ein eigenes Modell ergänzen.
12.5 Zweistufige stochastische Programmierung
Das zweistufige Modell mit Recourse bildet ab, dass Entscheidungen zeitlich gestaffelt sind:
- Stufe 1 (here and now, \mathbf{x}): muss jetzt getroffen werden, bevor der Zufall sich zeigt — Serverkapazität kaufen, Produktion planen, Portfolio aufsetzen.
- Stufe 2 (wait and see, \mathbf{y}_s): Korrekturmaßnahmen, nachdem Szenario s eingetreten ist — Spot-Zukauf, Überstunden, Notverkauf.
\min_{\mathbf{x}} \quad \mathbf{c}^\top\mathbf{x} \;+\; \sum_{s=1}^S p_s\,\mathbf{q}_s^\top\mathbf{y}_s
\begin{aligned} \mathbf{A}\mathbf{x} &\le \mathbf{b} && \text{(Stufe-1-Restriktionen)}\\ \mathbf{T}_s\mathbf{x} + \mathbf{W}_s\mathbf{y}_s &\le \mathbf{h}_s \quad \forall s && \text{(Kopplung je Szenario)}\\ \mathbf{x} \ge \mathbf{0},\ \mathbf{y}_s &\ge \mathbf{0} \quad \forall s \end{aligned}
📐 Formel-Lesehilfe * \mathbf{c}^\top\mathbf{x} — die Kosten der Vorabentscheidung. Sie fallen immer an. * p_s — Wahrscheinlichkeit von Szenario s; \sum_s p_s = 1. * \mathbf{q}_s^\top\mathbf{y}_s — die Korrekturkosten in Szenario s. * \mathbf{T}_s\mathbf{x} + \mathbf{W}_s\mathbf{y}_s \le \mathbf{h}_s — die Kopplungsbedingung: Sie verbindet die Vorabentscheidung mit dem, was danach möglich ist. Genau hier steckt die Modellierungsarbeit.
Ohne Formel gesagt: „Entscheide jetzt so, dass die Summe aus heutigen Kosten und durchschnittlich zu erwartenden Nachbesserungskosten minimal wird.“
Der entscheidende Punkt: Es gibt ein \mathbf{x}, aber je Szenario ein eigenes \mathbf{y}_s. Das ist keine Rechentrickserei, sondern bildet die Realität ab: Man legt sich einmal fest und reagiert dann unterschiedlich.
#!/usr/bin/env python3
# Stochastische_Optimierung.py
"""
Kapitel Unsicherheit: Two-Stage Stochastic Programming mit CVXPY.
Eigenschaften:
* Die Analyse am Ende wird BERECHNET statt fest verdrahtet
* Vergleich gegen drei Alternativen: Mittelwert, Worst Case, perfekte Voraussicht
* Kennzahl EVPI (Wert perfekter Information) wird ausgewiesen
"""
import cvxpy as cp
import numpy as np
import pandas as pd
SZENARIEN = ["Ruhig", "Volatil", "Crash"]
WAHRSCHEINLICHKEIT = np.array([0.50, 0.30, 0.20])
BEDARF = np.array([100.0, 250.0, 500.0])
KOSTEN_VORAB = 40.0
KOSTEN_SPOT = 120.0
KOSTEN_LEERLAUF = 5.0
S = len(SZENARIEN)
def loese_stochastisch():
"""Zweistufiges Modell: eine Vorabentscheidung, szenarioabhaengige Korrektur."""
x = cp.Variable(nonneg=True, name="Basiskapazitaet") # Stufe 1
y_spot = cp.Variable(S, nonneg=True, name="Spot_Zukauf") # Stufe 2
y_leer = cp.Variable(S, nonneg=True, name="Leerlauf") # Stufe 2
# Kopplung: Basis + Zukauf - Leerlauf == Bedarf (je Szenario)
nebenbedingungen = [x + y_spot[s] - y_leer[s] == BEDARF[s] for s in range(S)]
erwartete_korrektur = sum(
WAHRSCHEINLICHKEIT[s] * (KOSTEN_SPOT * y_spot[s] + KOSTEN_LEERLAUF * y_leer[s])
for s in range(S))
problem = cp.Problem(cp.Minimize(KOSTEN_VORAB * x + erwartete_korrektur),
nebenbedingungen)
problem.solve()
return problem, x, y_spot, y_leer
def kosten_bei(kapazitaet):
"""Erwartete Gesamtkosten fuer eine fest vorgegebene Kapazitaet."""
unter = np.maximum(BEDARF - kapazitaet, 0.0)
ueber = np.maximum(kapazitaet - BEDARF, 0.0)
je_szenario = KOSTEN_VORAB * kapazitaet + KOSTEN_SPOT * unter + KOSTEN_LEERLAUF * ueber
return float(WAHRSCHEINLICHKEIT @ je_szenario)
if __name__ == "__main__":
problem, x, y_spot, y_leer = loese_stochastisch()
kapazitaet = float(x.value)
mittelwert = float(WAHRSCHEINLICHKEIT @ BEDARF)
print("=" * 82)
print(" STOCHASTISCHE TWO-STAGE OPTIMIERUNG (KAPAZITAETSPLANUNG)")
print("=" * 82)
print(f"Status: {problem.status}")
print(f"Erwarteter Bedarf (Mittelwert): {mittelwert:.1f} Einheiten")
print(f"Optimale Stufe-1-Kapazitaet x*: {kapazitaet:.1f} Einheiten")
print(f"Minimale erwartete Gesamtkosten: {problem.value:,.2f} EUR\n")
tabelle = pd.DataFrame({
"Szenario": SZENARIEN,
"Wahrsch.": [f"{p*100:.0f} %" for p in WAHRSCHEINLICHKEIT],
"Bedarf": BEDARF,
"Basis genutzt": [min(kapazitaet, b) for b in BEDARF],
"Spot-Zukauf": np.round(y_spot.value, 1),
"Leerlauf": np.round(y_leer.value, 1),
"Kosten (EUR)": [f"{KOSTEN_VORAB*kapazitaet + KOSTEN_SPOT*y_spot.value[s] + KOSTEN_LEERLAUF*y_leer.value[s]:,.0f}"
for s in range(S)],
})
print(tabelle.to_string(index=False))
# --- Vergleich mit Alternativstrategien (berechnet, nicht behauptet) --
print("\n" + "-" * 82)
print("Vergleich verschiedener Planungsstrategien:")
print(f"{'Strategie':<34} {'Kapazitaet':>11} {'Erw. Kosten':>14} {'Mehrkosten':>13}")
print("-" * 82)
optimal = problem.value
strategien = [
("Stochastisch optimal", kapazitaet),
("Naiv: Mittelwert einsetzen", mittelwert),
("Vorsichtig: Worst Case abdecken", float(BEDARF.max())),
("Optimistisch: Bestfall", float(BEDARF.min())),
]
for name, kap in strategien:
kosten = kosten_bei(kap)
print(f"{name:<34} {kap:>11.1f} {kosten:>14,.0f} "
f"{kosten - optimal:>+13,.0f}")
# --- EVPI: Was waere perfekte Voraussicht wert? ----------------------
# Bei perfekter Information wuerde man je Szenario genau den Bedarf kaufen.
kosten_perfekt = float(WAHRSCHEINLICHKEIT @ (KOSTEN_VORAB * BEDARF))
evpi = optimal - kosten_perfekt
print("-" * 82)
print(f"Kosten bei perfekter Voraussicht: {kosten_perfekt:>10,.0f} EUR")
print(f"Wert perfekter Information (EVPI): {evpi:>10,.0f} EUR "
f"({evpi/optimal*100:.1f} % der Kosten)")
print(" -> So viel duerfte eine perfekte Bedarfsprognose hoechstens kosten.")
# --- Automatische Interpretation --------------------------------------
print("-" * 82)
if kapazitaet > mittelwert + 1e-6:
print(f"Analyse: Der Solver waehlt {kapazitaet:.0f} Einheiten und damit MEHR als")
print(f"den Mittelwert ({mittelwert:.0f}), weil Unterdeckung ({KOSTEN_SPOT:.0f} EUR)")
print(f"deutlich teurer ist als Leerlauf ({KOSTEN_LEERLAUF:.0f} EUR).")
elif kapazitaet < mittelwert - 1e-6:
print(f"Analyse: Der Solver waehlt {kapazitaet:.0f} und damit WENIGER als den")
print(f"Mittelwert ({mittelwert:.0f}) - Leerlauf ist hier teurer als Zukauf.")
else:
print("Analyse: Kapazitaet entspricht dem Mittelwert (symmetrische Kosten).")
print("=" * 82)Erwartete Ausgabe:
==================================================================================
STOCHASTISCHE TWO-STAGE OPTIMIERUNG (KAPAZITAETSPLANUNG)
==================================================================================
Status: optimal
Erwarteter Bedarf (Mittelwert): 225.0 Einheiten
Optimale Stufe-1-Kapazitaet x*: 250.0 Einheiten
Minimale erwartete Gesamtkosten: 16,375.00 EUR
Szenario Wahrsch. Bedarf Basis genutzt Spot-Zukauf Leerlauf Kosten (EUR)
Ruhig 50 % 100.0 100.0 0.0 150.0 10,750
Volatil 30 % 250.0 250.0 0.0 0.0 10,000
Crash 20 % 500.0 250.0 250.0 0.0 40,000
----------------------------------------------------------------------------------
Vergleich verschiedener Planungsstrategien:
Strategie Kapazitaet Erw. Kosten Mehrkosten
----------------------------------------------------------------------------------
Stochastisch optimal 250.0 16,375 -0
Naiv: Mittelwert einsetzen 225.0 16,813 +437
Vorsichtig: Worst Case abdecken 500.0 21,375 +5,000
Optimistisch: Bestfall 100.0 19,000 +2,625
----------------------------------------------------------------------------------
Kosten bei perfekter Voraussicht: 9,000 EUR
Wert perfekter Information (EVPI): 7,375 EUR (45.0 % der Kosten)
-> So viel duerfte eine perfekte Bedarfsprognose hoechstens kosten.
----------------------------------------------------------------------------------
Analyse: Der Solver waehlt 250 Einheiten und damit MEHR als
den Mittelwert (225), weil Unterdeckung (120 EUR)
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 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 Übung 9.4.
💡 Was ist der EVPI? Der Expected Value of Perfect Information 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.
12.6 Robuste Optimierung: gegen den Worst Case absichern
Wenn Wahrscheinlichkeiten unbekannt oder instabil sind — Marktcrashs, Lieferkettenabrisse, Pandemien —, hilft die robuste Optimierung. Sie fragt nicht nach dem Mittel, sondern nach dem Schlimmsten:
\min_{\mathbf{x}\in\mathcal{X}}\ \max_{\mathbf{u}\in\mathcal{U}}\ f(\mathbf{x},\mathbf{u})
📐 Formel-Lesehilfe Zwei ineinandergeschachtelte Optimierungen: * Das innere \max ist der „Gegner“: Er wählt aus der Unsicherheitsmenge \mathcal{U} die für Sie ungünstigsten Parameter. * Das äußere \min sind Sie: Sie wählen \mathbf{x} so, dass Sie selbst gegen diesen Gegner am besten dastehen.
Ohne Formel gesagt: „Entscheide so, dass du auch dann noch gut dastehst, wenn alles gegen dich läuft.“ Das ist Spieltheorie gegen die Natur.
Der Trick, der es lösbar macht. Ein Min-Max-Problem klingt unlösbar — man müsste ja unendlich viele Parameterkombinationen prüfen. Für einfache Unsicherheitsmengen lässt sich das innere Maximum aber geschlossen ausrechnen. Beispiel Box-Unsicherheit: Die Renditen liegen in Intervallen \mu_i \in [\hat\mu_i - \delta_i,\ \hat\mu_i + \delta_i]. Dann gilt für \mathbf{w} \ge 0:
\min_{\boldsymbol{\mu}\in\mathcal{U}} \boldsymbol{\mu}^\top\mathbf{w} = \sum_i (\hat\mu_i - \delta_i)w_i = \hat{\boldsymbol{\mu}}^\top\mathbf{w} - \boldsymbol{\delta}^\top\mathbf{w}
Das Min-Max-Problem wird damit zu einem gewöhnlichen Optimierungsproblem mit einem Abzugsterm. Genau das macht robuste Optimierung praktikabel.
#!/usr/bin/env python3
# Robuste_Optimierung.py
"""
Kapitel Unsicherheit: Robuste Portfolio-Optimierung.
Vergleicht drei Haltungen zur Unsicherheit:
(a) nominal - vertraut den Punktschaetzungen blind
(b) robust - sichert gegen Box-Unsicherheit ab (Worst Case)
(c) stochastisch - optimiert den Erwartungswert ueber Szenarien
und misst den "Preis der Robustheit": Wie viel Ertrag kostet die Absicherung
im Normalfall - und wie viel Verlust erspart sie im Ernstfall?
"""
import cvxpy as cp
import numpy as np
ASSETS = ["Aktien Welt", "Anleihen", "Rohstoffe", "Immobilien"]
MU_SCHAETZUNG = np.array([0.085, 0.030, 0.055, 0.060]) # Punktschaetzung
UNSICHERHEIT = np.array([0.040, 0.008, 0.045, 0.025]) # +/- delta je Titel
VOLA = np.array([0.17, 0.05, 0.22, 0.12])
KORR = np.array([
[1.00, -0.15, 0.35, 0.55],
[-0.15, 1.00, -0.05, 0.10],
[0.35, -0.05, 1.00, 0.25],
[0.55, 0.10, 0.25, 1.00],
])
SIGMA = np.diag(VOLA) @ KORR @ np.diag(VOLA)
LAMBDA = 4.0 # Risikoaversion
N = len(ASSETS)
def optimiere(mu_effektiv):
"""Standard-Mean-Variance mit vorgegebenem Renditevektor."""
w = cp.Variable(N, nonneg=True)
ziel = cp.Maximize(mu_effektiv @ w - 0.5 * LAMBDA * cp.quad_form(w, SIGMA))
problem = cp.Problem(ziel, [cp.sum(w) == 1])
problem.solve()
return w.value
def kennzahlen(w, mu):
ertrag = float(mu @ w)
risiko = float(np.sqrt(w @ SIGMA @ w))
return ertrag, risiko
if __name__ == "__main__":
print("=" * 88)
print(" ROBUSTE vs. NOMINALE PORTFOLIO-OPTIMIERUNG")
print("=" * 88)
print(f"{'Asset':<14} {'Erw. Rendite':>14} {'Unsicherheit':>14} "
f"{'Worst Case':>12} {'Volatilitaet':>13}")
print("-" * 88)
for i, name in enumerate(ASSETS):
print(f"{name:<14} {MU_SCHAETZUNG[i]*100:>13.1f} % "
f"{'+/- ' + format(UNSICHERHEIT[i]*100, '.1f') + ' %':>14} "
f"{(MU_SCHAETZUNG[i]-UNSICHERHEIT[i])*100:>11.1f} % "
f"{VOLA[i]*100:>12.1f} %")
# (a) nominal: vertraut den Schaetzungen
w_nominal = optimiere(MU_SCHAETZUNG)
# (b) robust: rechnet mit dem Worst Case der Box-Unsicherheitsmenge
w_robust = optimiere(MU_SCHAETZUNG - UNSICHERHEIT)
print("\n" + "-" * 88)
print(f"{'':<14} {'nominal':>22} {'robust':>22}")
print("-" * 88)
for i, name in enumerate(ASSETS):
print(f"{name:<14} {w_nominal[i]*100:>21.1f} % {w_robust[i]*100:>21.1f} %")
# --- Bewertung in beiden Welten --------------------------------------
mu_worst = MU_SCHAETZUNG - UNSICHERHEIT
e_nom_gut, r_nom = kennzahlen(w_nominal, MU_SCHAETZUNG)
e_rob_gut, r_rob = kennzahlen(w_robust, MU_SCHAETZUNG)
e_nom_schlecht, _ = kennzahlen(w_nominal, mu_worst)
e_rob_schlecht, _ = kennzahlen(w_robust, mu_worst)
print("\n" + "-" * 88)
print(f"{'Bewertung':<34} {'nominales Portfolio':>22} {'robustes Portfolio':>22}")
print("-" * 88)
print(f"{'Ertrag, wenn Schaetzung stimmt':<34} {e_nom_gut*100:>21.2f} % "
f"{e_rob_gut*100:>21.2f} %")
print(f"{'Ertrag im Worst Case':<34} {e_nom_schlecht*100:>21.2f} % "
f"{e_rob_schlecht*100:>21.2f} %")
print(f"{'Volatilitaet':<34} {r_nom*100:>21.2f} % {r_rob*100:>21.2f} %")
print("\n" + "-" * 88)
print(f"Preis der Robustheit (Ertragsverzicht im Normalfall): "
f"{(e_nom_gut - e_rob_gut)*100:+.2f} Prozentpunkte")
print(f"Nutzen der Robustheit (Vorteil im Worst Case): "
f"{(e_rob_schlecht - e_nom_schlecht)*100:+.2f} Prozentpunkte")
verhaeltnis = ((e_rob_schlecht - e_nom_schlecht)
/ max(e_nom_gut - e_rob_gut, 1e-9))
print(f"Verhaeltnis Nutzen/Preis: {verhaeltnis:.2f}")
print(" -> Werte > 1 bedeuten: Die Absicherung bringt im Ernstfall mehr,")
print(" als sie im Normalfall kostet.")
print("=" * 88)⚠️ Der Preis der Robustheit Robuste Modelle sind konservativ. Wer gegen den absoluten Worst Case absichert, zahlt im Normalfall drauf — oft erheblich. Drei Gegenmittel: 1. Unsicherheitsmenge realistisch wählen. Nicht „alles kann passieren“, sondern „Abweichungen bis zu einer Standardabweichung“. 2. Budgeted Uncertainty (Bertsimas/Sim): Man nimmt an, dass höchstens \Gamma von n Parametern gleichzeitig ihren Worst Case annehmen. \Gamma steuert die Vorsicht stufenlos. 3. Nutzen und Preis immer beziffern — genau wie im Programm oben. Ohne diese zwei Zahlen ist die Diskussion „robust oder nicht“ Glaubenssache.
12.7 Übungsaufgaben
Lösungen: Abschnitt A.12.
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.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?
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 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.)
12.8 Finde den Denkfehler
🐛 Finde den Denkfehler 9.1: Warum jedes Projekt zu spät fertig wird
Ein Projektleiter plant eine Umbaumaßnahme. Fünf Gewerke arbeiten parallel und unabhängig voneinander; fertig ist der Umbau, wenn das letzte fertig ist. Für jedes Gewerk liegt eine Schätzung vor: mindestens 6 Tage, wahrscheinlich 10, im schlechtesten Fall 18.
Er rechnet: „Jedes Gewerk braucht im Mittel (6 + 10 + 18)/3 = 11{,}3 Tage. Alle laufen gleichzeitig. Also ist der Umbau nach 11,3 Tagen fertig — ich plane großzügig 12 ein.“
Nachgerechnet mit 200 000 simulierten Umbauten:
import numpy as np rng = np.random.default_rng(3) dauer = rng.triangular(6, 10, 18, size=(200_000, 5)) # 5 Gewerke, je eine Schaetzung projekt = dauer.max(axis=1) # fertig, wenn das LETZTE fertig ist print(f"Mittelwert einer Einzeldauer: {dauer.mean():.2f} Tage") print(f"Tatsaechliche Projektdauer: {projekt.mean():.2f} Tage") print(f"90-%-Quantil: {np.quantile(projekt, 0.9):.2f} Tage") print(f"Anteil ueber 11,34 Tage: {(projekt > 11.34).mean() * 100:.1f} %")Ausgabe:
Mittelwert einer Einzeldauer: 11.34 Tage Tatsaechliche Projektdauer: 14.38 Tage 90-%-Quantil: 16.59 Tage Anteil ueber 11,34 Tage: 95.5 %Ihre Aufgabe: (a) Der Projektleiter hat richtig gerechnet — jedes Gewerk braucht tatsächlich im Mittel 11,34 Tage. Warum dauert das Projekt trotzdem 14,38 Tage? (b) Erklären Sie in einem Satz, warum ausgerechnet 95,5 % aller Umbauten den Plan reißen. Was müsste gelten, damit es 50 % wären? (c) Was passiert mit der Projektdauer, wenn statt fünf Gewerken zehn parallel arbeiten — bei unveränderter Einzelschätzung? (d) Welche Zahl gehört in den Projektplan, wenn der Auftraggeber eine Terminzusage mit 90 % Sicherheit verlangt?
Auflösung: Abschnitt A.12.
🎯 Merksatz Der Fluch des Durchschnitts hat zwei Gesichter. Beim Ersatzteil aus Abschnitt 12.1 führt der Mittelwert in die Irre, weil die Kosten asymmetrisch sind. Hier führt er in die Irre, weil die Verknüpfung asymmetrisch ist: Ein Gewerk, das früher fertig wird, hilft niemandem — ein Gewerk, das sich verspätet, verzögert alles. Beide Male gilt: Der Mittelwert einer Funktion ist nicht die Funktion des Mittelwerts.
12.9 Micro-Quiz
❓ Micro-Quiz 9: Drei Fragen zum Selbstcheck
Genau eine Antwort ist jeweils richtig. Auflösung in Anhang A.
1. Bei einem Ersatzteil kostet ein Stück zu wenig 1 400 €, ein Stück zu viel 120 €. Der Bedarf beträgt im Mittel 30 Stück. Wie viel bestellen Sie? (a) 30 — das ist der Erwartungswert des Bedarfs. (b) Deutlich mehr als 30, nämlich das 92,1-%-Quantil des Bedarfs. Das kritische Verhältnis 1400/(1400+120) sagt, wie weit man sich auf die günstigere Fehlerseite stellen soll. (c) Weniger als 30, weil Lagerhaltung Kapital bindet.
2. Was unterscheidet stochastische** von robuster Optimierung?** (a) Stochastische Optimierung ist genauer, robuste ist eine Näherung für schnelle Rechnungen. (b) Stochastische Optimierung braucht Wahrscheinlichkeiten und optimiert den Erwartungswert; robuste Optimierung braucht nur Bandbreiten und sichert den schlechtesten Fall darin ab. (c) Robuste Optimierung berücksichtigt mehr Szenarien.
3. Ein Kollege ersetzt in seinem Modell alle unsicheren Größen durch ihre Mittelwerte und rechnet deterministisch. Wann ist das unproblematisch? (a) Immer — der Erwartungswert ist die beste Einzelschätzung. (b) Nie. (c) Wenn Zielfunktion und Nebenbedingungen in den unsicheren Größen linear sind und keine Entscheidung erst nach Beobachtung fällt. Sobald Minimum, Maximum, Betrag oder eine Nachbesserungsentscheidung im Spiel ist, gilt es nicht mehr.
12.10 Selbsttest
Antworten: Anhang A.
- Warum ist Planung mit Erwartungswerten bei asymmetrischen Kosten systematisch falsch?
- Was unterscheidet Stufe-1- von Stufe-2-Variablen?
- Was misst der EVPI, und wofür ist er praktisch nützlich?
- Warum braucht robuste Optimierung keine Wahrscheinlichkeiten?
- Wie macht man ein Min-Max-Problem mit Box-Unsicherheit lösbar?
12.11 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.
- Monte-Carlo bewertet, optimiert aber nicht. Sein Wert liegt in Kennzahlen, für die es keine Formel gibt.
- 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.
- Beziffern Sie immer Preis und Nutzen der Absicherung. Ohne beide Zahlen ist die Entscheidung nicht begründbar.
Ausblick. Kapitel 13 fügt die Zeitdimension hinzu: Entscheidungen, die über viele Perioden aufeinander aufbauen — gelöst mit der Bellman-Gleichung.