diff --git a/CLAUDE.md b/CLAUDE.md index 871a862..dc46454 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -139,7 +139,9 @@ keinen Generator — dort kann nichts driften. Das Kriterium steht in `PROGRESS. Abschnitt 6c. Konventionen der Generatoren: `plt.rcParams["svg.hashsalt"] = "or-mit-python-v04"` und -`metadata={"Date": None}` für byteidentische Läufe; stammt die Instanz aus einem +`metadata={"Date": None}` für byteidentische Läufe — **beides, sonst trägt das SVG einen +Zeitstempel und wechselnde `clip-path`-IDs**. Geschrieben wird **nur SVG**; PNG-Zweitfassungen +gab es einmal, sie wurden nirgends referenziert; stammt die Instanz aus einem Zufallsstrom, wird die Ziehungsreihenfolge des Buchprogramms nachgespielt. ## Plotly-Figuren diff --git a/Notebooks_04/einfuehrung.ipynb b/Notebooks_04/einfuehrung.ipynb index 24f6f1c..0531984 100644 --- a/Notebooks_04/einfuehrung.ipynb +++ b/Notebooks_04/einfuehrung.ipynb @@ -405,8 +405,13 @@ "from or_kern import (lade_produktionsproblem, loese_mit_glop, pruefe_loesung,\n", " schreibe_ergebnis)\n", "\n", - "EINGABE = \"produktionsmix.xlsx\"\n", - "AUSGABE = \"produktionsmix_ergebnis.xlsx\"\n", + "# Die Mappen liegen NEBEN diesem Programm, nicht im aktuellen\n", + "# Arbeitsverzeichnis. Sonst haengt es davon ab, aus welchem Ordner man das\n", + "# Skript startet, wo die Dateien landen - und wer es aus der\n", + "# Repository-Wurzel aufruft, verstreut sie dort.\n", + "HIER = os.path.dirname(os.path.abspath(__file__))\n", + "EINGABE = os.path.join(HIER, \"produktionsmix.xlsx\")\n", + "AUSGABE = os.path.join(HIER, \"produktionsmix_ergebnis.xlsx\")\n", "\n", "\n", "def lege_beispieldatei_an(pfad: str) -> None:\n", diff --git a/OR_HTML_04/Notebooks_04/einfuehrung.ipynb b/OR_HTML_04/Notebooks_04/einfuehrung.ipynb index 24f6f1c..0531984 100644 --- a/OR_HTML_04/Notebooks_04/einfuehrung.ipynb +++ b/OR_HTML_04/Notebooks_04/einfuehrung.ipynb @@ -405,8 +405,13 @@ "from or_kern import (lade_produktionsproblem, loese_mit_glop, pruefe_loesung,\n", " schreibe_ergebnis)\n", "\n", - "EINGABE = \"produktionsmix.xlsx\"\n", - "AUSGABE = \"produktionsmix_ergebnis.xlsx\"\n", + "# Die Mappen liegen NEBEN diesem Programm, nicht im aktuellen\n", + "# Arbeitsverzeichnis. Sonst haengt es davon ab, aus welchem Ordner man das\n", + "# Skript startet, wo die Dateien landen - und wer es aus der\n", + "# Repository-Wurzel aufruft, verstreut sie dort.\n", + "HIER = os.path.dirname(os.path.abspath(__file__))\n", + "EINGABE = os.path.join(HIER, \"produktionsmix.xlsx\")\n", + "AUSGABE = os.path.join(HIER, \"produktionsmix_ergebnis.xlsx\")\n", "\n", "\n", "def lege_beispieldatei_an(pfad: str) -> None:\n", diff --git a/OR_HTML_04/Operations_Research_mit_Python_Version_04.pdf b/OR_HTML_04/Operations_Research_mit_Python_Version_04.pdf index 077f0a4..e86efe9 100644 Binary files a/OR_HTML_04/Operations_Research_mit_Python_Version_04.pdf and b/OR_HTML_04/Operations_Research_mit_Python_Version_04.pdf differ diff --git a/OR_HTML_04/bilder_04/kap01_analytik_reifegrad.png b/OR_HTML_04/bilder_04/kap01_analytik_reifegrad.png deleted file mode 100644 index 9ef9840..0000000 Binary files a/OR_HTML_04/bilder_04/kap01_analytik_reifegrad.png and /dev/null differ diff --git a/OR_HTML_04/bilder_04/kap01_vier_bausteine.png b/OR_HTML_04/bilder_04/kap01_vier_bausteine.png deleted file mode 100644 index f0b51a3..0000000 Binary files a/OR_HTML_04/bilder_04/kap01_vier_bausteine.png and /dev/null differ diff --git a/OR_HTML_04/bilder_04/kap02_konvexitaet.png b/OR_HTML_04/bilder_04/kap02_konvexitaet.png deleted file mode 100644 index 6bbd0cc..0000000 Binary files a/OR_HTML_04/bilder_04/kap02_konvexitaet.png and /dev/null differ diff --git a/OR_HTML_04/bilder_04/kap03_solver_architektur.png b/OR_HTML_04/bilder_04/kap03_solver_architektur.png deleted file mode 100644 index 79fa438..0000000 Binary files a/OR_HTML_04/bilder_04/kap03_solver_architektur.png and /dev/null differ diff --git a/OR_HTML_04/bilder_04/kap04_primal_dual.png b/OR_HTML_04/bilder_04/kap04_primal_dual.png deleted file mode 100644 index 8557112..0000000 Binary files a/OR_HTML_04/bilder_04/kap04_primal_dual.png and /dev/null differ diff --git a/OR_HTML_04/bilder_04/kap06_cp_sat_propagation.png b/OR_HTML_04/bilder_04/kap06_cp_sat_propagation.png deleted file mode 100644 index 64feb08..0000000 Binary files a/OR_HTML_04/bilder_04/kap06_cp_sat_propagation.png and /dev/null differ diff --git a/OR_HTML_04/bilder_04/kap06_jobshop_gantt.png b/OR_HTML_04/bilder_04/kap06_jobshop_gantt.png deleted file mode 100644 index a6b1def..0000000 Binary files a/OR_HTML_04/bilder_04/kap06_jobshop_gantt.png and /dev/null differ diff --git a/OR_HTML_04/bilder_04/kap06_jobshop_gantt.svg b/OR_HTML_04/bilder_04/kap06_jobshop_gantt.svg index 7765306..1bccc9b 100644 --- a/OR_HTML_04/bilder_04/kap06_jobshop_gantt.svg +++ b/OR_HTML_04/bilder_04/kap06_jobshop_gantt.svg @@ -6,7 +6,6 @@ - 2026-09-07T01:51:51.979555 image/svg+xml @@ -43,7 +42,7 @@ L 326.435455 32.849091 L 326.435455 64.809875 L 174.248182 64.809875 z -" clip-path="url(#p448fd06892)" style="fill: #4338ca; stroke: #ffffff; stroke-width: 1.2; stroke-linejoin: miter"/> +" clip-path="url(#pce73ba693e)" style="fill: #4338ca; stroke: #ffffff; stroke-width: 1.2; stroke-linejoin: miter"/> +" clip-path="url(#pce73ba693e)" style="fill: #4338ca; stroke: #ffffff; stroke-width: 1.2; stroke-linejoin: miter"/> +" clip-path="url(#pce73ba693e)" style="fill: #4338ca; stroke: #ffffff; stroke-width: 1.2; stroke-linejoin: miter"/> +" clip-path="url(#pce73ba693e)" style="fill: #0891b2; stroke: #ffffff; stroke-width: 1.2; stroke-linejoin: miter"/> +" clip-path="url(#pce73ba693e)" style="fill: #0891b2; stroke: #ffffff; stroke-width: 1.2; stroke-linejoin: miter"/> +" clip-path="url(#pce73ba693e)" style="fill: #0891b2; stroke: #ffffff; stroke-width: 1.2; stroke-linejoin: miter"/> +" clip-path="url(#pce73ba693e)" style="fill: #b45309; stroke: #ffffff; stroke-width: 1.2; stroke-linejoin: miter"/> +" clip-path="url(#pce73ba693e)" style="fill: #b45309; stroke: #ffffff; stroke-width: 1.2; stroke-linejoin: miter"/> +" clip-path="url(#pce73ba693e)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> - - + @@ -152,11 +151,11 @@ z +" clip-path="url(#pce73ba693e)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> - + @@ -186,11 +185,11 @@ z +" clip-path="url(#pce73ba693e)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> - + @@ -230,11 +229,11 @@ z +" clip-path="url(#pce73ba693e)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> - + @@ -282,11 +281,11 @@ z +" clip-path="url(#pce73ba693e)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> - + @@ -321,11 +320,11 @@ z +" clip-path="url(#pce73ba693e)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> - + @@ -366,11 +365,11 @@ z +" clip-path="url(#pce73ba693e)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> - + @@ -416,11 +415,11 @@ z +" clip-path="url(#pce73ba693e)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> - + @@ -446,11 +445,11 @@ z +" clip-path="url(#pce73ba693e)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> - + @@ -505,11 +504,11 @@ z +" clip-path="url(#pce73ba693e)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> - + @@ -555,11 +554,11 @@ z +" clip-path="url(#pce73ba693e)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> - + @@ -574,11 +573,11 @@ L 580.080909 25.44 +" clip-path="url(#pce73ba693e)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> - + @@ -724,12 +723,12 @@ z - - + @@ -843,7 +842,7 @@ z - + @@ -884,7 +883,7 @@ z - + @@ -1320,7 +1319,7 @@ z - + diff --git a/OR_HTML_04/bilder_04/kap09_unsicherheit_ansaetze.png b/OR_HTML_04/bilder_04/kap09_unsicherheit_ansaetze.png deleted file mode 100644 index 6a40ea0..0000000 Binary files a/OR_HTML_04/bilder_04/kap09_unsicherheit_ansaetze.png and /dev/null differ diff --git a/OR_HTML_04/bilder_04/kap10_zustandskette.png b/OR_HTML_04/bilder_04/kap10_zustandskette.png deleted file mode 100644 index cef457c..0000000 Binary files a/OR_HTML_04/bilder_04/kap10_zustandskette.png and /dev/null differ diff --git a/OR_HTML_04/bilder_04/kap11_ledoit_wolf_shrinkage.png b/OR_HTML_04/bilder_04/kap11_ledoit_wolf_shrinkage.png deleted file mode 100644 index e5b82f7..0000000 Binary files a/OR_HTML_04/bilder_04/kap11_ledoit_wolf_shrinkage.png and /dev/null differ diff --git a/OR_HTML_04/bilder_04/kap12_efficient_frontier.png b/OR_HTML_04/bilder_04/kap12_efficient_frontier.png deleted file mode 100644 index d8e04c5..0000000 Binary files a/OR_HTML_04/bilder_04/kap12_efficient_frontier.png and /dev/null differ diff --git a/OR_HTML_04/bilder_04/kap13_cvar_zielfunktion.png b/OR_HTML_04/bilder_04/kap13_cvar_zielfunktion.png deleted file mode 100644 index 5324d42..0000000 Binary files a/OR_HTML_04/bilder_04/kap13_cvar_zielfunktion.png and /dev/null differ diff --git a/OR_HTML_04/bilder_04/kap14_engine_overview.png b/OR_HTML_04/bilder_04/kap14_engine_overview.png deleted file mode 100644 index c9886a4..0000000 Binary files a/OR_HTML_04/bilder_04/kap14_engine_overview.png and /dev/null differ diff --git a/OR_HTML_04/bilder_04/kap15_or_plattform.png b/OR_HTML_04/bilder_04/kap15_or_plattform.png deleted file mode 100644 index 20f63a4..0000000 Binary files a/OR_HTML_04/bilder_04/kap15_or_plattform.png and /dev/null differ diff --git a/OR_HTML_04/bilder_04/kap15_praxisfallen.png b/OR_HTML_04/bilder_04/kap15_praxisfallen.png deleted file mode 100644 index 4a904ab..0000000 Binary files a/OR_HTML_04/bilder_04/kap15_praxisfallen.png and /dev/null differ diff --git a/OR_HTML_04/bilder_04/kap_cvar_var_vergleich.png b/OR_HTML_04/bilder_04/kap_cvar_var_vergleich.png deleted file mode 100644 index 0bbf9a0..0000000 Binary files a/OR_HTML_04/bilder_04/kap_cvar_var_vergleich.png and /dev/null differ diff --git a/OR_HTML_04/bilder_04/kap_fundament_kondition.png b/OR_HTML_04/bilder_04/kap_fundament_kondition.png deleted file mode 100644 index a82df02..0000000 Binary files a/OR_HTML_04/bilder_04/kap_fundament_kondition.png and /dev/null differ diff --git a/OR_HTML_04/bilder_04/kap_fundament_polyeder.png b/OR_HTML_04/bilder_04/kap_fundament_polyeder.png deleted file mode 100644 index d4bb3dc..0000000 Binary files a/OR_HTML_04/bilder_04/kap_fundament_polyeder.png and /dev/null differ diff --git a/OR_HTML_04/bilder_04/kap_graphen_min_cost_flow.png b/OR_HTML_04/bilder_04/kap_graphen_min_cost_flow.png deleted file mode 100644 index 1800e77..0000000 Binary files a/OR_HTML_04/bilder_04/kap_graphen_min_cost_flow.png and /dev/null differ diff --git a/OR_HTML_04/bilder_04/kap_graphen_vrp_touren.png b/OR_HTML_04/bilder_04/kap_graphen_vrp_touren.png deleted file mode 100644 index 9572a19..0000000 Binary files a/OR_HTML_04/bilder_04/kap_graphen_vrp_touren.png and /dev/null differ diff --git a/OR_HTML_04/bilder_04/kap_lp_simplex_ecken.png b/OR_HTML_04/bilder_04/kap_lp_simplex_ecken.png deleted file mode 100644 index 6c93a53..0000000 Binary files a/OR_HTML_04/bilder_04/kap_lp_simplex_ecken.png and /dev/null differ diff --git a/OR_HTML_04/bilder_04/kap_markowitz_restriktionen.png b/OR_HTML_04/bilder_04/kap_markowitz_restriktionen.png deleted file mode 100644 index 96d7e9a..0000000 Binary files a/OR_HTML_04/bilder_04/kap_markowitz_restriktionen.png and /dev/null differ diff --git a/OR_HTML_04/bilder_04/kap_mehrziel_pareto.png b/OR_HTML_04/bilder_04/kap_mehrziel_pareto.png deleted file mode 100644 index 324afd5..0000000 Binary files a/OR_HTML_04/bilder_04/kap_mehrziel_pareto.png and /dev/null differ diff --git a/OR_HTML_04/bilder_04/kap_metaheuristiken_landschaft.png b/OR_HTML_04/bilder_04/kap_metaheuristiken_landschaft.png deleted file mode 100644 index df8e89a..0000000 Binary files a/OR_HTML_04/bilder_04/kap_metaheuristiken_landschaft.png and /dev/null differ diff --git a/OR_HTML_04/bilder_04/kap_milp_runden.png b/OR_HTML_04/bilder_04/kap_milp_runden.png deleted file mode 100644 index 5d466f3..0000000 Binary files a/OR_HTML_04/bilder_04/kap_milp_runden.png and /dev/null differ diff --git a/OR_HTML_04/bilder_04/kap_milp_suchbaum.png b/OR_HTML_04/bilder_04/kap_milp_suchbaum.png deleted file mode 100644 index bec5d10..0000000 Binary files a/OR_HTML_04/bilder_04/kap_milp_suchbaum.png and /dev/null differ diff --git a/OR_HTML_04/bilder_04/kap_praxisfallen_schichten.png b/OR_HTML_04/bilder_04/kap_praxisfallen_schichten.png deleted file mode 100644 index df8206f..0000000 Binary files a/OR_HTML_04/bilder_04/kap_praxisfallen_schichten.png and /dev/null differ diff --git a/OR_HTML_04/bilder_04/kap_qp_kkt.png b/OR_HTML_04/bilder_04/kap_qp_kkt.png deleted file mode 100644 index 2e4d95b..0000000 Binary files a/OR_HTML_04/bilder_04/kap_qp_kkt.png and /dev/null differ diff --git a/OR_HTML_04/bilder_04/kap_supplychain_wirkung.png b/OR_HTML_04/bilder_04/kap_supplychain_wirkung.png deleted file mode 100644 index 91c255f..0000000 Binary files a/OR_HTML_04/bilder_04/kap_supplychain_wirkung.png and /dev/null differ diff --git a/OR_HTML_04/bilder_04/kap_testing_dienst.png b/OR_HTML_04/bilder_04/kap_testing_dienst.png deleted file mode 100644 index e4061ac..0000000 Binary files a/OR_HTML_04/bilder_04/kap_testing_dienst.png and /dev/null differ diff --git a/OR_HTML_04/bilder_04/teil2_solverwahl.png b/OR_HTML_04/bilder_04/teil2_solverwahl.png deleted file mode 100644 index 3c4dc43..0000000 Binary files a/OR_HTML_04/bilder_04/teil2_solverwahl.png and /dev/null differ diff --git a/OR_HTML_04/bilder_04/teil3_solverwahl.png b/OR_HTML_04/bilder_04/teil3_solverwahl.png deleted file mode 100644 index 72692b5..0000000 Binary files a/OR_HTML_04/bilder_04/teil3_solverwahl.png and /dev/null differ diff --git a/OR_HTML_04/bilder_04/titelseite.png b/OR_HTML_04/bilder_04/titelseite.png deleted file mode 100644 index 31e7f2a..0000000 Binary files a/OR_HTML_04/bilder_04/titelseite.png and /dev/null differ diff --git a/OR_HTML_04/einfuehrung.html b/OR_HTML_04/einfuehrung.html index 7498719..77cab65 100644 --- a/OR_HTML_04/einfuehrung.html +++ b/OR_HTML_04/einfuehrung.html @@ -1205,66 +1205,71 @@ Vorteil der Optimierung: 300.00 EUR pro Tag (15.0 %) from or_kern import (lade_produktionsproblem, loese_mit_glop, pruefe_loesung, schreibe_ergebnis) -EINGABE = "produktionsmix.xlsx" -AUSGABE = "produktionsmix_ergebnis.xlsx" - - -def lege_beispieldatei_an(pfad: str) -> None: - """Schreibt die Eingabemappe, wie sie auch aus dem Controlling kaeme.""" - produkte = pd.DataFrame({ - "Produkt": ["Tisch", "Stuhl", "Regal"], - "Deckungsbeitrag": [240.0, 60.0, 130.0], - "Montagestunden": [3.0, 1.0, 2.0], - "Plattenmaterial": [6.0, 1.0, 4.0], - }) - kapazitaeten = pd.DataFrame({ - "Ressource": ["Montagestunden", "Plattenmaterial"], - "Verfuegbar": [150.0, 240.0], - }) - with pd.ExcelWriter(pfad, engine="openpyxl") as mappe: - produkte.to_excel(mappe, sheet_name="Produkte", index=False) - kapazitaeten.to_excel(mappe, sheet_name="Kapazitaeten", index=False) - - -if __name__ == "__main__": - if not os.path.exists(EINGABE): - lege_beispieldatei_an(EINGABE) - print(f"Beispiel-Eingabedatei angelegt: {EINGABE}") +# Die Mappen liegen NEBEN diesem Programm, nicht im aktuellen +# Arbeitsverzeichnis. Sonst haengt es davon ab, aus welchem Ordner man das +# Skript startet, wo die Dateien landen - und wer es aus der +# Repository-Wurzel aufruft, verstreut sie dort. +HIER = os.path.dirname(os.path.abspath(__file__)) +EINGABE = os.path.join(HIER, "produktionsmix.xlsx") +AUSGABE = os.path.join(HIER, "produktionsmix_ergebnis.xlsx") + + +def lege_beispieldatei_an(pfad: str) -> None: + """Schreibt die Eingabemappe, wie sie auch aus dem Controlling kaeme.""" + produkte = pd.DataFrame({ + "Produkt": ["Tisch", "Stuhl", "Regal"], + "Deckungsbeitrag": [240.0, 60.0, 130.0], + "Montagestunden": [3.0, 1.0, 2.0], + "Plattenmaterial": [6.0, 1.0, 4.0], + }) + kapazitaeten = pd.DataFrame({ + "Ressource": ["Montagestunden", "Plattenmaterial"], + "Verfuegbar": [150.0, 240.0], + }) + with pd.ExcelWriter(pfad, engine="openpyxl") as mappe: + produkte.to_excel(mappe, sheet_name="Produkte", index=False) + kapazitaeten.to_excel(mappe, sheet_name="Kapazitaeten", index=False) + - # 1. Lesen und pruefen. Faellt hier etwas auf, ist der Fehler noch - # zuzuordnen - spaeter waere er nur noch eine merkwuerdige Zahl. - problem = lade_produktionsproblem(EINGABE) - - # 2. Loesen. Einzige solverabhaengige Zeile des ganzen Programms - - # 'loese_mit_scipy' waere ein Einzeiler-Wechsel. - loesung = loese_mit_glop(problem) - - # 3. Abnahmepruefung gegen die Anforderungen, ohne den Solver zu fragen. - beanstandungen = pruefe_loesung(problem, loesung) - if beanstandungen: - raise SystemExit("Abnahmepruefung fehlgeschlagen:\n - " - + "\n - ".join(beanstandungen)) - - # 4. Zurueckschreiben - im Format, das die Fachabteilung ohnehin benutzt. - schreibe_ergebnis(AUSGABE, problem, loesung) - - print("=" * 66) - print(" PRODUKTIONSPLAN AUS DER EXCEL-MAPPE") - print("=" * 66) - for produkt in problem.produkte: - menge = loesung.werte[produkt.name] - print(f"{produkt.name:<18} {menge:8.1f} Stueck " - f"{menge * produkt.deckungsbeitrag:12,.2f} EUR") - print("-" * 66) - print(loesung.als_bericht()) - print("Abnahmepruefung: bestanden\n") - - # Die Schattenpreise beantworten die Frage, die der Plan nicht stellt: - # Was waere eine zusaetzliche Einheit dieser Ressource wert? - for ressource, preis in loesung.schattenpreise.items(): - print(f" eine Einheit {ressource:<18} mehr waere wert: {preis:7.2f} EUR") - print("=" * 66) - print(f"Ergebnis geschrieben nach: {AUSGABE}") +if __name__ == "__main__": + if not os.path.exists(EINGABE): + lege_beispieldatei_an(EINGABE) + print(f"Beispiel-Eingabedatei angelegt: {EINGABE}") + + # 1. Lesen und pruefen. Faellt hier etwas auf, ist der Fehler noch + # zuzuordnen - spaeter waere er nur noch eine merkwuerdige Zahl. + problem = lade_produktionsproblem(EINGABE) + + # 2. Loesen. Einzige solverabhaengige Zeile des ganzen Programms - + # 'loese_mit_scipy' waere ein Einzeiler-Wechsel. + loesung = loese_mit_glop(problem) + + # 3. Abnahmepruefung gegen die Anforderungen, ohne den Solver zu fragen. + beanstandungen = pruefe_loesung(problem, loesung) + if beanstandungen: + raise SystemExit("Abnahmepruefung fehlgeschlagen:\n - " + + "\n - ".join(beanstandungen)) + + # 4. Zurueckschreiben - im Format, das die Fachabteilung ohnehin benutzt. + schreibe_ergebnis(AUSGABE, problem, loesung) + + print("=" * 66) + print(" PRODUKTIONSPLAN AUS DER EXCEL-MAPPE") + print("=" * 66) + for produkt in problem.produkte: + menge = loesung.werte[produkt.name] + print(f"{produkt.name:<18} {menge:8.1f} Stueck " + f"{menge * produkt.deckungsbeitrag:12,.2f} EUR") + print("-" * 66) + print(loesung.als_bericht()) + print("Abnahmepruefung: bestanden\n") + + # Die Schattenpreise beantworten die Frage, die der Plan nicht stellt: + # Was waere eine zusaetzliche Einheit dieser Ressource wert? + for ressource, preis in loesung.schattenpreise.items(): + print(f" eine Einheit {ressource:<18} mehr waere wert: {preis:7.2f} EUR") + print("=" * 66) + print(f"Ergebnis geschrieben nach: {AUSGABE}")

Erwartete Ausgabe:

Beispiel-Eingabedatei angelegt: produktionsmix.xlsx
 ==================================================================
diff --git a/OR_HTML_04/gesamtdokument.html b/OR_HTML_04/gesamtdokument.html
index 738764b..1773fb9 100644
--- a/OR_HTML_04/gesamtdokument.html
+++ b/OR_HTML_04/gesamtdokument.html
@@ -4198,66 +4198,71 @@ Vorteil der Optimierung:          300.00 EUR pro Tag (15.0 %)
 from or_kern import (lade_produktionsproblem, loese_mit_glop, pruefe_loesung,
                      schreibe_ergebnis)
 
-EINGABE = "produktionsmix.xlsx"
-AUSGABE = "produktionsmix_ergebnis.xlsx"
-
-
-def lege_beispieldatei_an(pfad: str) -> None:
-    """Schreibt die Eingabemappe, wie sie auch aus dem Controlling kaeme."""
-    produkte = pd.DataFrame({
-        "Produkt": ["Tisch", "Stuhl", "Regal"],
-        "Deckungsbeitrag": [240.0, 60.0, 130.0],
-        "Montagestunden": [3.0, 1.0, 2.0],
-        "Plattenmaterial": [6.0, 1.0, 4.0],
-    })
-    kapazitaeten = pd.DataFrame({
-        "Ressource": ["Montagestunden", "Plattenmaterial"],
-        "Verfuegbar": [150.0, 240.0],
-    })
-    with pd.ExcelWriter(pfad, engine="openpyxl") as mappe:
-        produkte.to_excel(mappe, sheet_name="Produkte", index=False)
-        kapazitaeten.to_excel(mappe, sheet_name="Kapazitaeten", index=False)
-
-
-if __name__ == "__main__":
-    if not os.path.exists(EINGABE):
-        lege_beispieldatei_an(EINGABE)
-        print(f"Beispiel-Eingabedatei angelegt: {EINGABE}")
+# Die Mappen liegen NEBEN diesem Programm, nicht im aktuellen
+# Arbeitsverzeichnis. Sonst haengt es davon ab, aus welchem Ordner man das
+# Skript startet, wo die Dateien landen - und wer es aus der
+# Repository-Wurzel aufruft, verstreut sie dort.
+HIER = os.path.dirname(os.path.abspath(__file__))
+EINGABE = os.path.join(HIER, "produktionsmix.xlsx")
+AUSGABE = os.path.join(HIER, "produktionsmix_ergebnis.xlsx")
+
+
+def lege_beispieldatei_an(pfad: str) -> None:
+    """Schreibt die Eingabemappe, wie sie auch aus dem Controlling kaeme."""
+    produkte = pd.DataFrame({
+        "Produkt": ["Tisch", "Stuhl", "Regal"],
+        "Deckungsbeitrag": [240.0, 60.0, 130.0],
+        "Montagestunden": [3.0, 1.0, 2.0],
+        "Plattenmaterial": [6.0, 1.0, 4.0],
+    })
+    kapazitaeten = pd.DataFrame({
+        "Ressource": ["Montagestunden", "Plattenmaterial"],
+        "Verfuegbar": [150.0, 240.0],
+    })
+    with pd.ExcelWriter(pfad, engine="openpyxl") as mappe:
+        produkte.to_excel(mappe, sheet_name="Produkte", index=False)
+        kapazitaeten.to_excel(mappe, sheet_name="Kapazitaeten", index=False)
+
 
-    # 1. Lesen und pruefen. Faellt hier etwas auf, ist der Fehler noch
-    #    zuzuordnen - spaeter waere er nur noch eine merkwuerdige Zahl.
-    problem = lade_produktionsproblem(EINGABE)
-
-    # 2. Loesen. Einzige solverabhaengige Zeile des ganzen Programms -
-    #    'loese_mit_scipy' waere ein Einzeiler-Wechsel.
-    loesung = loese_mit_glop(problem)
-
-    # 3. Abnahmepruefung gegen die Anforderungen, ohne den Solver zu fragen.
-    beanstandungen = pruefe_loesung(problem, loesung)
-    if beanstandungen:
-        raise SystemExit("Abnahmepruefung fehlgeschlagen:\n  - "
-                         + "\n  - ".join(beanstandungen))
-
-    # 4. Zurueckschreiben - im Format, das die Fachabteilung ohnehin benutzt.
-    schreibe_ergebnis(AUSGABE, problem, loesung)
-
-    print("=" * 66)
-    print("  PRODUKTIONSPLAN AUS DER EXCEL-MAPPE")
-    print("=" * 66)
-    for produkt in problem.produkte:
-        menge = loesung.werte[produkt.name]
-        print(f"{produkt.name:<18} {menge:8.1f} Stueck "
-              f"{menge * produkt.deckungsbeitrag:12,.2f} EUR")
-    print("-" * 66)
-    print(loesung.als_bericht())
-    print("Abnahmepruefung: bestanden\n")
-
-    # Die Schattenpreise beantworten die Frage, die der Plan nicht stellt:
-    # Was waere eine zusaetzliche Einheit dieser Ressource wert?
-    for ressource, preis in loesung.schattenpreise.items():
-        print(f"  eine Einheit {ressource:<18} mehr waere wert: {preis:7.2f} EUR")
-    print("=" * 66)
-    print(f"Ergebnis geschrieben nach: {AUSGABE}")
+if __name__ == "__main__": + if not os.path.exists(EINGABE): + lege_beispieldatei_an(EINGABE) + print(f"Beispiel-Eingabedatei angelegt: {EINGABE}") + + # 1. Lesen und pruefen. Faellt hier etwas auf, ist der Fehler noch + # zuzuordnen - spaeter waere er nur noch eine merkwuerdige Zahl. + problem = lade_produktionsproblem(EINGABE) + + # 2. Loesen. Einzige solverabhaengige Zeile des ganzen Programms - + # 'loese_mit_scipy' waere ein Einzeiler-Wechsel. + loesung = loese_mit_glop(problem) + + # 3. Abnahmepruefung gegen die Anforderungen, ohne den Solver zu fragen. + beanstandungen = pruefe_loesung(problem, loesung) + if beanstandungen: + raise SystemExit("Abnahmepruefung fehlgeschlagen:\n - " + + "\n - ".join(beanstandungen)) + + # 4. Zurueckschreiben - im Format, das die Fachabteilung ohnehin benutzt. + schreibe_ergebnis(AUSGABE, problem, loesung) + + print("=" * 66) + print(" PRODUKTIONSPLAN AUS DER EXCEL-MAPPE") + print("=" * 66) + for produkt in problem.produkte: + menge = loesung.werte[produkt.name] + print(f"{produkt.name:<18} {menge:8.1f} Stueck " + f"{menge * produkt.deckungsbeitrag:12,.2f} EUR") + print("-" * 66) + print(loesung.als_bericht()) + print("Abnahmepruefung: bestanden\n") + + # Die Schattenpreise beantworten die Frage, die der Plan nicht stellt: + # Was waere eine zusaetzliche Einheit dieser Ressource wert? + for ressource, preis in loesung.schattenpreise.items(): + print(f" eine Einheit {ressource:<18} mehr waere wert: {preis:7.2f} EUR") + print("=" * 66) + print(f"Ergebnis geschrieben nach: {AUSGABE}")

Erwartete Ausgabe:

Beispiel-Eingabedatei angelegt: produktionsmix.xlsx
 ==================================================================
diff --git a/OR_HTML_04/programme/Excel_Bruecke.py b/OR_HTML_04/programme/Excel_Bruecke.py
index b50b3be..e023ac7 100644
--- a/OR_HTML_04/programme/Excel_Bruecke.py
+++ b/OR_HTML_04/programme/Excel_Bruecke.py
@@ -34,8 +34,13 @@ import pandas as pd
 from or_kern import (lade_produktionsproblem, loese_mit_glop, pruefe_loesung,
                      schreibe_ergebnis)
 
-EINGABE = "produktionsmix.xlsx"
-AUSGABE = "produktionsmix_ergebnis.xlsx"
+# Die Mappen liegen NEBEN diesem Programm, nicht im aktuellen
+# Arbeitsverzeichnis. Sonst haengt es davon ab, aus welchem Ordner man das
+# Skript startet, wo die Dateien landen - und wer es aus der
+# Repository-Wurzel aufruft, verstreut sie dort.
+HIER = os.path.dirname(os.path.abspath(__file__))
+EINGABE = os.path.join(HIER, "produktionsmix.xlsx")
+AUSGABE = os.path.join(HIER, "produktionsmix_ergebnis.xlsx")
 
 
 def lege_beispieldatei_an(pfad: str) -> None:
diff --git a/OR_HTML_04/stichwortverzeichnis.html b/OR_HTML_04/stichwortverzeichnis.html
index 71d12db..24feda8 100644
--- a/OR_HTML_04/stichwortverzeichnis.html
+++ b/OR_HTML_04/stichwortverzeichnis.html
@@ -99,7 +99,7 @@
     
     
     
-

Stichwortverzeichnis

219 Fachbegriffe. Ein Klick führt zum jeweiligen Kapitel/Abschnitt (statt einer im Web bedeutungslosen Seitenzahl wie im gedruckten Register).

A

Absolutbetrag (Modellierungsmuster)Anhang B: Katalog der Modellierungsmuster
Aktivierungsschalter (Modellierungsmuster)Anhang B: Katalog der Modellierungsmuster
AlternativoptimaAnhang E: Glossar und Literatur

B

Bedingte Kopplung (Konjunktion)Anhang B: Katalog der Modellierungsmuster

C

D

DualitätstheorieAnhang E: Glossar und Literatur

E

Entweder-Oder-BedingungAnhang B: Katalog der Modellierungsmuster

F

Falsche Dualwerte (Fehlerbild)Anhang C: Fehlerdiagnose-Handbuch

G

Gestaffelte Preise (stückweise linear)Anhang B: Katalog der Modellierungsmuster
Gini-KoeffizientProjektwerkstatt

H

Herfindahl-IndexProjektwerkstatt

I

IIS (Irreducible Infeasible Subset)Anhang C: Fehlerdiagnose-Handbuch
Implikation (Modellierungsmuster)Anhang B: Katalog der Modellierungsmuster
Importfehler (ortools und highspy)Anhang C: Fehlerdiagnose-Handbuch
Instabile Lösung (Fehlerbild)Anhang C: Fehlerdiagnose-Handbuch

J

K

Kanonische StandardformAnhang E: Glossar und Literatur
Kohärentes RisikomaßAnhang E: Glossar und Literatur

L

Lagrange-MultiplikatorAnhang E: Glossar und Literatur
Laufzeitexplosion (Fehlerbild)Anhang C: Fehlerdiagnose-Handbuch
Lineare Programmierung (LP)Anhang E: Glossar und Literatur

M

Maximum DrawdownAnhang E: Glossar und Literatur

N

Nichtlineare Programmierung (NLP)Anhang E: Glossar und Literatur

O

P

Positiv (semi-)definitAnhang E: Glossar und Literatur

Q

R

S

T

TransaktionskostenAnhang E: Glossar und Literatur

U

Umrüstkosten (Modellierungsmuster)Anhang B: Katalog der Modellierungsmuster
Unbounded (Fehlerbild)Anhang C: Fehlerdiagnose-Handbuch
UnsicherheitsmengeAnhang E: Glossar und Literatur
Unsinniges Ergebnis (Fehlerbild)Anhang C: Fehlerdiagnose-Handbuch

V

Vehicle Routing Problem (VRP)Anhang E: Glossar und Literatur
Verdächtig guter Backtest (Fehlerbild)Anhang C: Fehlerdiagnose-Handbuch
Vertauschte Spalten (Fehlerbild)Anhang C: Fehlerdiagnose-Handbuch

W

Weiche Grenze mit StrafkostenAnhang B: Katalog der Modellierungsmuster
Widersprüchliche Solver (Fehlerbild)Anhang C: Fehlerdiagnose-Handbuch
Wurzel-Zeit-RegelAnhang E: Glossar und Literatur

Z

Zuordnungsproblem (1:1)Anhang B: Katalog der Modellierungsmuster
Zwei-Phasen-Simplex-MethodeAnhang A: Lösungen zu allen Übungsaufgaben
+

Stichwortverzeichnis

219 Fachbegriffe. Ein Klick führt zum jeweiligen Kapitel/Abschnitt (statt einer im Web bedeutungslosen Seitenzahl wie im gedruckten Register).

A

Absolutbetrag (Modellierungsmuster)Anhang B: Katalog der Modellierungsmuster
Aktivierungsschalter (Modellierungsmuster)Anhang B: Katalog der Modellierungsmuster
AlternativoptimaAnhang E: Glossar und Literatur

B

Bedingte Kopplung (Konjunktion)Anhang B: Katalog der Modellierungsmuster

C

D

DualitätstheorieAnhang E: Glossar und Literatur

E

Entweder-Oder-BedingungAnhang B: Katalog der Modellierungsmuster

F

Falsche Dualwerte (Fehlerbild)Anhang C: Fehlerdiagnose-Handbuch

G

Gestaffelte Preise (stückweise linear)Anhang B: Katalog der Modellierungsmuster
Gini-KoeffizientProjektwerkstatt

H

Herfindahl-IndexProjektwerkstatt

I

IIS (Irreducible Infeasible Subset)Anhang C: Fehlerdiagnose-Handbuch
Implikation (Modellierungsmuster)Anhang B: Katalog der Modellierungsmuster
Importfehler (ortools und highspy)Anhang C: Fehlerdiagnose-Handbuch
Instabile Lösung (Fehlerbild)Anhang C: Fehlerdiagnose-Handbuch

J

K

Kanonische StandardformAnhang E: Glossar und Literatur
Kohärentes RisikomaßAnhang E: Glossar und Literatur

L

Lagrange-MultiplikatorAnhang E: Glossar und Literatur
Laufzeitexplosion (Fehlerbild)Anhang C: Fehlerdiagnose-Handbuch
Lineare Programmierung (LP)Anhang E: Glossar und Literatur

M

Maximum DrawdownAnhang E: Glossar und Literatur

N

Nichtlineare Programmierung (NLP)Anhang E: Glossar und Literatur

O

P

Positiv (semi-)definitAnhang E: Glossar und Literatur

Q

R

S

T

TransaktionskostenAnhang E: Glossar und Literatur

U

Umrüstkosten (Modellierungsmuster)Anhang B: Katalog der Modellierungsmuster
Unbounded (Fehlerbild)Anhang C: Fehlerdiagnose-Handbuch
UnsicherheitsmengeAnhang E: Glossar und Literatur
Unsinniges Ergebnis (Fehlerbild)Anhang C: Fehlerdiagnose-Handbuch

V

Vehicle Routing Problem (VRP)Anhang E: Glossar und Literatur
Verdächtig guter Backtest (Fehlerbild)Anhang C: Fehlerdiagnose-Handbuch
Vertauschte Spalten (Fehlerbild)Anhang C: Fehlerdiagnose-Handbuch

W

Weiche Grenze mit StrafkostenAnhang B: Katalog der Modellierungsmuster
Widersprüchliche Solver (Fehlerbild)Anhang C: Fehlerdiagnose-Handbuch
Wurzel-Zeit-RegelAnhang E: Glossar und Literatur

Z

Zuordnungsproblem (1:1)Anhang B: Katalog der Modellierungsmuster
Zwei-Phasen-Simplex-MethodeAnhang A: Lösungen zu allen Übungsaufgaben
diff --git a/Operations_Research_mit_Python_Version_04.md b/Operations_Research_mit_Python_Version_04.md index 705ad32..6a4eb22 100644 --- a/Operations_Research_mit_Python_Version_04.md +++ b/Operations_Research_mit_Python_Version_04.md @@ -1539,8 +1539,13 @@ import pandas as pd from or_kern import (lade_produktionsproblem, loese_mit_glop, pruefe_loesung, schreibe_ergebnis) -EINGABE = "produktionsmix.xlsx" -AUSGABE = "produktionsmix_ergebnis.xlsx" +# Die Mappen liegen NEBEN diesem Programm, nicht im aktuellen +# Arbeitsverzeichnis. Sonst haengt es davon ab, aus welchem Ordner man das +# Skript startet, wo die Dateien landen - und wer es aus der +# Repository-Wurzel aufruft, verstreut sie dort. +HIER = os.path.dirname(os.path.abspath(__file__)) +EINGABE = os.path.join(HIER, "produktionsmix.xlsx") +AUSGABE = os.path.join(HIER, "produktionsmix_ergebnis.xlsx") def lege_beispieldatei_an(pfad: str) -> None: diff --git a/Operations_Research_mit_Python_Version_04.pdf b/Operations_Research_mit_Python_Version_04.pdf index 077f0a4..e86efe9 100644 Binary files a/Operations_Research_mit_Python_Version_04.pdf and b/Operations_Research_mit_Python_Version_04.pdf differ diff --git a/Operations_Research_mit_Python_Version_04/10_Einfuehrung_OR.md b/Operations_Research_mit_Python_Version_04/10_Einfuehrung_OR.md index 78f1804..fea3591 100644 --- a/Operations_Research_mit_Python_Version_04/10_Einfuehrung_OR.md +++ b/Operations_Research_mit_Python_Version_04/10_Einfuehrung_OR.md @@ -966,8 +966,13 @@ import pandas as pd from or_kern import (lade_produktionsproblem, loese_mit_glop, pruefe_loesung, schreibe_ergebnis) -EINGABE = "produktionsmix.xlsx" -AUSGABE = "produktionsmix_ergebnis.xlsx" +# Die Mappen liegen NEBEN diesem Programm, nicht im aktuellen +# Arbeitsverzeichnis. Sonst haengt es davon ab, aus welchem Ordner man das +# Skript startet, wo die Dateien landen - und wer es aus der +# Repository-Wurzel aufruft, verstreut sie dort. +HIER = os.path.dirname(os.path.abspath(__file__)) +EINGABE = os.path.join(HIER, "produktionsmix.xlsx") +AUSGABE = os.path.join(HIER, "produktionsmix_ergebnis.xlsx") def lege_beispieldatei_an(pfad: str) -> None: diff --git a/Operations_Research_mit_Python_Version_04/build_version_04.py b/Operations_Research_mit_Python_Version_04/build_version_04.py index 09544e6..dcae003 100644 --- a/Operations_Research_mit_Python_Version_04/build_version_04.py +++ b/Operations_Research_mit_Python_Version_04/build_version_04.py @@ -1447,7 +1447,13 @@ def spiegle_bilder(html_verz: str) -> None: return ziel_wurzel = os.path.join(html_verz, BILDER_NAME) kopiert = 0 - for wurzel, _verzeichnisse, dateien in os.walk(BILDER_VERZ): + for wurzel, verzeichnisse, dateien in os.walk(BILDER_VERZ): + # Unterverzeichnisse ohne Grafiken gar nicht erst betreten. os.walk + # wuerde sie sonst durchlaufen, und os.makedirs() legte sie am Ziel an - + # so stand ein leeres __pycache__/ auf dem Webserver, obwohl der + # Dateifilter unten korrekt nichts daraus kopiert hat. + verzeichnisse[:] = [v for v in verzeichnisse + if v != "__pycache__" and not v.startswith(".")] rel = os.path.relpath(wurzel, BILDER_VERZ) ziel_verz = ziel_wurzel if rel == "." else os.path.join(ziel_wurzel, rel) os.makedirs(ziel_verz, exist_ok=True) diff --git a/Operations_Research_mit_Python_Version_04_Programme/Excel_Bruecke.py b/Operations_Research_mit_Python_Version_04_Programme/Excel_Bruecke.py index b50b3be..e023ac7 100644 --- a/Operations_Research_mit_Python_Version_04_Programme/Excel_Bruecke.py +++ b/Operations_Research_mit_Python_Version_04_Programme/Excel_Bruecke.py @@ -34,8 +34,13 @@ import pandas as pd from or_kern import (lade_produktionsproblem, loese_mit_glop, pruefe_loesung, schreibe_ergebnis) -EINGABE = "produktionsmix.xlsx" -AUSGABE = "produktionsmix_ergebnis.xlsx" +# Die Mappen liegen NEBEN diesem Programm, nicht im aktuellen +# Arbeitsverzeichnis. Sonst haengt es davon ab, aus welchem Ordner man das +# Skript startet, wo die Dateien landen - und wer es aus der +# Repository-Wurzel aufruft, verstreut sie dort. +HIER = os.path.dirname(os.path.abspath(__file__)) +EINGABE = os.path.join(HIER, "produktionsmix.xlsx") +AUSGABE = os.path.join(HIER, "produktionsmix_ergebnis.xlsx") def lege_beispieldatei_an(pfad: str) -> None: diff --git a/PROGRESS.md b/PROGRESS.md index 81fb452..c76910c 100644 --- a/PROGRESS.md +++ b/PROGRESS.md @@ -77,9 +77,9 @@ sie unerwartet ab, ist etwas kaputtgegangen. | Kapiteldateien | 22 | **36** (31 + 5 Teil-Synthesen) | | Kapitel | 15 | **23** | | Anhänge | 4 | **5** | -| Zeilen im Gesamtdokument | 11 082 | **28 565** | +| Zeilen im Gesamtdokument | 11 082 | **28 570** | | Größe des Gesamtdokuments | 606 KB | **1 622 KB** | -| Hauptüberschriften | 131 | **302** | +| Hauptüberschriften | 131 | **306** | | registrierte Abschnitte | 122 | **296** | | aufgelöste Querverweise | 314 | **825** (0 unaufgelöst) | | Indexmarken | 295 | **328** | @@ -87,7 +87,7 @@ sie unerwartet ab, ist etwas kaputtgegangen. | PDF-Seiten | — | **760** | | Notebooks | — | **25** | | Plotly-Figuren | — | **4** | -| Diagramme (SVG) | 26 | **33**, davon **19** mit Generatorskript (16 Skripte) | +| Diagramme (SVG) | 26 | **33**, davon **19** mit Generatorskript (16 Skripte); keine PNG-Zweitfassung mehr | **Gegenprobe:** `build_version_03.py --check` läuft unverändert durch — Version 03 ist von allen Änderungen unberührt. @@ -1909,6 +1909,36 @@ könnte die Hälfte der Beispiele nicht ausführen. **Damit ist Phase 8 abgeschlossen und der Plan abgearbeitet.** +### ✅ Aufgeräumt — und dabei zwei Funde + +**Die 33 PNG-Zweitfassungen sind weg.** Jedes Diagramm lag doppelt vor, als SVG und als PNG, +und **kein einziges `src=`/`href=` in der Website zeigte je auf ein PNG**. Der Build kopierte +sie trotzdem mit: 3,3 MB im Repository plus 3,3 MB, die bei jeder Veröffentlichung auf den +Webserver gingen, ohne dass sie jemand abrief. Die 15 Generatoren schreiben jetzt nur noch +SVG; die Docstrings sind mitgezogen. Vor dem Löschen geprüft: Jedes PNG hatte sein +gleichnamiges SVG, und alle 33 waren versioniert — rückholbar. + +**Fund 1 dabei: `erzeuge_kap06_gantt.py` folgte als einziger Generator nicht der Konvention.** +Weder `svg.hashsalt` noch `metadata={"Date": None}` waren gesetzt. Sein SVG trug deshalb +einen echten Zeitstempel und bei jedem Lauf andere `clip-path`-IDs — es war **nie** +byteidentisch reproduzierbar, obwohl `CLAUDE.md` genau das für alle Generatoren festhält. +Aufgefallen ist es nur, weil nach der PNG-Umstellung 32 von 33 SVGs bitgleich blieben und +eines nicht. Jetzt byteidentisch über zwei Läufe. + +**Fund 2: `spiegle_bilder()` legte leere Verzeichnisse auf dem Webserver an.** Der +Dateifilter arbeitete korrekt, aber `os.walk` durchlief auch `__pycache__/`, und +`os.makedirs()` erzeugte es am Ziel — ein leerer Ordner in `OR_HTML_04/bilder_04/`. Die +Verzeichnisliste wird jetzt vorher gefiltert. Gegengetestet. + +**`Excel_Bruecke.py` schreibt neben das Skript statt ins Arbeitsverzeichnis.** Es benutzte +blanke relative Namen; wer es aus der Repository-Wurzel startete, verstreute dort +`produktionsmix.xlsx` und `produktionsmix_ergebnis.xlsx`. Jetzt wie die vier anderen +schreibenden Programme über `os.path.dirname(os.path.abspath(__file__))`. Nachgemessen: Lauf +aus der Wurzel legt dort **null** Dateien ab. + +**Und `git gc`:** 653 lose Objekte gepackt, `.git` von 71 MB auf **28 MB** — reines +Repacken, kein Inhalt berührt. + --- ## 8. Commit-Historie des V04-Strangs diff --git a/bilder_04/erzeuge_architektur_diagramme.py b/bilder_04/erzeuge_architektur_diagramme.py index 831bd7a..028f174 100644 --- a/bilder_04/erzeuge_architektur_diagramme.py +++ b/bilder_04/erzeuge_architektur_diagramme.py @@ -4,8 +4,8 @@ """ Erzeugt die beiden Architekturdiagramme fuer den Weg vom Skript zum Betrieb: - bilder_04/kap_praxisfallen_schichten.svg / .png Schichten von or_kern.py - bilder_04/kap_testing_dienst.svg / .png der Dienst und sein Ablauf + bilder_04/kap_praxisfallen_schichten.svg Schichten von or_kern.py + bilder_04/kap_testing_dienst.svg der Dienst und sein Ablauf Beide bilden ab, was in den Programmen tatsaechlich steht - nicht ein allgemeines Architekturschema: @@ -62,7 +62,7 @@ def kasten(punkt: graphviz.Digraph, name: str, text: str, farbe: str, def schreibe(punkt: graphviz.Digraph, name: str) -> None: os.makedirs(BILDER, exist_ok=True) - for endung in ("svg", "png"): + for endung in ("svg",): punkt.format = endung pfad = punkt.render(os.path.join(BILDER, name), cleanup=True) print(f"geschrieben: {pfad}") diff --git a/bilder_04/erzeuge_branch_and_bound.py b/bilder_04/erzeuge_branch_and_bound.py index 3a2cd4a..2a12aa7 100644 --- a/bilder_04/erzeuge_branch_and_bound.py +++ b/bilder_04/erzeuge_branch_and_bound.py @@ -4,7 +4,7 @@ """ Erzeugt den Branch-and-Bound-Suchbaum zum MILP-Kapitel: - bilder_04/kap_milp_suchbaum.svg / .png + bilder_04/kap_milp_suchbaum.svg Gezeichnet wird der Baum der Handrechnung des Kapitels: @@ -172,7 +172,7 @@ def zeichne(knoten, kanten, bestes, zielwert, geloest) -> None: color="#94a3b8", fontsize="10", margin="0.18,0.12") os.makedirs(BILDER, exist_ok=True) - for endung in ("svg", "png"): + for endung in ("svg",): punkt.format = endung pfad = punkt.render(os.path.join(BILDER, "kap_milp_suchbaum"), cleanup=True) print(f"geschrieben: {pfad}") diff --git a/bilder_04/erzeuge_effizienzlinie.py b/bilder_04/erzeuge_effizienzlinie.py index 2ad665b..679e775 100644 --- a/bilder_04/erzeuge_effizienzlinie.py +++ b/bilder_04/erzeuge_effizienzlinie.py @@ -5,7 +5,6 @@ Erzeugt die Figur "Was die Hausregeln kosten" zum Kapitel Markowitz: bilder_04/kap_markowitz_restriktionen.svg statisch, fuer das PDF - bilder_04/kap_markowitz_restriktionen.png Rasterfassung bilder_04/plotly/kap_markowitz_restriktionen.html interaktiv, fuer die Website Gezeigt werden zwei Effizienzlinien desselben Universums: einmal ohne @@ -210,7 +209,7 @@ def zeichne_statisch(frei, gebunden, abstand, risiko_stelle) -> None: figur.tight_layout() os.makedirs(BILDER, exist_ok=True) - for endung in ("svg", "png"): + for endung in ("svg",): pfad = os.path.join(BILDER, f"kap_markowitz_restriktionen.{endung}") figur.savefig(pfad, format=endung, dpi=160, metadata={"Date": None} if endung == "svg" else None) diff --git a/bilder_04/erzeuge_kap06_gantt.py b/bilder_04/erzeuge_kap06_gantt.py index 69f450c..65ee732 100644 --- a/bilder_04/erzeuge_kap06_gantt.py +++ b/bilder_04/erzeuge_kap06_gantt.py @@ -5,7 +5,6 @@ Erzeugt das Gantt-Diagramm zum Job-Shop-Beispiel aus Kapitel 6 in zwei Fassungen: bilder_04/kap06_jobshop_gantt.svg statisch, fuer das PDF - bilder_04/kap06_jobshop_gantt.png statisch, Rasterfassung bilder_04/plotly/kap06_jobshop_gantt.html interaktiv, fuer die Website Die Daten sind identisch mit JobShop_Intervalle.py; geloest wird hier erneut, @@ -27,6 +26,11 @@ import matplotlib.pyplot as plt import plotly.graph_objects as go from ortools.sat.python import cp_model +# Reproduzierbare SVG-Ausgabe (siehe erzeuge_titelseite.py). Dieser Generator +# war als einziger ohne beides - sein SVG trug deshalb einen echten +# Zeitstempel und bei jedem Lauf andere clip-path-IDs. +plt.rcParams["svg.hashsalt"] = "or-mit-python-v04" + # Identisch zu JobShop_Intervalle.py AUFTRAEGE = [ [(0, 3), (1, 2), (2, 2)], # Auftrag 0 @@ -111,9 +115,10 @@ def zeichne_statisch(plan, makespan: int) -> None: figur.tight_layout() os.makedirs(BILDER, exist_ok=True) - for endung in ("svg", "png"): + for endung in ("svg",): pfad = os.path.join(BILDER, f"kap06_jobshop_gantt.{endung}") - figur.savefig(pfad, format=endung, dpi=160) + figur.savefig(pfad, format=endung, dpi=160, + metadata={"Date": None} if endung == "svg" else None) print(f"geschrieben: {pfad}") plt.close(figur) diff --git a/bilder_04/erzeuge_kkt.py b/bilder_04/erzeuge_kkt.py index 47fff47..eccb685 100644 --- a/bilder_04/erzeuge_kkt.py +++ b/bilder_04/erzeuge_kkt.py @@ -4,7 +4,7 @@ """ Erzeugt das KKT-Diagramm zum QP/NLP-Kapitel: - bilder_04/kap_qp_kkt.svg / .png + bilder_04/kap_qp_kkt.svg Zwei Bilder nebeneinander: @@ -216,7 +216,7 @@ if __name__ == "__main__": zeichne_2d(rechts, x_stern, lam) figur.tight_layout() os.makedirs(BILDER, exist_ok=True) - for endung in ("svg", "png"): + for endung in ("svg",): pfad = os.path.join(BILDER, f"kap_qp_kkt.{endung}") figur.savefig(pfad, format=endung, dpi=160, metadata={"Date": None} if endung == "svg" else None) diff --git a/bilder_04/erzeuge_kondition.py b/bilder_04/erzeuge_kondition.py index 4caa085..70127f4 100644 --- a/bilder_04/erzeuge_kondition.py +++ b/bilder_04/erzeuge_kondition.py @@ -5,7 +5,6 @@ Erzeugt das Konditionszahl-Diagramm zum Kapitel Fundament: bilder_04/kap_fundament_kondition.svg statisch, fuer das PDF - bilder_04/kap_fundament_kondition.png Rasterfassung Zwei Aussagen, beide gerechnet und nicht behauptet: @@ -185,7 +184,7 @@ def zeichne(kappas, mediane, maxima, kappa_vorher, kappa_nachher) -> None: figur.tight_layout() os.makedirs(BILDER, exist_ok=True) - for endung in ("svg", "png"): + for endung in ("svg",): pfad = os.path.join(BILDER, f"kap_fundament_kondition.{endung}") figur.savefig(pfad, format=endung, dpi=160, metadata={"Date": None} if endung == "svg" else None) diff --git a/bilder_04/erzeuge_metaheuristik_landschaft.py b/bilder_04/erzeuge_metaheuristik_landschaft.py index 21b8bb7..a8bf51f 100644 --- a/bilder_04/erzeuge_metaheuristik_landschaft.py +++ b/bilder_04/erzeuge_metaheuristik_landschaft.py @@ -5,7 +5,6 @@ Erzeugt das Suchverlauf-Diagramm zum Kapitel Metaheuristiken: bilder_04/kap_metaheuristiken_landschaft.svg statisch, fuer das PDF - bilder_04/kap_metaheuristiken_landschaft.png Rasterfassung bilder_04/plotly/kap_metaheuristiken_verlauf.html interaktiv, fuer die Website Eine Suchlandschaft laesst sich bei 200 Auftraegen nicht zeichnen - der Raum @@ -223,7 +222,7 @@ def zeichne(verlaeufe, start, temperaturreihe) -> None: figur.tight_layout() os.makedirs(BILDER, exist_ok=True) - for endung in ("svg", "png"): + for endung in ("svg",): pfad = os.path.join(BILDER, f"kap_metaheuristiken_landschaft.{endung}") figur.savefig(pfad, format=endung, dpi=160, metadata={"Date": None} if endung == "svg" else None) diff --git a/bilder_04/erzeuge_min_cost_flow.py b/bilder_04/erzeuge_min_cost_flow.py index 7ad3e9e..be7bb86 100644 --- a/bilder_04/erzeuge_min_cost_flow.py +++ b/bilder_04/erzeuge_min_cost_flow.py @@ -4,7 +4,7 @@ """ Erzeugt das Flussdiagramm zum Graphen-Kapitel: - bilder_04/kap_graphen_min_cost_flow.svg / .png + bilder_04/kap_graphen_min_cost_flow.svg Das Vorgaengerbild zeigte die Instanz von Min_Cost_Flow.py korrekt - aber nur die Instanz. Kosten und Kapazitaeten standen an den Kanten, der FLUSS nicht. @@ -128,7 +128,7 @@ def zeichne(gesamtkosten: float, fluss: np.ndarray, preise: np.ndarray) -> None: penwidth=f"{1.0 + 3.0 * menge / kapazitaet:.1f}") os.makedirs(BILDER, exist_ok=True) - for endung in ("svg", "png"): + for endung in ("svg",): punkt.format = endung pfad = punkt.render(os.path.join(BILDER, "kap_graphen_min_cost_flow"), cleanup=True) diff --git a/bilder_04/erzeuge_pareto_front.py b/bilder_04/erzeuge_pareto_front.py index 156f84b..cb59146 100644 --- a/bilder_04/erzeuge_pareto_front.py +++ b/bilder_04/erzeuge_pareto_front.py @@ -5,7 +5,6 @@ Erzeugt das Pareto-Front-Diagramm zum Mehrziel-Kapitel in zwei Fassungen: bilder_04/kap_mehrziel_pareto.svg statisch, fuer das PDF - bilder_04/kap_mehrziel_pareto.png statisch, Rasterfassung bilder_04/plotly/kap_mehrziel_pareto.html interaktiv, fuer die Website Die Instanz ist identisch mit Mehrziel_Pareto.py, und gerechnet wird hier @@ -140,7 +139,7 @@ def zeichne_statisch(front, huelle) -> None: figur.tight_layout() os.makedirs(BILDER, exist_ok=True) - for endung in ("svg", "png"): + for endung in ("svg",): pfad = os.path.join(BILDER, f"kap_mehrziel_pareto.{endung}") figur.savefig(pfad, format=endung, dpi=160, metadata={"Date": None} if endung == "svg" else None) diff --git a/bilder_04/erzeuge_polyeder.py b/bilder_04/erzeuge_polyeder.py index b30192d..86a86cf 100644 --- a/bilder_04/erzeuge_polyeder.py +++ b/bilder_04/erzeuge_polyeder.py @@ -4,8 +4,8 @@ """ Erzeugt die beiden Polyeder-Diagramme zum Fundament- und zum LP-Kapitel: - bilder_04/kap_fundament_polyeder.svg / .png der zulaessige Bereich - bilder_04/kap_lp_simplex_ecken.svg / .png der Eckenlauf des Simplex + bilder_04/kap_fundament_polyeder.svg der zulaessige Bereich + bilder_04/kap_lp_simplex_ecken.svg der Eckenlauf des Simplex Beide zeigen DASSELBE Modell - das Bot-Allokationsproblem, das sich durch die ersten Kapitel zieht: @@ -165,7 +165,7 @@ def zeichne_rahmen(achse, ecken: np.ndarray) -> None: def schreibe(figur, name: str) -> None: os.makedirs(BILDER, exist_ok=True) - for endung in ("svg", "png"): + for endung in ("svg",): pfad = os.path.join(BILDER, f"{name}.{endung}") figur.savefig(pfad, format=endung, dpi=160, metadata={"Date": None} if endung == "svg" else None) diff --git a/bilder_04/erzeuge_runden.py b/bilder_04/erzeuge_runden.py index 3d47b3c..684561d 100644 --- a/bilder_04/erzeuge_runden.py +++ b/bilder_04/erzeuge_runden.py @@ -5,7 +5,6 @@ Erzeugt das Diagramm "Warum Runden scheitert" zum MILP-Kapitel: bilder_04/kap_milp_runden.svg statisch, fuer das PDF - bilder_04/kap_milp_runden.png Rasterfassung Zwei Bilder nebeneinander, beide aus dem Kapitel selbst: @@ -213,7 +212,7 @@ def zeichne(zeilen) -> None: figur.tight_layout() os.makedirs(BILDER, exist_ok=True) - for endung in ("svg", "png"): + for endung in ("svg",): pfad = os.path.join(BILDER, f"kap_milp_runden.{endung}") figur.savefig(pfad, format=endung, dpi=160, metadata={"Date": None} if endung == "svg" else None) diff --git a/bilder_04/erzeuge_solverwahl_diagramme.py b/bilder_04/erzeuge_solverwahl_diagramme.py index 0439740..1d3ed89 100644 --- a/bilder_04/erzeuge_solverwahl_diagramme.py +++ b/bilder_04/erzeuge_solverwahl_diagramme.py @@ -5,8 +5,8 @@ Erzeugt die beiden Entscheidungs-Flussdiagramme "Welches Werkzeug passt zu meinem Problem?" fuer die Auftakte von Teil II und Teil III: - bilder_04/teil2_solverwahl.svg / .png deterministische Verfahren - bilder_04/teil3_solverwahl.svg / .png Nichtlinearitaet und Unsicherheit + bilder_04/teil2_solverwahl.svg deterministische Verfahren + bilder_04/teil3_solverwahl.svg Nichtlinearitaet und Unsicherheit Beide entstehen mit Graphviz. Die Farben folgen der Buchpalette (Indigo, Cyan, Violett, Gruen, Amber), die Kastenform codiert die Rolle: @@ -57,7 +57,7 @@ def empfehlung(punkt: graphviz.Digraph, name: str, text: str, farbe: str) -> Non def schreibe(punkt: graphviz.Digraph, name: str) -> None: os.makedirs(BILDER, exist_ok=True) - for endung in ("svg", "png"): + for endung in ("svg",): punkt.format = endung pfad = punkt.render(os.path.join(BILDER, name), cleanup=True) print(f"geschrieben: {pfad}") diff --git a/bilder_04/erzeuge_var_cvar.py b/bilder_04/erzeuge_var_cvar.py index 6d9e5fa..55c7f83 100644 --- a/bilder_04/erzeuge_var_cvar.py +++ b/bilder_04/erzeuge_var_cvar.py @@ -5,7 +5,6 @@ Erzeugt das VaR/CVaR-Diagramm zum Kapitel CVaR: bilder_04/kap_cvar_var_vergleich.svg statisch, fuer das PDF - bilder_04/kap_cvar_var_vergleich.png Rasterfassung Gezeigt wird die Verteilung simulierter Tagesrenditen mit beiden Kennzahlen: Der VaR ist die SCHWELLE, unter die nur 5 % der Tage fallen; der CVaR ist der @@ -142,7 +141,7 @@ def zeichne(werte: np.ndarray, var: float, cvar: float) -> None: figur.tight_layout() os.makedirs(BILDER, exist_ok=True) - for endung in ("svg", "png"): + for endung in ("svg",): pfad = os.path.join(BILDER, f"kap_cvar_var_vergleich.{endung}") figur.savefig(pfad, format=endung, dpi=160, metadata={"Date": None} if endung == "svg" else None) diff --git a/bilder_04/erzeuge_vrp_touren.py b/bilder_04/erzeuge_vrp_touren.py index 29c326c..d14ef05 100644 --- a/bilder_04/erzeuge_vrp_touren.py +++ b/bilder_04/erzeuge_vrp_touren.py @@ -4,7 +4,7 @@ """ Erzeugt die Tourenkarte zum Graphen-Kapitel: - bilder_04/kap_graphen_vrp_touren.svg / .png + bilder_04/kap_graphen_vrp_touren.svg Das Vorgaengerbild war ein Schema: zwei Touren, vier Kunden, Zeitfenster in Uhrzeiten. Die Instanz des Kapitels hat 16 Kunden, vier Fahrzeuge und @@ -170,7 +170,7 @@ def zeichne(koordinaten, touren) -> None: figur.tight_layout() os.makedirs(BILDER, exist_ok=True) - for endung in ("svg", "png"): + for endung in ("svg",): pfad = os.path.join(BILDER, f"kap_graphen_vrp_touren.{endung}") figur.savefig(pfad, format=endung, dpi=160, bbox_inches="tight", metadata={"Date": None} if endung == "svg" else None) diff --git a/bilder_04/erzeuge_wirkung.py b/bilder_04/erzeuge_wirkung.py index cbee3b2..9fc985c 100644 --- a/bilder_04/erzeuge_wirkung.py +++ b/bilder_04/erzeuge_wirkung.py @@ -5,7 +5,6 @@ Erzeugt das Wasserfalldiagramm zum Kapitel Supply-Chain und Energieeinsatz: bilder_04/kap_supplychain_wirkung.svg statisch, fuer das PDF - bilder_04/kap_supplychain_wirkung.png Rasterfassung Die Frage, die es beantwortet, ist die des Managements: WOFUER genau kostet der Erwartungswert-Plan 149 % mehr? Die Tabelle im Kapitel nennt nur die @@ -228,7 +227,7 @@ def zeichne(zwei: dict, erw: dict) -> None: figur.tight_layout() os.makedirs(BILDER, exist_ok=True) - for endung in ("svg", "png"): + for endung in ("svg",): pfad = os.path.join(BILDER, f"kap_supplychain_wirkung.{endung}") figur.savefig(pfad, format=endung, dpi=160, metadata={"Date": None} if endung == "svg" else None) diff --git a/bilder_04/kap01_analytik_reifegrad.png b/bilder_04/kap01_analytik_reifegrad.png deleted file mode 100644 index 9ef9840..0000000 Binary files a/bilder_04/kap01_analytik_reifegrad.png and /dev/null differ diff --git a/bilder_04/kap01_vier_bausteine.png b/bilder_04/kap01_vier_bausteine.png deleted file mode 100644 index f0b51a3..0000000 Binary files a/bilder_04/kap01_vier_bausteine.png and /dev/null differ diff --git a/bilder_04/kap02_konvexitaet.png b/bilder_04/kap02_konvexitaet.png deleted file mode 100644 index 6bbd0cc..0000000 Binary files a/bilder_04/kap02_konvexitaet.png and /dev/null differ diff --git a/bilder_04/kap03_solver_architektur.png b/bilder_04/kap03_solver_architektur.png deleted file mode 100644 index 79fa438..0000000 Binary files a/bilder_04/kap03_solver_architektur.png and /dev/null differ diff --git a/bilder_04/kap04_primal_dual.png b/bilder_04/kap04_primal_dual.png deleted file mode 100644 index 8557112..0000000 Binary files a/bilder_04/kap04_primal_dual.png and /dev/null differ diff --git a/bilder_04/kap06_cp_sat_propagation.png b/bilder_04/kap06_cp_sat_propagation.png deleted file mode 100644 index 64feb08..0000000 Binary files a/bilder_04/kap06_cp_sat_propagation.png and /dev/null differ diff --git a/bilder_04/kap06_jobshop_gantt.png b/bilder_04/kap06_jobshop_gantt.png deleted file mode 100644 index a6b1def..0000000 Binary files a/bilder_04/kap06_jobshop_gantt.png and /dev/null differ diff --git a/bilder_04/kap06_jobshop_gantt.svg b/bilder_04/kap06_jobshop_gantt.svg index 7765306..1bccc9b 100644 --- a/bilder_04/kap06_jobshop_gantt.svg +++ b/bilder_04/kap06_jobshop_gantt.svg @@ -6,7 +6,6 @@ - 2026-09-07T01:51:51.979555 image/svg+xml @@ -43,7 +42,7 @@ L 326.435455 32.849091 L 326.435455 64.809875 L 174.248182 64.809875 z -" clip-path="url(#p448fd06892)" style="fill: #4338ca; stroke: #ffffff; stroke-width: 1.2; stroke-linejoin: miter"/> +" clip-path="url(#pce73ba693e)" style="fill: #4338ca; stroke: #ffffff; stroke-width: 1.2; stroke-linejoin: miter"/> +" clip-path="url(#pce73ba693e)" style="fill: #4338ca; stroke: #ffffff; stroke-width: 1.2; stroke-linejoin: miter"/> +" clip-path="url(#pce73ba693e)" style="fill: #4338ca; stroke: #ffffff; stroke-width: 1.2; stroke-linejoin: miter"/> +" clip-path="url(#pce73ba693e)" style="fill: #0891b2; stroke: #ffffff; stroke-width: 1.2; stroke-linejoin: miter"/> +" clip-path="url(#pce73ba693e)" style="fill: #0891b2; stroke: #ffffff; stroke-width: 1.2; stroke-linejoin: miter"/> +" clip-path="url(#pce73ba693e)" style="fill: #0891b2; stroke: #ffffff; stroke-width: 1.2; stroke-linejoin: miter"/> +" clip-path="url(#pce73ba693e)" style="fill: #b45309; stroke: #ffffff; stroke-width: 1.2; stroke-linejoin: miter"/> +" clip-path="url(#pce73ba693e)" style="fill: #b45309; stroke: #ffffff; stroke-width: 1.2; stroke-linejoin: miter"/> +" clip-path="url(#pce73ba693e)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> - - + @@ -152,11 +151,11 @@ z +" clip-path="url(#pce73ba693e)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> - + @@ -186,11 +185,11 @@ z +" clip-path="url(#pce73ba693e)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> - + @@ -230,11 +229,11 @@ z +" clip-path="url(#pce73ba693e)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> - + @@ -282,11 +281,11 @@ z +" clip-path="url(#pce73ba693e)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> - + @@ -321,11 +320,11 @@ z +" clip-path="url(#pce73ba693e)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> - + @@ -366,11 +365,11 @@ z +" clip-path="url(#pce73ba693e)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> - + @@ -416,11 +415,11 @@ z +" clip-path="url(#pce73ba693e)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> - + @@ -446,11 +445,11 @@ z +" clip-path="url(#pce73ba693e)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> - + @@ -505,11 +504,11 @@ z +" clip-path="url(#pce73ba693e)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> - + @@ -555,11 +554,11 @@ z +" clip-path="url(#pce73ba693e)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> - + @@ -574,11 +573,11 @@ L 580.080909 25.44 +" clip-path="url(#pce73ba693e)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> - + @@ -724,12 +723,12 @@ z - - + @@ -843,7 +842,7 @@ z - + @@ -884,7 +883,7 @@ z - + @@ -1320,7 +1319,7 @@ z - + diff --git a/bilder_04/kap09_unsicherheit_ansaetze.png b/bilder_04/kap09_unsicherheit_ansaetze.png deleted file mode 100644 index 6a40ea0..0000000 Binary files a/bilder_04/kap09_unsicherheit_ansaetze.png and /dev/null differ diff --git a/bilder_04/kap10_zustandskette.png b/bilder_04/kap10_zustandskette.png deleted file mode 100644 index cef457c..0000000 Binary files a/bilder_04/kap10_zustandskette.png and /dev/null differ diff --git a/bilder_04/kap11_ledoit_wolf_shrinkage.png b/bilder_04/kap11_ledoit_wolf_shrinkage.png deleted file mode 100644 index e5b82f7..0000000 Binary files a/bilder_04/kap11_ledoit_wolf_shrinkage.png and /dev/null differ diff --git a/bilder_04/kap12_efficient_frontier.png b/bilder_04/kap12_efficient_frontier.png deleted file mode 100644 index d8e04c5..0000000 Binary files a/bilder_04/kap12_efficient_frontier.png and /dev/null differ diff --git a/bilder_04/kap13_cvar_zielfunktion.png b/bilder_04/kap13_cvar_zielfunktion.png deleted file mode 100644 index 5324d42..0000000 Binary files a/bilder_04/kap13_cvar_zielfunktion.png and /dev/null differ diff --git a/bilder_04/kap14_engine_overview.png b/bilder_04/kap14_engine_overview.png deleted file mode 100644 index c9886a4..0000000 Binary files a/bilder_04/kap14_engine_overview.png and /dev/null differ diff --git a/bilder_04/kap15_or_plattform.png b/bilder_04/kap15_or_plattform.png deleted file mode 100644 index 20f63a4..0000000 Binary files a/bilder_04/kap15_or_plattform.png and /dev/null differ diff --git a/bilder_04/kap15_praxisfallen.png b/bilder_04/kap15_praxisfallen.png deleted file mode 100644 index 4a904ab..0000000 Binary files a/bilder_04/kap15_praxisfallen.png and /dev/null differ diff --git a/bilder_04/kap_cvar_var_vergleich.png b/bilder_04/kap_cvar_var_vergleich.png deleted file mode 100644 index 0bbf9a0..0000000 Binary files a/bilder_04/kap_cvar_var_vergleich.png and /dev/null differ diff --git a/bilder_04/kap_fundament_kondition.png b/bilder_04/kap_fundament_kondition.png deleted file mode 100644 index a82df02..0000000 Binary files a/bilder_04/kap_fundament_kondition.png and /dev/null differ diff --git a/bilder_04/kap_fundament_polyeder.png b/bilder_04/kap_fundament_polyeder.png deleted file mode 100644 index d4bb3dc..0000000 Binary files a/bilder_04/kap_fundament_polyeder.png and /dev/null differ diff --git a/bilder_04/kap_graphen_min_cost_flow.png b/bilder_04/kap_graphen_min_cost_flow.png deleted file mode 100644 index 1800e77..0000000 Binary files a/bilder_04/kap_graphen_min_cost_flow.png and /dev/null differ diff --git a/bilder_04/kap_graphen_vrp_touren.png b/bilder_04/kap_graphen_vrp_touren.png deleted file mode 100644 index 9572a19..0000000 Binary files a/bilder_04/kap_graphen_vrp_touren.png and /dev/null differ diff --git a/bilder_04/kap_lp_simplex_ecken.png b/bilder_04/kap_lp_simplex_ecken.png deleted file mode 100644 index 6c93a53..0000000 Binary files a/bilder_04/kap_lp_simplex_ecken.png and /dev/null differ diff --git a/bilder_04/kap_markowitz_restriktionen.png b/bilder_04/kap_markowitz_restriktionen.png deleted file mode 100644 index 96d7e9a..0000000 Binary files a/bilder_04/kap_markowitz_restriktionen.png and /dev/null differ diff --git a/bilder_04/kap_mehrziel_pareto.png b/bilder_04/kap_mehrziel_pareto.png deleted file mode 100644 index 324afd5..0000000 Binary files a/bilder_04/kap_mehrziel_pareto.png and /dev/null differ diff --git a/bilder_04/kap_metaheuristiken_landschaft.png b/bilder_04/kap_metaheuristiken_landschaft.png deleted file mode 100644 index df8e89a..0000000 Binary files a/bilder_04/kap_metaheuristiken_landschaft.png and /dev/null differ diff --git a/bilder_04/kap_milp_runden.png b/bilder_04/kap_milp_runden.png deleted file mode 100644 index 5d466f3..0000000 Binary files a/bilder_04/kap_milp_runden.png and /dev/null differ diff --git a/bilder_04/kap_milp_suchbaum.png b/bilder_04/kap_milp_suchbaum.png deleted file mode 100644 index bec5d10..0000000 Binary files a/bilder_04/kap_milp_suchbaum.png and /dev/null differ diff --git a/bilder_04/kap_praxisfallen_schichten.png b/bilder_04/kap_praxisfallen_schichten.png deleted file mode 100644 index df8206f..0000000 Binary files a/bilder_04/kap_praxisfallen_schichten.png and /dev/null differ diff --git a/bilder_04/kap_qp_kkt.png b/bilder_04/kap_qp_kkt.png deleted file mode 100644 index 2e4d95b..0000000 Binary files a/bilder_04/kap_qp_kkt.png and /dev/null differ diff --git a/bilder_04/kap_supplychain_wirkung.png b/bilder_04/kap_supplychain_wirkung.png deleted file mode 100644 index 91c255f..0000000 Binary files a/bilder_04/kap_supplychain_wirkung.png and /dev/null differ diff --git a/bilder_04/kap_testing_dienst.png b/bilder_04/kap_testing_dienst.png deleted file mode 100644 index e4061ac..0000000 Binary files a/bilder_04/kap_testing_dienst.png and /dev/null differ diff --git a/bilder_04/teil2_solverwahl.png b/bilder_04/teil2_solverwahl.png deleted file mode 100644 index 3c4dc43..0000000 Binary files a/bilder_04/teil2_solverwahl.png and /dev/null differ diff --git a/bilder_04/teil3_solverwahl.png b/bilder_04/teil3_solverwahl.png deleted file mode 100644 index 72692b5..0000000 Binary files a/bilder_04/teil3_solverwahl.png and /dev/null differ diff --git a/bilder_04/titelseite.png b/bilder_04/titelseite.png deleted file mode 100644 index 31e7f2a..0000000 Binary files a/bilder_04/titelseite.png and /dev/null differ