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:
dschlueter 2026-09-10 17:40:29 +02:00
commit e8abb66d75
52 changed files with 4316 additions and 1921 deletions

View file

@ -103,7 +103,7 @@
<div class="card card-blick">
<blockquote>
<p><strong>📌 Kapitel auf einen Blick</strong></p>
<p><strong>Worum geht es?</strong> Um die andere Antwort auf die Frage aus <a href="metaheuristiken.html#kap-metaheuristiken">Kapitel 9</a>: Was tun, wenn der Solver an der Größe scheitert? Statt die Lösung zu approximieren, formuliert man das Modell so um, dass exaktes Lösen wieder möglich wird.</p>
<p><strong>Worum geht es?</strong> Um die andere Antwort auf die Frage aus <a href="metaheuristiken.html#kap-metaheuristiken">Kapitel 9</a>: Was tun, wenn der <a href="anhang-glossar.md#gloss:solver" class="glossar-link">Solver</a> an der Größe scheitert? Statt die Lösung zu approximieren, formuliert man das Modell so um, dass exaktes Lösen wieder möglich wird.</p>
<p><strong>Voraussetzungen:</strong> <a href="lp.html#sec:lp-dualitaet-und-schattenpreise">Abschnitt 5.6</a> (Dualwerte) und <a href="milp.html#kap-milp">Kapitel 6</a> (<code>Rucksack.py</code>). Beides wird gebraucht, aber nicht neu erklärt.</p>
<p><strong>Danach können Sie:</strong> ein Problem in Master und Teilproblem zerlegen; die Spaltengenerierungsschleife selbst schreiben; und begründen, wann sich der Aufwand lohnt — die Antwort hängt an einer einzigen Kennzahl der Instanz.</p>
<p><strong>Zeitbedarf:</strong> ca. 3 Stunden.</p>
@ -121,7 +121,7 @@
<p>Die naheliegende Frage — <em>„welches Stück kommt auf welche Rolle?“</em> — führt zu 35 Einzelentscheidungen. Die bessere Frage lautet: <em>„Wie oft schneide ich welches Muster?“</em></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">import</span> itertools</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> numpy <span class="im">as</span> np</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="im">from</span> scipy.optimize <span class="im">import</span> linprog</span>
<span id="cb1-3"><a href="#cb1-3" 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-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>ROLLE <span class="op">=</span> <span class="dv">1000</span> <span class="co"># mm Mutterrolle</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>breiten, bedarf <span class="op">=</span> [<span class="dv">420</span>, <span class="dv">310</span>, <span class="dv">250</span>], [<span class="dv">9</span>, <span class="dv">12</span>, <span class="dv">14</span>]</span>
@ -151,7 +151,7 @@
<p><strong>Und jetzt der Punkt.</strong> Sehen Sie sich an, was da herauskommt: <strong>drei Schnittmuster</strong>. Kein Zuordnungsplan für 35 Stücke, sondern eine Anweisung, die an der Maschine hängen kann — neunmal dieses Muster, zweimal jenes, einmal das dritte.</p>
<p>Das ist kein kosmetischer Unterschied. Das Modell hat <strong>eine Variable je Muster</strong> statt einer je Stück-und-Rolle, und es kennt gar keine einzelnen Rollen mehr. Damit verschwindet ein Problem, das das naheliegende Modell praktisch unlösbar macht — dazu gleich mehr.</p>
<blockquote>
<p><strong>🎯 Merksatz</strong> Die schwierigste Arbeit an einem Optimierungsmodell ist selten die Zielfunktion. Es ist die Frage, <strong>worüber</strong> die Variablen laufen.</p>
<p><strong>🎯 Merksatz</strong> Die schwierigste Arbeit an einem Optimierungsmodell ist selten die <a href="anhang-glossar.md#gloss:zielfunktion" class="glossar-link">Zielfunktion</a>. Es ist die Frage, <strong>worüber</strong> die Variablen laufen.</p>
</blockquote>
<p><strong>Warum funktioniert das?</strong> Weil hier alle 16 möglichen Muster aufzählbar waren. Bei drei Breiten und einer 1 000-mm-Rolle sind es 16; bei dreizehn Breiten und 5 600 mm sind es zehntausende, und bei einer echten Papierfabrik mehr, als sich speichern lässt. Das ganze Kapitel handelt davon, wie man mit Mustern rechnet, ohne sie aufzuschreiben.</p>
<hr />
@ -160,7 +160,7 @@
<ol type="1">
<li>… erklären, warum das naheliegende Zuordnungsmodell an <strong>Symmetrie</strong> scheitert.</li>
<li>… ein Problem in <strong>Master</strong> und <strong>Pricing-Teilproblem</strong> zerlegen.</li>
<li>… die Schleife schreiben: Master-LP lösen, Dualwerte auslesen, Teilproblem lösen, Spalte hinzufügen.</li>
<li>… die Schleife schreiben: Master-<a href="anhang-glossar.md#gloss:lineare-programmierung-lp" class="glossar-link">LP</a> lösen, Dualwerte auslesen, Teilproblem lösen, Spalte hinzufügen.</li>
<li>… das Abbruchkriterium über die <strong>reduzierten Kosten</strong> begründen.</li>
<li>… an einer Kennzahl der Instanz abschätzen, ob sich das Verfahren lohnt.</li>
</ol>
@ -169,7 +169,7 @@
<p>Der erste Entwurf eines Zuschnittmodells sieht fast immer so aus: eine Binärvariable <span class="math inline">z_{jr}</span> für „Stück <span class="math inline">j</span> liegt auf Rolle <span class="math inline">r</span>“, dazu <span class="math inline">y_r</span> für „Rolle <span class="math inline">r</span> wird benutzt”.</p>
<p>Zwei Dinge gehen dabei schief.</p>
<p><strong>Die Größe.</strong> Bei 219 Zuschnitten und höchstens 82 Rollen sind das knapp 18 000 Binärvariablen — unangenehm, aber allein noch kein Hindernis.</p>
<p><strong>Die Symmetrie.</strong> Das ist das eigentliche Problem. Alle Mutterrollen sind <strong>gleich</strong>. Jede Lösung existiert deshalb in unzähligen Umbenennungen: Vertauscht man Rolle 3 und Rolle 47, entsteht eine formal andere, inhaltlich identische Lösung. Branch-and-Bound weiß das nicht und arbeitet sie einzeln ab.</p>
<p><strong>Die Symmetrie.</strong> Das ist das eigentliche Problem. Alle Mutterrollen sind <strong>gleich</strong>. Jede Lösung existiert deshalb in unzähligen Umbenennungen: Vertauscht man Rolle 3 und Rolle 47, entsteht eine formal andere, inhaltlich identische Lösung. <a href="anhang-glossar.md#gloss:branch-and-bound" class="glossar-link">Branch-and-Bound</a> weiß das nicht und arbeitet sie einzeln ab.</p>
<blockquote>
<p><strong>⚠️ Woran man ein Symmetrieproblem erkennt</strong></p>
<p>Der Suchbaum wächst, aber die <strong>Schranke bewegt sich nicht.</strong> Im Protokoll aus <a href="milp.html#sec:milp-gap">Abschnitt 6.8</a> sieht das so aus: Die Zahl der Knoten steigt in die Hunderttausende, der Incumbent verbessert sich hin und wieder, und der Dual Bound steht praktisch still.</p>
@ -229,7 +229,7 @@
<blockquote>
<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="lp.html#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>
<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 <a href="anhang-glossar.md#gloss:schattenpreis" class="glossar-link">Schattenpreis</a> aus <a href="lp.html#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>
@ -277,7 +277,7 @@
<p>Die letzte Zeile ist der Grund, warum das Verfahren <strong>exakt</strong> ist und nicht heuristisch: Wenn kein Muster mehr lohnende reduzierte Kosten hat, ist die LP-Lösung über <em>allen</em> Mustern optimal — auch über den nie erzeugten.</p>
</blockquote>
</div>
<p><strong>Und wie findet man das beste neue Muster?</strong> Man sucht die Zusammenstellung von Stücken mit dem größten Gesamtwert, die noch in die Rolle passt. Das ist ein <strong>Rucksackproblem</strong>:</p>
<p><strong>Und wie findet man das beste neue Muster?</strong> Man sucht die Zusammenstellung von Stücken mit dem größten Gesamtwert, die noch in die Rolle passt. Das ist ein <strong><a href="anhang-glossar.md#gloss:rucksackproblem" class="glossar-link">Rucksackproblem</a></strong>:</p>
<table>
<thead>
<tr class="header">
@ -811,7 +811,7 @@ Mutterrolle 5,600 mm, 13 bestellte Breiten, 219 Zuschnitte.
<hr />
<h2 id="sec:dekomposition-selbsttest">10.10 Selbsttest</h2>
<ol type="1">
<li>Erklären Sie Symmetrie in einem MILP an einem Beispiel aus Ihrem Arbeitsumfeld.</li>
<li>Erklären Sie Symmetrie in einem <a href="anhang-glossar.md#gloss:gemischt-ganzzahlige-optimierung-milp" class="glossar-link">MILP</a> an einem Beispiel aus Ihrem Arbeitsumfeld.</li>
<li>Was ist beim Zuschnitt eine „Spalte”, und was steht darin?</li>
<li>Woher kommen die Preise, mit denen das Teilproblem rechnet?</li>
<li>Warum ist das Verfahren exakt, obwohl es fast alle Muster nie ansieht?</li>