Phase 6.1: Chance Constraints - die Zusage "mit 95 % Sicherheit"
Neuer Abschnitt im Kapitel Unsicherheit plus Chance_Constraints.py (74. Programm). Das Kapitel hatte Monte-Carlo, Zweistufigkeit und Worst-Case-Robustheit; die Wahrscheinlichkeitszusage war die fehlende vierte Antwort - und die, nach der das Management tatsaechlich fragt. Setzt Paket 4 aus Verbesserungen_02.md um. Beide Wege an DERSELBEN Instanz (Kraftwerkspark, 500 MW gesicherte Zusage): analytisch als Second-Order-Cone-Bedingung (CLARABEL) und szenariobasiert als Big-M-MILP (SciPy/HiGHS) - beides in einem Prozess, ohne ortools- oder highspy-Import. Drei gemessene Befunde: * Der Mittelwertplan haelt 50,08 %. Kein Fehler, sondern die Definition des Erwartungswerts. * Sicherheit ist konvex bepreist: 56.289 EUR je Prozentpunkt auf dem Weg zu 80 %, 253.848 EUR zwischen 95 und 99 % - das 4,5-fache. Das Programm rechnet die Tabelle selbst aus, statt sie zu behaupten. * Die Zusage gilt nur fuer die unterstellte Verteilung: Der 95-%-Plan haelt gemessen 87,44 %, sobald die Testverteilung eine Kaeltewelle mit Dunkelflaute enthaelt, in der alles zugleich einbricht - auch das Gaskraftwerk. In einer reinen Normalwelt liefert derselbe Plan 94,97 %. Zwei eigene Fehlgriffe, beide durch Messen aufgefallen und korrigiert: Die erste Kostentarierung ergab eine entartete Loesung (alles ins Gaskraftwerk), womit die Kovarianzmatrix wirkungslos war - und gerade sie begruendet die Kegelform. Und der erste Kaelteeinbruch traf nur Wind und Sonne; der SOC-Plan hatte die ohnehin herausgehalten und war zufaellig robust, das Argument trug nicht. Ehrlich berichtet statt geglaettet: Die Szenariomethode ueberanpasst. Ueber zwoelf Laeufe (S = 200, 400, 800) lag die tatsaechliche Quote zwischen 93,14 % und 96,71 %, und die Spanne wurde von S = 400 auf 800 wieder breiter. Beide Solver bestaetigen optimal bei identischen Kosten - echte Ueberanpassung, kein Solverartefakt. Steht als Warnkasten im Abschnitt. Die Laufzeitmessung ist aus der Ausgabe entfernt: Eine Wanduhrzeit ist nie byteidentisch reproduzierbar (2,2 s / 2,3 s zwischen zwei Laeufen) und haette Regel 4 dauerhaft gebrochen. Danach drei Laeufe zeichengleich, und die abgedruckte Ausgabe stimmt mit dem Lauf des extrahierten Programms ueberein. Mitgezogen: Kapitelkopf, Lernziele, Uebersichtstabelle (drei -> vier Ansaetze), Selbsttest, Zusammenfassung, Vorwort-Programmverzeichnis, eine neue Uebungsaufgabe und ihre Loesung in Anhang A. pyproject.toml korrigiert: cvxpy lag in [finance], wird aber von 13 Programmen gebraucht, darunter dreien in diesem Kapitel - jetzt in der Grundausstattung. Es zieht kein highspy nach, der Solverkonflikt bleibt auf [large-scale] beschraenkt. Stand: 293 Abschnitte, 712 Querverweise, 327 Indexmarken, 74 Programme (0 Fehler), 33 pytest-Tests, PDF 725 Seiten. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
62952ba066
commit
6c67e126dd
23 changed files with 9089 additions and 6419 deletions
139
PROGRESS.md
139
PROGRESS.md
|
|
@ -77,14 +77,14 @@ sie unerwartet ab, ist etwas kaputtgegangen.
|
|||
| Kapiteldateien | 22 | **31** |
|
||||
| Kapitel | 15 | **23** |
|
||||
| Anhänge | 4 | **5** |
|
||||
| Zeilen im Gesamtdokument | 11 082 | **27 015** |
|
||||
| Größe des Gesamtdokuments | 606 KB | **1 512 KB** |
|
||||
| Hauptüberschriften | 131 | **276** |
|
||||
| registrierte Abschnitte | 122 | **292** |
|
||||
| aufgelöste Querverweise | 314 | **706** (0 unaufgelöst) |
|
||||
| Indexmarken | 295 | **325** |
|
||||
| Beispielprogramme | 41 | **73** (alle lauffähig) |
|
||||
| PDF-Seiten | — | **715** |
|
||||
| Zeilen im Gesamtdokument | 11 082 | **27 400** |
|
||||
| Größe des Gesamtdokuments | 606 KB | **1 536 KB** |
|
||||
| Hauptüberschriften | 131 | **289** |
|
||||
| registrierte Abschnitte | 122 | **293** |
|
||||
| aufgelöste Querverweise | 314 | **712** (0 unaufgelöst) |
|
||||
| Indexmarken | 295 | **327** |
|
||||
| Beispielprogramme | 41 | **74** (alle lauffähig) |
|
||||
| PDF-Seiten | — | **725** |
|
||||
| Notebooks | — | **25** |
|
||||
| Plotly-Figuren | — | **4** |
|
||||
| Diagramme (SVG) | 26 | **32**, davon **18** mit Generatorskript (15 Skripte) |
|
||||
|
|
@ -1329,18 +1329,25 @@ pytest-Tests grün, Version 03 unberührt.
|
|||
|
||||
### Der konkret nächste Handgriff
|
||||
|
||||
**Alle sechs Phasen sind abgeschlossen, und Version 04 liegt getrennt in `Version_04/`.**
|
||||
23 Kapitel, 5 Anhänge, 73 lauffähige Programme, 715 PDF-Seiten, Website mit vier
|
||||
interaktiven Figuren.
|
||||
**Alle sechs Phasen sind abgeschlossen. Seit dem 08.09.2026 ist `Version_04/` ein eigenes
|
||||
Git-Repository**, und Phase 6 (Umsetzung von `Verbesserungen_02/_03`) hat begonnen.
|
||||
23 Kapitel, 5 Anhänge, 74 lauffähige Programme, Website mit vier interaktiven Figuren.
|
||||
|
||||
Offen ist nur noch, was von außen kommt:
|
||||
**Zum eigenen Repository — eine Korrektur der früheren Angabe hier:** `git subtree split -P
|
||||
Version_04` hätte die Historie **nicht** mitgenommen. Der Pfad `Version_04/` existiert erst
|
||||
seit der Verzeichnistrennung; der Split hätte 7 statt 41 einschlägiger Commits gebracht — eine
|
||||
Teilhistorie, die vollständig aussieht und es nicht ist. Volle Historie ginge nur über
|
||||
`git-filter-repo` (nicht installiert). Deshalb: frischer `git init -b main`, das
|
||||
übergeordnete Repository bleibt das Archiv der 71 Commits und trägt `Version_04/` in seiner
|
||||
`.gitignore`.
|
||||
|
||||
Offen ist weiterhin, was von außen kommt:
|
||||
|
||||
* **Veröffentlichen.** `Version_04/OR_HTML_04/` ist selbstgenügsam und direkt auf einen
|
||||
Webserver kopierbar.
|
||||
* **Eigenes Repository.** `git subtree split -P Version_04 -b v04-only` nimmt die Historie
|
||||
mit. Danach **`COLAB_BASIS_URL`** in `build_version_04.py` auf Kontoname und
|
||||
Repository-Name setzen — die 25 Colab-Badges hängen daran, und ein falscher Wert fällt
|
||||
erst beim Klicken auf.
|
||||
* **Remote-Repository anlegen.** Danach **`COLAB_BASIS_URL`** in `build_version_04.py` auf
|
||||
Kontoname und Repository-Name setzen — die 25 Colab-Badges hängen daran, und ein falscher
|
||||
Wert fällt erst beim Klicken auf.
|
||||
|
||||
Was einer späteren Sitzung als Erstes auffallen wird und **kein Fehler** ist:
|
||||
|
||||
|
|
@ -1363,6 +1370,106 @@ Was einer späteren Sitzung als Erstes auffallen wird und **kein Fehler** ist:
|
|||
|
||||
---
|
||||
|
||||
## 6d. Phase 6 — Umsetzung von `Verbesserungen_02` / `_03` 🔄
|
||||
|
||||
Grundlage: `Kritik_und_Verbesserungsvorschlaege/Verbesserungen_02.md` und `_03.md`, zwölf
|
||||
Arbeitspakete. Nach Ertrag geordnet umgesetzt; **Streamlit-Apps sind auf Wunsch des Autors
|
||||
zurückgestellt**, ebenso Folium-Karten (die VRP-Instanz ist ein synthetisches Raster ohne
|
||||
Geokoordinaten) und Zielgruppen-Callouts in allen Kapiteln.
|
||||
|
||||
### ✅ Repository und `pyproject.toml`
|
||||
|
||||
`git init -b main` in `Version_04`, `Version_04` im übergeordneten Repository ausgetragen.
|
||||
Neu: `pyproject.toml` mit den Gruppen `finance`, `large-scale`, `api`, `figures`, `dev`,
|
||||
`empfehlungen` — die abgedruckte `requirements.txt` bleibt unverändert daneben bestehen.
|
||||
|
||||
**`ortools` steht in der Grundausstattung, `highspy` erst in `[large-scale]`.** Damit kann
|
||||
der HiGHS-Symbolkonflikt bei der schlanken Installation gar nicht erst auftreten; `cvxpy`
|
||||
zieht `highspy` nicht nach.
|
||||
|
||||
Zwei Funde beim Abgleich der Importe gegen `requirements.txt`:
|
||||
|
||||
* **`graphviz` fehlte** — `bilder_04/erzeuge_architektur_diagramme.py` importiert es, die
|
||||
Leserliste kennt es nicht. Es gehört nicht in die abgedruckte Datei (kein
|
||||
Beispielprogramm braucht es), steht jetzt aber in `[figures]`.
|
||||
* **`pymoo` steht in `requirements.txt`, wird aber von keinem der 74 Programme importiert** —
|
||||
es ist nur eine Empfehlung im Kapitel Metaheuristiken. Jetzt in `[empfehlungen]`.
|
||||
|
||||
Später korrigiert: **`cvxpy` lag zuerst in `[finance]`** — falsch, es wird von 13 Programmen
|
||||
gebraucht, darunter dreien im Kapitel Unsicherheit, lange vor dem Finanzteil. Jetzt in der
|
||||
Grundausstattung.
|
||||
|
||||
### ✅ 6.1 Chance Constraints ({ref:kap:unsicherheit})
|
||||
|
||||
Neuer Abschnitt {ref:sec:unsicherheit-chance-constraints} plus `Chance_Constraints.py`
|
||||
(74. Programm). Das Kapitel hatte Monte-Carlo, Zweistufigkeit und Worst-Case-Robustheit; die
|
||||
Wahrscheinlichkeitszusage war die fehlende vierte Antwort — und die, nach der das Management
|
||||
tatsächlich fragt. Beide Wege an **derselben** Instanz: analytisch als
|
||||
Second-Order-Cone-Bedingung (CLARABEL) und szenariobasiert als Big-M-MILP (SciPy/HiGHS),
|
||||
beide in einem Prozess ohne `ortools`- oder `highspy`-Import.
|
||||
|
||||
Der Fall ist ein Kraftwerkspark mit 500 MW Zusage. **Drei Befunde, alle gemessen:**
|
||||
|
||||
1. **Der Mittelwertplan hält 50,08 %.** Kein Fehler, sondern die Definition des
|
||||
Erwartungswerts — dieselbe Falle wie im Kapitelanfang, nur teurer.
|
||||
2. **Sicherheit ist konvex bepreist.** 56 289 € je Prozentpunkt auf dem Weg zu 80 %,
|
||||
253 848 € zwischen 95 % und 99 % — das **4,5-fache**. Das Programm rechnet die Tabelle
|
||||
selbst aus, statt sie zu behaupten.
|
||||
3. **Die Zusage gilt nur für die unterstellte Verteilung.** Der 95-%-Plan hält gemessen
|
||||
**87,44 %**, sobald die Testverteilung eine Kältewelle mit Dunkelflaute enthält, in der
|
||||
*alles zugleich* einbricht — auch das Gaskraftwerk. In einer reinen Normalwelt liefert
|
||||
derselbe Plan 94,97 %. Nicht das Verfahren ist falsch, sondern die Annahme.
|
||||
|
||||
**Zwei eigene Fehlgriffe unterwegs, beide durch Messen aufgefallen:**
|
||||
|
||||
* Die erste Kostentarierung ergab eine **entartete Lösung** (alles ins Gaskraftwerk), womit
|
||||
die Kovarianzmatrix wirkungslos war — und gerade sie ist der Grund für die Kegelform. Erst
|
||||
Kosten, die je *erwarteter* MW vergleichbar sind, machen den Konflikt echt.
|
||||
* Der erste Kälteeinbruch traf nur Wind und Sonne. Der SOC-Plan hatte die aber ohnehin fast
|
||||
herausgehalten und war zufällig robust (94,40 %) — das Argument trug nicht. Physikalisch
|
||||
richtig ist, dass bei Frost auch der Gasdruck fällt; damit trifft der Einbruch alles
|
||||
zugleich, und genau das kann eine Kovarianzmatrix mit Korrelationen um null nicht
|
||||
ausdrücken.
|
||||
|
||||
**Ehrlich berichtet statt geglättet:** Die Szenariomethode **überanpasst**. Über zwölf Läufe
|
||||
(je vier Ziehungen bei S = 200, 400, 800, geprüft an 200 000 unabhängigen Szenarien) lag die
|
||||
tatsächliche Quote zwischen **93,14 % und 96,71 %**, und die Spanne wurde von S = 400 auf
|
||||
S = 800 wieder **breiter**. Beide Solver (SciPy und HiGHS) bestätigten `optimal` bei
|
||||
identischen Kosten — es ist echte Überanpassung, kein Solverartefakt. Steht als
|
||||
⚠️-Kasten im Abschnitt.
|
||||
|
||||
**Aus der Ausgabe entfernt: die Laufzeitmessung.** Eine Wanduhrzeit ist nie byteidentisch
|
||||
reproduzierbar (2,2 s / 2,3 s zwischen zwei Läufen) und hätte Regel 4 dauerhaft gebrochen.
|
||||
Die Beobachtung steht jetzt im Fließtext, wo eine Spanne ehrlich ist. Danach: drei Läufe
|
||||
zeichengleich, und die abgedruckte Ausgabe stimmt mit dem Lauf des **extrahierten**
|
||||
Programms überein.
|
||||
|
||||
Eine Aufgabenprämisse musste ich verwerfen: „Ab welcher Zusage wird das Modell unlösbar?“ —
|
||||
das analytische Modell bleibt bis praktisch 100 % lösbar. Die Aufgabe fragt jetzt nach dem
|
||||
Fall mit gedrosselter Biomasse, in dem das **szenariobasierte** Modell `infeasible` meldet
|
||||
(7,50 % der Szenarien deckt selbst der Vollausbau nicht), das analytische aber `optimal`
|
||||
liefert — und dann 87,39 % hält.
|
||||
|
||||
### ⏳ Offen: die Lösungsnummern in Anhang A — **sechste** harte Nummer
|
||||
|
||||
**Gefunden, noch nicht behoben.** Der Lösungsanhang trägt **97** feste Marken der Bauart
|
||||
`**9.2 — Ansatz wählen.**`. Sie stammen aus Version 03, wo Unsicherheit Kapitel 9 war. Heute
|
||||
ist es Kapitel 12, und die Aufgabe selbst wird korrekt als **„Aufgabe 12.2"** gesetzt.
|
||||
|
||||
Das ist keine Schönheitsfrage: **„Aufgabe 9.2" existiert heute wirklich** — sie gehört zum
|
||||
Kapitel Metaheuristiken („Zuggröße und Temperatur"). Wer die Lösung zu 9.2 sucht, landet
|
||||
beim falschen Thema.
|
||||
|
||||
Beide Prüfungen laufen daran vorbei: Vor der Zahl steht kein Schlüsselwort, und es ist keine
|
||||
Tabellenzelle.
|
||||
|
||||
**Vorschlag zur Behebung** (eigenes Arbeitspaket, rührt an 97 Stellen plus Build):
|
||||
Die Zuordnung ist herleitbar — der Abschnitt `{#sec:loesungen-<X>}` gehört zum Kapitel
|
||||
`{#kap:<X>}`. Der Build kann die Marken also selbst vergeben, so wie er es für Aufgaben
|
||||
bereits tut; im Quelltext bliebe nur noch der Titel stehen.
|
||||
|
||||
---
|
||||
|
||||
## 8. Commit-Historie des V04-Strangs
|
||||
|
||||
> **Zu den Kapitelnummern in dieser Tabelle:** Sie stammen aus den Commit-Betreffs und geben
|
||||
|
|
|
|||
Loading…
Reference in a new issue