operations_research/OR_HTML_04/anhang-modellierungsmuster.html
dschlueter 47d63dfe9c Menue: ZIP-Punkt nicht mehr eingerueckt, "(eine HTML-Seite)"
Zwei Beschriftungsaenderungen in baue_sidebar_html():

* "Download Notebooks als ZIP" steht jetzt auf gleicher Hoehe wie die
  uebrigen Punkte statt eingerueckt unter "Notebooks".
* "Gesamtdokument (eine Seite)" -> "(eine HTML-Seite)". Direkt darunter steht
  "Download Buch als PDF"; ohne das Wort HTML liess sich nicht erkennen, dass
  es zwei verschiedene Formate sind.

Mit der Einrueckung faellt ihre Ursache weg: Die CSS-Klasse
.sidebar-unterpunkt in web_04/assets/site.css war eigens dafuer angelegt
worden und wird von nichts mehr benutzt - entfernt, statt als tote Regel
stehen zu bleiben.

Veroeffentlicht: 42 Dateien uebertragen (die Seiten, nichts sonst - dank
--checksum), 0 geloescht, alle vierzehn HTTP-Proben richtig. Gegenprobe vom
Server: kein sidebar-unterpunkt mehr im ausgelieferten HTML.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-08 19:24:54 +02:00

