Commit graph operations_research/Notebooks_04/praxisfallen.ipynb
Author SHA1 Message Date
dschlueter
99cb85907c Stichwortregister: automatische Markierung aller Glossarbegriffe (988 statt 456 Marker)
Neues Skript erzeuge_stichwortregister_04.py:
- Sucht alle Glossarbegriffe (Anzeigename) in den Kapiteldateien
  und markiert die erste Fundstelle je Datei mit {idx:Indexmarke}
- Termliste aus glossar_eintraege_04.py + vorhandenen {idx:...}-Markern
- Idempotent: erkennt vorhandene Marker und überspringt sie
- Überspringt Codeblöcke, Inline-Code und Math
- --check und --bericht Modi
- 605 Marker eingefügt (2 Durchläufe: 597 + 8)

Zusätzlich:
- titeltexte_04.py _saeubern(): entfernt {idx:...}-Marker vor
  Titeltext-Vergleich (pruefe_titeltexte schlug sonst fehl)
2026-09-10 00:07:01 +02:00
dschlueter
862e92bc7b Phase 8.2: Solver-Isolation ohne subprocess-Codestrings
Setzt den Isolationsteil von Paket 1 aus Verbesserungen_02.md um. Der Plan
nannte zwei Programme; beim Suchen kam ein drittes dazu, das dasselbe Muster
verwendete.

Ein_System_Vier_Ansaetze.py und Benchmark_Skalierung.py hielten ihre vier
Solvervarianten als Zeichenketten in einem Dictionary und gaben sie an
"python -c" weiter - bei Benchmark_Skalierung.py sogar mit
.format()-Platzhaltern fuer die Instanzgroesse. Aus jeder Variante ist jetzt
eine gewoehnliche Funktion mit lokalem Import geworden.
Solverwechsel_CPSAT_HiGHS.py rief sich selbst ueber sys.argv erneut auf;
auch das entfaellt.

Ausgefuehrt wird ueber einen ProcessPoolExecutor mit zwei Einstellungen, die
beide noetig sind: mp_context "spawn" (frischer Interpreter statt geerbtem
Speicher - unter Linux ist fork der Standard) und max_tasks_per_child=1 (ein
neuer Prozess je Aufgabe; ohne das verwendet der Pool seinen Arbeiter
wieder, und beim zweiten Solver ist der Konflikt zurueck). Nachgemessen:
vier Aufgaben, vier verschiedene PIDs.

Der zweite Punkt hat einen eigenen Warnkasten bekommen, weil der Fehler
leicht zu machen und schwer zu finden ist: Der Absturz kaeme nicht beim
ersten Solver, sondern beim zweiten - und saehe aus wie ein Problem des
zweiten.

Regel 4, dreifach geprueft. Ein_System_Vier_Ansaetze.py: identisch bis auf
die Zeitspalte, einschliesslich der Spannweite 2,41e-08, auf die sich der
Merksatz des Kapitels beruft. Benchmark_Skalierung.py: alle zwoelf
Zielwerte und alle drei Spannweiten bitgleich; Zeiten und Speicher haben
sich verschoben, beide sind im Abdruck seit jeher als hardwareabhaengig
gekennzeichnet. Solverwechsel_CPSAT_HiGHS.py: Ausgabe ohne Zeiten
unveraendert.

Bewusst subprocess bleibt Mutationstest.py: Dort wird pytest auf einer
mutierten Kopie in einem temporaeren Verzeichnis gestartet - ein externes
Werkzeug auf veraenderten Dateien, nicht die Isolation eines Imports.

Neu im Kapitel Oekosystem: ein Abschnitt "Wie die Isolation aussieht, wenn
sie tragen soll" - warum ein Codestring die schlechteste Umsetzung von
"eigener Prozess" ist. Anhang C nennt jetzt ebenfalls ProcessPoolExecutor.

