Glossar: Sprungleiste, Abkürzungen ausschreiben, CLAUDE.md-Regel
Sprungleiste (A B C ... Z) im Glossar — wie im Stichwortverzeichnis:
ein Klick je Buchstabe springt zur '## <Buchstabe>'-Überschrift.
Eingebaut in erzeuge_glossar_04.py als {=html}-Rohblock (nur HTML,
im PDF bedeutungslos).
Abkürzungen beim ersten Mal ausschreiben: 'VaR' → 'VaR (Value at Risk)',
'EVPI' → 'EVPI (Expected Value of Perfect Information)' als Link-Text
bei der ersten Nennung je Datei; danach nur die Abkürzung. 19 Abkürzungen
erfasst (VaR, CVaR, KKT, NLP, MILP, EVPI, LP, QP, ...).
CLAUDE.md: Regel 'Glossar-Links: Fachbegriffe im Fließtext automatisch
verlinkt' dokumentiert — resolve_glossar(), LINK_TEXTE,
ABBREV_ERSTE_NENNUNG, _NICHT_AUTO_LINKEN, _ZU_KURZ_ABK, .glossar-link,
{gl:}-Marke, Sprungleiste, {#gloss:<slug>}-Anchor.
This commit is contained in:
parent
e8abb66d75
commit
0e2c011732
47 changed files with 545 additions and 561 deletions
8
OR_HTML_04/testing.html
generated
8
OR_HTML_04/testing.html
generated
|
|
@ -145,7 +145,7 @@
|
|||
AssertionError: Plan [31. 48.] braucht [141. 234.], verfuegbar sind [140. 232.]</code></pre>
|
||||
</blockquote>
|
||||
</div>
|
||||
<p><strong>Und jetzt der Punkt.</strong> Der Solver hat richtig gerechnet: 30,67 Tische und 48 Stühle sind das Optimum des <a href="anhang-glossar.md#gloss:lineare-programmierung-lp" class="glossar-link">LP</a>. Das Runden hat den Plan kaputt gemacht — 31 Tische brauchen eine Montagestunde mehr, als es gibt. Ohne die drei Zeilen wäre dieser Plan in die Fertigung gegangen, und dort hätte am Monatsende eine Stunde gefehlt, die niemand einer Zeile Python zugeordnet hätte.</p>
|
||||
<p><strong>Und jetzt der Punkt.</strong> Der Solver hat richtig gerechnet: 30,67 Tische und 48 Stühle sind das Optimum des <a href="anhang-glossar.md#gloss:lineare-programmierung-lp" class="glossar-link">LP (Lineare Programmierung)</a>. Das Runden hat den Plan kaputt gemacht — 31 Tische brauchen eine Montagestunde mehr, als es gibt. Ohne die drei Zeilen wäre dieser Plan in die Fertigung gegangen, und dort hätte am Monatsende eine Stunde gefehlt, die niemand einer Zeile Python zugeordnet hätte.</p>
|
||||
<p>Bemerkenswert ist, <strong>was</strong> der Test prüft. Er prüft nicht, ob 30,67 das Optimum ist — das könnte er gar nicht, dafür bräuchte er einen zweiten Solver. Er prüft die Eigenschaft, die jede brauchbare Lösung haben muss: <em>Sie hält die Kapazität ein.</em> Diese Verschiebung — <strong>von der Frage nach dem richtigen Wert zur Frage nach den notwendigen Eigenschaften</strong> — ist der Schlüssel zum ganzen Kapitel.</p>
|
||||
<blockquote>
|
||||
<p><strong>🎯 Merksatz</strong> Ein Optimierungsmodell lässt sich fast nie gegen den richtigen Wert testen. Gegen seine Eigenschaften lässt es sich immer testen.</p>
|
||||
|
|
@ -1131,7 +1131,7 @@ NICHT ablesen darf man:
|
|||
<p>Die zweite unbequeme Zahl steht ganz rechts: <strong><a href="anhang-glossar.md#gloss:cvxpy" class="glossar-link">CVXPY</a> braucht rund 240 MB</strong>, unabhängig von der Problemgröße — das ist der Preis seiner Modellierungsschicht. Auf einem Rechner mit knappem Speicher entscheidet diese Spalte und nicht die Laufzeit darüber, was überhaupt läuft.</p>
|
||||
<blockquote>
|
||||
<p><strong>⚠️ Was diese Tabelle nicht sagt</strong></p>
|
||||
<p>Sie sagt <strong>nicht</strong> „ortools ist langsamer als scipy”. Gemessen wurde <em>ein</em> Problemtyp in <em>einer</em> Formulierung auf <em>einer</em> Maschine. Ein <a href="anhang-glossar.md#gloss:gemischt-ganzzahlige-optimierung-milp" class="glossar-link">MILP</a> statt eines LP, eine andere Modellierung desselben Problems oder ein anderer Rechner können die Reihenfolge umdrehen — und bei MILPs tun sie es regelmäßig.</p>
|
||||
<p>Sie sagt <strong>nicht</strong> „ortools ist langsamer als scipy”. Gemessen wurde <em>ein</em> Problemtyp in <em>einer</em> Formulierung auf <em>einer</em> Maschine. Ein <a href="anhang-glossar.md#gloss:gemischt-ganzzahlige-optimierung-milp" class="glossar-link">MILP (Gemischt-ganzzahlige Optimierung)</a> statt eines LP, eine andere Modellierung desselben Problems oder ein anderer Rechner können die Reihenfolge umdrehen — und bei MILPs tun sie es regelmäßig.</p>
|
||||
<p>Übertragbar ist der <strong>Trend</strong>, nicht der Absolutwert: dass der Aufbauanteil mit der Größe wächst, dass CVXPY einen konstanten Speichersockel hat. Der Zweck des Programms ist, dass Sie es auf Ihrer Maschine mit Ihrem Problem laufen lassen.</p>
|
||||
</blockquote>
|
||||
<hr />
|
||||
|
|
@ -1561,11 +1561,11 @@ Das zugehoerige Dockerfile ist kurz genug, um es ganz zu zeigen:
|
|||
<blockquote>
|
||||
<p><strong>💻 Code-Durchgang: drei Entscheidungen</strong></p>
|
||||
<p><strong>1. Das Domänenmodell ist das API-Schema.</strong> Der <a href="anhang-glossar.md#gloss:parameter" class="glossar-link">Parameter</a> heißt <code>problem: Produktionsproblem</code> — mehr steht nicht da. FastAPI validiert die Anfrage damit gegen dieselben Pydantic-Regeln wie der Excel-Import aus <a href="einfuehrung.html#kap-einfuehrung">Kapitel 1</a> und antwortet bei Unsinn mit <code>422</code>, <strong>bevor</strong> ein Solver startet. Die drei abgewiesenen Anfragen im Selbsttest sind genau die drei Fälle, die <code>or_kern.py</code> schon beim Einlesen abfängt.</p>
|
||||
<p><strong>2. Die Antwort enthält Status und Gap, nicht nur Zahlen.</strong> Ein Aufrufer, der nur die Mengen bekommt, kann nicht unterscheiden, ob er ein bewiesenes Optimum oder einen Zeitlimit-Abbruch in der Hand hält. Das <code>Loesung</code>-Objekt geht deshalb vollständig durch die Schnittstelle — dasselbe <a href="anhang-glossar.md#gloss:dto-data-transfer-object" class="glossar-link">DTO</a>, das in <a href="praxisfallen.html#sec:praxisfallen-solverwechsel">Abschnitt 22.7</a> schon eine Prozessgrenze überlebt hat.</p>
|
||||
<p><strong>2. Die Antwort enthält Status und Gap, nicht nur Zahlen.</strong> Ein Aufrufer, der nur die Mengen bekommt, kann nicht unterscheiden, ob er ein bewiesenes Optimum oder einen Zeitlimit-Abbruch in der Hand hält. Das <code>Loesung</code>-Objekt geht deshalb vollständig durch die Schnittstelle — dasselbe <a href="anhang-glossar.md#gloss:dto-data-transfer-object" class="glossar-link">DTO (Data Transfer Object)</a>, das in <a href="praxisfallen.html#sec:praxisfallen-solverwechsel">Abschnitt 22.7</a> schon eine Prozessgrenze überlebt hat.</p>
|
||||
<p><strong>3. Die Abnahmeprüfung läuft auch hier.</strong> <code>pruefe_loesung()</code> steht im Arbeiter, nicht nur im Skript. Ein Dienst ohne sie liefert Fehler schneller aus, als ein Mensch sie finden könnte.</p>
|
||||
</blockquote>
|
||||
<h3 id="threads-oder-prozesse-eine-messung-keine-meinung">Threads oder Prozesse? Eine Messung, keine Meinung</h3>
|
||||
<p>Punkt 6 des Selbsttests misst, ob vier Solverläufe in Threads sich überlappen. Das Ergebnis ist ein Faktor von rund 3,5 bei vier Threads: <strong>OR-Tools rechnet in C++ und gibt den <a href="anhang-glossar.md#gloss:gil-global-interpreter-lock" class="glossar-link">GIL</a> während <code>Solve()</code> frei.</strong> Ein Threadpool genügt also, es braucht keine eigenen Prozesse.</p>
|
||||
<p>Punkt 6 des Selbsttests misst, ob vier Solverläufe in Threads sich überlappen. Das Ergebnis ist ein Faktor von rund 3,5 bei vier Threads: <strong>OR-Tools rechnet in C++ und gibt den <a href="anhang-glossar.md#gloss:gil-global-interpreter-lock" class="glossar-link">GIL (Global Interpreter Lock)</a> während <code>Solve()</code> frei.</strong> Ein Threadpool genügt also, es braucht keine eigenen Prozesse.</p>
|
||||
<p>Das gilt aber nicht allgemein. Eine in reinem Python geschriebene Heuristik (<a href="metaheuristiken.html#kap-metaheuristiken">Kapitel 9</a>) hält den GIL die ganze Zeit — für sie braucht derselbe Dienst einen <code>ProcessPoolExecutor</code>. Die Entscheidung gehört gemessen, nicht angenommen.</p>
|
||||
<blockquote>
|
||||
<p><strong>⚠️ Der erste Entwurf dieser Messung war falsch</strong></p>
|
||||
|
|
|
|||
Loading…
Reference in a new issue