Version 04 als eigenes Repository
Erster Commit des Strangs "Optimierte Entscheidungsfindung mit Python" (Version 04). Die Historie der 71 Commits bis zur Trennung bleibt im uebergeordneten Repository OR_mit_Python liegen, das ab jetzt nur noch Version_03 (eingefroren) verwaltet und Version_04/ ignoriert. Bewusst kein "git subtree split": Der Pfad Version_04/ existiert erst seit der Verzeichnistrennung, ein Split braechte daher nur 7 der 41 einschlaegigen Commits - eine Teilhistorie, die vollstaendig aussieht und es nicht ist. Stand: 5 Teile, 23 Kapitel, 5 Anhaenge, 292 Abschnitte, 703 Querverweise, 325 Indexmarken, 73 Beispielprogramme, 32 SVGs, 4 Plotly-Figuren, 25 Notebooks, PDF mit 715 Seiten. Zusaetzlich in diesem Commit: * pyproject.toml mit Abhaengigkeitsgruppen finance, large-scale, api, figures, dev, empfehlungen. Die abgedruckte requirements.txt bleibt unveraendert daneben bestehen. ortools steht in der Grundausstattung, highspy erst in [large-scale] - so kann der HiGHS-Symbolkonflikt bei der schlanken Installation gar nicht erst auftreten. * Dabei zwei Funde: graphviz wird von erzeuge_architektur_diagramme.py importiert, fehlt aber in requirements.txt (jetzt in [figures]); pymoo steht in requirements.txt, wird aber von keinem Programm importiert, sondern nur im Kapitel Metaheuristiken empfohlen (jetzt in [empfehlungen]). * NEUER_TITEL.md nach Kritik_und_Verbesserungsvorschlaege/ verschoben - es ist die Vorlage des Titelblatts, kein Bestandteil des Werks. Die beiden Fundstellen in PROGRESS.md und erzeuge_titelseite.py nachgezogen. * PROGRESS.md nannte noch den Untertitel der ersten Fassung; auf den tatsaechlichen aus erzeuge_titelseite.py korrigiert. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
commit
b7af2f1d9a
468 changed files with 262141 additions and 0 deletions
96
OR_HTML_04/programme/Excel_Bruecke.py
Normal file
96
OR_HTML_04/programme/Excel_Bruecke.py
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# Excel_Bruecke.py
|
||||
"""
|
||||
Kapitel Einfuehrung: Vom Excel-Solver zu Python - dieselbe Rechnung, dieselbe Datei.
|
||||
|
||||
Das Programm bildet den vollstaendigen Arbeitsweg ab, den ein Excel-Modell im
|
||||
Betrieb sonst von Hand geht:
|
||||
|
||||
Tabellenblatt lesen -> Modell bauen -> loesen -> Ergebnis zurueckschreiben
|
||||
|
||||
Damit es ohne Vorbereitung laeuft, legt es die Eingabedatei beim ersten Start
|
||||
selbst an. Ersetzen Sie sie durch Ihre eigene Datei - solange die Spalten
|
||||
gleich heissen, aendert sich am Code nichts.
|
||||
|
||||
Die vier Arbeitsschritte kommen aus or_kern.py (Kapitel Praxisfallen). Was
|
||||
hier steht, ist nur noch das, was diesen Fall ausmacht - der Rest ist
|
||||
gemeinsamer Unterbau. Wer das Modul nicht kennt: Es ist im Buch vollstaendig
|
||||
abgedruckt und liegt im selben Verzeichnis.
|
||||
|
||||
Erzeugte Dateien (im Arbeitsverzeichnis):
|
||||
produktionsmix.xlsx Eingabe: Blaetter 'Produkte' und 'Kapazitaeten'
|
||||
produktionsmix_ergebnis.xlsx Ausgabe: Blaetter 'Plan' und 'Kennzahlen'
|
||||
|
||||
Benoetigt: pandas, openpyxl, ortools, pydantic (ueber or_kern)
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
|
||||
import pandas as pd
|
||||
|
||||
from or_kern import (lade_produktionsproblem, loese_mit_glop, pruefe_loesung,
|
||||
schreibe_ergebnis)
|
||||
|
||||
EINGABE = "produktionsmix.xlsx"
|
||||
AUSGABE = "produktionsmix_ergebnis.xlsx"
|
||||
|
||||
|
||||
def lege_beispieldatei_an(pfad: str) -> None:
|
||||
"""Schreibt die Eingabemappe, wie sie auch aus dem Controlling kaeme."""
|
||||
produkte = pd.DataFrame({
|
||||
"Produkt": ["Tisch", "Stuhl", "Regal"],
|
||||
"Deckungsbeitrag": [240.0, 60.0, 130.0],
|
||||
"Montagestunden": [3.0, 1.0, 2.0],
|
||||
"Plattenmaterial": [6.0, 1.0, 4.0],
|
||||
})
|
||||
kapazitaeten = pd.DataFrame({
|
||||
"Ressource": ["Montagestunden", "Plattenmaterial"],
|
||||
"Verfuegbar": [150.0, 240.0],
|
||||
})
|
||||
with pd.ExcelWriter(pfad, engine="openpyxl") as mappe:
|
||||
produkte.to_excel(mappe, sheet_name="Produkte", index=False)
|
||||
kapazitaeten.to_excel(mappe, sheet_name="Kapazitaeten", index=False)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if not os.path.exists(EINGABE):
|
||||
lege_beispieldatei_an(EINGABE)
|
||||
print(f"Beispiel-Eingabedatei angelegt: {EINGABE}")
|
||||
|
||||
# 1. Lesen und pruefen. Faellt hier etwas auf, ist der Fehler noch
|
||||
# zuzuordnen - spaeter waere er nur noch eine merkwuerdige Zahl.
|
||||
problem = lade_produktionsproblem(EINGABE)
|
||||
|
||||
# 2. Loesen. Einzige solverabhaengige Zeile des ganzen Programms -
|
||||
# 'loese_mit_scipy' waere ein Einzeiler-Wechsel.
|
||||
loesung = loese_mit_glop(problem)
|
||||
|
||||
# 3. Abnahmepruefung gegen die Anforderungen, ohne den Solver zu fragen.
|
||||
beanstandungen = pruefe_loesung(problem, loesung)
|
||||
if beanstandungen:
|
||||
raise SystemExit("Abnahmepruefung fehlgeschlagen:\n - "
|
||||
+ "\n - ".join(beanstandungen))
|
||||
|
||||
# 4. Zurueckschreiben - im Format, das die Fachabteilung ohnehin benutzt.
|
||||
schreibe_ergebnis(AUSGABE, problem, loesung)
|
||||
|
||||
print("=" * 66)
|
||||
print(" PRODUKTIONSPLAN AUS DER EXCEL-MAPPE")
|
||||
print("=" * 66)
|
||||
for produkt in problem.produkte:
|
||||
menge = loesung.werte[produkt.name]
|
||||
print(f"{produkt.name:<18} {menge:8.1f} Stueck "
|
||||
f"{menge * produkt.deckungsbeitrag:12,.2f} EUR")
|
||||
print("-" * 66)
|
||||
print(loesung.als_bericht())
|
||||
print("Abnahmepruefung: bestanden\n")
|
||||
|
||||
# Die Schattenpreise beantworten die Frage, die der Plan nicht stellt:
|
||||
# Was waere eine zusaetzliche Einheit dieser Ressource wert?
|
||||
for ressource, preis in loesung.schattenpreise.items():
|
||||
print(f" eine Einheit {ressource:<18} mehr waere wert: {preis:7.2f} EUR")
|
||||
print("=" * 66)
|
||||
print(f"Ergebnis geschrieben nach: {AUSGABE}")
|
||||
Loading…
Reference in a new issue