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>
797 lines
100 KiB
HTML
797 lines
100 KiB
HTML
<!doctype html>
|
||
<html lang="de">
|
||
<head>
|
||
<meta charset="utf-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||
<title>Kapitel 4: Vom Management-Wunsch zum Modell · Optimierte Entscheidungsfindung mit Python</title>
|
||
<script>
|
||
(function () {
|
||
try {
|
||
var t = localStorage.getItem("or-theme");
|
||
if (t) document.documentElement.setAttribute("data-theme", t);
|
||
} catch (e) {}
|
||
})();
|
||
</script>
|
||
<link rel="stylesheet" href="assets/highlight.css" />
|
||
<link rel="stylesheet" href="katex/katex.min.css" />
|
||
<script defer="" src="katex/katex.min.js"></script>
|
||
<script>document.addEventListener("DOMContentLoaded", function () {
|
||
var mathElements = document.getElementsByClassName("math");
|
||
var macros = [];
|
||
for (var i = 0; i < mathElements.length; i++) {
|
||
var texText = mathElements[i].firstChild;
|
||
if (mathElements[i].tagName == "SPAN") {
|
||
katex.render(texText.data, mathElements[i], {
|
||
displayMode: mathElements[i].classList.contains('display'),
|
||
throwOnError: false,
|
||
macros: macros,
|
||
fleqn: false
|
||
});
|
||
}}
|
||
// Der Browser springt zu einem #anker in der URL schon beim ersten Rendern
|
||
// an, BEVOR die KaTeX-Formeln oben im Text ihre finale Hoehe bekommen -
|
||
// durch den Reflow landet der Anker danach zu weit unten. Nach dem
|
||
// Formel-Rendering hier erneut zum Anker springen, das behebt es.
|
||
if (location.hash) {
|
||
var ziel = document.getElementById(decodeURIComponent(location.hash.slice(1)));
|
||
if (ziel) ziel.scrollIntoView({behavior: "instant", block: "start"});
|
||
}
|
||
});
|
||
</script>
|
||
<link rel="stylesheet" href="assets/site.css" />
|
||
</head>
|
||
<body>
|
||
<svg style="display:none" aria-hidden="true"><symbol id="icon-menu" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
|
||
<line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1="12" x2="21" y2="12"/><line x1="3" y1="18" x2="21" y2="18"/>
|
||
</symbol>
|
||
<symbol id="icon-search" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
|
||
<circle cx="11" cy="11" r="7"/><line x1="21" y1="21" x2="16.2" y2="16.2"/>
|
||
</symbol>
|
||
<symbol id="icon-sun" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
|
||
<circle cx="12" cy="12" r="4.5"/>
|
||
<line x1="12" y1="1.5" x2="12" y2="4"/><line x1="12" y1="20" x2="12" y2="22.5"/>
|
||
<line x1="1.5" y1="12" x2="4" y2="12"/><line x1="20" y1="12" x2="22.5" y2="12"/>
|
||
<line x1="4.5" y1="4.5" x2="6.2" y2="6.2"/><line x1="17.8" y1="17.8" x2="19.5" y2="19.5"/>
|
||
<line x1="19.5" y1="4.5" x2="17.8" y2="6.2"/><line x1="6.2" y1="17.8" x2="4.5" y2="19.5"/>
|
||
</symbol>
|
||
<symbol id="icon-moon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<path d="M20 14.5A8.5 8.5 0 1 1 9.5 4a6.8 6.8 0 0 0 10.5 10.5z"/>
|
||
</symbol>
|
||
<symbol id="icon-chevron-left" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<polyline points="15 4 7 12 15 20"/>
|
||
</symbol>
|
||
<symbol id="icon-chevron-right" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<polyline points="9 4 17 12 9 20"/>
|
||
</symbol>
|
||
<symbol id="icon-check" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<polyline points="4 13 9.5 18.5 20 6"/>
|
||
</symbol>
|
||
<symbol id="icon-external-link" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<path d="M18 13.5V19a1.5 1.5 0 0 1-1.5 1.5H5A1.5 1.5 0 0 1 3.5 19V7A1.5 1.5 0 0 1 5 5.5h5.5"/>
|
||
<polyline points="14.5 3.5 20.5 3.5 20.5 9.5"/><line x1="11" y1="13" x2="20" y2="4"/>
|
||
</symbol>
|
||
<symbol id="icon-book" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<path d="M4 5.5A2 2 0 0 1 6 4h6v16H6a2 2 0 0 0-2 1.5z"/>
|
||
<path d="M20 5.5A2 2 0 0 0 18 4h-6v16h6a2 2 0 0 1 2 1.5z"/>
|
||
</symbol>
|
||
<symbol id="icon-copy" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/>
|
||
</symbol>
|
||
<symbol id="icon-download" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<path d="M12 3v12"/><polyline points="7 10 12 15 17 10"/><path d="M4 19.5h16"/>
|
||
</symbol></svg>
|
||
<header class="site-header">
|
||
<button type="button" class="icon-btn" id="sidebar-toggle" aria-label="Menü öffnen"><svg class="icon" aria-hidden="true"><use href="#icon-menu"></use></svg></button>
|
||
<a class="brand" href="index.html"><svg class="icon" aria-hidden="true"><use href="#icon-book"></use></svg> <span>Optimierte Entscheidungsfindung mit Python</span></a>
|
||
<div class="site-search">
|
||
<input id="suche-eingabe" type="search" placeholder="Suchen …" aria-label="Suche" autocomplete="off" />
|
||
<svg class="icon such-icon" aria-hidden="true"><use href="#icon-search"></use></svg>
|
||
<div id="suche-ergebnisse" class="suche-ergebnisse" hidden></div>
|
||
</div>
|
||
<button type="button" class="icon-btn" id="theme-toggle" aria-label="Darstellung umschalten">
|
||
<svg class="icon icon-sun" aria-hidden="true"><use href="#icon-sun"></use></svg><svg class="icon icon-moon" aria-hidden="true"><use href="#icon-moon"></use></svg>
|
||
</button>
|
||
</header>
|
||
<div class="site-body">
|
||
<div class="sidebar-overlay" id="sidebar-overlay" hidden></div>
|
||
<nav class="sidebar" id="sidebar" aria-label="Kapitelnavigation"><div class="sidebar-inhalt"><details class="sidebar-gruppe"><summary>Einstieg</summary><ul><li data-kapitel="vorwort.html"><a href="vorwort.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Vorwort & Lesehilfe</span></a></li><li data-kapitel="notation.html"><a href="notation.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Notation & Abkürzungen</span></a></li></ul></details><details class="sidebar-gruppe" open><summary>Teil I: Grundlagen des Operations Research</summary><ul><li data-kapitel="einfuehrung.html"><a href="einfuehrung.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Kapitel 1: Einführung in Operations Research — Vom Ursprung zur mathematischen Entscheidungsfindung</span></a></li><li data-kapitel="fundament.html"><a href="fundament.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Kapitel 2: Das mathematische Fundament — Vektoren, Matrizen, Konvexität</span></a></li><li data-kapitel="oekosystem.html"><a href="oekosystem.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Kapitel 3: Das Python-Ökosystem für OR — Solver, Bindings und Modellierungsschichten</span></a></li><li data-kapitel="modellierung.html" class="aktiv"><a href="modellierung.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Kapitel 4: Vom Management-Wunsch zum Modell</span></a></li></ul></details><details class="sidebar-gruppe"><summary>Teil II: Die Kernverfahren der deterministischen Optimierung</summary><ul><li data-kapitel="lp.html"><a href="lp.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Kapitel 5: Lineare Programmierung — Simplex, Dualität und Schattenpreise</span></a></li><li data-kapitel="milp.html"><a href="milp.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Kapitel 6: Gemischt-ganzzahlige Optimierung — Diskrete Entscheidungen und Branch-and-Bound</span></a></li><li data-kapitel="cpsat.html"><a href="cpsat.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Kapitel 7: Constraint Programming mit CP-SAT — Logik, Scheduling und Zuweisung</span></a></li><li data-kapitel="graphen.html"><a href="graphen.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Kapitel 8: Graphen, Flüsse und Touren — Min-Cost-Flow, Matching und VRP</span></a></li><li data-kapitel="metaheuristiken.html"><a href="metaheuristiken.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Kapitel 9: Metaheuristiken — wenn der exakte Solver aussteigt</span></a></li><li data-kapitel="dekomposition.html"><a href="dekomposition.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Kapitel 10: Spaltengenerierung — das Modell umbauen statt die Lösung raten</span></a></li></ul></details><details class="sidebar-gruppe"><summary>Teil III: Nichtlinearität, Unsicherheit und mehrperiodige Dynamik</summary><ul><li data-kapitel="qp-nlp.html"><a href="qp-nlp.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Kapitel 11: Quadratische und nichtlineare Optimierung — KKT, Lagrange, Konvexität</span></a></li><li data-kapitel="unsicherheit.html"><a href="unsicherheit.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Kapitel 12: Optimierung unter Unsicherheit — Monte-Carlo, Stochastik, Robustheit</span></a></li><li data-kapitel="dynamische-programmierung.html"><a href="dynamische-programmierung.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Kapitel 13: Dynamische Programmierung — Die Bellman-Gleichung und Order-Execution</span></a></li><li data-kapitel="mehrziel.html"><a href="mehrziel.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Kapitel 14: Mehrere Ziele — Pareto-Fronten statt Gewichte</span></a></li><li data-kapitel="prognose.html"><a href="prognose.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Kapitel 15: Predict-then-Optimize — die bessere Prognose, die schlechtere Entscheidung</span></a></li></ul></details><details class="sidebar-gruppe"><summary>Teil IV: Anwendungen — Energiewirtschaft und Finanzmärkte</summary><ul><li data-kapitel="bruecke.html"><a href="bruecke.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Kapitel 16: Die Strukturbrücke — dieselbe Mathematik, zwei Welten</span></a></li><li data-kapitel="supplychain.html"><a href="supplychain.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Kapitel 17: Supply-Chain und Energieeinsatz unter Unsicherheit</span></a></li><li data-kapitel="finanzdaten.html"><a href="finanzdaten.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Kapitel 18: Finanzdaten-Modellierung — Renditen, Kovarianz und Shrinkage</span></a></li><li data-kapitel="markowitz.html"><a href="markowitz.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Kapitel 19: Die moderne Portfoliotheorie nach Markowitz</span></a></li><li data-kapitel="cvar.html"><a href="cvar.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Kapitel 20: Tail-Risiko, CVaR und Transaktionskosten</span></a></li><li data-kapitel="handelsmaschine.html"><a href="handelsmaschine.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Kapitel 21: Die vollständige quantitative Handelsmaschine</span></a></li></ul></details><details class="sidebar-gruppe"><summary>Teil V: Praxis</summary><ul><li data-kapitel="praxisfallen.html"><a href="praxisfallen.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Kapitel 22: Praxisfallen und der Weg zum produktiven Einsatz</span></a></li><li data-kapitel="testing.html"><a href="testing.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Kapitel 23: Testen, Messen, Ausliefern</span></a></li><li data-kapitel="projektwerkstatt.html"><a href="projektwerkstatt.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Projektwerkstatt</span></a></li></ul></details><details class="sidebar-gruppe"><summary>Anhänge</summary><ul><li data-kapitel="anhang-loesungen.html"><a href="anhang-loesungen.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Anhang A: Lösungen zu allen Übungsaufgaben</span></a></li><li data-kapitel="anhang-modellierungsmuster.html"><a href="anhang-modellierungsmuster.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Anhang B: Katalog der Modellierungsmuster</span></a></li><li data-kapitel="anhang-fehlerdiagnose.html"><a href="anhang-fehlerdiagnose.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Anhang C: Fehlerdiagnose-Handbuch</span></a></li><li data-kapitel="anhang-spickzettel.html"><a href="anhang-spickzettel.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Anhang D: Spickzettel der Solver</span></a></li><li data-kapitel="anhang-glossar-literatur.html"><a href="anhang-glossar-literatur.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Anhang E: Glossar und Literatur</span></a></li></ul></details><ul class="sidebar-extra"><li><a href="programme.html"><svg class="icon" aria-hidden="true"><use href="#icon-book"></use></svg> Beispielprogramme</a></li><li><a href="stichwortverzeichnis.html"><svg class="icon" aria-hidden="true"><use href="#icon-search"></use></svg> Stichwortverzeichnis</a></li><li><a href="gesamtdokument.html"><svg class="icon" aria-hidden="true"><use href="#icon-external-link"></use></svg> Gesamtdokument (eine Seite)</a></li><li><a href="Operations_Research_mit_Python_Version_04.pdf" download><svg class="icon" aria-hidden="true"><use href="#icon-download"></use></svg> Download als PDF</a></li></ul></div></nav>
|
||
<main class="content">
|
||
<nav class="breadcrumb" aria-label="Breadcrumb"><a href="index.html">Start</a> › <span>Teil I</span> › <span>Kapitel 4: Vom Management-Wunsch zum Modell</span></nav>
|
||
<nav class="prev-next"><a class="prev-next-knopf prev-next-prev" href="oekosystem.html"><svg class="icon" aria-hidden="true"><use href="#icon-chevron-left"></use></svg><span><small>Zurück</small>Kapitel 3: Das Python-Ökosystem für OR — Solver, Bindings und Modellierungsschichten</span></a><a class="prev-next-knopf prev-next-next" href="lp.html"><span><small>Weiter</small>Kapitel 5: Lineare Programmierung — Simplex, Dualität und Schattenpreise</span><svg class="icon" aria-hidden="true"><use href="#icon-chevron-right"></use></svg></a></nav>
|
||
<article>
|
||
<h1 id="kap-modellierung">Kapitel 4: Vom Management-Wunsch zum Modell</h1>
|
||
<div class="card card-blick">
|
||
<blockquote>
|
||
<p><strong>📌 Kapitel auf einen Blick</strong></p>
|
||
<p><strong>Worum geht es?</strong> Um den Schritt, der vor jedem Solver kommt und über den kaum ein Lehrbuch spricht: aus einem Satz in einer Besprechung ein Modell zu machen. Genau hier scheitern Projekte — nicht an der Mathematik.</p>
|
||
<p><strong>Voraussetzungen:</strong> <a href="einfuehrung.html#kap-einfuehrung">Kapitel 1</a> (die vier Bausteine eines Modells). Kein Solverwissen nötig; das ganze Kapitel kommt mit einer einzigen <code>linprog</code>-Zeile aus.</p>
|
||
<p><strong>Danach können Sie:</strong> eine Anforderung daraufhin abklopfen, was sie <em>nicht</em> sagt; die Zielgröße so wählen, dass sie keinen Fehlanreiz setzt; harte von weichen Regeln unterscheiden — und begründen, warum diese Unterscheidung ein Jahr später über die Betriebsfähigkeit entscheidet.</p>
|
||
<p><strong>Zeitbedarf:</strong> ca. 3 Stunden.</p>
|
||
<p><strong>Programme:</strong><br />
|
||
<code>Vom_Wunsch_zum_Modell.py</code></p>
|
||
<p><strong>Notebook:</strong> <a href="Notebooks_04/modellierung.ipynb">modellierung.ipynb</a><br />
|
||
<a href="https://colab.research.google.com/github/dschlueter/or-mit-python/blob/main/Notebooks_04/modellierung.ipynb">In Google Colab öffnen</a></p>
|
||
</blockquote>
|
||
</div>
|
||
<hr />
|
||
<h2 id="sec:modellierung-schnellstart">4.1 In 5 Minuten gelöst</h2>
|
||
<div class="card card-schnellstart">
|
||
<blockquote>
|
||
<p><strong>🚀 In 5 Minuten gelöst: „Maximieren Sie den Umsatz”</strong></p>
|
||
<p>Eine Lohnfertigung hat fünf Anfragen und 60 freie Maschinenstunden. Die Anfragen verlangen zusammen 160 Stunden — es muss ausgewählt werden.</p>
|
||
<table>
|
||
<thead>
|
||
<tr class="header">
|
||
<th>Auftrag</th>
|
||
<th style="text-align: right;">Stunden</th>
|
||
<th style="text-align: right;">Umsatz</th>
|
||
<th style="text-align: right;">Material</th>
|
||
<th style="text-align: right;">Deckungsbeitrag</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr class="odd">
|
||
<td><strong>A</strong></td>
|
||
<td style="text-align: right;">60</td>
|
||
<td style="text-align: right;">60 000 €</td>
|
||
<td style="text-align: right;">55 000 €</td>
|
||
<td style="text-align: right;">5 000 €</td>
|
||
</tr>
|
||
<tr class="even">
|
||
<td><strong>B</strong></td>
|
||
<td style="text-align: right;">30</td>
|
||
<td style="text-align: right;">22 000 €</td>
|
||
<td style="text-align: right;">12 000 €</td>
|
||
<td style="text-align: right;">10 000 €</td>
|
||
</tr>
|
||
<tr class="odd">
|
||
<td><strong>C</strong></td>
|
||
<td style="text-align: right;">30</td>
|
||
<td style="text-align: right;">20 000 €</td>
|
||
<td style="text-align: right;">11 000 €</td>
|
||
<td style="text-align: right;">9 000 €</td>
|
||
</tr>
|
||
<tr class="even">
|
||
<td><strong>D</strong></td>
|
||
<td style="text-align: right;">25</td>
|
||
<td style="text-align: right;">18 000 €</td>
|
||
<td style="text-align: right;">9 000 €</td>
|
||
<td style="text-align: right;">9 000 €</td>
|
||
</tr>
|
||
<tr class="odd">
|
||
<td><strong>E</strong></td>
|
||
<td style="text-align: right;">15</td>
|
||
<td style="text-align: right;">12 000 €</td>
|
||
<td style="text-align: right;">7 000 €</td>
|
||
<td style="text-align: right;">5 000 €</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<div class="sourceCode" id="cb1"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> numpy <span class="im">as</span> np</span>
|
||
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="im">from</span> scipy.optimize <span class="im">import</span> linprog</span>
|
||
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="co"># Auftrag: A B C D E</span></span>
|
||
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>stunden <span class="op">=</span> np.array([ <span class="dv">60</span>, <span class="dv">30</span>, <span class="dv">30</span>, <span class="dv">25</span>, <span class="dv">15</span>], dtype<span class="op">=</span><span class="bu">float</span>)</span>
|
||
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>umsatz <span class="op">=</span> np.array([ <span class="dv">60_000</span>, <span class="dv">22_000</span>, <span class="dv">20_000</span>, <span class="dv">18_000</span>, <span class="dv">12_000</span>], dtype<span class="op">=</span><span class="bu">float</span>)</span>
|
||
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>material <span class="op">=</span> np.array([ <span class="dv">55_000</span>, <span class="dv">12_000</span>, <span class="dv">11_000</span>, <span class="dv">9_000</span>, <span class="dv">7_000</span>], dtype<span class="op">=</span><span class="bu">float</span>)</span>
|
||
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>KAPAZITAET <span class="op">=</span> <span class="dv">60</span> <span class="co"># Maschinenstunden; die Anfragen verlangen 160</span></span>
|
||
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>waehle <span class="op">=</span> <span class="kw">lambda</span> ziel: np.<span class="bu">round</span>(linprog(</span>
|
||
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a> <span class="op">-</span>ziel, A_ub<span class="op">=</span>[stunden], b_ub<span class="op">=</span>[KAPAZITAET],</span>
|
||
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a> bounds<span class="op">=</span>(<span class="dv">0</span>, <span class="dv">1</span>), integrality<span class="op">=</span><span class="dv">1</span>, method<span class="op">=</span><span class="st">"highs"</span>).x).astype(<span class="bu">int</span>)</span>
|
||
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a><span class="cf">for</span> wunsch, ziel <span class="kw">in</span> [(<span class="st">"Umsatz maximieren"</span>, umsatz),</span>
|
||
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a> (<span class="st">"Deckungsbeitrag maximieren"</span>, umsatz <span class="op">-</span> material)]:</span>
|
||
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a> plan <span class="op">=</span> waehle(ziel)</span>
|
||
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f"</span><span class="sc">{</span>wunsch<span class="sc">:<27}</span><span class="ss"> -> </span><span class="sc">{</span><span class="st">''</span><span class="sc">.</span>join(b <span class="cf">for</span> b, ja <span class="kw">in</span> <span class="bu">zip</span>(<span class="st">'ABCDE'</span>, plan) <span class="cf">if</span> ja)<span class="sc">:<5}</span><span class="ss">"</span></span>
|
||
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a> <span class="ss">f" Umsatz </span><span class="sc">{</span>umsatz <span class="op">@</span> plan<span class="sc">:>7,.0f}</span><span class="ss"> DB </span><span class="sc">{</span>(umsatz <span class="op">-</span> material) <span class="op">@</span> plan<span class="sc">:>6,.0f}</span><span class="ss">"</span>)</span></code></pre></div>
|
||
<p><strong>Ausgabe:</strong></p>
|
||
<pre><code>Umsatz maximieren -> A Umsatz 60,000 DB 5,000
|
||
Deckungsbeitrag maximieren -> BD Umsatz 40,000 DB 19,000</code></pre>
|
||
</blockquote>
|
||
</div>
|
||
<p><strong>Und jetzt der Punkt.</strong> Beide Modelle sind korrekt. Beide Pläne sind zulässig. Beide sind <em>optimal</em> — nur für verschiedene Fragen.</p>
|
||
<p>Wer „Umsatz maximieren” sagt, bekommt Auftrag A: 60 000 € Umsatz und 5 000 € Deckungsbeitrag. Wer „Deckungsbeitrag maximieren” sagt, bekommt B und D: 20 000 € weniger Umsatz und <strong>14 000 € mehr Ergebnis</strong>. Der Umsatzplan verkauft die gesamte Kapazität für eine Marge von 8 %.</p>
|
||
<p>Niemand in der Besprechung hätte behauptet, Umsatz sei wichtiger als Ertrag. Der Satz „maximieren Sie den Umsatz” ist trotzdem gefallen, weil Umsatz die Zahl ist, die im Monatsbericht steht.</p>
|
||
<blockquote>
|
||
<p><strong>🎯 Merksatz</strong> Ein Modell rechnet nicht aus, was man will, sondern was man aufgeschrieben hat. Die Differenz zwischen beidem ist die eigentliche Arbeit dieses Kapitels.</p>
|
||
</blockquote>
|
||
<p><strong>Warum funktioniert das?</strong> Weil eine Zielfunktion eine <strong>vollständige</strong> Aussage darüber ist, was zählt. Alles, was nicht darin steht, ist dem Modell gleichgültig — nicht „weniger wichtig”, sondern <strong>wertlos</strong>. Der Umsatzplan opfert den Deckungsbeitrag nicht aus Bosheit; er sieht ihn schlicht nicht.</p>
|
||
<hr />
|
||
<h2 id="sec:modellierung-lernziele">4.2 Lernziele</h2>
|
||
<p>Nach diesem Kapitel können Sie …</p>
|
||
<ol type="1">
|
||
<li>… erklären, warum die Zielgröße die folgenreichste Entscheidung eines OR-Projekts ist — folgenreicher als die Wahl des Solvers.</li>
|
||
<li>… die vier Fragen stellen, die aus einer Anforderung ein Modell machen.</li>
|
||
<li>… erkennen, dass ein Satz wie „Stammkunden dürfen wir nicht verlieren” mehrere Lesarten hat, und den Unterschied in Euro beziffern.</li>
|
||
<li>… begründen, wann eine Regel hart und wann sie weich sein muss — und was eine harte Regel im Betrieb anrichtet, wenn sie einmal nicht erfüllbar ist.</li>
|
||
<li>… einen Kennzahlen-Fehlanreiz benennen, bevor er in die Zielfunktion gerät.</li>
|
||
</ol>
|
||
<hr />
|
||
<h2 id="sec:modellierung-vier-fragen">4.3 Ein Satz ist noch kein Modell</h2>
|
||
<p>Was aus einer Besprechung mitkommt, klingt meist so:</p>
|
||
<blockquote>
|
||
<p><em>„Wir müssen die Maschinen besser auslasten. Und die Stammkunden dürfen wir nicht verlieren.”</em></p>
|
||
</blockquote>
|
||
<p>Zwei Sätze, aus denen ein Modell werden soll. Sie enthalten: keine Entscheidungsvariable, keine messbare Zielgröße, keine Nebenbedingung. Sie enthalten nicht einmal genug, um zu erkennen, <em>was</em> entschieden werden soll.</p>
|
||
<p>Der Weg dorthin führt über vier Fragen. Sie sind unspektakulär, und genau deshalb werden sie übersprungen.</p>
|
||
<table>
|
||
<colgroup>
|
||
<col style="width: 33%" />
|
||
<col style="width: 33%" />
|
||
<col style="width: 33%" />
|
||
</colgroup>
|
||
<thead>
|
||
<tr class="header">
|
||
<th>#</th>
|
||
<th>Frage</th>
|
||
<th>Was ohne sie passiert</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr class="odd">
|
||
<td>1</td>
|
||
<td><strong>Worüber wird entschieden?</strong> Welche Größen kann der Betrieb tatsächlich festlegen?</td>
|
||
<td>Man modelliert Dinge, die gar nicht zur Disposition stehen — oder übersieht die eine Stellschraube, um die es geht.</td>
|
||
</tr>
|
||
<tr class="even">
|
||
<td>2</td>
|
||
<td><strong>Woran wird der Erfolg gemessen?</strong> Welche Zahl steht am Jahresende im Bericht?</td>
|
||
<td>Man optimiert eine Kennzahl, die niemanden interessiert — oder eine, deren Maximierung schadet.</td>
|
||
</tr>
|
||
<tr class="odd">
|
||
<td>3</td>
|
||
<td><strong>Was ist unverhandelbar, was nur unerwünscht?</strong></td>
|
||
<td>Jede unnötig harte Regel ist eine Zeitbombe: Irgendwann ist sie nicht erfüllbar, und das System antwortet gar nicht mehr.</td>
|
||
</tr>
|
||
<tr class="even">
|
||
<td>4</td>
|
||
<td><strong>Was passiert, wenn es nicht geht?</strong></td>
|
||
<td>Der Nachtlauf bricht ab, und niemand weiß, welche Regel schuld war.</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<blockquote>
|
||
<p><strong>📖 Zur zweiten Frage</strong></p>
|
||
<p>Sie ist absichtlich anders gestellt als „Was ist Ihnen wichtig?“. Auf diese Frage antwortet jeder Betrieb mit einer Liste, in der alles wichtig ist. Die brauchbare Frage lautet: <strong>Welche Zahl steht am Jahresende im Bericht, und wer wird danach beurteilt?</strong></p>
|
||
<p>Die Antwort ist unbequem und aufschlussreich — und sie erklärt, warum in der Besprechung „Umsatz” gesagt wird, obwohl „Deckungsbeitrag” gemeint ist.</p>
|
||
</blockquote>
|
||
<hr />
|
||
<h2 id="sec:modellierung-fuenf-modelle">4.4 Derselbe Datensatz, fünf Modelle</h2>
|
||
<p>Das Programm dieses Kapitels arbeitet die vier Fragen an einer Auftragsannahme ab: 14 Anfragen verlangen 800 Maschinenstunden, verfügbar sind 300.</p>
|
||
<p>Es ist bewusst das <strong>einfachste Modell des ganzen Buchs</strong> — eine Binärvariable je Auftrag, eine Nebenbedingung. Alles, was sich zwischen den fünf Varianten ändert, ist die Frage.</p>
|
||
<div class="sourceCode" id="cb3"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="co">#!/usr/bin/env python3</span></span>
|
||
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="co"># Vom_Wunsch_zum_Modell.py</span></span>
|
||
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="co">"""</span></span>
|
||
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a><span class="co">Kapitel Modellierung: Derselbe Datensatz, fuenf zulaessige Modelle, fuenf andere Plaene.</span></span>
|
||
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a><span class="co">Eine Lohnfertigung kann nicht alle Anfragen annehmen: 14 Auftraege verlangen</span></span>
|
||
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a><span class="co">zusammen 800 Maschinenstunden, verfuegbar sind 300. Es muss also ausgewaehlt</span></span>
|
||
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a><span class="co">werden. Die Daten stehen fest - was FEHLT, ist die Frage.</span></span>
|
||
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a><span class="co">Das Programm zeigt in vier Teilen, was daran haengt:</span></span>
|
||
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a><span class="co"> 1. Drei naheliegende Ziele aus dem Managementgespraech ("Umsatz", "Auslastung",</span></span>
|
||
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a><span class="co"> "Deckungsbeitrag") - und wie weit die Plaene auseinanderlaufen.</span></span>
|
||
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a><span class="co"> 2. Der Satz "Stammkunden duerfen wir nicht verlieren" in drei Lesarten. Alle</span></span>
|
||
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true" tabindex="-1"></a><span class="co"> drei sind vertretbar, alle drei kosten unterschiedlich viel.</span></span>
|
||
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true" tabindex="-1"></a><span class="co"> 3. Was ein Strafgewicht daraus macht - und ab wann es dasselbe tut wie eine</span></span>
|
||
<span id="cb3-18"><a href="#cb3-18" aria-hidden="true" tabindex="-1"></a><span class="co"> harte Regel.</span></span>
|
||
<span id="cb3-19"><a href="#cb3-19" aria-hidden="true" tabindex="-1"></a><span class="co"> 4. Was die harte Lesart ein Quartal spaeter anrichtet.</span></span>
|
||
<span id="cb3-20"><a href="#cb3-20" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-21"><a href="#cb3-21" aria-hidden="true" tabindex="-1"></a><span class="co">Der Punkt des Kapitels: Nicht die Daten bestimmen das Modell, sondern die</span></span>
|
||
<span id="cb3-22"><a href="#cb3-22" aria-hidden="true" tabindex="-1"></a><span class="co">Frage. Und die steht selten in der Anforderung.</span></span>
|
||
<span id="cb3-23"><a href="#cb3-23" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-24"><a href="#cb3-24" aria-hidden="true" tabindex="-1"></a><span class="co">Benoetigt: numpy, scipy</span></span>
|
||
<span id="cb3-25"><a href="#cb3-25" aria-hidden="true" tabindex="-1"></a><span class="co">"""</span></span>
|
||
<span id="cb3-26"><a href="#cb3-26" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-27"><a href="#cb3-27" aria-hidden="true" tabindex="-1"></a><span class="im">from</span> __future__ <span class="im">import</span> annotations</span>
|
||
<span id="cb3-28"><a href="#cb3-28" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-29"><a href="#cb3-29" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> numpy <span class="im">as</span> np</span>
|
||
<span id="cb3-30"><a href="#cb3-30" aria-hidden="true" tabindex="-1"></a><span class="im">from</span> scipy.optimize <span class="im">import</span> linprog</span>
|
||
<span id="cb3-31"><a href="#cb3-31" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-32"><a href="#cb3-32" aria-hidden="true" tabindex="-1"></a><span class="co"># (Nummer, Kunde, Stammkunde?, Maschinenstunden, Umsatz, Materialkosten)</span></span>
|
||
<span id="cb3-33"><a href="#cb3-33" aria-hidden="true" tabindex="-1"></a>AUFTRAEGE <span class="op">=</span> [</span>
|
||
<span id="cb3-34"><a href="#cb3-34" aria-hidden="true" tabindex="-1"></a> (<span class="st">"A-101"</span>, <span class="st">"Weber GmbH"</span>, <span class="va">True</span>, <span class="dv">40</span>, <span class="dv">28_000</span>, <span class="dv">19_000</span>),</span>
|
||
<span id="cb3-35"><a href="#cb3-35" aria-hidden="true" tabindex="-1"></a> (<span class="st">"A-102"</span>, <span class="st">"Weber GmbH"</span>, <span class="va">True</span>, <span class="dv">25</span>, <span class="dv">15_000</span>, <span class="dv">9_500</span>),</span>
|
||
<span id="cb3-36"><a href="#cb3-36" aria-hidden="true" tabindex="-1"></a> (<span class="st">"A-103"</span>, <span class="st">"Kranz AG"</span>, <span class="va">True</span>, <span class="dv">60</span>, <span class="dv">33_000</span>, <span class="dv">24_000</span>),</span>
|
||
<span id="cb3-37"><a href="#cb3-37" aria-hidden="true" tabindex="-1"></a> (<span class="st">"A-104"</span>, <span class="st">"Kranz AG"</span>, <span class="va">True</span>, <span class="dv">35</span>, <span class="dv">19_000</span>, <span class="dv">13_500</span>),</span>
|
||
<span id="cb3-38"><a href="#cb3-38" aria-hidden="true" tabindex="-1"></a> (<span class="st">"A-105"</span>, <span class="st">"Obermeier KG"</span>, <span class="va">True</span>, <span class="dv">20</span>, <span class="dv">12_000</span>, <span class="dv">7_000</span>),</span>
|
||
<span id="cb3-39"><a href="#cb3-39" aria-hidden="true" tabindex="-1"></a> (<span class="st">"A-106"</span>, <span class="st">"Siedler & Co"</span>, <span class="va">False</span>, <span class="dv">120</span>, <span class="dv">84_000</span>, <span class="dv">71_000</span>),</span>
|
||
<span id="cb3-40"><a href="#cb3-40" aria-hidden="true" tabindex="-1"></a> (<span class="st">"A-107"</span>, <span class="st">"Siedler & Co"</span>, <span class="va">False</span>, <span class="dv">110</span>, <span class="dv">74_000</span>, <span class="dv">63_000</span>),</span>
|
||
<span id="cb3-41"><a href="#cb3-41" aria-hidden="true" tabindex="-1"></a> (<span class="st">"A-108"</span>, <span class="st">"Novatek"</span>, <span class="va">False</span>, <span class="dv">95</span>, <span class="dv">61_000</span>, <span class="dv">52_000</span>),</span>
|
||
<span id="cb3-42"><a href="#cb3-42" aria-hidden="true" tabindex="-1"></a> (<span class="st">"A-109"</span>, <span class="st">"Novatek"</span>, <span class="va">False</span>, <span class="dv">30</span>, <span class="dv">31_000</span>, <span class="dv">17_000</span>),</span>
|
||
<span id="cb3-43"><a href="#cb3-43" aria-hidden="true" tabindex="-1"></a> (<span class="st">"A-110"</span>, <span class="st">"Hellwig"</span>, <span class="va">False</span>, <span class="dv">15</span>, <span class="dv">17_000</span>, <span class="dv">8_000</span>),</span>
|
||
<span id="cb3-44"><a href="#cb3-44" aria-hidden="true" tabindex="-1"></a> (<span class="st">"A-111"</span>, <span class="st">"Hellwig"</span>, <span class="va">False</span>, <span class="dv">55</span>, <span class="dv">41_000</span>, <span class="dv">30_000</span>),</span>
|
||
<span id="cb3-45"><a href="#cb3-45" aria-hidden="true" tabindex="-1"></a> (<span class="st">"A-112"</span>, <span class="st">"Pfeiffer Werke"</span>, <span class="va">False</span>, <span class="dv">80</span>, <span class="dv">46_000</span>, <span class="dv">39_000</span>),</span>
|
||
<span id="cb3-46"><a href="#cb3-46" aria-hidden="true" tabindex="-1"></a> (<span class="st">"A-113"</span>, <span class="st">"Obermeier KG"</span>, <span class="va">True</span>, <span class="dv">45</span>, <span class="dv">26_000</span>, <span class="dv">17_000</span>),</span>
|
||
<span id="cb3-47"><a href="#cb3-47" aria-hidden="true" tabindex="-1"></a> (<span class="st">"A-114"</span>, <span class="st">"Pfeiffer Werke"</span>, <span class="va">False</span>, <span class="dv">70</span>, <span class="dv">52_000</span>, <span class="dv">36_000</span>),</span>
|
||
<span id="cb3-48"><a href="#cb3-48" aria-hidden="true" tabindex="-1"></a>]</span>
|
||
<span id="cb3-49"><a href="#cb3-49" aria-hidden="true" tabindex="-1"></a>KAPAZITAET <span class="op">=</span> <span class="dv">300</span> <span class="co"># Maschinenstunden im Planungszeitraum</span></span>
|
||
<span id="cb3-50"><a href="#cb3-50" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-51"><a href="#cb3-51" aria-hidden="true" tabindex="-1"></a>STUNDEN <span class="op">=</span> np.array([a[<span class="dv">3</span>] <span class="cf">for</span> a <span class="kw">in</span> AUFTRAEGE], dtype<span class="op">=</span><span class="bu">float</span>)</span>
|
||
<span id="cb3-52"><a href="#cb3-52" aria-hidden="true" tabindex="-1"></a>UMSATZ <span class="op">=</span> np.array([a[<span class="dv">4</span>] <span class="cf">for</span> a <span class="kw">in</span> AUFTRAEGE], dtype<span class="op">=</span><span class="bu">float</span>)</span>
|
||
<span id="cb3-53"><a href="#cb3-53" aria-hidden="true" tabindex="-1"></a>DECKUNGSBEITRAG <span class="op">=</span> np.array([a[<span class="dv">4</span>] <span class="op">-</span> a[<span class="dv">5</span>] <span class="cf">for</span> a <span class="kw">in</span> AUFTRAEGE], dtype<span class="op">=</span><span class="bu">float</span>)</span>
|
||
<span id="cb3-54"><a href="#cb3-54" aria-hidden="true" tabindex="-1"></a>IST_STAMM <span class="op">=</span> np.array([a[<span class="dv">2</span>] <span class="cf">for</span> a <span class="kw">in</span> AUFTRAEGE])</span>
|
||
<span id="cb3-55"><a href="#cb3-55" aria-hidden="true" tabindex="-1"></a>STAMMKUNDEN <span class="op">=</span> <span class="bu">sorted</span>({a[<span class="dv">1</span>] <span class="cf">for</span> a <span class="kw">in</span> AUFTRAEGE <span class="cf">if</span> a[<span class="dv">2</span>]})</span>
|
||
<span id="cb3-56"><a href="#cb3-56" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-57"><a href="#cb3-57" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-58"><a href="#cb3-58" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> waehle_aus(ziel: np.ndarray, zusatz_ub<span class="op">=</span><span class="va">None</span>, zusatz_b_ub<span class="op">=</span><span class="va">None</span>,</span>
|
||
<span id="cb3-59"><a href="#cb3-59" aria-hidden="true" tabindex="-1"></a> zusatz_eq<span class="op">=</span><span class="va">None</span>, zusatz_b_eq<span class="op">=</span><span class="va">None</span>, auftraege<span class="op">=</span>AUFTRAEGE,</span>
|
||
<span id="cb3-60"><a href="#cb3-60" aria-hidden="true" tabindex="-1"></a> stunden<span class="op">=</span>STUNDEN, kapazitaet<span class="op">=</span>KAPAZITAET):</span>
|
||
<span id="cb3-61"><a href="#cb3-61" aria-hidden="true" tabindex="-1"></a> <span class="co">"""Ein Auftrag wird angenommen oder nicht - mehr Modell ist das nicht.</span></span>
|
||
<span id="cb3-62"><a href="#cb3-62" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-63"><a href="#cb3-63" aria-hidden="true" tabindex="-1"></a><span class="co"> Der ganze Unterschied zwischen den fuenf Varianten unten steckt in 'ziel'</span></span>
|
||
<span id="cb3-64"><a href="#cb3-64" aria-hidden="true" tabindex="-1"></a><span class="co"> und in den Zusatzbedingungen. Das Modell selbst bleibt dasselbe.</span></span>
|
||
<span id="cb3-65"><a href="#cb3-65" aria-hidden="true" tabindex="-1"></a><span class="co"> """</span></span>
|
||
<span id="cb3-66"><a href="#cb3-66" aria-hidden="true" tabindex="-1"></a> ergebnis <span class="op">=</span> linprog(</span>
|
||
<span id="cb3-67"><a href="#cb3-67" aria-hidden="true" tabindex="-1"></a> <span class="op">-</span>ziel,</span>
|
||
<span id="cb3-68"><a href="#cb3-68" aria-hidden="true" tabindex="-1"></a> A_ub<span class="op">=</span>[stunden] <span class="op">+</span> (zusatz_ub <span class="kw">or</span> []),</span>
|
||
<span id="cb3-69"><a href="#cb3-69" aria-hidden="true" tabindex="-1"></a> b_ub<span class="op">=</span>[kapazitaet] <span class="op">+</span> (zusatz_b_ub <span class="kw">or</span> []),</span>
|
||
<span id="cb3-70"><a href="#cb3-70" aria-hidden="true" tabindex="-1"></a> A_eq<span class="op">=</span>zusatz_eq, b_eq<span class="op">=</span>zusatz_b_eq,</span>
|
||
<span id="cb3-71"><a href="#cb3-71" aria-hidden="true" tabindex="-1"></a> bounds<span class="op">=</span>(<span class="dv">0</span>, <span class="dv">1</span>), integrality<span class="op">=</span><span class="dv">1</span>, method<span class="op">=</span><span class="st">"highs"</span>)</span>
|
||
<span id="cb3-72"><a href="#cb3-72" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> <span class="kw">not</span> ergebnis.success:</span>
|
||
<span id="cb3-73"><a href="#cb3-73" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> <span class="va">None</span></span>
|
||
<span id="cb3-74"><a href="#cb3-74" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> np.<span class="bu">round</span>(ergebnis.x).astype(<span class="bu">int</span>)</span>
|
||
<span id="cb3-75"><a href="#cb3-75" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-76"><a href="#cb3-76" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-77"><a href="#cb3-77" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> kennzahlen(plan, auftraege<span class="op">=</span>AUFTRAEGE, stunden<span class="op">=</span>STUNDEN, umsatz<span class="op">=</span>UMSATZ,</span>
|
||
<span id="cb3-78"><a href="#cb3-78" aria-hidden="true" tabindex="-1"></a> db<span class="op">=</span>DECKUNGSBEITRAG, ist_stamm<span class="op">=</span>IST_STAMM, kapazitaet<span class="op">=</span>KAPAZITAET):</span>
|
||
<span id="cb3-79"><a href="#cb3-79" aria-hidden="true" tabindex="-1"></a> <span class="co">"""Immer dieselben fuenf Zahlen - nur so sind die Varianten vergleichbar."""</span></span>
|
||
<span id="cb3-80"><a href="#cb3-80" aria-hidden="true" tabindex="-1"></a> abgelehnte_stammauftraege <span class="op">=</span> <span class="bu">int</span>(((<span class="dv">1</span> <span class="op">-</span> plan) <span class="op">&</span> ist_stamm.astype(<span class="bu">int</span>)).<span class="bu">sum</span>())</span>
|
||
<span id="cb3-81"><a href="#cb3-81" aria-hidden="true" tabindex="-1"></a> leer_ausgegangen <span class="op">=</span> <span class="bu">sum</span>(</span>
|
||
<span id="cb3-82"><a href="#cb3-82" aria-hidden="true" tabindex="-1"></a> <span class="dv">1</span> <span class="cf">for</span> kunde <span class="kw">in</span> <span class="bu">sorted</span>({a[<span class="dv">1</span>] <span class="cf">for</span> a <span class="kw">in</span> auftraege <span class="cf">if</span> a[<span class="dv">2</span>]})</span>
|
||
<span id="cb3-83"><a href="#cb3-83" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> <span class="kw">not</span> <span class="bu">any</span>(plan[i] <span class="cf">for</span> i, a <span class="kw">in</span> <span class="bu">enumerate</span>(auftraege) <span class="cf">if</span> a[<span class="dv">1</span>] <span class="op">==</span> kunde))</span>
|
||
<span id="cb3-84"><a href="#cb3-84" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> {<span class="st">"umsatz"</span>: <span class="bu">float</span>(umsatz <span class="op">@</span> plan), <span class="st">"db"</span>: <span class="bu">float</span>(db <span class="op">@</span> plan),</span>
|
||
<span id="cb3-85"><a href="#cb3-85" aria-hidden="true" tabindex="-1"></a> <span class="st">"auslastung"</span>: <span class="bu">float</span>(stunden <span class="op">@</span> plan) <span class="op">/</span> kapazitaet <span class="op">*</span> <span class="dv">100</span>,</span>
|
||
<span id="cb3-86"><a href="#cb3-86" aria-hidden="true" tabindex="-1"></a> <span class="st">"stamm_abgelehnt"</span>: abgelehnte_stammauftraege,</span>
|
||
<span id="cb3-87"><a href="#cb3-87" aria-hidden="true" tabindex="-1"></a> <span class="st">"kunden_leer"</span>: leer_ausgegangen, <span class="st">"angenommen"</span>: <span class="bu">int</span>(plan.<span class="bu">sum</span>())}</span>
|
||
<span id="cb3-88"><a href="#cb3-88" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-89"><a href="#cb3-89" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-90"><a href="#cb3-90" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> zeile(name: <span class="bu">str</span>, plan) <span class="op">-></span> <span class="va">None</span>:</span>
|
||
<span id="cb3-91"><a href="#cb3-91" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> plan <span class="kw">is</span> <span class="va">None</span>:</span>
|
||
<span id="cb3-92"><a href="#cb3-92" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f" </span><span class="sc">{</span>name<span class="sc">:<34}</span><span class="ss"> </span><span class="sc">{</span><span class="st">'UNZULAESSIG - kein Plan moeglich'</span><span class="sc">:>44}</span><span class="ss">"</span>)</span>
|
||
<span id="cb3-93"><a href="#cb3-93" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span></span>
|
||
<span id="cb3-94"><a href="#cb3-94" aria-hidden="true" tabindex="-1"></a> k <span class="op">=</span> kennzahlen(plan)</span>
|
||
<span id="cb3-95"><a href="#cb3-95" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f" </span><span class="sc">{</span>name<span class="sc">:<34}</span><span class="ss"> </span><span class="sc">{</span>k[<span class="st">'umsatz'</span>]<span class="sc">:>10,.0f}</span><span class="ss"> </span><span class="sc">{</span>k[<span class="st">'db'</span>]<span class="sc">:>9,.0f}</span><span class="ss"> "</span></span>
|
||
<span id="cb3-96"><a href="#cb3-96" aria-hidden="true" tabindex="-1"></a> <span class="ss">f"</span><span class="sc">{</span>k[<span class="st">'auslastung'</span>]<span class="sc">:>6.0f}</span><span class="ss">% </span><span class="sc">{</span>k[<span class="st">'stamm_abgelehnt'</span>]<span class="sc">:>7}</span><span class="ss"> "</span></span>
|
||
<span id="cb3-97"><a href="#cb3-97" aria-hidden="true" tabindex="-1"></a> <span class="ss">f"</span><span class="sc">{</span>k[<span class="st">'kunden_leer'</span>]<span class="sc">:>6}</span><span class="ss"> </span><span class="sc">{</span>k[<span class="st">'angenommen'</span>]<span class="sc">:>7}</span><span class="ss">"</span>)</span>
|
||
<span id="cb3-98"><a href="#cb3-98" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-99"><a href="#cb3-99" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-100"><a href="#cb3-100" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> kopfzeile() <span class="op">-></span> <span class="va">None</span>:</span>
|
||
<span id="cb3-101"><a href="#cb3-101" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f" </span><span class="sc">{</span><span class="st">''</span><span class="sc">:<34}</span><span class="ss"> </span><span class="sc">{</span><span class="st">'Umsatz'</span><span class="sc">:>10}</span><span class="ss"> </span><span class="sc">{</span><span class="st">'DB'</span><span class="sc">:>9}</span><span class="ss"> </span><span class="sc">{</span><span class="st">'Aus-'</span><span class="sc">:>7}</span><span class="ss"> </span><span class="sc">{</span><span class="st">'Stamm-'</span><span class="sc">:>7}</span><span class="ss"> "</span></span>
|
||
<span id="cb3-102"><a href="#cb3-102" aria-hidden="true" tabindex="-1"></a> <span class="ss">f"</span><span class="sc">{</span><span class="st">'Kunden'</span><span class="sc">:>6}</span><span class="ss"> </span><span class="sc">{</span><span class="st">'ange-'</span><span class="sc">:>7}</span><span class="ss">"</span>)</span>
|
||
<span id="cb3-103"><a href="#cb3-103" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f" </span><span class="sc">{</span><span class="st">''</span><span class="sc">:<34}</span><span class="ss"> </span><span class="sc">{</span><span class="st">''</span><span class="sc">:>10}</span><span class="ss"> </span><span class="sc">{</span><span class="st">''</span><span class="sc">:>9}</span><span class="ss"> </span><span class="sc">{</span><span class="st">'lastung'</span><span class="sc">:>7}</span><span class="ss"> </span><span class="sc">{</span><span class="st">'auftr.'</span><span class="sc">:>7}</span><span class="ss"> "</span></span>
|
||
<span id="cb3-104"><a href="#cb3-104" aria-hidden="true" tabindex="-1"></a> <span class="ss">f"</span><span class="sc">{</span><span class="st">'ohne'</span><span class="sc">:>6}</span><span class="ss"> </span><span class="sc">{</span><span class="st">'nommen'</span><span class="sc">:>7}</span><span class="ss">"</span>)</span>
|
||
<span id="cb3-105"><a href="#cb3-105" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" "</span> <span class="op">+</span> <span class="st">"-"</span> <span class="op">*</span> <span class="dv">78</span>)</span>
|
||
<span id="cb3-106"><a href="#cb3-106" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-107"><a href="#cb3-107" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-108"><a href="#cb3-108" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">"__main__"</span>:</span>
|
||
<span id="cb3-109"><a href="#cb3-109" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"="</span> <span class="op">*</span> <span class="dv">84</span>)</span>
|
||
<span id="cb3-110"><a href="#cb3-110" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" VOM MANAGEMENT-WUNSCH ZUM MODELL"</span>)</span>
|
||
<span id="cb3-111"><a href="#cb3-111" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"="</span> <span class="op">*</span> <span class="dv">84</span>)</span>
|
||
<span id="cb3-112"><a href="#cb3-112" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f"</span><span class="sc">{</span><span class="bu">len</span>(AUFTRAEGE)<span class="sc">}</span><span class="ss"> Anfragen verlangen </span><span class="sc">{</span>STUNDEN<span class="sc">.</span><span class="bu">sum</span>()<span class="sc">:.0f}</span><span class="ss"> Maschinenstunden, "</span></span>
|
||
<span id="cb3-113"><a href="#cb3-113" aria-hidden="true" tabindex="-1"></a> <span class="ss">f"verfuegbar sind </span><span class="sc">{</span>KAPAZITAET<span class="sc">}</span><span class="ss">."</span>)</span>
|
||
<span id="cb3-114"><a href="#cb3-114" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f"Es muss also ausgewaehlt werden. </span><span class="sc">{</span><span class="bu">len</span>(STAMMKUNDEN)<span class="sc">}</span><span class="ss"> der Kunden sind "</span></span>
|
||
<span id="cb3-115"><a href="#cb3-115" aria-hidden="true" tabindex="-1"></a> <span class="ss">f"Stammkunden:"</span>)</span>
|
||
<span id="cb3-116"><a href="#cb3-116" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f" </span><span class="sc">{</span><span class="st">', '</span><span class="sc">.</span>join(STAMMKUNDEN)<span class="sc">}</span><span class="ch">\n</span><span class="ss">"</span>)</span>
|
||
<span id="cb3-117"><a href="#cb3-117" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-118"><a href="#cb3-118" aria-hidden="true" tabindex="-1"></a> <span class="co"># --- 1. Drei Saetze aus dem Gespraech, drei Ziele ---------------------</span></span>
|
||
<span id="cb3-119"><a href="#cb3-119" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"-"</span> <span class="op">*</span> <span class="dv">84</span>)</span>
|
||
<span id="cb3-120"><a href="#cb3-120" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"1. Was im Gespraech gesagt wurde - drei naheliegende Ziele</span><span class="ch">\n</span><span class="st">"</span>)</span>
|
||
<span id="cb3-121"><a href="#cb3-121" aria-hidden="true" tabindex="-1"></a> kopfzeile()</span>
|
||
<span id="cb3-122"><a href="#cb3-122" aria-hidden="true" tabindex="-1"></a> plaene <span class="op">=</span> {}</span>
|
||
<span id="cb3-123"><a href="#cb3-123" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> name, ziel <span class="kw">in</span> [(<span class="st">"</span><span class="ch">\"</span><span class="st">Umsatz maximieren</span><span class="ch">\"</span><span class="st">"</span>, UMSATZ),</span>
|
||
<span id="cb3-124"><a href="#cb3-124" aria-hidden="true" tabindex="-1"></a> (<span class="st">"</span><span class="ch">\"</span><span class="st">Maschinen besser auslasten</span><span class="ch">\"</span><span class="st">"</span>, STUNDEN),</span>
|
||
<span id="cb3-125"><a href="#cb3-125" aria-hidden="true" tabindex="-1"></a> (<span class="st">"</span><span class="ch">\"</span><span class="st">Deckungsbeitrag maximieren</span><span class="ch">\"</span><span class="st">"</span>, DECKUNGSBEITRAG)]:</span>
|
||
<span id="cb3-126"><a href="#cb3-126" aria-hidden="true" tabindex="-1"></a> plaene[name] <span class="op">=</span> waehle_aus(ziel)</span>
|
||
<span id="cb3-127"><a href="#cb3-127" aria-hidden="true" tabindex="-1"></a> zeile(name, plaene[name])</span>
|
||
<span id="cb3-128"><a href="#cb3-128" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-129"><a href="#cb3-129" aria-hidden="true" tabindex="-1"></a> umsatzplan <span class="op">=</span> kennzahlen(plaene[<span class="st">"</span><span class="ch">\"</span><span class="st">Umsatz maximieren</span><span class="ch">\"</span><span class="st">"</span>])</span>
|
||
<span id="cb3-130"><a href="#cb3-130" aria-hidden="true" tabindex="-1"></a> auslastungsplan <span class="op">=</span> kennzahlen(plaene[<span class="st">"</span><span class="ch">\"</span><span class="st">Maschinen besser auslasten</span><span class="ch">\"</span><span class="st">"</span>])</span>
|
||
<span id="cb3-131"><a href="#cb3-131" aria-hidden="true" tabindex="-1"></a> dbplan <span class="op">=</span> kennzahlen(plaene[<span class="st">"</span><span class="ch">\"</span><span class="st">Deckungsbeitrag maximieren</span><span class="ch">\"</span><span class="st">"</span>])</span>
|
||
<span id="cb3-132"><a href="#cb3-132" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-133"><a href="#cb3-133" aria-hidden="true" tabindex="-1"></a> mehr_umsatz <span class="op">=</span> umsatzplan[<span class="st">"umsatz"</span>] <span class="op">-</span> dbplan[<span class="st">"umsatz"</span>]</span>
|
||
<span id="cb3-134"><a href="#cb3-134" aria-hidden="true" tabindex="-1"></a> weniger_db <span class="op">=</span> dbplan[<span class="st">"db"</span>] <span class="op">-</span> umsatzplan[<span class="st">"db"</span>]</span>
|
||
<span id="cb3-135"><a href="#cb3-135" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f"</span><span class="ch">\n</span><span class="ss"> Der Umsatzplan bringt </span><span class="sc">{</span>mehr_umsatz<span class="sc">:,.0f}</span><span class="ss"> EUR mehr Umsatz und "</span></span>
|
||
<span id="cb3-136"><a href="#cb3-136" aria-hidden="true" tabindex="-1"></a> <span class="ss">f"</span><span class="sc">{</span>weniger_db<span class="sc">:,.0f}</span><span class="ss"> EUR WENIGER"</span>)</span>
|
||
<span id="cb3-137"><a href="#cb3-137" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f" Deckungsbeitrag. Fuer </span><span class="sc">{</span>mehr_umsatz<span class="sc">:,.0f}</span><span class="ss"> EUR Umsatz werden also "</span></span>
|
||
<span id="cb3-138"><a href="#cb3-138" aria-hidden="true" tabindex="-1"></a> <span class="ss">f"</span><span class="sc">{</span>weniger_db<span class="sc">:,.0f}</span><span class="ss"> EUR Ergebnis"</span>)</span>
|
||
<span id="cb3-139"><a href="#cb3-139" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f" aufgegeben - und </span><span class="sc">{</span>umsatzplan[<span class="st">'stamm_abgelehnt'</span>]<span class="sc">}</span><span class="ss"> von "</span></span>
|
||
<span id="cb3-140"><a href="#cb3-140" aria-hidden="true" tabindex="-1"></a> <span class="ss">f"</span><span class="sc">{</span><span class="bu">int</span>(IST_STAMM.<span class="bu">sum</span>())<span class="sc">}</span><span class="ss"> Stammkundenauftraegen dazu."</span>)</span>
|
||
<span id="cb3-141"><a href="#cb3-141" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>()</span>
|
||
<span id="cb3-142"><a href="#cb3-142" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" </span><span class="ch">\"</span><span class="st">Auslastung</span><span class="ch">\"</span><span class="st"> ist der haeufigste Wunsch und der schaedlichste. Der"</span>)</span>
|
||
<span id="cb3-143"><a href="#cb3-143" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f" darauf optimierte Plan bringt </span><span class="sc">{</span>dbplan[<span class="st">'db'</span>] <span class="op">-</span> auslastungsplan[<span class="st">'db'</span>]<span class="sc">:,.0f}</span><span class="ss"> EUR weniger "</span></span>
|
||
<span id="cb3-144"><a href="#cb3-144" aria-hidden="true" tabindex="-1"></a> <span class="ss">f"Deckungsbeitrag und"</span>)</span>
|
||
<span id="cb3-145"><a href="#cb3-145" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f" </span><span class="sc">{</span>dbplan[<span class="st">'umsatz'</span>] <span class="op">-</span> auslastungsplan[<span class="st">'umsatz'</span>]<span class="sc">:,.0f}</span><span class="ss"> EUR weniger Umsatz als der "</span></span>
|
||
<span id="cb3-146"><a href="#cb3-146" aria-hidden="true" tabindex="-1"></a> <span class="ss">f"DB-Plan - und erreicht dabei"</span>)</span>
|
||
<span id="cb3-147"><a href="#cb3-147" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f" nicht einmal mehr Auslastung: alle drei liegen bei "</span></span>
|
||
<span id="cb3-148"><a href="#cb3-148" aria-hidden="true" tabindex="-1"></a> <span class="ss">f"</span><span class="sc">{</span>dbplan[<span class="st">'auslastung'</span>]<span class="sc">:.0f}</span><span class="ss"> %."</span>)</span>
|
||
<span id="cb3-149"><a href="#cb3-149" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" Eine volle Maschine ist eben kein Ziel, sondern ein Nebenprodukt."</span>)</span>
|
||
<span id="cb3-150"><a href="#cb3-150" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-151"><a href="#cb3-151" aria-hidden="true" tabindex="-1"></a> <span class="co"># --- 2. Ein Satz, drei Lesarten --------------------------------------</span></span>
|
||
<span id="cb3-152"><a href="#cb3-152" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"</span><span class="ch">\n</span><span class="st">"</span> <span class="op">+</span> <span class="st">"-"</span> <span class="op">*</span> <span class="dv">84</span>)</span>
|
||
<span id="cb3-153"><a href="#cb3-153" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"2. </span><span class="ch">\"</span><span class="st">Stammkunden duerfen wir nicht verlieren</span><span class="ch">\"</span><span class="st"> - aber was heisst das?</span><span class="ch">\n</span><span class="st">"</span>)</span>
|
||
<span id="cb3-154"><a href="#cb3-154" aria-hidden="true" tabindex="-1"></a> kopfzeile()</span>
|
||
<span id="cb3-155"><a href="#cb3-155" aria-hidden="true" tabindex="-1"></a> zeile(<span class="st">"ohne die Regel (DB maximieren)"</span>, waehle_aus(DECKUNGSBEITRAG))</span>
|
||
<span id="cb3-156"><a href="#cb3-156" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-157"><a href="#cb3-157" aria-hidden="true" tabindex="-1"></a> <span class="co"># Lesart A: jeder Stammkundenauftrag wird angenommen</span></span>
|
||
<span id="cb3-158"><a href="#cb3-158" aria-hidden="true" tabindex="-1"></a> alle_stamm <span class="op">=</span> [[<span class="fl">1.0</span> <span class="cf">if</span> IST_STAMM[i] <span class="cf">else</span> <span class="fl">0.0</span> <span class="cf">for</span> i <span class="kw">in</span> <span class="bu">range</span>(<span class="bu">len</span>(AUFTRAEGE))]]</span>
|
||
<span id="cb3-159"><a href="#cb3-159" aria-hidden="true" tabindex="-1"></a> lesart_a <span class="op">=</span> waehle_aus(DECKUNGSBEITRAG, zusatz_eq<span class="op">=</span>alle_stamm,</span>
|
||
<span id="cb3-160"><a href="#cb3-160" aria-hidden="true" tabindex="-1"></a> zusatz_b_eq<span class="op">=</span>[<span class="bu">float</span>(IST_STAMM.<span class="bu">sum</span>())])</span>
|
||
<span id="cb3-161"><a href="#cb3-161" aria-hidden="true" tabindex="-1"></a> zeile(<span class="st">"A: jeden Stammauftrag annehmen"</span>, lesart_a)</span>
|
||
<span id="cb3-162"><a href="#cb3-162" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-163"><a href="#cb3-163" aria-hidden="true" tabindex="-1"></a> <span class="co"># Lesart B: kein Stammkunde geht leer aus (mindestens ein Auftrag je Kunde)</span></span>
|
||
<span id="cb3-164"><a href="#cb3-164" aria-hidden="true" tabindex="-1"></a> je_kunde_ub, je_kunde_b <span class="op">=</span> [], []</span>
|
||
<span id="cb3-165"><a href="#cb3-165" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> kunde <span class="kw">in</span> STAMMKUNDEN:</span>
|
||
<span id="cb3-166"><a href="#cb3-166" aria-hidden="true" tabindex="-1"></a> je_kunde_ub.append([<span class="op">-</span><span class="fl">1.0</span> <span class="cf">if</span> a[<span class="dv">1</span>] <span class="op">==</span> kunde <span class="cf">else</span> <span class="fl">0.0</span> <span class="cf">for</span> a <span class="kw">in</span> AUFTRAEGE])</span>
|
||
<span id="cb3-167"><a href="#cb3-167" aria-hidden="true" tabindex="-1"></a> je_kunde_b.append(<span class="op">-</span><span class="fl">1.0</span>)</span>
|
||
<span id="cb3-168"><a href="#cb3-168" aria-hidden="true" tabindex="-1"></a> lesart_b <span class="op">=</span> waehle_aus(DECKUNGSBEITRAG, zusatz_ub<span class="op">=</span>je_kunde_ub,</span>
|
||
<span id="cb3-169"><a href="#cb3-169" aria-hidden="true" tabindex="-1"></a> zusatz_b_ub<span class="op">=</span>je_kunde_b)</span>
|
||
<span id="cb3-170"><a href="#cb3-170" aria-hidden="true" tabindex="-1"></a> zeile(<span class="st">"B: kein Stammkunde geht leer aus"</span>, lesart_b)</span>
|
||
<span id="cb3-171"><a href="#cb3-171" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-172"><a href="#cb3-172" aria-hidden="true" tabindex="-1"></a> a, b <span class="op">=</span> kennzahlen(lesart_a), kennzahlen(lesart_b)</span>
|
||
<span id="cb3-173"><a href="#cb3-173" aria-hidden="true" tabindex="-1"></a> ohne <span class="op">=</span> kennzahlen(waehle_aus(DECKUNGSBEITRAG))</span>
|
||
<span id="cb3-174"><a href="#cb3-174" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"</span><span class="ch">\n</span><span class="st"> Beide Lesarten erreichen dasselbe: kein Stammkunde geht leer aus."</span>)</span>
|
||
<span id="cb3-175"><a href="#cb3-175" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f" Lesart A kostet dafuer </span><span class="sc">{</span>ohne[<span class="st">'db'</span>] <span class="op">-</span> a[<span class="st">'db'</span>]<span class="sc">:,.0f}</span><span class="ss"> EUR Deckungsbeitrag, "</span></span>
|
||
<span id="cb3-176"><a href="#cb3-176" aria-hidden="true" tabindex="-1"></a> <span class="ss">f"Lesart B nur </span><span class="sc">{</span>ohne[<span class="st">'db'</span>] <span class="op">-</span> b[<span class="st">'db'</span>]<span class="sc">:,.0f}</span><span class="ss"> EUR -"</span>)</span>
|
||
<span id="cb3-177"><a href="#cb3-177" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f" ein Unterschied von </span><span class="sc">{</span>b[<span class="st">'db'</span>] <span class="op">-</span> a[<span class="st">'db'</span>]<span class="sc">:,.0f}</span><span class="ss"> EUR fuer denselben Satz aus derselben"</span>)</span>
|
||
<span id="cb3-178"><a href="#cb3-178" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" Besprechung. Wer nicht nachfragt, entscheidet das selbst, ohne es"</span>)</span>
|
||
<span id="cb3-179"><a href="#cb3-179" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" zu merken."</span>)</span>
|
||
<span id="cb3-180"><a href="#cb3-180" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-181"><a href="#cb3-181" aria-hidden="true" tabindex="-1"></a> <span class="co"># --- 3. Die weiche Variante ------------------------------------------</span></span>
|
||
<span id="cb3-182"><a href="#cb3-182" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"</span><span class="ch">\n</span><span class="st">"</span> <span class="op">+</span> <span class="st">"-"</span> <span class="op">*</span> <span class="dv">84</span>)</span>
|
||
<span id="cb3-183"><a href="#cb3-183" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"3. Dieselbe Regel als Strafkosten je abgelehntem Stammauftrag</span><span class="ch">\n</span><span class="st">"</span>)</span>
|
||
<span id="cb3-184"><a href="#cb3-184" aria-hidden="true" tabindex="-1"></a> kopfzeile()</span>
|
||
<span id="cb3-185"><a href="#cb3-185" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> strafe <span class="kw">in</span> (<span class="dv">3_000</span>, <span class="dv">6_000</span>, <span class="dv">10_000</span>):</span>
|
||
<span id="cb3-186"><a href="#cb3-186" aria-hidden="true" tabindex="-1"></a> ziel <span class="op">=</span> DECKUNGSBEITRAG <span class="op">+</span> np.where(IST_STAMM, <span class="bu">float</span>(strafe), <span class="fl">0.0</span>)</span>
|
||
<span id="cb3-187"><a href="#cb3-187" aria-hidden="true" tabindex="-1"></a> zeile(<span class="ss">f"C: Strafe </span><span class="sc">{</span>strafe<span class="sc">:>6,}</span><span class="ss"> EUR je Auftrag"</span>, waehle_aus(ziel))</span>
|
||
<span id="cb3-188"><a href="#cb3-188" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-189"><a href="#cb3-189" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"</span><span class="ch">\n</span><span class="st"> Bei 3.000 EUR aendert sich nichts: Die Strafe liegt unter dem, was"</span>)</span>
|
||
<span id="cb3-190"><a href="#cb3-190" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" die Auftraege an Deckungsbeitrag verdraengen wuerden. Bei 10.000 EUR"</span>)</span>
|
||
<span id="cb3-191"><a href="#cb3-191" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" kommt genau Lesart A heraus. Eine harte Regel ist also nichts"</span>)</span>
|
||
<span id="cb3-192"><a href="#cb3-192" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" anderes als eine weiche mit hinreichend grosser Strafe - was ein"</span>)</span>
|
||
<span id="cb3-193"><a href="#cb3-193" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" Strafgewicht sonst noch bedeutet, steht im Kapitel CP-SAT."</span>)</span>
|
||
<span id="cb3-194"><a href="#cb3-194" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-195"><a href="#cb3-195" aria-hidden="true" tabindex="-1"></a> <span class="co"># --- 4. Was die harte Lesart ein Quartal spaeter anrichtet -----------</span></span>
|
||
<span id="cb3-196"><a href="#cb3-196" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"</span><span class="ch">\n</span><span class="st">"</span> <span class="op">+</span> <span class="st">"-"</span> <span class="op">*</span> <span class="dv">84</span>)</span>
|
||
<span id="cb3-197"><a href="#cb3-197" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"4. Ein Quartal spaeter: Weber fragt einen Grossauftrag an</span><span class="ch">\n</span><span class="st">"</span>)</span>
|
||
<span id="cb3-198"><a href="#cb3-198" aria-hidden="true" tabindex="-1"></a> erweitert <span class="op">=</span> AUFTRAEGE <span class="op">+</span> [(<span class="st">"A-115"</span>, <span class="st">"Weber GmbH"</span>, <span class="va">True</span>, <span class="dv">320</span>, <span class="dv">210_000</span>, <span class="dv">150_000</span>)]</span>
|
||
<span id="cb3-199"><a href="#cb3-199" aria-hidden="true" tabindex="-1"></a> stunden_neu <span class="op">=</span> np.array([a[<span class="dv">3</span>] <span class="cf">for</span> a <span class="kw">in</span> erweitert], dtype<span class="op">=</span><span class="bu">float</span>)</span>
|
||
<span id="cb3-200"><a href="#cb3-200" aria-hidden="true" tabindex="-1"></a> db_neu <span class="op">=</span> np.array([a[<span class="dv">4</span>] <span class="op">-</span> a[<span class="dv">5</span>] <span class="cf">for</span> a <span class="kw">in</span> erweitert], dtype<span class="op">=</span><span class="bu">float</span>)</span>
|
||
<span id="cb3-201"><a href="#cb3-201" aria-hidden="true" tabindex="-1"></a> stamm_neu <span class="op">=</span> np.array([a[<span class="dv">2</span>] <span class="cf">for</span> a <span class="kw">in</span> erweitert])</span>
|
||
<span id="cb3-202"><a href="#cb3-202" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-203"><a href="#cb3-203" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f" A-115: Weber GmbH, </span><span class="sc">{</span>erweitert[<span class="op">-</span><span class="dv">1</span>][<span class="dv">3</span>]<span class="sc">}</span><span class="ss"> Maschinenstunden - allein mehr,"</span>)</span>
|
||
<span id="cb3-204"><a href="#cb3-204" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f" als der ganze Zeitraum hergibt (</span><span class="sc">{</span>KAPAZITAET<span class="sc">}</span><span class="ss"> h).</span><span class="ch">\n</span><span class="ss">"</span>)</span>
|
||
<span id="cb3-205"><a href="#cb3-205" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-206"><a href="#cb3-206" aria-hidden="true" tabindex="-1"></a> alle_stamm_neu <span class="op">=</span> [[<span class="fl">1.0</span> <span class="cf">if</span> stamm_neu[i] <span class="cf">else</span> <span class="fl">0.0</span> <span class="cf">for</span> i <span class="kw">in</span> <span class="bu">range</span>(<span class="bu">len</span>(erweitert))]]</span>
|
||
<span id="cb3-207"><a href="#cb3-207" aria-hidden="true" tabindex="-1"></a> hart <span class="op">=</span> waehle_aus(db_neu, zusatz_eq<span class="op">=</span>alle_stamm_neu,</span>
|
||
<span id="cb3-208"><a href="#cb3-208" aria-hidden="true" tabindex="-1"></a> zusatz_b_eq<span class="op">=</span>[<span class="bu">float</span>(stamm_neu.<span class="bu">sum</span>())],</span>
|
||
<span id="cb3-209"><a href="#cb3-209" aria-hidden="true" tabindex="-1"></a> auftraege<span class="op">=</span>erweitert, stunden<span class="op">=</span>stunden_neu)</span>
|
||
<span id="cb3-210"><a href="#cb3-210" aria-hidden="true" tabindex="-1"></a> weich <span class="op">=</span> waehle_aus(db_neu <span class="op">+</span> np.where(stamm_neu, <span class="fl">10_000.0</span>, <span class="fl">0.0</span>),</span>
|
||
<span id="cb3-211"><a href="#cb3-211" aria-hidden="true" tabindex="-1"></a> auftraege<span class="op">=</span>erweitert, stunden<span class="op">=</span>stunden_neu)</span>
|
||
<span id="cb3-212"><a href="#cb3-212" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-213"><a href="#cb3-213" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f" Lesart A (hart): "</span></span>
|
||
<span id="cb3-214"><a href="#cb3-214" aria-hidden="true" tabindex="-1"></a> <span class="ss">f"</span><span class="sc">{</span><span class="st">'UNZULAESSIG - der Nachtlauf bricht ab'</span> <span class="cf">if</span> hart <span class="kw">is</span> <span class="va">None</span> <span class="cf">else</span> <span class="st">'loesbar'</span><span class="sc">}</span><span class="ss">"</span>)</span>
|
||
<span id="cb3-215"><a href="#cb3-215" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> weich <span class="kw">is</span> <span class="kw">not</span> <span class="va">None</span>:</span>
|
||
<span id="cb3-216"><a href="#cb3-216" aria-hidden="true" tabindex="-1"></a> k <span class="op">=</span> kennzahlen(weich, erweitert, stunden_neu,</span>
|
||
<span id="cb3-217"><a href="#cb3-217" aria-hidden="true" tabindex="-1"></a> np.array([a[<span class="dv">4</span>] <span class="cf">for</span> a <span class="kw">in</span> erweitert], dtype<span class="op">=</span><span class="bu">float</span>),</span>
|
||
<span id="cb3-218"><a href="#cb3-218" aria-hidden="true" tabindex="-1"></a> db_neu, stamm_neu)</span>
|
||
<span id="cb3-219"><a href="#cb3-219" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f" Lesart C (weich): loesbar - </span><span class="sc">{</span>k[<span class="st">'db'</span>]<span class="sc">:,.0f}</span><span class="ss"> EUR Deckungsbeitrag, "</span></span>
|
||
<span id="cb3-220"><a href="#cb3-220" aria-hidden="true" tabindex="-1"></a> <span class="ss">f"</span><span class="sc">{</span>k[<span class="st">'stamm_abgelehnt'</span>]<span class="sc">}</span><span class="ss"> Stammauftrag abgelehnt"</span>)</span>
|
||
<span id="cb3-221"><a href="#cb3-221" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-222"><a href="#cb3-222" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"</span><span class="ch">\n</span><span class="st">"</span> <span class="op">+</span> <span class="st">"="</span> <span class="op">*</span> <span class="dv">84</span>)</span>
|
||
<span id="cb3-223"><a href="#cb3-223" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" WORAUF ES ANKOMMT"</span>)</span>
|
||
<span id="cb3-224"><a href="#cb3-224" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"="</span> <span class="op">*</span> <span class="dv">84</span>)</span>
|
||
<span id="cb3-225"><a href="#cb3-225" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"Die Daten waren in allen vier Teilen dieselben. Was sich geaendert hat,"</span>)</span>
|
||
<span id="cb3-226"><a href="#cb3-226" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"war nur die Frage - und mit ihr der Plan, der Deckungsbeitrag und die"</span>)</span>
|
||
<span id="cb3-227"><a href="#cb3-227" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"Kundenbeziehung."</span>)</span>
|
||
<span id="cb3-228"><a href="#cb3-228" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>()</span>
|
||
<span id="cb3-229"><a href="#cb3-229" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"Drei Dinge, die deshalb vor dem ersten Modell geklaert gehoeren:"</span>)</span>
|
||
<span id="cb3-230"><a href="#cb3-230" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>()</span>
|
||
<span id="cb3-231"><a href="#cb3-231" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" 1. WORAN wird der Erfolg gemessen? Nicht 'was ist Ihnen wichtig',"</span>)</span>
|
||
<span id="cb3-232"><a href="#cb3-232" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" sondern: Welche Zahl steht am Jahresende im Bericht? Umsatz,"</span>)</span>
|
||
<span id="cb3-233"><a href="#cb3-233" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" Auslastung und Deckungsbeitrag fuehren hier zu drei"</span>)</span>
|
||
<span id="cb3-234"><a href="#cb3-234" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" verschiedenen Plaenen."</span>)</span>
|
||
<span id="cb3-235"><a href="#cb3-235" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" 2. WAS GENAU heisst der Satz? 'Stammkunden nicht verlieren' hat"</span>)</span>
|
||
<span id="cb3-236"><a href="#cb3-236" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f" mindestens drei Lesarten mit </span><span class="sc">{</span>b[<span class="st">'db'</span>] <span class="op">-</span> a[<span class="st">'db'</span>]<span class="sc">:,.0f}</span><span class="ss"> EUR Unterschied. Die Frage"</span>)</span>
|
||
<span id="cb3-237"><a href="#cb3-237" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" 'meinen Sie jeden Auftrag oder jeden Kunden?' dauert zehn"</span>)</span>
|
||
<span id="cb3-238"><a href="#cb3-238" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" Sekunden."</span>)</span>
|
||
<span id="cb3-239"><a href="#cb3-239" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" 3. WAS PASSIERT, WENN ES NICHT GEHT? Eine harte Regel, die niemand"</span>)</span>
|
||
<span id="cb3-240"><a href="#cb3-240" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" hinterfragt hat, macht das System eines Tages unloesbar - und"</span>)</span>
|
||
<span id="cb3-241"><a href="#cb3-241" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" zwar genau dann, wenn ein besonders grosser Auftrag hereinkommt."</span>)</span>
|
||
<span id="cb3-242"><a href="#cb3-242" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" Weiche Regeln antworten auch dann noch."</span>)</span>
|
||
<span id="cb3-243"><a href="#cb3-243" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"="</span> <span class="op">*</span> <span class="dv">84</span>)</span></code></pre></div>
|
||
<p><strong>Erwartete Ausgabe:</strong></p>
|
||
<pre><code>====================================================================================
|
||
VOM MANAGEMENT-WUNSCH ZUM MODELL
|
||
====================================================================================
|
||
14 Anfragen verlangen 800 Maschinenstunden, verfuegbar sind 300.
|
||
Es muss also ausgewaehlt werden. 3 der Kunden sind Stammkunden:
|
||
Kranz AG, Obermeier KG, Weber GmbH
|
||
|
||
------------------------------------------------------------------------------------
|
||
1. Was im Gespraech gesagt wurde - drei naheliegende Ziele
|
||
|
||
Umsatz DB Aus- Stamm- Kunden ange-
|
||
lastung auftr. ohne nommen
|
||
------------------------------------------------------------------------------
|
||
"Umsatz maximieren" 227,000 66,000 100% 5 2 6
|
||
"Maschinen besser auslasten" 205,000 54,000 100% 4 1 5
|
||
"Deckungsbeitrag maximieren" 222,000 78,500 100% 2 1 8
|
||
|
||
Der Umsatzplan bringt 5,000 EUR mehr Umsatz und 12,500 EUR WENIGER
|
||
Deckungsbeitrag. Fuer 5,000 EUR Umsatz werden also 12,500 EUR Ergebnis
|
||
aufgegeben - und 5 von 6 Stammkundenauftraegen dazu.
|
||
|
||
"Auslastung" ist der haeufigste Wunsch und der schaedlichste. Der
|
||
darauf optimierte Plan bringt 24,500 EUR weniger Deckungsbeitrag und
|
||
17,000 EUR weniger Umsatz als der DB-Plan - und erreicht dabei
|
||
nicht einmal mehr Auslastung: alle drei liegen bei 100 %.
|
||
Eine volle Maschine ist eben kein Ziel, sondern ein Nebenprodukt.
|
||
|
||
------------------------------------------------------------------------------------
|
||
2. "Stammkunden duerfen wir nicht verlieren" - aber was heisst das?
|
||
|
||
Umsatz DB Aus- Stamm- Kunden ange-
|
||
lastung auftr. ohne nommen
|
||
------------------------------------------------------------------------------
|
||
ohne die Regel (DB maximieren) 222,000 78,500 100% 2 1 8
|
||
A: jeden Stammauftrag annehmen 181,000 66,000 90% 0 0 8
|
||
B: kein Stammkunde geht leer aus 213,000 75,000 98% 2 0 8
|
||
|
||
Beide Lesarten erreichen dasselbe: kein Stammkunde geht leer aus.
|
||
Lesart A kostet dafuer 12,500 EUR Deckungsbeitrag, Lesart B nur 3,500 EUR -
|
||
ein Unterschied von 9,000 EUR fuer denselben Satz aus derselben
|
||
Besprechung. Wer nicht nachfragt, entscheidet das selbst, ohne es
|
||
zu merken.
|
||
|
||
------------------------------------------------------------------------------------
|
||
3. Dieselbe Regel als Strafkosten je abgelehntem Stammauftrag
|
||
|
||
Umsatz DB Aus- Stamm- Kunden ange-
|
||
lastung auftr. ohne nommen
|
||
------------------------------------------------------------------------------
|
||
C: Strafe 3,000 EUR je Auftrag 222,000 78,500 100% 2 1 8
|
||
C: Strafe 6,000 EUR je Auftrag 205,000 73,000 100% 1 0 8
|
||
C: Strafe 10,000 EUR je Auftrag 181,000 66,000 90% 0 0 8
|
||
|
||
Bei 3.000 EUR aendert sich nichts: Die Strafe liegt unter dem, was
|
||
die Auftraege an Deckungsbeitrag verdraengen wuerden. Bei 10.000 EUR
|
||
kommt genau Lesart A heraus. Eine harte Regel ist also nichts
|
||
anderes als eine weiche mit hinreichend grosser Strafe - was ein
|
||
Strafgewicht sonst noch bedeutet, steht im Kapitel CP-SAT.
|
||
|
||
------------------------------------------------------------------------------------
|
||
4. Ein Quartal spaeter: Weber fragt einen Grossauftrag an
|
||
|
||
A-115: Weber GmbH, 320 Maschinenstunden - allein mehr,
|
||
als der ganze Zeitraum hergibt (300 h).
|
||
|
||
Lesart A (hart): UNZULAESSIG - der Nachtlauf bricht ab
|
||
Lesart C (weich): loesbar - 66,000 EUR Deckungsbeitrag, 1 Stammauftrag abgelehnt
|
||
|
||
====================================================================================
|
||
WORAUF ES ANKOMMT
|
||
====================================================================================
|
||
Die Daten waren in allen vier Teilen dieselben. Was sich geaendert hat,
|
||
war nur die Frage - und mit ihr der Plan, der Deckungsbeitrag und die
|
||
Kundenbeziehung.
|
||
|
||
Drei Dinge, die deshalb vor dem ersten Modell geklaert gehoeren:
|
||
|
||
1. WORAN wird der Erfolg gemessen? Nicht 'was ist Ihnen wichtig',
|
||
sondern: Welche Zahl steht am Jahresende im Bericht? Umsatz,
|
||
Auslastung und Deckungsbeitrag fuehren hier zu drei
|
||
verschiedenen Plaenen.
|
||
2. WAS GENAU heisst der Satz? 'Stammkunden nicht verlieren' hat
|
||
mindestens drei Lesarten mit 9,000 EUR Unterschied. Die Frage
|
||
'meinen Sie jeden Auftrag oder jeden Kunden?' dauert zehn
|
||
Sekunden.
|
||
3. WAS PASSIERT, WENN ES NICHT GEHT? Eine harte Regel, die niemand
|
||
hinterfragt hat, macht das System eines Tages unloesbar - und
|
||
zwar genau dann, wenn ein besonders grosser Auftrag hereinkommt.
|
||
Weiche Regeln antworten auch dann noch.
|
||
====================================================================================</code></pre>
|
||
<h3 id="teil-1-drei-ziele-drei-pläne">Teil 1: Drei Ziele, drei Pläne</h3>
|
||
<table>
|
||
<colgroup>
|
||
<col style="width: 15%" />
|
||
<col style="width: 21%" />
|
||
<col style="width: 21%" />
|
||
<col style="width: 21%" />
|
||
<col style="width: 21%" />
|
||
</colgroup>
|
||
<thead>
|
||
<tr class="header">
|
||
<th>Zielgröße</th>
|
||
<th style="text-align: right;">Umsatz</th>
|
||
<th style="text-align: right;">Deckungsbeitrag</th>
|
||
<th style="text-align: right;">Auslastung</th>
|
||
<th style="text-align: right;">abgelehnte Stammaufträge</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr class="odd">
|
||
<td>„Umsatz maximieren”</td>
|
||
<td style="text-align: right;"><strong>227 000 €</strong></td>
|
||
<td style="text-align: right;">66 000 €</td>
|
||
<td style="text-align: right;">100 %</td>
|
||
<td style="text-align: right;">5 von 6</td>
|
||
</tr>
|
||
<tr class="even">
|
||
<td>„Maschinen besser auslasten”</td>
|
||
<td style="text-align: right;">205 000 €</td>
|
||
<td style="text-align: right;">54 000 €</td>
|
||
<td style="text-align: right;">100 %</td>
|
||
<td style="text-align: right;">4 von 6</td>
|
||
</tr>
|
||
<tr class="odd">
|
||
<td>„Deckungsbeitrag maximieren”</td>
|
||
<td style="text-align: right;">222 000 €</td>
|
||
<td style="text-align: right;"><strong>78 500 €</strong></td>
|
||
<td style="text-align: right;">100 %</td>
|
||
<td style="text-align: right;">2 von 6</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>Zwei Beobachtungen, die im Gespräch niemand vorhergesagt hätte:</p>
|
||
<p><strong>Der Umsatzplan kostet 12 500 € Ergebnis, um 5 000 € Umsatz zu gewinnen</strong> — und nimmt dabei fünf von sechs Stammkundenaufträgen aus dem Plan. Das Wechselkursverhältnis ist 1 : 2,5 gegen den Betrieb.</p>
|
||
<p><strong>Der Auslastungsplan ist in jeder Hinsicht der schlechteste — auch bei der Auslastung.</strong> Alle drei Pläne belegen die Maschinen zu 100 %; der eigens darauf optimierte Plan erreicht nur nicht mehr, sondern verliert dabei 24 500 € Deckungsbeitrag. Der Grund ist einfach: Bei knapper Kapazität ist eine volle Maschine keine Leistung, sondern die Voreinstellung. Zu optimieren gibt es nur, <strong>womit</strong> sie voll wird.</p>
|
||
<blockquote>
|
||
<p><strong>⚠️ Auslastung ist ein Ergebnis, kein Ziel</strong></p>
|
||
<p>„Wir müssen die Maschinen besser auslasten” ist der häufigste Satz in Produktionsbesprechungen und fast immer die falsche Zielgröße. Auslastung misst, wie viel Zeit vergeht — nicht, was dabei herauskommt. Wer sie maximiert, belohnt lange, schlecht bezahlte Aufträge.</p>
|
||
<p>Die Ausnahme, die die Regel erklärt: Wenn Maschinen tatsächlich leer stehen, <em>weil</em> zu wenig hereinkommt, ist Auslastung ein sinnvolles <strong>Symptom</strong> — aber dann liegt das Problem im Vertrieb und nicht in der Planung.</p>
|
||
</blockquote>
|
||
<h3 id="teil-2-ein-satz-drei-lesarten">Teil 2: Ein Satz, drei Lesarten</h3>
|
||
<p>„Stammkunden dürfen wir nicht verlieren.” Jeder im Raum nickt. Niemand merkt, dass drei verschiedene Modelle gemeint sein können:</p>
|
||
<table>
|
||
<thead>
|
||
<tr class="header">
|
||
<th>Lesart</th>
|
||
<th style="text-align: right;">Deckungsbeitrag</th>
|
||
<th style="text-align: right;">kostet gegenüber „ohne Regel”</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr class="odd">
|
||
<td>ohne die Regel</td>
|
||
<td style="text-align: right;">78 500 €</td>
|
||
<td style="text-align: right;">—</td>
|
||
</tr>
|
||
<tr class="even">
|
||
<td><strong>A:</strong> jeden Stammkundenauftrag annehmen</td>
|
||
<td style="text-align: right;">66 000 €</td>
|
||
<td style="text-align: right;">12 500 €</td>
|
||
</tr>
|
||
<tr class="odd">
|
||
<td><strong>B:</strong> kein Stammkunde geht leer aus</td>
|
||
<td style="text-align: right;">75 000 €</td>
|
||
<td style="text-align: right;">3 500 €</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p><strong>Beide Lesarten erreichen dasselbe Ziel</strong> — kein Stammkunde geht leer aus. Lesart A kostet dafür das Dreieinhalbfache. Der Unterschied von 9 000 € entsteht durch eine Frage, die zehn Sekunden dauert:</p>
|
||
<blockquote>
|
||
<p><em>„Meinen Sie jeden Auftrag oder jeden Kunden?“</em></p>
|
||
</blockquote>
|
||
<p>Wer sie nicht stellt, entscheidet sie trotzdem — nur unbewusst, beim Tippen.</p>
|
||
<h3 id="teil-3-hart-oder-weich">Teil 3: Hart oder weich</h3>
|
||
<p>Dieselbe Regel als Strafkosten je abgelehntem Stammkundenauftrag:</p>
|
||
<table>
|
||
<thead>
|
||
<tr class="header">
|
||
<th style="text-align: right;">Strafe je Auftrag</th>
|
||
<th style="text-align: right;">Deckungsbeitrag</th>
|
||
<th style="text-align: right;">abgelehnte Stammaufträge</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr class="odd">
|
||
<td style="text-align: right;">3 000 €</td>
|
||
<td style="text-align: right;">78 500 €</td>
|
||
<td style="text-align: right;">2</td>
|
||
</tr>
|
||
<tr class="even">
|
||
<td style="text-align: right;">6 000 €</td>
|
||
<td style="text-align: right;">73 000 €</td>
|
||
<td style="text-align: right;">1</td>
|
||
</tr>
|
||
<tr class="odd">
|
||
<td style="text-align: right;">10 000 €</td>
|
||
<td style="text-align: right;">66 000 €</td>
|
||
<td style="text-align: right;">0</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>Bei 3 000 € ändert sich <strong>nichts</strong>: Die Strafe liegt unter dem Deckungsbeitrag, den die Stammkundenaufträge verdrängen würden. Bei 10 000 € kommt genau Lesart A heraus.</p>
|
||
<p>Daraus folgt eine Einsicht, die das Modellieren erleichtert: <strong>Eine harte Regel ist eine weiche mit hinreichend großer Strafe.</strong> Man kann also immer weich anfangen und die Strafe hochdrehen, bis die Regel greift — und sieht dabei, was sie kostet. Was ein Strafgewicht darüber hinaus bedeutet und warum zwei Gewichte einen <em>Wechselkurs</em> festlegen und keine Wichtigkeiten, steht in <a href="cpsat.html#sec:cpsat-denkfehler">Abschnitt 7.9</a>.</p>
|
||
<h3 id="teil-4-ein-quartal-später">Teil 4: Ein Quartal später</h3>
|
||
<p>Die harte Lesart A wurde eingebaut, alles lief drei Monate lang. Dann fragt Weber einen Auftrag über 320 Maschinenstunden an — mehr, als der ganze Zeitraum hergibt.</p>
|
||
<pre><code>Lesart A (hart): UNZULAESSIG - der Nachtlauf bricht ab
|
||
Lesart C (weich): loesbar - 66,000 EUR Deckungsbeitrag, 1 Stammauftrag abgelehnt</code></pre>
|
||
<p>Das ist kein konstruierter Sonderfall, sondern der Normalfall: <strong>Harte Regeln scheitern nicht bei ihrer Einführung, sondern Monate später</strong> — und zwar bevorzugt dann, wenn etwas Ungewöhnliches passiert, also genau dann, wenn man die Planung am dringendsten braucht.</p>
|
||
<p>Die weiche Variante antwortet auch dann noch. Sie lehnt den Großauftrag ab, weist das im Bericht aus, und ein Mensch entscheidet. Das ist der ganze Unterschied — und er wird beim Schreiben der Anforderung festgelegt, nicht beim Programmieren.</p>
|
||
<blockquote>
|
||
<p><strong>🎯 Merksatz</strong> Hart ist nur, was rechtlich oder physikalisch unmöglich ist. Alles andere wird weich mit hoher Strafe. Dann liefert der Solver den am wenigsten schlechten Plan statt einer Fehlermeldung — und die Fehlermeldung ist das, was niemand gebrauchen kann.</p>
|
||
</blockquote>
|
||
<hr />
|
||
<h2 id="sec:modellierung-leitfaden">4.5 Der Gesprächsleitfaden</h2>
|
||
<p>Was aus den vier Teilen als Handwerkszeug bleibt — Fragen, die man in der ersten Besprechung stellt, bevor eine Zeile Code entsteht:</p>
|
||
<blockquote>
|
||
<p><strong>📎 Zwölf Fragen für das erste Gespräch</strong></p>
|
||
<p><strong>Zur Entscheidung</strong> 1. Was genau wird entschieden — und von wem heute? 2. Was steht dabei <em>nicht</em> zur Disposition? 3. Wie oft wird entschieden, und wie viel Zeit ist dafür?</p>
|
||
<p><strong>Zum Ziel</strong> 4. Welche Zahl steht am Jahresende im Bericht? 5. Wenn genau diese Zahl maximiert würde — welcher Plan käme heraus, und wäre er akzeptabel? 6. Gibt es eine zweite Zahl, die auch stimmen muss? Was ist Ihnen ein Prozent der ersten wert, um ein Prozent der zweiten zu gewinnen?</p>
|
||
<p><strong>Zu den Regeln</strong> 7. Welche dieser Regeln ist gesetzlich oder physikalisch zwingend? 8. Welche würden Sie in einer Ausnahmesituation brechen — und was wäre eine Ausnahmesituation? 9. Bei „darf nicht”: Betrifft das jeden einzelnen Fall oder das Gesamtbild?</p>
|
||
<p><strong>Zum Betrieb</strong> 10. Was soll passieren, wenn es keine zulässige Lösung gibt? 11. Wer sieht das Ergebnis, und was muss er daran erkennen können? 12. Woran würden Sie in einem halben Jahr merken, dass das System nicht mehr das Richtige tut?</p>
|
||
<p>Frage 5 ist die wichtigste. Sie verwandelt eine abstrakte Zielangabe in einen konkreten Plan, den man ablehnen kann — und Ablehnung ist die einzige Form von Anforderungsklärung, die zuverlässig funktioniert.</p>
|
||
</blockquote>
|
||
<hr />
|
||
<h2 id="sec:modellierung-uebungsaufgaben">4.6 Übungsaufgaben</h2>
|
||
<blockquote>
|
||
<p>Lösungen: <a href="anhang-loesungen.html#sec:loesungen-modellierung">Abschnitt A.4</a>.</p>
|
||
</blockquote>
|
||
<p><strong>Aufgabe 4.1 ⭐ — Die fehlende Lesart.</strong> Der Text nennt zwei Lesarten von „Stammkunden dürfen wir nicht verlieren”. Formulieren Sie eine dritte, die weder A noch B ist, und sagen Sie, welchen Betrieb sie beschreiben würde.</p>
|
||
<p><strong>Aufgabe 4.2 ⭐ — Frage 5 anwenden.</strong> Ein Krankenhaus möchte „die Wartezeiten in der Notaufnahme senken”. Wenden Sie Frage 5 an: Welcher Plan käme heraus, wenn genau die durchschnittliche Wartezeit minimiert würde — und was wäre daran nicht akzeptabel?</p>
|
||
<p><strong>Aufgabe 4.3 ⭐⭐ — Der Kompromiss dazwischen.</strong> Zwischen Lesart A (12 500 €) und Lesart B (3 500 €) liegt Spielraum. Bauen Sie eine Variante, in der jeder Stammkunde <strong>mindestens die Hälfte</strong> seiner Auftragsstunden zugeteilt bekommt. Was kostet sie?</p>
|
||
<p><strong>Aufgabe 4.4 ⭐⭐ — Zwei Ziele gleichzeitig.</strong> Maximieren Sie <span class="math inline">\text{DB} + \lambda \cdot \text{Umsatz}</span> für <span class="math inline">\lambda \in \{0; 0{,}1; 0{,}3; 1\}</span> und tragen Sie die Ergebnisse als Tabelle auf. Ab welchem <span class="math inline">\lambda</span> kippt der Plan von der DB- in die Umsatzlösung? Was sagt dieser Wert dem Betrieb?</p>
|
||
<p><strong>Aufgabe 4.5 ⭐⭐⭐ — Die Anforderung schreiben.</strong> Formulieren Sie für den Fall dieses Kapitels eine vollständige, prüfbare Anforderung: Ziel, harte Regeln, weiche Regeln mit Strafgewichten, Verhalten bei Unlösbarkeit, auszuweisende Kennzahlen. Zwei Seiten genügen — sie sind mehr wert als zwei Wochen Programmierung.</p>
|
||
<hr />
|
||
<h2 id="sec:modellierung-denkfehler">4.7 Finde den Denkfehler</h2>
|
||
<div class="card card-denkfehler">
|
||
<blockquote>
|
||
<p><strong>🐛 „Die Engpassmaschine soll zu mindestens 92 % ausgelastet sein”</strong></p>
|
||
<p>Der Werkleiter formuliert eine klare, messbare, prüfbare Anforderung:</p>
|
||
<blockquote>
|
||
<p><em>„Die Engpassmaschine soll in jedem Planungszeitraum zu mindestens 92 % ausgelastet sein. > Das ist unsere teuerste Anlage, Leerlauf können wir uns nicht leisten.”</em></p>
|
||
</blockquote>
|
||
<p>Der Entwickler baut sie als harte Nebenbedingung ein — sie ist ja klar formuliert. Die Abnahme läuft mit den Daten des letzten Quartals: Der Plan hält die Vorgabe ein, der Deckungsbeitrag stimmt, alle Tests grün. Das System geht in Betrieb.</p>
|
||
<p><strong>Diese Anforderung enthält zwei verschiedene Fehler. Welche?</strong></p>
|
||
<p>Ein Hinweis für den zweiten: Sehen Sie sich an, was das Modell im Abnahmetest <em>tatsächlich</em> geprüft hat — und rechnen Sie einen Monat durch, in dem weniger Anfragen hereinkommen.</p>
|
||
</blockquote>
|
||
</div>
|
||
<hr />
|
||
<h2 id="sec:modellierung-quiz">4.8 Micro-Quiz</h2>
|
||
<div class="card card-quiz">
|
||
<blockquote>
|
||
<p><strong>❓ Drei Fragen</strong></p>
|
||
<p><strong>1. Warum liefert „Umsatz maximieren” hier einen schlechteren Plan als „Deckungsbeitrag maximieren”, obwohl beide Modelle korrekt sind?</strong> a) Weil der Solver bei Umsatzzielen ungenauer rechnet. b) Weil alles, was nicht in der Zielfunktion steht, für das Modell wertlos ist — nicht weniger wichtig. c) Weil Umsatzdaten in der Praxis unzuverlässiger sind als Kostendaten.</p>
|
||
<p><strong>2. Eine Regel als harte Nebenbedingung statt als Strafkosten zu formulieren, ist vor allem deshalb riskant, weil …</strong> a) … harte Nebenbedingungen den Solver verlangsamen. b) … das Modell unlösbar wird, sobald die Regel einmal nicht erfüllbar ist — und dann gar keine Antwort mehr liefert. c) … sich harte Regeln nachträglich nicht mehr ändern lassen.</p>
|
||
<p><strong>3. Alle drei Zielgrößen erreichen 100 % Auslastung. Was folgt daraus?</strong> a) Die Auslastung war schon vorher optimal, das Projekt ist überflüssig. b) Bei knapper Kapazität ist volle Auslastung die Voreinstellung; zu entscheiden ist nur, <em>womit</em> die Maschine voll wird. c) Die Kapazitätsdaten sind vermutlich falsch erfasst.</p>
|
||
</blockquote>
|
||
</div>
|
||
<hr />
|
||
<h2 id="sec:modellierung-selbsttest">4.9 Selbsttest</h2>
|
||
<ol type="1">
|
||
<li>Warum ist „Was ist Ihnen wichtig?” eine schlechte Frage und „Welche Zahl steht im Jahresbericht?” eine gute?</li>
|
||
<li>Nennen Sie zwei Kennzahlen aus Ihrem eigenen Arbeitsumfeld, deren Maximierung schaden würde.</li>
|
||
<li>Erklären Sie in einem Satz, warum eine harte Regel eine weiche mit großer Strafe ist — und wann der Unterschied trotzdem zählt.</li>
|
||
<li>Ein Kunde sagt: „Kein Mitarbeiter soll mehr als zwei Wochenenden im Monat arbeiten.” Nennen Sie zwei Lesarten und je eine Situation, in der sie auseinanderfallen.</li>
|
||
<li>Was antworten Sie auf die Frage „Was soll passieren, wenn es keine zulässige Lösung gibt?” — und warum ist „das kommt nicht vor” keine Antwort?</li>
|
||
</ol>
|
||
<hr />
|
||
<h2 id="sec:modellierung-zusammenfassung">4.10 Zusammenfassung</h2>
|
||
<ul>
|
||
<li>Ein Modell rechnet aus, was <strong>aufgeschrieben</strong> wurde, nicht was gemeint war. Die Zielfunktion ist eine vollständige Aussage: Was nicht darin steht, ist wertlos.</li>
|
||
<li>Die <strong>Zielgröße</strong> ist die folgenreichste Entscheidung eines OR-Projekts. Umsatz, Auslastung und Deckungsbeitrag führten hier auf demselben Datensatz zu drei verschiedenen Plänen mit 24 500 € Unterschied.</li>
|
||
<li><strong>Auslastung ist ein Ergebnis, kein Ziel.</strong> Bei knapper Kapazität ist die Maschine ohnehin voll; entscheidend ist, womit.</li>
|
||
<li>Ein Satz aus einer Besprechung hat meist <strong>mehrere Lesarten</strong>. „Stammkunden nicht verlieren” kostete je nach Lesart 3 500 € oder 12 500 € — bei identischem Ergebnis für die Kunden.</li>
|
||
<li><strong>Hart ist nur, was rechtlich oder physikalisch unmöglich ist.</strong> Eine harte Regel ist eine weiche mit hinreichend großer Strafe; der Unterschied zeigt sich erst, wenn sie einmal nicht erfüllbar ist — dann liefert die harte Variante gar nichts mehr.</li>
|
||
<li>Die vier Fragen — worüber wird entschieden, woran gemessen, was ist unverhandelbar, was bei Unlösbarkeit — gehören in die erste Besprechung. Der Leitfaden in <a href="#sec:modellierung-leitfaden">Abschnitt 4.5</a> macht zwölf daraus.</li>
|
||
</ul>
|
||
|
||
</article>
|
||
<button type="button" class="fortschritt-knopf" data-kapitel="modellierung.html"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg> <span>Als gelesen markieren</span></button>
|
||
<nav class="prev-next"><a class="prev-next-knopf prev-next-prev" href="oekosystem.html"><svg class="icon" aria-hidden="true"><use href="#icon-chevron-left"></use></svg><span><small>Zurück</small>Kapitel 3: Das Python-Ökosystem für OR — Solver, Bindings und Modellierungsschichten</span></a><a class="prev-next-knopf prev-next-next" href="lp.html"><span><small>Weiter</small>Kapitel 5: Lineare Programmierung — Simplex, Dualität und Schattenpreise</span><svg class="icon" aria-hidden="true"><use href="#icon-chevron-right"></use></svg></a></nav>
|
||
</main>
|
||
</div>
|
||
<footer class="site-footer">
|
||
<p>© Dieter Schlüter · <a href="gesamtdokument.html">Gesamtdokument</a> ·
|
||
<a href="programme.html">Beispielprogramme</a></p>
|
||
</footer>
|
||
<script defer src="assets/search-index.js"></script>
|
||
<script defer src="assets/programme.js"></script>
|
||
<script defer src="assets/site.js"></script>
|
||
</body>
|
||
</html>
|