Ein eigener Fehler, gefunden und abgesichert: Ich hatte dem neuen ### ein
{#sec:...}-Label gegeben. ABSCHNITT_RE erkennt nur "## " - das Label waere
nie registriert worden und jeder Verweis darauf ins Leere gelaufen, ohne
Warnung. Label entfernt, --check meldet den Fall jetzt. Gegengetestet.

Stand: 818 Querverweise, 76 Programme, 33 pytest-Tests, PDF 760 Seiten, 69
netzfreie Programme fehlerfrei.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-08 12:39:34 +02:00
dschlueter
dd4acda129 Phase 6.2: Constraint Attribution und Managementbericht
Neuer Abschnitt im Kapitel Praxisfallen plus Constraint_Attribution.py (75.
Programm). Setzt den fehlenden Teil von Paket 3 aus Verbesserungen_02.md um.

Die Luecke, die es schliesst: Erklaerbarkeit.py beantwortet "warum DIESE
Zuweisung?", Konfliktsuche.py "warum geht es GAR NICHT?". Der haeufigste Fall
der Praxis lag dazwischen und hatte kein Werkzeug - das Modell rechnet, der
Plan ist zulaessig, und trotzdem enttaeuschend, nur weiss niemand woran es
liegt.

Gerechnet wird auf derselben Fabrik wie die Konfliktsuche, nach der
Reparatur: Dort war die Lackierkapazitaet von 150 Stunden der Kern des
Widerspruchs (2*40 + 3*30 = 170 > 150), eine zweite Schicht bringt sie auf
210. Damit laesst sich dieselbe Instanz ueber zwei Kapitel verfolgen - erst
"warum nicht?", dann "was kostet was?".

Drei gemessene Befunde:

* Bindend heisst nicht teuer: Fuenf Bedingungen binden, "Lackierbudget
  Schicht 2" mit einem Schattenpreis von 0,00 EUR.
* Der Schattenpreis ist eine Momentaufnahme: Fuer die Lackiererei verspricht
  die Hochrechnung 4,00 * 30 = 120 EUR, gemessen kommen 60 EUR; der Preis
  gilt exakt bis +15 Stunden. Die Ranglisten drehen sich dabei um - nach
  Schattenpreis fuehrt der Traegervertrag (18 EUR/Stueck), nach
  tatsaechlicher Wirkung die Montage-Sonderschicht (450 EUR).
* Ein Wunsch kann unmoeglich statt teuer sein: "mindestens 55 Rahmen" ist
  INFEASIBLE, blockiert von drei Bedingungen gemeinsam. Mit +15 Stunden
  Lackierkapazitaet wird er erfuellbar und kostet dann nichts - der Plan
  waehlt diese Menge von sich aus. Der Konflikt bestand nie zwischen
  Vertrieb und Produktion.

Der Managementbericht entsteht aus genau diesen Zahlen; kein Satz enthaelt
eine Zahl, die nicht vorher gerechnet wurde. Voraussetzung ist der
sprechende Name jeder Bedingung - aus A_ub[7] wird kein Satz.

Dazu die Grenze, als Warnkasten und als Uebungsaufgabe: Der Bericht erklaert
das Modell, nicht die Wirklichkeit. Steigt der Deckungsbeitrag von Deckel
von 9 auf 20 EUR, kippt der Plan (Rahmen auf das Vertragsminimum 40, Deckel
auf die Marktgrenze 120), "Kapazitaet Lackieren" hoert auf zu binden,
"Liefervertrag Rahmen" faengt damit an - und der Satz "Teuerste Bindung ist
Liefervertrag Traeger" steht woertlich unveraendert im Bericht, waehrend die
Zahl dahinter von 18 auf 58 EUR springt.

Die Zaehlprobe aus 6.1a hat sich sofort bewaehrt: Nach dem Einbau der
Uebungsaufgabe meldete --check "6 Loesungen, das Kapitel aber 7 Aufgaben",
bevor die Loesung geschrieben war.

Mitgezogen: Kapitelkopf, Lernziele, Selbsttest, Zusammenfassung,
Vorwort-Programmverzeichnis, Vorwaertsverweis aus Falle 2, Uebungsaufgabe
und Loesung in Anhang A.

Stand: 294 Abschnitte, 725 Querverweise, 328 Indexmarken, 75 Programme,
139 Aufgaben mit 139 Loesungen, 33 pytest-Tests, PDF 737 Seiten, 68
netzfreie Programme fehlerfrei.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-08 10:30:33 +02:00
dschlueter
b7af2f1d9a Version 04 als eigenes Repository
Erster Commit des Strangs "Optimierte Entscheidungsfindung mit Python"
(Version 04). Die Historie der 71 Commits bis zur Trennung bleibt im
uebergeordneten Repository OR_mit_Python liegen, das ab jetzt nur noch
Version_03 (eingefroren) verwaltet und Version_04/ ignoriert.

Bewusst kein "git subtree split": Der Pfad Version_04/ existiert erst seit
der Verzeichnistrennung, ein Split braechte daher nur 7 der 41 einschlaegigen
Commits - eine Teilhistorie, die vollstaendig aussieht und es nicht ist.

Stand: 5 Teile, 23 Kapitel, 5 Anhaenge, 292 Abschnitte, 703 Querverweise,
325 Indexmarken, 73 Beispielprogramme, 32 SVGs, 4 Plotly-Figuren,
25 Notebooks, PDF mit 715 Seiten.

Zusaetzlich in diesem Commit:

* pyproject.toml mit Abhaengigkeitsgruppen finance, large-scale, api,
  figures, dev, empfehlungen. Die abgedruckte requirements.txt bleibt
  unveraendert daneben bestehen. ortools steht in der Grundausstattung,
  highspy erst in [large-scale] - so kann der HiGHS-Symbolkonflikt bei der
  schlanken Installation gar nicht erst auftreten.

* Dabei zwei Funde: graphviz wird von erzeuge_architektur_diagramme.py
  importiert, fehlt aber in requirements.txt (jetzt in [figures]); pymoo
  steht in requirements.txt, wird aber von keinem Programm importiert,
  sondern nur im Kapitel Metaheuristiken empfohlen (jetzt in
  [empfehlungen]).

* NEUER_TITEL.md nach Kritik_und_Verbesserungsvorschlaege/ verschoben - es
  ist die Vorlage des Titelblatts, kein Bestandteil des Werks. Die beiden
  Fundstellen in PROGRESS.md und erzeuge_titelseite.py nachgezogen.

* PROGRESS.md nannte noch den Untertitel der ersten Fassung; auf den
  tatsaechlichen aus erzeuge_titelseite.py korrigiert.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-08 01:20:09 +02:00