Glossar-Links: Fachbegriffe im Fließtext automatisch verlinken
Auto-Linking im Build: Glossar-Begriffe werden im Fließtext automatisch
erkannt und als Link auf den Glossar-Eintrag gesetzt — erste Nennung je
Begriff je Datei, dezent gestrichelte Unterstreichung im HTML, hyperref
im PDF. Kein manuelles Markieren bei Textänderungen nötig.
Neue Infrastruktur:
- glossar_eintraege_04.py: glossar_slug() + LINK_TEXTE-Map (automatisch
generiert aus EINTRAEGEN + Abkürzungs-Extraktion)
- erzeuge_glossar_04.py: jeder Eintrag bekommt {#gloss:<slug>}-Anchor
- build_version_04.py: resolve_glossar() — Auto-Linking + {gl:}-Marke
- web_04/site.css: .glossar-link (dezent, nicht wie Navigationslink)
5 neue Glossar-Einträge (waren als Begriff im Text, aber nicht im Glossar):
Solver, Scheduling, Graphen, Backtest, DCP (Disciplined Convex Programming)
Schutzmechanismen:
- Code-Blöcke, Inline-Code, {idx:}/{ref:}-Marken, Markdown-Links und
Überschriften werden nicht verlinkt
- Verschachtelung verhindert: 'CP-SAT-Solver' als Ganzes, nicht 'CP'+[
-'SAT'+[-'Solver'
- 'OR' als 2-Zeichen-Abkürzung nicht auto-verlinkt (False Positive in
'OR-Tools'); {gl:OR} als manuelle Marke
- Glossar selbst nicht auto-verlinkt (sonst Self-Links)
- reflow_markdown(): ::: als Block-Grenze (sonst kollabiert fenced div)
619 Glossar-Links im Gesamtdokument, 239 Anchor im Glossar, 34 im Vorwort.
This commit is contained in:
parent
81ddb02d5c
commit
e8abb66d75
52 changed files with 4316 additions and 1921 deletions
78
OR_HTML_04/praxisfallen.html
generated
78
OR_HTML_04/praxisfallen.html
generated
|
|
@ -126,7 +126,7 @@
|
|||
<blockquote>
|
||||
<p><strong>🚀 In 5 Minuten gelöst: Die Abnahmeprüfung, die in jedes Modell gehört</strong></p>
|
||||
<div class="sourceCode" id="cb1"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> pruefe_loesung(x, A, b, kosten, zielwert, ganzzahlig<span class="op">=</span>(), toleranz<span class="op">=</span><span class="fl">1e-6</span>):</span>
|
||||
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a> <span class="co">"""Prueft eine Loesung gegen die Anforderungen - OHNE den Solver zu fragen."""</span></span>
|
||||
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a> <span class="co">"""Prueft eine Loesung gegen die Anforderungen - OHNE den [Solver](anhang-glossar.md#gloss:solver){.glossar-link} zu fragen."""</span></span>
|
||||
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a> beanstandungen <span class="op">=</span> []</span>
|
||||
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a> verbrauch <span class="op">=</span> A <span class="op">@</span> x <span class="co"># 1. Werden Grenzen eingehalten?</span></span>
|
||||
|
|
@ -193,13 +193,13 @@
|
|||
<ol type="1">
|
||||
<li>… die fünf typischen Praxisfallen benennen und je ein Gegenmittel nennen.</li>
|
||||
<li>… ein unlösbares Modell in einen „am wenigsten schlechten“ Plan verwandeln.</li>
|
||||
<li>… Solver-Ergebnisse erklärbar machen (<em>Explainable OR</em>).</li>
|
||||
<li>… für jede Nebenbedingung beziffern, was sie den Plan kostet — und begründen, warum der Schattenpreis diese Frage nur für die <em>nächste</em> Einheit beantwortet.</li>
|
||||
<li>… Solver-Ergebnisse erklärbar machen (<em><a href="anhang-glossar.md#gloss:explainable-or" class="glossar-link">Explainable OR</a></em>).</li>
|
||||
<li>… für jede Nebenbedingung beziffern, was sie den Plan kostet — und begründen, warum der <a href="anhang-glossar.md#gloss:schattenpreis" class="glossar-link">Schattenpreis</a> diese Frage nur für die <em>nächste</em> Einheit beantwortet.</li>
|
||||
<li>… Zeitlimits und Optimalitätslücken sinnvoll setzen.</li>
|
||||
<li>… die Architektur einer produktionsreifen OR-Plattform skizzieren.</li>
|
||||
<li>… eine <strong>modellunabhängige Abnahmeprüfung</strong> schreiben, die eine Lösung gegen die Anforderungen prüft statt gegen das Modell.</li>
|
||||
<li>… Status, Gap und Zeitausschöpfung protokollieren und begründen, warum eine konstante Laufzeit bei Zeitlimit ein Warnsignal ist.</li>
|
||||
<li>… ein Modell in Domänenschicht, Modellbauer und Lösungs-DTO trennen — und begründen, warum sich das nicht wegen des Solverwechsels lohnt, sondern wegen der Prüfbarkeit.</li>
|
||||
<li>… ein Modell in Domänenschicht, Modellbauer und Lösungs-<a href="anhang-glossar.md#gloss:dto-data-transfer-object" class="glossar-link">DTO</a> trennen — und begründen, warum sich das nicht wegen des Solverwechsels lohnt, sondern wegen der Prüfbarkeit.</li>
|
||||
<li>… die Statuswerte verschiedener Solverbibliotheken auf eine gemeinsame Sprache abbilden.</li>
|
||||
</ol>
|
||||
<hr />
|
||||
|
|
@ -209,10 +209,10 @@
|
|||
<figcaption aria-hidden="true">Abb. 22.1: Die fünf typischen Praxisfallen</figcaption>
|
||||
</figure>
|
||||
<h3 id="falle-1-infeasibility">Falle 1 — Infeasibility</h3>
|
||||
<p>Wenn Parameter unglücklich zusammentreffen — drei Mitarbeitende gleichzeitig krank, kein qualifizierter Ersatz —, meldet der Solver schlicht <code>INFEASIBLE</code>.</p>
|
||||
<p>Wenn <a href="anhang-glossar.md#gloss:parameter" class="glossar-link">Parameter</a> unglücklich zusammentreffen — drei Mitarbeitende gleichzeitig krank, kein qualifizierter Ersatz —, meldet der Solver schlicht <code>INFEASIBLE</code>.</p>
|
||||
<ul>
|
||||
<li><strong>Falsch:</strong> Das System stürzt ab oder zeigt „Fehler“. Der Disponent steht ohne Plan da.</li>
|
||||
<li><strong>Richtig:</strong> <strong>Hierarchische Relaxation.</strong> Jede harte Bedingung, die im Notfall gebrochen werden darf, erhält eine teure Schlupfvariable. So liefert der Solver immer einen Plan — und zeigt zugleich präzise, <strong>wo</strong> es klemmt.</li>
|
||||
<li><strong>Richtig:</strong> <strong><a href="anhang-glossar.md#gloss:hierarchische-relaxation" class="glossar-link">Hierarchische Relaxation</a>.</strong> Jede harte Bedingung, die im Notfall gebrochen werden darf, erhält eine teure Schlupfvariable. So liefert der Solver immer einen Plan — und zeigt zugleich präzise, <strong>wo</strong> es klemmt.</li>
|
||||
</ul>
|
||||
<div class="sourceCode" id="cb2"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="co">#!/usr/bin/env python3</span></span>
|
||||
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a></span>
|
||||
|
|
@ -328,11 +328,11 @@
|
|||
<span id="cb2-112"><a href="#cb2-112" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"="</span> <span class="op">*</span> <span class="dv">78</span>)</span></code></pre></div>
|
||||
<h3 id="falle-2-der-black-box-effekt">Falle 2 — Der Black-Box-Effekt</h3>
|
||||
<p>Ein Planer oder Trader lehnt ein System ab, wenn er die Zuweisungen nicht nachvollziehen kann. <strong>Akzeptanz ist keine Nebensache, sondern Voraussetzung für den Betrieb.</strong></p>
|
||||
<p>Jede Entscheidung braucht einen <strong>Constraint-Trace</strong>:</p>
|
||||
<p>Jede Entscheidung braucht einen <strong><a href="anhang-glossar.md#gloss:constraint-trace" class="glossar-link">Constraint-Trace</a></strong>:</p>
|
||||
<blockquote>
|
||||
<p><em>„Warum bekommt Person A die Stunde und nicht Person B?“</em> → <em>„Weil B heute bereits zwei Vertretungsstunden hat und bei einer dritten die gesetzliche Ruhezeit von 11 Stunden unterschritten würde. A hat 80 Strafpunkte weniger.“</em></p>
|
||||
</blockquote>
|
||||
<p>Bei Portfolioentscheidungen: <strong>Kostenzerlegung</strong> ausweisen — Alpha-Ertrag, Risikoprämie, Transaktionskostenstrafe (siehe das Muster in <a href="cpsat.html#kap-cpsat">Kapitel 7</a> und <a href="cvar.html#kap-cvar">Kapitel 20</a>).</p>
|
||||
<p>Bei Portfolioentscheidungen: <strong><a href="anhang-glossar.md#gloss:kostenzerlegung" class="glossar-link">Kostenzerlegung</a></strong> ausweisen — Alpha-Ertrag, Risikoprämie, Transaktionskostenstrafe (siehe das Muster in <a href="cpsat.html#kap-cpsat">Kapitel 7</a> und <a href="cvar.html#kap-cvar">Kapitel 20</a>).</p>
|
||||
<blockquote>
|
||||
<p><strong>🎯 Die Faustregel für Erklärbarkeit</strong> Für jede Entscheidung sollten Sie drei Fragen beantworten können: 1. <strong>Warum diese Lösung?</strong> — Zielfunktionswert und seine Bestandteile. 2. <strong>Warum nicht die naheliegende Alternative?</strong> — Welche Bedingung verhindert sie? 3. <strong>Was würde die Lösung verbessern?</strong> — Schattenpreise: welcher Engpass, welcher Wert.</p>
|
||||
<p><a href="lp.html#kap-lp">Kapitel 5</a> liefert für Frage 3 das Werkzeug. Nutzen Sie es — Schattenpreise sind in Managementgesprächen oft wertvoller als die Lösung selbst.</p>
|
||||
|
|
@ -446,14 +446,14 @@
|
|||
<h3 id="falle-3-regimewechsel-und-schätzfehler">Falle 3 — Regimewechsel und Schätzfehler</h3>
|
||||
<p>Ein Modell, das auf einer mehrjährigen Aufwärtsphase kalibriert wurde, kennt keine Liquiditätskrise und keine Zinswende.</p>
|
||||
<ul>
|
||||
<li><strong>Robuste Schätzung</strong> statt roher Historie: Ledoit-Wolf-Shrinkage (<a href="finanzdaten.html#kap-finanzdaten">Kapitel 18</a>), Szenarien (<a href="unsicherheit.html#kap-unsicherheit">Kapitel 12</a>).</li>
|
||||
<li><strong>Robuste Schätzung</strong> statt roher Historie: <a href="anhang-glossar.md#gloss:ledoit-wolf-shrinkage" class="glossar-link">Ledoit-Wolf-Shrinkage</a> (<a href="finanzdaten.html#kap-finanzdaten">Kapitel 18</a>), Szenarien (<a href="unsicherheit.html#kap-unsicherheit">Kapitel 12</a>).</li>
|
||||
<li><strong>Harte Obergrenzen</strong> für Einzelpositionen und Sektoren — auch dann, wenn der Solver rechnerisch alles in einen Titel legen möchte. Die Grenze kostet Ertrag im Normalfall und rettet im Ernstfall.</li>
|
||||
<li><strong>Rollierende Neuschätzung</strong> statt einmaliger Kalibrierung.</li>
|
||||
</ul>
|
||||
<h3 id="falle-4-lookahead--und-survivorship-bias">Falle 4 — Lookahead- und Survivorship-Bias</h3>
|
||||
<p>Ausführlich in <a href="handelsmaschine.html#kap-handelsmaschine">Kapitel 21</a> behandelt. Die Kurzfassung: Beide Fehler machen Backtests systematisch zu gut, ohne eine Fehlermeldung zu erzeugen. Der Lookahead-Selbsttest aus <a href="handelsmaschine.html#sec:handelsmaschine-die-engine">Abschnitt 21.5</a> findet den ersten automatisch.</p>
|
||||
<h3 id="falle-5-laufzeitexplosion">Falle 5 — Laufzeitexplosion</h3>
|
||||
<p>Exakte Optimalität kann bei MILP oder CP-SAT Minuten bis Stunden dauern — und die Laufzeit wächst nicht linear mit der Problemgröße.</p>
|
||||
<p>Exakte Optimalität kann bei <a href="anhang-glossar.md#gloss:gemischt-ganzzahlige-optimierung-milp" class="glossar-link">MILP</a> oder <a href="anhang-glossar.md#gloss:cp-sat" class="glossar-link">CP-SAT</a> Minuten bis Stunden dauern — und die Laufzeit wächst nicht linear mit der Problemgröße.</p>
|
||||
<table>
|
||||
<colgroup>
|
||||
<col style="width: 33%" />
|
||||
|
|
@ -464,7 +464,7 @@
|
|||
<tr class="header">
|
||||
<th>Einsatzszenario</th>
|
||||
<th>Empfohlenes Zeitlimit</th>
|
||||
<th>Akzeptabler MIP-Gap</th>
|
||||
<th>Akzeptabler <a href="anhang-glossar.md#gloss:mip-gap" class="glossar-link">MIP-Gap</a></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
|
@ -496,11 +496,11 @@
|
|||
</blockquote>
|
||||
<hr />
|
||||
<h2 id="sec:praxisfallen-attribution">22.4 Constraint Attribution: welche Bedingung kostet wie viel?</h2>
|
||||
<p>Der Constraint-Trace beantwortet „warum <strong>diese</strong> Zuweisung?“. Der Deletion Filter in <a href="anhang-fehlerdiagnose.html#anhang-fehlerdiagnose">Anhang C</a> beantwortet „warum geht es <strong>gar nicht</strong>?“. Der häufigste Fall in der Praxis liegt dazwischen, und für ihn hat bisher niemand ein Werkzeug bekommen:</p>
|
||||
<p>Der Constraint-Trace beantwortet „warum <strong>diese</strong> Zuweisung?“. Der <a href="anhang-glossar.md#gloss:deletion-filter" class="glossar-link">Deletion Filter</a> in <a href="anhang-fehlerdiagnose.html#anhang-fehlerdiagnose">Anhang C</a> beantwortet „warum geht es <strong>gar nicht</strong>?“. Der häufigste Fall in der Praxis liegt dazwischen, und für ihn hat bisher niemand ein Werkzeug bekommen:</p>
|
||||
<blockquote>
|
||||
<p><em>Das Modell rechnet. Der Plan ist zulässig. Und trotzdem ist er enttäuschend — nur weiß niemand, woran es liegt.</em></p>
|
||||
</blockquote>
|
||||
<p>Die Antwort heißt <strong>Constraint Attribution</strong>: Jede Bedingungsgruppe wird einzeln gelockert, und gemessen wird, was sich am Zielwert ändert. Das ist dasselbe Verfahren wie der Deletion Filter — nur mit <strong>Kosten</strong> statt Zulässigkeit als Kriterium.</p>
|
||||
<p>Die Antwort heißt <strong><a href="anhang-glossar.md#gloss:constraint-attribution" class="glossar-link">Constraint Attribution</a></strong>: Jede Bedingungsgruppe wird einzeln gelockert, und gemessen wird, was sich am Zielwert ändert. Das ist dasselbe Verfahren wie der Deletion Filter — nur mit <strong>Kosten</strong> statt Zulässigkeit als Kriterium.</p>
|
||||
<p>Gerechnet wird auf derselben Fabrik wie die Konfliktsuche in <a href="anhang-fehlerdiagnose.html#anhang-fehlerdiagnose">Anhang C</a>, aber <strong>nach der Reparatur</strong>: Dort war die Lackierkapazität von 150 Stunden der Kern des Widerspruchs (<span class="math inline">2 \cdot 40 + 3 \cdot 30 = 170 > 150</span>). Eine zweite Schicht hat sie auf 210 gebracht, der Mindestumsatz wurde auf 10 000 € gesenkt. Jetzt ist das Modell lösbar — und die Frage lautet nicht mehr „warum nicht?“, sondern „was kostet uns was?“.</p>
|
||||
<div class="sourceCode" id="cb5"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="co">#!/usr/bin/env python3</span></span>
|
||||
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a></span>
|
||||
|
|
@ -908,7 +908,7 @@ aus.
|
|||
|
||||
==============================================================================</code></pre>
|
||||
<h3 id="drei-befunde-und-keiner-steht-im-solverergebnis">Drei Befunde, und keiner steht im Solverergebnis</h3>
|
||||
<p><strong>Erstens: bindend heißt nicht teuer.</strong> Fünf Bedingungen binden, aber „Lackierbudget Schicht 2“ tut es mit einem Schattenpreis von <strong>0,00 €</strong>. Sie berührt den Plan, ohne ihn zu verteuern — wer sie nachverhandelt, gewinnt nichts. Das ist derselbe Unterschied, den <code>Erklaerbarkeit.py</code> oben an einer einzelnen Zuweisung zeigt, hier im Dualwert eines LP.</p>
|
||||
<p><strong>Erstens: bindend heißt nicht teuer.</strong> Fünf Bedingungen binden, aber „Lackierbudget Schicht 2“ tut es mit einem Schattenpreis von <strong>0,00 €</strong>. Sie berührt den Plan, ohne ihn zu verteuern — wer sie nachverhandelt, gewinnt nichts. Das ist derselbe Unterschied, den <code>Erklaerbarkeit.py</code> oben an einer einzelnen Zuweisung zeigt, hier im Dualwert eines <a href="anhang-glossar.md#gloss:lineare-programmierung-lp" class="glossar-link">LP</a>.</p>
|
||||
<p><strong>Zweitens: Der Schattenpreis ist eine Momentaufnahme.</strong> Er gilt für die <strong>nächste</strong> Einheit. Ein Planer kauft aber keine Einheit, sondern eine Schicht. Für die Lackiererei verspricht die Hochrechnung <span class="math inline">4{,}00 \cdot 30 = 120</span> €; gemessen kommen <strong>60 €</strong>. Der Preis von 4,00 € gilt exakt bis <strong>+15 Stunden</strong>, danach begrenzt etwas anderes — <strong>die zweite Hälfte der Sonderschicht wäre bezahlt und wirkungslos.</strong></p>
|
||||
<p>Und die Ranglisten drehen sich dabei um: Nach Schattenpreis führt der Trägervertrag mit 18,00 € je Stück, nach tatsächlicher Wirkung die Montage-Sonderschicht mit 450 €. Der Schattenpreis sagt, was <strong>eine</strong> Einheit wert ist — nicht, wie viele Einheiten zu haben sind. Für die Frage „welchen Hebel ziehen wir?“ ist das der entscheidende Unterschied.</p>
|
||||
<p><strong>Drittens: Ein Wunsch kann unmöglich statt teuer sein.</strong> Der Vertrieb hätte gern 55 Rahmen statt 47,5. Das Modell antwortet nicht mit einem Preis, sondern mit <code>INFEASIBLE</code> — und drei Bedingungen blockieren den Wunsch <strong>gemeinsam</strong>: Fällt eine davon weg, ist er erfüllbar, keine allein ist „der“ Grund. Genau die Struktur, die <a href="anhang-fehlerdiagnose.html#anhang-fehlerdiagnose">Anhang C</a> für den unlösbaren Fall beschreibt, hier auf einen Wunsch angewandt.</p>
|
||||
|
|
@ -959,7 +959,7 @@ aus.
|
|||
<tr class="odd">
|
||||
<td><strong>Optimierungs-Worker</strong></td>
|
||||
<td>Modell bauen, lösen, Timeout, Fallback</td>
|
||||
<td>Celery/Redis, OR-Tools, HiGHS, CVXPY</td>
|
||||
<td>Celery/Redis, <a href="anhang-glossar.md#gloss:or-tools" class="glossar-link">OR-Tools</a>, <a href="anhang-glossar.md#gloss:highs" class="glossar-link">HiGHS</a>, <a href="anhang-glossar.md#gloss:cvxpy" class="glossar-link">CVXPY</a></td>
|
||||
</tr>
|
||||
<tr class="even">
|
||||
<td><strong>Disposition</strong></td>
|
||||
|
|
@ -981,10 +981,10 @@ aus.
|
|||
<p><strong>Was Sie in der Abbildung sehen.</strong> Fünf der sechs Schichten bilden einen Weg: Daten gehen oben hinein und unten als Handlung wieder hinaus. Die sechste steht daneben, und das ist keine zeichnerische Verlegenheit — Monitoring und Audit-Trail sind keine Station, die man durchläuft, sondern eine Anforderung an jede. Wer sie als sechsten Kasten unten anhängt, baut sie am Ende auch so: als etwas, das man hinterher noch macht.</p>
|
||||
<p><strong>Fünf Prinzipien, die sich in der Praxis bewährt haben:</strong></p>
|
||||
<ol type="1">
|
||||
<li><strong>Snapshot-Prinzip.</strong> Jeder Optimierungslauf arbeitet auf einem unveränderlichen Datenschnappschuss mit eigener ID. Nur so ist ein Ergebnis später reproduzierbar — und im Streitfall belegbar.</li>
|
||||
<li><strong>Zustandslosigkeit.</strong> Der Worker hält keinen Zustand; Eingabe und Ausgabe sind Daten. Das macht Skalierung und Wiederholung trivial.</li>
|
||||
<li><strong>Mensch in der Schleife.</strong> Der Optimierer <strong>schlägt vor</strong>, ein Mensch <strong>entscheidet</strong> — zumindest in der Einführungsphase. Das baut Vertrauen auf und fängt Modellfehler ab.</li>
|
||||
<li><strong>Fallback-Strategie.</strong> Was passiert, wenn der Solver kein Ergebnis liefert? Antwort: letzter gültiger Plan, regelbasierte Notlösung, Alarm. Nie: nichts.</li>
|
||||
<li><strong><a href="anhang-glossar.md#gloss:snapshot-prinzip" class="glossar-link">Snapshot-Prinzip</a>.</strong> Jeder Optimierungslauf arbeitet auf einem unveränderlichen Datenschnappschuss mit eigener ID. Nur so ist ein Ergebnis später reproduzierbar — und im Streitfall belegbar.</li>
|
||||
<li><strong><a href="anhang-glossar.md#gloss:zustandslosigkeit" class="glossar-link">Zustandslosigkeit</a>.</strong> Der Worker hält keinen Zustand; Eingabe und Ausgabe sind Daten. Das macht Skalierung und Wiederholung trivial.</li>
|
||||
<li><strong><a href="anhang-glossar.md#gloss:mensch-in-der-schleife" class="glossar-link">Mensch in der Schleife</a>.</strong> Der Optimierer <strong>schlägt vor</strong>, ein Mensch <strong>entscheidet</strong> — zumindest in der Einführungsphase. Das baut Vertrauen auf und fängt Modellfehler ab.</li>
|
||||
<li><strong><a href="anhang-glossar.md#gloss:fallback-strategie" class="glossar-link">Fallback-Strategie</a>.</strong> Was passiert, wenn der Solver kein Ergebnis liefert? Antwort: letzter gültiger Plan, regelbasierte Notlösung, Alarm. Nie: nichts.</li>
|
||||
<li><strong>Versionierung.</strong> Modellversion, Parametersatz und Solver-Version gehören ins Protokoll jedes Laufs. Ohne das lässt sich nicht klären, warum das Ergebnis von letzter Woche anders aussah.</li>
|
||||
</ol>
|
||||
<blockquote>
|
||||
|
|
@ -1062,9 +1062,9 @@ aus.
|
|||
<tr class="header">
|
||||
<th>Bedeutung</th>
|
||||
<th>pywraplp</th>
|
||||
<th>CP-SAT</th>
|
||||
<th><a href="anhang-glossar.md#gloss:constraint-programming-cp" class="glossar-link">CP</a>-<a href="anhang-glossar.md#gloss:sat-boolean-satisfiability" class="glossar-link">SAT</a></th>
|
||||
<th>HiGHS</th>
|
||||
<th>SciPy</th>
|
||||
<th><a href="anhang-glossar.md#gloss:scipy" class="glossar-link">SciPy</a></th>
|
||||
<th>CVXPY</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
|
@ -1694,7 +1694,7 @@ Domaenenschicht.
|
|||
<tr class="even">
|
||||
<td><code>import pandas</code> <strong>in</strong> der Funktion</td>
|
||||
<td>Excel-Schicht als optionale Abhängigkeit</td>
|
||||
<td>Wer <code>or_kern</code> nur für Statusauswertung und Prüfung benutzt, soll pandas nicht installieren müssen.</td>
|
||||
<td>Wer <code>or_kern</code> nur für Statusauswertung und Prüfung benutzt, soll <a href="anhang-glossar.md#gloss:pandas" class="glossar-link">pandas</a> nicht installieren müssen.</td>
|
||||
</tr>
|
||||
<tr class="odd">
|
||||
<td><code>schattenpreise</code> im DTO</td>
|
||||
|
|
@ -1710,7 +1710,7 @@ Domaenenschicht.
|
|||
<hr />
|
||||
<h2 id="sec:praxisfallen-solverwechsel">22.7 Der Solverwechsel in der Praxis</h2>
|
||||
<p>Der vorige Abschnitt endet mit einer Behauptung: Ein Solverwechsel betreffe genau <strong>einen</strong> Baustein. Das ist die Art Satz, die in jedem Architekturvortrag vorkommt und die man deshalb nicht glauben sollte, bevor sie jemand vorgeführt hat.</p>
|
||||
<p>Also führen wir sie vor — und zwar am unbequemsten Paar, das dieses Buch zu bieten hat: <strong>CP-SAT gegen HiGHS</strong>. Die beiden sind grundverschieden. CP-SAT ist ein Constraint-Programming-Solver, der ausschließlich ganzzahlig rechnet und Restriktionen als Ausdrücke entgegennimmt. HiGHS ist ein klassischer Branch-and-Bound-Löser, der eine Koeffizientenmatrix erwartet. Und sie lassen sich nicht einmal gemeinsam importieren (<a href="oekosystem.html#kap-oekosystem">Kapitel 3</a>).</p>
|
||||
<p>Also führen wir sie vor — und zwar am unbequemsten Paar, das dieses Buch zu bieten hat: <strong>CP-SAT gegen HiGHS</strong>. Die beiden sind grundverschieden. CP-SAT ist ein Constraint-Programming-Solver, der ausschließlich ganzzahlig rechnet und Restriktionen als Ausdrücke entgegennimmt. HiGHS ist ein klassischer <a href="anhang-glossar.md#gloss:branch-and-bound" class="glossar-link">Branch-and-Bound</a>-Löser, der eine Koeffizientenmatrix erwartet. Und sie lassen sich nicht einmal gemeinsam importieren (<a href="oekosystem.html#kap-oekosystem">Kapitel 3</a>).</p>
|
||||
<p><strong>Die Aufgabe</strong> ist eine kapazitierte Standortplanung: Aus sechs möglichen Lagern sind diejenigen zu eröffnen, mit denen zwölf Kunden am günstigsten beliefert werden. Jeder Kunde wird von genau einem Lager bedient, jedes eröffnete Lager kostet eine Fixgebühr, und die Kapazität reicht je Lager für 174 der insgesamt 387 Paletten — es müssen also mindestens drei Lager öffnen.</p>
|
||||
<p><strong>Der Aufbau folgt dem Muster aus <code>or_kern.py</code>:</strong></p>
|
||||
<table>
|
||||
|
|
@ -2141,16 +2141,16 @@ ein unzuverlaessiger Test (siehe JobShop_Intervalle.py).
|
|||
<hr />
|
||||
<h2 id="sec:praxisfallen-eine-checkliste-vor-dem-produktivgang">22.8 Eine Checkliste vor dem Produktivgang</h2>
|
||||
<p>Arbeiten Sie diese Liste ab, bevor ein OR-System in Betrieb geht:</p>
|
||||
<p><strong>Modell</strong> - [ ] Alle Nebenbedingungen sind dokumentiert — mit fachlicher Begründung, nicht nur als Code. - [ ] Für jede harte Bedingung ist geprüft: Muss sie wirklich hart sein? - [ ] Es gibt eine Relaxationsstrategie für den Infeasible-Fall. - [ ] Big-M-Werte sind so klein wie möglich gewählt. - [ ] Die Zielfunktion ist in konsistenten Einheiten formuliert.</p>
|
||||
<p><strong>Modell</strong> - [ ] Alle Nebenbedingungen sind dokumentiert — mit fachlicher Begründung, nicht nur als Code. - [ ] Für jede harte Bedingung ist geprüft: Muss sie wirklich hart sein? - [ ] Es gibt eine Relaxationsstrategie für den Infeasible-Fall. - [ ] Big-M-Werte sind so klein wie möglich gewählt. - [ ] Die <a href="anhang-glossar.md#gloss:zielfunktion" class="glossar-link">Zielfunktion</a> ist in konsistenten Einheiten formuliert.</p>
|
||||
<p><strong>Daten</strong> - [ ] Spaltenreihenfolge und Datentypen werden nach jedem Import geprüft. - [ ] Fehlende Werte und Ausreißer haben eine definierte Behandlung. - [ ] Kovarianzmatrizen werden auf positive Definitheit geprüft. - [ ] Datenstände sind versioniert und reproduzierbar.</p>
|
||||
<p><strong>Validierung</strong> - [ ] Das Ergebnis wurde gegen eine unabhängige Rechnung geprüft (Handrechnung, zweiter Solver, Simulation). - [ ] Alle Nebenbedingungen werden nach dem Lösen per <code>assert</code> verifiziert. - [ ] Es gibt einen Vergleich gegen eine naive Referenzstrategie. - [ ] Bei Backtests: Lookahead-Selbsttest bestanden, Zahl der Versuche protokolliert.</p>
|
||||
<p><strong>Betrieb</strong> - [ ] Zeitlimit und akzeptierter Gap sind festgelegt und begründet. - [ ] Es gibt eine Fallback-Strategie und Alarmierung. - [ ] Jedes Ergebnis ist mit Snapshot-ID, Modellversion und Solver-Version protokolliert. - [ ] Die Ergebnisse sind erklärbar (Kostenzerlegung, Schattenpreise, Constraint-Trace).</p>
|
||||
<hr />
|
||||
<h2 id="sec:praxisfallen-weiterfuehrende-literatur-und-roadmap">22.9 Weiterführende Literatur und Roadmap</h2>
|
||||
<p><strong>Grundlagen und lineare/ganzzahlige Optimierung</strong> * Bertsimas & Tsitsiklis: <em>Introduction to Linear Optimization</em> — Standardwerk zu Simplex, Dualität, Polyedertheorie. * Wolsey: <em>Integer Programming</em> — Branch-and-Cut, Schnittebenen, Formulierungsstärke.</p>
|
||||
<p><strong>Grundlagen und lineare/ganzzahlige Optimierung</strong> * Bertsimas & Tsitsiklis: <em>Introduction to Linear Optimization</em> — Standardwerk zu Simplex, Dualität, Polyedertheorie. * Wolsey: <em>Integer Programming</em> — <a href="anhang-glossar.md#gloss:branch-and-cut" class="glossar-link">Branch-and-Cut</a>, Schnittebenen, Formulierungsstärke.</p>
|
||||
<p><strong>Konvexe Optimierung</strong> * Boyd & Vandenberghe: <em>Convex Optimization</em> — Pflichtlektüre; frei verfügbar. Die theoretische Basis von CVXPY.</p>
|
||||
<p><strong>Constraint Programming und Scheduling</strong> * Google OR-Tools Dokumentation und das CP-SAT-Primer von Laurent Perron.</p>
|
||||
<p><strong>Quantitative Finanzmathematik</strong> * López de Prado: <em>Advances in Financial Machine Learning</em> — Backtest-Overfitting, Denoising, Deflated Sharpe Ratio. * Cornuéjols, Peña & Tütüncü: <em>Optimization Methods in Finance</em>.</p>
|
||||
<p><strong>Constraint Programming und <a href="anhang-glossar.md#gloss:scheduling" class="glossar-link">Scheduling</a></strong> * Google OR-Tools Dokumentation und das CP-SAT-Primer von Laurent Perron.</p>
|
||||
<p><strong>Quantitative Finanzmathematik</strong> * López de Prado: <em>Advances in Financial Machine Learning</em> — <a href="anhang-glossar.md#gloss:backtest" class="glossar-link">Backtest</a>-<a href="anhang-glossar.md#gloss:overfitting" class="glossar-link">Overfitting</a>, Denoising, Deflated <a href="anhang-glossar.md#gloss:sharpe-ratio" class="glossar-link">Sharpe Ratio</a>. * Cornuéjols, Peña & Tütüncü: <em>Optimization Methods in Finance</em>.</p>
|
||||
<p><strong>Wie es weitergeht</strong></p>
|
||||
<p>Der nächste Schritt nach diesem Kurs ist selten ein weiteres Verfahren, sondern die <strong>Verankerung im Betrieb</strong>: reproduzierbare Datenpipelines, versionierte Modelle, Monitoring der Lösungsqualität, bewusster Umgang mit Zeitlimits.</p>
|
||||
<p>Wenn Sie doch tiefer in die Methodik wollen, sind das die lohnendsten Richtungen:</p>
|
||||
|
|
@ -2169,27 +2169,27 @@ ein unzuverlaessiger Test (siehe JobShop_Intervalle.py).
|
|||
</thead>
|
||||
<tbody>
|
||||
<tr class="odd">
|
||||
<td><strong>Column Generation / Branch-and-Price</strong></td>
|
||||
<td><strong><a href="anhang-glossar.md#gloss:column-generation" class="glossar-link">Column Generation</a> / Branch-and-Price</strong></td>
|
||||
<td>sehr große Zuschnitt- und Dienstplanprobleme</td>
|
||||
<td><a href="dekomposition.html#kap-dekomposition">Kapitel 10</a>, Wolsey</td>
|
||||
</tr>
|
||||
<tr class="even">
|
||||
<td><strong>Benders-Zerlegung</strong></td>
|
||||
<td><strong><a href="anhang-glossar.md#gloss:benders-zerlegung" class="glossar-link">Benders-Zerlegung</a></strong></td>
|
||||
<td>zweistufige stochastische Modelle mit vielen Szenarien</td>
|
||||
<td>Birge & Louveaux</td>
|
||||
</tr>
|
||||
<tr class="odd">
|
||||
<td><strong>Approximate Dynamic Programming / RL</strong></td>
|
||||
<td><strong><a href="anhang-glossar.md#gloss:approximate-dynamic-programming" class="glossar-link">Approximate Dynamic Programming</a> / RL</strong></td>
|
||||
<td>hochdimensionale Zustandsräume</td>
|
||||
<td>Powell: <em>Reinforcement Learning and Stochastic Optimization</em></td>
|
||||
<td>Powell: <em><a href="anhang-glossar.md#gloss:reinforcement-learning" class="glossar-link">Reinforcement Learning</a> and Stochastic Optimization</em></td>
|
||||
</tr>
|
||||
<tr class="even">
|
||||
<td><strong>Konische Optimierung (SOCP, SDP)</strong></td>
|
||||
<td><strong><a href="anhang-glossar.md#gloss:konische-optimierung" class="glossar-link">Konische Optimierung</a> (SOCP, SDP)</strong></td>
|
||||
<td>robuste Portfolios, Ellipsoid-Unsicherheit</td>
|
||||
<td>Boyd & Vandenberghe, <a href="lp.html#kap-lp">Kapitel 5</a></td>
|
||||
</tr>
|
||||
<tr class="odd">
|
||||
<td><strong>Multi-Objective Optimization</strong></td>
|
||||
<td><strong><a href="anhang-glossar.md#gloss:multi-objective-optimization" class="glossar-link">Multi-Objective Optimization</a></strong></td>
|
||||
<td>echte Zielkonflikte ohne Gewichtung</td>
|
||||
<td>Ehrgott: <em>Multicriteria Optimization</em></td>
|
||||
</tr>
|
||||
|
|
@ -2201,15 +2201,15 @@ ein unzuverlaessiger Test (siehe JobShop_Intervalle.py).
|
|||
<p>Lösungen: <a href="anhang-loesungen.html#sec:loesungen-praxisfallen">Abschnitt A.22</a>.</p>
|
||||
</blockquote>
|
||||
<p><strong>Aufgabe 22.1 ⭐ — Hart oder weich, revisited.</strong> Nennen Sie für ein Vertretungsplanungssystem je zwei Bedingungen, die (a) zwingend hart bleiben müssen, (b) unbedingt weich sein sollten, (c) diskutabel sind. Begründen Sie.</p>
|
||||
<p><strong>Aufgabe 22.2 ⭐ — Zeitlimit wählen.</strong> Für welche Szenarien setzen Sie welches Zeitlimit und welchen Gap? (a) Taxi-Disposition in Echtzeit, (b) Wochendienstplan, freitags erstellt, (c) Jahresproduktionsplanung, (d) Portfolio-Rebalancing monatlich.</p>
|
||||
<p><strong>Aufgabe 22.3 ⭐⭐ — Relaxation einbauen.</strong> Nehmen Sie Ihr Modell aus der Aufgabe <em>Eigener Dienstplan</em> (<a href="cpsat.html#sec:cpsat-uebungsaufgaben">Abschnitt 7.9</a>) und machen Sie es <code>INFEASIBLE</code>-sicher: Schlupfvariablen für unbesetzte Schichten, gestaffelte Strafen. Testen Sie mit einem bewusst überlasteten Szenario.</p>
|
||||
<p><strong>Aufgabe 22.2 ⭐ — Zeitlimit wählen.</strong> Für welche Szenarien setzen Sie welches Zeitlimit und welchen Gap? (a) Taxi-Disposition in Echtzeit, (b) Wochendienstplan, freitags erstellt, (c) Jahresproduktionsplanung, (d) Portfolio-<a href="anhang-glossar.md#gloss:rebalancing" class="glossar-link">Rebalancing</a> monatlich.</p>
|
||||
<p><strong>Aufgabe 22.3 ⭐⭐ — <a href="anhang-glossar.md#gloss:relaxation" class="glossar-link">Relaxation</a> einbauen.</strong> Nehmen Sie Ihr Modell aus der Aufgabe <em>Eigener Dienstplan</em> (<a href="cpsat.html#sec:cpsat-uebungsaufgaben">Abschnitt 7.9</a>) und machen Sie es <code>INFEASIBLE</code>-sicher: Schlupfvariablen für unbesetzte Schichten, gestaffelte Strafen. Testen Sie mit einem bewusst überlasteten Szenario.</p>
|
||||
<p><strong>Aufgabe 22.4 ⭐⭐ — Erklärbarkeit implementieren.</strong> Erweitern Sie ein beliebiges Modell aus dem Kurs um einen <code>erklaere(loesung)</code>-Report, der die drei Fragen aus <a href="#sec:praxisfallen-die-fuenf-typischen-praxisfallen">Abschnitt 22.3</a> beantwortet.</p>
|
||||
<p><strong>Aufgabe 22.5 ⭐⭐ — Den Bericht in die Irre führen.</strong> <code>Constraint_Attribution.py</code> erzeugt seinen Bericht aus gerechneten Zahlen — richtig ist er deshalb noch nicht. (a) Setzen Sie den Deckungsbeitrag von <em>Deckel</em> von 9 € auf 20 €. Wie ändern sich Plan, Rangliste und Bericht? Welche Sätze bleiben wörtlich stehen, obwohl sie jetzt etwas anderes bedeuten? (b) Der Bericht nennt „Liefervertrag Träger” als teuerste Bindung. Formulieren Sie den Satz so um, dass ein Leser erkennt, <strong>worauf</strong> die Aussage beruht. (c) Welche Angabe müsste das Programm zusätzlich ausgeben, damit ein Empfänger die Belastbarkeit selbst einschätzen kann?</p>
|
||||
<p><strong>Aufgabe 22.6 ⭐⭐⭐ — Gap gegen Laufzeit.</strong> Nehmen Sie das MILP-Portfolio aus <a href="milp.html#kap-milp">Kapitel 6</a> und vergrößern Sie es auf 50 Anlagen. Messen Sie Laufzeit und Zielwert bei Gap-Vorgaben von 10 %, 5 %, 2 %, 1 %, 0,1 % und 0 %. Stellen Sie den Zusammenhang grafisch dar und leiten Sie eine Empfehlung ab.</p>
|
||||
<p><strong>Aufgabe 22.7 ⭐⭐⭐ — Post-Mortem schreiben.</strong> Suchen Sie sich einen der im Buch besprochenen Fehler aus (z. B. die Vorzeichenfalle in <a href="lp.html#sec:lp-die-vorzeichenfalle-bei-schattenpreisen">Abschnitt 5.7</a>, die ungültige Kovarianzmatrix in <a href="qp-nlp.html#kap-qp-nlp">Kapitel 11</a>, die Sektor-Positionsindizes in <a href="markowitz.html#kap-markowitz">Kapitel 19</a>, die vermischten Einheiten in <a href="cvar.html#sec:cvar-implementierung-cvar-portfolio-mit-reibung">Abschnitt 20.6</a> oder die Rebalancing-Termine in <a href="handelsmaschine.html#sec:handelsmaschine-rebalancing-termine-richtig-bestimmen">Abschnitt 21.4</a>) und schreiben Sie ein einseitiges Post-Mortem: Was war der Fehler? Warum fiel er nicht auf? Welche Prüfung hätte ihn gefunden? Welche Regel leiten Sie daraus für eigene Projekte ab?</p>
|
||||
<p><strong>Aufgabe 22.7 ⭐⭐⭐ — Post-Mortem schreiben.</strong> Suchen Sie sich einen der im Buch besprochenen Fehler aus (z. B. die Vorzeichenfalle in <a href="lp.html#sec:lp-die-vorzeichenfalle-bei-schattenpreisen">Abschnitt 5.7</a>, die ungültige <a href="anhang-glossar.md#gloss:kovarianzmatrix" class="glossar-link">Kovarianzmatrix</a> in <a href="qp-nlp.html#kap-qp-nlp">Kapitel 11</a>, die Sektor-Positionsindizes in <a href="markowitz.html#kap-markowitz">Kapitel 19</a>, die vermischten Einheiten in <a href="cvar.html#sec:cvar-implementierung-cvar-portfolio-mit-reibung">Abschnitt 20.6</a> oder die Rebalancing-Termine in <a href="handelsmaschine.html#sec:handelsmaschine-rebalancing-termine-richtig-bestimmen">Abschnitt 21.4</a>) und schreiben Sie ein einseitiges Post-Mortem: Was war der Fehler? Warum fiel er nicht auf? Welche Prüfung hätte ihn gefunden? Welche Regel leiten Sie daraus für eigene Projekte ab?</p>
|
||||
<hr />
|
||||
<h2 id="sec:praxisfallen-denkfehler">22.11 Finde den Denkfehler</h2>
|
||||
<p>Falle 5 — die Laufzeitexplosion — zeigt sich im Betrieb selten als Absturz. Sie zeigt sich als <strong>gar nichts</strong>.</p>
|
||||
<p>Falle 5 — die <a href="anhang-glossar.md#gloss:laufzeitexplosion" class="glossar-link">Laufzeitexplosion</a> — zeigt sich im Betrieb selten als Absturz. Sie zeigt sich als <strong>gar nichts</strong>.</p>
|
||||
<div class="card card-denkfehler">
|
||||
<blockquote>
|
||||
<p><strong>🐛 Finde den Denkfehler: Das Modell, das seit einem Jahr nicht mehr optimiert</strong></p>
|
||||
|
|
@ -2501,7 +2501,7 @@ sichtbar wird, und gibt Zeit zum Handeln.
|
|||
<p>Genau eine Antwort ist jeweils richtig. Auflösung in <a href="anhang-loesungen.html#quiz-loesung-praxisfallen">Anhang A</a>.</p>
|
||||
<p><strong>1. Ihr Nachtjob läuft seit Monaten konstant 3,0 Sekunden bei einem Zeitlimit von 3 Sekunden. Was schließen Sie daraus?</strong> (a) Das System ist bemerkenswert stabil. (b) Das Zeitlimit greift jedes Mal. Der Solver bricht ab, statt fertig zu werden — die konstante Laufzeit ist das Symptom, nicht die Beruhigung. (c) Der Rechner ist ausgelastet und sollte aufgerüstet werden.</p>
|
||||
<p><strong>2. Eine Prüffunktion soll kontrollieren, ob ein Tourenplan die Fahrzeugkapazitäten einhält. Woher nimmt sie die geladenen Mengen?</strong> (a) Aus der Ladungsdimension des Routing-Modells — dort stehen sie ja bereits. (b) Sie summiert die Bedarfe der Kunden aus dem <strong>ausgegebenen Tourenplan</strong> auf. Alles andere fragt das Modell, ob es sich an sich selbst hält. (c) Aus der Zielfunktion, sofern die Kapazität dort bepreist ist.</p>
|
||||
<p><strong>3. Ein Modell meldet <code>INFEASIBLE</code>, nachdem eine neue Regel aufgenommen wurde. Was ist der produktivste erste Schritt?</strong> (a) Das Zeitlimit erhöhen. (b) Die neue Regel wieder entfernen und in Ruhe abwarten. (c) Die harten Regeln hierarchisch lockern — mit teuren Strafkosten statt Verboten —, damit der Solver benennt, <strong>welche</strong> Regel den Widerspruch erzeugt, statt nur zu sagen, dass es einen gibt.</p>
|
||||
<p><strong>3. Ein Modell meldet <code>INFEASIBLE</code>, nachdem eine neue Regel aufgenommen wurde. Was ist der produktivste erste Schritt?</strong> (a) Das Zeitlimit erhöhen. (b) Die neue Regel wieder entfernen und in Ruhe abwarten. (c) Die harten Regeln hierarchisch lockern — mit teuren <a href="anhang-glossar.md#gloss:strafkosten" class="glossar-link">Strafkosten</a> statt Verboten —, damit der Solver benennt, <strong>welche</strong> Regel den Widerspruch erzeugt, statt nur zu sagen, dass es einen gibt.</p>
|
||||
</blockquote>
|
||||
</div>
|
||||
<hr />
|
||||
|
|
@ -2521,7 +2521,7 @@ sichtbar wird, und gibt Zeit zum Handeln.
|
|||
<hr />
|
||||
<h2 id="sec:praxisfallen-zusammenfassung">22.14 Zusammenfassung</h2>
|
||||
<ul>
|
||||
<li><strong>Infeasibility ist ein Entwurfsproblem, kein Solverproblem.</strong> Wer alles hart formuliert, erhält irgendwann eine Fehlermeldung statt eines Plans.</li>
|
||||
<li><strong><a href="anhang-glossar.md#gloss:infeasibility" class="glossar-link">Infeasibility</a> ist ein Entwurfsproblem, kein Solverproblem.</strong> Wer alles hart formuliert, erhält irgendwann eine Fehlermeldung statt eines Plans.</li>
|
||||
<li><strong>Erklärbarkeit entscheidet über Akzeptanz.</strong> Schattenpreise, Kostenzerlegung und Constraint-Traces sind keine Kür.</li>
|
||||
<li><strong>Bindend heißt nicht teuer.</strong> Eine Bedingung kann den Plan berühren und trotzdem 0,00 € kosten. Nur die kostenrelevanten lohnen eine Nachverhandlung.</li>
|
||||
<li><strong>Der Schattenpreis gilt für die nächste Einheit, nicht für die nächste Schicht.</strong> Hochgerechnet auf einen realistischen Schritt überschätzt er den Nutzen — im Beispiel um das Doppelte. Wer wissen will, was ein Hebel bringt, <strong>misst</strong> die Lockerung, statt zu multiplizieren; die beiden Ranglisten können sich dabei umdrehen.</li>
|
||||
|
|
|
|||
Loading…
Reference in a new issue