Grafik-Upgrade Stufe 1: elf neue Diagramme

Grafik_Upgrade.md verlangt "37 didaktisch wertvolle Visualisierungen". Es sind
19: Die Abschnitte "Modul 1-4" wiederholen die Grafiken 1-18 unter den Nummern
19-36, nur Grafik 37 ist zusaetzlich. Belegt an den Skriptnamen - 38
Nennungen, 19 verschiedene Dateien, erzeuge_kombinatorik_wand.py steht dreimal
darin. Von den 19 betreffen neun bereits vorhandene Diagramme.

Umgesetzt sind die zehn wirklich neuen plus eine elfte, die aus einem
Sachfehler des Auftrags entstand: Grafik 14 sollte in Abschnitt 12.3 stehen,
nannte aber Zahlen aus Kapitel 17. Beide Stellen haben jetzt ihre eigene
Grafik mit ihren eigenen Zahlen.

Vier Vorgaben des Auftrags wurden bewusst nicht befolgt: PNG bei 300 dpi (das
Buch kennt nur SVG - die 33 verwaisten PNGs waren gerade erst geloescht
worden), Matplotlib-Standardfarben (die Buchpalette steht in 33 Diagrammen),
harte Kapitelnummern im Fliesstext ({ref:sec:...} stattdessen) und die
fehlende Byte-Reproduzierbarkeit.

Der eigentliche Ertrag waren die Selbsttests. Jeder Generator prueft seine
Zahlen gegen das, was im Kapitel steht, und bricht bei Abweichung ab. Vier
haben angeschlagen:

* Kombinatorik-Wand: 25! ergibt 491,5 Mio. Jahre, die Tabelle nennt 490 Mio. -
  Rundung auf zwei signifikante Stellen, nicht Fehler des Buchs.
* Laufzeit-Diagramm: Die abgedruckte Prozentspalte laesst sich aus den
  abgedruckten Zeiten nicht exakt nachrechnen (0,001/0,008 ergibt 12 %,
  gedruckt sind 14 %) - die Zeiten sind gerundet, die Prozente nicht.
* Predict-then-Optimize: geratene Datenaufteilung ergab 197,35 statt 200,95
  MSE. Mit TRAINING aus dem Buchprogramm stimmen alle vier Kostenwerte.
* Almgren-Chriss: ein echter Fehler im Buchprogramm.

DER FUND: analytische_loesung() minimiert die eigene Kostenfunktion nicht. Ihr
Pfad kostet 10.860,40 EUR, der DP-Pfad 10.266,24 EUR - ein Gitterverfahren
kann das kontinuierliche Optimum aber nicht unterbieten. periodenkosten()
rechnet das Risiko mit lambda/2, die geschlossene Formel setzt
kappa~^2 = lambda*sigma^2*P0^2/eta ohne dieses Halbe. Mit lambda/2 liefert die
Formel 10.264,85 EUR und denselben Pfad wie die DP, knapp UNTER der
Gitterloesung. Die Grafik zeigt bis zur Entscheidung darueber den DP-Pfad; er
ist der, den das Kapitel abdruckt.

Nachweise: Alle elf Diagramme sind ueber zwei Laeufe byte-identisch. Kein
vorhandenes Diagramm wurde veraendert. Die Lastabwurf-Grafik reproduziert die
Befundtabelle exakt (874.870/2.504.154/28 von 40 gegen 351.356/415.924/0).

Zwei Abbildungen landeten beim automatischen Einfuegen im Codeblock (ihre
Anker standen in abgedruckten Ausgaben) und wurden dahinter verschoben; eine
Pruefung ueber alle elf zeigt null Fehlplatzierungen.

Neu: bilder_04/stil_04.py buendelt Palette, rcParams und speichere().
networkx wurde entgegen der Planung nicht gebraucht - pyproject.toml bleibt
unveraendert. PDF von 781 auf 788 Seiten, 44 Diagramme, 27 Generatoren.
Veroeffentlicht: 25 Dateien.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
dschlueter 2026-09-09 01:11:33 +02:00
commit 0f9c815b86
64 changed files with 52288 additions and 25 deletions

View file

