Aufgeraeumt: 33 PNG-Zweitfassungen, Bau-Ueberbleibsel, Ausgabepfade

Drei Aufraeumarbeiten - und zwei Funde, die dabei auffielen.

1. DIE 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 Veroeffentlichung auf den Webserver gingen. Die 15 Generatoren
schreiben jetzt nur noch SVG, die Docstrings sind mitgezogen. Vor dem
Loeschen geprueft: Jedes PNG hatte sein gleichnamiges SVG, alle 33 waren
versioniert.

FUND 1: erzeuge_kap06_gantt.py folgte als einziger Generator nicht der
Konvention - weder svg.hashsalt noch metadata={"Date": None}. Sein SVG trug
einen echten Zeitstempel und bei jedem Lauf andere clip-path-IDs, war also
nie byteidentisch reproduzierbar, obwohl CLAUDE.md genau das fuer alle
Generatoren festhaelt. Aufgefallen nur, weil nach der PNG-Umstellung 32 von
33 SVGs bitgleich blieben und eines nicht. Jetzt byteidentisch ueber zwei
Laeufe.

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. Die Verzeichnisliste wird jetzt vorher
gefiltert. Gegengetestet.

2. BAU-UEBERBLEIBSEL entfernt (alle ignoriert und neu erzeugbar):
svg-inkscape/, build_v04.log, .pytest_cache/, Programme/output/, vier
__pycache__/ und die Excel-Mappen. Arbeitsbaum 36 -> 33 MB, danach null
ignorierte Ueberbleibsel.

3. 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 ueber os.path.dirname(os.path.abspath(__file__)). Nachgemessen:
Lauf aus der Wurzel legt dort null Dateien ab.

Ausserdem git gc: 653 lose Objekte gepackt, .git von 71 MB auf 28 MB -
reines Repacken, kein Inhalt beruehrt.

Geprueft: alle 33 im Buch referenzierten SVGs vorhanden, in Quelle und
Website; 16 Generatoren fehlerfrei; keine fehlenden Bilder im LaTeX-Lauf;
33 pytest-Tests; PDF unveraendert 760 Seiten.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
dschlueter 2026-09-08 14:22:26 +02:00
commit 360912dbfa
97 changed files with 322 additions and 248 deletions

View file

