kleine Änderungen
This commit is contained in:
parent
0f9c815b86
commit
dc088fa214
47 changed files with 183868 additions and 573 deletions
55
Operations_Research_mit_Python_Version_04.md
generated
55
Operations_Research_mit_Python_Version_04.md
generated
|
|
@ -2104,6 +2104,11 @@ $$
|
|||
|
||||
> **🎯 Merksatz** Konvex heißt: Wer bergab geht, kommt am tiefsten Punkt an. Nicht-konvex heißt: Wer bergab geht, kommt *irgendwo* an — und weiß nicht, ob es der tiefste Punkt war.
|
||||
|
||||

|
||||
|
||||
**Was Sie in der Abbildung sehen.** Links sind es fünf Läufe desselben Verfahrens, die in vier verschiedenen Tälern enden — dieselben vier, die Teil 2 von `Konvexitaet_Demo.py` weiter unten auflistet. In zwei Dimensionen werden aus den Tälern Mulden in einem Gitter, und der Unterschied zwischen Start A und Start B beträgt hier bereits mehr als 24 Einheiten. Keiner der beiden Läufe hat etwas falsch gemacht: Beide enden dort, wo es nicht mehr bergab geht.
|
||||
|
||||
### Was ist konvex, was nicht?
|
||||
|
||||
| Problemtyp | Konvex? | Konsequenz |
|
||||
|
|
@ -2423,7 +2428,7 @@ Bis hierher war die lineare Algebra exakt. Ein Rechner rechnet aber nicht exakt,
|
|||
|
||||
> **Wenn meine Eingabedaten leicht ungenau sind — wie ungenau ist dann meine Lösung?**
|
||||
|
||||

