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
30
OR_HTML_04/lp.html
generated
30
OR_HTML_04/lp.html
generated
|
|
@ -107,17 +107,17 @@
|
|||
<figcaption aria-hidden="true">Entscheidungsdiagramm: Welches Werkzeug passt zu meinem Problem? (Teil II)</figcaption>
|
||||
</figure>
|
||||
<blockquote>
|
||||
<p><strong>🎯 Merksatz zum Diagramm</strong> Die erste Frage ist die wichtigste — und sie lautet <strong>nicht</strong> „welcher Solver ist der schnellste?“, sondern „welche <strong>Struktur</strong> hat mein Problem?“. Ein Zuordnungsproblem braucht keinen MILP-Solver, sondern eine Zeile <code>linear_sum_assignment</code>. Ein Dienstplan gehört nicht in ein LP, sondern zu CP-SAT. Wer die Struktur erkennt, hat die halbe Laufzeit gespart, bevor die erste Zeile Code geschrieben ist.</p>
|
||||
<p><strong>🎯 Merksatz zum Diagramm</strong> Die erste Frage ist die wichtigste — und sie lautet <strong>nicht</strong> „welcher <a href="anhang-glossar.md#gloss:solver" class="glossar-link">Solver</a> ist der schnellste?“, sondern „welche <strong>Struktur</strong> hat mein Problem?“. Ein <a href="anhang-glossar.md#gloss:zuordnungsproblem" class="glossar-link">Zuordnungsproblem</a> braucht keinen <a href="anhang-glossar.md#gloss:gemischt-ganzzahlige-optimierung-milp" class="glossar-link">MILP</a>-Solver, sondern eine Zeile <code>linear_sum_assignment</code>. Ein Dienstplan gehört nicht in ein <a href="anhang-glossar.md#gloss:lineare-programmierung-lp" class="glossar-link">LP</a>, sondern zu <a href="anhang-glossar.md#gloss:cp-sat" class="glossar-link">CP-SAT</a>. Wer die Struktur erkennt, hat die halbe Laufzeit gespart, bevor die erste Zeile Code geschrieben ist.</p>
|
||||
</blockquote>
|
||||
<p>Fällt Ihr Problem durch das Diagramm hindurch — nichtlineare Zielfunktion, unsichere Daten, Entscheidungen über mehrere Zeitstufen —, dann ist <a href="qp-nlp.html#teil-nichtlinear">Teil III</a> der richtige Ort. Dort steht ein zweites Diagramm für genau diese Fälle.</p>
|
||||
<p>Fällt Ihr Problem durch das Diagramm hindurch — nichtlineare <a href="anhang-glossar.md#gloss:zielfunktion" class="glossar-link">Zielfunktion</a>, unsichere Daten, Entscheidungen über mehrere Zeitstufen —, dann ist <a href="qp-nlp.html#teil-nichtlinear">Teil III</a> der richtige Ort. Dort steht ein zweites Diagramm für genau diese Fälle.</p>
|
||||
<hr />
|
||||
<h1 id="kap-lp">Kapitel 5: Lineare Programmierung — Simplex, Dualität und Schattenpreise</h1>
|
||||
<div class="card card-blick">
|
||||
<blockquote>
|
||||
<p><strong>📌 Kapitel auf einen Blick</strong></p>
|
||||
<p><strong>Worum geht es?</strong> Um das Kernverfahren des Operations Research. Wir bauen den Simplex-Algorithmus selbst — nicht um ihn zu verwenden, sondern um zu verstehen, woher <strong>Schattenpreise</strong> kommen. Sie sind das wertvollste Nebenprodukt jeder Optimierung.</p>
|
||||
<p><strong>Voraussetzungen:</strong> <a href="fundament.html#kap-fundament">Kapitel 2</a> (Matrixform, Polyeder, Ecken).</p>
|
||||
<p><strong>Danach können Sie:</strong> Ein LP in Standardform bringen, den Simplex von Hand rechnen, Dualwerte interpretieren, daraus wirtschaftliche Handlungsempfehlungen ableiten — und erkennen, wann ein Schattenpreis eine Entscheidung <strong>nicht</strong> tragen darf.</p>
|
||||
<p><strong>Worum geht es?</strong> Um das Kernverfahren des Operations Research. Wir bauen den <a href="anhang-glossar.md#gloss:simplex-algorithmus" class="glossar-link">Simplex-Algorithmus</a> selbst — nicht um ihn zu verwenden, sondern um zu verstehen, woher <strong>Schattenpreise</strong> kommen. Sie sind das wertvollste Nebenprodukt jeder Optimierung.</p>
|
||||
<p><strong>Voraussetzungen:</strong> <a href="fundament.html#kap-fundament">Kapitel 2</a> (Matrixform, <a href="anhang-glossar.md#gloss:polyeder" class="glossar-link">Polyeder</a>, Ecken).</p>
|
||||
<p><strong>Danach können Sie:</strong> Ein LP in Standardform bringen, den Simplex von Hand rechnen, Dualwerte interpretieren, daraus wirtschaftliche Handlungsempfehlungen ableiten — und erkennen, wann ein <a href="anhang-glossar.md#gloss:schattenpreis" class="glossar-link">Schattenpreis</a> eine Entscheidung <strong>nicht</strong> tragen darf.</p>
|
||||
<p><strong>Zeitbedarf:</strong> ca. 7 Stunden — das umfangreichste Kapitel von <a href="#teil-kernverfahren">Teil II</a>.</p>
|
||||
<p><strong>Programme:</strong><br />
|
||||
<code>Simplex_Tableau_LP.py</code><br />
|
||||
|
|
@ -162,7 +162,7 @@
|
|||
</tbody>
|
||||
</table>
|
||||
<p>Der Betriebsrat hat 20 Überstunden genehmigt. <strong>In welchem Bereich sollen sie eingesetzt werden?</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="im">from</span> scipy.optimize <span class="im">import</span> linprog</span>
|
||||
<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="im">from</span> scipy.optimize <span class="im">import</span> [linprog](anhang<span class="op">-</span>glossar.md<span class="co">#gloss:linprog){.glossar-link}</span></span>
|
||||
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="co"># Deckungsbeitrag je Stueck (negiert, weil linprog minimiert)</span></span>
|
||||
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>c <span class="op">=</span> [<span class="op">-</span><span class="dv">90</span>, <span class="op">-</span><span class="dv">140</span>]</span>
|
||||
|
|
@ -198,9 +198,9 @@
|
|||
<li>… eine Simplex-Iteration von Hand rechnen: Pivotspalte, Pivotzeile, Basistausch.</li>
|
||||
<li>… erklären, warum das Verfahren terminiert und warum es das Optimum findet.</li>
|
||||
<li>… das duale Problem zu einem gegebenen primalen aufstellen.</li>
|
||||
<li>… <strong>Schattenpreise</strong> korrekt auslesen und interpretieren — inklusive der Vorzeichenfalle, die einer der häufigsten Fehler bei der Sensitivitätsanalyse ist.</li>
|
||||
<li>… <strong>Schattenpreise</strong> korrekt auslesen und interpretieren — inklusive der Vorzeichenfalle, die einer der häufigsten Fehler bei der <a href="anhang-glossar.md#gloss:sensitivitaetsanalyse" class="glossar-link">Sensitivitätsanalyse</a> ist.</li>
|
||||
<li>… aus einer Sensitivitätsanalyse eine begründete Kaufentscheidung ableiten.</li>
|
||||
<li>… ein Modell auf <strong>Entartung</strong> prüfen und statt eines nicht eindeutigen Schattenpreises dessen belastbare Spanne berechnen.</li>
|
||||
<li>… ein Modell auf <strong><a href="anhang-glossar.md#gloss:entartung" class="glossar-link">Entartung</a></strong> prüfen und statt eines nicht eindeutigen Schattenpreises dessen belastbare Spanne berechnen.</li>
|
||||
<li>… erklären, warum Zulässigkeit immer gegen eine Toleranz und nie mit <code>== 0</code> geprüft wird.</li>
|
||||
</ol>
|
||||
<hr />
|
||||
|
|
@ -251,7 +251,7 @@
|
|||
<p>Der von George Dantzig 1947 formulierte Simplex-Algorithmus nutzt den Fundamentalsatz aus <a href="fundament.html#kap-fundament">Kapitel 2</a>: <strong>Das Optimum liegt in einer Ecke.</strong> Statt alle Ecken aufzuzählen, wandert er von Ecke zu Ecke — und zwar immer in Richtung Verbesserung.</p>
|
||||
<figure>
|
||||
<img src="bilder_04/kap_lp_simplex_ecken.svg" alt="Abb. 5.1: Derselbe zulässige Bereich, aber der Weg der Handrechnung weiter unten: vom Ursprung über (0; 8) zum Optimum (7,5; 5). Drei der fünf Ecken werden besucht, keine zweimal — das ist der ganze Gewinn gegenüber dem Aufzählen aller Ecken. Punktiert die Niveaulinien der Zielfunktion, der Pfeil ihr Gradient \mathbf{c}. Erzeugt von bilder_04/erzeuge_polyeder.py." />
|
||||
<figcaption aria-hidden="true">Abb. 5.1: Derselbe zulässige Bereich, aber der Weg der Handrechnung weiter unten: vom Ursprung über (0; 8) zum Optimum (7,5; 5). Drei der fünf Ecken werden besucht, keine zweimal — das ist der ganze Gewinn gegenüber dem Aufzählen aller Ecken. Punktiert die Niveaulinien der Zielfunktion, der Pfeil ihr Gradient <span class="math inline">\mathbf{c}</span>. Erzeugt von <code>bilder_04/erzeuge_polyeder.py</code>.</figcaption>
|
||||
<figcaption aria-hidden="true">Abb. 5.1: Derselbe zulässige Bereich, aber der Weg der Handrechnung weiter unten: vom Ursprung über (0; 8) zum Optimum (7,5; 5). Drei der fünf Ecken werden besucht, keine zweimal — das ist der ganze Gewinn gegenüber dem Aufzählen aller Ecken. Punktiert die Niveaulinien der Zielfunktion, der Pfeil ihr <a href="anhang-glossar.md#gloss:gradient" class="glossar-link">Gradient</a> <span class="math inline">\mathbf{c}</span>. Erzeugt von <code>bilder_04/erzeuge_polyeder.py</code>.</figcaption>
|
||||
</figure>
|
||||
<p><strong>Was Sie in der Abbildung sehen.</strong> Durch jede besuchte Ecke läuft genau eine Niveaulinie — die Linien sind nicht gewählt, sondern die Zielwerte 0 €, 2.000 € und 2.375 € der drei Ecken. Der Simplex schiebt diese Linie in Richtung des Pfeils so weit hinaus, wie das Polyeder es zulässt. Dass er dabei an einer Ecke anhält und nicht mittendrin, ist keine Eigenheit des Verfahrens, sondern der Fundamentalsatz: Weiter geht es nur noch hinaus.</p>
|
||||
<h3 id="der-ablauf">Der Ablauf</h3>
|
||||
|
|
@ -682,7 +682,7 @@ Optimum nach 2 Pivotschritten erreicht.
|
|||
<ul>
|
||||
<li><strong>Negative rechte Seite.</strong> <span class="math inline">-3x_1 - 2x_2 \le -12</span> (aus einer „<span class="math inline">\ge</span>“-Bedingung entstanden) macht den Ursprung unzulässig. Dann braucht man Phase 1 mit künstlichen Variablen. Dieser Solver meldet das jetzt ehrlich.</li>
|
||||
<li><strong>Zyklen bei Entartung.</strong> Wenn mehrere Quotienten gleich sind, kann der Simplex theoretisch endlos kreisen. In der Praxis extrem selten; Bland’s Regel verhindert es beweisbar.</li>
|
||||
<li><strong>Den Simplex selbst produktiv einsetzen.</strong> Diese Implementierung ist ein Lehrmodell. HiGHS ist um Größenordnungen schneller und numerisch stabiler.</li>
|
||||
<li><strong>Den Simplex selbst produktiv einsetzen.</strong> Diese Implementierung ist ein Lehrmodell. <a href="anhang-glossar.md#gloss:highs" class="glossar-link">HiGHS</a> ist um Größenordnungen schneller und numerisch stabiler.</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
<hr />
|
||||
|
|
@ -1120,7 +1120,7 @@ Pruefung: komplementaerer Schlupf fuer alle Ressourcen erfuellt.
|
|||
<ol type="1">
|
||||
<li><strong><code>schattenpreise = -ergebnis.ineqlin.marginals</code></strong> — die eigentliche Korrektur.</li>
|
||||
<li><strong>Numerische Gegenprobe:</strong> Das Modell wird mit <span class="math inline">b_3 + 1</span> neu gelöst; der gemessene Zuwachs muss dem Schattenpreis entsprechen. Diese Prüfung ist unabhängig von jeder Vorzeichenkonvention und deshalb der zuverlässigste Test überhaupt.</li>
|
||||
<li><strong>Komplementärer Schlupf:</strong> <span class="math inline">s_i \cdot y_i = 0</span> muss für alle <span class="math inline">i</span> gelten.</li>
|
||||
<li><strong><a href="anhang-glossar.md#gloss:komplementaerer-schlupf" class="glossar-link">Komplementärer Schlupf</a>:</strong> <span class="math inline">s_i \cdot y_i = 0</span> muss für alle <span class="math inline">i</span> gelten.</li>
|
||||
</ol>
|
||||
<p><strong>Übernehmen Sie dieses Muster in eigene Projekte.</strong> Der Aufwand ist eine Handvoll Zeilen, der Nutzen ist die Gewissheit, dass Ihre Handlungsempfehlung nicht das Gegenteil des Richtigen sagt.</p>
|
||||
</blockquote>
|
||||
|
|
@ -1158,7 +1158,7 @@ Pruefung: komplementaerer Schlupf fuer alle Ressourcen erfuellt.
|
|||
</thead>
|
||||
<tbody>
|
||||
<tr class="odd">
|
||||
<td>Dual Simplex</td>
|
||||
<td><a href="anhang-glossar.md#gloss:dual-simplex" class="glossar-link">Dual Simplex</a></td>
|
||||
<td><span class="math inline">(0{,}33;\ 0{,}33;\ 0)</span></td>
|
||||
<td>„Fräse und Schleiferei sind die Engpässe, die Prüfung ist wertlos.“</td>
|
||||
</tr>
|
||||
|
|
@ -1190,7 +1190,7 @@ Pruefung: komplementaerer Schlupf fuer alle Ressourcen erfuellt.
|
|||
<tr class="odd">
|
||||
<td><strong>Primale Zulässigkeit</strong></td>
|
||||
<td>Wie weit darf <span class="math inline">\mathbf{A}\mathbf{x}</span> die Schranke <span class="math inline">\mathbf{b}</span> überschreiten?</td>
|
||||
<td><span class="math inline">10^{-7}</span> (HiGHS), <span class="math inline">10^{-6}</span> (CP-SAT)</td>
|
||||
<td><span class="math inline">10^{-7}</span> (HiGHS), <span class="math inline">10^{-6}</span> (<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>)</td>
|
||||
</tr>
|
||||
<tr class="even">
|
||||
<td><strong>Duale Zulässigkeit</strong> (Optimalität)</td>
|
||||
|
|
@ -1534,7 +1534,7 @@ brauchbare Aussage. Ein erfundener Einzelwert ist es nicht.</code></pre>
|
|||
<p><strong>Aufgabe 5.1 ⭐ — Schlupf deuten.</strong> Ein LP liefert <span class="math inline">s = (0;\ 12{,}5;\ 0;\ 3)</span> und <span class="math inline">y = (4{,}2;\ 0;\ 9{,}8;\ 0)</span>. (a) Welche Ressourcen sind Engpässe? (b) Ist die Lösung mit dem Satz vom komplementären Schlupf verträglich? (c) In welche Ressource würden Sie zuerst investieren?</p>
|
||||
<p><strong>Aufgabe 5.2 ⭐ — Vorzeichen prüfen.</strong> Ein Kollege maximiert Gewinn mit <code>linprog</code> und meldet: „Der Schattenpreis der Engpassmaschine ist <span class="math inline">-45</span> €.“ Was ist passiert, und wie lautet der korrekte Wert?</p>
|
||||
<p><strong>Aufgabe 5.3 ⭐⭐ — Simplex von Hand.</strong> Lösen Sie mit dem Tableau-Verfahren vollständig von Hand: <span class="math display">\max\ 5x_1 + 4x_2 \quad \text{u. d. N.}\quad 6x_1+4x_2 \le 24,\quad x_1+2x_2 \le 6,\quad x_1,x_2\ge0</span> Geben Sie jedes Zwischentableau an und lesen Sie am Ende Lösung <strong>und</strong> Schattenpreise ab. Prüfen Sie mit <code>scipy.optimize.linprog</code>.</p>
|
||||
<p><strong>Aufgabe 5.4 ⭐⭐ — Duales Problem aufstellen.</strong> Stellen Sie zum Modell aus der Aufgabe <em>Simplex von Hand</em> das duale Problem auf, lösen Sie es mit <code>linprog</code> und weisen Sie den starken Dualitätssatz numerisch nach.</p>
|
||||
<p><strong>Aufgabe 5.4 ⭐⭐ — <a href="anhang-glossar.md#gloss:duales-problem" class="glossar-link">Duales Problem</a> aufstellen.</strong> Stellen Sie zum Modell aus der Aufgabe <em>Simplex von Hand</em> das duale Problem auf, lösen Sie es mit <code>linprog</code> und weisen Sie den starken Dualitätssatz numerisch nach.</p>
|
||||
<p><strong>Aufgabe 5.5 ⭐⭐ — Unbeschränktheit erkennen.</strong> Was liefert <code>SimplexTableauSolver</code> für <span class="math inline">\max x_1 + x_2</span> u. d. N. <span class="math inline">x_1 - x_2 \le 5</span>, <span class="math inline">x_1, x_2 \ge 0</span>? Erklären Sie die Fehlermeldung geometrisch.</p>
|
||||
<p><strong>Aufgabe 5.6 ⭐⭐⭐ — Gültigkeitsbereich des Schattenpreises.</strong> Erweitern Sie <code>Sensitivitaetsanalyse.py</code>: Lösen Sie das Modell für Prüfkapazitäten von 30 bis 120 Stunden (Schrittweite 5) und tragen Sie Gewinn und Schattenpreis gegen die Kapazität auf. (a) Ab welcher Kapazität fällt der Schattenpreis auf einen niedrigeren Wert? Warum? (b) Wie viele Stunden sollte der Betrieb bei einem Angebotspreis von 18 €/h <strong>maximal</strong> zukaufen? (c) Zeichnen Sie den Gewinnverlauf. Was für eine Kurvenform ergibt sich, und warum?</p>
|
||||
<p><strong>Aufgabe 5.7 ⭐⭐⭐ — Phase 1 ergänzen.</strong> Erweitern Sie den <code>SimplexTableauSolver</code> um eine Phase-1-Rechnung mit künstlichen Variablen, sodass auch <span class="math inline">b_i < 0</span> verarbeitet werden kann. Testen Sie an: <span class="math display">\max\ 3x_1+2x_2 \quad\text{u. d. N.}\quad x_1+x_2 \ge 4,\quad x_1+3x_2 \le 12,\quad x_1,x_2\ge0</span></p>
|
||||
|
|
@ -1594,7 +1594,7 @@ brauchbare Aussage. Ein erfundener Einzelwert ist es nicht.</code></pre>
|
|||
<li><strong>Schattenpreise</strong> beantworten die Managementfrage schlechthin: Wo ist der Engpass, und was ist seine Beseitigung wert?</li>
|
||||
<li><strong>Vorzeichen prüfen!</strong> Nach einer Negation der Zielfunktion müssen die Dualwerte zurücknegiert werden. Die numerische Gegenprobe („Kapazität um 1 erhöhen und neu lösen“) ist die sicherste Kontrolle.</li>
|
||||
</ul>
|
||||
<p><strong>Ausblick.</strong> <a href="milp.html#kap-milp">Kapitel 6</a> bricht mit der Annahme beliebiger Teilbarkeit: Was, wenn man nur ganze Maschinen kaufen kann? Wir werden sehen, dass Runden der LP-Lösung nicht nur ungenau, sondern grundsätzlich falsch ist — und lernen Branch-and-Bound kennen.</p>
|
||||
<p><strong>Ausblick.</strong> <a href="milp.html#kap-milp">Kapitel 6</a> bricht mit der Annahme beliebiger Teilbarkeit: Was, wenn man nur ganze Maschinen kaufen kann? Wir werden sehen, dass Runden der LP-Lösung nicht nur ungenau, sondern grundsätzlich falsch ist — und lernen <a href="anhang-glossar.md#gloss:branch-and-bound" class="glossar-link">Branch-and-Bound</a> kennen.</p>
|
||||
|
||||
</article>
|
||||
<button type="button" class="fortschritt-knopf" data-kapitel="lp.html"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg> <span>Als gelesen markieren</span></button>
|
||||
|
|
|
|||
Loading…
Reference in a new issue