<aclass="brand"href="index.html"><svgclass="icon"aria-hidden="true"><usehref="#icon-book"></use></svg><span>Optimierte Entscheidungsfindung mit Python</span></a>
<navclass="sidebar"id="sidebar"aria-label="Kapitelnavigation"><divclass="sidebar-inhalt"><detailsclass="sidebar-gruppe"><summary>Einstieg</summary><ul><lidata-kapitel="vorwort.html"><ahref="vorwort.html"><spanclass="fortschritt-haken"><svgclass="icon"aria-hidden="true"><usehref="#icon-check"></use></svg></span><span>Vorwort & Lesehilfe</span></a></li><lidata-kapitel="notation.html"><ahref="notation.html"><spanclass="fortschritt-haken"><svgclass="icon"aria-hidden="true"><usehref="#icon-check"></use></svg></span><span>Notation & Abkürzungen</span></a></li></ul></details><detailsclass="sidebar-gruppe"><summary>Teil I: Grundlagen des Operations Research</summary><ul><lidata-kapitel="einfuehrung.html"><ahref="einfuehrung.html"><spanclass="fortschritt-haken"><svgclass="icon"aria-hidden="true"><usehref="#icon-check"></use></svg></span><span>Kapitel 1: Einführung in Operations Research — Vom Ursprung zur mathematischen Entscheidungsfindung</span></a></li><lidata-kapitel="fundament.html"><ahref="fundament.html"><spanclass="fortschritt-haken"><svgclass="icon"aria-hidden="true"><usehref="#icon-check"></use></svg></span><span>Kapitel 2: Das mathematische Fundament — Vektoren, Matrizen, Konvexität</span></a></li><lidata-kapitel="oekosystem.html"><ahref="oekosystem.html"><spanclass="fortschritt-haken"><svgclass="icon"aria-hidden="true"><usehref="#icon-check"></use></svg></span><span>Kapitel 3: Das Python-Ökosystem für OR — Solver, Bindings und Modellierungsschichten</span></a></li><lidata-kapitel="modellierung.html"><ahref="modellierung.html"><spanclass="fortschritt-haken"><svgclass="icon"aria-hidden="true"><usehref="#icon-check"></use></svg></span><span>Kapitel 4: Vom Management-Wunsch zum Modell</span></a></li></ul></details><detailsclass="sidebar-gruppe"><summary>Teil II: Die Kernverfahren der deterministischen Optimierung</summary><ul><lidata-kapitel="lp.html"><ahref="lp.html"><spanclass="fortschritt-haken"><svgclass="icon"aria-hidden="true"><usehref="#icon-check"></use></svg></span><span>Kapitel 5: Lineare Programmierung — Simplex, Dualität und Schattenpreise</span></a></li><lidata-kapitel="milp.html"><ahref="milp.html"><spanclass="fortschritt-haken"><svgclass="icon"aria-hidden="true"><usehref="#icon-check"></use></svg></span><span>Kapitel 6: Gemischt-ganzzahlige Optimierung — Diskrete Entscheidungen und Branch-and-Bound</span></a></li><lidata-kapitel="cpsat.html"><ahref="cpsat.html"><spanclass="fortschritt-haken"><svgclass="icon"aria-hidden="true"><usehref="#icon-check"></use></svg></span><span>Kapitel 7: Constraint Programming mit CP-SAT — Logik, Scheduling und Zuweisung</span></a></li><lidata-kapitel="graphen.html"><ahref="graphen.html"><spanclass="fortschritt-haken"><svgclass="icon"aria-hidden="true"><usehref="#icon-check"></use></svg></span><span>Kapitel 8: Graphen, Flüsse und Touren — Min-Cost-Flow, Matching und VRP</span></a></li><lidata-kapitel="metaheuristiken.html"><ahref="metaheuristiken.html"><spanclass="fortschritt-haken"><svgclass="icon"aria-hidden="true"><usehref="#icon-check"></use></svg></span><span>Kapitel 9: Metaheuristiken — wenn der exakte Solver aussteigt</span></a></li><lidata-kapitel="dekomposition.html"><ahref="dekomposition.html"><spanclass="fortschritt-haken"><svgclass="icon"aria-hidden="true"><usehref="#icon-check"></use></svg></span><span>Kapitel 10: Spaltengenerierung — das Modell umbauen statt die Lösung raten</span></a></li></ul></details><detailsclass="sidebar-gruppe"open><summary>Teil III: Nichtlinearität, Unsicherheit und mehrperiodige Dynamik</summary><ul><lidata-kapitel="qp-nlp.html"><ahref="qp-nlp.html"><spanclass="fortschritt-haken"><svgclass="icon"aria-hidden="true"><usehref="#icon-check"></use></svg></span><span>Kapitel 11: Quadratische und nichtlineare Optimierung — KKT, Lagrange, Konvexität</span></a></li><lidata-kapitel="unsicherheit.html"><ahref="unsicherheit.html"><spanclass="fortschritt-haken"><svgclass="icon"aria-hidden="true"><usehref="#icon-check"></use></s
<mainclass="content">
<navclass="breadcrumb"aria-label="Breadcrumb"><ahref="index.html">Start</a>›<span>Teil III</span>›<span>Kapitel 14: Mehrere Ziele — Pareto-Fronten statt Gewichte</span></nav>
<navclass="prev-next"><aclass="prev-next-knopf prev-next-prev"href="dynamische-programmierung.html"><svgclass="icon"aria-hidden="true"><usehref="#icon-chevron-left"></use></svg><span><small>Zurück</small>Kapitel 13: Dynamische Programmierung — Die Bellman-Gleichung und Order-Execution</span></a><aclass="prev-next-knopf prev-next-next"href="prognose.html"><span><small>Weiter</small>Kapitel 15: Predict-then-Optimize — die bessere Prognose, die schlechtere Entscheidung</span><svgclass="icon"aria-hidden="true"><usehref="#icon-chevron-right"></use></svg></a></nav>
<article>
<h1id="kap-mehrziel">Kapitel 14: Mehrere Ziele — Pareto-Fronten statt Gewichte</h1>
<divclass="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><ahref="modellierung.html#kap-modellierung">Kapitel 4</a> (die Zielgröße als Entscheidung) und <ahref="milp.html#kap-milp">Kapitel 6</a>. Für den Denkfehler hilft <ahref="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>
<ahref="https://colab.research.google.com/github/dschlueter/or-mit-python/blob/main/Notebooks_04/mehrziel.ipynb">In Google Colab öffnen</a></p>
</blockquote>
</div>
<hr/>
<h2id="sec:mehrziel-schnellstart">14.1 In 5 Minuten gelöst</h2>
<divclass="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>
<spanid="cb1-13"><ahref="#cb1-13"aria-hidden="true"tabindex="-1"></a> A, b <spanclass="op">=</span><spanclass="bu">list</span>(bahn_trassen), [<spanclass="fl">2.0</span>] <spanclass="co"># nur zwei Trassen frei</span></span>
<spanid="cb1-22"><ahref="#cb1-22"aria-hidden="true"tabindex="-1"></a><spanclass="bu">print</span>(<spanclass="ss">f"guenstigster Plan: </span><spanclass="sc">{</span>k0<spanclass="sc">:>7,.0f}</span><spanclass="ss"> EUR </span><spanclass="sc">{</span>c0<spanclass="sc">:>6,.0f}</span><spanclass="ss"> kg CO2"</span>)</span>
<spanid="cb1-23"><ahref="#cb1-23"aria-hidden="true"tabindex="-1"></a><spanclass="bu">print</span>(<spanclass="ss">f"mit 2 % Aufpreis: </span><spanclass="sc">{</span>k1<spanclass="sc">:>7,.0f}</span><spanclass="ss"> EUR </span><spanclass="sc">{</span>c1<spanclass="sc">:>6,.0f}</span><spanclass="ss"> kg CO2 "</span></span>
<spanid="cb1-24"><ahref="#cb1-24"aria-hidden="true"tabindex="-1"></a><spanclass="ss">f"(</span><spanclass="sc">{</span>(c0<spanclass="op">-</span>c1)<spanclass="op">/</span>c0<spanclass="sc">:.0%}</span><spanclass="ss"> weniger, </span><spanclass="sc">{</span>(k1<spanclass="op">-</span>k0)<spanclass="op">/</span>(c0<spanclass="op">-</span>c1)<spanclass="sc">:.2f}</span><spanclass="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>
<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/>
<h2id="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><spanclass="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>
<divclass="card card-formel">
<blockquote>
<p><strong>🔤 Formel-Übersetzer</strong></p>
<table>
<colgroup>
<colstyle="width: 50%"/>
<colstyle="width: 50%"/>
</colgroup>
<thead>
<trclass="header">
<th>Mathematik</th>
<th>Alltagssprache</th>
</tr>
</thead>
<tbody>
<trclass="odd">
<td><spanclass="math inline">f_i(x) \le f_i(y)</span> für alle <spanclass="math inline">i</span></td>
<td>„Plan <spanclass="math inline">x</span> ist in <strong>keinem</strong> Ziel schlechter als <spanclass="math inline">y</span>.“</td>
</tr>
<trclass="even">
<td><spanclass="math inline">f_j(x) < f_j(y)</span> für ein <spanclass="math inline">j</span></td>
<td>„<spanclass="math inline">y</span> kann man wegwerfen. Es gibt keinen Grund, ihn zu wählen.“</td>
</tr>
<trclass="even">
<td><spanclass="math inline">x</span> ist <strong>pareto-optimal</strong></td>
<td>„Niemand dominiert <spanclass="math inline">x</span>. Wer <spanclass="math inline">x</span> verbessern will, muss anderswo schlechter werden.“</td>
</tr>
<trclass="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>
<td>„So viele Euro ist mir ein Kilogramm CO₂ wert.“ Ein <strong>Wechselkurs</strong>, kein Wichtigkeitsregler (<ahref="cpsat.html#sec:cpsat-denkfehler">Abschnitt 7.10</a>).</td>
<p>Der Ausdruck hat eine Einheit: Euro. Damit ist <spanclass="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/>
<h2id="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>
<spanid="cb3-5"><ahref="#cb3-5"aria-hidden="true"tabindex="-1"></a><spanclass="co">Kapitel Mehrziel: Kosten gegen CO2 - und warum Gewichte nicht genuegen.</span></span>
<spanid="cb3-7"><ahref="#cb3-7"aria-hidden="true"tabindex="-1"></a><spanclass="co">Eine Spedition vergibt zwoelf Sendungen an drei Verkehrstraeger: LKW (schnell,</span></span>
<spanid="cb3-8"><ahref="#cb3-8"aria-hidden="true"tabindex="-1"></a><spanclass="co">teuer, schmutzig), Bahn (billig und sauber, aber nur fuenf Trassen frei) und</span></span>
<spanid="cb3-9"><ahref="#cb3-9"aria-hidden="true"tabindex="-1"></a><spanclass="co">Kombinierten Verkehr (dazwischen). Zwei Ziele stehen gegeneinander:</span></span>
<spanid="cb3-10"><ahref="#cb3-10"aria-hidden="true"tabindex="-1"></a><spanclass="co">Transportkosten und CO2-Ausstoss.</span></span>
<spanid="cb3-12"><ahref="#cb3-12"aria-hidden="true"tabindex="-1"></a><spanclass="co">Der uebliche Reflex ist, beide Ziele zu einem zusammenzuruehren:</span></span>
<spanid="cb3-16"><ahref="#cb3-16"aria-hidden="true"tabindex="-1"></a><spanclass="co">Das ist bequem, liefert zulaessige Loesungen - und ist unvollstaendig. Bei</span></span>
<spanid="cb3-17"><ahref="#cb3-17"aria-hidden="true"tabindex="-1"></a><spanclass="co">ganzzahligen Entscheidungen gibt es Kompromisse, die auf diesem Weg</span></span>
<spanid="cb3-18"><ahref="#cb3-18"aria-hidden="true"tabindex="-1"></a><spanclass="co">GRUNDSAETZLICH nicht erreichbar sind, egal welches w man waehlt. Nicht "schwer</span></span>
<spanid="cb3-19"><ahref="#cb3-19"aria-hidden="true"tabindex="-1"></a><spanclass="co">zu finden", sondern beweisbar unerreichbar.</span></span>
<spanid="cb3-23"><ahref="#cb3-23"aria-hidden="true"tabindex="-1"></a><spanclass="co"> 1. Die beiden Extreme - was jedes Ziel allein kostet.</span></span>
<spanid="cb3-24"><ahref="#cb3-24"aria-hidden="true"tabindex="-1"></a><spanclass="co"> 2. Die lineare Skalarisierung ueber ein feines Gewichtsraster.</span></span>
<spanid="cb3-25"><ahref="#cb3-25"aria-hidden="true"tabindex="-1"></a><spanclass="co"> 3. Die vollstaendige Pareto-Front ueber das eps-Constraint-Verfahren.</span></span>
<spanid="cb3-26"><ahref="#cb3-26"aria-hidden="true"tabindex="-1"></a><spanclass="co"> 4. Den Nachweis, dass die Luecke keine Frage des Rasters ist, sondern</span></span>
<spanid="cb3-27"><ahref="#cb3-27"aria-hidden="true"tabindex="-1"></a><spanclass="co"> Geometrie: Die fehlenden Punkte liegen strikt oberhalb der konvexen</span></span>
<spanid="cb3-28"><ahref="#cb3-28"aria-hidden="true"tabindex="-1"></a><spanclass="co"> Huelle und koennen deshalb von keiner Geraden gestuetzt werden.</span></span>
<spanid="cb3-39"><ahref="#cb3-39"aria-hidden="true"tabindex="-1"></a>BAHN_TRASSEN <spanclass="op">=</span><spanclass="dv">5</span><spanclass="co"># so viele Sendungen passen hoechstens auf die Bahn</span></span>
<spanid="cb3-44"><ahref="#cb3-44"aria-hidden="true"tabindex="-1"></a><spanclass="co">"""Kosten und CO2 je Sendung und Verkehrstraeger.</span></span>
<spanid="cb3-46"><ahref="#cb3-46"aria-hidden="true"tabindex="-1"></a><spanclass="co"> Die Bahn ist immer billiger und sauberer als der LKW - der Zielkonflikt</span></span>
<spanid="cb3-47"><ahref="#cb3-47"aria-hidden="true"tabindex="-1"></a><spanclass="co"> entsteht nicht zwischen den Traegern, sondern durch die KNAPPHEIT der</span></span>
<spanid="cb3-48"><ahref="#cb3-48"aria-hidden="true"tabindex="-1"></a><spanclass="co"> Trassen. Genau so sieht es in der Praxis aus.</span></span>
<spanid="cb3-52"><ahref="#cb3-52"aria-hidden="true"tabindex="-1"></a> co2 <spanclass="op">=</span> np.zeros((anzahl, <spanclass="dv">3</span>))</span>
<spanid="cb3-53"><ahref="#cb3-53"aria-hidden="true"tabindex="-1"></a><spanclass="cf">for</span> i <spanclass="kw">in</span><spanclass="bu">range</span>(anzahl):</span>
<spanid="cb3-71"><ahref="#cb3-71"aria-hidden="true"tabindex="-1"></a><spanclass="co">"""Jede Sendung genau einem Traeger zuordnen; Trassen sind knapp.</span></span>
<spanid="cb3-73"><ahref="#cb3-73"aria-hidden="true"tabindex="-1"></a><spanclass="co">'ziel' ist die zu minimierende Matrix (Kosten, CO2 oder eine Mischung).</span></span>
<spanid="cb3-74"><ahref="#cb3-74"aria-hidden="true"tabindex="-1"></a><spanclass="co"> Die beiden Grenzen sind das Werkzeug fuer eps-Constraint und</span></span>
<spanid="cb3-75"><ahref="#cb3-75"aria-hidden="true"tabindex="-1"></a><spanclass="co"> lexikografische Optimierung - sie machen aus einem Ziel eine Schranke.</span></span>
<spanid="cb3-77"><ahref="#cb3-77"aria-hidden="true"tabindex="-1"></a> gleichungen <spanclass="op">=</span> np.zeros((N, N <spanclass="op">*</span><spanclass="dv">3</span>))</span>
<spanid="cb3-78"><ahref="#cb3-78"aria-hidden="true"tabindex="-1"></a><spanclass="cf">for</span> i <spanclass="kw">in</span><spanclass="bu">range</span>(N):</span>
<spanid="cb3-79"><ahref="#cb3-79"aria-hidden="true"tabindex="-1"></a> gleichungen[i, i <spanclass="op">*</span><spanclass="dv">3</span>:(i <spanclass="op">+</span><spanclass="dv">1</span>) <spanclass="op">*</span><spanclass="dv">3</span>] <spanclass="op">=</span><spanclass="fl">1.0</span><spanclass="co"># genau ein Traeger</span></span>
<spanid="cb3-96"><ahref="#cb3-96"aria-hidden="true"tabindex="-1"></a> plan <spanclass="op">=</span> np.<spanclass="bu">round</span>(ergebnis.x).astype(<spanclass="bu">int</span>)</span>
<spanid="cb3-101"><ahref="#cb3-101"aria-hidden="true"tabindex="-1"></a><spanclass="co">"""Vollstaendige Front ueber das eps-Constraint-Verfahren.</span></span>
<spanid="cb3-103"><ahref="#cb3-103"aria-hidden="true"tabindex="-1"></a><spanclass="co"> Der Ablauf ist der eigentliche Inhalt dieser Funktion: Erst das</span></span>
<spanid="cb3-104"><ahref="#cb3-104"aria-hidden="true"tabindex="-1"></a><spanclass="co"> Kostenminimum bestimmen (der eine Rand der Front), dann die CO2-Schranke</span></span>
<spanid="cb3-105"><ahref="#cb3-105"aria-hidden="true"tabindex="-1"></a><spanclass="co"> schrittweise um genau ein Kilogramm unter den zuletzt erreichten Wert</span></span>
<spanid="cb3-106"><ahref="#cb3-106"aria-hidden="true"tabindex="-1"></a><spanclass="co"> druecken. Jeder Lauf liefert den naechsten Punkt - und wenn keiner mehr</span></span>
<spanid="cb3-107"><ahref="#cb3-107"aria-hidden="true"tabindex="-1"></a><spanclass="co"> zulaessig ist, ist die Front vollstaendig.</span></span>
<spanid="cb3-109"><ahref="#cb3-109"aria-hidden="true"tabindex="-1"></a><spanclass="co"> Das braucht so viele Solveraufrufe, wie die Front Punkte hat. Ein Raster</span></span>
<spanid="cb3-110"><ahref="#cb3-110"aria-hidden="true"tabindex="-1"></a><spanclass="co"> ueber alle moeglichen CO2-Werte braeuchte hier fast tausend.</span></span>
<spanid="cb3-120"><ahref="#cb3-120"aria-hidden="true"tabindex="-1"></a> grenze <spanclass="op">=</span> ergebnis[<spanclass="dv">1</span>] <spanclass="op">-</span><spanclass="dv">1</span></span>
<spanid="cb3-125"><ahref="#cb3-125"aria-hidden="true"tabindex="-1"></a><spanclass="co">"""Was 'Kosten + w * CO2' fuer viele w hergibt - als Menge von Punkten."""</span></span>
<spanid="cb3-135"><ahref="#cb3-135"aria-hidden="true"tabindex="-1"></a><spanclass="co">"""Untere linke konvexe Huelle - genau die Punkte, die eine Gerade stuetzt.</span></span>
<spanid="cb3-137"><ahref="#cb3-137"aria-hidden="true"tabindex="-1"></a><spanclass="co"> Der Zusammenhang, um den es geht: 'Kosten + w*CO2 minimieren' heisst</span></span>
<spanid="cb3-138"><ahref="#cb3-138"aria-hidden="true"tabindex="-1"></a><spanclass="co"> geometrisch, eine Gerade der Steigung -1/w von links unten an die</span></span>
<spanid="cb3-139"><ahref="#cb3-139"aria-hidden="true"tabindex="-1"></a><spanclass="co"> Punktwolke zu schieben. Sie beruehrt immer einen Eckpunkt der konvexen</span></span>
<spanid="cb3-140"><ahref="#cb3-140"aria-hidden="true"tabindex="-1"></a><spanclass="co"> Huelle. Punkte, die oberhalb liegen, werden nie beruehrt - fuer kein w.</span></span>
<spanid="cb3-143"><ahref="#cb3-143"aria-hidden="true"tabindex="-1"></a><spanclass="cf">for</span> punkt <spanclass="kw">in</span><spanclass="bu">sorted</span>(punkte):</span>
<spanid="cb3-156"><ahref="#cb3-156"aria-hidden="true"tabindex="-1"></a><spanclass="bu">print</span>(<spanclass="st">" KOSTEN GEGEN CO2 - UND WARUM GEWICHTE NICHT GENUEGEN"</span>)</span>
<spanid="cb3-161"><ahref="#cb3-161"aria-hidden="true"tabindex="-1"></a><spanclass="co"># --- 1. Die beiden Extreme -------------------------------------------</span></span>
<spanid="cb3-164"><ahref="#cb3-164"aria-hidden="true"tabindex="-1"></a><spanclass="bu">print</span>(<spanclass="st">"1. Was jedes Ziel allein ergibt</span><spanclass="ch">\n</span><spanclass="st">"</span>)</span>
<spanid="cb3-168"><ahref="#cb3-168"aria-hidden="true"tabindex="-1"></a><spanclass="bu">print</span>(<spanclass="ss">f"</span><spanclass="sc">{</span><spanclass="st">'nur CO2 minimal'</span><spanclass="sc">:<22}</span><spanclass="ss"></span><spanclass="sc">{</span>saubersten[<spanclass="dv">0</span>]<spanclass="sc">:>10,}</span><spanclass="ss"></span><spanclass="sc">{</span>saubersten[<spanclass="dv">1</span>]<spanclass="sc">:>9,}</span><spanclass="ss"> kg"</span>)</span>
<spanid="cb3-169"><ahref="#cb3-169"aria-hidden="true"tabindex="-1"></a><spanclass="bu">print</span>(<spanclass="ss">f"</span><spanclass="ch">\n</span><spanclass="ss"> Der Zielkonflikt ist echt, aber klein: "</span></span>
<spanid="cb3-172"><ahref="#cb3-172"aria-hidden="true"tabindex="-1"></a><spanclass="ss">f"</span><spanclass="sc">{</span>guenstigst[<spanclass="dv">1</span>] <spanclass="op">-</span> saubersten[<spanclass="dv">1</span>]<spanclass="sc">:,}</span><spanclass="ss"> kg CO2 "</span></span>
<spanid="cb3-174"><ahref="#cb3-174"aria-hidden="true"tabindex="-1"></a><spanclass="bu">print</span>(<spanclass="st">" Genau solche Zahlen will die Geschaeftsfuehrung sehen - nicht ein"</span>)</span>
<spanid="cb3-175"><ahref="#cb3-175"aria-hidden="true"tabindex="-1"></a><spanclass="bu">print</span>(<spanclass="st">" Gewicht, das niemand interpretieren kann."</span>)</span>
<spanid="cb3-184"><ahref="#cb3-184"aria-hidden="true"tabindex="-1"></a><spanclass="bu">print</span>(<spanclass="ss">f"</span><spanclass="sc">{</span><spanclass="st">'Kosten'</span><spanclass="sc">:>10}</span><spanclass="ss"></span><spanclass="sc">{</span><spanclass="st">'CO2'</span><spanclass="sc">:>10}</span><spanclass="ss"></span><spanclass="sc">{</span><spanclass="st">'gefunden bei w'</span><spanclass="sc">:>16}</span><spanclass="ss">"</span>)</span>
<spanid="cb3-187"><ahref="#cb3-187"aria-hidden="true"tabindex="-1"></a><spanclass="bu">print</span>(<spanclass="ss">f"</span><spanclass="sc">{</span>k<spanclass="sc">:>10,}</span><spanclass="ss"></span><spanclass="sc">{</span>c<spanclass="sc">:>9,}</span><spanclass="ss"> kg </span><spanclass="sc">{</span><spanclass="bu">min</span>(ws)<spanclass="sc">:>7.3f}</span><spanclass="ss"> bis </span><spanclass="sc">{</span><spanclass="bu">max</span>(ws)<spanclass="sc">:>7.3f}</span><spanclass="ss">"</span>)</span>
<spanid="cb3-188"><ahref="#cb3-188"aria-hidden="true"tabindex="-1"></a><spanclass="bu">print</span>(<spanclass="ss">f"</span><spanclass="ch">\n</span><spanclass="ss"></span><spanclass="sc">{</span><spanclass="bu">len</span>(gefunden)<spanclass="sc">}</span><spanclass="ss"> verschiedene Plaene - fuer </span><spanclass="sc">{</span><spanclass="bu">len</span>(gewichte)<spanclass="sc">:,}</span><spanclass="ss"> Gewichte."</span>)</span>
<spanid="cb3-189"><ahref="#cb3-189"aria-hidden="true"tabindex="-1"></a><spanclass="bu">print</span>(<spanclass="st">" Das Gewicht ist also gar keine Feineinstellung: Weite Bereiche"</span>)</span>
<spanid="cb3-190"><ahref="#cb3-190"aria-hidden="true"tabindex="-1"></a><spanclass="bu">print</span>(<spanclass="st">" liefern dasselbe Ergebnis, und dazwischen springt es."</span>)</span>
<spanid="cb3-192"><ahref="#cb3-192"aria-hidden="true"tabindex="-1"></a><spanclass="co"># --- 3. Die vollstaendige Front --------------------------------------</span></span>
<spanid="cb3-193"><ahref="#cb3-193"aria-hidden="true"tabindex="-1"></a> front <spanclass="op">=</span> pareto_front()</span>
<spanid="cb3-198"><ahref="#cb3-198"aria-hidden="true"tabindex="-1"></a><spanclass="ss">f"</span><spanclass="sc">{</span><spanclass="st">'EUR je kg'</span><spanclass="sc">:>10}</span><spanclass="ss">"</span>)</span>
<spanid="cb3-200"><ahref="#cb3-200"aria-hidden="true"tabindex="-1"></a><spanclass="cf">for</span> k, c <spanclass="kw">in</span> front:</span>
<spanid="cb3-201"><ahref="#cb3-201"aria-hidden="true"tabindex="-1"></a> auf <spanclass="op">=</span> k <spanclass="op">-</span> guenstigst[<spanclass="dv">0</span>]</span>
<spanid="cb3-203"><ahref="#cb3-203"aria-hidden="true"tabindex="-1"></a> preis <spanclass="op">=</span> auf <spanclass="op">/</span> ersparnis <spanclass="cf">if</span> ersparnis <spanclass="cf">else</span><spanclass="fl">0.0</span></span>
<spanid="cb3-204"><ahref="#cb3-204"aria-hidden="true"tabindex="-1"></a><spanclass="bu">print</span>(<spanclass="ss">f"</span><spanclass="sc">{</span>k<spanclass="sc">:>10,}</span><spanclass="ss"></span><spanclass="sc">{</span>c<spanclass="sc">:>9,}</span><spanclass="ss"> kg </span><spanclass="sc">{</span>auf<spanclass="sc">:>8,}</span><spanclass="ss"></span><spanclass="sc">{</span>ersparnis<spanclass="sc">:>13,}</span><spanclass="ss">"</span></span>
<spanid="cb3-209"><ahref="#cb3-209"aria-hidden="true"tabindex="-1"></a> unerreichbar <spanclass="op">=</span> [p <spanclass="cf">for</span> p <spanclass="kw">in</span> front <spanclass="cf">if</span> p <spanclass="kw">not</span><spanclass="kw">in</span> huelle]</span>
<spanid="cb3-211"><ahref="#cb3-211"aria-hidden="true"tabindex="-1"></a><spanclass="bu">print</span>(<spanclass="st">"4. Was die Skalarisierung nicht findet</span><spanclass="ch">\n</span><spanclass="st">"</span>)</span>
<spanid="cb3-212"><ahref="#cb3-212"aria-hidden="true"tabindex="-1"></a> erreicht <spanclass="op">=</span> [p <spanclass="cf">for</span> p <spanclass="kw">in</span> front <spanclass="cf">if</span> p <spanclass="kw">in</span> gefunden]</span>
<spanid="cb3-214"><ahref="#cb3-214"aria-hidden="true"tabindex="-1"></a><spanclass="bu">print</span>(<spanclass="ss">f" davon von der Skalarisierung gefunden: </span><spanclass="sc">{</span><spanclass="bu">len</span>(erreicht)<spanclass="sc">}</span><spanclass="ss">"</span>)</span>
<spanid="cb3-215"><ahref="#cb3-215"aria-hidden="true"tabindex="-1"></a><spanclass="bu">print</span>(<spanclass="ss">f" nie gefunden: </span><spanclass="sc">{</span><spanclass="bu">len</span>(front) <spanclass="op">-</span><spanclass="bu">len</span>(erreicht)<spanclass="sc">}</span><spanclass="ss">"</span>)</span>
<spanid="cb3-217"><ahref="#cb3-217"aria-hidden="true"tabindex="-1"></a><spanclass="bu">print</span>(<spanclass="st">" Diese Kompromisse sind fuer KEIN Gewicht erreichbar:</span><spanclass="ch">\n</span><spanclass="st">"</span>)</span>
<spanid="cb3-220"><ahref="#cb3-220"aria-hidden="true"tabindex="-1"></a><spanclass="cf">for</span> k, c <spanclass="kw">in</span> unerreichbar:</span>
<spanid="cb3-221"><ahref="#cb3-221"aria-hidden="true"tabindex="-1"></a><spanclass="bu">print</span>(<spanclass="ss">f"</span><spanclass="sc">{</span>k<spanclass="sc">:>10,}</span><spanclass="ss"></span><spanclass="sc">{</span>c<spanclass="sc">:>9,}</span><spanclass="ss"> kg </span><spanclass="sc">{</span>k <spanclass="op">-</span> guenstigst[<spanclass="dv">0</span>]<spanclass="sc">:>8,}</span><spanclass="ss">"</span></span>
<spanid="cb3-224"><ahref="#cb3-224"aria-hidden="true"tabindex="-1"></a> stimmt <spanclass="op">=</span><spanclass="bu">sorted</span>(unerreichbar) <spanclass="op">==</span><spanclass="bu">sorted</span>(p <spanclass="cf">for</span> p <spanclass="kw">in</span> front <spanclass="cf">if</span> p <spanclass="kw">not</span><spanclass="kw">in</span> gefunden)</span>
<spanid="cb3-225"><ahref="#cb3-225"aria-hidden="true"tabindex="-1"></a><spanclass="bu">print</span>(<spanclass="ss">f"</span><spanclass="ch">\n</span><spanclass="ss"> Gegenprobe ueber die Geometrie: </span><spanclass="sc">{</span><spanclass="st">'bestanden'</span><spanclass="cf">if</span> stimmt <spanclass="cf">else</span><spanclass="st">'ABWEICHUNG'</span><spanclass="sc">}</span><spanclass="ss">"</span>)</span>
<spanid="cb3-226"><ahref="#cb3-226"aria-hidden="true"tabindex="-1"></a><spanclass="bu">print</span>(<spanclass="st">" Genau die Punkte, die das Gewichtsraster verfehlt, liegen strikt"</span>)</span>
<spanid="cb3-227"><ahref="#cb3-227"aria-hidden="true"tabindex="-1"></a><spanclass="bu">print</span>(<spanclass="st">" oberhalb der unteren konvexen Huelle. Das ist kein Rasterproblem -"</span>)</span>
<spanid="cb3-228"><ahref="#cb3-228"aria-hidden="true"tabindex="-1"></a><spanclass="bu">print</span>(<spanclass="st">" eine Gerade, die von links unten an die Wolke geschoben wird,"</span>)</span>
<spanid="cb3-229"><ahref="#cb3-229"aria-hidden="true"tabindex="-1"></a><spanclass="bu">print</span>(<spanclass="st">" beruehrt immer einen Eckpunkt der Huelle und nie einen Punkt"</span>)</span>
<spanid="cb3-230"><ahref="#cb3-230"aria-hidden="true"tabindex="-1"></a><spanclass="bu">print</span>(<spanclass="st">" darueber. Ein feineres Raster aendert daran nichts."</span>)</span>
<spanid="cb3-234"><ahref="#cb3-234"aria-hidden="true"tabindex="-1"></a><spanclass="bu">print</span>(<spanclass="st">"5. Lexikografisch: erst Kosten, dann CO2 im Rahmen eines Budgets</span><spanclass="ch">\n</span><spanclass="st">"</span>)</span>
<spanid="cb3-243"><ahref="#cb3-243"aria-hidden="true"tabindex="-1"></a><spanclass="bu">print</span>(<spanclass="ss">f"</span><spanclass="sc">{</span>aufschlag<spanclass="sc">:>13.0%}</span><spanclass="ss"></span><spanclass="sc">{</span>ergebnis[<spanclass="dv">0</span>]<spanclass="sc">:>10,}</span><spanclass="ss"></span><spanclass="sc">{</span>ergebnis[<spanclass="dv">1</span>]<spanclass="sc">:>9,}</span><spanclass="ss"> kg "</span></span>
<spanid="cb3-244"><ahref="#cb3-244"aria-hidden="true"tabindex="-1"></a><spanclass="ss">f"</span><spanclass="sc">{</span>guenstigst[<spanclass="dv">1</span>] <spanclass="op">-</span> ergebnis[<spanclass="dv">1</span>]<spanclass="sc">:>15,}</span><spanclass="ss"> kg weniger"</span>)</span>
<spanid="cb3-246"><ahref="#cb3-246"aria-hidden="true"tabindex="-1"></a><spanclass="bu">print</span>(<spanclass="st">"</span><spanclass="ch">\n</span><spanclass="st"> Das ist die Form, die im Betrieb am ehesten trifft: Nicht 'wie"</span>)</span>
<spanid="cb3-247"><ahref="#cb3-247"aria-hidden="true"tabindex="-1"></a><spanclass="bu">print</span>(<spanclass="st">" wichtig ist CO2?', sondern 'wir geben zwei Prozent mehr aus - was"</span>)</span>
<spanid="cb3-248"><ahref="#cb3-248"aria-hidden="true"tabindex="-1"></a><spanclass="bu">print</span>(<spanclass="st">" bringt das?'. Die Frage kann ein Kaufmann beantworten."</span>)</span>
<spanid="cb3-251"><ahref="#cb3-251"aria-hidden="true"tabindex="-1"></a><spanclass="bu">print</span>(<spanclass="st">" WAS MAN DARAUS MITNIMMT"</span>)</span>
<spanid="cb3-253"><ahref="#cb3-253"aria-hidden="true"tabindex="-1"></a><spanclass="bu">print</span>(<spanclass="st">"Ein Gewicht zu setzen heisst, die Entscheidung heimlich zu treffen -"</span>)</span>
<spanid="cb3-254"><ahref="#cb3-254"aria-hidden="true"tabindex="-1"></a><spanclass="bu">print</span>(<spanclass="st">"und dabei einen Teil der Moeglichkeiten gar nicht erst zu sehen."</span>)</span>
<spanid="cb3-256"><ahref="#cb3-256"aria-hidden="true"tabindex="-1"></a><spanclass="bu">print</span>(<spanclass="st">"Die Pareto-Front ist die ehrlichere Antwort: Sie legt dem Betrieb"</span>)</span>
<spanid="cb3-257"><ahref="#cb3-257"aria-hidden="true"tabindex="-1"></a><spanclass="bu">print</span>(<spanclass="st">"alle sinnvollen Kompromisse vor und ueberlaesst ihm die Wahl. Die"</span>)</span>
<spanid="cb3-258"><ahref="#cb3-258"aria-hidden="true"tabindex="-1"></a><spanclass="bu">print</span>(<spanclass="st">"Spalte 'EUR je kg' macht sie entscheidbar - man vergleicht sie mit"</span>)</span>
<spanid="cb3-259"><ahref="#cb3-259"aria-hidden="true"tabindex="-1"></a><spanclass="bu">print</span>(<spanclass="st">"dem CO2-Preis, den das Unternehmen ohnehin ansetzt."</span>)</span>
<h2id="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>
<imgsrc="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."/>
<figcaptionaria-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.</figcaption>
<p><strong>Warum es keine Frage des Rasters ist.</strong> „<spanclass="math inline">c(x) + w\,e(x)</span> minimieren” heißt geometrisch: eine Gerade der Steigung <spanclass="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 <spanclass="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>
<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>
<h3id="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/>
<h2id="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><spanclass="math display">
\min_{x \in X} \; c(x)
\qquad \text{unter} \qquad
e(x) \le \varepsilon
</span></p>
<p>Für jedes <spanclass="math inline">\varepsilon</span> liefert das einen Punkt der Front. Die Kunst besteht nur darin, die <spanclass="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>
<oltype="1">
<li>Kostenminimum bestimmen. Das ist der eine Rand der Front; nebenbei fällt sein CO₂-Wert an.</li>
<li><spanclass="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>
<h3id="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>
<trclass="header">
<thstyle="text-align: right;">Kostenbudget</th>
<thstyle="text-align: right;">Kosten</th>
<thstyle="text-align: right;">CO₂</th>
<thstyle="text-align: right;">gegenüber dem Minimum</th>
</tr>
</thead>
<tbody>
<trclass="odd">
<tdstyle="text-align: right;">+0 %</td>
<tdstyle="text-align: right;">13 543 €</td>
<tdstyle="text-align: right;">6 475 kg</td>
<tdstyle="text-align: right;">—</td>
</tr>
<trclass="even">
<tdstyle="text-align: right;">+1 %</td>
<tdstyle="text-align: right;">13 635 €</td>
<tdstyle="text-align: right;">6 317 kg</td>
<tdstyle="text-align: right;">158 kg weniger</td>
</tr>
<trclass="odd">
<tdstyle="text-align: right;">+2 %</td>
<tdstyle="text-align: right;">13 724 €</td>
<tdstyle="text-align: right;">6 022 kg</td>
<tdstyle="text-align: right;">453 kg weniger</td>
</tr>
<trclass="even">
<tdstyle="text-align: right;">+5 %</td>
<tdstyle="text-align: right;">14 189 €</td>
<tdstyle="text-align: right;">5 632 kg</td>
<tdstyle="text-align: right;">843 kg weniger</td>
</tr>
<trclass="odd">
<tdstyle="text-align: right;">+10 %</td>
<tdstyle="text-align: right;">14 821 €</td>
<tdstyle="text-align: right;">5 506 kg</td>
<tdstyle="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/>
<h2id="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><spanclass="math display">
\text{Schattenpreis} = \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>
<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>
<trclass="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>
<trclass="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>
<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/>
<h2id="sec:mehrziel-denkfehler">14.10 Finde den Denkfehler</h2>
<divclass="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 <spanclass="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/>
<h2id="sec:mehrziel-quiz">14.11 Micro-Quiz</h2>
<divclass="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>
<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>
<navclass="prev-next"><aclass="prev-next-knopf prev-next-prev"href="dynamische-programmierung.html"><svgclass="icon"aria-hidden="true"><usehref="#icon-chevron-left"></use></svg><span><small>Zurück</small>Kapitel 13: Dynamische Programmierung — Die Bellman-Gleichung und Order-Execution</span></a><aclass="prev-next-knopf prev-next-next"href="prognose.html"><span><small>Weiter</small>Kapitel 15: Predict-then-Optimize — die bessere Prognose, die schlechtere Entscheidung</span><svgclass="icon"aria-hidden="true"><usehref="#icon-chevron-right"></use></svg></a></nav>