521 lines
49 KiB
HTML
Generated
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!doctype html>
<html lang="de">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Anhang B: Katalog der Modellierungsmuster · 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</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</span></a></li><li data-kapitel="cpsat.html"><a href="cpsat.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Kapitel 7: Constraint Programming mit CP-SAT — Logik, Scheduling und Zuweisung</span></a></li><li data-kapitel="graphen.html"><a href="graphen.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Kapitel 8: Graphen, Flüsse und Touren — Min-Cost-Flow, Matching und VRP</span></a></li><li data-kapitel="metaheuristiken.html"><a href="metaheuristiken.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Kapitel 9: Metaheuristiken — wenn der exakte Solver aussteigt</span></a></li><li data-kapitel="dekomposition.html"><a href="dekomposition.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Kapitel 10: Spaltengenerierung — das Modell umbauen statt die Lösung raten</span></a></li><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"><summary>Teil III: Nichtlinearität, Unsicherheit und mehrperiodige Dynamik</summary><ul><li data-kapitel="qp-nlp.html"><a href="qp-nlp.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Kapitel 11: Quadratische und nichtlineare Optimierung — KKT, Lagrange, Konvexität</span></a></li><li data-kapitel="unsicherheit.html"><a href="unsicherheit.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Kapitel 12: Optimierung unter Unsicherheit — Monte-Carlo, Stochastik, Robustheit</span></a></li><li data-kapitel="dynamische-programmierung.html"><a href="dynamische-programmierung.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Kapitel 13: Dynamische Programmierung — Die Bellman-Gleichung und Order-Execution</span></a></li><li data-kapitel="mehrziel.html"><a href="mehrziel.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Kapitel 14: Mehrere Ziele — Pareto-Fronten statt Gewichte</span></a></li><li data-kapitel="prognose.html"><a href="prognose.html"><span class="fortschritt-haken"><svg class="icon" aria-hidden="true"><use href="#icon-check"></use></svg></span><span>Kapitel 15: Predict-then-Optimize — die bessere Prognose, die schlechtere Entscheidung</span></a></li><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</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" open><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" class="aktiv"><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>Anhang B: Katalog der Modellierungsmuster</span></nav>
<nav class="prev-next"><a class="prev-next-knopf prev-next-prev" href="anhang-loesungen.html"><svg class="icon" aria-hidden="true"><use href="#icon-chevron-left"></use></svg><span><small>Zurück</small>Anhang A: Lösungen zu allen Übungsaufgaben</span></a><a class="prev-next-knopf prev-next-next" href="anhang-fehlerdiagnose.html"><span><small>Weiter</small>Anhang C: Fehlerdiagnose-Handbuch</span><svg class="icon" aria-hidden="true"><use href="#icon-chevron-right"></use></svg></a></nav>
<article>
<h1 id="anhang-modellierungsmuster">Anhang B: Katalog der Modellierungsmuster</h1>
<blockquote>
<p><strong>Wofür dieser Anhang gedacht ist:</strong> Sie sitzen vor einem konkreten Problem und wissen nicht, wie Sie eine bestimmte Regel in ein Modell bekommen. Suchen Sie hier das Muster, das zu Ihrer Formulierung passt. Jeder Eintrag nennt die Regel in Alltagssprache, die mathematische Formulierung, den Code und die Fallstricke.</p>
</blockquote>
<hr />
<h2 id="übersicht">Übersicht</h2>
<table>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>#</th>
<th>Muster</th>
<th>Umgangssprachlich</th>
<th>Wo im Buch</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><strong>Logische Schalter</strong></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>B1</td>
<td>Aktivierungsschalter</td>
<td>„Wenn genutzt, dann Fixkosten“</td>
<td><a href="milp.html#kap-milp">Kapitel 6</a></td>
</tr>
<tr class="odd">
<td>B2</td>
<td>Semikontinuierlich</td>
<td>„Entweder 0 oder mindestens L“</td>
<td><a href="milp.html#kap-milp">Kapitel 6</a></td>
</tr>
<tr class="even">
<td>B3</td>
<td>Implikation</td>
<td>„Wenn A, dann auch B“</td>
<td><a href="milp.html#kap-milp">Kapitel 6</a></td>
</tr>
<tr class="odd">
<td>B4</td>
<td>Entweder-Oder</td>
<td>„A oder B, aber nicht beides“</td>
<td><a href="milp.html#kap-milp">Kapitel 6</a></td>
</tr>
<tr class="even">
<td>B5</td>
<td>Exklusiv-Oder</td>
<td>„Genau eines von N“</td>
<td><a href="cpsat.html#kap-cpsat">Kapitel 7</a></td>
</tr>
<tr class="odd">
<td>B6</td>
<td>Kardinalität</td>
<td>„Höchstens K von N“</td>
<td><a href="milp.html#kap-milp">Kapitel 6</a></td>
</tr>
<tr class="even">
<td>B7</td>
<td>Bedingte Kopplung</td>
<td>„Wenn A und B, dann C“</td>
<td><a href="milp.html#kap-milp">Kapitel 6</a></td>
</tr>
<tr class="odd">
<td><strong>Mengen und Grenzen</strong></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>B8</td>
<td>Weiche Grenze</td>
<td>„Möglichst nicht über X“</td>
<td><a href="cpsat.html#kap-cpsat">Kapitel 7</a></td>
</tr>
<tr class="odd">
<td>B9</td>
<td>Gestaffelte Preise</td>
<td>„Erste 100 Stück billiger“</td>
<td></td>
</tr>
<tr class="even">
<td>B10</td>
<td>Absolutbetrag</td>
<td>„Abweichung nach oben wie unten“</td>
<td><a href="cvar.html#kap-cvar">Kapitel 20</a></td>
</tr>
<tr class="odd">
<td>B11</td>
<td>Min/Max in der Zielfunktion</td>
<td>„Den Schlechtesten verbessern“</td>
<td><a href="cpsat.html#kap-cpsat">Kapitel 7</a></td>
</tr>
<tr class="even">
<td>B12</td>
<td>Verhältnis-Bedingung</td>
<td>„Anteil mindestens 30 %“</td>
<td><a href="markowitz.html#kap-markowitz">Kapitel 19</a></td>
</tr>
<tr class="odd">
<td>B25</td>
<td>Mindestabnahme im Zeitraum</td>
<td>„Entweder gar nicht oder 500 im Jahr“</td>
<td><a href="bruecke.html#kap-bruecke">Kapitel 16</a></td>
</tr>
<tr class="even">
<td>B27</td>
<td>Budgetlimit</td>
<td>„Mehr als 2 Mio. gibt es nicht“</td>
<td><a href="milp.html#kap-milp">Kapitel 6</a></td>
</tr>
<tr class="odd">
<td><strong>Zeit und Reihenfolge</strong></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>B13</td>
<td>Vorrangbeziehung</td>
<td>„B erst nach A“</td>
<td><a href="cpsat.html#kap-cpsat">Kapitel 7</a></td>
</tr>
<tr class="odd">
<td>B14</td>
<td>Nichtüberlappung</td>
<td>„Eine Maschine, ein Job“</td>
<td><a href="cpsat.html#kap-cpsat">Kapitel 7</a></td>
</tr>
<tr class="even">
<td>B15</td>
<td>Kumulative Ressource</td>
<td>„Höchstens 3 gleichzeitig“</td>
<td><a href="cpsat.html#kap-cpsat">Kapitel 7</a></td>
</tr>
<tr class="odd">
<td>B16</td>
<td>Gleitendes Fenster</td>
<td>„Höchstens 5 Tage in Folge“</td>
<td><a href="cpsat.html#kap-cpsat">Kapitel 7</a></td>
</tr>
<tr class="even">
<td>B17</td>
<td>Umrüstkosten</td>
<td>„Wechsel kostet extra“</td>
<td><a href="cpsat.html#kap-cpsat">Kapitel 7</a></td>
</tr>
<tr class="odd">
<td>B26</td>
<td>Rüstzeit als Kapazität</td>
<td>„Umbauen kostet Maschinenstunden“</td>
<td><a href="supplychain.html#kap-supplychain">Kapitel 17</a></td>
</tr>
<tr class="even">
<td><strong>Robustheit und Diagnose</strong></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr class="odd">
<td>B18</td>
<td>Schlupf gegen Unlösbarkeit</td>
<td>„Regel notfalls brechen“</td>
<td><a href="praxisfallen.html#kap-praxisfallen">Kapitel 22</a></td>
</tr>
<tr class="even">
<td>B19</td>
<td>Hierarchische Ziele</td>
<td>„Erst A, dann B optimieren“</td>
<td><a href="praxisfallen.html#kap-praxisfallen">Kapitel 22</a></td>
</tr>
<tr class="odd">
<td>B20</td>
<td>Symmetriebrechung</td>
<td>„Gleiche Objekte nicht doppelt zählen“</td>
<td><a href="dekomposition.html#kap-dekomposition">Kapitel 10</a></td>
</tr>
<tr class="even">
<td>B21</td>
<td>Worst-Case-Abzug</td>
<td>„Gegen Schätzfehler absichern“</td>
<td><a href="unsicherheit.html#kap-unsicherheit">Kapitel 12</a></td>
</tr>
<tr class="odd">
<td><strong>Netzwerke</strong></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>B22</td>
<td>Flusserhaltung</td>
<td>„Was reinkommt, geht raus“</td>
<td><a href="graphen.html#kap-graphen">Kapitel 8</a></td>
</tr>
<tr class="odd">
<td>B23</td>
<td>Zuordnung 1:1</td>
<td>„Jeder genau eine Aufgabe“</td>
<td><a href="graphen.html#kap-graphen">Kapitel 8</a></td>
</tr>
<tr class="even">
<td>B24</td>
<td>Subtour-Eliminierung</td>
<td>„Keine isolierten Kreise“</td>
<td><a href="graphen.html#kap-graphen">Kapitel 8</a></td>
</tr>
</tbody>
</table>
<blockquote>
<p><strong>Umgekehrte Richtung:</strong> Wer von einem Satz aus der Besprechung kommt und das Muster sucht, findet in <a href="modellierung.html#sec:modellierung-glossar">Abschnitt 4.6</a> ein Lexikon, das genau so herum aufgebaut ist — und die Wendungen benennt, bei denen es keine eindeutige Übersetzung gibt.</p>
<p>Die Spalte „Wo im Buch“ nennt das Kapitel, in dem das Muster <strong>im Zusammenhang</strong> vorkommt — nicht die einzige Stelle, an der es taugt. Die Nummern entstehen beim Bauen; im Quelltext dieses Anhangs steht keine einzige.</p>
</blockquote>
<hr />
<h2 id="logische-schalter">Logische Schalter</h2>
<h3 id="b1-aktivierungsschalter-fixkosten">B1 — Aktivierungsschalter (Fixkosten)</h3>
<p><strong>Regel.</strong> „Wenn überhaupt etwas produziert wird, fallen Rüstkosten <span class="math inline">F</span> an.“</p>
<p><span class="math display">x \le M\,y,\qquad y\in\{0,1\},\ x\ge0</span> Zielfunktion: <span class="math inline">\dots + F\,y</span></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>modell.Add(x <span class="op">&lt;=</span> M <span class="op">*</span> y) <span class="co"># CP-SAT</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="co"># LP/MILP: Zeile x - M*y &lt;= 0</span></span></code></pre></div>
<blockquote>
<p>⚠️ <strong><span class="math inline">M</span> so klein wie möglich</strong> — idealerweise die ohnehin vorhandene Kapazitätsgrenze von <span class="math inline">x</span>. Zu großes <span class="math inline">M</span> macht die LP-Relaxation wertlos (<a href="milp.html#sec:milp-modellierungstricks-big-m-und-logische-bedingungen">Abschnitt 6.5</a>).</p>
</blockquote>
<h3 id="b2-semikontinuierliche-variable">B2 — Semikontinuierliche Variable</h3>
<p><strong>Regel.</strong> „Entweder gar nicht oder mindestens <span class="math inline">L</span> (und höchstens <span class="math inline">U</span>).“</p>
<p><span class="math display">L\,y \le x \le U\,y,\qquad y\in\{0,1\}</span></p>
<p>Typisch für Mindestordergrößen, Mindestlosgrößen, Mindestabnahmemengen.</p>
<h3 id="b3-implikation">B3 — Implikation</h3>
<p><strong>Regel.</strong> „Wenn A gewählt wird, muss auch B gewählt werden.“</p>
<p><span class="math display">y_A \le y_B</span></p>
<div class="sourceCode" id="cb2"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>modell.AddImplication(y_a, y_b) <span class="co"># CP-SAT, gleichwertig und lesbarer</span></span></code></pre></div>
<p>Für die Umkehrung („nur wenn“) einfach vertauschen. Für Äquivalenz: <span class="math inline">y_A = y_B</span>.</p>
<h3 id="b4-entweder-oder-disjunktive-bedingung">B4 — Entweder-Oder (disjunktive Bedingung)</h3>
<p><strong>Regel.</strong> „Es muss <span class="math inline">f(\mathbf{x}) \le b_1</span> <strong>oder</strong> <span class="math inline">g(\mathbf{x}) \le b_2</span> gelten.“</p>
<p><span class="math display">f(\mathbf{x}) \le b_1 + M(1-y),\qquad g(\mathbf{x}) \le b_2 + M y</span></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"># CP-SAT: viel eleganter ueber Reifizierung</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>modell.Add(f_ausdruck <span class="op">&lt;=</span> b1).OnlyEnforceIf(y)</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>modell.Add(g_ausdruck <span class="op">&lt;=</span> b2).OnlyEnforceIf(y.Not())</span></code></pre></div>
<h3 id="b5-exklusiv-oder">B5 — Exklusiv-Oder</h3>
<p><strong>Regel.</strong> „Genau eine der Optionen wird gewählt.“</p>
<p><span class="math display">\sum_{j=1}^N y_j = 1</span></p>
<div class="sourceCode" id="cb4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>modell.AddExactlyOne(y) <span class="co"># bzw. AddAtMostOne / AddBoolOr</span></span></code></pre></div>
<h3 id="b6-kardinalität">B6 — Kardinalität</h3>
<p><strong>Regel.</strong> „Höchstens (mindestens, genau) <span class="math inline">K</span> von <span class="math inline">N</span>.“</p>
<p><span class="math display">\sum_j y_j \le K \qquad(\ \ge K,\ = K\ )</span></p>
<h3 id="b7-bedingte-kopplung-konjunktion">B7 — Bedingte Kopplung (Konjunktion)</h3>
<p><strong>Regel.</strong> „Wenn A <strong>und</strong> B, dann auch C.“</p>
<p><span class="math display">y_A + y_B - 1 \le y_C</span></p>
<p>Prüfen Sie die vier Fälle: nur bei <span class="math inline">y_A = y_B = 1</span> erzwingt die Ungleichung <span class="math inline">y_C \ge 1</span>.</p>
<p>Für „Wenn A <strong>oder</strong> B, dann C“: <span class="math inline">y_A \le y_C</span> <strong>und</strong> <span class="math inline">y_B \le y_C</span>.</p>
<hr />
<h2 id="mengen-und-grenzen">Mengen und Grenzen</h2>
<h3 id="b8-weiche-grenze-mit-strafkosten">B8 — Weiche Grenze mit Strafkosten</h3>
<p><strong>Regel.</strong> „Möglichst nicht über <span class="math inline">b</span> — wenn doch, kostet es.“</p>
<p><span class="math display">f(\mathbf{x}) \le b + s,\qquad s \ge 0</span> Zielfunktion: <span class="math inline">\dots + c_{\text{Strafe}}\cdot s</span></p>
<p>Das ist das wichtigste Muster überhaupt für praxistaugliche Modelle (siehe B18).</p>
<h3 id="b9-gestaffelte-preise-stückweise-linear">B9 — Gestaffelte Preise (stückweise linear)</h3>
<p><strong>Regel.</strong> „Die ersten 100 Stück kosten 5 €, danach 8 €.“</p>
<p>Variablen je Stufe: <span class="math inline">x = x_1 + x_2</span> mit <span class="math inline">0 \le x_1 \le 100</span>, <span class="math inline">x_2 \ge 0</span>; Kosten <span class="math inline">5x_1 + 8x_2</span>.</p>
<blockquote>
<p>⚠️ Das funktioniert <strong>nur bei steigenden</strong> Preisen (konvexe Kostenfunktion) ohne Binärvariablen — der Optimierer füllt dann automatisch erst die billige Stufe. Bei <strong>fallenden</strong> Preisen (Mengenrabatt, konkav) braucht man Binärvariablen je Stufe, sonst „schummelt“ das Modell.</p>
</blockquote>
<h3 id="b10-absolutbetrag-abweichung">B10 — Absolutbetrag / Abweichung</h3>
<p><strong>Regel.</strong> „Die Abweichung vom Zielwert soll klein sein, egal in welche Richtung.“</p>
<p><span class="math display">|x - z| \le d \quad\Longleftrightarrow\quad x - z \le d\ \ \text{und}\ \ z - x \le d</span></p>
<p>In der <strong>Zielfunktion</strong> (Minimierung von <span class="math inline">|x-z|</span>) genügt: <span class="math display">\min d \quad\text{u. d. N.}\quad x-z \le d,\quad z-x \le d</span></p>
<div class="sourceCode" id="cb5"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>turnover <span class="op">=</span> cp.norm1(w <span class="op">-</span> w_alt) <span class="co"># CVXPY macht das automatisch</span></span></code></pre></div>
<h3 id="b11-minmax-in-der-zielfunktion">B11 — Min/Max in der Zielfunktion</h3>
<p><strong>Regel.</strong> „Der am schlechtesten gestellte Beteiligte soll möglichst gut dastehen“ (Maximin/Fairness).</p>
<p><span class="math display">\max t \quad\text{u. d. N.}\quad t \le f_i(\mathbf{x})\ \ \forall i</span></p>
<div class="sourceCode" id="cb6"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>modell.AddMaxEquality(max_var, liste) <span class="co"># CP-SAT</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>modell.AddMinEquality(min_var, liste)</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a><span class="co"># Fairness ueber die Spannweite:</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>modell.Add(spannweite <span class="op">==</span> max_var <span class="op">-</span> min_var) <span class="co"># dann minimieren</span></span></code></pre></div>
<h3 id="b12-verhältnis-bedingung">B12 — Verhältnis-Bedingung</h3>
<p><strong>Regel.</strong> „Der Anteil von Gruppe G soll mindestens 30 % betragen.“</p>
<p><span class="math display">\frac{\sum_{i\in G} x_i}{\sum_i x_i} \ge 0{,}3 \quad\Longleftrightarrow\quad \sum_{i\in G} x_i \ge 0{,}3\sum_i x_i</span></p>
<blockquote>
<p>⚠️ <strong>Brüche immer wegmultiplizieren</strong> — ein Quotient von Variablen ist nichtlinear und meist nicht konvex. Nach dem Umstellen ist die Bedingung linear.</p>
</blockquote>
<h3 id="b25-mindestabnahmemenge-über-einen-zeitraum">B25 — Mindestabnahmemenge über einen Zeitraum</h3>
<p><strong>Regel.</strong> „Entweder wir arbeiten mit diesem Lieferanten gar nicht, oder wir nehmen ihm im Jahr mindestens 500 Einheiten ab.“</p>
<p>Ein <strong>Schalter für den ganzen Zeitraum</strong>, nicht je Periode:</p>
<p><span class="math display">Q\,y \le \sum_{t} x_{t} \le U\,y, \qquad y \in \{0,1\},\ x_t \ge 0</span></p>
<div class="sourceCode" id="cb7"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="co"># y_s ist EINE Variable je Lieferant - nicht eine je Lieferant UND Periode</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>y <span class="op">=</span> {s: modell.NewBoolVar(<span class="ss">f&quot;vertrag_</span><span class="sc">{</span>s<span class="sc">}</span><span class="ss">&quot;</span>) <span class="cf">for</span> s <span class="kw">in</span> lieferanten}</span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a><span class="cf">for</span> s <span class="kw">in</span> lieferanten:</span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a> jahresmenge <span class="op">=</span> <span class="bu">sum</span>(x[s, t] <span class="cf">for</span> t <span class="kw">in</span> perioden)</span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a> modell.Add(jahresmenge <span class="op">&gt;=</span> MINDESTMENGE[s] <span class="op">*</span> y[s])</span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a> modell.Add(jahresmenge <span class="op">&lt;=</span> JAHRESKAPAZITAET[s] <span class="op">*</span> y[s]) <span class="co"># koppelt x an y</span></span></code></pre></div>
<blockquote>
<p>⚠️ <strong>Die häufigste Verwechslung:</strong> <span class="math inline">L\,y_t \le x_t</span> <strong>je Periode</strong> (B2) ist ein <em>anderes</em> Modell — es verlangt in jeder einzelnen Periode eine Mindestmenge und ist erheblich strenger. Wer den Jahresvertrag so formuliert, erzeugt ein unlösbares Modell und sucht den Fehler dann in den Daten.</p>
</blockquote>
<blockquote>
<p>⚠️ <strong>Die obere Kopplung nicht vergessen.</strong> Ohne <span class="math inline">\sum_t x_t \le U\,y</span> kann das Modell <span class="math inline">y = 0</span> setzen und trotzdem einkaufen — der Vertrag gilt dann als nicht geschlossen, die Ware fließt aber. Das ist der <em>Trickle Flow</em> aus <a href="milp.html#sec:milp-modellierungstricks-big-m-und-logische-bedingungen">Abschnitt 6.5</a>, nur andersherum. <span class="math inline">U</span> ist die Jahreskapazität des Lieferanten, keine runde Zahl.</p>
</blockquote>
<h3 id="b27-budgetlimit">B27 — Budgetlimit</h3>
<p><strong>Regel.</strong> „Alle Maßnahmen zusammen dürfen 2 Mio. € nicht überschreiten.“</p>
<p><span class="math display">\sum_i c_i x_i \le B</span></p>
<p>Mit <span class="math inline">x_i \in \{0,1\}</span> ist das ein <strong>Rucksackproblem</strong> — dasselbe Muster, das <a href="milp.html#kap-milp">Kapitel 6</a> an <code>Rucksack.py</code> vorrechnet und <a href="dekomposition.html#kap-dekomposition">Kapitel 10</a> als Pricing-Teilproblem wiederverwendet.</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a>modell.Add(<span class="bu">sum</span>(KOSTEN[i] <span class="op">*</span> x[i] <span class="cf">for</span> i <span class="kw">in</span> massnahmen) <span class="op">&lt;=</span> BUDGET)</span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="co"># Mehrere Toepfe: je Topf eine Zeile - NICHT die Summe ueber alle Toepfe</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a><span class="cf">for</span> topf, grenze <span class="kw">in</span> BUDGETS.items():</span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a> modell.Add(<span class="bu">sum</span>(KOSTEN[i] <span class="op">*</span> x[i] <span class="cf">for</span> i <span class="kw">in</span> massnahmen</span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> TOPF[i] <span class="op">==</span> topf) <span class="op">&lt;=</span> grenze)</span></code></pre></div>
<blockquote>
<p>💡 <strong>Der Schattenpreis des Budgets ist die Zahl, nach der die Geschäftsführung fragt:</strong> „Was bringt der nächste Euro?“ Bei einem <strong>LP</strong> ist er direkt ablesbar. Bei <strong>Ganzzahligkeit gibt es ihn nicht</strong> — die Dualwerte der Relaxation sind keine gültige Antwort. Rechnen Sie stattdessen mit erhöhtem Budget neu und vergleichen Sie die Zielwerte (<a href="lp.html#sec:lp-entartung">Abschnitt 5.9</a>).</p>
</blockquote>
<blockquote>
<p>⚠️ <strong>Die LP-Relaxation verspricht zu viel.</strong> Sie darf die letzte Maßnahme anteilig kaufen und liefert deshalb eine Schranke, die spürbar über dem tatsächlich Erreichbaren liegen kann. Wer sie als Prognose berichtet, verspricht Geld, das nicht kommt.</p>
</blockquote>
<hr />
<h2 id="zeit-und-reihenfolge">Zeit und Reihenfolge</h2>
<h3 id="b13-vorrangbeziehung">B13 — Vorrangbeziehung</h3>
<p><strong>Regel.</strong> „Arbeitsgang B darf erst beginnen, wenn A fertig ist.“</p>
<p><span class="math display">\text{start}_B \ge \text{ende}_A</span></p>
<p>Mit Mindestwartezeit <span class="math inline">w</span>: <span class="math inline">\text{start}_B \ge \text{ende}_A + w</span>.</p>
<h3 id="b14-nichtüberlappung">B14 — Nichtüberlappung</h3>
<p><strong>Regel.</strong> „Eine Maschine bearbeitet nur einen Job gleichzeitig.“</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>modell.AddNoOverlap([intervall_1, intervall_2, ...])</span></code></pre></div>
<p>In MILP bräuchte man je Paar eine Disjunktion (B4) — bei <span class="math inline">k</span> Jobs sind das <span class="math inline">\binom{k}{2}</span> Konstruktionen. <strong>Nehmen Sie hier CP-SAT.</strong></p>
<h3 id="b15-kumulative-ressource">B15 — Kumulative Ressource</h3>
<p><strong>Regel.</strong> „Zu keinem Zeitpunkt dürfen mehr als 3 Arbeiten gleichzeitig laufen“ bzw. „die Stromlast darf 500 kW nie übersteigen“.</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a>modell.AddCumulative(intervalle, bedarfe, kapazitaet)</span></code></pre></div>
<h3 id="b16-gleitendes-fenster">B16 — Gleitendes Fenster</h3>
<p><strong>Regel.</strong> „Höchstens 5 Arbeitstage in Folge“ / „mindestens 2 freie Tage je Woche“.</p>
<p><span class="math display">\sum_{u=t}^{t+5} x_u \le 5 \qquad \forall t</span></p>
<div class="sourceCode" id="cb11"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="cf">for</span> t <span class="kw">in</span> <span class="bu">range</span>(<span class="bu">len</span>(tage) <span class="op">-</span> <span class="dv">5</span>):</span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a> modell.Add(<span class="bu">sum</span>(x[p, u] <span class="cf">for</span> u <span class="kw">in</span> <span class="bu">range</span>(t, t <span class="op">+</span> <span class="dv">6</span>)) <span class="op">&lt;=</span> <span class="dv">5</span>)</span></code></pre></div>
<h3 id="b17-umrüst--bzw.-wechselkosten">B17 — Umrüst- bzw. Wechselkosten</h3>
<p><strong>Regel.</strong> „Ein Produktwechsel kostet Rüstzeit.“</p>
<p>Hilfsvariable <span class="math inline">z_t \in \{0,1\}</span> = „in Periode <span class="math inline">t</span> wird gewechselt“:</p>
<p><span class="math display">z_t \ge y_{j,t} - y_{j,t-1} \qquad \forall j, t</span></p>
<p>Zielfunktion: <span class="math inline">\dots + c_{\text{Ruest}}\sum_t z_t</span>. Für <strong>reihenfolgeabhängige</strong> Rüstzeiten: <code>AddCircuit</code> mit Übergangsmatrix.</p>
<h3 id="b26-rüstzeit-als-kapazitätsverbrauch">B26 — Rüstzeit als Kapazitätsverbrauch</h3>
<p><strong>Regel.</strong> „Das Umrüsten kostet nicht nur Geld, es kostet <strong>Maschinenstunden</strong> — und die fehlen dann für die Produktion.“</p>
<p>B17 verbucht den Wechsel in der <em>Zielfunktion</em>. Sobald die Maschine ausgelastet ist, gehört er zusätzlich in die <em>Kapazitätszeile</em>:</p>
<p><span class="math display">\sum_j a_j\,x_{j,t} \;+\; \sum_j r_j\,y_{j,t} \;\le\; C_t \qquad \forall t</span></p>
<p>mit <span class="math inline">a_j</span> Stückzeit, <span class="math inline">r_j</span> Rüstzeit, <span class="math inline">y_{j,t}\in\{0,1\}</span> = „Produkt <span class="math inline">j</span> läuft in Periode <span class="math inline">t</span>“ (gekoppelt über B1: <span class="math inline">x_{j,t} \le M\,y_{j,t}</span>).</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="cf">for</span> t <span class="kw">in</span> perioden:</span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a> modell.Add(<span class="bu">sum</span>(STUECKZEIT[j] <span class="op">*</span> x[j, t] <span class="cf">for</span> j <span class="kw">in</span> produkte)</span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a> <span class="op">+</span> <span class="bu">sum</span>(RUESTZEIT[j] <span class="op">*</span> y[j, t] <span class="cf">for</span> j <span class="kw">in</span> produkte) <span class="op">&lt;=</span> KAPAZITAET[t])</span></code></pre></div>
<blockquote>
<p>⚠️ <strong>Wer die Rüstzeit nur als Kosten führt, erhält Pläne, die in der Halle nicht laufen.</strong> Das Modell verteilt die Produktion dann auf viele kleine Lose, weil ein zusätzlicher Wechsel zwar etwas kostet, aber keine Zeit verbraucht — die Rechnung geht auf dem Papier auf und in der Schicht nicht.</p>
</blockquote>
<p><strong>Reihenfolgeabhängig</strong> (<span class="math inline">r_{ij}</span> statt <span class="math inline">r_j</span> — von Weiß auf Schwarz ist schneller als umgekehrt) ist es kein Kapazitätsproblem mehr, sondern ein Rundreiseproblem: <code>AddCircuit</code> mit der Übergangsmatrix als Kantengewicht (B24, <a href="cpsat.html#kap-cpsat">Kapitel 7</a>).</p>
<hr />
<h2 id="robustheit-und-diagnose">Robustheit und Diagnose</h2>
<h3 id="b18-schlupfvariablen-gegen-unlösbarkeit">B18 — Schlupfvariablen gegen Unlösbarkeit</h3>
<p><strong>Das wichtigste Muster für den Produktivbetrieb.</strong></p>
<p><strong>Regel.</strong> „Diese Bedingung soll gelten — aber lieber ein schlechter Plan als gar keiner.“</p>
<p><span class="math display">\sum_p x_{p,s} + u_s = 1,\qquad u_s\in\{0,1\}</span> Zielfunktion: <span class="math inline">\dots + 10\,000\cdot u_s</span></p>
<p>Die Strafe muss <strong>hoch genug</strong> sein, dass der Solver sie nur im Notfall in Kauf nimmt, aber <strong>endlich</strong>, damit es überhaupt eine Lösung gibt. Faustregel: eine Größenordnung über der Summe aller weichen Ziele.</p>
<h3 id="b19-hierarchische-ziele-lexikografisch">B19 — Hierarchische Ziele (lexikografisch)</h3>
<p><strong>Regel.</strong> „Erst die Besetzung sicherstellen, dann die Fairness optimieren.“</p>
<p><strong>Variante A — Gewichtung:</strong> Strafen um Größenordnungen staffeln (<span class="math inline">10\,000 \gg 100 \gg 1</span>). Einfach, aber bei extremen Skalenunterschieden numerisch heikel.</p>
<p><strong>Variante B — Zweistufig lösen (sauberer):</strong></p>
<div class="sourceCode" id="cb13"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="co"># Stufe 1: nur das Hauptziel</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>modell.Minimize(unbesetzte_schichten)</span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>loeser.Solve(modell)</span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a>bestwert <span class="op">=</span> loeser.ObjectiveValue()</span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a><span class="co"># Stufe 2: Hauptziel fixieren, Nebenziel optimieren</span></span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a>modell.Add(unbesetzte_schichten <span class="op">&lt;=</span> <span class="bu">int</span>(bestwert))</span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a>modell.Minimize(unfairness)</span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a>loeser.Solve(modell)</span></code></pre></div>
<h3 id="b20-symmetriebrechung">B20 — Symmetriebrechung</h3>
<p><strong>Regel.</strong> „Drei identische Maschinen — der Solver soll nicht alle Vertauschungen durchprobieren.“</p>
<p><span class="math display">\text{start}_1 \le \text{start}_2 \le \text{start}_3 \qquad\text{bzw.}\qquad \sum_j x_{1j} \ge \sum_j x_{2j}</span></p>
<p>Ohne Symmetriebrechung durchsucht Branch-and-Bound <span class="math inline">k!</span> gleichwertige Lösungen. <strong>Eine einzige Ordnungsbedingung kann die Laufzeit um Größenordnungen senken.</strong></p>
<h3 id="b21-worst-case-abzug-robuste-formulierung">B21 — Worst-Case-Abzug (robuste Formulierung)</h3>
<p><strong>Regel.</strong> „Rechne nicht mit dem geschätzten Wert, sondern mit dem ungünstigsten plausiblen.“</p>
<p>Bei Box-Unsicherheit <span class="math inline">\mu_i \in [\hat\mu_i - \delta_i, \hat\mu_i + \delta_i]</span> und <span class="math inline">w \ge 0</span>: <span class="math display">\hat{\boldsymbol{\mu}}^\top\mathbf{w} \;\longrightarrow\; \hat{\boldsymbol{\mu}}^\top\mathbf{w} - \boldsymbol{\delta}^\top\mathbf{w}</span></p>
<p>Abgestuft (Bertsimas/Sim): nur die <span class="math inline">\Gamma</span> ungünstigsten gleichzeitig:</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a>abzug <span class="op">=</span> cp.sum_largest(cp.multiply(delta, w), Gamma)</span></code></pre></div>
<hr />
<h2 id="netzwerke">Netzwerke</h2>
<h3 id="b22-flusserhaltung">B22 — Flusserhaltung</h3>
<p><span class="math display">\sum_{j:(i,j)\in E} x_{ij} - \sum_{k:(k,i)\in E} x_{ki} = b_i \qquad \forall i</span></p>
<p><span class="math inline">b_i &gt; 0</span> Quelle, <span class="math inline">b_i &lt; 0</span> Senke, <span class="math inline">b_i = 0</span> Umschlagknoten. <strong>Voraussetzung:</strong> <span class="math inline">\sum_i b_i = 0</span> — sonst unlösbar (Dummy-Knoten einführen).</p>
<h3 id="b23-zuordnung-11">B23 — Zuordnung 1:1</h3>
<p></p>
<p><span class="math display">\sum_j x_{ij} = 1\ \forall i,\qquad \sum_i x_{ij} = 1\ \forall j,\qquad x_{ij} \ge 0</span></p>
<blockquote>
<p>💡 <strong>Ganzzahligkeit nicht fordern!</strong> Die Matrix ist total unimodular; ein LP-Solver liefert automatisch 0/1-Lösungen. Für reine Zuordnungen ist <code>scipy.optimize.linear_sum_assignment</code> (Ungarischer Algorithmus, <span class="math inline">O(n^3)</span>) noch deutlich schneller.</p>
</blockquote>
<h3 id="b24-subtour-eliminierung">B24 — Subtour-Eliminierung</h3>
<p><strong>MTZ (einfach, aber schwach):</strong> <span class="math display">u_i - u_j + C x_{ij} \le C - d_j \qquad \forall i\ne j</span></p>
<p><strong>Besser in der Praxis:</strong> <code>AddCircuit</code> in CP-SAT oder die Routing-Bibliothek von OR-Tools.</p>
<hr />
<h2 id="ein-wort-zur-auswahl">Ein Wort zur Auswahl</h2>
<p>Wenn mehrere Muster passen, entscheiden Sie nach dieser Reihenfolge:</p>
<ol type="1">
<li><strong>Gibt es ein globales Constraint dafür?</strong> (<code>AddAllDifferent</code>, <code>AddNoOverlap</code>, <code>AddCumulative</code>, <code>AddCircuit</code>) → nehmen Sie es. Es propagiert stärker und ist lesbarer.</li>
<li><strong>Kommt man ohne Big-M aus?</strong> (z. B. B3 statt B4) → ja, dann so.</li>
<li><strong>Muss es wirklich hart sein?</strong> → sonst B8/B18.</li>
<li><strong>Ist <span class="math inline">M</span> so klein wie möglich?</strong> → prüfen.</li>
</ol>
</article>
<button type="button" class="fortschritt-knopf" data-kapitel="anhang-modellierungsmuster.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="anhang-loesungen.html"><svg class="icon" aria-hidden="true"><use href="#icon-chevron-left"></use></svg><span><small>Zurück</small>Anhang A: Lösungen zu allen Übungsaufgaben</span></a><a class="prev-next-knopf prev-next-next" href="anhang-fehlerdiagnose.html"><span><small>Weiter</small>Anhang C: Fehlerdiagnose-Handbuch</span><svg class="icon" aria-hidden="true"><use href="#icon-chevron-right"></use></svg></a></nav>
</main>
</div>
<footer class="site-footer">
<p>© Dieter Schlüter · <a href="gesamtdokument.html">Gesamtdokument</a> ·
<a href="programme.html">Beispielprogramme</a></p>
</footer>
<script defer src="assets/search-index.js"></script>
<script defer src="assets/programme.js"></script>
<script defer src="assets/site.js"></script>
</body>
</html>