@ -550,7 +550,6 @@
<li><a href="#sec:modellierung-vier-fragen" id="toc-sec:modellierung-vier-fragen">4.3 Ein Satz ist noch kein Modell</a></li>
<li><a href="#sec:modellierung-fuenf-modelle" id="toc-sec:modellierung-fuenf-modelle">4.4 Derselbe Datensatz, fünf Modelle</a>
<ul>
<li><a href="#teil-1-drei-ziele-drei-pläne" id="toc-teil-1-drei-ziele-drei-pläne">Teil 1: Drei Ziele, drei Pläne</a></li>
<li><a href="#teil-2-ein-satz-drei-lesarten" id="toc-teil-2-ein-satz-drei-lesarten">Teil 2: Ein Satz, drei Lesarten</a></li>
<li><a href="#teil-3-hart-oder-weich" id="toc-teil-3-hart-oder-weich">Teil 3: Hart oder weich</a></li>
<li><a href="#teil-4-ein-quartal-später" id="toc-teil-4-ein-quartal-später">Teil 4: Ein Quartal später</a></li>
@ -835,6 +834,7 @@
<li><a href="#sec:prognose-lernziele" id="toc-sec:prognose-lernziele">15.2 Lernziele</a></li>
<li><a href="#sec:prognose-naht" id="toc-sec:prognose-naht">15.3 Die Naht zwischen zwei Abteilungen</a></li>
<li><a href="#sec:prognose-programm" id="toc-sec:prognose-programm">15.4 Das Programm</a></li>
<li><a href="#was-sie-in-der-abbildung-sehen.-links-und-rechts-gewinnt-nicht-dasselbe-verfahren.-die-punktprognose-hat-den-besten-prognosefehler-und-die-höchsten-kosten-beide-maßstäbe-messen-etwas-anderes-und-nur-einer-davon-steht-am-ende-in-der-bilanz." id="toc-was-sie-in-der-abbildung-sehen.-links-und-rechts-gewinnt-nicht-dasselbe-verfahren.-die-punktprognose-hat-den-besten-prognosefehler-und-die-höchsten-kosten-beide-maßstäbe-messen-etwas-anderes-und-nur-einer-davon-steht-am-ende-in-der-bilanz."><strong>Was Sie in der Abbildung sehen.</strong> Links und rechts gewinnt nicht dasselbe Verfahren. Die Punktprognose hat den besten Prognosefehler und die höchsten Kosten — beide Maßstäbe messen etwas anderes, und nur einer davon steht am Ende in der Bilanz.</a></li>
<li><a href="#sec:prognose-befund" id="toc-sec:prognose-befund">15.5 Der Befund</a>
<ul>
<li><a href="#warum-ein-pauschaler-zuschlag-zu-kurz-greift" id="toc-warum-ein-pauschaler-zuschlag-zu-kurz-greift">Warum ein pauschaler Zuschlag zu kurz greift</a></li>
@ -3366,6 +3366,11 @@ Deckungsbeitrag: 10800 EUR</code></pre>
</table>
<p><strong>Der springende Punkt:</strong> Zwischen <span class="math inline">n = 15</span> (22 Minuten, machbar) und <span class="math inline">n = 20</span> (77 Jahre, hoffnungslos) liegen nur <strong>fünf zusätzliche Aufträge</strong>. Es gibt keine sanfte Verschlechterung — es gibt eine Wand.</p>
</blockquote>
<figure>
<img src="bilder_04/kap_einfuehrung_kombinatorik.svg" alt="Abb. 1.2: Rechenzeit bei einer Milliarde geprüften Reihenfolgen je Sekunde. Alle drei Kurven stehen auf derselben Achse — deshalb kleben n^2 und n^3 am unteren Rand, während n! das Bild verlässt. Erzeugt von bilder_04/erzeuge_kombinatorik_wand.py." />
<figcaption aria-hidden="true">Abb. 1.2: Rechenzeit bei einer Milliarde geprüften Reihenfolgen je Sekunde. Alle drei Kurven stehen auf derselben Achse — deshalb kleben <span class="math inline">n^2</span> und <span class="math inline">n^3</span> am unteren Rand, während <span class="math inline">n!</span> das Bild verlässt. Erzeugt von <code>bilder_04/erzeuge_kombinatorik_wand.py</code>.</figcaption>
</figure>
<p><strong>Was Sie in der Abbildung sehen.</strong> Der markierte Streifen zwischen <span class="math inline">n = 15</span> und <span class="math inline">n = 20</span> ist der eigentliche Befund: Dort wird aus einer Kaffeepause ein Menschenleben. Wer eine Maschine kauft, die tausendmal schneller rechnet, verschiebt diese Wand um genau zwei Aufträge.</p>
<p>Und die Rechnung ist noch geschönt: Ein schnellerer Rechner hilft praktisch nicht. Selbst eine Beschleunigung um den Faktor <strong>eine Million</strong> verschiebt die Grenze von <span class="math inline">n=20</span> nur auf etwa <span class="math inline">n=24</span>. Gegen kombinatorisches Wachstum ist Hardware machtlos.</p>
<p>Das folgende Programm macht diesen Effekt erfahrbar. Es löst dasselbe Zuordnungsproblem zweimal — einmal durch vollständiges Durchprobieren, einmal mit einem OR-Solver — und vergleicht die Laufzeiten.</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="co">#!/usr/bin/env python3</span></span>
@ -3561,8 +3566,8 @@ Der Solver löst dieselbe Instanz in Sekundenbruchteilen.
<h2 id="sec:einfuehrung-die-vier-universellen-bausteine-jedes-or">1.6 Die vier universellen Bausteine jedes OR-Problems</h2>
<p>Dies ist der wichtigste Abschnitt des Kapitels. Jedes Optimierungsproblem der Welt lässt sich — unabhängig von der Branche — auf vier Elemente reduzieren. Wenn Sie später vor einem neuen Problem sitzen, ist dies Ihre Checkliste.</p>
<figure>
<img src="bilder_04/kap01_vier_bausteine.svg" alt="Abb. 1.2: Die vier universellen Bausteine eines OR-Modells" />
<figcaption aria-hidden="true">Abb. 1.2: Die vier universellen Bausteine eines OR-Modells</figcaption>
<img src="bilder_04/kap01_vier_bausteine.svg" alt="Abb. 1.3: Die vier universellen Bausteine eines OR-Modells" />
<figcaption aria-hidden="true">Abb. 1.3: Die vier universellen Bausteine eines OR-Modells</figcaption>
</figure>
<h3 id="baustein-1-entscheidungsvariablen-x">Baustein 1 — Entscheidungsvariablen (<span class="math inline">x</span>)</h3>
<p>Die <strong>Stellschrauben</strong> des Modells: Werte, die der Algorithmus aktiv festlegen darf.</p>
@ -6849,6 +6854,11 @@ Groesse Variante Aufbau Loesen Aufba
-&gt; Zielwert (alle gleich) 8316.24 Spanne 1.8e-12
----------------------------------------------------------------------------------------</code></pre>
<p><strong>Lesen Sie die letzte Spalte.</strong> Bei 62 500 Variablen verbringt Variante A <strong>69 % der Gesamtzeit damit, das Modell überhaupt aufzuschreiben</strong> — und nur 31 % mit Rechnen. Die vektorisierten Varianten kehren das Verhältnis um: 1 % Aufbau, 99 % Solver. Erst dort ist ein schnellerer Solver überhaupt die richtige Stellschraube.</p>
<figure>
<img src="bilder_04/kap_oekosystem_laufzeit.svg" alt="Abb. 3.2: Dieselbe Aufgabe, zwei Arten sie aufzuschreiben — aufgeteilt in Aufbauzeit (Python) und Lösezeit (C++). Werte aus der Messung oben. Erzeugt von bilder_04/erzeuge_laufzeit_aufbau.py." />
<figcaption aria-hidden="true">Abb. 3.2: Dieselbe Aufgabe, zwei Arten sie aufzuschreiben — aufgeteilt in Aufbauzeit (Python) und Lösezeit (C++). Werte aus der Messung oben. Erzeugt von <code>bilder_04/erzeuge_laufzeit_aufbau.py</code>.</figcaption>
</figure>
<p><strong>Was Sie in der Abbildung sehen.</strong> Der rote Anteil ist die Zeit, in der der Solver noch gar nicht rechnet. Bei Variante A wächst er mit dem Modell, bei Variante C verschwindet er — dieselbe Mathematik, nur anders aufgeschrieben.</p>
<blockquote>
<p><strong>💻 Code-Durchgang</strong></p>
<table>
@ -7381,6 +7391,7 @@ Es muss also ausgewaehlt werden. 3 der Kunden sind Stammkunden:
&quot;Maschinen besser auslasten&quot; 205,000 54,000 100% 4 1 5
&quot;Deckungsbeitrag maximieren&quot; 222,000 78,500 100% 2 1 8
Der Umsatzplan bringt 5,000 EUR mehr Umsatz und 12,500 EUR WENIGER
Deckungsbeitrag. Fuer 5,000 EUR Umsatz werden also 12,500 EUR Ergebnis
aufgegeben - und 5 von 6 Stammkundenauftraegen dazu.
@ -7454,7 +7465,11 @@ Drei Dinge, die deshalb vor dem ersten Modell geklaert gehoeren:
zwar genau dann, wenn ein besonders grosser Auftrag hereinkommt.
Weiche Regeln antworten auch dann noch.
====================================================================================</code></pre>
<h3 id="teil-1-drei-ziele-drei-pläne">Teil 1: Drei Ziele, drei Pläne</h3>
<figure>
<img src="bilder_04/kap_modellierung_zielgroessen.svg" alt="Abb. 4.1: Die drei Pläne aus der Tabelle, je Achse auf den besten der drei bezogen. Erzeugt von bilder_04/erzeuge_zielgroessen_radar.py." />
<figcaption aria-hidden="true">Abb. 4.1: Die drei Pläne aus der Tabelle, je Achse auf den besten der drei bezogen. Erzeugt von <code>bilder_04/erzeuge_zielgroessen_radar.py</code>.</figcaption>
</figure>
<p><strong>Was Sie in der Abbildung sehen.</strong> Jeder Plan gewinnt auf seiner eigenen Achse — das ist keine Überraschung, sondern die Definition. Interessant ist, was daneben passiert: Der Auslastungsplan liegt bei der Auslastung gleichauf mit den anderen und verliert beim Deckungsbeitrag ein knappes Drittel. ### Teil 1: Drei Ziele, drei Pläne</p>
<table>
<colgroup>
<col style="width: 15%" />
@ -8923,6 +8938,11 @@ Pruefung: komplementaerer Schlupf fuer alle Ressourcen erfuellt.
<hr />
<h2 id="sec:lp-entartung">5.9 Wann Schattenpreise lügen: Entartung und Toleranzen</h2>
<p>Der vorige Abschnitt hat gezeigt, wie wertvoll Schattenpreise sind. Dieser zeigt die zwei Fälle, in denen sie eine Entscheidung <strong>nicht</strong> tragen — und wie man beide erkennt, bevor jemand auf ihrer Grundlage eine Maschine kauft.</p>
<figure>
<img src="bilder_04/kap_lp_entartung.svg" alt="Abb. 5.3: Links laufen drei Geraden durch dieselbe Ecke — eine mehr, als zwei Dimensionen brauchen. Rechts die Folge: Der Schattenpreis ist keine Zahl mehr, sondern eine Spanne. Erzeugt von bilder_04/erzeuge_entartung_polyeder.py." />
<figcaption aria-hidden="true">Abb. 5.3: Links laufen drei Geraden durch dieselbe Ecke — eine mehr, als zwei Dimensionen brauchen. Rechts die Folge: Der Schattenpreis ist keine Zahl mehr, sondern eine Spanne. Erzeugt von <code>bilder_04/erzeuge_entartung_polyeder.py</code>.</figcaption>
</figure>
<p><strong>Was Sie in der Abbildung sehen.</strong> Jeder Wert innerhalb der farbigen Balken erfüllt die Optimalitätsbedingungen. Zwei Solver dürfen also verschiedene Schattenpreise melden und haben beide recht — die Frage „was ist eine Stunde wert?” hat hier schlicht keine eindeutige Antwort.</p>
<h3 id="fall-1-entartung">Fall 1: Entartung</h3>
<p>Erinnern Sie sich an <a href="#sec:fundament-der-zulaessige-loesungsraum-und-das-polyeder">Abschnitt 2.4</a>: In zwei Dimensionen legen <strong>zwei</strong> sich schneidende Geraden eine Ecke fest, in drei Dimensionen drei Ebenen, allgemein <span class="math inline">n</span> Restriktionen bei <span class="math inline">n</span> Variablen. Was passiert, wenn in einer Ecke <strong>mehr</strong> Nebenbedingungen aktiv sind als das Problem Variablen hat?</p>
<p>Geometrisch: Drei Geraden laufen zufällig durch denselben Punkt. Die Ecke ist immer noch eine Ecke — aber sie ist <strong>überbestimmt</strong>. Man nennt das <strong>Entartung</strong> (<em>Degeneriertheit</em>), und sie ist in der Praxis nicht die Ausnahme, sondern die Regel: Sie entsteht überall dort, wo Kapazitäten aus derselben Planung stammen und deshalb glatt aufeinander passen — Schichtlängen, Chargengrößen, runde Vertragsmengen.</p>
@ -9669,6 +9689,11 @@ Loesung eine Nebenbedingung verletzt. &#39;Verlust&#39; = Abstand zum exakten Op
<hr />
<h2 id="sec:milp-modellierungstricks-big-m-und-logische-bedingungen">6.5 Modellierungstricks: Big-M und logische Bedingungen</h2>
<p>Hier kommt das Handwerkszeug, das MILP so mächtig macht: Man übersetzt Geschäftsregeln in lineare Ungleichungen — mithilfe binärer Hilfsvariablen <span class="math inline">y \in \{0,1\}</span> und einer hinreichend großen Konstante <span class="math inline">M</span>.</p>
<figure>
<img src="bilder_04/kap_milp_big_m.svg" alt="Abb. 6.3: Dieselbe Bedingung x \le M\,y, zwei Zahlen für M. Gezeigt ist die LP-Relaxation — also das, was der Solver sieht, bevor y ganzzahlig wird. Erzeugt von bilder_04/erzeuge_big_m_vergleich.py." />
<figcaption aria-hidden="true">Abb. 6.3: Dieselbe Bedingung <span class="math inline">x \le M\,y</span>, zwei Zahlen für <span class="math inline">M</span>. Gezeigt ist die LP-Relaxation — also das, was der Solver sieht, bevor <span class="math inline">y</span> ganzzahlig wird. Erzeugt von <code>bilder_04/erzeuge_big_m_vergleich.py</code>.</figcaption>
</figure>
<p><strong>Was Sie in der Abbildung sehen.</strong> Für <span class="math inline">y \in \{0,1\}</span> sind beide Modelle gleichwertig; die beiden blauen Punkte stimmen überein. Verschieden ist nur, was dazwischen erlaubt ist — und rechts genügt bereits <span class="math inline">y = 0{,}08</span>, um die volle Kapazität freizugeben.</p>
<h3 id="muster-1-fixkosten-aktivierungsschalter">Muster 1 — Fixkosten / Aktivierungsschalter</h3>
<p><em>Regel:</em> Wird Maschine <span class="math inline">j</span> genutzt (<span class="math inline">x_j &gt; 0</span>), fallen Rüstkosten <span class="math inline">F_j</span> an.</p>
<p><span class="math display">
@ -13232,6 +13257,11 @@ Umschlag -&gt; Kunde_2 5.0 10 3.00 15.00
<p>Die Touren sind aus demselben Grund <strong>Luftlinien und keine Straßenrouten</strong>: Das Modell kennt keine Straßen, es rechnet mit den Abständen der Distanzmatrix. Eine Linie, die einer echten Straße folgte, wäre hübscher und würde eine Genauigkeit vortäuschen, die das Modell nicht hat. Wer Straßenentfernungen braucht, ersetzt die Matrix — <a href="#sec:graphen-denkfehler">Abschnitt 8.7</a> sagt, was dabei zu beachten ist.</p>
<h3 id="kurzzyklen-verhindern">Kurzzyklen verhindern</h3>
<p>Ein naives Modell erlaubt <strong>Subtouren</strong>: isolierte Kreise, die das Depot nie anfahren. Die klassische Gegenmaßnahme ist die <strong>MTZ-Formulierung</strong> nach Miller, Tucker und Zemlin. Man führt Rangvariablen <span class="math inline">u_i</span> ein (die Position des Knotens in der Tour):</p>
<figure>
<img src="bilder_04/kap_graphen_subtouren.svg" alt="Abb. 8.3: Links eine Lösung, die jede Gradbedingung erfüllt und trotzdem unbrauchbar ist; rechts dieselbe Instanz mit Kurzzyklus-Bedingungen. Erzeugt von bilder_04/erzeuge_vrp_subtours.py." />
<figcaption aria-hidden="true">Abb. 8.3: Links eine Lösung, die jede Gradbedingung erfüllt und trotzdem unbrauchbar ist; rechts dieselbe Instanz mit Kurzzyklus-Bedingungen. Erzeugt von <code>bilder_04/erzeuge_vrp_subtours.py</code>.</figcaption>
</figure>
<p><strong>Was Sie in der Abbildung sehen.</strong> Links wird jeder Kunde genau einmal angefahren — das Modell hat also gerechnet, was man ihm aufgeschrieben hat. Was fehlt, ist die Bedingung, an die man beim Aufschreiben nicht denkt: dass jede Tour am Depot beginnen muss.</p>
<p><span class="math display">
u_i - u_j + C \cdot x_{ij} \le C - d_j \qquad \forall i \ne j
</span></p>
@ -15397,6 +15427,11 @@ Abstand zum Optimum.
<p>Fange mit wenigen Mustern an. Frage nach jeder Lösung, ob es ein <strong>noch nicht bekanntes</strong> Muster gibt, das sich lohnen würde — und wenn ja, nimm nur dieses eine dazu.</p>
</blockquote>
<p>Die Frage „lohnt sich noch ein Muster?” beantworten die <strong>Dualwerte</strong> des Master-LPs. Der Dualwert <span class="math inline">\pi_i</span> zur Bedarfszeile <span class="math inline">i</span> ist genau der Schattenpreis aus <a href="#sec:lp-dualitaet-und-schattenpreise">Abschnitt 5.6</a>: Er sagt, wie viele Rollen ein zusätzliches Stück der Breite <span class="math inline">i</span> kostet.</p>
<figure>
<img src="bilder_04/kap_dekomposition_regelkreis.svg" alt="Abb. 10.1: Der Kreislauf zwischen Master-LP und Pricing-Problem. Erzeugt von bilder_04/erzeuge_spaltengenerierung_flow.py." />
<figcaption aria-hidden="true">Abb. 10.1: Der Kreislauf zwischen Master-LP und Pricing-Problem. Erzeugt von <code>bilder_04/erzeuge_spaltengenerierung_flow.py</code>.</figcaption>
</figure>
<p><strong>Was Sie in der Abbildung sehen.</strong> Die Information fließt in beide Richtungen: Preise nach rechts, Muster nach links. Der Ausgang unten wird erst geöffnet, wenn das Pricing nichts mehr findet — und genau das ist der Optimalitätsbeweis.</p>
<p>Ein neues Muster <span class="math inline">a</span> lohnt sich, wenn seine <strong>reduzierten Kosten</strong> negativ sind:</p>
<p><span class="math display">
1 - \sum_i \pi_i\, a_i &lt; 0
@ -17503,6 +17538,11 @@ q^{*} = \frac{c_{\text{zu wenig}}}{c_{\text{zu wenig}} + c_{\text{zu viel}}}
<span id="cb128-51"><a href="#cb128-51" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb128-52"><a href="#cb128-52" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">&quot;</span><span class="ch">\n</span><span class="st">Das Optimum liegt exakt auf einem Szenariowert (250 = &#39;Volatil&#39;),&quot;</span>)</span>
<span id="cb128-53"><a href="#cb128-53" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">&quot;nicht beim Mittelwert 225 - typisch fuer asymmetrische Kostenfunktionen.&quot;</span>)</span></code></pre></div>
<figure>
<img src="bilder_04/kap_unsicherheit_durchschnitt.svg" alt="Abb. 12.1: Erwartete Gesamtkosten über allen Bestellmengen, gerechnet aus den drei Szenarien der Handrechnung. Erzeugt von bilder_04/erzeuge_fluch_durchschnitt.py." />
<figcaption aria-hidden="true">Abb. 12.1: Erwartete Gesamtkosten über allen Bestellmengen, gerechnet aus den drei Szenarien der Handrechnung. Erzeugt von <code>bilder_04/erzeuge_fluch_durchschnitt.py</code>.</figcaption>
</figure>
<p><strong>Was Sie in der Abbildung sehen.</strong> Die Kurve ist nicht symmetrisch: Sie fällt links flach und steigt rechts steil, weil Fehlmenge 120 € kostet und Überschuss nur 5 €. Ihr tiefster Punkt liegt deshalb rechts vom Erwartungswert — nicht auf ihm.</p>
<p><strong>Erwartete Ausgabe:</strong></p>
<pre><code>======================================================================
DER FLUCH DES DURCHSCHNITTS
@ -17530,8 +17570,8 @@ nicht beim Mittelwert 225 - typisch fuer asymmetrische Kostenfunktionen.</code><
</blockquote>
<h3 id="die-vier-ansätze-im-überblick">Die vier Ansätze im Überblick</h3>
<figure>
<img src="bilder_04/kap09_unsicherheit_ansaetze.svg" alt="Abb. 12.1: Ansätze für Optimierung unter Unsicherheit" />
<figcaption aria-hidden="true">Abb. 12.1: Ansätze für Optimierung unter Unsicherheit</figcaption>
<img src="bilder_04/kap09_unsicherheit_ansaetze.svg" alt="Abb. 12.2: Ansätze für Optimierung unter Unsicherheit" />
<figcaption aria-hidden="true">Abb. 12.2: Ansätze für Optimierung unter Unsicherheit</figcaption>
</figure>
<table>
<colgroup>
@ -19113,6 +19153,11 @@ C(n_t, X_t) = \underbrace{\eta\,n_t^2}_{\text{Marktauswirkung}} \;+\; \underbrac
<span id="cb143-209"><a href="#cb143-209" aria-hidden="true" tabindex="-1"></a> plt.savefig(ziel, dpi<span class="op">=</span><span class="dv">150</span>)</span>
<span id="cb143-210"><a href="#cb143-210" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f&quot;</span><span class="ch">\n</span><span class="ss">Diagramm gespeichert unter &#39;</span><span class="sc">{</span>ziel<span class="sc">}</span><span class="ss">&#39;&quot;</span>)</span>
<span id="cb143-211"><a href="#cb143-211" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">&quot;=&quot;</span> <span class="op">*</span> <span class="dv">84</span>)</span></code></pre></div>
<figure>
<img src="bilder_04/kap_dp_almgren_chriss.svg" alt="Abb. 13.2: Drei Wege, dieselbe Position abzubauen, mit den Kosten aus periodenkosten(). Erzeugt von bilder_04/erzeuge_almgren_chriss.py." />
<figcaption aria-hidden="true">Abb. 13.2: Drei Wege, dieselbe Position abzubauen, mit den Kosten aus <code>periodenkosten()</code>. Erzeugt von <code>bilder_04/erzeuge_almgren_chriss.py</code>.</figcaption>
</figure>
<p><strong>Was Sie in der Abbildung sehen.</strong> Die optimale Kurve liegt nicht in der Mitte zwischen den Extremen, sondern ist gekrümmt: vorne mehr, hinten weniger. Diese Krümmung ist die Antwort auf die Frage, wie teuer Eile gegen Warten steht.</p>
<p><strong>Erwartete Ausgabe:</strong></p>
<pre><code>====================================================================================
OPTIMALE MEHRPERIODIGE ORDER-EXECUTION (BELLMAN DP)
@ -20326,6 +20371,7 @@ Training: Tag 1 bis 1000. Bewertung: die restlichen 4000 Tage.
bester MSE: bestelle die Punktprognose
beste Kosten: Quantilregression aufs kritische Quantil
Das Verfahren mit dem besten MSE hat die HOECHSTEN Kosten, und das
Verfahren mit den besten Kosten hat einen um 13% SCHLECHTEREN MSE.
Wer Prognosemodelle nach MSE auswaehlt, waehlt hier das falsche.
@ -20400,7 +20446,11 @@ erfordert Bibliotheken wie cvxpylayers. Die dritte Zeile der Tabelle
oben ist seine einfachste denkbare Form: ein einziger Parameter, auf
Kosten statt auf Fehler trainiert.
====================================================================================</code></pre>
<hr />
<figure>
<img src="bilder_04/kap_prognose_entscheidungsguete.svg" alt="Abb. 15.1: Dieselben vier Verfahren, zwei Maßstäbe. Grün ist jeweils der beste Wert. Erzeugt von bilder_04/erzeuge_predict_vs_optimize.py." />
<figcaption aria-hidden="true">Abb. 15.1: Dieselben vier Verfahren, zwei Maßstäbe. Grün ist jeweils der beste Wert. Erzeugt von <code>bilder_04/erzeuge_predict_vs_optimize.py</code>.</figcaption>
</figure>
<h2 id="was-sie-in-der-abbildung-sehen.-links-und-rechts-gewinnt-nicht-dasselbe-verfahren.-die-punktprognose-hat-den-besten-prognosefehler-und-die-höchsten-kosten-beide-maßstäbe-messen-etwas-anderes-und-nur-einer-davon-steht-am-ende-in-der-bilanz."><strong>Was Sie in der Abbildung sehen.</strong> Links und rechts gewinnt nicht dasselbe Verfahren. Die Punktprognose hat den besten Prognosefehler und die höchsten Kosten — beide Maßstäbe messen etwas anderes, und nur einer davon steht am Ende in der Bilanz.</h2>
<h2 id="sec:prognose-befund">15.5 Der Befund</h2>
<table>
<colgroup>
@ -22081,10 +22131,15 @@ Was Versorgungssicherheit kostet
</tbody>
</table>
<p>Der Erwartungswert-Plan kostet in der Wirklichkeit <strong>149 % mehr</strong>, und sein schlimmster Tag ist sechsmal so teuer.</p>
<figure>
<img src="bilder_04/kap_supplychain_lastabwurf.svg" alt="Abb. 17.1: Die 40 Szenarien einzeln, aufsteigend nach Kosten. Punkte markieren Szenarien mit Lastabwurf. Erzeugt von bilder_04/erzeuge_lastabwurf_verteilung.py." />
<figcaption aria-hidden="true">Abb. 17.1: Die 40 Szenarien einzeln, aufsteigend nach Kosten. Punkte markieren Szenarien mit Lastabwurf. Erzeugt von <code>bilder_04/erzeuge_lastabwurf_verteilung.py</code>.</figcaption>
</figure>
<p><strong>Was Sie in der Abbildung sehen.</strong> Der Erwartungswert-Plan ist in den ruhigen Szenarien tatsächlich der billigere — die rote Kurve verläuft links von der grünen. Er kippt erst rechts, und zwar so weit, dass der Mittelwert das Vorzeichen wechselt.</p>
<p><strong>Wofür genau?</strong> Die Summendifferenz von 523 514 € sagt noch nicht, wo sie entsteht. Zerlegt man sie nach Kostenarten, wird aus dem Befund eine Aussage, die man vorlegen kann:</p>
<figure>
<img src="bilder_04/kap_supplychain_wirkung.svg" alt="Abb. 17.1: Wofür der Erwartungswert-Plan 149 % mehr bezahlt" />
<figcaption aria-hidden="true">Abb. 17.1: Wofür der Erwartungswert-Plan 149 % mehr bezahlt</figcaption>
<img src="bilder_04/kap_supplychain_wirkung.svg" alt="Abb. 17.2: Wofür der Erwartungswert-Plan 149 % mehr bezahlt" />
<figcaption aria-hidden="true">Abb. 17.2: Wofür der Erwartungswert-Plan 149 % mehr bezahlt</figcaption>
</figure>
<p>Drei Dinge stehen darin, die die Tabelle nicht zeigt. Die <strong>Anfahrkosten sind in beiden Plänen gleich</strong> (58 000 €) — der Erwartungswert-Plan spart also nicht dort, wo man es vermuten würde. Er spart <strong>12 725 € Brennstoff</strong>, weil er weniger Blockstunden vorhält. Und er bezahlt dafür <strong>536 239 € Lastabwurf</strong>: das <strong>42-fache</strong> seiner Ersparnis.</p>
<p>Genau diese Gegenüberstellung ist es, die eine Investitionsentscheidung trägt. „149 % mehr” ist eine Zahl, über die man streiten kann; „wir sparen 12 725 € und riskieren dafür 536 239 €” ist eine, über die man entscheidet.</p>