|
||||
|
||||
Die Antwort trägt einen Namen: die **Konditionszahl**`\index{Konditionszahl}`{=latex} $\kappa(\mathbf{A})$. Sie ist der wichtigste Begriff dieses Kapitels für den Produktivbetrieb, weil er erklärt, warum ein mathematisch korrektes Modell trotzdem unbrauchbare Ergebnisse liefern kann — oder sich mit einem sachlich falschen `INFEASIBLE` verabschiedet.
|
||||
|
|
@ -4873,7 +4878,9 @@ $$
|
|||
Der von George `\index{Dantzig, George}`{=latex}Dantzig 1947 formulierte `\index{Simplex-Algorithmus}`{=latex}Simplex-Algorithmus nutzt den Fundamentalsatz aus [Kapitel 2](#kap-fundament): **Das Optimum liegt in einer Ecke.** Statt alle Ecken aufzuzählen, wandert er von Ecke zu Ecke — und zwar immer in Richtung Verbesserung.
|
||||
|
||||

|
||||
(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`.](bilder_04/kap_lp_simplex_ecken.svg)
|
||||
|
||||
**Was Sie in der Abbildung sehen.** 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.
|
||||
|
||||
### Der Ablauf
|
||||
|
||||
|
|
@ -5187,6 +5194,11 @@ Zu **jedem** linearen Optimierungsproblem (dem **primalen Problem**`\index{Prima
|
|||
|
||||
Prüfen wir das an unserem Beispiel: $\mathbf{b}^\top\mathbf{y}^* = 40 \cdot 12{,}5 + 60 \cdot 31{,}25 + 8 \cdot 0 = 500 + 1875 + 0 = 2375$ ✓ — identisch mit $Z^* = 2375$.
|
||||
|
||||

|
||||
|
||||
**Was Sie in der Abbildung sehen.** Die beiden Tafeln haben nichts gemeinsam: verschiedene Achsen, verschiedene Einheiten, links ein geschlossenes Polyeder, rechts ein nach oben offener Bereich. Links wird maximiert, rechts minimiert. Und doch steht an beiden Optima dieselbe Zahl — 2.375 €. Genau das behauptet der Satz, und mehr ist an ihm nicht zu sehen.
|
||||
|
||||
Das lässt sich auch unabhängig von der Handrechnung nachweisen: Primal- und Dualproblem werden als **zwei getrennte, voneinander unabhängige LPs** aufgestellt und gelöst — wenn der starke Dualitätssatz`\index{Starker Dualitätssatz}`{=latex} stimmt, müssen beide denselben Zielwert liefern, ohne dass eines vom anderen „weiß“.
|
||||
|
||||
```python
|
||||
|
|
@ -5555,7 +5567,7 @@ Der Zukauf für 18 €/h ist hochprofitabel: Jede zusätzliche Prüfstunde bring
|
|||
|
||||
Der vorige Abschnitt hat gezeigt, wie wertvoll Schattenpreise sind. Dieser zeigt die zwei Fälle, in denen sie eine Entscheidung **nicht** tragen — und wie man beide erkennt, bevor jemand auf ihrer Grundlage eine Maschine kauft.
|
||||
|
||||

|
||||
|
||||
**Was Sie in der Abbildung sehen.** Jeder Wert innerhalb der farbigen Balken erfüllt die Optimalitätsbedingungen. Zwei Solver dürfen also verschiedene Schattenpreise melden und haben beide recht — die Frage „was ist eine Stunde wert?" hat hier schlicht keine eindeutige Antwort.
|
||||
|
|
@ -6222,6 +6234,11 @@ Skript löst die LP-Relaxationen und kappt nach denselben drei Regeln, die oben
|
|||
* seine LP-Schranke schlechter ist als die beste bereits gefundene ganzzahlige Lösung (der **Incumbent**`\index{Branch-and-Bound!Incumbent}`{=latex}),
|
||||
* oder die LP-Lösung bereits ganzzahlig ist (dann ist dieser Ast fertig).
|
||||
|
||||

|
||||
|
||||
**Was Sie in der Abbildung sehen.** Der rote Streifen ist genau das, was Phase 2 wegnimmt — und in ihm liegt kein einziger grauer Punkt. Deshalb ist Verzweigen verlustfrei. Weggenommen wird trotzdem etwas Wertvolles: das LP-Optimum (3; 1,5) selbst. Genau darum sinkt die Schranke von 21 auf 20,67, und genau dieses Sinken ist der Fortschritt, den der Suchbaum Knoten für Knoten protokolliert.
|
||||
|
||||
Zusätzlich fügen Solver **Schnittebenen**`\index{Schnittebenen}`{=latex} (*cutting planes*, z. B. Gomory-Cuts`\index{Schnittebenen!Gomory-Cuts}`{=latex}) hinzu: gültige Ungleichungen, die gebrochene Bereiche wegschneiden, ohne einen einzigen zulässigen ganzzahligen Punkt zu entfernen.
|
||||
|
||||
> **✏️ Handrechnung 6.2: Ein Suchbaum von Hand**
|
||||
|
|
@ -6246,7 +6263,7 @@ Zusätzlich fügen Solver **Schnittebenen**`\index{Schnittebenen}`{=latex} (*cut
|
|||
|
||||
Hier kommt das Handwerkszeug, das MILP so mächtig macht:`\index{Big-M-Methode}`{=latex} Man übersetzt Geschäftsregeln in lineare Ungleichungen — mithilfe binärer Hilfsvariablen $y \in \{0,1\}$ und einer hinreichend großen Konstante $M$.
|
||||
|
||||

|
||||
|
||||
**Was Sie in der Abbildung sehen.** Für $y \in \{0,1\}$ sind beide Modelle gleichwertig; die beiden blauen Punkte stimmen überein. Verschieden ist nur, was dazwischen erlaubt ist — und rechts genügt bereits $y = 0{,}08$, um die volle Kapazität freizugeben.
|
||||
|
|
@ -7693,6 +7710,11 @@ Der **CP-SAT-Solver**`\index{CP-SAT-Solver}`{=latex} von Google OR-Tools verbind
|
|||
>
|
||||
> **Und wenn ein Widerspruch auftritt?** Dann lernt der SAT-Kern eine **Sperrklausel** (*nogood*): „Diese Kombination nie wieder probieren.“ Der Solver springt dann nicht nur einen Schritt zurück, sondern direkt zur Ursache des Konflikts (*non-chronological backtracking*).
|
||||
|
||||

|
||||
|
||||
**Was Sie in der Abbildung sehen.** Jede Runde streicht genau **einen** Wert — und trotzdem sinkt die Zahl der Kombinationen von 16 auf 9, also um gut vierzig Prozent. Das ist der Hebel: Gestrichen wird nicht eine Kombination, sondern ein Wert, und mit ihm alle Kombinationen, in denen er vorkam.
|
||||
|
||||
```python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
|
|
@ -8273,11 +8295,14 @@ Erreichter Makespan: 11
|
|||
==========================================================================
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
*Eine interaktive Fassung dieser Grafik steht auf den Kapitelseiten der Website bereit.*
|
||||
|
||||
**Lesen Sie das Gantt-Diagramm.** Auftrag 1 kommt zuerst an die Fräse (0–2), Auftrag 0 muss warten und ist dort erst von 2 bis 5 an der Reihe. Auffällig ist die Lücke in der Dreherei bei Zeitpunkt 4: Die Maschine steht still, obwohl Auftrag 0 schon Arbeit hätte — er ist aber bis 5 noch an der Fräse. Dieses **Warten ist unvermeidlich**; es entsteht aus dem Zusammenspiel von Reihenfolge- und Maschinenbedingungen, nicht aus einer schlechten Planung.
|
||||
**Lesen Sie das Gantt-Diagramm.** Auftrag 1 kommt zuerst an die Fräse (0–2), Auftrag 0 muss warten und ist dort erst von 2 bis 5 an der Reihe. Auffällig sind die beiden schraffierten Lücken. Die in der Dreherei bei Zeitpunkt 4 ist die sprechendere: Die Maschine steht still, obwohl Auftrag 0 schon Arbeit hätte — er ist aber bis 5 noch an der Fräse. Dieses **Warten ist unvermeidlich**; es entsteht aus dem Zusammenspiel von Reihenfolge- und Maschinenbedingungen, nicht aus einer schlechten Planung.
|
||||
|
||||
Die gestrichelte Linie bei 10 sagt dasselbe von der anderen Seite. Sie ist die untere Schranke aus dem Programm, und sie stammt von der Dreherei: Deren drei Arbeitsgänge dauern zusammen 2 + 4 + 4 = 10 Zeiteinheiten, die sich nicht überlappen dürfen. Die Dreherei ist im Plan von 0 bis 11 belegt — also genau ihre 10 Einheiten Arbeit plus die eine schraffierte Einheit Stillstand. Der Plan ist somit nicht deshalb elf lang, weil schlecht geplant wurde, sondern weil die Engpassmaschine einmal warten muss. (Die zweite Lücke, in der Lackiererei, kostet nichts: Diese Maschine ist ohnehin nicht der Engpass.)
|
||||
|
||||
> **⚠️ Mehrere gleich gute Pläne — und was das für Ihre Tests bedeutet**
|
||||
>
|
||||
|
|
@ -15778,7 +15803,7 @@ dem CO2-Preis, den das Unternehmen ohnehin ansetzt.
|
|||
Die Front hat **zehn** Punkte. Ein Raster aus 1 401 Gewichten findet **sechs** davon. Vier Kompromisse sind für kein Gewicht erreichbar — und das ist keine Frage der Rasterweite.
|
||||
|
||||

|
||||
Hülle und sind über Gewichte erreichbar; die vier offenen Kreise sind pareto-optimal, werden aber von keiner Geraden gestützt. Die dünne Gerade ist eine solche Stützgerade, die punktierte die parallele Gerade durch den am weitesten abliegenden der vier Punkte. Erzeugt von `bilder_04/erzeuge_pareto_front.py`.](bilder_04/kap_mehrziel_pareto.svg)
|
||||
|
||||
*Eine interaktive Fassung dieser Grafik steht auf den Kapitelseiten der Website bereit.*
|
||||
|
||||
|
|
@ -15786,6 +15811,8 @@ Hülle und sind über Gewichte erreichbar; die vier offenen Kreise sind pareto-o
|
|||
|
||||
Das Programm rechnet diese Hülle in `untere_huelle()` unabhängig aus und vergleicht: Genau die vier Punkte, die das Gewichtsraster verfehlt, liegen strikt oberhalb. Die Gegenprobe steht in der Ausgabe.
|
||||
|
||||
**Was Sie in der Abbildung sehen.** Die beiden Geraden haben dieselbe Steigung, also dasselbe Gewicht $w$. Die untere berührt die Hülle in zwei Ecken — eine von beiden meldet der Solver als Optimum. Die obere geht durch einen pareto-optimalen Punkt, der damit für dieses Gewicht chancenlos ist, und zwar nicht knapp: Er liegt eine ganze Stufe darüber. Verschieben Sie die Steigung, verschiebt sich die Berührung von einer Ecke zur nächsten — über den Punkt dazwischen springt sie hinweg. Die waagerechte Linie zeigt den Ausweg, um den es in [Abschnitt 14.7](#sec:mehrziel-epsilon) geht: Eine Schranke für den CO₂-Ausstoß statt eines Gewichts findet genau diesen Punkt.
|
||||
|
||||
> **⚠️ Der Grund liegt in der Ganzzahligkeit**
|
||||
>
|
||||
> Bei einem reinen LP ist der zulässige Bereich konvex, und die Pareto-Front liegt vollständig auf ihrer eigenen konvexen Hülle — dort findet die gewichtete Summe alles. Sobald Entscheidungen **ganzzahlig** werden (welcher Träger, welches Lager, welche Schicht), zerfällt der Bereich in einzelne Punkte, und zwischen ihnen entstehen Einbuchtungen.
|
||||
|
|
@ -19842,6 +19869,11 @@ CVaR: Portfolio 101.33 vs. Summe 159.24 -> subadditiv (kohaerent)
|
|||
|
||||
Und Teil 2 zeigt das Grundproblem des VaR an einem Beispiel, das Sie von Hand nachrechnen können: Einzeln meldet er für jede Anleihe einen *Gewinn* von 2 €, im Portfolio einen *Verlust* von 98 €. Diversifikation hätte demnach das Risiko um 102 € erhöht. Der CVaR dagegen verhält sich korrekt: 101,33 € im Portfolio gegenüber 159,24 € bei getrennter Betrachtung — die Streuung **senkt** das Risiko, wie es sein muss.
|
||||
|
||||

|
||||
|
||||
**Was Sie in der Abbildung sehen.** Links wechselt der Balken über null das Vorzeichen: Aus zwei gemeldeten Gewinnen wird im Portfolio ein Verlust. Rechts passiert nichts dergleichen — der Portfoliobalken ist kürzer als der Summenbalken, und genau das heißt Subadditivität. Der Grund für den Sprung links ist keine Rechenungenauigkeit, sondern die Bauart des Maßes: Eine Schwelle bei 95 % sieht ein Ereignis mit 4 % Wahrscheinlichkeit nicht — bis zwei davon zusammenkommen.
|
||||
|
||||
> **⚠️ Eine Falle bei der CVaR-Berechnung** Der naheliegende Weg — „Mittelwert aller Verluste $\ge$ VaR“ — ist **falsch**, sobald die Verteilung **Atome** hat (also einzelne Werte mit positiver Wahrscheinlichkeit, wie hier die zwei möglichen Ausgänge). Der VaR liegt dann selbst auf einem Atom, und der Vergleich `>=` erfasst zu viel Wahrscheinlichkeitsmasse. Im Beispiel oben liefert dieser naive Schätzer für Anleihe A den Wert 2,08 statt der korrekten 79,59 — ein Fehler um Faktor 38.
|
||||
>
|
||||
> Die Rockafellar-Uryasev-Formel behandelt Atome von sich aus korrekt. Verwenden Sie sie auch dann, wenn Sie „nur schnell“ einen CVaR ausrechnen wollen.
|
||||
|
|
@ -19850,7 +19882,7 @@ Und Teil 2 zeigt das Grundproblem des VaR an einem Beispiel, das Sie von Hand na
|
|||
|
||||
## 20.4 Value at Risk und Conditional Value at Risk {#sec:cvar-value-at-risk-und-conditional-value}
|
||||
|
||||

|
||||
|
||||
**Value at Risk ($\text{VaR}_\alpha$):**`\index{Value at Risk (VaR)}`{=latex} Der Verlust, der mit Wahrscheinlichkeit $\alpha$ nicht überschritten wird.
|
||||
|
|
@ -19925,7 +19957,7 @@ $$
|
|||
= \lVert \mathbf{w}-\mathbf{w}_{\text{alt}}\rVert_1
|
||||
$$
|
||||
|
||||

|
||||

|
||||
|
||||
> **📐 Formel-Lesehilfe** Die $L_1$-Norm ist die Summe der **Beträge**. Sie misst, wie viel Prozent des Portfolios insgesamt bewegt werden — Käufe und Verkäufe zusammen.
|
||||
>
|
||||
|
|
@ -22050,7 +22082,8 @@ Alle drei Antworten stehen bis hierhin in Tabellen. Tabellen liest niemand in ei
|
|||
|
||||
## 22.5 Architektur einer produktionsreifen OR-Plattform {#sec:praxisfallen-architektur-einer-produktionsreifen-or-plattform}
|
||||
|
||||

|
||||

|
||||
|
||||
In einer professionellen Umgebung ist der Optimierer kein Skript, sondern ein **versionierter, zustandsloser Dienst**:
|
||||
|
||||
|
|
@ -22063,6 +22096,8 @@ In einer professionellen Umgebung ist der Optimierer kein Skript, sondern ein **
|
|||
| **Ausführung** | Kalender-Sync, Benachrichtigung, Order-Routing | Kalender-APIs, Messaging, Broker |
|
||||
| **Betrieb** | Monitoring, Audit-Trail, Alarme | Logging, Metriken, Versionierung |
|
||||
|
||||
**Was Sie in der Abbildung sehen.** Fünf der sechs Schichten bilden einen Weg: Daten gehen oben hinein und unten als Handlung wieder hinaus. Die sechste steht daneben, und das ist keine zeichnerische Verlegenheit — Monitoring und Audit-Trail sind keine Station, die man durchläuft, sondern eine Anforderung an jede. Wer sie als sechsten Kasten unten anhängt, baut sie am Ende auch so: als etwas, das man hinterher noch macht.
|
||||
|
||||
**Fünf Prinzipien, die sich in der Praxis bewährt haben:**
|
||||
|
||||
1. **Snapshot-Prinzip.**`\index{Snapshot-Prinzip}`{=latex} Jeder Optimierungslauf arbeitet auf einem unveränderlichen Datenschnappschuss mit eigener ID. Nur so ist ein Ergebnis später reproduzierbar — und im Streitfall belegbar.
|
||||
|
|
|
|||
Loading…
Reference in a new issue