Neues Skript erzeuge_stichwortregister_04.py:
- Sucht alle Glossarbegriffe (Anzeigename) in den Kapiteldateien
und markiert die erste Fundstelle je Datei mit {idx:Indexmarke}
- Termliste aus glossar_eintraege_04.py + vorhandenen {idx:...}-Markern
- Idempotent: erkennt vorhandene Marker und überspringt sie
- Überspringt Codeblöcke, Inline-Code und Math
- --check und --bericht Modi
- 605 Marker eingefügt (2 Durchläufe: 597 + 8)
Zusätzlich:
- titeltexte_04.py _saeubern(): entfernt {idx:...}-Marker vor
Titeltext-Vergleich (pruefe_titeltexte schlug sonst fehl)
819 lines
114 KiB
HTML
Generated
819 lines
114 KiB
HTML
Generated
<!doctype html>
|
||
<html lang="de">
|
||
<head>
|
||
<meta charset="utf-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||
<title>Kapitel 14: Mehrere Ziele — Pareto-Fronten statt Gewichte · 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"><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{idx: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"><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><li data-kapitel="synthese-grundlagen.html"><a href="synthese-grundlagen.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Synthese Teil I</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{idx: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{idx: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><li data-kapitel="synthese-kernverfahren.html"><a href="synthese-kernverfahren.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Synthese Teil II</span></a></li></ul></details><details class="sidebar-gruppe" open><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{idx:Bellman-Gleichung} und Order-Execution</span></a></li><li data-kapitel="mehrziel.html" class="aktiv"><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{idx:Predict-then-Optimize} — die bessere Prognose, die schlechtere Entscheidung</span></a></li><li data-kapitel="synthese-nichtlinear.html"><a href="synthese-nichtlinear.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Synthese Teil III</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{idx: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><li data-kapitel="synthese-anwendungen.html"><a href="synthese-anwendungen.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Synthese Teil IV</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="synthese-praxis.html"><a href="synthese-praxis.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Synthese Teil V</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.html"><a href="anhang-glossar.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Anhang E: Glossar</span></a></li><li data-kapitel="anhang-literatur.html"><a href="anhang-literatur.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Anhang F: Literaturverzeichnis</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="notebooks.html"><svg class="icon" aria-hidden="true"><use href="#icon-book"></use></svg> Notebooks</a></li><li><a href="Notebooks_04.zip" download><svg class="icon" aria-hidden="true"><use href="#icon-download"></use></svg> Download Notebooks als ZIP</a></li><li><a href="anhang-glossar.html"><svg class="icon" aria-hidden="true"><use href="#icon-book"></use></svg> Glossar</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 HTML-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 Buch als PDF</a></li></ul></div></nav>
|
||
<main class="content">
|
||
<nav class="breadcrumb" aria-label="Breadcrumb"><a href="index.html">Start</a> › <span>Teil III</span> › <span>Kapitel 14: Mehrere Ziele — Pareto-Fronten statt Gewichte</span></nav>
|
||
<nav class="prev-next"><a class="prev-next-knopf prev-next-prev" href="dynamische-programmierung.html"><svg class="icon" aria-hidden="true"><use href="#icon-chevron-left"></use></svg><span><small>Zurück</small>Kapitel 13: Dynamische Programmierung — Die Bellman-Gleichung{idx:Bellman-Gleichung} und Order-Execution</span></a><a class="prev-next-knopf prev-next-next" href="prognose.html"><span><small>Weiter</small>Kapitel 15: Predict-then-Optimize{idx:Predict-then-Optimize} — die bessere Prognose, die schlechtere Entscheidung</span><svg class="icon" aria-hidden="true"><use href="#icon-chevron-right"></use></svg></a></nav>
|
||
<article>
|
||
<h1 id="kap-mehrziel">Kapitel 14: Mehrere Ziele — Pareto-Fronten statt Gewichte</h1>
|
||
<div class="card card-blick">
|
||
<blockquote>
|
||
<p><strong>📌 Kapitel auf einen Blick</strong></p>
|
||
<p><strong>Worum geht es?</strong> Um den Normalfall, den die bisherigen Kapitel umgangen haben: Es gibt nicht <em>ein</em> Ziel, sondern zwei, die gegeneinander stehen. Kosten und CO₂, Termintreue und Bestand, Rendite und Risiko.</p>
|
||
<p><strong>Voraussetzungen:</strong> <a href="modellierung.html#kap-modellierung">Kapitel 4</a> (die Zielgröße als Entscheidung) und <a href="milp.html#kap-milp">Kapitel 6</a>. Für den Denkfehler hilft <a href="markowitz.html#kap-markowitz">Kapitel 19</a>.</p>
|
||
<p><strong>Danach können Sie:</strong> begründen, warum eine gewichtete Summe bei ganzzahligen Modellen Kompromisse <strong>grundsätzlich</strong> nicht erreichen kann; eine vollständige Pareto-Front mit dem ε-Constraint-Verfahren berechnen; und einer Geschäftsführung eine Entscheidung vorlegen, die sie tatsächlich treffen kann.</p>
|
||
<p><strong>Zeitbedarf:</strong> ca. 4 Stunden.</p>
|
||
<p><strong>Programme:</strong><br />
|
||
<code>Mehrziel_Pareto.py</code></p>
|
||
<p><strong>Notebook:</strong> <a href="Notebooks_04/mehrziel.ipynb">mehrziel.ipynb</a> — herunterladen und in Jupyter öffnen, in Colab hochladen oder mit dem Kurs-Image starten</p>
|
||
</blockquote>
|
||
</div>
|
||
<hr />
|
||
<h2 id="sec:mehrziel-schnellstart">14.1 In 5 Minuten gelöst</h2>
|
||
<div class="card card-schnellstart">
|
||
<blockquote>
|
||
<p><strong>🚀 In 5 Minuten gelöst: Was kostet ein Kilogramm CO₂?</strong></p>
|
||
<p>Eine Spedition vergibt fünf Sendungen an LKW, Bahn oder Kombinierten Verkehr. Der LKW ist billig und schmutzig, die Bahn teuer und sauber — und es sind nur zwei Trassen frei.</p>
|
||
<p>Statt zu fragen „wie wichtig ist uns CO₂?” fragen wir: <strong>Was bekommen wir für zwei Prozent mehr Geld?</strong></p>
|
||
<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"># LKW Bahn Kombi LKW billig+schmutzig, Bahn teuer+sauber</span></span>
|
||
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>kosten <span class="op">=</span> np.array([[ <span class="dv">900</span>, <span class="dv">1150</span>, <span class="dv">1020</span>], [ <span class="dv">620</span>, <span class="dv">790</span>, <span class="dv">700</span>], [<span class="dv">1300</span>, <span class="dv">1660</span>, <span class="dv">1470</span>],</span>
|
||
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a> [ <span class="dv">480</span>, <span class="dv">610</span>, <span class="dv">545</span>], [<span class="dv">1050</span>, <span class="dv">1340</span>, <span class="dv">1180</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>co2 <span class="op">=</span> np.array([[ <span class="dv">1400</span>, <span class="dv">310</span>, <span class="dv">760</span>], [ <span class="dv">980</span>, <span class="dv">220</span>, <span class="dv">530</span>], [<span class="dv">2000</span>, <span class="dv">440</span>, <span class="dv">1080</span>],</span>
|
||
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a> [ <span class="dv">760</span>, <span class="dv">170</span>, <span class="dv">410</span>], [<span class="dv">1620</span>, <span class="dv">360</span>, <span class="dv">880</span>]], dtype<span class="op">=</span><span class="bu">float</span>)</span>
|
||
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>eine_pro_sendung <span class="op">=</span> np.repeat(np.eye(<span class="dv">5</span>), <span class="dv">3</span>, axis<span class="op">=</span><span class="dv">1</span>)</span>
|
||
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>bahn_trassen <span class="op">=</span> [[<span class="fl">1.0</span> <span class="cf">if</span> j <span class="op">==</span> <span class="dv">1</span> <span class="cf">else</span> <span class="fl">0.0</span> <span class="cf">for</span> _ <span class="kw">in</span> <span class="bu">range</span>(<span class="dv">5</span>) <span class="cf">for</span> j <span class="kw">in</span> <span class="bu">range</span>(<span class="dv">3</span>)]]</span>
|
||
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> plane(ziel, kostenbudget<span class="op">=</span><span class="va">None</span>):</span>
|
||
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a> A, b <span class="op">=</span> <span class="bu">list</span>(bahn_trassen), [<span class="fl">2.0</span>] <span class="co"># nur zwei Trassen frei</span></span>
|
||
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> kostenbudget <span class="kw">is</span> <span class="kw">not</span> <span class="va">None</span>:</span>
|
||
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a> A.append(kosten.reshape(<span class="op">-</span><span class="dv">1</span>))<span class="op">;</span> b.append(kostenbudget)</span>
|
||
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a> x <span class="op">=</span> linprog(ziel.reshape(<span class="op">-</span><span class="dv">1</span>), A_ub<span class="op">=</span>A, b_ub<span class="op">=</span>b, A_eq<span class="op">=</span>eine_pro_sendung,</span>
|
||
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a> b_eq<span class="op">=</span>np.ones(<span class="dv">5</span>), 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</span>
|
||
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> kosten.reshape(<span class="op">-</span><span class="dv">1</span>) <span class="op">@</span> x, co2.reshape(<span class="op">-</span><span class="dv">1</span>) <span class="op">@</span> x</span>
|
||
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a>k0, c0 <span class="op">=</span> plane(kosten) <span class="co"># nur Kosten minimieren</span></span>
|
||
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a>k1, c1 <span class="op">=</span> plane(co2, kostenbudget<span class="op">=</span>k0 <span class="op">*</span> <span class="fl">1.02</span>) <span class="co"># 2 % mehr ausgeben</span></span>
|
||
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a><span class="bu">print</span>(<span class="ss">f"guenstigster Plan: </span><span class="sc">{</span>k0<span class="sc">:>7,.0f}</span><span class="ss"> EUR </span><span class="sc">{</span>c0<span class="sc">:>6,.0f}</span><span class="ss"> kg CO2"</span>)</span>
|
||
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a><span class="bu">print</span>(<span class="ss">f"mit 2 % Aufpreis: </span><span class="sc">{</span>k1<span class="sc">:>7,.0f}</span><span class="ss"> EUR </span><span class="sc">{</span>c1<span class="sc">:>6,.0f}</span><span class="ss"> kg CO2 "</span></span>
|
||
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a> <span class="ss">f"(</span><span class="sc">{</span>(c0<span class="op">-</span>c1)<span class="op">/</span>c0<span class="sc">:.0%}</span><span class="ss"> weniger, </span><span class="sc">{</span>(k1<span class="op">-</span>k0)<span class="op">/</span>(c0<span class="op">-</span>c1)<span class="sc">:.2f}</span><span class="ss"> EUR je kg)"</span>)</span></code></pre></div>
|
||
<p><strong>Ausgabe:</strong></p>
|
||
<pre><code>guenstigster Plan: 4,350 EUR 6,760 kg CO2
|
||
mit 2 % Aufpreis: 4,430 EUR 6,310 kg CO2 (7% weniger, 0.18 EUR je kg)</code></pre>
|
||
</blockquote>
|
||
</div>
|
||
<p><strong>Und jetzt der Punkt.</strong> 80 Euro mehr sparen 450 Kilogramm CO₂ — <strong>18 Cent je Kilogramm</strong>. Der europäische Emissionshandel bewegt sich um ein Vielfaches davon. Die Entscheidung ist damit keine Wertefrage mehr, sondern eine Rechnung.</p>
|
||
<p>Beachten Sie, was hier <em>nicht</em> passiert ist: Niemand musste ein Gewicht festlegen. Die zweite Zeile setzt eine <strong>Schranke</strong> („höchstens 2 % teurer”) und optimiert dann das andere Ziel. Das Ergebnis ist eine Aussage, die ein Kaufmann prüfen kann.</p>
|
||
<blockquote>
|
||
<p><strong>🎯 Merksatz</strong> „Wie wichtig ist Ihnen CO₂?” ist keine beantwortbare Frage. „Wir geben zwei Prozent mehr aus — was bringt das?” ist eine.</p>
|
||
</blockquote>
|
||
<p><strong>Warum funktioniert das?</strong> Weil aus zwei Zielen ein Ziel und eine Nebenbedingung geworden sind. Das ist die Grundidee des <strong>ε-Constraint-Verfahrens</strong>, um das sich dieses Kapitel dreht — und es ist der Grund, warum es ohne jedes Gewicht auskommt.</p>
|
||
<hr />
|
||
<h2 id="sec:mehrziel-lernziele">14.2 Lernziele</h2>
|
||
<p>Nach diesem Kapitel können Sie …</p>
|
||
<ol type="1">
|
||
<li>… Pareto-Dominanz und Pareto-Front definieren und an einem Diagramm zeigen.</li>
|
||
<li>… erklären, warum die gewichtete Summe nur <strong>gestützte</strong> Lösungen findet — und was das geometrisch heißt.</li>
|
||
<li>… eine vollständige Pareto-Front mit dem ε-Constraint-Verfahren berechnen, mit so vielen Solverläufen, wie die Front Punkte hat.</li>
|
||
<li>… lexikografische Optimierung einsetzen, wenn es eine klare Rangfolge der Ziele gibt.</li>
|
||
<li>… einer Entscheiderin die Front so vorlegen, dass sie eine Wahl treffen kann.</li>
|
||
</ol>
|
||
<hr />
|
||
<h2 id="sec:mehrziel-dominanz">14.3 Wann ein Kompromiss gut ist</h2>
|
||
<p>Bei einem Ziel ist „besser” eindeutig. Bei zwei Zielen nicht mehr: Ein Plan kann billiger und schmutziger sein als ein anderer, und dann ist keiner von beiden besser.</p>
|
||
<p>Vergleichbar sind nur die Fälle, in denen ein Plan in <strong>keinem</strong> Ziel schlechter ist:</p>
|
||
<p><span class="math display">
|
||
x \text{ dominiert } y
|
||
\quad :\Longleftrightarrow \quad
|
||
f_i(x) \le f_i(y)\ \text{ für alle } i
|
||
\ \text{ und }\
|
||
f_j(x) < f_j(y)\ \text{ für mindestens ein } j
|
||
</span></p>
|
||
<div class="card card-formel">
|
||
<blockquote>
|
||
<p><strong>🔤 Formel-Übersetzer</strong></p>
|
||
<table>
|
||
<colgroup>
|
||
<col style="width: 50%" />
|
||
<col style="width: 50%" />
|
||
</colgroup>
|
||
<thead>
|
||
<tr class="header">
|
||
<th>Mathematik</th>
|
||
<th>Alltagssprache</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr class="odd">
|
||
<td><span class="math inline">f_i(x) \le f_i(y)</span> für alle <span class="math inline">i</span></td>
|
||
<td>„Plan <span class="math inline">x</span> ist in <strong>keinem</strong> Ziel schlechter als <span class="math inline">y</span>.“</td>
|
||
</tr>
|
||
<tr class="even">
|
||
<td><span class="math inline">f_j(x) < f_j(y)</span> für ein <span class="math inline">j</span></td>
|
||
<td>„… und in mindestens einem echt besser.“</td>
|
||
</tr>
|
||
<tr class="odd">
|
||
<td><span class="math inline">x</span> dominiert <span class="math inline">y</span></td>
|
||
<td>„<span class="math inline">y</span> kann man wegwerfen. Es gibt keinen Grund, ihn zu wählen.“</td>
|
||
</tr>
|
||
<tr class="even">
|
||
<td><span class="math inline">x</span> ist <strong>pareto-optimal</strong></td>
|
||
<td>„Niemand dominiert <span class="math inline">x</span>. Wer <span class="math inline">x</span> verbessern will, muss anderswo schlechter werden.“</td>
|
||
</tr>
|
||
<tr class="odd">
|
||
<td><strong>Pareto-Front</strong></td>
|
||
<td>„Die Speisekarte: alle Pläne, die man ernsthaft in Betracht ziehen kann.“</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p><strong>Ohne Formel gesagt:</strong> Wegwerfen darf man einen Plan nur, wenn ein anderer ihn in jeder Hinsicht schlägt. Alles Übrige ist eine Frage der Präferenz — und die gehört nicht dem Modellierer.</p>
|
||
</blockquote>
|
||
</div>
|
||
<blockquote>
|
||
<p><strong>📖 Definition: Pareto-Front</strong></p>
|
||
<p>Die Menge aller nicht dominierten Lösungen. Sie ist das vollständige Ergebnis eines Mehrzielproblems — nicht ein Punkt, sondern eine Liste.</p>
|
||
<p>Wer daraus einen einzelnen Punkt macht, trifft eine Entscheidung. Die Frage ist nur, ob er es merkt.</p>
|
||
</blockquote>
|
||
<hr />
|
||
<h2 id="sec:mehrziel-skalarisierung">14.4 Der Reflex: alles in ein Ziel rühren</h2>
|
||
<p>Der naheliegende Weg, zwei Ziele zu einem zu machen, ist die <strong>gewichtete Summe</strong>:</p>
|
||
<p><span class="math display">
|
||
\min_{x \in X} \; c(x) + w \cdot e(x)
|
||
</span></p>
|
||
<div class="card card-formel">
|
||
<blockquote>
|
||
<p><strong>🔤 Formel-Übersetzer</strong></p>
|
||
<table>
|
||
<colgroup>
|
||
<col style="width: 50%" />
|
||
<col style="width: 50%" />
|
||
</colgroup>
|
||
<thead>
|
||
<tr class="header">
|
||
<th>Mathematik</th>
|
||
<th>Alltagssprache</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr class="odd">
|
||
<td><span class="math inline">c(x)</span></td>
|
||
<td>Transportkosten des Plans <span class="math inline">x</span>, in Euro.</td>
|
||
</tr>
|
||
<tr class="even">
|
||
<td><span class="math inline">e(x)</span></td>
|
||
<td>CO₂-Ausstoß desselben Plans, in Kilogramm.</td>
|
||
</tr>
|
||
<tr class="odd">
|
||
<td><span class="math inline">w</span></td>
|
||
<td>„So viele Euro ist mir ein Kilogramm CO₂ wert.“ Ein <strong>Wechselkurs</strong>, kein Wichtigkeitsregler (<a href="cpsat.html#sec:cpsat-denkfehler">Abschnitt 7.10</a>).</td>
|
||
</tr>
|
||
<tr class="even">
|
||
<td><span class="math inline">\min_{x \in X}</span></td>
|
||
<td>über alle zulässigen Pläne.</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>Der Ausdruck hat eine Einheit: Euro. Damit ist <span class="math inline">w</span> keine freie Zahl zwischen 0 und 1, sondern ein CO₂-Preis in €/kg — und den kann man tatsächlich beziffern.</p>
|
||
</blockquote>
|
||
</div>
|
||
<p>Das ist bequem, liefert zulässige Lösungen und wird in der Praxis fast immer so gemacht. Es hat nur einen Fehler, den man erst sieht, wenn man das Ergebnis mit der vollständigen Front vergleicht.</p>
|
||
<hr />
|
||
<h2 id="sec:mehrziel-programm">14.5 Das Programm</h2>
|
||
<p>Zwölf Sendungen, drei Verkehrsträger, fünf freie Bahntrassen. Der Zielkonflikt entsteht nicht zwischen den Trägern — die Bahn ist immer billiger <em>und</em> sauberer als der LKW —, sondern durch die <strong>Knappheit</strong> der Trassen. Genau so sieht es in der Praxis aus.</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"># Mehrziel_Pareto.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 Mehrziel: Kosten gegen CO2 - und warum Gewichte nicht genuegen.</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 Spedition vergibt zwoelf Sendungen an drei Verkehrstraeger: LKW (schnell,</span></span>
|
||
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a><span class="co">teuer, schmutzig), Bahn (billig und sauber, aber nur fuenf Trassen frei) und</span></span>
|
||
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a><span class="co">Kombinierten Verkehr (dazwischen). Zwei Ziele stehen gegeneinander:</span></span>
|
||
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a><span class="co">Transportkosten und CO2-Ausstoss.</span></span>
|
||
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a><span class="co">Der uebliche Reflex ist, beide Ziele zu einem zusammenzuruehren:</span></span>
|
||
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a><span class="co"> minimiere Kosten + w * CO2</span></span>
|
||
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true" tabindex="-1"></a><span class="co">Das ist bequem, liefert zulaessige Loesungen - und ist unvollstaendig. Bei</span></span>
|
||
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true" tabindex="-1"></a><span class="co">ganzzahligen Entscheidungen gibt es Kompromisse, die auf diesem Weg</span></span>
|
||
<span id="cb3-18"><a href="#cb3-18" aria-hidden="true" tabindex="-1"></a><span class="co">GRUNDSAETZLICH nicht erreichbar sind, egal welches w man waehlt. Nicht "schwer</span></span>
|
||
<span id="cb3-19"><a href="#cb3-19" aria-hidden="true" tabindex="-1"></a><span class="co">zu finden", sondern beweisbar unerreichbar.</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">Das Programm zeigt in vier Teilen:</span></span>
|
||
<span id="cb3-22"><a href="#cb3-22" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-23"><a href="#cb3-23" aria-hidden="true" tabindex="-1"></a><span class="co"> 1. Die beiden Extreme - was jedes Ziel allein kostet.</span></span>
|
||
<span id="cb3-24"><a href="#cb3-24" aria-hidden="true" tabindex="-1"></a><span class="co"> 2. Die lineare Skalarisierung ueber ein feines Gewichtsraster.</span></span>
|
||
<span id="cb3-25"><a href="#cb3-25" aria-hidden="true" tabindex="-1"></a><span class="co"> 3. Die vollstaendige Pareto-Front ueber das eps-Constraint-Verfahren.</span></span>
|
||
<span id="cb3-26"><a href="#cb3-26" aria-hidden="true" tabindex="-1"></a><span class="co"> 4. Den Nachweis, dass die Luecke keine Frage des Rasters ist, sondern</span></span>
|
||
<span id="cb3-27"><a href="#cb3-27" aria-hidden="true" tabindex="-1"></a><span class="co"> Geometrie: Die fehlenden Punkte liegen strikt oberhalb der konvexen</span></span>
|
||
<span id="cb3-28"><a href="#cb3-28" aria-hidden="true" tabindex="-1"></a><span class="co"> Huelle und koennen deshalb von keiner Geraden gestuetzt werden.</span></span>
|
||
<span id="cb3-29"><a href="#cb3-29" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-30"><a href="#cb3-30" aria-hidden="true" tabindex="-1"></a><span class="co">Benoetigt: numpy, scipy</span></span>
|
||
<span id="cb3-31"><a href="#cb3-31" aria-hidden="true" tabindex="-1"></a><span class="co">"""</span></span>
|
||
<span id="cb3-32"><a href="#cb3-32" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-33"><a href="#cb3-33" aria-hidden="true" tabindex="-1"></a><span class="im">from</span> __future__ <span class="im">import</span> annotations</span>
|
||
<span id="cb3-34"><a href="#cb3-34" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-35"><a href="#cb3-35" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> numpy <span class="im">as</span> np</span>
|
||
<span id="cb3-36"><a href="#cb3-36" aria-hidden="true" tabindex="-1"></a><span class="im">from</span> scipy.optimize <span class="im">import</span> linprog</span>
|
||
<span id="cb3-37"><a href="#cb3-37" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-38"><a href="#cb3-38" aria-hidden="true" tabindex="-1"></a>TRAEGER <span class="op">=</span> [<span class="st">"LKW"</span>, <span class="st">"Bahn"</span>, <span class="st">"Kombiniert"</span>]</span>
|
||
<span id="cb3-39"><a href="#cb3-39" aria-hidden="true" tabindex="-1"></a>BAHN_TRASSEN <span class="op">=</span> <span class="dv">5</span> <span class="co"># so viele Sendungen passen hoechstens auf die Bahn</span></span>
|
||
<span id="cb3-40"><a href="#cb3-40" aria-hidden="true" tabindex="-1"></a>SAAT <span class="op">=</span> <span class="dv">5</span></span>
|
||
<span id="cb3-41"><a href="#cb3-41" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-42"><a href="#cb3-42" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-43"><a href="#cb3-43" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> erzeuge_sendungen(anzahl: <span class="bu">int</span> <span class="op">=</span> <span class="dv">12</span>, saat: <span class="bu">int</span> <span class="op">=</span> SAAT):</span>
|
||
<span id="cb3-44"><a href="#cb3-44" aria-hidden="true" tabindex="-1"></a> <span class="co">"""Kosten und CO2 je Sendung und Verkehrstraeger.</span></span>
|
||
<span id="cb3-45"><a href="#cb3-45" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-46"><a href="#cb3-46" aria-hidden="true" tabindex="-1"></a><span class="co"> Die Bahn ist immer billiger und sauberer als der LKW - der Zielkonflikt</span></span>
|
||
<span id="cb3-47"><a href="#cb3-47" aria-hidden="true" tabindex="-1"></a><span class="co"> entsteht nicht zwischen den Traegern, sondern durch die KNAPPHEIT der</span></span>
|
||
<span id="cb3-48"><a href="#cb3-48" aria-hidden="true" tabindex="-1"></a><span class="co"> Trassen. Genau so sieht es in der Praxis aus.</span></span>
|
||
<span id="cb3-49"><a href="#cb3-49" aria-hidden="true" tabindex="-1"></a><span class="co"> """</span></span>
|
||
<span id="cb3-50"><a href="#cb3-50" aria-hidden="true" tabindex="-1"></a> rng <span class="op">=</span> np.random.default_rng(saat)</span>
|
||
<span id="cb3-51"><a href="#cb3-51" aria-hidden="true" tabindex="-1"></a> kosten <span class="op">=</span> np.zeros((anzahl, <span class="dv">3</span>))</span>
|
||
<span id="cb3-52"><a href="#cb3-52" aria-hidden="true" tabindex="-1"></a> co2 <span class="op">=</span> np.zeros((anzahl, <span class="dv">3</span>))</span>
|
||
<span id="cb3-53"><a href="#cb3-53" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> i <span class="kw">in</span> <span class="bu">range</span>(anzahl):</span>
|
||
<span id="cb3-54"><a href="#cb3-54" aria-hidden="true" tabindex="-1"></a> grund_kosten <span class="op">=</span> rng.integers(<span class="dv">600</span>, <span class="dv">2400</span>)</span>
|
||
<span id="cb3-55"><a href="#cb3-55" aria-hidden="true" tabindex="-1"></a> grund_co2 <span class="op">=</span> rng.integers(<span class="dv">400</span>, <span class="dv">1800</span>)</span>
|
||
<span id="cb3-56"><a href="#cb3-56" aria-hidden="true" tabindex="-1"></a> kosten[i] <span class="op">=</span> [grund_kosten,</span>
|
||
<span id="cb3-57"><a href="#cb3-57" aria-hidden="true" tabindex="-1"></a> grund_kosten <span class="op">*</span> rng.uniform(<span class="fl">0.55</span>, <span class="fl">0.85</span>),</span>
|
||
<span id="cb3-58"><a href="#cb3-58" aria-hidden="true" tabindex="-1"></a> grund_kosten <span class="op">*</span> rng.uniform(<span class="fl">0.70</span>, <span class="fl">1.00</span>)]</span>
|
||
<span id="cb3-59"><a href="#cb3-59" aria-hidden="true" tabindex="-1"></a> co2[i] <span class="op">=</span> [grund_co2,</span>
|
||
<span id="cb3-60"><a href="#cb3-60" aria-hidden="true" tabindex="-1"></a> grund_co2 <span class="op">*</span> rng.uniform(<span class="fl">0.15</span>, <span class="fl">0.35</span>),</span>
|
||
<span id="cb3-61"><a href="#cb3-61" aria-hidden="true" tabindex="-1"></a> grund_co2 <span class="op">*</span> rng.uniform(<span class="fl">0.40</span>, <span class="fl">0.70</span>)]</span>
|
||
<span id="cb3-62"><a href="#cb3-62" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> np.<span class="bu">round</span>(kosten).astype(<span class="bu">int</span>), np.<span class="bu">round</span>(co2).astype(<span class="bu">int</span>)</span>
|
||
<span id="cb3-63"><a href="#cb3-63" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-64"><a href="#cb3-64" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-65"><a href="#cb3-65" aria-hidden="true" tabindex="-1"></a>KOSTEN, CO2 <span class="op">=</span> erzeuge_sendungen()</span>
|
||
<span id="cb3-66"><a href="#cb3-66" aria-hidden="true" tabindex="-1"></a>N <span class="op">=</span> <span class="bu">len</span>(KOSTEN)</span>
|
||
<span id="cb3-67"><a href="#cb3-67" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-68"><a href="#cb3-68" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-69"><a href="#cb3-69" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> plane(ziel: np.ndarray, co2_grenze: <span class="bu">float</span> <span class="op">|</span> <span class="va">None</span> <span class="op">=</span> <span class="va">None</span>,</span>
|
||
<span id="cb3-70"><a href="#cb3-70" aria-hidden="true" tabindex="-1"></a> kosten_grenze: <span class="bu">float</span> <span class="op">|</span> <span class="va">None</span> <span class="op">=</span> <span class="va">None</span>):</span>
|
||
<span id="cb3-71"><a href="#cb3-71" aria-hidden="true" tabindex="-1"></a> <span class="co">"""Jede Sendung genau einem Traeger zuordnen; Trassen sind knapp.</span></span>
|
||
<span id="cb3-72"><a href="#cb3-72" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-73"><a href="#cb3-73" aria-hidden="true" tabindex="-1"></a><span class="co"> 'ziel' ist die zu minimierende Matrix (Kosten, CO2 oder eine Mischung).</span></span>
|
||
<span id="cb3-74"><a href="#cb3-74" aria-hidden="true" tabindex="-1"></a><span class="co"> Die beiden Grenzen sind das Werkzeug fuer eps-Constraint und</span></span>
|
||
<span id="cb3-75"><a href="#cb3-75" aria-hidden="true" tabindex="-1"></a><span class="co"> lexikografische Optimierung - sie machen aus einem Ziel eine Schranke.</span></span>
|
||
<span id="cb3-76"><a href="#cb3-76" aria-hidden="true" tabindex="-1"></a><span class="co"> """</span></span>
|
||
<span id="cb3-77"><a href="#cb3-77" aria-hidden="true" tabindex="-1"></a> gleichungen <span class="op">=</span> np.zeros((N, N <span class="op">*</span> <span class="dv">3</span>))</span>
|
||
<span id="cb3-78"><a href="#cb3-78" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> i <span class="kw">in</span> <span class="bu">range</span>(N):</span>
|
||
<span id="cb3-79"><a href="#cb3-79" aria-hidden="true" tabindex="-1"></a> gleichungen[i, i <span class="op">*</span> <span class="dv">3</span>:(i <span class="op">+</span> <span class="dv">1</span>) <span class="op">*</span> <span class="dv">3</span>] <span class="op">=</span> <span class="fl">1.0</span> <span class="co"># genau ein Traeger</span></span>
|
||
<span id="cb3-80"><a href="#cb3-80" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-81"><a href="#cb3-81" aria-hidden="true" tabindex="-1"></a> ungleichungen <span class="op">=</span> [[<span class="fl">1.0</span> <span class="cf">if</span> j <span class="op">==</span> <span class="dv">1</span> <span class="cf">else</span> <span class="fl">0.0</span> <span class="cf">for</span> _ <span class="kw">in</span> <span class="bu">range</span>(N) <span class="cf">for</span> j <span class="kw">in</span> <span class="bu">range</span>(<span class="dv">3</span>)]]</span>
|
||
<span id="cb3-82"><a href="#cb3-82" aria-hidden="true" tabindex="-1"></a> grenzen <span class="op">=</span> [<span class="bu">float</span>(BAHN_TRASSEN)]</span>
|
||
<span id="cb3-83"><a href="#cb3-83" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> co2_grenze <span class="kw">is</span> <span class="kw">not</span> <span class="va">None</span>:</span>
|
||
<span id="cb3-84"><a href="#cb3-84" aria-hidden="true" tabindex="-1"></a> ungleichungen.append(CO2.reshape(<span class="op">-</span><span class="dv">1</span>).astype(<span class="bu">float</span>))</span>
|
||
<span id="cb3-85"><a href="#cb3-85" aria-hidden="true" tabindex="-1"></a> grenzen.append(<span class="bu">float</span>(co2_grenze))</span>
|
||
<span id="cb3-86"><a href="#cb3-86" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> kosten_grenze <span class="kw">is</span> <span class="kw">not</span> <span class="va">None</span>:</span>
|
||
<span id="cb3-87"><a href="#cb3-87" aria-hidden="true" tabindex="-1"></a> ungleichungen.append(KOSTEN.reshape(<span class="op">-</span><span class="dv">1</span>).astype(<span class="bu">float</span>))</span>
|
||
<span id="cb3-88"><a href="#cb3-88" aria-hidden="true" tabindex="-1"></a> grenzen.append(<span class="bu">float</span>(kosten_grenze))</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> ergebnis <span class="op">=</span> linprog(ziel.reshape(<span class="op">-</span><span class="dv">1</span>).astype(<span class="bu">float</span>),</span>
|
||
<span id="cb3-91"><a href="#cb3-91" aria-hidden="true" tabindex="-1"></a> A_ub<span class="op">=</span>ungleichungen, b_ub<span class="op">=</span>grenzen,</span>
|
||
<span id="cb3-92"><a href="#cb3-92" aria-hidden="true" tabindex="-1"></a> A_eq<span class="op">=</span>gleichungen, b_eq<span class="op">=</span>np.ones(N),</span>
|
||
<span id="cb3-93"><a href="#cb3-93" 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-94"><a href="#cb3-94" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> <span class="kw">not</span> ergebnis.success:</span>
|
||
<span id="cb3-95"><a href="#cb3-95" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> <span class="va">None</span></span>
|
||
<span id="cb3-96"><a href="#cb3-96" aria-hidden="true" tabindex="-1"></a> plan <span class="op">=</span> np.<span class="bu">round</span>(ergebnis.x).astype(<span class="bu">int</span>)</span>
|
||
<span id="cb3-97"><a href="#cb3-97" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> (<span class="bu">int</span>(KOSTEN.reshape(<span class="op">-</span><span class="dv">1</span>) <span class="op">@</span> plan), <span class="bu">int</span>(CO2.reshape(<span class="op">-</span><span class="dv">1</span>) <span class="op">@</span> plan), plan)</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> pareto_front():</span>
|
||
<span id="cb3-101"><a href="#cb3-101" aria-hidden="true" tabindex="-1"></a> <span class="co">"""Vollstaendige Front ueber das eps-Constraint-Verfahren.</span></span>
|
||
<span id="cb3-102"><a href="#cb3-102" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-103"><a href="#cb3-103" aria-hidden="true" tabindex="-1"></a><span class="co"> Der Ablauf ist der eigentliche Inhalt dieser Funktion: Erst das</span></span>
|
||
<span id="cb3-104"><a href="#cb3-104" aria-hidden="true" tabindex="-1"></a><span class="co"> Kostenminimum bestimmen (der eine Rand der Front), dann die CO2-Schranke</span></span>
|
||
<span id="cb3-105"><a href="#cb3-105" aria-hidden="true" tabindex="-1"></a><span class="co"> schrittweise um genau ein Kilogramm unter den zuletzt erreichten Wert</span></span>
|
||
<span id="cb3-106"><a href="#cb3-106" aria-hidden="true" tabindex="-1"></a><span class="co"> druecken. Jeder Lauf liefert den naechsten Punkt - und wenn keiner mehr</span></span>
|
||
<span id="cb3-107"><a href="#cb3-107" aria-hidden="true" tabindex="-1"></a><span class="co"> zulaessig ist, ist die Front vollstaendig.</span></span>
|
||
<span id="cb3-108"><a href="#cb3-108" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-109"><a href="#cb3-109" aria-hidden="true" tabindex="-1"></a><span class="co"> Das braucht so viele Solveraufrufe, wie die Front Punkte hat. Ein Raster</span></span>
|
||
<span id="cb3-110"><a href="#cb3-110" aria-hidden="true" tabindex="-1"></a><span class="co"> ueber alle moeglichen CO2-Werte braeuchte hier fast tausend.</span></span>
|
||
<span id="cb3-111"><a href="#cb3-111" aria-hidden="true" tabindex="-1"></a><span class="co"> """</span></span>
|
||
<span id="cb3-112"><a href="#cb3-112" aria-hidden="true" tabindex="-1"></a> front <span class="op">=</span> []</span>
|
||
<span id="cb3-113"><a href="#cb3-113" aria-hidden="true" tabindex="-1"></a> start <span class="op">=</span> plane(KOSTEN)</span>
|
||
<span id="cb3-114"><a href="#cb3-114" aria-hidden="true" tabindex="-1"></a> grenze <span class="op">=</span> start[<span class="dv">1</span>]</span>
|
||
<span id="cb3-115"><a href="#cb3-115" aria-hidden="true" tabindex="-1"></a> <span class="cf">while</span> <span class="va">True</span>:</span>
|
||
<span id="cb3-116"><a href="#cb3-116" aria-hidden="true" tabindex="-1"></a> ergebnis <span class="op">=</span> plane(KOSTEN, co2_grenze<span class="op">=</span>grenze)</span>
|
||
<span id="cb3-117"><a href="#cb3-117" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> ergebnis <span class="kw">is</span> <span class="va">None</span>:</span>
|
||
<span id="cb3-118"><a href="#cb3-118" aria-hidden="true" tabindex="-1"></a> <span class="cf">break</span></span>
|
||
<span id="cb3-119"><a href="#cb3-119" aria-hidden="true" tabindex="-1"></a> front.append((ergebnis[<span class="dv">0</span>], ergebnis[<span class="dv">1</span>]))</span>
|
||
<span id="cb3-120"><a href="#cb3-120" aria-hidden="true" tabindex="-1"></a> grenze <span class="op">=</span> ergebnis[<span class="dv">1</span>] <span class="op">-</span> <span class="dv">1</span></span>
|
||
<span id="cb3-121"><a href="#cb3-121" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> front</span>
|
||
<span id="cb3-122"><a href="#cb3-122" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-123"><a href="#cb3-123" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-124"><a href="#cb3-124" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> skalarisierung(gewichte):</span>
|
||
<span id="cb3-125"><a href="#cb3-125" aria-hidden="true" tabindex="-1"></a> <span class="co">"""Was 'Kosten + w * CO2' fuer viele w hergibt - als Menge von Punkten."""</span></span>
|
||
<span id="cb3-126"><a href="#cb3-126" aria-hidden="true" tabindex="-1"></a> gefunden <span class="op">=</span> {}</span>
|
||
<span id="cb3-127"><a href="#cb3-127" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> w <span class="kw">in</span> gewichte:</span>
|
||
<span id="cb3-128"><a href="#cb3-128" aria-hidden="true" tabindex="-1"></a> ergebnis <span class="op">=</span> plane(KOSTEN <span class="op">+</span> w <span class="op">*</span> CO2)</span>
|
||
<span id="cb3-129"><a href="#cb3-129" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> ergebnis:</span>
|
||
<span id="cb3-130"><a href="#cb3-130" aria-hidden="true" tabindex="-1"></a> gefunden.setdefault((ergebnis[<span class="dv">0</span>], ergebnis[<span class="dv">1</span>]), []).append(w)</span>
|
||
<span id="cb3-131"><a href="#cb3-131" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> gefunden</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></span>
|
||
<span id="cb3-134"><a href="#cb3-134" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> untere_huelle(punkte):</span>
|
||
<span id="cb3-135"><a href="#cb3-135" aria-hidden="true" tabindex="-1"></a> <span class="co">"""Untere linke konvexe Huelle - genau die Punkte, die eine Gerade stuetzt.</span></span>
|
||
<span id="cb3-136"><a href="#cb3-136" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-137"><a href="#cb3-137" aria-hidden="true" tabindex="-1"></a><span class="co"> Der Zusammenhang, um den es geht: 'Kosten + w*CO2 minimieren' heisst</span></span>
|
||
<span id="cb3-138"><a href="#cb3-138" aria-hidden="true" tabindex="-1"></a><span class="co"> geometrisch, eine Gerade der Steigung -1/w von links unten an die</span></span>
|
||
<span id="cb3-139"><a href="#cb3-139" aria-hidden="true" tabindex="-1"></a><span class="co"> Punktwolke zu schieben. Sie beruehrt immer einen Eckpunkt der konvexen</span></span>
|
||
<span id="cb3-140"><a href="#cb3-140" aria-hidden="true" tabindex="-1"></a><span class="co"> Huelle. Punkte, die oberhalb liegen, werden nie beruehrt - fuer kein w.</span></span>
|
||
<span id="cb3-141"><a href="#cb3-141" aria-hidden="true" tabindex="-1"></a><span class="co"> """</span></span>
|
||
<span id="cb3-142"><a href="#cb3-142" aria-hidden="true" tabindex="-1"></a> huelle <span class="op">=</span> []</span>
|
||
<span id="cb3-143"><a href="#cb3-143" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> punkt <span class="kw">in</span> <span class="bu">sorted</span>(punkte):</span>
|
||
<span id="cb3-144"><a href="#cb3-144" aria-hidden="true" tabindex="-1"></a> <span class="cf">while</span> <span class="bu">len</span>(huelle) <span class="op">>=</span> <span class="dv">2</span>:</span>
|
||
<span id="cb3-145"><a href="#cb3-145" aria-hidden="true" tabindex="-1"></a> (x1, y1), (x2, y2) <span class="op">=</span> huelle[<span class="op">-</span><span class="dv">2</span>], huelle[<span class="op">-</span><span class="dv">1</span>]</span>
|
||
<span id="cb3-146"><a href="#cb3-146" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> (x2 <span class="op">-</span> x1) <span class="op">*</span> (punkt[<span class="dv">1</span>] <span class="op">-</span> y1) <span class="op">-</span> (y2 <span class="op">-</span> y1) <span class="op">*</span> (punkt[<span class="dv">0</span>] <span class="op">-</span> x1) <span class="op"><=</span> <span class="dv">0</span>:</span>
|
||
<span id="cb3-147"><a href="#cb3-147" aria-hidden="true" tabindex="-1"></a> huelle.pop()</span>
|
||
<span id="cb3-148"><a href="#cb3-148" aria-hidden="true" tabindex="-1"></a> <span class="cf">else</span>:</span>
|
||
<span id="cb3-149"><a href="#cb3-149" aria-hidden="true" tabindex="-1"></a> <span class="cf">break</span></span>
|
||
<span id="cb3-150"><a href="#cb3-150" aria-hidden="true" tabindex="-1"></a> huelle.append(punkt)</span>
|
||
<span id="cb3-151"><a href="#cb3-151" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> huelle</span>
|
||
<span id="cb3-152"><a href="#cb3-152" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-153"><a href="#cb3-153" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-154"><a href="#cb3-154" 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-155"><a href="#cb3-155" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"="</span> <span class="op">*</span> <span class="dv">80</span>)</span>
|
||
<span id="cb3-156"><a href="#cb3-156" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" KOSTEN GEGEN CO2 - UND WARUM GEWICHTE NICHT GENUEGEN"</span>)</span>
|
||
<span id="cb3-157"><a href="#cb3-157" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"="</span> <span class="op">*</span> <span class="dv">80</span>)</span>
|
||
<span id="cb3-158"><a href="#cb3-158" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f"</span><span class="sc">{</span>N<span class="sc">}</span><span class="ss"> Sendungen, </span><span class="sc">{</span><span class="bu">len</span>(TRAEGER)<span class="sc">}</span><span class="ss"> Verkehrstraeger, "</span></span>
|
||
<span id="cb3-159"><a href="#cb3-159" aria-hidden="true" tabindex="-1"></a> <span class="ss">f"</span><span class="sc">{</span>BAHN_TRASSEN<span class="sc">}</span><span class="ss"> freie Bahntrassen.</span><span class="ch">\n</span><span class="ss">"</span>)</span>
|
||
<span id="cb3-160"><a href="#cb3-160" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-161"><a href="#cb3-161" aria-hidden="true" tabindex="-1"></a> <span class="co"># --- 1. Die beiden Extreme -------------------------------------------</span></span>
|
||
<span id="cb3-162"><a href="#cb3-162" aria-hidden="true" tabindex="-1"></a> guenstigst <span class="op">=</span> plane(KOSTEN)</span>
|
||
<span id="cb3-163"><a href="#cb3-163" aria-hidden="true" tabindex="-1"></a> saubersten <span class="op">=</span> plane(CO2)</span>
|
||
<span id="cb3-164"><a href="#cb3-164" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"1. Was jedes Ziel allein ergibt</span><span class="ch">\n</span><span class="st">"</span>)</span>
|
||
<span id="cb3-165"><a href="#cb3-165" 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">:<22}</span><span class="ss"> </span><span class="sc">{</span><span class="st">'Kosten'</span><span class="sc">:>10}</span><span class="ss"> </span><span class="sc">{</span><span class="st">'CO2'</span><span class="sc">:>10}</span><span class="ss">"</span>)</span>
|
||
<span id="cb3-166"><a href="#cb3-166" 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">44</span>)</span>
|
||
<span id="cb3-167"><a href="#cb3-167" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f" </span><span class="sc">{</span><span class="st">'nur Kosten minimal'</span><span class="sc">:<22}</span><span class="ss"> </span><span class="sc">{</span>guenstigst[<span class="dv">0</span>]<span class="sc">:>10,}</span><span class="ss"> </span><span class="sc">{</span>guenstigst[<span class="dv">1</span>]<span class="sc">:>9,}</span><span class="ss"> kg"</span>)</span>
|
||
<span id="cb3-168"><a href="#cb3-168" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f" </span><span class="sc">{</span><span class="st">'nur CO2 minimal'</span><span class="sc">:<22}</span><span class="ss"> </span><span class="sc">{</span>saubersten[<span class="dv">0</span>]<span class="sc">:>10,}</span><span class="ss"> </span><span class="sc">{</span>saubersten[<span class="dv">1</span>]<span class="sc">:>9,}</span><span class="ss"> kg"</span>)</span>
|
||
<span id="cb3-169"><a href="#cb3-169" 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 Zielkonflikt ist echt, aber klein: "</span></span>
|
||
<span id="cb3-170"><a href="#cb3-170" aria-hidden="true" tabindex="-1"></a> <span class="ss">f"</span><span class="sc">{</span>saubersten[<span class="dv">0</span>] <span class="op">-</span> guenstigst[<span class="dv">0</span>]<span class="sc">:,}</span><span class="ss"> EUR mehr"</span>)</span>
|
||
<span id="cb3-171"><a href="#cb3-171" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f" (</span><span class="sc">{</span>(saubersten[<span class="dv">0</span>] <span class="op">-</span> guenstigst[<span class="dv">0</span>]) <span class="op">/</span> guenstigst[<span class="dv">0</span>] <span class="op">*</span> <span class="dv">100</span><span class="sc">:.1f}</span><span class="ss"> %) sparen "</span></span>
|
||
<span id="cb3-172"><a href="#cb3-172" aria-hidden="true" tabindex="-1"></a> <span class="ss">f"</span><span class="sc">{</span>guenstigst[<span class="dv">1</span>] <span class="op">-</span> saubersten[<span class="dv">1</span>]<span class="sc">:,}</span><span class="ss"> kg CO2 "</span></span>
|
||
<span id="cb3-173"><a href="#cb3-173" aria-hidden="true" tabindex="-1"></a> <span class="ss">f"(</span><span class="sc">{</span>(guenstigst[<span class="dv">1</span>] <span class="op">-</span> saubersten[<span class="dv">1</span>]) <span class="op">/</span> guenstigst[<span class="dv">1</span>] <span class="op">*</span> <span class="dv">100</span><span class="sc">:.1f}</span><span class="ss"> %)."</span>)</span>
|
||
<span id="cb3-174"><a href="#cb3-174" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" Genau solche Zahlen will die Geschaeftsfuehrung sehen - nicht ein"</span>)</span>
|
||
<span id="cb3-175"><a href="#cb3-175" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" Gewicht, das niemand interpretieren kann."</span>)</span>
|
||
<span id="cb3-176"><a href="#cb3-176" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-177"><a href="#cb3-177" aria-hidden="true" tabindex="-1"></a> <span class="co"># --- 2. Die lineare Skalarisierung -----------------------------------</span></span>
|
||
<span id="cb3-178"><a href="#cb3-178" aria-hidden="true" tabindex="-1"></a> gewichte <span class="op">=</span> np.concatenate([np.linspace(<span class="fl">0.0</span>, <span class="fl">3.0</span>, <span class="dv">1201</span>),</span>
|
||
<span id="cb3-179"><a href="#cb3-179" aria-hidden="true" tabindex="-1"></a> np.geomspace(<span class="fl">3.0</span>, <span class="fl">1000.0</span>, <span class="dv">200</span>)])</span>
|
||
<span id="cb3-180"><a href="#cb3-180" aria-hidden="true" tabindex="-1"></a> gefunden <span class="op">=</span> skalarisierung(gewichte)</span>
|
||
<span id="cb3-181"><a href="#cb3-181" 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">80</span>)</span>
|
||
<span id="cb3-182"><a href="#cb3-182" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f"2. Lineare Skalarisierung: 'Kosten + w * CO2' fuer "</span></span>
|
||
<span id="cb3-183"><a href="#cb3-183" aria-hidden="true" tabindex="-1"></a> <span class="ss">f"</span><span class="sc">{</span><span class="bu">len</span>(gewichte)<span class="sc">:,}</span><span class="ss"> Gewichte</span><span class="ch">\n</span><span class="ss">"</span>)</span>
|
||
<span id="cb3-184"><a href="#cb3-184" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f" </span><span class="sc">{</span><span class="st">'Kosten'</span><span class="sc">:>10}</span><span class="ss"> </span><span class="sc">{</span><span class="st">'CO2'</span><span class="sc">:>10}</span><span class="ss"> </span><span class="sc">{</span><span class="st">'gefunden bei w'</span><span class="sc">:>16}</span><span class="ss">"</span>)</span>
|
||
<span id="cb3-185"><a href="#cb3-185" 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">46</span>)</span>
|
||
<span id="cb3-186"><a href="#cb3-186" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> (k, c), ws <span class="kw">in</span> <span class="bu">sorted</span>(gefunden.items()):</span>
|
||
<span id="cb3-187"><a href="#cb3-187" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f" </span><span class="sc">{</span>k<span class="sc">:>10,}</span><span class="ss"> </span><span class="sc">{</span>c<span class="sc">:>9,}</span><span class="ss"> kg </span><span class="sc">{</span><span class="bu">min</span>(ws)<span class="sc">:>7.3f}</span><span class="ss"> bis </span><span class="sc">{</span><span class="bu">max</span>(ws)<span class="sc">:>7.3f}</span><span class="ss">"</span>)</span>
|
||
<span id="cb3-188"><a href="#cb3-188" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f"</span><span class="ch">\n</span><span class="ss"> </span><span class="sc">{</span><span class="bu">len</span>(gefunden)<span class="sc">}</span><span class="ss"> verschiedene Plaene - fuer </span><span class="sc">{</span><span class="bu">len</span>(gewichte)<span class="sc">:,}</span><span class="ss"> Gewichte."</span>)</span>
|
||
<span id="cb3-189"><a href="#cb3-189" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" Das Gewicht ist also gar keine Feineinstellung: Weite Bereiche"</span>)</span>
|
||
<span id="cb3-190"><a href="#cb3-190" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" liefern dasselbe Ergebnis, und dazwischen springt es."</span>)</span>
|
||
<span id="cb3-191"><a href="#cb3-191" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-192"><a href="#cb3-192" aria-hidden="true" tabindex="-1"></a> <span class="co"># --- 3. Die vollstaendige Front --------------------------------------</span></span>
|
||
<span id="cb3-193"><a href="#cb3-193" aria-hidden="true" tabindex="-1"></a> front <span class="op">=</span> pareto_front()</span>
|
||
<span id="cb3-194"><a href="#cb3-194" 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">80</span>)</span>
|
||
<span id="cb3-195"><a href="#cb3-195" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f"3. Die vollstaendige Pareto-Front ueber eps-Constraint "</span></span>
|
||
<span id="cb3-196"><a href="#cb3-196" aria-hidden="true" tabindex="-1"></a> <span class="ss">f"(</span><span class="sc">{</span><span class="bu">len</span>(front)<span class="sc">}</span><span class="ss"> Solverlaeufe)</span><span class="ch">\n</span><span class="ss">"</span>)</span>
|
||
<span id="cb3-197"><a href="#cb3-197" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f" </span><span class="sc">{</span><span class="st">'Kosten'</span><span class="sc">:>10}</span><span class="ss"> </span><span class="sc">{</span><span class="st">'CO2'</span><span class="sc">:>10}</span><span class="ss"> </span><span class="sc">{</span><span class="st">'Aufpreis'</span><span class="sc">:>9}</span><span class="ss"> </span><span class="sc">{</span><span class="st">'CO2-Ersparnis'</span><span class="sc">:>14}</span><span class="ss"> "</span></span>
|
||
<span id="cb3-198"><a href="#cb3-198" aria-hidden="true" tabindex="-1"></a> <span class="ss">f"</span><span class="sc">{</span><span class="st">'EUR je kg'</span><span class="sc">:>10}</span><span class="ss">"</span>)</span>
|
||
<span id="cb3-199"><a href="#cb3-199" 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">60</span>)</span>
|
||
<span id="cb3-200"><a href="#cb3-200" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> k, c <span class="kw">in</span> front:</span>
|
||
<span id="cb3-201"><a href="#cb3-201" aria-hidden="true" tabindex="-1"></a> auf <span class="op">=</span> k <span class="op">-</span> guenstigst[<span class="dv">0</span>]</span>
|
||
<span id="cb3-202"><a href="#cb3-202" aria-hidden="true" tabindex="-1"></a> ersparnis <span class="op">=</span> guenstigst[<span class="dv">1</span>] <span class="op">-</span> c</span>
|
||
<span id="cb3-203"><a href="#cb3-203" aria-hidden="true" tabindex="-1"></a> preis <span class="op">=</span> auf <span class="op">/</span> ersparnis <span class="cf">if</span> ersparnis <span class="cf">else</span> <span class="fl">0.0</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" </span><span class="sc">{</span>k<span class="sc">:>10,}</span><span class="ss"> </span><span class="sc">{</span>c<span class="sc">:>9,}</span><span class="ss"> kg </span><span class="sc">{</span>auf<span class="sc">:>8,}</span><span class="ss"> </span><span class="sc">{</span>ersparnis<span class="sc">:>13,}</span><span class="ss"> "</span></span>
|
||
<span id="cb3-205"><a href="#cb3-205" aria-hidden="true" tabindex="-1"></a> <span class="ss">f"</span><span class="sc">{</span>preis<span class="sc">:>10.2f}</span><span class="ss">"</span>)</span>
|
||
<span id="cb3-206"><a href="#cb3-206" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-207"><a href="#cb3-207" aria-hidden="true" tabindex="-1"></a> <span class="co"># --- 4. Der Nachweis --------------------------------------------------</span></span>
|
||
<span id="cb3-208"><a href="#cb3-208" aria-hidden="true" tabindex="-1"></a> huelle <span class="op">=</span> untere_huelle(front)</span>
|
||
<span id="cb3-209"><a href="#cb3-209" aria-hidden="true" tabindex="-1"></a> unerreichbar <span class="op">=</span> [p <span class="cf">for</span> p <span class="kw">in</span> front <span class="cf">if</span> p <span class="kw">not</span> <span class="kw">in</span> huelle]</span>
|
||
<span id="cb3-210"><a href="#cb3-210" 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">80</span>)</span>
|
||
<span id="cb3-211"><a href="#cb3-211" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"4. Was die Skalarisierung nicht findet</span><span class="ch">\n</span><span class="st">"</span>)</span>
|
||
<span id="cb3-212"><a href="#cb3-212" aria-hidden="true" tabindex="-1"></a> erreicht <span class="op">=</span> [p <span class="cf">for</span> p <span class="kw">in</span> front <span class="cf">if</span> p <span class="kw">in</span> gefunden]</span>
|
||
<span id="cb3-213"><a href="#cb3-213" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f" Pareto-Punkte insgesamt: </span><span class="sc">{</span><span class="bu">len</span>(front)<span class="sc">}</span><span class="ss">"</span>)</span>
|
||
<span id="cb3-214"><a href="#cb3-214" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f" davon von der Skalarisierung gefunden: </span><span class="sc">{</span><span class="bu">len</span>(erreicht)<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="bu">print</span>(<span class="ss">f" nie gefunden: </span><span class="sc">{</span><span class="bu">len</span>(front) <span class="op">-</span> <span class="bu">len</span>(erreicht)<span class="sc">}</span><span class="ss">"</span>)</span>
|
||
<span id="cb3-216"><a href="#cb3-216" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>()</span>
|
||
<span id="cb3-217"><a href="#cb3-217" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" Diese Kompromisse sind fuer KEIN Gewicht erreichbar:</span><span class="ch">\n</span><span class="st">"</span>)</span>
|
||
<span id="cb3-218"><a href="#cb3-218" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f" </span><span class="sc">{</span><span class="st">'Kosten'</span><span class="sc">:>10}</span><span class="ss"> </span><span class="sc">{</span><span class="st">'CO2'</span><span class="sc">:>10}</span><span class="ss"> </span><span class="sc">{</span><span class="st">'Aufpreis'</span><span class="sc">:>9}</span><span class="ss"> </span><span class="sc">{</span><span class="st">'CO2-Ersparnis'</span><span class="sc">:>14}</span><span class="ss">"</span>)</span>
|
||
<span id="cb3-219"><a href="#cb3-219" 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">50</span>)</span>
|
||
<span id="cb3-220"><a href="#cb3-220" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> k, c <span class="kw">in</span> unerreichbar:</span>
|
||
<span id="cb3-221"><a href="#cb3-221" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f" </span><span class="sc">{</span>k<span class="sc">:>10,}</span><span class="ss"> </span><span class="sc">{</span>c<span class="sc">:>9,}</span><span class="ss"> kg </span><span class="sc">{</span>k <span class="op">-</span> guenstigst[<span class="dv">0</span>]<span class="sc">:>8,}</span><span class="ss"> "</span></span>
|
||
<span id="cb3-222"><a href="#cb3-222" aria-hidden="true" tabindex="-1"></a> <span class="ss">f"</span><span class="sc">{</span>guenstigst[<span class="dv">1</span>] <span class="op">-</span> c<span class="sc">:>13,}</span><span class="ss">"</span>)</span>
|
||
<span id="cb3-223"><a href="#cb3-223" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-224"><a href="#cb3-224" aria-hidden="true" tabindex="-1"></a> stimmt <span class="op">=</span> <span class="bu">sorted</span>(unerreichbar) <span class="op">==</span> <span class="bu">sorted</span>(p <span class="cf">for</span> p <span class="kw">in</span> front <span class="cf">if</span> p <span class="kw">not</span> <span class="kw">in</span> gefunden)</span>
|
||
<span id="cb3-225"><a href="#cb3-225" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f"</span><span class="ch">\n</span><span class="ss"> Gegenprobe ueber die Geometrie: </span><span class="sc">{</span><span class="st">'bestanden'</span> <span class="cf">if</span> stimmt <span class="cf">else</span> <span class="st">'ABWEICHUNG'</span><span class="sc">}</span><span class="ss">"</span>)</span>
|
||
<span id="cb3-226"><a href="#cb3-226" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" Genau die Punkte, die das Gewichtsraster verfehlt, liegen strikt"</span>)</span>
|
||
<span id="cb3-227"><a href="#cb3-227" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" oberhalb der unteren konvexen Huelle. Das ist kein Rasterproblem -"</span>)</span>
|
||
<span id="cb3-228"><a href="#cb3-228" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" eine Gerade, die von links unten an die Wolke geschoben wird,"</span>)</span>
|
||
<span id="cb3-229"><a href="#cb3-229" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" beruehrt immer einen Eckpunkt der Huelle und nie einen Punkt"</span>)</span>
|
||
<span id="cb3-230"><a href="#cb3-230" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" darueber. Ein feineres Raster aendert daran nichts."</span>)</span>
|
||
<span id="cb3-231"><a href="#cb3-231" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-232"><a href="#cb3-232" aria-hidden="true" tabindex="-1"></a> <span class="co"># --- 5. Lexikografisch -------------------------------------------------</span></span>
|
||
<span id="cb3-233"><a href="#cb3-233" 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">80</span>)</span>
|
||
<span id="cb3-234"><a href="#cb3-234" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"5. Lexikografisch: erst Kosten, dann CO2 im Rahmen eines Budgets</span><span class="ch">\n</span><span class="st">"</span>)</span>
|
||
<span id="cb3-235"><a href="#cb3-235" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f" </span><span class="sc">{</span><span class="st">'Kostenbudget'</span><span class="sc">:>14}</span><span class="ss"> </span><span class="sc">{</span><span class="st">'Kosten'</span><span class="sc">:>10}</span><span class="ss"> </span><span class="sc">{</span><span class="st">'CO2'</span><span class="sc">:>10}</span><span class="ss"> </span><span class="sc">{</span><span class="st">'gegenueber Minimum'</span><span class="sc">:>20}</span><span class="ss">"</span>)</span>
|
||
<span id="cb3-236"><a href="#cb3-236" 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">58</span>)</span>
|
||
<span id="cb3-237"><a href="#cb3-237" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> aufschlag <span class="kw">in</span> (<span class="fl">0.00</span>, <span class="fl">0.01</span>, <span class="fl">0.02</span>, <span class="fl">0.05</span>, <span class="fl">0.10</span>):</span>
|
||
<span id="cb3-238"><a href="#cb3-238" aria-hidden="true" tabindex="-1"></a> budget <span class="op">=</span> guenstigst[<span class="dv">0</span>] <span class="op">*</span> (<span class="dv">1</span> <span class="op">+</span> aufschlag)</span>
|
||
<span id="cb3-239"><a href="#cb3-239" aria-hidden="true" tabindex="-1"></a> ergebnis <span class="op">=</span> plane(CO2, kosten_grenze<span class="op">=</span>budget)</span>
|
||
<span id="cb3-240"><a href="#cb3-240" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> ergebnis <span class="kw">is</span> <span class="va">None</span>:</span>
|
||
<span id="cb3-241"><a href="#cb3-241" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f" </span><span class="sc">{</span>aufschlag<span class="sc">:>13.0%}</span><span class="ss"> unzulaessig"</span>)</span>
|
||
<span id="cb3-242"><a href="#cb3-242" aria-hidden="true" tabindex="-1"></a> <span class="cf">continue</span></span>
|
||
<span id="cb3-243"><a href="#cb3-243" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f" </span><span class="sc">{</span>aufschlag<span class="sc">:>13.0%}</span><span class="ss"> </span><span class="sc">{</span>ergebnis[<span class="dv">0</span>]<span class="sc">:>10,}</span><span class="ss"> </span><span class="sc">{</span>ergebnis[<span class="dv">1</span>]<span class="sc">:>9,}</span><span class="ss"> kg "</span></span>
|
||
<span id="cb3-244"><a href="#cb3-244" aria-hidden="true" tabindex="-1"></a> <span class="ss">f"</span><span class="sc">{</span>guenstigst[<span class="dv">1</span>] <span class="op">-</span> ergebnis[<span class="dv">1</span>]<span class="sc">:>15,}</span><span class="ss"> kg weniger"</span>)</span>
|
||
<span id="cb3-245"><a href="#cb3-245" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-246"><a href="#cb3-246" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"</span><span class="ch">\n</span><span class="st"> Das ist die Form, die im Betrieb am ehesten trifft: Nicht 'wie"</span>)</span>
|
||
<span id="cb3-247"><a href="#cb3-247" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" wichtig ist CO2?', sondern 'wir geben zwei Prozent mehr aus - was"</span>)</span>
|
||
<span id="cb3-248"><a href="#cb3-248" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" bringt das?'. Die Frage kann ein Kaufmann beantworten."</span>)</span>
|
||
<span id="cb3-249"><a href="#cb3-249" aria-hidden="true" tabindex="-1"></a></span>
|
||
<span id="cb3-250"><a href="#cb3-250" 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">80</span>)</span>
|
||
<span id="cb3-251"><a href="#cb3-251" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" WAS MAN DARAUS MITNIMMT"</span>)</span>
|
||
<span id="cb3-252"><a href="#cb3-252" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"="</span> <span class="op">*</span> <span class="dv">80</span>)</span>
|
||
<span id="cb3-253"><a href="#cb3-253" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"Ein Gewicht zu setzen heisst, die Entscheidung heimlich zu treffen -"</span>)</span>
|
||
<span id="cb3-254"><a href="#cb3-254" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"und dabei einen Teil der Moeglichkeiten gar nicht erst zu sehen."</span>)</span>
|
||
<span id="cb3-255"><a href="#cb3-255" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>()</span>
|
||
<span id="cb3-256"><a href="#cb3-256" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"Die Pareto-Front ist die ehrlichere Antwort: Sie legt dem Betrieb"</span>)</span>
|
||
<span id="cb3-257"><a href="#cb3-257" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"alle sinnvollen Kompromisse vor und ueberlaesst ihm die Wahl. Die"</span>)</span>
|
||
<span id="cb3-258"><a href="#cb3-258" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"Spalte 'EUR je kg' macht sie entscheidbar - man vergleicht sie mit"</span>)</span>
|
||
<span id="cb3-259"><a href="#cb3-259" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"dem CO2-Preis, den das Unternehmen ohnehin ansetzt."</span>)</span>
|
||
<span id="cb3-260"><a href="#cb3-260" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"="</span> <span class="op">*</span> <span class="dv">80</span>)</span></code></pre></div>
|
||
<p><strong>Erwartete Ausgabe:</strong></p>
|
||
<pre><code>================================================================================
|
||
KOSTEN GEGEN CO2 - UND WARUM GEWICHTE NICHT GENUEGEN
|
||
================================================================================
|
||
12 Sendungen, 3 Verkehrstraeger, 5 freie Bahntrassen.
|
||
|
||
1. Was jedes Ziel allein ergibt
|
||
|
||
Kosten CO2
|
||
--------------------------------------------
|
||
nur Kosten minimal 13,543 6,475 kg
|
||
nur CO2 minimal 14,821 5,506 kg
|
||
|
||
Der Zielkonflikt ist echt, aber klein: 1,278 EUR mehr
|
||
(9.4 %) sparen 969 kg CO2 (15.0 %).
|
||
Genau solche Zahlen will die Geschaeftsfuehrung sehen - nicht ein
|
||
Gewicht, das niemand interpretieren kann.
|
||
|
||
--------------------------------------------------------------------------------
|
||
2. Lineare Skalarisierung: 'Kosten + w * CO2' fuer 1,401 Gewichte
|
||
|
||
Kosten CO2 gefunden bei w
|
||
----------------------------------------------
|
||
13,543 6,475 kg 0.000 bis 0.398
|
||
13,724 6,022 kg 0.400 bis 1.002
|
||
14,036 5,711 kg 1.005 bis 1.935
|
||
14,189 5,632 kg 1.938 bis 3.471
|
||
14,592 5,517 kg 3.574 bis 20.599
|
||
14,821 5,506 kg 21.210 bis 1000.000
|
||
|
||
6 verschiedene Plaene - fuer 1,401 Gewichte.
|
||
Das Gewicht ist also gar keine Feineinstellung: Weite Bereiche
|
||
liefern dasselbe Ergebnis, und dazwischen springt es.
|
||
|
||
--------------------------------------------------------------------------------
|
||
3. Die vollstaendige Pareto-Front ueber eps-Constraint (10 Solverlaeufe)
|
||
|
||
Kosten CO2 Aufpreis CO2-Ersparnis EUR je kg
|
||
------------------------------------------------------------
|
||
13,543 6,475 kg 0 0 0.00
|
||
13,635 6,317 kg 92 158 0.58
|
||
13,718 6,286 kg 175 189 0.93
|
||
13,724 6,022 kg 181 453 0.40
|
||
13,868 5,927 kg 325 548 0.59
|
||
13,978 5,912 kg 435 563 0.77
|
||
14,036 5,711 kg 493 764 0.65
|
||
14,189 5,632 kg 646 843 0.77
|
||
14,592 5,517 kg 1,049 958 1.09
|
||
14,821 5,506 kg 1,278 969 1.32
|
||
|
||
--------------------------------------------------------------------------------
|
||
4. Was die Skalarisierung nicht findet
|
||
|
||
Pareto-Punkte insgesamt: 10
|
||
davon von der Skalarisierung gefunden: 6
|
||
nie gefunden: 4
|
||
|
||
Diese Kompromisse sind fuer KEIN Gewicht erreichbar:
|
||
|
||
Kosten CO2 Aufpreis CO2-Ersparnis
|
||
--------------------------------------------------
|
||
13,635 6,317 kg 92 158
|
||
13,718 6,286 kg 175 189
|
||
13,868 5,927 kg 325 548
|
||
13,978 5,912 kg 435 563
|
||
|
||
Gegenprobe ueber die Geometrie: bestanden
|
||
Genau die Punkte, die das Gewichtsraster verfehlt, liegen strikt
|
||
oberhalb der unteren konvexen Huelle. Das ist kein Rasterproblem -
|
||
eine Gerade, die von links unten an die Wolke geschoben wird,
|
||
beruehrt immer einen Eckpunkt der Huelle und nie einen Punkt
|
||
darueber. Ein feineres Raster aendert daran nichts.
|
||
|
||
--------------------------------------------------------------------------------
|
||
5. Lexikografisch: erst Kosten, dann CO2 im Rahmen eines Budgets
|
||
|
||
Kostenbudget Kosten CO2 gegenueber Minimum
|
||
----------------------------------------------------------
|
||
0% 13,543 6,475 kg 0 kg weniger
|
||
1% 13,635 6,317 kg 158 kg weniger
|
||
2% 13,724 6,022 kg 453 kg weniger
|
||
5% 14,189 5,632 kg 843 kg weniger
|
||
10% 14,821 5,506 kg 969 kg weniger
|
||
|
||
Das ist die Form, die im Betrieb am ehesten trifft: Nicht 'wie
|
||
wichtig ist CO2?', sondern 'wir geben zwei Prozent mehr aus - was
|
||
bringt das?'. Die Frage kann ein Kaufmann beantworten.
|
||
|
||
================================================================================
|
||
WAS MAN DARAUS MITNIMMT
|
||
================================================================================
|
||
Ein Gewicht zu setzen heisst, die Entscheidung heimlich zu treffen -
|
||
und dabei einen Teil der Moeglichkeiten gar nicht erst zu sehen.
|
||
|
||
Die Pareto-Front ist die ehrlichere Antwort: Sie legt dem Betrieb
|
||
alle sinnvollen Kompromisse vor und ueberlaesst ihm die Wahl. Die
|
||
Spalte 'EUR je kg' macht sie entscheidbar - man vergleicht sie mit
|
||
dem CO2-Preis, den das Unternehmen ohnehin ansetzt.
|
||
================================================================================</code></pre>
|
||
<hr />
|
||
<h2 id="sec:mehrziel-luecke">14.6 Was die gewichtete Summe nicht sieht</h2>
|
||
<p>Die Front hat <strong>zehn</strong> Punkte. Ein Raster aus 1 401 Gewichten findet <strong>sechs</strong> davon. Vier Kompromisse sind für kein Gewicht erreichbar — und das ist keine Frage der Rasterweite.</p>
|
||
<figure>
|
||
<img src="bilder_04/kap_mehrziel_pareto.svg" alt="Abb. 14.1: Pareto-Front: Kosten gegen CO₂. Die gefüllten Punkte liegen auf der unteren konvexen Hülle und sind über Gewichte erreichbar; die vier offenen Kreise sind pareto-optimal, werden aber von keiner Geraden gestützt. Die dünne Gerade ist eine solche Stützgerade, die punktierte die parallele Gerade durch den am weitesten abliegenden der vier Punkte. Erzeugt von bilder_04/erzeuge_pareto_front.py." />
|
||
<figcaption aria-hidden="true">Abb. 14.1: Pareto-Front: Kosten gegen CO₂. Die gefüllten Punkte liegen auf der unteren konvexen Hülle und sind über Gewichte erreichbar; die vier offenen Kreise sind pareto-optimal, werden aber von keiner Geraden gestützt. Die dünne Gerade ist eine solche Stützgerade, die punktierte die parallele Gerade durch den am weitesten abliegenden der vier Punkte. Erzeugt von <code>bilder_04/erzeuge_pareto_front.py</code>.</figcaption>
|
||
</figure>
|
||
<div class="plotly-figur">
|
||
<div> <div id="kap-mehrziel-pareto" class="plotly-graph-div" style="height:430px; width:100%;"></div> <script type="text/javascript"> window.PLOTLYENV=window.PLOTLYENV || {}; if (document.getElementById("kap-mehrziel-pareto")) { Plotly.newPlot( "kap-mehrziel-pareto", [{"hoverinfo":"skip","line":{"color":"#4338ca","dash":"dash","width":1.5},"mode":"lines","name":"untere konvexe Hülle","x":[13543,13724,14036,14189,14592,14821],"y":[6475,6022,5711,5632,5517,5506],"type":"scatter"},{"hovertemplate":["\u003cb\u003e13,543 EUR\u003c\u002fb\u003e\u003cbr\u003e6,475 kg CO₂\u003cbr\u003eAufpreis 0 EUR\u003cbr\u003eErsparnis 0 kg\u003cbr\u003eKostenminimum\u003cextra\u003e\u003c\u002fextra\u003e","\u003cb\u003e13,724 EUR\u003c\u002fb\u003e\u003cbr\u003e6,022 kg CO₂\u003cbr\u003eAufpreis 181 EUR\u003cbr\u003eErsparnis 453 kg\u003cbr\u003e0.40 EUR je kg\u003cextra\u003e\u003c\u002fextra\u003e","\u003cb\u003e14,036 EUR\u003c\u002fb\u003e\u003cbr\u003e5,711 kg CO₂\u003cbr\u003eAufpreis 493 EUR\u003cbr\u003eErsparnis 764 kg\u003cbr\u003e0.65 EUR je kg\u003cextra\u003e\u003c\u002fextra\u003e","\u003cb\u003e14,189 EUR\u003c\u002fb\u003e\u003cbr\u003e5,632 kg CO₂\u003cbr\u003eAufpreis 646 EUR\u003cbr\u003eErsparnis 843 kg\u003cbr\u003e0.77 EUR je kg\u003cextra\u003e\u003c\u002fextra\u003e","\u003cb\u003e14,592 EUR\u003c\u002fb\u003e\u003cbr\u003e5,517 kg CO₂\u003cbr\u003eAufpreis 1,049 EUR\u003cbr\u003eErsparnis 958 kg\u003cbr\u003e1.09 EUR je kg\u003cextra\u003e\u003c\u002fextra\u003e","\u003cb\u003e14,821 EUR\u003c\u002fb\u003e\u003cbr\u003e5,506 kg CO₂\u003cbr\u003eAufpreis 1,278 EUR\u003cbr\u003eErsparnis 969 kg\u003cbr\u003e1.32 EUR je kg\u003cextra\u003e\u003c\u002fextra\u003e"],"marker":{"color":"#4338ca","size":11},"mode":"markers","name":"von Gewichten erreichbar (6)","x":[13543,13724,14036,14189,14592,14821],"y":[6475,6022,5711,5632,5517,5506],"type":"scatter"},{"hovertemplate":["\u003cb\u003e13,635 EUR\u003c\u002fb\u003e\u003cbr\u003e6,317 kg CO₂\u003cbr\u003eAufpreis 92 EUR\u003cbr\u003eErsparnis 158 kg\u003cbr\u003e0.58 EUR je kg\u003cextra\u003e\u003c\u002fextra\u003e","\u003cb\u003e13,718 EUR\u003c\u002fb\u003e\u003cbr\u003e6,286 kg CO₂\u003cbr\u003eAufpreis 175 EUR\u003cbr\u003eErsparnis 189 kg\u003cbr\u003e0.93 EUR je kg\u003cextra\u003e\u003c\u002fextra\u003e","\u003cb\u003e13,868 EUR\u003c\u002fb\u003e\u003cbr\u003e5,927 kg CO₂\u003cbr\u003eAufpreis 325 EUR\u003cbr\u003eErsparnis 548 kg\u003cbr\u003e0.59 EUR je kg\u003cextra\u003e\u003c\u002fextra\u003e","\u003cb\u003e13,978 EUR\u003c\u002fb\u003e\u003cbr\u003e5,912 kg CO₂\u003cbr\u003eAufpreis 435 EUR\u003cbr\u003eErsparnis 563 kg\u003cbr\u003e0.77 EUR je kg\u003cextra\u003e\u003c\u002fextra\u003e"],"marker":{"color":"rgba(0,0,0,0)","line":{"color":"#b45309","width":2.5},"size":13},"mode":"markers","name":"Pareto-optimal, aber unerreichbar (4)","x":[13635,13718,13868,13978],"y":[6317,6286,5927,5912],"type":"scatter"}], {"template":{"data":{"histogram2dcontour":[{"type":"histogram2dcontour","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"choropleth":[{"type":"choropleth","colorbar":{"outlinewidth":0,"ticks":""}}],"histogram2d":[{"type":"histogram2d","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"heatmap":[{"type":"heatmap","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"contourcarpet":[{"type":"contourcarpet","colorbar":{"outlinewidth":0,"ticks":""}}],"contour":[{"type":"contour","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"surface":[{"type":"surface","colorbar":{"outlinewidth":0,"ticks":""},"colorscale":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]]}],"mesh3d":[{"type":"mesh3d","colorbar":{"outlinewidth":0,"ticks":""}}],"scatter":[{"fillpattern":{"fillmode":"overlay","size":10,"solidity":0.2},"type":"scatter"}],"parcoords":[{"type":"parcoords","line":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scatterpolargl":[{"type":"scatterpolargl","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"bar":[{"error_x":{"color":"#2a3f5f"},"error_y":{"color":"#2a3f5f"},"marker":{"line":{"color":"#E5ECF6","width":0.5},"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"bar"}],"scattergeo":[{"type":"scattergeo","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scatterpolar":[{"type":"scatterpolar","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"histogram":[{"marker":{"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"histogram"}],"scattergl":[{"type":"scattergl","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scatter3d":[{"type":"scatter3d","line":{"colorbar":{"outlinewidth":0,"ticks":""}},"marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scattermap":[{"type":"scattermap","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scattermapbox":[{"type":"scattermapbox","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scatterternary":[{"type":"scatterternary","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"scattercarpet":[{"type":"scattercarpet","marker":{"colorbar":{"outlinewidth":0,"ticks":""}}}],"carpet":[{"aaxis":{"endlinecolor":"#2a3f5f","gridcolor":"white","linecolor":"white","minorgridcolor":"white","startlinecolor":"#2a3f5f"},"baxis":{"endlinecolor":"#2a3f5f","gridcolor":"white","linecolor":"white","minorgridcolor":"white","startlinecolor":"#2a3f5f"},"type":"carpet"}],"table":[{"cells":{"fill":{"color":"#EBF0F8"},"line":{"color":"white"}},"header":{"fill":{"color":"#C8D4E3"},"line":{"color":"white"}},"type":"table"}],"barpolar":[{"marker":{"line":{"color":"#E5ECF6","width":0.5},"pattern":{"fillmode":"overlay","size":10,"solidity":0.2}},"type":"barpolar"}],"pie":[{"automargin":true,"type":"pie"}]},"layout":{"autotypenumbers":"strict","colorway":["#636efa","#EF553B","#00cc96","#ab63fa","#FFA15A","#19d3f3","#FF6692","#B6E880","#FF97FF","#FECB52"],"font":{"color":"#2a3f5f"},"hovermode":"closest","hoverlabel":{"align":"left"},"paper_bgcolor":"white","plot_bgcolor":"#E5ECF6","polar":{"bgcolor":"#E5ECF6","angularaxis":{"gridcolor":"white","linecolor":"white","ticks":""},"radialaxis":{"gridcolor":"white","linecolor":"white","ticks":""}},"ternary":{"bgcolor":"#E5ECF6","aaxis":{"gridcolor":"white","linecolor":"white","ticks":""},"baxis":{"gridcolor":"white","linecolor":"white","ticks":""},"caxis":{"gridcolor":"white","linecolor":"white","ticks":""}},"coloraxis":{"colorbar":{"outlinewidth":0,"ticks":""}},"colorscale":{"sequential":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"sequentialminus":[[0.0,"#0d0887"],[0.1111111111111111,"#46039f"],[0.2222222222222222,"#7201a8"],[0.3333333333333333,"#9c179e"],[0.4444444444444444,"#bd3786"],[0.5555555555555556,"#d8576b"],[0.6666666666666666,"#ed7953"],[0.7777777777777778,"#fb9f3a"],[0.8888888888888888,"#fdca26"],[1.0,"#f0f921"]],"diverging":[[0,"#8e0152"],[0.1,"#c51b7d"],[0.2,"#de77ae"],[0.3,"#f1b6da"],[0.4,"#fde0ef"],[0.5,"#f7f7f7"],[0.6,"#e6f5d0"],[0.7,"#b8e186"],[0.8,"#7fbc41"],[0.9,"#4d9221"],[1,"#276419"]]},"xaxis":{"gridcolor":"white","linecolor":"white","ticks":"","title":{"standoff":15},"zerolinecolor":"white","automargin":true,"zerolinewidth":2},"yaxis":{"gridcolor":"white","linecolor":"white","ticks":"","title":{"standoff":15},"zerolinecolor":"white","automargin":true,"zerolinewidth":2},"scene":{"xaxis":{"backgroundcolor":"#E5ECF6","gridcolor":"white","linecolor":"white","showbackground":true,"ticks":"","zerolinecolor":"white","gridwidth":2},"yaxis":{"backgroundcolor":"#E5ECF6","gridcolor":"white","linecolor":"white","showbackground":true,"ticks":"","zerolinecolor":"white","gridwidth":2},"zaxis":{"backgroundcolor":"#E5ECF6","gridcolor":"white","linecolor":"white","showbackground":true,"ticks":"","zerolinecolor":"white","gridwidth":2}},"shapedefaults":{"line":{"color":"#2a3f5f"}},"annotationdefaults":{"arrowcolor":"#2a3f5f","arrowhead":0,"arrowwidth":1},"geo":{"bgcolor":"white","landcolor":"#E5ECF6","subunitcolor":"white","showland":true,"showlakes":true,"lakecolor":"white"},"title":{"x":0.05},"mapbox":{"style":"light"}}},"margin":{"l":70,"r":20,"t":55,"b":50},"legend":{"orientation":"h","y":-0.2},"title":{"text":"Pareto-Front: Kosten gegen CO₂"},"xaxis":{"title":{"text":"Transportkosten (EUR)"}},"yaxis":{"title":{"text":"CO₂-Ausstoß (kg)"}},"height":430,"paper_bgcolor":"rgba(0,0,0,0)","plot_bgcolor":"rgba(0,0,0,0)","hovermode":"closest"}, {"responsive": true} ) }; </script> </div>
|
||
</div>
|
||
<p><strong>Warum es keine Frage des Rasters ist.</strong> „<span class="math inline">c(x) + w\,e(x)</span> minimieren” heißt geometrisch: eine Gerade der Steigung <span class="math inline">-1/w</span> von links unten an die Punktwolke schieben und schauen, welchen Punkt sie zuerst berührt. Eine Gerade berührt immer einen <strong>Eckpunkt der unteren konvexen Hülle</strong>. Punkte, die oberhalb der Hülle liegen, werden von keiner Geraden zuerst getroffen — für kein <span class="math inline">w</span>, bei beliebig feiner Abstufung.</p>
|
||
<p>Das Programm rechnet diese Hülle in <code>untere_huelle()</code> unabhängig aus und vergleicht: Genau die vier Punkte, die das Gewichtsraster verfehlt, liegen strikt oberhalb. Die Gegenprobe steht in der Ausgabe.</p>
|
||
<p><strong>Was Sie in der Abbildung sehen.</strong> Die beiden Geraden haben dieselbe Steigung, also dasselbe Gewicht <span class="math inline">w</span>. Die untere berührt die Hülle in zwei Ecken — eine von beiden meldet der Solver als Optimum. Die obere geht durch einen pareto-optimalen Punkt, der damit für dieses Gewicht chancenlos ist, und zwar nicht knapp: Er liegt eine ganze Stufe darüber. Verschieben Sie die Steigung, verschiebt sich die Berührung von einer Ecke zur nächsten — über den Punkt dazwischen springt sie hinweg. Die waagerechte Linie zeigt den Ausweg, um den es in <a href="#sec:mehrziel-epsilon">Abschnitt 14.7</a> geht: Eine Schranke für den CO₂-Ausstoß statt eines Gewichts findet genau diesen Punkt.</p>
|
||
<blockquote>
|
||
<p><strong>⚠️ Der Grund liegt in der Ganzzahligkeit</strong></p>
|
||
<p>Bei einem reinen LP ist der zulässige Bereich konvex, und die Pareto-Front liegt vollständig auf ihrer eigenen konvexen Hülle — dort findet die gewichtete Summe alles. Sobald Entscheidungen <strong>ganzzahlig</strong> werden (welcher Träger, welches Lager, welche Schicht), zerfällt der Bereich in einzelne Punkte, und zwischen ihnen entstehen Einbuchtungen.</p>
|
||
<p>Deshalb betrifft dieses Problem praktisch jedes betriebliche Mehrzielmodell. Wer mit Gewichten arbeitet, verliert nicht ein paar Nachkommastellen, sondern <strong>ganze Alternativen</strong> — im Beispiel 40 % der Front.</p>
|
||
</blockquote>
|
||
<h3 id="das-gewicht-ist-keine-feineinstellung">Das Gewicht ist keine Feineinstellung</h3>
|
||
<p>Die zweite Beobachtung aus derselben Tabelle: 1 401 Gewichte erzeugen <strong>sechs</strong> verschiedene Pläne. Weite Gewichtsbereiche liefern dasselbe Ergebnis, und dazwischen springt es.</p>
|
||
<p>Das macht die verbreitete Vorgehensweise — „wir probieren ein paar Gewichte und schauen, was herauskommt” — zu einem Glücksspiel. Man weiß nie, ob man einen neuen Kompromiss gefunden hat oder nur denselben noch einmal.</p>
|
||
<hr />
|
||
<h2 id="sec:mehrziel-epsilon">14.7 Das ε-Constraint-Verfahren</h2>
|
||
<p>Der Ausweg ist unspektakulär: <strong>Man macht aus dem zweiten Ziel eine Nebenbedingung.</strong></p>
|
||
<p><span class="math display">
|
||
\min_{x \in X} \; c(x)
|
||
\qquad \text{unter} \qquad
|
||
e(x) \le \varepsilon
|
||
</span></p>
|
||
<p>Für jedes <span class="math inline">\varepsilon</span> liefert das einen Punkt der Front. Die Kunst besteht nur darin, die <span class="math inline">\varepsilon</span> geschickt zu wählen — und dafür gibt es ein Verfahren, das genau so viele Solverläufe braucht, wie die Front Punkte hat:</p>
|
||
<ol type="1">
|
||
<li>Kostenminimum bestimmen. Das ist der eine Rand der Front; nebenbei fällt sein CO₂-Wert an.</li>
|
||
<li><span class="math inline">\varepsilon</span> auf <strong>ein Kilogramm unter diesen Wert</strong> setzen und erneut lösen.</li>
|
||
<li>Schritt 2 wiederholen, bis kein zulässiger Plan mehr existiert.</li>
|
||
</ol>
|
||
<p>Im Beispiel sind das zehn Läufe. Ein Raster über alle möglichen CO₂-Werte bräuchte fast tausend, ein Gewichtsraster findet auch mit 1 401 Läufen nur sechs Punkte.</p>
|
||
<blockquote>
|
||
<p><strong>🎯 Merksatz</strong> ε-Constraint ist das Arbeitspferd der Mehrzieloptimierung: vollständig, mit minimal vielen Solverläufen, und ohne dass jemand ein Gewicht erfinden muss.</p>
|
||
</blockquote>
|
||
<h3 id="wenn-es-eine-klare-rangfolge-gibt-lexikografisch">Wenn es eine klare Rangfolge gibt: lexikografisch</h3>
|
||
<p>Manchmal ist ein Ziel wirklich vorrangig. Dann optimiert man <strong>lexikografisch</strong>: erst das erste Ziel, dann das zweite unter der Bedingung, dass das erste (fast) erhalten bleibt.</p>
|
||
<table>
|
||
<thead>
|
||
<tr class="header">
|
||
<th style="text-align: right;">Kostenbudget</th>
|
||
<th style="text-align: right;">Kosten</th>
|
||
<th style="text-align: right;">CO₂</th>
|
||
<th style="text-align: right;">gegenüber dem Minimum</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr class="odd">
|
||
<td style="text-align: right;">+0 %</td>
|
||
<td style="text-align: right;">13 543 €</td>
|
||
<td style="text-align: right;">6 475 kg</td>
|
||
<td style="text-align: right;">—</td>
|
||
</tr>
|
||
<tr class="even">
|
||
<td style="text-align: right;">+1 %</td>
|
||
<td style="text-align: right;">13 635 €</td>
|
||
<td style="text-align: right;">6 317 kg</td>
|
||
<td style="text-align: right;">158 kg weniger</td>
|
||
</tr>
|
||
<tr class="odd">
|
||
<td style="text-align: right;">+2 %</td>
|
||
<td style="text-align: right;">13 724 €</td>
|
||
<td style="text-align: right;">6 022 kg</td>
|
||
<td style="text-align: right;">453 kg weniger</td>
|
||
</tr>
|
||
<tr class="even">
|
||
<td style="text-align: right;">+5 %</td>
|
||
<td style="text-align: right;">14 189 €</td>
|
||
<td style="text-align: right;">5 632 kg</td>
|
||
<td style="text-align: right;">843 kg weniger</td>
|
||
</tr>
|
||
<tr class="odd">
|
||
<td style="text-align: right;">+10 %</td>
|
||
<td style="text-align: right;">14 821 €</td>
|
||
<td style="text-align: right;">5 506 kg</td>
|
||
<td style="text-align: right;">969 kg weniger</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>Der Sprung von +1 % auf +2 % ist der interessante: Das zweite Prozent bringt fast dreimal so viel wie das erste. Solche Unregelmäßigkeiten sind bei ganzzahligen Modellen die Regel — und ein weiteres Argument gegen Gewichte, die eine gleichmäßige Abwägung suggerieren.</p>
|
||
<p>Beachten Sie außerdem: Die Zeile „+0 %” ist ein Sonderfall, der sich auszahlt. Sie sucht unter allen <strong>kostenminimalen</strong> Plänen den saubersten. Gibt es mehrere optimale Lösungen — und das ist bei ganzzahligen Modellen fast immer so —, bekommt man die CO₂-Ersparnis geschenkt. Ein Solver, der nur ein Ziel kennt, gibt einfach die erstbeste zurück.</p>
|
||
<hr />
|
||
<h2 id="sec:mehrziel-vorlegen">14.8 Wie man die Front vorlegt</h2>
|
||
<p>Eine Front mit zehn Punkten ist kein Ergebnis, sondern eine Speisekarte. Damit sie entscheidbar wird, gehört eine Spalte dazu, die im Programm <code>EUR je kg</code> heißt:</p>
|
||
<p><span class="math display">
|
||
\text{Schattenpreis`\index{Schattenpreis}`{=latex}} = \frac{\text{Aufpreis gegenüber dem Kostenminimum}}
|
||
{\text{eingesparte Kilogramm}}
|
||
</span></p>
|
||
<p>Diese Zahl ist mit etwas vergleichbar, das das Unternehmen ohnehin kennt: dem internen CO₂-Preis oder dem Zertifikatspreis. Liegt der Schattenpreis darunter, ist die Entscheidung kaufmännisch schon getroffen.</p>
|
||
<blockquote>
|
||
<p><strong>💻 Code-Durchgang: die drei Bausteine</strong></p>
|
||
<table>
|
||
<colgroup>
|
||
<col style="width: 50%" />
|
||
<col style="width: 50%" />
|
||
</colgroup>
|
||
<thead>
|
||
<tr class="header">
|
||
<th>Stelle</th>
|
||
<th>Was sie tut</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr class="odd">
|
||
<td><code>plane(ziel, co2_grenze, kosten_grenze)</code></td>
|
||
<td><strong>eine</strong> Funktion für alle Varianten. Welches Ziel und welche Schranke — mehr Unterschied gibt es zwischen den fünf Teilen des Programms nicht</td>
|
||
</tr>
|
||
<tr class="even">
|
||
<td><code>pareto_front()</code></td>
|
||
<td>das ε-Verfahren: Grenze jeweils um 1 kg unter den zuletzt erreichten Wert drücken, bis nichts mehr geht</td>
|
||
</tr>
|
||
<tr class="odd">
|
||
<td><code>untere_huelle()</code></td>
|
||
<td>rechnet die Hülle <strong>unabhängig</strong> aus, damit die Aussage „unerreichbar“ nicht auf dem Gewichtsraster beruht, sondern auf Geometrie</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>Der Vergleich am Ende von Teil 4 ist bewusst ein <code>assert</code>-artiger Abgleich: Wenn Gewichtsraster und Hüllenrechnung verschiedene Punktmengen liefern, stimmt eines von beidem nicht — und das steht dann in der Ausgabe.</p>
|
||
</blockquote>
|
||
<hr />
|
||
<h2 id="sec:mehrziel-uebungsaufgaben">14.9 Übungsaufgaben</h2>
|
||
<blockquote>
|
||
<p>Lösungen: <a href="anhang-loesungen.html#sec:loesungen-mehrziel">Abschnitt A.14</a>.</p>
|
||
</blockquote>
|
||
<p><strong>Aufgabe 14.1 ⭐ — Dominanz prüfen.</strong> Plan P kostet 14 000 € und stößt 6 000 kg aus, Plan Q kostet 13 800 € und stößt 6 100 kg aus. Dominiert einer den anderen? Und wie steht es mit R (14 000 €, 6 100 kg)?</p>
|
||
<p><strong>Aufgabe 14.2 ⭐ — Der Schattenpreis in der Praxis.</strong> Der interne CO₂-Preis des Unternehmens beträgt 0,90 € je Kilogramm. Welchen Punkt der Front würden Sie empfehlen — und wie begründen Sie ihn in einem Satz?</p>
|
||
<p><strong>Aufgabe 14.3 ⭐⭐ — Mehr Trassen.</strong> Erhöhen Sie <code>BAHN_TRASSEN</code> von 5 auf 8. Was passiert mit der Länge der Front und mit der Zahl der unerreichbaren Punkte? Erklären Sie den Zusammenhang.</p>
|
||
<p><strong>Aufgabe 14.4 ⭐⭐ — Die Front der Relaxation.</strong> Lassen Sie <code>integrality</code> weg, sodass Anteile erlaubt sind. Berechnen Sie die Front erneut (mit einem ε-Raster, da es nun unendlich viele Punkte gibt). Wie viele Punkte liegen jetzt oberhalb der konvexen Hülle — und warum?</p>
|
||
<p><strong>Aufgabe 14.5 ⭐⭐⭐ — Drei Ziele.</strong> Ergänzen Sie die Laufzeit als drittes Ziel (LKW schnell, Bahn langsam). Die Front wird zu einer Fläche. Wie ändert sich das ε-Verfahren, und warum wächst der Aufwand so schnell?</p>
|
||
<hr />
|
||
<h2 id="sec:mehrziel-denkfehler">14.10 Finde den Denkfehler</h2>
|
||
<div class="card card-denkfehler">
|
||
<blockquote>
|
||
<p><strong>🐛 „Wir haben die Gewichte sauber kalibriert”</strong></p>
|
||
<p>Ein Team baut ein Mehrzielmodell für die Tourenplanung: Kosten gegen CO₂. Um das Gewicht nicht willkürlich zu setzen, geht es methodisch vor:</p>
|
||
<blockquote>
|
||
<p><em>„Wir haben <span class="math inline">w</span> in 500 Schritten von 0 bis 5 durchgerechnet und für jeden Wert den > optimalen Plan bestimmt. Dann haben wir der Geschäftsführung alle so gefundenen Pläne > vorgelegt und sie hat einen ausgewählt. Damit ist die Entscheidung nicht von uns > getroffen worden, sondern vom Fachbereich — und wir haben den Lösungsraum vollständig > abgetastet.”</em></p>
|
||
</blockquote>
|
||
<p>Das Vorgehen ist sorgfältig, die Rechnung stimmt, und die Beteiligung des Fachbereichs ist vorbildlich.</p>
|
||
<p><strong>Trotzdem stimmt die letzte Behauptung nicht. Warum — und was hätte das Team stattdessen tun müssen?</strong></p>
|
||
<p>Und ein zweiter Teil, der schwerer wiegt: Angenommen, unter den nicht gefundenen Plänen wäre einer gewesen, der die Geschäftsführung überzeugt hätte. <strong>Hätte irgendjemand das bemerkt?</strong></p>
|
||
</blockquote>
|
||
</div>
|
||
<hr />
|
||
<h2 id="sec:mehrziel-quiz">14.11 Micro-Quiz</h2>
|
||
<div class="card card-quiz">
|
||
<blockquote>
|
||
<p><strong>❓ Drei Fragen</strong></p>
|
||
<p><strong>1. Warum findet die gewichtete Summe nicht alle Pareto-Punkte?</strong> a) Weil das Gewichtsraster zwangsläufig zu grob ist. b) Weil sie nur Punkte auf der unteren konvexen Hülle erreichen kann — Punkte darüber werden von keiner Geraden gestützt. c) Weil Solver bei gemischten Zielfunktionen numerisch ungenau werden.</p>
|
||
<p><strong>2. Wie viele Solverläufe braucht das ε-Constraint-Verfahren in der gezeigten Form?</strong> a) So viele, wie das ε-Raster Schritte hat. b) So viele, wie die Pareto-Front Punkte hat, plus einen. c) Genau zwei — einen je Ziel.</p>
|
||
<p><strong>3. Die Zeile „+0 % Kostenbudget” in der lexikografischen Tabelle liefert weniger CO₂ als das reine Kostenminimum. Wie kann das sein?</strong> a) Ein Rundungsfehler im Solver. b) Es gibt mehrere kostenminimale Pläne; unter ihnen wird der sauberste gewählt. c) Das Kostenbudget ist durch die Prozentrechnung minimal größer.</p>
|
||
</blockquote>
|
||
</div>
|
||
<hr />
|
||
<h2 id="sec:mehrziel-selbsttest">14.12 Selbsttest</h2>
|
||
<ol type="1">
|
||
<li>Erklären Sie Pareto-Dominanz an einem Beispiel aus Ihrem Arbeitsumfeld.</li>
|
||
<li>Warum ist „gewichtete Summe” bei einem reinen LP unproblematisch und bei einem MILP nicht?</li>
|
||
<li>Ein Kollege sagt: „Ich nehme <span class="math inline">w = 0{,}5</span>, das ist neutral.” Was ist daran falsch?</li>
|
||
<li>Beschreiben Sie das ε-Constraint-Verfahren in drei Sätzen, ohne Formeln.</li>
|
||
<li>Sie legen einer Geschäftsführung eine Front mit zwölf Punkten vor. Welche Spalte brauchen Sie, damit die Entscheidung fallen kann?</li>
|
||
</ol>
|
||
<hr />
|
||
<h2 id="sec:mehrziel-zusammenfassung">14.13 Zusammenfassung</h2>
|
||
<ul>
|
||
<li>Bei mehreren Zielen ist „besser” nur noch über <strong>Dominanz</strong> definiert. Das vollständige Ergebnis ist keine Lösung, sondern die <strong>Pareto-Front</strong>.</li>
|
||
<li>Die <strong>gewichtete Summe</strong> findet nur Punkte auf der unteren konvexen Hülle. Bei ganzzahligen Modellen liegen regelmäßig Pareto-Punkte darüber — im Beispiel 4 von 10, also 40 % der Alternativen. Das ist kein Rasterproblem, sondern Geometrie.</li>
|
||
<li>Das Gewicht ist außerdem <strong>keine Feineinstellung</strong>: 1 401 Gewichte erzeugten sechs verschiedene Pläne, mit Sprüngen dazwischen.</li>
|
||
<li>Das <strong>ε-Constraint-Verfahren</strong> macht aus dem zweiten Ziel eine Schranke und liefert die vollständige Front mit so vielen Solverläufen, wie sie Punkte hat.</li>
|
||
<li><strong>Lexikografisch</strong> optimiert man, wenn es eine echte Rangfolge gibt — „höchstens 2 % teurer, dafür so sauber wie möglich” ist eine Frage, die ein Kaufmann beantworten kann.</li>
|
||
<li>Die Front wird erst entscheidbar durch die Spalte <strong>€ je kg</strong>: Sie ist mit dem internen CO₂-Preis vergleichbar und verwandelt eine Wertefrage in eine Rechnung.</li>
|
||
</ul>
|
||
|
||
</article>
|
||
<button type="button" class="fortschritt-knopf" data-kapitel="mehrziel.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="dynamische-programmierung.html"><svg class="icon" aria-hidden="true"><use href="#icon-chevron-left"></use></svg><span><small>Zurück</small>Kapitel 13: Dynamische Programmierung — Die Bellman-Gleichung{idx:Bellman-Gleichung} und Order-Execution</span></a><a class="prev-next-knopf prev-next-next" href="prognose.html"><span><small>Weiter</small>Kapitel 15: Predict-then-Optimize{idx:Predict-then-Optimize} — die bessere Prognose, die schlechtere Entscheidung</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/plotly.min.js"></script>
|
||
<script defer src="assets/search-index.js"></script>
|
||
<script defer src="assets/programme.js"></script>
|
||
<script defer src="assets/site.js"></script>
|
||
</body>
|
||
</html>
|