@ -139,7 +139,9 @@ keinen Generator — dort kann nichts driften. Das Kriterium steht in `PROGRESS.
Abschnitt 6c. Abschnitt 6c.
Konventionen der Generatoren: `plt.rcParams["svg.hashsalt"] = "or-mit-python-v04"` und 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. Zufallsstrom, wird die Ziehungsreihenfolge des Buchprogramms nachgespielt.
## Plotly-Figuren ## Plotly-Figuren

View file

@ -405,8 +405,13 @@
"from or_kern import (lade_produktionsproblem, loese_mit_glop, pruefe_loesung,\n", "from or_kern import (lade_produktionsproblem, loese_mit_glop, pruefe_loesung,\n",
" schreibe_ergebnis)\n", " schreibe_ergebnis)\n",
"\n", "\n",
"EINGABE = \"produktionsmix.xlsx\"\n", "# Die Mappen liegen NEBEN diesem Programm, nicht im aktuellen\n",
"AUSGABE = \"produktionsmix_ergebnis.xlsx\"\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",
"\n", "\n",
"def lege_beispieldatei_an(pfad: str) -> None:\n", "def lege_beispieldatei_an(pfad: str) -> None:\n",

View file

@ -405,8 +405,13 @@
"from or_kern import (lade_produktionsproblem, loese_mit_glop, pruefe_loesung,\n", "from or_kern import (lade_produktionsproblem, loese_mit_glop, pruefe_loesung,\n",
" schreibe_ergebnis)\n", " schreibe_ergebnis)\n",
"\n", "\n",
"EINGABE = \"produktionsmix.xlsx\"\n", "# Die Mappen liegen NEBEN diesem Programm, nicht im aktuellen\n",
"AUSGABE = \"produktionsmix_ergebnis.xlsx\"\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",
"\n", "\n",
"def lege_beispieldatei_an(pfad: str) -> None:\n", "def lege_beispieldatei_an(pfad: str) -> None:\n",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

View file

@ -6,7 +6,6 @@
<rdf:RDF xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:RDF xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<cc:Work> <cc:Work>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/> <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
<dc:date>2026-09-07T01:51:51.979555</dc:date>
<dc:format>image/svg+xml</dc:format> <dc:format>image/svg+xml</dc:format>
<dc:creator> <dc:creator>
<cc:Agent> <cc:Agent>
@ -43,7 +42,7 @@ L 326.435455 32.849091
L 326.435455 64.809875 L 326.435455 64.809875
L 174.248182 64.809875 L 174.248182 64.809875
z 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"/>
</g> </g>
<g id="patch_4"> <g id="patch_4">
<path d="M 326.435455 90.959608 <path d="M 326.435455 90.959608
@ -51,7 +50,7 @@ L 427.893636 90.959608
L 427.893636 122.920392 L 427.893636 122.920392
L 326.435455 122.920392 L 326.435455 122.920392
z 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"/>
</g> </g>
<g id="patch_5"> <g id="patch_5">
<path d="M 427.893636 149.070125 <path d="M 427.893636 149.070125
@ -59,7 +58,7 @@ L 529.351818 149.070125
L 529.351818 181.030909 L 529.351818 181.030909
L 427.893636 181.030909 L 427.893636 181.030909
z 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"/>
</g> </g>
<g id="patch_6"> <g id="patch_6">
<path d="M 72.79 32.849091 <path d="M 72.79 32.849091
@ -67,7 +66,7 @@ L 174.248182 32.849091
L 174.248182 64.809875 L 174.248182 64.809875
L 72.79 64.809875 L 72.79 64.809875
z z
" clip-path="url(#p448fd06892)" 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"/>
</g> </g>
<g id="patch_7"> <g id="patch_7">
<path d="M 174.248182 149.070125 <path d="M 174.248182 149.070125
@ -75,7 +74,7 @@ L 224.977273 149.070125
L 224.977273 181.030909 L 224.977273 181.030909
L 174.248182 181.030909 L 174.248182 181.030909
z z
" clip-path="url(#p448fd06892)" 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"/>
</g> </g>
<g id="patch_8"> <g id="patch_8">
<path d="M 427.893636 90.959608 <path d="M 427.893636 90.959608
@ -83,7 +82,7 @@ L 630.81 90.959608
L 630.81 122.920392 L 630.81 122.920392
L 427.893636 122.920392 L 427.893636 122.920392
z z
" clip-path="url(#p448fd06892)" 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"/>
</g> </g>
<g id="patch_9"> <g id="patch_9">
<path d="M 72.79 90.959608 <path d="M 72.79 90.959608
@ -91,7 +90,7 @@ L 275.706364 90.959608
L 275.706364 122.920392 L 275.706364 122.920392
L 72.79 122.920392 L 72.79 122.920392
z z
" clip-path="url(#p448fd06892)" 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"/>
</g> </g>
<g id="patch_10"> <g id="patch_10">
<path d="M 275.706364 149.070125 <path d="M 275.706364 149.070125
@ -99,23 +98,23 @@ L 427.893636 149.070125
L 427.893636 181.030909 L 427.893636 181.030909
L 275.706364 181.030909 L 275.706364 181.030909
z z
" clip-path="url(#p448fd06892)" 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"/>
</g> </g>
<g id="matplotlib.axis_1"> <g id="matplotlib.axis_1">
<g id="xtick_1"> <g id="xtick_1">
<g id="line2d_1"> <g id="line2d_1">
<path d="M 72.79 188.44 <path d="M 72.79 188.44
L 72.79 25.44 L 72.79 25.44
" clip-path="url(#p448fd06892)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> " 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"/>
</g> </g>
<g id="line2d_2"> <g id="line2d_2">
<defs> <defs>
<path id="mfeb5fcddc7" d="M 0 0 <path id="mf0a04b41f8" d="M 0 0
L 0 3.5 L 0 3.5
" style="stroke: #000000; stroke-width: 0.8"/> " style="stroke: #000000; stroke-width: 0.8"/>
</defs> </defs>
<g> <g>
<use xlink:href="#mfeb5fcddc7" x="72.79" y="188.44" style="stroke: #000000; stroke-width: 0.8"/> <use xlink:href="#mf0a04b41f8" x="72.79" y="188.44" style="stroke: #000000; stroke-width: 0.8"/>
</g> </g>
</g> </g>
<g id="text_1"> <g id="text_1">
@ -152,11 +151,11 @@ z
<g id="line2d_3"> <g id="line2d_3">
<path d="M 123.519091 188.44 <path d="M 123.519091 188.44
L 123.519091 25.44 L 123.519091 25.44
" clip-path="url(#p448fd06892)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> " 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"/>
</g> </g>
<g id="line2d_4"> <g id="line2d_4">
<g> <g>
<use xlink:href="#mfeb5fcddc7" x="123.519091" y="188.44" style="stroke: #000000; stroke-width: 0.8"/> <use xlink:href="#mf0a04b41f8" x="123.519091" y="188.44" style="stroke: #000000; stroke-width: 0.8"/>
</g> </g>
</g> </g>
<g id="text_2"> <g id="text_2">
@ -186,11 +185,11 @@ z
<g id="line2d_5"> <g id="line2d_5">
<path d="M 174.248182 188.44 <path d="M 174.248182 188.44
L 174.248182 25.44 L 174.248182 25.44
" clip-path="url(#p448fd06892)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> " 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"/>
</g> </g>
<g id="line2d_6"> <g id="line2d_6">
<g> <g>
<use xlink:href="#mfeb5fcddc7" x="174.248182" y="188.44" style="stroke: #000000; stroke-width: 0.8"/> <use xlink:href="#mf0a04b41f8" x="174.248182" y="188.44" style="stroke: #000000; stroke-width: 0.8"/>
</g> </g>
</g> </g>
<g id="text_3"> <g id="text_3">
@ -230,11 +229,11 @@ z
<g id="line2d_7"> <g id="line2d_7">
<path d="M 224.977273 188.44 <path d="M 224.977273 188.44
L 224.977273 25.44 L 224.977273 25.44
" clip-path="url(#p448fd06892)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> " 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"/>
</g> </g>
<g id="line2d_8"> <g id="line2d_8">
<g> <g>
<use xlink:href="#mfeb5fcddc7" x="224.977273" y="188.44" style="stroke: #000000; stroke-width: 0.8"/> <use xlink:href="#mf0a04b41f8" x="224.977273" y="188.44" style="stroke: #000000; stroke-width: 0.8"/>
</g> </g>
</g> </g>
<g id="text_4"> <g id="text_4">
@ -282,11 +281,11 @@ z
<g id="line2d_9"> <g id="line2d_9">
<path d="M 275.706364 188.44 <path d="M 275.706364 188.44
L 275.706364 25.44 L 275.706364 25.44
" clip-path="url(#p448fd06892)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> " 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"/>
</g> </g>
<g id="line2d_10"> <g id="line2d_10">
<g> <g>
<use xlink:href="#mfeb5fcddc7" x="275.706364" y="188.44" style="stroke: #000000; stroke-width: 0.8"/> <use xlink:href="#mf0a04b41f8" x="275.706364" y="188.44" style="stroke: #000000; stroke-width: 0.8"/>
</g> </g>
</g> </g>
<g id="text_5"> <g id="text_5">
@ -321,11 +320,11 @@ z
<g id="line2d_11"> <g id="line2d_11">
<path d="M 326.435455 188.44 <path d="M 326.435455 188.44
L 326.435455 25.44 L 326.435455 25.44
" clip-path="url(#p448fd06892)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> " 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"/>
</g> </g>
<g id="line2d_12"> <g id="line2d_12">
<g> <g>
<use xlink:href="#mfeb5fcddc7" x="326.435455" y="188.44" style="stroke: #000000; stroke-width: 0.8"/> <use xlink:href="#mf0a04b41f8" x="326.435455" y="188.44" style="stroke: #000000; stroke-width: 0.8"/>
</g> </g>
</g> </g>
<g id="text_6"> <g id="text_6">
@ -366,11 +365,11 @@ z
<g id="line2d_13"> <g id="line2d_13">
<path d="M 377.164545 188.44 <path d="M 377.164545 188.44
L 377.164545 25.44 L 377.164545 25.44
" clip-path="url(#p448fd06892)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> " 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"/>
</g> </g>
<g id="line2d_14"> <g id="line2d_14">
<g> <g>
<use xlink:href="#mfeb5fcddc7" x="377.164545" y="188.44" style="stroke: #000000; stroke-width: 0.8"/> <use xlink:href="#mf0a04b41f8" x="377.164545" y="188.44" style="stroke: #000000; stroke-width: 0.8"/>
</g> </g>
</g> </g>
<g id="text_7"> <g id="text_7">
@ -416,11 +415,11 @@ z
<g id="line2d_15"> <g id="line2d_15">
<path d="M 427.893636 188.44 <path d="M 427.893636 188.44
L 427.893636 25.44 L 427.893636 25.44
" clip-path="url(#p448fd06892)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> " 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"/>
</g> </g>
<g id="line2d_16"> <g id="line2d_16">
<g> <g>
<use xlink:href="#mfeb5fcddc7" x="427.893636" y="188.44" style="stroke: #000000; stroke-width: 0.8"/> <use xlink:href="#mf0a04b41f8" x="427.893636" y="188.44" style="stroke: #000000; stroke-width: 0.8"/>
</g> </g>
</g> </g>
<g id="text_8"> <g id="text_8">
@ -446,11 +445,11 @@ z
<g id="line2d_17"> <g id="line2d_17">
<path d="M 478.622727 188.44 <path d="M 478.622727 188.44
L 478.622727 25.44 L 478.622727 25.44
" clip-path="url(#p448fd06892)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> " 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"/>
</g> </g>
<g id="line2d_18"> <g id="line2d_18">
<g> <g>
<use xlink:href="#mfeb5fcddc7" x="478.622727" y="188.44" style="stroke: #000000; stroke-width: 0.8"/> <use xlink:href="#mf0a04b41f8" x="478.622727" y="188.44" style="stroke: #000000; stroke-width: 0.8"/>
</g> </g>
</g> </g>
<g id="text_9"> <g id="text_9">
@ -505,11 +504,11 @@ z
<g id="line2d_19"> <g id="line2d_19">
<path d="M 529.351818 188.44 <path d="M 529.351818 188.44
L 529.351818 25.44 L 529.351818 25.44
" clip-path="url(#p448fd06892)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> " 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"/>
</g> </g>
<g id="line2d_20"> <g id="line2d_20">
<g> <g>
<use xlink:href="#mfeb5fcddc7" x="529.351818" y="188.44" style="stroke: #000000; stroke-width: 0.8"/> <use xlink:href="#mf0a04b41f8" x="529.351818" y="188.44" style="stroke: #000000; stroke-width: 0.8"/>
</g> </g>
</g> </g>
<g id="text_10"> <g id="text_10">
@ -555,11 +554,11 @@ z
<g id="line2d_21"> <g id="line2d_21">
<path d="M 580.080909 188.44 <path d="M 580.080909 188.44
L 580.080909 25.44 L 580.080909 25.44
" clip-path="url(#p448fd06892)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> " 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"/>
</g> </g>
<g id="line2d_22"> <g id="line2d_22">
<g> <g>
<use xlink:href="#mfeb5fcddc7" x="580.080909" y="188.44" style="stroke: #000000; stroke-width: 0.8"/> <use xlink:href="#mf0a04b41f8" x="580.080909" y="188.44" style="stroke: #000000; stroke-width: 0.8"/>
</g> </g>
</g> </g>
<g id="text_11"> <g id="text_11">
@ -574,11 +573,11 @@ L 580.080909 25.44
<g id="line2d_23"> <g id="line2d_23">
<path d="M 630.81 188.44 <path d="M 630.81 188.44
L 630.81 25.44 L 630.81 25.44
" clip-path="url(#p448fd06892)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> " 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"/>
</g> </g>
<g id="line2d_24"> <g id="line2d_24">
<g> <g>
<use xlink:href="#mfeb5fcddc7" x="630.81" y="188.44" style="stroke: #000000; stroke-width: 0.8"/> <use xlink:href="#mf0a04b41f8" x="630.81" y="188.44" style="stroke: #000000; stroke-width: 0.8"/>
</g> </g>
</g> </g>
<g id="text_12"> <g id="text_12">
@ -724,12 +723,12 @@ z
<g id="ytick_1"> <g id="ytick_1">
<g id="line2d_25"> <g id="line2d_25">
<defs> <defs>
<path id="m2b8ef16b3a" d="M 0 0 <path id="mc0b9ff744f" d="M 0 0
L -3.5 0 L -3.5 0
" style="stroke: #000000; stroke-width: 0.8"/> " style="stroke: #000000; stroke-width: 0.8"/>
</defs> </defs>
<g> <g>
<use xlink:href="#m2b8ef16b3a" x="72.79" y="48.829483" style="stroke: #000000; stroke-width: 0.8"/> <use xlink:href="#mc0b9ff744f" x="72.79" y="48.829483" style="stroke: #000000; stroke-width: 0.8"/>
</g> </g>
</g> </g>
<g id="text_14"> <g id="text_14">
@ -843,7 +842,7 @@ z
<g id="ytick_2"> <g id="ytick_2">
<g id="line2d_26"> <g id="line2d_26">
<g> <g>
<use xlink:href="#m2b8ef16b3a" x="72.79" y="106.94" style="stroke: #000000; stroke-width: 0.8"/> <use xlink:href="#mc0b9ff744f" x="72.79" y="106.94" style="stroke: #000000; stroke-width: 0.8"/>
</g> </g>
</g> </g>
<g id="text_15"> <g id="text_15">
@ -884,7 +883,7 @@ z
<g id="ytick_3"> <g id="ytick_3">
<g id="line2d_27"> <g id="line2d_27">
<g> <g>
<use xlink:href="#m2b8ef16b3a" x="72.79" y="165.050517" style="stroke: #000000; stroke-width: 0.8"/> <use xlink:href="#mc0b9ff744f" x="72.79" y="165.050517" style="stroke: #000000; stroke-width: 0.8"/>
</g> </g>
</g> </g>
<g id="text_16"> <g id="text_16">
@ -1320,7 +1319,7 @@ z
</g> </g>
</g> </g>
<defs> <defs>
<clipPath id="p448fd06892"> <clipPath id="pce73ba693e">
<rect x="72.79" y="25.44" width="558.02" height="163"/> <rect x="72.79" y="25.44" width="558.02" height="163"/>
</clipPath> </clipPath>
</defs> </defs>

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 142 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 157 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 194 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 230 KiB

View file

@ -1205,66 +1205,71 @@ Vorteil der Optimierung: 300.00 EUR pro Tag (15.0 %)
<span id="cb9-34"><a href="#cb9-34" aria-hidden="true" tabindex="-1"></a><span class="im">from</span> or_kern <span class="im">import</span> (lade_produktionsproblem, loese_mit_glop, pruefe_loesung,</span> <span id="cb9-34"><a href="#cb9-34" aria-hidden="true" tabindex="-1"></a><span class="im">from</span> or_kern <span class="im">import</span> (lade_produktionsproblem, loese_mit_glop, pruefe_loesung,</span>
<span id="cb9-35"><a href="#cb9-35" aria-hidden="true" tabindex="-1"></a> schreibe_ergebnis)</span> <span id="cb9-35"><a href="#cb9-35" aria-hidden="true" tabindex="-1"></a> schreibe_ergebnis)</span>
<span id="cb9-36"><a href="#cb9-36" aria-hidden="true" tabindex="-1"></a></span> <span id="cb9-36"><a href="#cb9-36" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-37"><a href="#cb9-37" aria-hidden="true" tabindex="-1"></a>EINGABE <span class="op">=</span> <span class="st">&quot;produktionsmix.xlsx&quot;</span></span> <span id="cb9-37"><a href="#cb9-37" aria-hidden="true" tabindex="-1"></a><span class="co"># Die Mappen liegen NEBEN diesem Programm, nicht im aktuellen</span></span>
<span id="cb9-38"><a href="#cb9-38" aria-hidden="true" tabindex="-1"></a>AUSGABE <span class="op">=</span> <span class="st">&quot;produktionsmix_ergebnis.xlsx&quot;</span></span> <span id="cb9-38"><a href="#cb9-38" aria-hidden="true" tabindex="-1"></a><span class="co"># Arbeitsverzeichnis. Sonst haengt es davon ab, aus welchem Ordner man das</span></span>
<span id="cb9-39"><a href="#cb9-39" aria-hidden="true" tabindex="-1"></a></span> <span id="cb9-39"><a href="#cb9-39" aria-hidden="true" tabindex="-1"></a><span class="co"># Skript startet, wo die Dateien landen - und wer es aus der</span></span>
<span id="cb9-40"><a href="#cb9-40" aria-hidden="true" tabindex="-1"></a></span> <span id="cb9-40"><a href="#cb9-40" aria-hidden="true" tabindex="-1"></a><span class="co"># Repository-Wurzel aufruft, verstreut sie dort.</span></span>
<span id="cb9-41"><a href="#cb9-41" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> lege_beispieldatei_an(pfad: <span class="bu">str</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span> <span id="cb9-41"><a href="#cb9-41" aria-hidden="true" tabindex="-1"></a>HIER <span class="op">=</span> os.path.dirname(os.path.abspath(<span class="va">__file__</span>))</span>
<span id="cb9-42"><a href="#cb9-42" aria-hidden="true" tabindex="-1"></a> <span class="co">&quot;&quot;&quot;Schreibt die Eingabemappe, wie sie auch aus dem Controlling kaeme.&quot;&quot;&quot;</span></span> <span id="cb9-42"><a href="#cb9-42" aria-hidden="true" tabindex="-1"></a>EINGABE <span class="op">=</span> os.path.join(HIER, <span class="st">&quot;produktionsmix.xlsx&quot;</span>)</span>
<span id="cb9-43"><a href="#cb9-43" aria-hidden="true" tabindex="-1"></a> produkte <span class="op">=</span> pd.DataFrame({</span> <span id="cb9-43"><a href="#cb9-43" aria-hidden="true" tabindex="-1"></a>AUSGABE <span class="op">=</span> os.path.join(HIER, <span class="st">&quot;produktionsmix_ergebnis.xlsx&quot;</span>)</span>
<span id="cb9-44"><a href="#cb9-44" aria-hidden="true" tabindex="-1"></a> <span class="st">&quot;Produkt&quot;</span>: [<span class="st">&quot;Tisch&quot;</span>, <span class="st">&quot;Stuhl&quot;</span>, <span class="st">&quot;Regal&quot;</span>],</span> <span id="cb9-44"><a href="#cb9-44" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-45"><a href="#cb9-45" aria-hidden="true" tabindex="-1"></a> <span class="st">&quot;Deckungsbeitrag&quot;</span>: [<span class="fl">240.0</span>, <span class="fl">60.0</span>, <span class="fl">130.0</span>],</span> <span id="cb9-45"><a href="#cb9-45" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-46"><a href="#cb9-46" aria-hidden="true" tabindex="-1"></a> <span class="st">&quot;Montagestunden&quot;</span>: [<span class="fl">3.0</span>, <span class="fl">1.0</span>, <span class="fl">2.0</span>],</span> <span id="cb9-46"><a href="#cb9-46" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> lege_beispieldatei_an(pfad: <span class="bu">str</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb9-47"><a href="#cb9-47" aria-hidden="true" tabindex="-1"></a> <span class="st">&quot;Plattenmaterial&quot;</span>: [<span class="fl">6.0</span>, <span class="fl">1.0</span>, <span class="fl">4.0</span>],</span> <span id="cb9-47"><a href="#cb9-47" aria-hidden="true" tabindex="-1"></a> <span class="co">&quot;&quot;&quot;Schreibt die Eingabemappe, wie sie auch aus dem Controlling kaeme.&quot;&quot;&quot;</span></span>
<span id="cb9-48"><a href="#cb9-48" aria-hidden="true" tabindex="-1"></a> })</span> <span id="cb9-48"><a href="#cb9-48" aria-hidden="true" tabindex="-1"></a> produkte <span class="op">=</span> pd.DataFrame({</span>
<span id="cb9-49"><a href="#cb9-49" aria-hidden="true" tabindex="-1"></a> kapazitaeten <span class="op">=</span> pd.DataFrame({</span> <span id="cb9-49"><a href="#cb9-49" aria-hidden="true" tabindex="-1"></a> <span class="st">&quot;Produkt&quot;</span>: [<span class="st">&quot;Tisch&quot;</span>, <span class="st">&quot;Stuhl&quot;</span>, <span class="st">&quot;Regal&quot;</span>],</span>
<span id="cb9-50"><a href="#cb9-50" aria-hidden="true" tabindex="-1"></a> <span class="st">&quot;Ressource&quot;</span>: [<span class="st">&quot;Montagestunden&quot;</span>, <span class="st">&quot;Plattenmaterial&quot;</span>],</span> <span id="cb9-50"><a href="#cb9-50" aria-hidden="true" tabindex="-1"></a> <span class="st">&quot;Deckungsbeitrag&quot;</span>: [<span class="fl">240.0</span>, <span class="fl">60.0</span>, <span class="fl">130.0</span>],</span>
<span id="cb9-51"><a href="#cb9-51" aria-hidden="true" tabindex="-1"></a> <span class="st">&quot;Verfuegbar&quot;</span>: [<span class="fl">150.0</span>, <span class="fl">240.0</span>],</span> <span id="cb9-51"><a href="#cb9-51" aria-hidden="true" tabindex="-1"></a> <span class="st">&quot;Montagestunden&quot;</span>: [<span class="fl">3.0</span>, <span class="fl">1.0</span>, <span class="fl">2.0</span>],</span>
<span id="cb9-52"><a href="#cb9-52" aria-hidden="true" tabindex="-1"></a> })</span> <span id="cb9-52"><a href="#cb9-52" aria-hidden="true" tabindex="-1"></a> <span class="st">&quot;Plattenmaterial&quot;</span>: [<span class="fl">6.0</span>, <span class="fl">1.0</span>, <span class="fl">4.0</span>],</span>
<span id="cb9-53"><a href="#cb9-53" aria-hidden="true" tabindex="-1"></a> <span class="cf">with</span> pd.ExcelWriter(pfad, engine<span class="op">=</span><span class="st">&quot;openpyxl&quot;</span>) <span class="im">as</span> mappe:</span> <span id="cb9-53"><a href="#cb9-53" aria-hidden="true" tabindex="-1"></a> })</span>
<span id="cb9-54"><a href="#cb9-54" aria-hidden="true" tabindex="-1"></a> produkte.to_excel(mappe, sheet_name<span class="op">=</span><span class="st">&quot;Produkte&quot;</span>, index<span class="op">=</span><span class="va">False</span>)</span> <span id="cb9-54"><a href="#cb9-54" aria-hidden="true" tabindex="-1"></a> kapazitaeten <span class="op">=</span> pd.DataFrame({</span>
<span id="cb9-55"><a href="#cb9-55" aria-hidden="true" tabindex="-1"></a> kapazitaeten.to_excel(mappe, sheet_name<span class="op">=</span><span class="st">&quot;Kapazitaeten&quot;</span>, index<span class="op">=</span><span class="va">False</span>)</span> <span id="cb9-55"><a href="#cb9-55" aria-hidden="true" tabindex="-1"></a> <span class="st">&quot;Ressource&quot;</span>: [<span class="st">&quot;Montagestunden&quot;</span>, <span class="st">&quot;Plattenmaterial&quot;</span>],</span>
<span id="cb9-56"><a href="#cb9-56" aria-hidden="true" tabindex="-1"></a></span> <span id="cb9-56"><a href="#cb9-56" aria-hidden="true" tabindex="-1"></a> <span class="st">&quot;Verfuegbar&quot;</span>: [<span class="fl">150.0</span>, <span class="fl">240.0</span>],</span>
<span id="cb9-57"><a href="#cb9-57" aria-hidden="true" tabindex="-1"></a></span> <span id="cb9-57"><a href="#cb9-57" aria-hidden="true" tabindex="-1"></a> })</span>
<span id="cb9-58"><a href="#cb9-58" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">&quot;__main__&quot;</span>:</span> <span id="cb9-58"><a href="#cb9-58" aria-hidden="true" tabindex="-1"></a> <span class="cf">with</span> pd.ExcelWriter(pfad, engine<span class="op">=</span><span class="st">&quot;openpyxl&quot;</span>) <span class="im">as</span> mappe:</span>
<span id="cb9-59"><a href="#cb9-59" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> <span class="kw">not</span> os.path.exists(EINGABE):</span> <span id="cb9-59"><a href="#cb9-59" aria-hidden="true" tabindex="-1"></a> produkte.to_excel(mappe, sheet_name<span class="op">=</span><span class="st">&quot;Produkte&quot;</span>, index<span class="op">=</span><span class="va">False</span>)</span>
<span id="cb9-60"><a href="#cb9-60" aria-hidden="true" tabindex="-1"></a> lege_beispieldatei_an(EINGABE)</span> <span id="cb9-60"><a href="#cb9-60" aria-hidden="true" tabindex="-1"></a> kapazitaeten.to_excel(mappe, sheet_name<span class="op">=</span><span class="st">&quot;Kapazitaeten&quot;</span>, index<span class="op">=</span><span class="va">False</span>)</span>
<span id="cb9-61"><a href="#cb9-61" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f&quot;Beispiel-Eingabedatei angelegt: </span><span class="sc">{</span>EINGABE<span class="sc">}</span><span class="ss">&quot;</span>)</span> <span id="cb9-61"><a href="#cb9-61" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-62"><a href="#cb9-62" aria-hidden="true" tabindex="-1"></a></span> <span id="cb9-62"><a href="#cb9-62" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-63"><a href="#cb9-63" aria-hidden="true" tabindex="-1"></a> <span class="co"># 1. Lesen und pruefen. Faellt hier etwas auf, ist der Fehler noch</span></span> <span id="cb9-63"><a href="#cb9-63" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">&quot;__main__&quot;</span>:</span>
<span id="cb9-64"><a href="#cb9-64" aria-hidden="true" tabindex="-1"></a> <span class="co"># zuzuordnen - spaeter waere er nur noch eine merkwuerdige Zahl.</span></span> <span id="cb9-64"><a href="#cb9-64" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> <span class="kw">not</span> os.path.exists(EINGABE):</span>
<span id="cb9-65"><a href="#cb9-65" aria-hidden="true" tabindex="-1"></a> problem <span class="op">=</span> lade_produktionsproblem(EINGABE)</span> <span id="cb9-65"><a href="#cb9-65" aria-hidden="true" tabindex="-1"></a> lege_beispieldatei_an(EINGABE)</span>
<span id="cb9-66"><a href="#cb9-66" aria-hidden="true" tabindex="-1"></a></span> <span id="cb9-66"><a href="#cb9-66" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f&quot;Beispiel-Eingabedatei angelegt: </span><span class="sc">{</span>EINGABE<span class="sc">}</span><span class="ss">&quot;</span>)</span>
<span id="cb9-67"><a href="#cb9-67" aria-hidden="true" tabindex="-1"></a> <span class="co"># 2. Loesen. Einzige solverabhaengige Zeile des ganzen Programms -</span></span> <span id="cb9-67"><a href="#cb9-67" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-68"><a href="#cb9-68" aria-hidden="true" tabindex="-1"></a> <span class="co"># &#39;loese_mit_scipy&#39; waere ein Einzeiler-Wechsel.</span></span> <span id="cb9-68"><a href="#cb9-68" aria-hidden="true" tabindex="-1"></a> <span class="co"># 1. Lesen und pruefen. Faellt hier etwas auf, ist der Fehler noch</span></span>
<span id="cb9-69"><a href="#cb9-69" aria-hidden="true" tabindex="-1"></a> loesung <span class="op">=</span> loese_mit_glop(problem)</span> <span id="cb9-69"><a href="#cb9-69" aria-hidden="true" tabindex="-1"></a> <span class="co"># zuzuordnen - spaeter waere er nur noch eine merkwuerdige Zahl.</span></span>
<span id="cb9-70"><a href="#cb9-70" aria-hidden="true" tabindex="-1"></a></span> <span id="cb9-70"><a href="#cb9-70" aria-hidden="true" tabindex="-1"></a> problem <span class="op">=</span> lade_produktionsproblem(EINGABE)</span>
<span id="cb9-71"><a href="#cb9-71" aria-hidden="true" tabindex="-1"></a> <span class="co"># 3. Abnahmepruefung gegen die Anforderungen, ohne den Solver zu fragen.</span></span> <span id="cb9-71"><a href="#cb9-71" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-72"><a href="#cb9-72" aria-hidden="true" tabindex="-1"></a> beanstandungen <span class="op">=</span> pruefe_loesung(problem, loesung)</span> <span id="cb9-72"><a href="#cb9-72" aria-hidden="true" tabindex="-1"></a> <span class="co"># 2. Loesen. Einzige solverabhaengige Zeile des ganzen Programms -</span></span>
<span id="cb9-73"><a href="#cb9-73" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> beanstandungen:</span> <span id="cb9-73"><a href="#cb9-73" aria-hidden="true" tabindex="-1"></a> <span class="co"># &#39;loese_mit_scipy&#39; waere ein Einzeiler-Wechsel.</span></span>
<span id="cb9-74"><a href="#cb9-74" aria-hidden="true" tabindex="-1"></a> <span class="cf">raise</span> <span class="pp">SystemExit</span>(<span class="st">&quot;Abnahmepruefung fehlgeschlagen:</span><span class="ch">\n</span><span class="st"> - &quot;</span></span> <span id="cb9-74"><a href="#cb9-74" aria-hidden="true" tabindex="-1"></a> loesung <span class="op">=</span> loese_mit_glop(problem)</span>
<span id="cb9-75"><a href="#cb9-75" aria-hidden="true" tabindex="-1"></a> <span class="op">+</span> <span class="st">&quot;</span><span class="ch">\n</span><span class="st"> - &quot;</span>.join(beanstandungen))</span> <span id="cb9-75"><a href="#cb9-75" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-76"><a href="#cb9-76" aria-hidden="true" tabindex="-1"></a></span> <span id="cb9-76"><a href="#cb9-76" aria-hidden="true" tabindex="-1"></a> <span class="co"># 3. Abnahmepruefung gegen die Anforderungen, ohne den Solver zu fragen.</span></span>
<span id="cb9-77"><a href="#cb9-77" aria-hidden="true" tabindex="-1"></a> <span class="co"># 4. Zurueckschreiben - im Format, das die Fachabteilung ohnehin benutzt.</span></span> <span id="cb9-77"><a href="#cb9-77" aria-hidden="true" tabindex="-1"></a> beanstandungen <span class="op">=</span> pruefe_loesung(problem, loesung)</span>
<span id="cb9-78"><a href="#cb9-78" aria-hidden="true" tabindex="-1"></a> schreibe_ergebnis(AUSGABE, problem, loesung)</span> <span id="cb9-78"><a href="#cb9-78" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> beanstandungen:</span>
<span id="cb9-79"><a href="#cb9-79" aria-hidden="true" tabindex="-1"></a></span> <span id="cb9-79"><a href="#cb9-79" aria-hidden="true" tabindex="-1"></a> <span class="cf">raise</span> <span class="pp">SystemExit</span>(<span class="st">&quot;Abnahmepruefung fehlgeschlagen:</span><span class="ch">\n</span><span class="st"> - &quot;</span></span>
<span id="cb9-80"><a href="#cb9-80" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">&quot;=&quot;</span> <span class="op">*</span> <span class="dv">66</span>)</span> <span id="cb9-80"><a href="#cb9-80" aria-hidden="true" tabindex="-1"></a> <span class="op">+</span> <span class="st">&quot;</span><span class="ch">\n</span><span class="st"> - &quot;</span>.join(beanstandungen))</span>
<span id="cb9-81"><a href="#cb9-81" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">&quot; PRODUKTIONSPLAN AUS DER EXCEL-MAPPE&quot;</span>)</span> <span id="cb9-81"><a href="#cb9-81" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-82"><a href="#cb9-82" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">&quot;=&quot;</span> <span class="op">*</span> <span class="dv">66</span>)</span> <span id="cb9-82"><a href="#cb9-82" aria-hidden="true" tabindex="-1"></a> <span class="co"># 4. Zurueckschreiben - im Format, das die Fachabteilung ohnehin benutzt.</span></span>
<span id="cb9-83"><a href="#cb9-83" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> produkt <span class="kw">in</span> problem.produkte:</span> <span id="cb9-83"><a href="#cb9-83" aria-hidden="true" tabindex="-1"></a> schreibe_ergebnis(AUSGABE, problem, loesung)</span>
<span id="cb9-84"><a href="#cb9-84" aria-hidden="true" tabindex="-1"></a> menge <span class="op">=</span> loesung.werte[produkt.name]</span> <span id="cb9-84"><a href="#cb9-84" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-85"><a href="#cb9-85" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f&quot;</span><span class="sc">{</span>produkt<span class="sc">.</span>name<span class="sc">:&lt;18}</span><span class="ss"> </span><span class="sc">{</span>menge<span class="sc">:8.1f}</span><span class="ss"> Stueck &quot;</span></span> <span id="cb9-85"><a href="#cb9-85" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">&quot;=&quot;</span> <span class="op">*</span> <span class="dv">66</span>)</span>
<span id="cb9-86"><a href="#cb9-86" aria-hidden="true" tabindex="-1"></a> <span class="ss">f&quot;</span><span class="sc">{</span>menge <span class="op">*</span> produkt<span class="sc">.</span>deckungsbeitrag<span class="sc">:12,.2f}</span><span class="ss"> EUR&quot;</span>)</span> <span id="cb9-86"><a href="#cb9-86" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">&quot; PRODUKTIONSPLAN AUS DER EXCEL-MAPPE&quot;</span>)</span>
<span id="cb9-87"><a href="#cb9-87" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">&quot;-&quot;</span> <span class="op">*</span> <span class="dv">66</span>)</span> <span id="cb9-87"><a href="#cb9-87" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">&quot;=&quot;</span> <span class="op">*</span> <span class="dv">66</span>)</span>
<span id="cb9-88"><a href="#cb9-88" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(loesung.als_bericht())</span> <span id="cb9-88"><a href="#cb9-88" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> produkt <span class="kw">in</span> problem.produkte:</span>
<span id="cb9-89"><a href="#cb9-89" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">&quot;Abnahmepruefung: bestanden</span><span class="ch">\n</span><span class="st">&quot;</span>)</span> <span id="cb9-89"><a href="#cb9-89" aria-hidden="true" tabindex="-1"></a> menge <span class="op">=</span> loesung.werte[produkt.name]</span>
<span id="cb9-90"><a href="#cb9-90" aria-hidden="true" tabindex="-1"></a></span> <span id="cb9-90"><a href="#cb9-90" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f&quot;</span><span class="sc">{</span>produkt<span class="sc">.</span>name<span class="sc">:&lt;18}</span><span class="ss"> </span><span class="sc">{</span>menge<span class="sc">:8.1f}</span><span class="ss"> Stueck &quot;</span></span>
<span id="cb9-91"><a href="#cb9-91" aria-hidden="true" tabindex="-1"></a> <span class="co"># Die Schattenpreise beantworten die Frage, die der Plan nicht stellt:</span></span> <span id="cb9-91"><a href="#cb9-91" aria-hidden="true" tabindex="-1"></a> <span class="ss">f&quot;</span><span class="sc">{</span>menge <span class="op">*</span> produkt<span class="sc">.</span>deckungsbeitrag<span class="sc">:12,.2f}</span><span class="ss"> EUR&quot;</span>)</span>
<span id="cb9-92"><a href="#cb9-92" aria-hidden="true" tabindex="-1"></a> <span class="co"># Was waere eine zusaetzliche Einheit dieser Ressource wert?</span></span> <span id="cb9-92"><a href="#cb9-92" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">&quot;-&quot;</span> <span class="op">*</span> <span class="dv">66</span>)</span>
<span id="cb9-93"><a href="#cb9-93" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> ressource, preis <span class="kw">in</span> loesung.schattenpreise.items():</span> <span id="cb9-93"><a href="#cb9-93" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(loesung.als_bericht())</span>
<span id="cb9-94"><a href="#cb9-94" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f&quot; eine Einheit </span><span class="sc">{</span>ressource<span class="sc">:&lt;18}</span><span class="ss"> mehr waere wert: </span><span class="sc">{</span>preis<span class="sc">:7.2f}</span><span class="ss"> EUR&quot;</span>)</span> <span id="cb9-94"><a href="#cb9-94" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">&quot;Abnahmepruefung: bestanden</span><span class="ch">\n</span><span class="st">&quot;</span>)</span>
<span id="cb9-95"><a href="#cb9-95" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">&quot;=&quot;</span> <span class="op">*</span> <span class="dv">66</span>)</span> <span id="cb9-95"><a href="#cb9-95" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-96"><a href="#cb9-96" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f&quot;Ergebnis geschrieben nach: </span><span class="sc">{</span>AUSGABE<span class="sc">}</span><span class="ss">&quot;</span>)</span></code></pre></div> <span id="cb9-96"><a href="#cb9-96" aria-hidden="true" tabindex="-1"></a> <span class="co"># Die Schattenpreise beantworten die Frage, die der Plan nicht stellt:</span></span>
<span id="cb9-97"><a href="#cb9-97" aria-hidden="true" tabindex="-1"></a> <span class="co"># Was waere eine zusaetzliche Einheit dieser Ressource wert?</span></span>
<span id="cb9-98"><a href="#cb9-98" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> ressource, preis <span class="kw">in</span> loesung.schattenpreise.items():</span>
<span id="cb9-99"><a href="#cb9-99" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f&quot; eine Einheit </span><span class="sc">{</span>ressource<span class="sc">:&lt;18}</span><span class="ss"> mehr waere wert: </span><span class="sc">{</span>preis<span class="sc">:7.2f}</span><span class="ss"> EUR&quot;</span>)</span>
<span id="cb9-100"><a href="#cb9-100" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">&quot;=&quot;</span> <span class="op">*</span> <span class="dv">66</span>)</span>
<span id="cb9-101"><a href="#cb9-101" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f&quot;Ergebnis geschrieben nach: </span><span class="sc">{</span>AUSGABE<span class="sc">}</span><span class="ss">&quot;</span>)</span></code></pre></div>
<p><strong>Erwartete Ausgabe:</strong></p> <p><strong>Erwartete Ausgabe:</strong></p>
<pre><code>Beispiel-Eingabedatei angelegt: produktionsmix.xlsx <pre><code>Beispiel-Eingabedatei angelegt: produktionsmix.xlsx
================================================================== ==================================================================

View file

@ -4198,66 +4198,71 @@ Vorteil der Optimierung: 300.00 EUR pro Tag (15.0 %)
<span id="cb13-34"><a href="#cb13-34" aria-hidden="true" tabindex="-1"></a><span class="im">from</span> or_kern <span class="im">import</span> (lade_produktionsproblem, loese_mit_glop, pruefe_loesung,</span> <span id="cb13-34"><a href="#cb13-34" aria-hidden="true" tabindex="-1"></a><span class="im">from</span> or_kern <span class="im">import</span> (lade_produktionsproblem, loese_mit_glop, pruefe_loesung,</span>
<span id="cb13-35"><a href="#cb13-35" aria-hidden="true" tabindex="-1"></a> schreibe_ergebnis)</span> <span id="cb13-35"><a href="#cb13-35" aria-hidden="true" tabindex="-1"></a> schreibe_ergebnis)</span>
<span id="cb13-36"><a href="#cb13-36" aria-hidden="true" tabindex="-1"></a></span> <span id="cb13-36"><a href="#cb13-36" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-37"><a href="#cb13-37" aria-hidden="true" tabindex="-1"></a>EINGABE <span class="op">=</span> <span class="st">&quot;produktionsmix.xlsx&quot;</span></span> <span id="cb13-37"><a href="#cb13-37" aria-hidden="true" tabindex="-1"></a><span class="co"># Die Mappen liegen NEBEN diesem Programm, nicht im aktuellen</span></span>
<span id="cb13-38"><a href="#cb13-38" aria-hidden="true" tabindex="-1"></a>AUSGABE <span class="op">=</span> <span class="st">&quot;produktionsmix_ergebnis.xlsx&quot;</span></span> <span id="cb13-38"><a href="#cb13-38" aria-hidden="true" tabindex="-1"></a><span class="co"># Arbeitsverzeichnis. Sonst haengt es davon ab, aus welchem Ordner man das</span></span>
<span id="cb13-39"><a href="#cb13-39" aria-hidden="true" tabindex="-1"></a></span> <span id="cb13-39"><a href="#cb13-39" aria-hidden="true" tabindex="-1"></a><span class="co"># Skript startet, wo die Dateien landen - und wer es aus der</span></span>
<span id="cb13-40"><a href="#cb13-40" aria-hidden="true" tabindex="-1"></a></span> <span id="cb13-40"><a href="#cb13-40" aria-hidden="true" tabindex="-1"></a><span class="co"># Repository-Wurzel aufruft, verstreut sie dort.</span></span>
<span id="cb13-41"><a href="#cb13-41" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> lege_beispieldatei_an(pfad: <span class="bu">str</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span> <span id="cb13-41"><a href="#cb13-41" aria-hidden="true" tabindex="-1"></a>HIER <span class="op">=</span> os.path.dirname(os.path.abspath(<span class="va">__file__</span>))</span>
<span id="cb13-42"><a href="#cb13-42" aria-hidden="true" tabindex="-1"></a> <span class="co">&quot;&quot;&quot;Schreibt die Eingabemappe, wie sie auch aus dem Controlling kaeme.&quot;&quot;&quot;</span></span> <span id="cb13-42"><a href="#cb13-42" aria-hidden="true" tabindex="-1"></a>EINGABE <span class="op">=</span> os.path.join(HIER, <span class="st">&quot;produktionsmix.xlsx&quot;</span>)</span>
<span id="cb13-43"><a href="#cb13-43" aria-hidden="true" tabindex="-1"></a> produkte <span class="op">=</span> pd.DataFrame({</span> <span id="cb13-43"><a href="#cb13-43" aria-hidden="true" tabindex="-1"></a>AUSGABE <span class="op">=</span> os.path.join(HIER, <span class="st">&quot;produktionsmix_ergebnis.xlsx&quot;</span>)</span>
<span id="cb13-44"><a href="#cb13-44" aria-hidden="true" tabindex="-1"></a> <span class="st">&quot;Produkt&quot;</span>: [<span class="st">&quot;Tisch&quot;</span>, <span class="st">&quot;Stuhl&quot;</span>, <span class="st">&quot;Regal&quot;</span>],</span> <span id="cb13-44"><a href="#cb13-44" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-45"><a href="#cb13-45" aria-hidden="true" tabindex="-1"></a> <span class="st">&quot;Deckungsbeitrag&quot;</span>: [<span class="fl">240.0</span>, <span class="fl">60.0</span>, <span class="fl">130.0</span>],</span> <span id="cb13-45"><a href="#cb13-45" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-46"><a href="#cb13-46" aria-hidden="true" tabindex="-1"></a> <span class="st">&quot;Montagestunden&quot;</span>: [<span class="fl">3.0</span>, <span class="fl">1.0</span>, <span class="fl">2.0</span>],</span> <span id="cb13-46"><a href="#cb13-46" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> lege_beispieldatei_an(pfad: <span class="bu">str</span>) <span class="op">-&gt;</span> <span class="va">None</span>:</span>
<span id="cb13-47"><a href="#cb13-47" aria-hidden="true" tabindex="-1"></a> <span class="st">&quot;Plattenmaterial&quot;</span>: [<span class="fl">6.0</span>, <span class="fl">1.0</span>, <span class="fl">4.0</span>],</span> <span id="cb13-47"><a href="#cb13-47" aria-hidden="true" tabindex="-1"></a> <span class="co">&quot;&quot;&quot;Schreibt die Eingabemappe, wie sie auch aus dem Controlling kaeme.&quot;&quot;&quot;</span></span>
<span id="cb13-48"><a href="#cb13-48" aria-hidden="true" tabindex="-1"></a> })</span> <span id="cb13-48"><a href="#cb13-48" aria-hidden="true" tabindex="-1"></a> produkte <span class="op">=</span> pd.DataFrame({</span>
<span id="cb13-49"><a href="#cb13-49" aria-hidden="true" tabindex="-1"></a> kapazitaeten <span class="op">=</span> pd.DataFrame({</span> <span id="cb13-49"><a href="#cb13-49" aria-hidden="true" tabindex="-1"></a> <span class="st">&quot;Produkt&quot;</span>: [<span class="st">&quot;Tisch&quot;</span>, <span class="st">&quot;Stuhl&quot;</span>, <span class="st">&quot;Regal&quot;</span>],</span>
<span id="cb13-50"><a href="#cb13-50" aria-hidden="true" tabindex="-1"></a> <span class="st">&quot;Ressource&quot;</span>: [<span class="st">&quot;Montagestunden&quot;</span>, <span class="st">&quot;Plattenmaterial&quot;</span>],</span> <span id="cb13-50"><a href="#cb13-50" aria-hidden="true" tabindex="-1"></a> <span class="st">&quot;Deckungsbeitrag&quot;</span>: [<span class="fl">240.0</span>, <span class="fl">60.0</span>, <span class="fl">130.0</span>],</span>
<span id="cb13-51"><a href="#cb13-51" aria-hidden="true" tabindex="-1"></a> <span class="st">&quot;Verfuegbar&quot;</span>: [<span class="fl">150.0</span>, <span class="fl">240.0</span>],</span> <span id="cb13-51"><a href="#cb13-51" aria-hidden="true" tabindex="-1"></a> <span class="st">&quot;Montagestunden&quot;</span>: [<span class="fl">3.0</span>, <span class="fl">1.0</span>, <span class="fl">2.0</span>],</span>
<span id="cb13-52"><a href="#cb13-52" aria-hidden="true" tabindex="-1"></a> })</span> <span id="cb13-52"><a href="#cb13-52" aria-hidden="true" tabindex="-1"></a> <span class="st">&quot;Plattenmaterial&quot;</span>: [<span class="fl">6.0</span>, <span class="fl">1.0</span>, <span class="fl">4.0</span>],</span>
<span id="cb13-53"><a href="#cb13-53" aria-hidden="true" tabindex="-1"></a> <span class="cf">with</span> pd.ExcelWriter(pfad, engine<span class="op">=</span><span class="st">&quot;openpyxl&quot;</span>) <span class="im">as</span> mappe:</span> <span id="cb13-53"><a href="#cb13-53" aria-hidden="true" tabindex="-1"></a> })</span>
<span id="cb13-54"><a href="#cb13-54" aria-hidden="true" tabindex="-1"></a> produkte.to_excel(mappe, sheet_name<span class="op">=</span><span class="st">&quot;Produkte&quot;</span>, index<span class="op">=</span><span class="va">False</span>)</span> <span id="cb13-54"><a href="#cb13-54" aria-hidden="true" tabindex="-1"></a> kapazitaeten <span class="op">=</span> pd.DataFrame({</span>
<span id="cb13-55"><a href="#cb13-55" aria-hidden="true" tabindex="-1"></a> kapazitaeten.to_excel(mappe, sheet_name<span class="op">=</span><span class="st">&quot;Kapazitaeten&quot;</span>, index<span class="op">=</span><span class="va">False</span>)</span> <span id="cb13-55"><a href="#cb13-55" aria-hidden="true" tabindex="-1"></a> <span class="st">&quot;Ressource&quot;</span>: [<span class="st">&quot;Montagestunden&quot;</span>, <span class="st">&quot;Plattenmaterial&quot;</span>],</span>
<span id="cb13-56"><a href="#cb13-56" aria-hidden="true" tabindex="-1"></a></span> <span id="cb13-56"><a href="#cb13-56" aria-hidden="true" tabindex="-1"></a> <span class="st">&quot;Verfuegbar&quot;</span>: [<span class="fl">150.0</span>, <span class="fl">240.0</span>],</span>
<span id="cb13-57"><a href="#cb13-57" aria-hidden="true" tabindex="-1"></a></span> <span id="cb13-57"><a href="#cb13-57" aria-hidden="true" tabindex="-1"></a> })</span>
<span id="cb13-58"><a href="#cb13-58" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">&quot;__main__&quot;</span>:</span> <span id="cb13-58"><a href="#cb13-58" aria-hidden="true" tabindex="-1"></a> <span class="cf">with</span> pd.ExcelWriter(pfad, engine<span class="op">=</span><span class="st">&quot;openpyxl&quot;</span>) <span class="im">as</span> mappe:</span>
<span id="cb13-59"><a href="#cb13-59" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> <span class="kw">not</span> os.path.exists(EINGABE):</span> <span id="cb13-59"><a href="#cb13-59" aria-hidden="true" tabindex="-1"></a> produkte.to_excel(mappe, sheet_name<span class="op">=</span><span class="st">&quot;Produkte&quot;</span>, index<span class="op">=</span><span class="va">False</span>)</span>
<span id="cb13-60"><a href="#cb13-60" aria-hidden="true" tabindex="-1"></a> lege_beispieldatei_an(EINGABE)</span> <span id="cb13-60"><a href="#cb13-60" aria-hidden="true" tabindex="-1"></a> kapazitaeten.to_excel(mappe, sheet_name<span class="op">=</span><span class="st">&quot;Kapazitaeten&quot;</span>, index<span class="op">=</span><span class="va">False</span>)</span>
<span id="cb13-61"><a href="#cb13-61" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f&quot;Beispiel-Eingabedatei angelegt: </span><span class="sc">{</span>EINGABE<span class="sc">}</span><span class="ss">&quot;</span>)</span> <span id="cb13-61"><a href="#cb13-61" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-62"><a href="#cb13-62" aria-hidden="true" tabindex="-1"></a></span> <span id="cb13-62"><a href="#cb13-62" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-63"><a href="#cb13-63" aria-hidden="true" tabindex="-1"></a> <span class="co"># 1. Lesen und pruefen. Faellt hier etwas auf, ist der Fehler noch</span></span> <span id="cb13-63"><a href="#cb13-63" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">&quot;__main__&quot;</span>:</span>
<span id="cb13-64"><a href="#cb13-64" aria-hidden="true" tabindex="-1"></a> <span class="co"># zuzuordnen - spaeter waere er nur noch eine merkwuerdige Zahl.</span></span> <span id="cb13-64"><a href="#cb13-64" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> <span class="kw">not</span> os.path.exists(EINGABE):</span>
<span id="cb13-65"><a href="#cb13-65" aria-hidden="true" tabindex="-1"></a> problem <span class="op">=</span> lade_produktionsproblem(EINGABE)</span> <span id="cb13-65"><a href="#cb13-65" aria-hidden="true" tabindex="-1"></a> lege_beispieldatei_an(EINGABE)</span>
<span id="cb13-66"><a href="#cb13-66" aria-hidden="true" tabindex="-1"></a></span> <span id="cb13-66"><a href="#cb13-66" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f&quot;Beispiel-Eingabedatei angelegt: </span><span class="sc">{</span>EINGABE<span class="sc">}</span><span class="ss">&quot;</span>)</span>
<span id="cb13-67"><a href="#cb13-67" aria-hidden="true" tabindex="-1"></a> <span class="co"># 2. Loesen. Einzige solverabhaengige Zeile des ganzen Programms -</span></span> <span id="cb13-67"><a href="#cb13-67" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-68"><a href="#cb13-68" aria-hidden="true" tabindex="-1"></a> <span class="co"># &#39;loese_mit_scipy&#39; waere ein Einzeiler-Wechsel.</span></span> <span id="cb13-68"><a href="#cb13-68" aria-hidden="true" tabindex="-1"></a> <span class="co"># 1. Lesen und pruefen. Faellt hier etwas auf, ist der Fehler noch</span></span>
<span id="cb13-69"><a href="#cb13-69" aria-hidden="true" tabindex="-1"></a> loesung <span class="op">=</span> loese_mit_glop(problem)</span> <span id="cb13-69"><a href="#cb13-69" aria-hidden="true" tabindex="-1"></a> <span class="co"># zuzuordnen - spaeter waere er nur noch eine merkwuerdige Zahl.</span></span>
<span id="cb13-70"><a href="#cb13-70" aria-hidden="true" tabindex="-1"></a></span> <span id="cb13-70"><a href="#cb13-70" aria-hidden="true" tabindex="-1"></a> problem <span class="op">=</span> lade_produktionsproblem(EINGABE)</span>
<span id="cb13-71"><a href="#cb13-71" aria-hidden="true" tabindex="-1"></a> <span class="co"># 3. Abnahmepruefung gegen die Anforderungen, ohne den Solver zu fragen.</span></span> <span id="cb13-71"><a href="#cb13-71" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-72"><a href="#cb13-72" aria-hidden="true" tabindex="-1"></a> beanstandungen <span class="op">=</span> pruefe_loesung(problem, loesung)</span> <span id="cb13-72"><a href="#cb13-72" aria-hidden="true" tabindex="-1"></a> <span class="co"># 2. Loesen. Einzige solverabhaengige Zeile des ganzen Programms -</span></span>
<span id="cb13-73"><a href="#cb13-73" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> beanstandungen:</span> <span id="cb13-73"><a href="#cb13-73" aria-hidden="true" tabindex="-1"></a> <span class="co"># &#39;loese_mit_scipy&#39; waere ein Einzeiler-Wechsel.</span></span>
<span id="cb13-74"><a href="#cb13-74" aria-hidden="true" tabindex="-1"></a> <span class="cf">raise</span> <span class="pp">SystemExit</span>(<span class="st">&quot;Abnahmepruefung fehlgeschlagen:</span><span class="ch">\n</span><span class="st"> - &quot;</span></span> <span id="cb13-74"><a href="#cb13-74" aria-hidden="true" tabindex="-1"></a> loesung <span class="op">=</span> loese_mit_glop(problem)</span>
<span id="cb13-75"><a href="#cb13-75" aria-hidden="true" tabindex="-1"></a> <span class="op">+</span> <span class="st">&quot;</span><span class="ch">\n</span><span class="st"> - &quot;</span>.join(beanstandungen))</span> <span id="cb13-75"><a href="#cb13-75" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-76"><a href="#cb13-76" aria-hidden="true" tabindex="-1"></a></span> <span id="cb13-76"><a href="#cb13-76" aria-hidden="true" tabindex="-1"></a> <span class="co"># 3. Abnahmepruefung gegen die Anforderungen, ohne den Solver zu fragen.</span></span>
<span id="cb13-77"><a href="#cb13-77" aria-hidden="true" tabindex="-1"></a> <span class="co"># 4. Zurueckschreiben - im Format, das die Fachabteilung ohnehin benutzt.</span></span> <span id="cb13-77"><a href="#cb13-77" aria-hidden="true" tabindex="-1"></a> beanstandungen <span class="op">=</span> pruefe_loesung(problem, loesung)</span>
<span id="cb13-78"><a href="#cb13-78" aria-hidden="true" tabindex="-1"></a> schreibe_ergebnis(AUSGABE, problem, loesung)</span> <span id="cb13-78"><a href="#cb13-78" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> beanstandungen:</span>
<span id="cb13-79"><a href="#cb13-79" aria-hidden="true" tabindex="-1"></a></span> <span id="cb13-79"><a href="#cb13-79" aria-hidden="true" tabindex="-1"></a> <span class="cf">raise</span> <span class="pp">SystemExit</span>(<span class="st">&quot;Abnahmepruefung fehlgeschlagen:</span><span class="ch">\n</span><span class="st"> - &quot;</span></span>
<span id="cb13-80"><a href="#cb13-80" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">&quot;=&quot;</span> <span class="op">*</span> <span class="dv">66</span>)</span> <span id="cb13-80"><a href="#cb13-80" aria-hidden="true" tabindex="-1"></a> <span class="op">+</span> <span class="st">&quot;</span><span class="ch">\n</span><span class="st"> - &quot;</span>.join(beanstandungen))</span>
<span id="cb13-81"><a href="#cb13-81" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">&quot; PRODUKTIONSPLAN AUS DER EXCEL-MAPPE&quot;</span>)</span> <span id="cb13-81"><a href="#cb13-81" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-82"><a href="#cb13-82" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">&quot;=&quot;</span> <span class="op">*</span> <span class="dv">66</span>)</span> <span id="cb13-82"><a href="#cb13-82" aria-hidden="true" tabindex="-1"></a> <span class="co"># 4. Zurueckschreiben - im Format, das die Fachabteilung ohnehin benutzt.</span></span>
<span id="cb13-83"><a href="#cb13-83" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> produkt <span class="kw">in</span> problem.produkte:</span> <span id="cb13-83"><a href="#cb13-83" aria-hidden="true" tabindex="-1"></a> schreibe_ergebnis(AUSGABE, problem, loesung)</span>
<span id="cb13-84"><a href="#cb13-84" aria-hidden="true" tabindex="-1"></a> menge <span class="op">=</span> loesung.werte[produkt.name]</span> <span id="cb13-84"><a href="#cb13-84" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-85"><a href="#cb13-85" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f&quot;</span><span class="sc">{</span>produkt<span class="sc">.</span>name<span class="sc">:&lt;18}</span><span class="ss"> </span><span class="sc">{</span>menge<span class="sc">:8.1f}</span><span class="ss"> Stueck &quot;</span></span> <span id="cb13-85"><a href="#cb13-85" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">&quot;=&quot;</span> <span class="op">*</span> <span class="dv">66</span>)</span>
<span id="cb13-86"><a href="#cb13-86" aria-hidden="true" tabindex="-1"></a> <span class="ss">f&quot;</span><span class="sc">{</span>menge <span class="op">*</span> produkt<span class="sc">.</span>deckungsbeitrag<span class="sc">:12,.2f}</span><span class="ss"> EUR&quot;</span>)</span> <span id="cb13-86"><a href="#cb13-86" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">&quot; PRODUKTIONSPLAN AUS DER EXCEL-MAPPE&quot;</span>)</span>
<span id="cb13-87"><a href="#cb13-87" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">&quot;-&quot;</span> <span class="op">*</span> <span class="dv">66</span>)</span> <span id="cb13-87"><a href="#cb13-87" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">&quot;=&quot;</span> <span class="op">*</span> <span class="dv">66</span>)</span>
<span id="cb13-88"><a href="#cb13-88" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(loesung.als_bericht())</span> <span id="cb13-88"><a href="#cb13-88" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> produkt <span class="kw">in</span> problem.produkte:</span>
<span id="cb13-89"><a href="#cb13-89" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">&quot;Abnahmepruefung: bestanden</span><span class="ch">\n</span><span class="st">&quot;</span>)</span> <span id="cb13-89"><a href="#cb13-89" aria-hidden="true" tabindex="-1"></a> menge <span class="op">=</span> loesung.werte[produkt.name]</span>
<span id="cb13-90"><a href="#cb13-90" aria-hidden="true" tabindex="-1"></a></span> <span id="cb13-90"><a href="#cb13-90" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f&quot;</span><span class="sc">{</span>produkt<span class="sc">.</span>name<span class="sc">:&lt;18}</span><span class="ss"> </span><span class="sc">{</span>menge<span class="sc">:8.1f}</span><span class="ss"> Stueck &quot;</span></span>
<span id="cb13-91"><a href="#cb13-91" aria-hidden="true" tabindex="-1"></a> <span class="co"># Die Schattenpreise beantworten die Frage, die der Plan nicht stellt:</span></span> <span id="cb13-91"><a href="#cb13-91" aria-hidden="true" tabindex="-1"></a> <span class="ss">f&quot;</span><span class="sc">{</span>menge <span class="op">*</span> produkt<span class="sc">.</span>deckungsbeitrag<span class="sc">:12,.2f}</span><span class="ss"> EUR&quot;</span>)</span>
<span id="cb13-92"><a href="#cb13-92" aria-hidden="true" tabindex="-1"></a> <span class="co"># Was waere eine zusaetzliche Einheit dieser Ressource wert?</span></span> <span id="cb13-92"><a href="#cb13-92" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">&quot;-&quot;</span> <span class="op">*</span> <span class="dv">66</span>)</span>
<span id="cb13-93"><a href="#cb13-93" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> ressource, preis <span class="kw">in</span> loesung.schattenpreise.items():</span> <span id="cb13-93"><a href="#cb13-93" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(loesung.als_bericht())</span>
<span id="cb13-94"><a href="#cb13-94" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f&quot; eine Einheit </span><span class="sc">{</span>ressource<span class="sc">:&lt;18}</span><span class="ss"> mehr waere wert: </span><span class="sc">{</span>preis<span class="sc">:7.2f}</span><span class="ss"> EUR&quot;</span>)</span> <span id="cb13-94"><a href="#cb13-94" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">&quot;Abnahmepruefung: bestanden</span><span class="ch">\n</span><span class="st">&quot;</span>)</span>
<span id="cb13-95"><a href="#cb13-95" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">&quot;=&quot;</span> <span class="op">*</span> <span class="dv">66</span>)</span> <span id="cb13-95"><a href="#cb13-95" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-96"><a href="#cb13-96" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f&quot;Ergebnis geschrieben nach: </span><span class="sc">{</span>AUSGABE<span class="sc">}</span><span class="ss">&quot;</span>)</span></code></pre></div> <span id="cb13-96"><a href="#cb13-96" aria-hidden="true" tabindex="-1"></a> <span class="co"># Die Schattenpreise beantworten die Frage, die der Plan nicht stellt:</span></span>
<span id="cb13-97"><a href="#cb13-97" aria-hidden="true" tabindex="-1"></a> <span class="co"># Was waere eine zusaetzliche Einheit dieser Ressource wert?</span></span>
<span id="cb13-98"><a href="#cb13-98" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> ressource, preis <span class="kw">in</span> loesung.schattenpreise.items():</span>
<span id="cb13-99"><a href="#cb13-99" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f&quot; eine Einheit </span><span class="sc">{</span>ressource<span class="sc">:&lt;18}</span><span class="ss"> mehr waere wert: </span><span class="sc">{</span>preis<span class="sc">:7.2f}</span><span class="ss"> EUR&quot;</span>)</span>
<span id="cb13-100"><a href="#cb13-100" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">&quot;=&quot;</span> <span class="op">*</span> <span class="dv">66</span>)</span>
<span id="cb13-101"><a href="#cb13-101" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f&quot;Ergebnis geschrieben nach: </span><span class="sc">{</span>AUSGABE<span class="sc">}</span><span class="ss">&quot;</span>)</span></code></pre></div>
<p><strong>Erwartete Ausgabe:</strong></p> <p><strong>Erwartete Ausgabe:</strong></p>
<pre><code>Beispiel-Eingabedatei angelegt: produktionsmix.xlsx <pre><code>Beispiel-Eingabedatei angelegt: produktionsmix.xlsx
================================================================== ==================================================================

View file

@ -34,8 +34,13 @@ import pandas as pd
from or_kern import (lade_produktionsproblem, loese_mit_glop, pruefe_loesung, from or_kern import (lade_produktionsproblem, loese_mit_glop, pruefe_loesung,
schreibe_ergebnis) schreibe_ergebnis)
EINGABE = "produktionsmix.xlsx" # Die Mappen liegen NEBEN diesem Programm, nicht im aktuellen
AUSGABE = "produktionsmix_ergebnis.xlsx" # 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: def lege_beispieldatei_an(pfad: str) -> None:

File diff suppressed because one or more lines are too long

View file

@ -1539,8 +1539,13 @@ import pandas as pd
from or_kern import (lade_produktionsproblem, loese_mit_glop, pruefe_loesung, from or_kern import (lade_produktionsproblem, loese_mit_glop, pruefe_loesung,
schreibe_ergebnis) schreibe_ergebnis)
EINGABE = "produktionsmix.xlsx" # Die Mappen liegen NEBEN diesem Programm, nicht im aktuellen
AUSGABE = "produktionsmix_ergebnis.xlsx" # 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: def lege_beispieldatei_an(pfad: str) -> None:

View file

@ -966,8 +966,13 @@ import pandas as pd
from or_kern import (lade_produktionsproblem, loese_mit_glop, pruefe_loesung, from or_kern import (lade_produktionsproblem, loese_mit_glop, pruefe_loesung,
schreibe_ergebnis) schreibe_ergebnis)
EINGABE = "produktionsmix.xlsx" # Die Mappen liegen NEBEN diesem Programm, nicht im aktuellen
AUSGABE = "produktionsmix_ergebnis.xlsx" # 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: def lege_beispieldatei_an(pfad: str) -> None:

View file

@ -1447,7 +1447,13 @@ def spiegle_bilder(html_verz: str) -> None:
return return
ziel_wurzel = os.path.join(html_verz, BILDER_NAME) ziel_wurzel = os.path.join(html_verz, BILDER_NAME)
kopiert = 0 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) rel = os.path.relpath(wurzel, BILDER_VERZ)
ziel_verz = ziel_wurzel if rel == "." else os.path.join(ziel_wurzel, rel) ziel_verz = ziel_wurzel if rel == "." else os.path.join(ziel_wurzel, rel)
os.makedirs(ziel_verz, exist_ok=True) os.makedirs(ziel_verz, exist_ok=True)

View file

@ -34,8 +34,13 @@ import pandas as pd
from or_kern import (lade_produktionsproblem, loese_mit_glop, pruefe_loesung, from or_kern import (lade_produktionsproblem, loese_mit_glop, pruefe_loesung,
schreibe_ergebnis) schreibe_ergebnis)
EINGABE = "produktionsmix.xlsx" # Die Mappen liegen NEBEN diesem Programm, nicht im aktuellen
AUSGABE = "produktionsmix_ergebnis.xlsx" # 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: def lege_beispieldatei_an(pfad: str) -> None:

View file

@ -77,9 +77,9 @@ sie unerwartet ab, ist etwas kaputtgegangen.
| Kapiteldateien | 22 | **36** (31 + 5 Teil-Synthesen) | | Kapiteldateien | 22 | **36** (31 + 5 Teil-Synthesen) |
| Kapitel | 15 | **23** | | Kapitel | 15 | **23** |
| Anhänge | 4 | **5** | | 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** | | Größe des Gesamtdokuments | 606 KB | **1 622 KB** |
| Hauptüberschriften | 131 | **302** | | Hauptüberschriften | 131 | **306** |
| registrierte Abschnitte | 122 | **296** | | registrierte Abschnitte | 122 | **296** |
| aufgelöste Querverweise | 314 | **825** (0 unaufgelöst) | | aufgelöste Querverweise | 314 | **825** (0 unaufgelöst) |
| Indexmarken | 295 | **328** | | Indexmarken | 295 | **328** |
@ -87,7 +87,7 @@ sie unerwartet ab, ist etwas kaputtgegangen.
| PDF-Seiten | — | **760** | | PDF-Seiten | — | **760** |
| Notebooks | — | **25** | | Notebooks | — | **25** |
| Plotly-Figuren | — | **4** | | 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 **Gegenprobe:** `build_version_03.py --check` läuft unverändert durch — Version 03 ist von
allen Änderungen unberührt. 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.** **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 ## 8. Commit-Historie des V04-Strangs

View file

@ -4,8 +4,8 @@
""" """
Erzeugt die beiden Architekturdiagramme fuer den Weg vom Skript zum Betrieb: 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_praxisfallen_schichten.svg Schichten von or_kern.py
bilder_04/kap_testing_dienst.svg / .png der Dienst und sein Ablauf bilder_04/kap_testing_dienst.svg der Dienst und sein Ablauf
Beide bilden ab, was in den Programmen tatsaechlich steht - nicht ein Beide bilden ab, was in den Programmen tatsaechlich steht - nicht ein
allgemeines Architekturschema: 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: def schreibe(punkt: graphviz.Digraph, name: str) -> None:
os.makedirs(BILDER, exist_ok=True) os.makedirs(BILDER, exist_ok=True)
for endung in ("svg", "png"): for endung in ("svg",):
punkt.format = endung punkt.format = endung
pfad = punkt.render(os.path.join(BILDER, name), cleanup=True) pfad = punkt.render(os.path.join(BILDER, name), cleanup=True)
print(f"geschrieben: {pfad}") print(f"geschrieben: {pfad}")

View file

@ -4,7 +4,7 @@
""" """
Erzeugt den Branch-and-Bound-Suchbaum zum MILP-Kapitel: 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: 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") color="#94a3b8", fontsize="10", margin="0.18,0.12")
os.makedirs(BILDER, exist_ok=True) os.makedirs(BILDER, exist_ok=True)
for endung in ("svg", "png"): for endung in ("svg",):
punkt.format = endung punkt.format = endung
pfad = punkt.render(os.path.join(BILDER, "kap_milp_suchbaum"), cleanup=True) pfad = punkt.render(os.path.join(BILDER, "kap_milp_suchbaum"), cleanup=True)
print(f"geschrieben: {pfad}") print(f"geschrieben: {pfad}")

View file

@ -5,7 +5,6 @@
Erzeugt die Figur "Was die Hausregeln kosten" zum Kapitel Markowitz: 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.svg statisch, fuer das PDF
bilder_04/kap_markowitz_restriktionen.png Rasterfassung
bilder_04/plotly/kap_markowitz_restriktionen.html interaktiv, fuer die Website bilder_04/plotly/kap_markowitz_restriktionen.html interaktiv, fuer die Website
Gezeigt werden zwei Effizienzlinien desselben Universums: einmal ohne Gezeigt werden zwei Effizienzlinien desselben Universums: einmal ohne
@ -210,7 +209,7 @@ def zeichne_statisch(frei, gebunden, abstand, risiko_stelle) -> None:
figur.tight_layout() figur.tight_layout()
os.makedirs(BILDER, exist_ok=True) 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}") pfad = os.path.join(BILDER, f"kap_markowitz_restriktionen.{endung}")
figur.savefig(pfad, format=endung, dpi=160, figur.savefig(pfad, format=endung, dpi=160,
metadata={"Date": None} if endung == "svg" else None) metadata={"Date": None} if endung == "svg" else None)

View file

@ -5,7 +5,6 @@
Erzeugt das Gantt-Diagramm zum Job-Shop-Beispiel aus Kapitel 6 in zwei Fassungen: 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.svg statisch, fuer das PDF
bilder_04/kap06_jobshop_gantt.png statisch, Rasterfassung
bilder_04/plotly/kap06_jobshop_gantt.html interaktiv, fuer die Website bilder_04/plotly/kap06_jobshop_gantt.html interaktiv, fuer die Website
Die Daten sind identisch mit JobShop_Intervalle.py; geloest wird hier erneut, 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 import plotly.graph_objects as go
from ortools.sat.python import cp_model 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 # Identisch zu JobShop_Intervalle.py
AUFTRAEGE = [ AUFTRAEGE = [
[(0, 3), (1, 2), (2, 2)], # Auftrag 0 [(0, 3), (1, 2), (2, 2)], # Auftrag 0
@ -111,9 +115,10 @@ def zeichne_statisch(plan, makespan: int) -> None:
figur.tight_layout() figur.tight_layout()
os.makedirs(BILDER, exist_ok=True) 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}") 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}") print(f"geschrieben: {pfad}")
plt.close(figur) plt.close(figur)

View file

@ -4,7 +4,7 @@
""" """
Erzeugt das KKT-Diagramm zum QP/NLP-Kapitel: Erzeugt das KKT-Diagramm zum QP/NLP-Kapitel:
bilder_04/kap_qp_kkt.svg / .png bilder_04/kap_qp_kkt.svg
Zwei Bilder nebeneinander: Zwei Bilder nebeneinander:
@ -216,7 +216,7 @@ if __name__ == "__main__":
zeichne_2d(rechts, x_stern, lam) zeichne_2d(rechts, x_stern, lam)
figur.tight_layout() figur.tight_layout()
os.makedirs(BILDER, exist_ok=True) 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}") pfad = os.path.join(BILDER, f"kap_qp_kkt.{endung}")
figur.savefig(pfad, format=endung, dpi=160, figur.savefig(pfad, format=endung, dpi=160,
metadata={"Date": None} if endung == "svg" else None) metadata={"Date": None} if endung == "svg" else None)

View file

@ -5,7 +5,6 @@
Erzeugt das Konditionszahl-Diagramm zum Kapitel Fundament: Erzeugt das Konditionszahl-Diagramm zum Kapitel Fundament:
bilder_04/kap_fundament_kondition.svg statisch, fuer das PDF bilder_04/kap_fundament_kondition.svg statisch, fuer das PDF
bilder_04/kap_fundament_kondition.png Rasterfassung
Zwei Aussagen, beide gerechnet und nicht behauptet: Zwei Aussagen, beide gerechnet und nicht behauptet:
@ -185,7 +184,7 @@ def zeichne(kappas, mediane, maxima, kappa_vorher, kappa_nachher) -> None:
figur.tight_layout() figur.tight_layout()
os.makedirs(BILDER, exist_ok=True) 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}") pfad = os.path.join(BILDER, f"kap_fundament_kondition.{endung}")
figur.savefig(pfad, format=endung, dpi=160, figur.savefig(pfad, format=endung, dpi=160,
metadata={"Date": None} if endung == "svg" else None) metadata={"Date": None} if endung == "svg" else None)

View file

@ -5,7 +5,6 @@
Erzeugt das Suchverlauf-Diagramm zum Kapitel Metaheuristiken: Erzeugt das Suchverlauf-Diagramm zum Kapitel Metaheuristiken:
bilder_04/kap_metaheuristiken_landschaft.svg statisch, fuer das PDF 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 bilder_04/plotly/kap_metaheuristiken_verlauf.html interaktiv, fuer die Website
Eine Suchlandschaft laesst sich bei 200 Auftraegen nicht zeichnen - der Raum Eine Suchlandschaft laesst sich bei 200 Auftraegen nicht zeichnen - der Raum
@ -223,7 +222,7 @@ def zeichne(verlaeufe, start, temperaturreihe) -> None:
figur.tight_layout() figur.tight_layout()
os.makedirs(BILDER, exist_ok=True) 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}") pfad = os.path.join(BILDER, f"kap_metaheuristiken_landschaft.{endung}")
figur.savefig(pfad, format=endung, dpi=160, figur.savefig(pfad, format=endung, dpi=160,
metadata={"Date": None} if endung == "svg" else None) metadata={"Date": None} if endung == "svg" else None)

View file

@ -4,7 +4,7 @@
""" """
Erzeugt das Flussdiagramm zum Graphen-Kapitel: 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 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. 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}") penwidth=f"{1.0 + 3.0 * menge / kapazitaet:.1f}")
os.makedirs(BILDER, exist_ok=True) os.makedirs(BILDER, exist_ok=True)
for endung in ("svg", "png"): for endung in ("svg",):
punkt.format = endung punkt.format = endung
pfad = punkt.render(os.path.join(BILDER, "kap_graphen_min_cost_flow"), pfad = punkt.render(os.path.join(BILDER, "kap_graphen_min_cost_flow"),
cleanup=True) cleanup=True)

View file

@ -5,7 +5,6 @@
Erzeugt das Pareto-Front-Diagramm zum Mehrziel-Kapitel in zwei Fassungen: 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.svg statisch, fuer das PDF
bilder_04/kap_mehrziel_pareto.png statisch, Rasterfassung
bilder_04/plotly/kap_mehrziel_pareto.html interaktiv, fuer die Website bilder_04/plotly/kap_mehrziel_pareto.html interaktiv, fuer die Website
Die Instanz ist identisch mit Mehrziel_Pareto.py, und gerechnet wird hier 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() figur.tight_layout()
os.makedirs(BILDER, exist_ok=True) 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}") pfad = os.path.join(BILDER, f"kap_mehrziel_pareto.{endung}")
figur.savefig(pfad, format=endung, dpi=160, figur.savefig(pfad, format=endung, dpi=160,
metadata={"Date": None} if endung == "svg" else None) metadata={"Date": None} if endung == "svg" else None)

View file

@ -4,8 +4,8 @@
""" """
Erzeugt die beiden Polyeder-Diagramme zum Fundament- und zum LP-Kapitel: Erzeugt die beiden Polyeder-Diagramme zum Fundament- und zum LP-Kapitel:
bilder_04/kap_fundament_polyeder.svg / .png der zulaessige Bereich bilder_04/kap_fundament_polyeder.svg der zulaessige Bereich
bilder_04/kap_lp_simplex_ecken.svg / .png der Eckenlauf des Simplex bilder_04/kap_lp_simplex_ecken.svg der Eckenlauf des Simplex
Beide zeigen DASSELBE Modell - das Bot-Allokationsproblem, das sich durch die Beide zeigen DASSELBE Modell - das Bot-Allokationsproblem, das sich durch die
ersten Kapitel zieht: ersten Kapitel zieht:
@ -165,7 +165,7 @@ def zeichne_rahmen(achse, ecken: np.ndarray) -> None:
def schreibe(figur, name: str) -> None: def schreibe(figur, name: str) -> None:
os.makedirs(BILDER, exist_ok=True) os.makedirs(BILDER, exist_ok=True)
for endung in ("svg", "png"): for endung in ("svg",):
pfad = os.path.join(BILDER, f"{name}.{endung}") pfad = os.path.join(BILDER, f"{name}.{endung}")
figur.savefig(pfad, format=endung, dpi=160, figur.savefig(pfad, format=endung, dpi=160,
metadata={"Date": None} if endung == "svg" else None) metadata={"Date": None} if endung == "svg" else None)

View file

@ -5,7 +5,6 @@
Erzeugt das Diagramm "Warum Runden scheitert" zum MILP-Kapitel: Erzeugt das Diagramm "Warum Runden scheitert" zum MILP-Kapitel:
bilder_04/kap_milp_runden.svg statisch, fuer das PDF 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: Zwei Bilder nebeneinander, beide aus dem Kapitel selbst:
@ -213,7 +212,7 @@ def zeichne(zeilen) -> None:
figur.tight_layout() figur.tight_layout()
os.makedirs(BILDER, exist_ok=True) 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}") pfad = os.path.join(BILDER, f"kap_milp_runden.{endung}")
figur.savefig(pfad, format=endung, dpi=160, figur.savefig(pfad, format=endung, dpi=160,
metadata={"Date": None} if endung == "svg" else None) metadata={"Date": None} if endung == "svg" else None)

View file

@ -5,8 +5,8 @@
Erzeugt die beiden Entscheidungs-Flussdiagramme "Welches Werkzeug passt zu Erzeugt die beiden Entscheidungs-Flussdiagramme "Welches Werkzeug passt zu
meinem Problem?" fuer die Auftakte von Teil II und Teil III: meinem Problem?" fuer die Auftakte von Teil II und Teil III:
bilder_04/teil2_solverwahl.svg / .png deterministische Verfahren bilder_04/teil2_solverwahl.svg deterministische Verfahren
bilder_04/teil3_solverwahl.svg / .png Nichtlinearitaet und Unsicherheit bilder_04/teil3_solverwahl.svg Nichtlinearitaet und Unsicherheit
Beide entstehen mit Graphviz. Die Farben folgen der Buchpalette Beide entstehen mit Graphviz. Die Farben folgen der Buchpalette
(Indigo, Cyan, Violett, Gruen, Amber), die Kastenform codiert die Rolle: (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: def schreibe(punkt: graphviz.Digraph, name: str) -> None:
os.makedirs(BILDER, exist_ok=True) os.makedirs(BILDER, exist_ok=True)
for endung in ("svg", "png"): for endung in ("svg",):
punkt.format = endung punkt.format = endung
pfad = punkt.render(os.path.join(BILDER, name), cleanup=True) pfad = punkt.render(os.path.join(BILDER, name), cleanup=True)
print(f"geschrieben: {pfad}") print(f"geschrieben: {pfad}")

View file

@ -5,7 +5,6 @@
Erzeugt das VaR/CVaR-Diagramm zum Kapitel CVaR: 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.svg statisch, fuer das PDF
bilder_04/kap_cvar_var_vergleich.png Rasterfassung
Gezeigt wird die Verteilung simulierter Tagesrenditen mit beiden Kennzahlen: 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 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() figur.tight_layout()
os.makedirs(BILDER, exist_ok=True) 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}") pfad = os.path.join(BILDER, f"kap_cvar_var_vergleich.{endung}")
figur.savefig(pfad, format=endung, dpi=160, figur.savefig(pfad, format=endung, dpi=160,
metadata={"Date": None} if endung == "svg" else None) metadata={"Date": None} if endung == "svg" else None)

View file

@ -4,7 +4,7 @@
""" """
Erzeugt die Tourenkarte zum Graphen-Kapitel: 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 Das Vorgaengerbild war ein Schema: zwei Touren, vier Kunden, Zeitfenster in
Uhrzeiten. Die Instanz des Kapitels hat 16 Kunden, vier Fahrzeuge und Uhrzeiten. Die Instanz des Kapitels hat 16 Kunden, vier Fahrzeuge und
@ -170,7 +170,7 @@ def zeichne(koordinaten, touren) -> None:
figur.tight_layout() figur.tight_layout()
os.makedirs(BILDER, exist_ok=True) 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}") pfad = os.path.join(BILDER, f"kap_graphen_vrp_touren.{endung}")
figur.savefig(pfad, format=endung, dpi=160, bbox_inches="tight", figur.savefig(pfad, format=endung, dpi=160, bbox_inches="tight",
metadata={"Date": None} if endung == "svg" else None) metadata={"Date": None} if endung == "svg" else None)

View file

@ -5,7 +5,6 @@
Erzeugt das Wasserfalldiagramm zum Kapitel Supply-Chain und Energieeinsatz: Erzeugt das Wasserfalldiagramm zum Kapitel Supply-Chain und Energieeinsatz:
bilder_04/kap_supplychain_wirkung.svg statisch, fuer das PDF 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 Die Frage, die es beantwortet, ist die des Managements: WOFUER genau kostet
der Erwartungswert-Plan 149 % mehr? Die Tabelle im Kapitel nennt nur die 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() figur.tight_layout()
os.makedirs(BILDER, exist_ok=True) 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}") pfad = os.path.join(BILDER, f"kap_supplychain_wirkung.{endung}")
figur.savefig(pfad, format=endung, dpi=160, figur.savefig(pfad, format=endung, dpi=160,
metadata={"Date": None} if endung == "svg" else None) metadata={"Date": None} if endung == "svg" else None)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

View file

@ -6,7 +6,6 @@
<rdf:RDF xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:RDF xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<cc:Work> <cc:Work>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/> <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
<dc:date>2026-09-07T01:51:51.979555</dc:date>
<dc:format>image/svg+xml</dc:format> <dc:format>image/svg+xml</dc:format>
<dc:creator> <dc:creator>
<cc:Agent> <cc:Agent>
@ -43,7 +42,7 @@ L 326.435455 32.849091
L 326.435455 64.809875 L 326.435455 64.809875
L 174.248182 64.809875 L 174.248182 64.809875
z 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"/>
</g> </g>
<g id="patch_4"> <g id="patch_4">
<path d="M 326.435455 90.959608 <path d="M 326.435455 90.959608
@ -51,7 +50,7 @@ L 427.893636 90.959608
L 427.893636 122.920392 L 427.893636 122.920392
L 326.435455 122.920392 L 326.435455 122.920392
z 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"/>
</g> </g>
<g id="patch_5"> <g id="patch_5">
<path d="M 427.893636 149.070125 <path d="M 427.893636 149.070125
@ -59,7 +58,7 @@ L 529.351818 149.070125
L 529.351818 181.030909 L 529.351818 181.030909
L 427.893636 181.030909 L 427.893636 181.030909
z 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"/>
</g> </g>
<g id="patch_6"> <g id="patch_6">
<path d="M 72.79 32.849091 <path d="M 72.79 32.849091
@ -67,7 +66,7 @@ L 174.248182 32.849091
L 174.248182 64.809875 L 174.248182 64.809875
L 72.79 64.809875 L 72.79 64.809875
z z
" clip-path="url(#p448fd06892)" 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"/>
</g> </g>
<g id="patch_7"> <g id="patch_7">
<path d="M 174.248182 149.070125 <path d="M 174.248182 149.070125
@ -75,7 +74,7 @@ L 224.977273 149.070125
L 224.977273 181.030909 L 224.977273 181.030909
L 174.248182 181.030909 L 174.248182 181.030909
z z
" clip-path="url(#p448fd06892)" 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"/>
</g> </g>
<g id="patch_8"> <g id="patch_8">
<path d="M 427.893636 90.959608 <path d="M 427.893636 90.959608
@ -83,7 +82,7 @@ L 630.81 90.959608
L 630.81 122.920392 L 630.81 122.920392
L 427.893636 122.920392 L 427.893636 122.920392
z z
" clip-path="url(#p448fd06892)" 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"/>
</g> </g>
<g id="patch_9"> <g id="patch_9">
<path d="M 72.79 90.959608 <path d="M 72.79 90.959608
@ -91,7 +90,7 @@ L 275.706364 90.959608
L 275.706364 122.920392 L 275.706364 122.920392
L 72.79 122.920392 L 72.79 122.920392
z z
" clip-path="url(#p448fd06892)" 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"/>
</g> </g>
<g id="patch_10"> <g id="patch_10">
<path d="M 275.706364 149.070125 <path d="M 275.706364 149.070125
@ -99,23 +98,23 @@ L 427.893636 149.070125
L 427.893636 181.030909 L 427.893636 181.030909
L 275.706364 181.030909 L 275.706364 181.030909
z z
" clip-path="url(#p448fd06892)" 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"/>
</g> </g>
<g id="matplotlib.axis_1"> <g id="matplotlib.axis_1">
<g id="xtick_1"> <g id="xtick_1">
<g id="line2d_1"> <g id="line2d_1">
<path d="M 72.79 188.44 <path d="M 72.79 188.44
L 72.79 25.44 L 72.79 25.44
" clip-path="url(#p448fd06892)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> " 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"/>
</g> </g>
<g id="line2d_2"> <g id="line2d_2">
<defs> <defs>
<path id="mfeb5fcddc7" d="M 0 0 <path id="mf0a04b41f8" d="M 0 0
L 0 3.5 L 0 3.5
" style="stroke: #000000; stroke-width: 0.8"/> " style="stroke: #000000; stroke-width: 0.8"/>
</defs> </defs>
<g> <g>
<use xlink:href="#mfeb5fcddc7" x="72.79" y="188.44" style="stroke: #000000; stroke-width: 0.8"/> <use xlink:href="#mf0a04b41f8" x="72.79" y="188.44" style="stroke: #000000; stroke-width: 0.8"/>
</g> </g>
</g> </g>
<g id="text_1"> <g id="text_1">
@ -152,11 +151,11 @@ z
<g id="line2d_3"> <g id="line2d_3">
<path d="M 123.519091 188.44 <path d="M 123.519091 188.44
L 123.519091 25.44 L 123.519091 25.44
" clip-path="url(#p448fd06892)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> " 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"/>
</g> </g>
<g id="line2d_4"> <g id="line2d_4">
<g> <g>
<use xlink:href="#mfeb5fcddc7" x="123.519091" y="188.44" style="stroke: #000000; stroke-width: 0.8"/> <use xlink:href="#mf0a04b41f8" x="123.519091" y="188.44" style="stroke: #000000; stroke-width: 0.8"/>
</g> </g>
</g> </g>
<g id="text_2"> <g id="text_2">
@ -186,11 +185,11 @@ z
<g id="line2d_5"> <g id="line2d_5">
<path d="M 174.248182 188.44 <path d="M 174.248182 188.44
L 174.248182 25.44 L 174.248182 25.44
" clip-path="url(#p448fd06892)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> " 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"/>
</g> </g>
<g id="line2d_6"> <g id="line2d_6">
<g> <g>
<use xlink:href="#mfeb5fcddc7" x="174.248182" y="188.44" style="stroke: #000000; stroke-width: 0.8"/> <use xlink:href="#mf0a04b41f8" x="174.248182" y="188.44" style="stroke: #000000; stroke-width: 0.8"/>
</g> </g>
</g> </g>
<g id="text_3"> <g id="text_3">
@ -230,11 +229,11 @@ z
<g id="line2d_7"> <g id="line2d_7">
<path d="M 224.977273 188.44 <path d="M 224.977273 188.44
L 224.977273 25.44 L 224.977273 25.44
" clip-path="url(#p448fd06892)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> " 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"/>
</g> </g>
<g id="line2d_8"> <g id="line2d_8">
<g> <g>
<use xlink:href="#mfeb5fcddc7" x="224.977273" y="188.44" style="stroke: #000000; stroke-width: 0.8"/> <use xlink:href="#mf0a04b41f8" x="224.977273" y="188.44" style="stroke: #000000; stroke-width: 0.8"/>
</g> </g>
</g> </g>
<g id="text_4"> <g id="text_4">
@ -282,11 +281,11 @@ z
<g id="line2d_9"> <g id="line2d_9">
<path d="M 275.706364 188.44 <path d="M 275.706364 188.44
L 275.706364 25.44 L 275.706364 25.44
" clip-path="url(#p448fd06892)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> " 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"/>
</g> </g>
<g id="line2d_10"> <g id="line2d_10">
<g> <g>
<use xlink:href="#mfeb5fcddc7" x="275.706364" y="188.44" style="stroke: #000000; stroke-width: 0.8"/> <use xlink:href="#mf0a04b41f8" x="275.706364" y="188.44" style="stroke: #000000; stroke-width: 0.8"/>
</g> </g>
</g> </g>
<g id="text_5"> <g id="text_5">
@ -321,11 +320,11 @@ z
<g id="line2d_11"> <g id="line2d_11">
<path d="M 326.435455 188.44 <path d="M 326.435455 188.44
L 326.435455 25.44 L 326.435455 25.44
" clip-path="url(#p448fd06892)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> " 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"/>
</g> </g>
<g id="line2d_12"> <g id="line2d_12">
<g> <g>
<use xlink:href="#mfeb5fcddc7" x="326.435455" y="188.44" style="stroke: #000000; stroke-width: 0.8"/> <use xlink:href="#mf0a04b41f8" x="326.435455" y="188.44" style="stroke: #000000; stroke-width: 0.8"/>
</g> </g>
</g> </g>
<g id="text_6"> <g id="text_6">
@ -366,11 +365,11 @@ z
<g id="line2d_13"> <g id="line2d_13">
<path d="M 377.164545 188.44 <path d="M 377.164545 188.44
L 377.164545 25.44 L 377.164545 25.44
" clip-path="url(#p448fd06892)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> " 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"/>
</g> </g>
<g id="line2d_14"> <g id="line2d_14">
<g> <g>
<use xlink:href="#mfeb5fcddc7" x="377.164545" y="188.44" style="stroke: #000000; stroke-width: 0.8"/> <use xlink:href="#mf0a04b41f8" x="377.164545" y="188.44" style="stroke: #000000; stroke-width: 0.8"/>
</g> </g>
</g> </g>
<g id="text_7"> <g id="text_7">
@ -416,11 +415,11 @@ z
<g id="line2d_15"> <g id="line2d_15">
<path d="M 427.893636 188.44 <path d="M 427.893636 188.44
L 427.893636 25.44 L 427.893636 25.44
" clip-path="url(#p448fd06892)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> " 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"/>
</g> </g>
<g id="line2d_16"> <g id="line2d_16">
<g> <g>
<use xlink:href="#mfeb5fcddc7" x="427.893636" y="188.44" style="stroke: #000000; stroke-width: 0.8"/> <use xlink:href="#mf0a04b41f8" x="427.893636" y="188.44" style="stroke: #000000; stroke-width: 0.8"/>
</g> </g>
</g> </g>
<g id="text_8"> <g id="text_8">
@ -446,11 +445,11 @@ z
<g id="line2d_17"> <g id="line2d_17">
<path d="M 478.622727 188.44 <path d="M 478.622727 188.44
L 478.622727 25.44 L 478.622727 25.44
" clip-path="url(#p448fd06892)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> " 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"/>
</g> </g>
<g id="line2d_18"> <g id="line2d_18">
<g> <g>
<use xlink:href="#mfeb5fcddc7" x="478.622727" y="188.44" style="stroke: #000000; stroke-width: 0.8"/> <use xlink:href="#mf0a04b41f8" x="478.622727" y="188.44" style="stroke: #000000; stroke-width: 0.8"/>
</g> </g>
</g> </g>
<g id="text_9"> <g id="text_9">
@ -505,11 +504,11 @@ z
<g id="line2d_19"> <g id="line2d_19">
<path d="M 529.351818 188.44 <path d="M 529.351818 188.44
L 529.351818 25.44 L 529.351818 25.44
" clip-path="url(#p448fd06892)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> " 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"/>
</g> </g>
<g id="line2d_20"> <g id="line2d_20">
<g> <g>
<use xlink:href="#mfeb5fcddc7" x="529.351818" y="188.44" style="stroke: #000000; stroke-width: 0.8"/> <use xlink:href="#mf0a04b41f8" x="529.351818" y="188.44" style="stroke: #000000; stroke-width: 0.8"/>
</g> </g>
</g> </g>
<g id="text_10"> <g id="text_10">
@ -555,11 +554,11 @@ z
<g id="line2d_21"> <g id="line2d_21">
<path d="M 580.080909 188.44 <path d="M 580.080909 188.44
L 580.080909 25.44 L 580.080909 25.44
" clip-path="url(#p448fd06892)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> " 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"/>
</g> </g>
<g id="line2d_22"> <g id="line2d_22">
<g> <g>
<use xlink:href="#mfeb5fcddc7" x="580.080909" y="188.44" style="stroke: #000000; stroke-width: 0.8"/> <use xlink:href="#mf0a04b41f8" x="580.080909" y="188.44" style="stroke: #000000; stroke-width: 0.8"/>
</g> </g>
</g> </g>
<g id="text_11"> <g id="text_11">
@ -574,11 +573,11 @@ L 580.080909 25.44
<g id="line2d_23"> <g id="line2d_23">
<path d="M 630.81 188.44 <path d="M 630.81 188.44
L 630.81 25.44 L 630.81 25.44
" clip-path="url(#p448fd06892)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/> " 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"/>
</g> </g>
<g id="line2d_24"> <g id="line2d_24">
<g> <g>
<use xlink:href="#mfeb5fcddc7" x="630.81" y="188.44" style="stroke: #000000; stroke-width: 0.8"/> <use xlink:href="#mf0a04b41f8" x="630.81" y="188.44" style="stroke: #000000; stroke-width: 0.8"/>
</g> </g>
</g> </g>
<g id="text_12"> <g id="text_12">
@ -724,12 +723,12 @@ z
<g id="ytick_1"> <g id="ytick_1">
<g id="line2d_25"> <g id="line2d_25">
<defs> <defs>
<path id="m2b8ef16b3a" d="M 0 0 <path id="mc0b9ff744f" d="M 0 0
L -3.5 0 L -3.5 0
" style="stroke: #000000; stroke-width: 0.8"/> " style="stroke: #000000; stroke-width: 0.8"/>
</defs> </defs>
<g> <g>
<use xlink:href="#m2b8ef16b3a" x="72.79" y="48.829483" style="stroke: #000000; stroke-width: 0.8"/> <use xlink:href="#mc0b9ff744f" x="72.79" y="48.829483" style="stroke: #000000; stroke-width: 0.8"/>
</g> </g>
</g> </g>
<g id="text_14"> <g id="text_14">
@ -843,7 +842,7 @@ z
<g id="ytick_2"> <g id="ytick_2">
<g id="line2d_26"> <g id="line2d_26">
<g> <g>
<use xlink:href="#m2b8ef16b3a" x="72.79" y="106.94" style="stroke: #000000; stroke-width: 0.8"/> <use xlink:href="#mc0b9ff744f" x="72.79" y="106.94" style="stroke: #000000; stroke-width: 0.8"/>
</g> </g>
</g> </g>
<g id="text_15"> <g id="text_15">
@ -884,7 +883,7 @@ z
<g id="ytick_3"> <g id="ytick_3">
<g id="line2d_27"> <g id="line2d_27">
<g> <g>
<use xlink:href="#m2b8ef16b3a" x="72.79" y="165.050517" style="stroke: #000000; stroke-width: 0.8"/> <use xlink:href="#mc0b9ff744f" x="72.79" y="165.050517" style="stroke: #000000; stroke-width: 0.8"/>
</g> </g>
</g> </g>
<g id="text_16"> <g id="text_16">
@ -1320,7 +1319,7 @@ z
</g> </g>
</g> </g>
<defs> <defs>
<clipPath id="p448fd06892"> <clipPath id="pce73ba693e">
<rect x="72.79" y="25.44" width="558.02" height="163"/> <rect x="72.79" y="25.44" width="558.02" height="163"/>
</clipPath> </clipPath>
</defs> </defs>

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 142 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 157 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 194 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 230 KiB