Phase 8.2: Solver-Isolation ohne subprocess-Codestrings
Setzt den Isolationsteil von Paket 1 aus Verbesserungen_02.md um. Der Plan
nannte zwei Programme; beim Suchen kam ein drittes dazu, das dasselbe Muster
verwendete.
Ein_System_Vier_Ansaetze.py und Benchmark_Skalierung.py hielten ihre vier
Solvervarianten als Zeichenketten in einem Dictionary und gaben sie an
"python -c" weiter - bei Benchmark_Skalierung.py sogar mit
.format()-Platzhaltern fuer die Instanzgroesse. Aus jeder Variante ist jetzt
eine gewoehnliche Funktion mit lokalem Import geworden.
Solverwechsel_CPSAT_HiGHS.py rief sich selbst ueber sys.argv erneut auf;
auch das entfaellt.
Ausgefuehrt wird ueber einen ProcessPoolExecutor mit zwei Einstellungen, die
beide noetig sind: mp_context "spawn" (frischer Interpreter statt geerbtem
Speicher - unter Linux ist fork der Standard) und max_tasks_per_child=1 (ein
neuer Prozess je Aufgabe; ohne das verwendet der Pool seinen Arbeiter
wieder, und beim zweiten Solver ist der Konflikt zurueck). Nachgemessen:
vier Aufgaben, vier verschiedene PIDs.
Der zweite Punkt hat einen eigenen Warnkasten bekommen, weil der Fehler
leicht zu machen und schwer zu finden ist: Der Absturz kaeme nicht beim
ersten Solver, sondern beim zweiten - und saehe aus wie ein Problem des
zweiten.
Regel 4, dreifach geprueft. Ein_System_Vier_Ansaetze.py: identisch bis auf
die Zeitspalte, einschliesslich der Spannweite 2,41e-08, auf die sich der
Merksatz des Kapitels beruft. Benchmark_Skalierung.py: alle zwoelf
Zielwerte und alle drei Spannweiten bitgleich; Zeiten und Speicher haben
sich verschoben, beide sind im Abdruck seit jeher als hardwareabhaengig
gekennzeichnet. Solverwechsel_CPSAT_HiGHS.py: Ausgabe ohne Zeiten
unveraendert.
Bewusst subprocess bleibt Mutationstest.py: Dort wird pytest auf einer
mutierten Kopie in einem temporaeren Verzeichnis gestartet - ein externes
Werkzeug auf veraenderten Dateien, nicht die Isolation eines Imports.
Neu im Kapitel Oekosystem: ein Abschnitt "Wie die Isolation aussieht, wenn
sie tragen soll" - warum ein Codestring die schlechteste Umsetzung von
"eigener Prozess" ist. Anhang C nennt jetzt ebenfalls ProcessPoolExecutor.
Ein eigener Fehler, gefunden und abgesichert: Ich hatte dem neuen ### ein
{#sec:...}-Label gegeben. ABSCHNITT_RE erkennt nur "## " - das Label waere
nie registriert worden und jeder Verweis darauf ins Leere gelaufen, ohne
Warnung. Label entfernt, --check meldet den Fall jetzt. Gegengetestet.
Stand: 818 Querverweise, 76 Programme, 33 pytest-Tests, PDF 760 Seiten, 69
netzfreie Programme fehlerfrei.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
9c83716095
commit
862e92bc7b
29 changed files with 2401 additions and 1912 deletions
|
|
@ -523,6 +523,7 @@
|
|||
</ul></li>
|
||||
<li><a href="#sec:oekosystem-ein-system-vier-programmieransaetze" id="toc-sec:oekosystem-ein-system-vier-programmieransaetze">3.5 Ein System — vier Programmieransätze</a>
|
||||
<ul>
|
||||
<li><a href="#wie-die-isolation-aussieht-wenn-sie-tragen-soll" id="toc-wie-die-isolation-aussieht-wenn-sie-tragen-soll">Wie die Isolation aussieht, wenn sie tragen soll</a></li>
|
||||
<li><a href="#was-das-csr-format-bedeutet" id="toc-was-das-csr-format-bedeutet">Was das CSR-Format bedeutet</a></li>
|
||||
</ul></li>
|
||||
<li><a href="#sec:oekosystem-wann-lohnt-sich-welche-ebene" id="toc-sec:oekosystem-wann-lohnt-sich-welche-ebene">3.6 Wann lohnt sich welche Ebene?</a></li>
|
||||
|
|
@ -5892,6 +5893,35 @@ Weizen 0.750 kg, Soja 0.250 kg -> 0.5350 EUR/kg</code></pre>
|
|||
<p><strong>Abhilfe:</strong> Jeden Solver in einem <strong>eigenen Prozess</strong> ausführen — genau das tut das folgende Programm. Alternativ: getrennte virtuelle Umgebungen, oder auf <code>highspy</code> verzichten und HiGHS über <code>scipy.optimize.linprog</code> bzw. CVXPY ansprechen (dort ist es ohnehin als Backend verfügbar).</p>
|
||||
<p>Der Installationstest im Vorspann umgeht die Falle bereits: Er lädt <code>ortools</code> zuerst, prüft <code>highspy</code> und <code>cvxpy</code> in der Paketübersicht nur auf Anwesenheit (<code>importlib.util.find_spec</code>) und importiert CVXPY erst im Funktionstest.</p>
|
||||
</blockquote>
|
||||
<h3 id="wie-die-isolation-aussieht-wenn-sie-tragen-soll">Wie die Isolation aussieht, wenn sie tragen soll</h3>
|
||||
<p>„Eigener Prozess” ist schnell gesagt. Die naheliegende Umsetzung — ein Codeschnipsel als Zeichenkette an <code>python -c</code> übergeben — funktioniert und ist trotzdem die schlechteste: Der Schnipsel ist für Editor, Linter und Testwerkzeug unsichtbar, ein Tippfehler darin fällt erst zur Laufzeit auf, und übergeben lassen sich nur Zeichenketten.</p>
|
||||
<p>Tragfähig ist stattdessen: <strong>jeder Solver eine gewöhnliche Funktion mit lokalem Import</strong>, ausgeführt von einem <code>ProcessPoolExecutor</code> mit zwei Einstellungen, die zusammen die Garantie ergeben:</p>
|
||||
<table>
|
||||
<colgroup>
|
||||
<col style="width: 50%" />
|
||||
<col style="width: 50%" />
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr class="header">
|
||||
<th>Einstellung</th>
|
||||
<th>Wozu</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="odd">
|
||||
<td><code>mp_context=multiprocessing.get_context("spawn")</code></td>
|
||||
<td>Der Kindprozess startet mit einem <strong>frischen</strong> Interpreter, statt den Speicher des Elternprozesses zu erben. Unter Linux ist <code>fork</code> der Standard — und damit wäre alles, was hier schon importiert ist, auch dort importiert.</td>
|
||||
</tr>
|
||||
<tr class="even">
|
||||
<td><code>max_tasks_per_child=1</code></td>
|
||||
<td>Jede Aufgabe bekommt einen <strong>neuen</strong> Prozess. Ohne das verwendet der Pool seinen Arbeiter wieder, und beim zweiten Solver ist der Konflikt zurück. Genau dieser Fehler ist leicht zu machen und schwer zu finden.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<blockquote>
|
||||
<p><strong>⚠️ <code>max_tasks_per_child=1</code> ist nicht optional</strong> Ein Pool ohne diese Angabe ist der <strong>Normalfall</strong> — er soll seine Arbeiter ja wiederverwenden. Wer die Isolation über einen Pool herstellt und das vergisst, hat einen Prozesswechsel programmiert, aber keine Isolation gewonnen: Die zweite Aufgabe landet im selben Interpreter wie die erste. Der Absturz kommt dann nicht beim ersten Solver, sondern beim zweiten — und sieht aus wie ein Problem des zweiten.</p>
|
||||
</blockquote>
|
||||
<p>Denselben Aufbau verwenden <code>Solverwechsel_CPSAT_HiGHS.py</code> (<a href="#kap-praxisfallen">Kapitel 22</a>) und <code>Benchmark_Skalierung.py</code> (<a href="#kap-testing">Kapitel 23</a>). Dort wandern zusätzlich <strong>Datenobjekte</strong> über die Prozessgrenze statt Zeichenketten — möglich, weil Domänenmodell und Lösungs-DTO keinen Solver kennen (<a href="#sec:praxisfallen-or-kern">Abschnitt 22.6</a>).</p>
|
||||
<div class="sourceCode" id="cb34"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb34-1"><a href="#cb34-1" aria-hidden="true" tabindex="-1"></a><span class="co">#!/usr/bin/env python3</span></span>
|
||||
<span id="cb34-2"><a href="#cb34-2" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb34-3"><a href="#cb34-3" aria-hidden="true" tabindex="-1"></a><span class="co"># Ein_System_Vier_Ansaetze.py</span></span>
|
||||
|
|
@ -5902,132 +5932,157 @@ Weizen 0.750 kg, Soja 0.250 kg -> 0.5350 EUR/kg</code></pre>
|
|||
<span id="cb34-8"><a href="#cb34-8" aria-hidden="true" tabindex="-1"></a><span class="co"> 2*x1 + 3*x2 + x3 <= 50</span></span>
|
||||
<span id="cb34-9"><a href="#cb34-9" aria-hidden="true" tabindex="-1"></a><span class="co"> x >= 0</span></span>
|
||||
<span id="cb34-10"><a href="#cb34-10" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb34-11"><a href="#cb34-11" aria-hidden="true" tabindex="-1"></a><span class="co">Deckt scipy.optimize, highspy, CVXPY und OR-Tools/GLOP ab, mit Kreuzvergleich am Ende.</span></span>
|
||||
<span id="cb34-12"><a href="#cb34-12" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb34-13"><a href="#cb34-13" aria-hidden="true" tabindex="-1"></a><span class="co">WICHTIG: Jeder Solver läuft in einem EIGENEN Prozess, weil sich ortools und</span></span>
|
||||
<span id="cb34-14"><a href="#cb34-14" aria-hidden="true" tabindex="-1"></a><span class="co">highspy auf vielen Systemen nicht gemeinsam importieren lassen (beide bringen</span></span>
|
||||
<span id="cb34-15"><a href="#cb34-15" aria-hidden="true" tabindex="-1"></a><span class="co">eine eigene HiGHS-Kopie mit -> Symbolkonflikt).</span></span>
|
||||
<span id="cb34-16"><a href="#cb34-16" aria-hidden="true" tabindex="-1"></a><span class="co">"""</span></span>
|
||||
<span id="cb34-11"><a href="#cb34-11" aria-hidden="true" tabindex="-1"></a><span class="co">Deckt scipy.optimize, highspy, CVXPY und OR-Tools/GLOP ab, mit Kreuzvergleich</span></span>
|
||||
<span id="cb34-12"><a href="#cb34-12" aria-hidden="true" tabindex="-1"></a><span class="co">am Ende.</span></span>
|
||||
<span id="cb34-13"><a href="#cb34-13" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb34-14"><a href="#cb34-14" aria-hidden="true" tabindex="-1"></a><span class="co">WICHTIG: Jeder Solver laeuft in einem EIGENEN Prozess, weil sich ortools und</span></span>
|
||||
<span id="cb34-15"><a href="#cb34-15" aria-hidden="true" tabindex="-1"></a><span class="co">highspy auf vielen Systemen nicht gemeinsam importieren lassen (beide bringen</span></span>
|
||||
<span id="cb34-16"><a href="#cb34-16" aria-hidden="true" tabindex="-1"></a><span class="co">eine eigene HiGHS-Kopie mit -> Symbolkonflikt).</span></span>
|
||||
<span id="cb34-17"><a href="#cb34-17" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb34-18"><a href="#cb34-18" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> json</span>
|
||||
<span id="cb34-19"><a href="#cb34-19" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> subprocess</span>
|
||||
<span id="cb34-20"><a href="#cb34-20" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> sys</span>
|
||||
<span id="cb34-21"><a href="#cb34-21" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> textwrap</span>
|
||||
<span id="cb34-22"><a href="#cb34-22" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> time</span>
|
||||
<span id="cb34-23"><a href="#cb34-23" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb34-24"><a href="#cb34-24" aria-hidden="true" tabindex="-1"></a>ERWARTET <span class="op">=</span> <span class="fl">530.0</span> <span class="co"># Ergebnis der Handrechnung zum Produktionsprogramm</span></span>
|
||||
<span id="cb34-25"><a href="#cb34-25" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb34-26"><a href="#cb34-26" aria-hidden="true" tabindex="-1"></a><span class="co"># Jeder Eintrag ist ein eigenständiges Miniprogramm, das sein Ergebnis als</span></span>
|
||||
<span id="cb34-27"><a href="#cb34-27" aria-hidden="true" tabindex="-1"></a><span class="co"># JSON auf stdout ausgibt. So bleibt jeder Import in seinem eigenen Prozess.</span></span>
|
||||
<span id="cb34-28"><a href="#cb34-28" aria-hidden="true" tabindex="-1"></a>ANSAETZE: <span class="bu">dict</span>[<span class="bu">str</span>, <span class="bu">str</span>] <span class="op">=</span> {</span>
|
||||
<span id="cb34-29"><a href="#cb34-29" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb34-30"><a href="#cb34-30" aria-hidden="true" tabindex="-1"></a> <span class="st">"scipy.optimize.linprog"</span>: <span class="st">"""</span></span>
|
||||
<span id="cb34-31"><a href="#cb34-31" aria-hidden="true" tabindex="-1"></a><span class="st"> from scipy.optimize import linprog</span></span>
|
||||
<span id="cb34-32"><a href="#cb34-32" aria-hidden="true" tabindex="-1"></a><span class="st"> res = linprog(c=[-10.0, -15.0, -25.0], # linprog MINIMIERT -> negieren</span></span>
|
||||
<span id="cb34-33"><a href="#cb34-33" aria-hidden="true" tabindex="-1"></a><span class="st"> A_ub=[[1, 1, 2], [2, 3, 1]], b_ub=[40, 50],</span></span>
|
||||
<span id="cb34-34"><a href="#cb34-34" aria-hidden="true" tabindex="-1"></a><span class="st"> bounds=[(0, None)] * 3, method="highs")</span></span>
|
||||
<span id="cb34-35"><a href="#cb34-35" aria-hidden="true" tabindex="-1"></a><span class="st"> ausgabe = (-res.fun, list(res.x))</span></span>
|
||||
<span id="cb34-36"><a href="#cb34-36" aria-hidden="true" tabindex="-1"></a><span class="st"> """</span>,</span>
|
||||
<span id="cb34-18"><a href="#cb34-18" aria-hidden="true" tabindex="-1"></a><span class="co">Die Isolation besorgt ein ProcessPoolExecutor. Drei Einstellungen ergeben</span></span>
|
||||
<span id="cb34-19"><a href="#cb34-19" aria-hidden="true" tabindex="-1"></a><span class="co">zusammen die Garantie:</span></span>
|
||||
<span id="cb34-20"><a href="#cb34-20" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb34-21"><a href="#cb34-21" aria-hidden="true" tabindex="-1"></a><span class="co"> mp_context "spawn" Der Kindprozess startet mit einem FRISCHEN</span></span>
|
||||
<span id="cb34-22"><a href="#cb34-22" aria-hidden="true" tabindex="-1"></a><span class="co"> Interpreter, statt den Speicher des Elternprozesses</span></span>
|
||||
<span id="cb34-23"><a href="#cb34-23" aria-hidden="true" tabindex="-1"></a><span class="co"> zu erben. Was hier schon importiert ist, ist dort</span></span>
|
||||
<span id="cb34-24"><a href="#cb34-24" aria-hidden="true" tabindex="-1"></a><span class="co"> nicht importiert. Mit dem Standard "fork" auf Linux</span></span>
|
||||
<span id="cb34-25"><a href="#cb34-25" aria-hidden="true" tabindex="-1"></a><span class="co"> waere das nicht so.</span></span>
|
||||
<span id="cb34-26"><a href="#cb34-26" aria-hidden="true" tabindex="-1"></a><span class="co"> max_tasks_per_child=1 Jede Aufgabe bekommt einen NEUEN Prozess. Ohne das</span></span>
|
||||
<span id="cb34-27"><a href="#cb34-27" aria-hidden="true" tabindex="-1"></a><span class="co"> wuerde der Pool seinen Arbeiter wiederverwenden - und</span></span>
|
||||
<span id="cb34-28"><a href="#cb34-28" aria-hidden="true" tabindex="-1"></a><span class="co"> beim zweiten Solver waere der Konflikt zurueck.</span></span>
|
||||
<span id="cb34-29"><a href="#cb34-29" aria-hidden="true" tabindex="-1"></a><span class="co"> max_workers=1 Haelt die vier Laeufe nacheinander. Nicht aus</span></span>
|
||||
<span id="cb34-30"><a href="#cb34-30" aria-hidden="true" tabindex="-1"></a><span class="co"> Vorsicht, sondern damit die gemessenen Zeiten</span></span>
|
||||
<span id="cb34-31"><a href="#cb34-31" aria-hidden="true" tabindex="-1"></a><span class="co"> vergleichbar bleiben.</span></span>
|
||||
<span id="cb34-32"><a href="#cb34-32" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb34-33"><a href="#cb34-33" aria-hidden="true" tabindex="-1"></a><span class="co">Jeder Solver steht in einer eigenen Funktion mit LOKALEM Import. Das ist der</span></span>
|
||||
<span id="cb34-34"><a href="#cb34-34" aria-hidden="true" tabindex="-1"></a><span class="co">Unterschied zu einem Codestring, den man an 'python -c' uebergibt: Die</span></span>
|
||||
<span id="cb34-35"><a href="#cb34-35" aria-hidden="true" tabindex="-1"></a><span class="co">Funktion laesst sich einzeln aufrufen, testen und vom Editor pruefen - ein</span></span>
|
||||
<span id="cb34-36"><a href="#cb34-36" aria-hidden="true" tabindex="-1"></a><span class="co">String nicht.</span></span>
|
||||
<span id="cb34-37"><a href="#cb34-37" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb34-38"><a href="#cb34-38" aria-hidden="true" tabindex="-1"></a> <span class="st">"highspy (natives HiGHS)"</span>: <span class="st">"""</span></span>
|
||||
<span id="cb34-39"><a href="#cb34-39" aria-hidden="true" tabindex="-1"></a><span class="st"> import numpy as np, highspy</span></span>
|
||||
<span id="cb34-40"><a href="#cb34-40" aria-hidden="true" tabindex="-1"></a><span class="st"> h = highspy.Highs()</span></span>
|
||||
<span id="cb34-41"><a href="#cb34-41" aria-hidden="true" tabindex="-1"></a><span class="st"> h.setOptionValue("output_flag", False)</span></span>
|
||||
<span id="cb34-42"><a href="#cb34-42" aria-hidden="true" tabindex="-1"></a><span class="st"> h.addVars(3, np.zeros(3), np.full(3, highspy.kHighsInf))</span></span>
|
||||
<span id="cb34-43"><a href="#cb34-43" aria-hidden="true" tabindex="-1"></a><span class="st"> h.changeObjectiveSense(highspy.ObjSense.kMaximize)</span></span>
|
||||
<span id="cb34-44"><a href="#cb34-44" aria-hidden="true" tabindex="-1"></a><span class="st"> for j, wert in enumerate([10.0, 15.0, 25.0]):</span></span>
|
||||
<span id="cb34-45"><a href="#cb34-45" aria-hidden="true" tabindex="-1"></a><span class="st"> h.changeColCost(j, wert)</span></span>
|
||||
<span id="cb34-46"><a href="#cb34-46" aria-hidden="true" tabindex="-1"></a><span class="st"> # CSR-Format: starts[i] = Beginn von Zeile i in indices/values</span></span>
|
||||
<span id="cb34-47"><a href="#cb34-47" aria-hidden="true" tabindex="-1"></a><span class="st"> h.addRows(2, np.full(2, -highspy.kHighsInf), np.array([40.0, 50.0]), 6,</span></span>
|
||||
<span id="cb34-48"><a href="#cb34-48" aria-hidden="true" tabindex="-1"></a><span class="st"> np.array([0, 3], dtype=np.int32),</span></span>
|
||||
<span id="cb34-49"><a href="#cb34-49" aria-hidden="true" tabindex="-1"></a><span class="st"> np.array([0, 1, 2, 0, 1, 2], dtype=np.int32),</span></span>
|
||||
<span id="cb34-50"><a href="#cb34-50" aria-hidden="true" tabindex="-1"></a><span class="st"> np.array([1.0, 1.0, 2.0, 2.0, 3.0, 1.0]))</span></span>
|
||||
<span id="cb34-51"><a href="#cb34-51" aria-hidden="true" tabindex="-1"></a><span class="st"> h.run()</span></span>
|
||||
<span id="cb34-52"><a href="#cb34-52" aria-hidden="true" tabindex="-1"></a><span class="st"> ausgabe = (h.getInfo().objective_function_value,</span></span>
|
||||
<span id="cb34-53"><a href="#cb34-53" aria-hidden="true" tabindex="-1"></a><span class="st"> list(h.getSolution().col_value[:3]))</span></span>
|
||||
<span id="cb34-54"><a href="#cb34-54" aria-hidden="true" tabindex="-1"></a><span class="st"> """</span>,</span>
|
||||
<span id="cb34-55"><a href="#cb34-55" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb34-56"><a href="#cb34-56" aria-hidden="true" tabindex="-1"></a> <span class="st">"cvxpy"</span>: <span class="st">"""</span></span>
|
||||
<span id="cb34-57"><a href="#cb34-57" aria-hidden="true" tabindex="-1"></a><span class="st"> import numpy as np, cvxpy as cp</span></span>
|
||||
<span id="cb34-58"><a href="#cb34-58" aria-hidden="true" tabindex="-1"></a><span class="st"> x = cp.Variable(3, nonneg=True)</span></span>
|
||||
<span id="cb34-59"><a href="#cb34-59" aria-hidden="true" tabindex="-1"></a><span class="st"> problem = cp.Problem(cp.Maximize(np.array([10.0, 15.0, 25.0]) @ x),</span></span>
|
||||
<span id="cb34-60"><a href="#cb34-60" aria-hidden="true" tabindex="-1"></a><span class="st"> [np.array([[1, 1, 2], [2, 3, 1]]) @ x <= np.array([40, 50])])</span></span>
|
||||
<span id="cb34-61"><a href="#cb34-61" aria-hidden="true" tabindex="-1"></a><span class="st"> problem.solve()</span></span>
|
||||
<span id="cb34-62"><a href="#cb34-62" aria-hidden="true" tabindex="-1"></a><span class="st"> ausgabe = (float(problem.value), [float(v) for v in x.value])</span></span>
|
||||
<span id="cb34-63"><a href="#cb34-63" aria-hidden="true" tabindex="-1"></a><span class="st"> """</span>,</span>
|
||||
<span id="cb34-64"><a href="#cb34-64" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb34-65"><a href="#cb34-65" aria-hidden="true" tabindex="-1"></a> <span class="st">"ortools / GLOP"</span>: <span class="st">"""</span></span>
|
||||
<span id="cb34-66"><a href="#cb34-66" aria-hidden="true" tabindex="-1"></a><span class="st"> from ortools.linear_solver import pywraplp</span></span>
|
||||
<span id="cb34-67"><a href="#cb34-67" aria-hidden="true" tabindex="-1"></a><span class="st"> s = pywraplp.Solver.CreateSolver("GLOP")</span></span>
|
||||
<span id="cb34-68"><a href="#cb34-68" aria-hidden="true" tabindex="-1"></a><span class="st"> x = [s.NumVar(0, s.infinity(), f"x{j+1}") for j in range(3)]</span></span>
|
||||
<span id="cb34-69"><a href="#cb34-69" aria-hidden="true" tabindex="-1"></a><span class="st"> A = [[1, 1, 2], [2, 3, 1]]</span></span>
|
||||
<span id="cb34-70"><a href="#cb34-70" aria-hidden="true" tabindex="-1"></a><span class="st"> for i, kap in enumerate([40, 50]):</span></span>
|
||||
<span id="cb34-71"><a href="#cb34-71" aria-hidden="true" tabindex="-1"></a><span class="st"> s.Add(sum(A[i][j] * x[j] for j in range(3)) <= kap)</span></span>
|
||||
<span id="cb34-72"><a href="#cb34-72" aria-hidden="true" tabindex="-1"></a><span class="st"> s.Maximize(10 * x[0] + 15 * x[1] + 25 * x[2])</span></span>
|
||||
<span id="cb34-73"><a href="#cb34-73" aria-hidden="true" tabindex="-1"></a><span class="st"> s.Solve()</span></span>
|
||||
<span id="cb34-74"><a href="#cb34-74" aria-hidden="true" tabindex="-1"></a><span class="st"> ausgabe = (s.Objective().Value(), [v.solution_value() for v in x])</span></span>
|
||||
<span id="cb34-75"><a href="#cb34-75" aria-hidden="true" tabindex="-1"></a><span class="st"> """</span>,</span>
|
||||
<span id="cb34-76"><a href="#cb34-76" aria-hidden="true" tabindex="-1"></a>}</span>
|
||||
<span id="cb34-77"><a href="#cb34-77" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb34-38"><a href="#cb34-38" aria-hidden="true" tabindex="-1"></a><span class="co">Benoetigt: scipy, highspy, cvxpy, ortools</span></span>
|
||||
<span id="cb34-39"><a href="#cb34-39" aria-hidden="true" tabindex="-1"></a><span class="co">"""</span></span>
|
||||
<span id="cb34-40"><a href="#cb34-40" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb34-41"><a href="#cb34-41" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> multiprocessing</span>
|
||||
<span id="cb34-42"><a href="#cb34-42" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> time</span>
|
||||
<span id="cb34-43"><a href="#cb34-43" aria-hidden="true" tabindex="-1"></a><span class="im">from</span> concurrent.futures <span class="im">import</span> ProcessPoolExecutor</span>
|
||||
<span id="cb34-44"><a href="#cb34-44" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb34-45"><a href="#cb34-45" aria-hidden="true" tabindex="-1"></a>ERWARTET <span class="op">=</span> <span class="fl">530.0</span> <span class="co"># Ergebnis der Handrechnung zum Produktionsprogramm</span></span>
|
||||
<span id="cb34-46"><a href="#cb34-46" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb34-47"><a href="#cb34-47" aria-hidden="true" tabindex="-1"></a><span class="co"># Die Instanz - einmal notiert, von allen vier Funktionen benutzt.</span></span>
|
||||
<span id="cb34-48"><a href="#cb34-48" aria-hidden="true" tabindex="-1"></a>ZIEL <span class="op">=</span> [<span class="fl">10.0</span>, <span class="fl">15.0</span>, <span class="fl">25.0</span>]</span>
|
||||
<span id="cb34-49"><a href="#cb34-49" aria-hidden="true" tabindex="-1"></a>MATRIX <span class="op">=</span> [[<span class="dv">1</span>, <span class="dv">1</span>, <span class="dv">2</span>], [<span class="dv">2</span>, <span class="dv">3</span>, <span class="dv">1</span>]]</span>
|
||||
<span id="cb34-50"><a href="#cb34-50" aria-hidden="true" tabindex="-1"></a>KAPAZITAET <span class="op">=</span> [<span class="fl">40.0</span>, <span class="fl">50.0</span>]</span>
|
||||
<span id="cb34-51"><a href="#cb34-51" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb34-52"><a href="#cb34-52" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb34-53"><a href="#cb34-53" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> loese_mit_scipy() <span class="op">-></span> <span class="bu">tuple</span>[<span class="bu">float</span>, <span class="bu">list</span>[<span class="bu">float</span>]]:</span>
|
||||
<span id="cb34-54"><a href="#cb34-54" aria-hidden="true" tabindex="-1"></a> <span class="im">from</span> scipy.optimize <span class="im">import</span> linprog</span>
|
||||
<span id="cb34-55"><a href="#cb34-55" aria-hidden="true" tabindex="-1"></a> ergebnis <span class="op">=</span> linprog(c<span class="op">=</span>[<span class="op">-</span>w <span class="cf">for</span> w <span class="kw">in</span> ZIEL], <span class="co"># linprog MINIMIERT -> negieren</span></span>
|
||||
<span id="cb34-56"><a href="#cb34-56" aria-hidden="true" tabindex="-1"></a> A_ub<span class="op">=</span>MATRIX, b_ub<span class="op">=</span>KAPAZITAET,</span>
|
||||
<span id="cb34-57"><a href="#cb34-57" aria-hidden="true" tabindex="-1"></a> bounds<span class="op">=</span>[(<span class="dv">0</span>, <span class="va">None</span>)] <span class="op">*</span> <span class="dv">3</span>, method<span class="op">=</span><span class="st">"highs"</span>)</span>
|
||||
<span id="cb34-58"><a href="#cb34-58" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> <span class="op">-</span>ergebnis.fun, <span class="bu">list</span>(ergebnis.x)</span>
|
||||
<span id="cb34-59"><a href="#cb34-59" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb34-60"><a href="#cb34-60" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb34-61"><a href="#cb34-61" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> loese_mit_highspy() <span class="op">-></span> <span class="bu">tuple</span>[<span class="bu">float</span>, <span class="bu">list</span>[<span class="bu">float</span>]]:</span>
|
||||
<span id="cb34-62"><a href="#cb34-62" aria-hidden="true" tabindex="-1"></a> <span class="im">import</span> highspy</span>
|
||||
<span id="cb34-63"><a href="#cb34-63" aria-hidden="true" tabindex="-1"></a> <span class="im">import</span> numpy <span class="im">as</span> np</span>
|
||||
<span id="cb34-64"><a href="#cb34-64" aria-hidden="true" tabindex="-1"></a> h <span class="op">=</span> highspy.Highs()</span>
|
||||
<span id="cb34-65"><a href="#cb34-65" aria-hidden="true" tabindex="-1"></a> h.setOptionValue(<span class="st">"output_flag"</span>, <span class="va">False</span>)</span>
|
||||
<span id="cb34-66"><a href="#cb34-66" aria-hidden="true" tabindex="-1"></a> h.addVars(<span class="dv">3</span>, np.zeros(<span class="dv">3</span>), np.full(<span class="dv">3</span>, highspy.kHighsInf))</span>
|
||||
<span id="cb34-67"><a href="#cb34-67" aria-hidden="true" tabindex="-1"></a> h.changeObjectiveSense(highspy.ObjSense.kMaximize)</span>
|
||||
<span id="cb34-68"><a href="#cb34-68" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> j, wert <span class="kw">in</span> <span class="bu">enumerate</span>(ZIEL):</span>
|
||||
<span id="cb34-69"><a href="#cb34-69" aria-hidden="true" tabindex="-1"></a> h.changeColCost(j, wert)</span>
|
||||
<span id="cb34-70"><a href="#cb34-70" aria-hidden="true" tabindex="-1"></a> <span class="co"># CSR-Format: starts[i] = Beginn von Zeile i in indices/values</span></span>
|
||||
<span id="cb34-71"><a href="#cb34-71" aria-hidden="true" tabindex="-1"></a> h.addRows(<span class="dv">2</span>, np.full(<span class="dv">2</span>, <span class="op">-</span>highspy.kHighsInf), np.array(KAPAZITAET), <span class="dv">6</span>,</span>
|
||||
<span id="cb34-72"><a href="#cb34-72" aria-hidden="true" tabindex="-1"></a> np.array([<span class="dv">0</span>, <span class="dv">3</span>], dtype<span class="op">=</span>np.int32),</span>
|
||||
<span id="cb34-73"><a href="#cb34-73" aria-hidden="true" tabindex="-1"></a> np.array([<span class="dv">0</span>, <span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">0</span>, <span class="dv">1</span>, <span class="dv">2</span>], dtype<span class="op">=</span>np.int32),</span>
|
||||
<span id="cb34-74"><a href="#cb34-74" aria-hidden="true" tabindex="-1"></a> np.array([<span class="bu">float</span>(w) <span class="cf">for</span> zeile <span class="kw">in</span> MATRIX <span class="cf">for</span> w <span class="kw">in</span> zeile]))</span>
|
||||
<span id="cb34-75"><a href="#cb34-75" aria-hidden="true" tabindex="-1"></a> h.run()</span>
|
||||
<span id="cb34-76"><a href="#cb34-76" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> (h.getInfo().objective_function_value,</span>
|
||||
<span id="cb34-77"><a href="#cb34-77" aria-hidden="true" tabindex="-1"></a> <span class="bu">list</span>(h.getSolution().col_value[:<span class="dv">3</span>]))</span>
|
||||
<span id="cb34-78"><a href="#cb34-78" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb34-79"><a href="#cb34-79" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> fuehre_in_eigenem_prozess_aus(quelltext: <span class="bu">str</span>) <span class="op">-></span> <span class="bu">tuple</span>[<span class="bu">float</span>, <span class="bu">list</span>[<span class="bu">float</span>]]:</span>
|
||||
<span id="cb34-80"><a href="#cb34-80" aria-hidden="true" tabindex="-1"></a> <span class="co">"""Startet den Codeschnipsel als separaten Python-Prozess und liest das Ergebnis."""</span></span>
|
||||
<span id="cb34-81"><a href="#cb34-81" aria-hidden="true" tabindex="-1"></a> programm <span class="op">=</span> textwrap.dedent(quelltext) <span class="op">+</span> <span class="st">"</span><span class="ch">\n</span><span class="st">import json; print(json.dumps(ausgabe))</span><span class="ch">\n</span><span class="st">"</span></span>
|
||||
<span id="cb34-82"><a href="#cb34-82" aria-hidden="true" tabindex="-1"></a> ergebnis <span class="op">=</span> subprocess.run([sys.executable, <span class="st">"-c"</span>, programm],</span>
|
||||
<span id="cb34-83"><a href="#cb34-83" aria-hidden="true" tabindex="-1"></a> capture_output<span class="op">=</span><span class="va">True</span>, text<span class="op">=</span><span class="va">True</span>, timeout<span class="op">=</span><span class="dv">120</span>)</span>
|
||||
<span id="cb34-84"><a href="#cb34-84" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> ergebnis.returncode <span class="op">!=</span> <span class="dv">0</span>:</span>
|
||||
<span id="cb34-85"><a href="#cb34-85" aria-hidden="true" tabindex="-1"></a> <span class="cf">raise</span> <span class="pp">RuntimeError</span>(ergebnis.stderr.strip().splitlines()[<span class="op">-</span><span class="dv">1</span>])</span>
|
||||
<span id="cb34-86"><a href="#cb34-86" aria-hidden="true" tabindex="-1"></a> wert, loesung <span class="op">=</span> json.loads(ergebnis.stdout.strip().splitlines()[<span class="op">-</span><span class="dv">1</span>])</span>
|
||||
<span id="cb34-87"><a href="#cb34-87" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> wert, loesung</span>
|
||||
<span id="cb34-79"><a href="#cb34-79" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb34-80"><a href="#cb34-80" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> loese_mit_cvxpy() <span class="op">-></span> <span class="bu">tuple</span>[<span class="bu">float</span>, <span class="bu">list</span>[<span class="bu">float</span>]]:</span>
|
||||
<span id="cb34-81"><a href="#cb34-81" aria-hidden="true" tabindex="-1"></a> <span class="im">import</span> cvxpy <span class="im">as</span> cp</span>
|
||||
<span id="cb34-82"><a href="#cb34-82" aria-hidden="true" tabindex="-1"></a> <span class="im">import</span> numpy <span class="im">as</span> np</span>
|
||||
<span id="cb34-83"><a href="#cb34-83" aria-hidden="true" tabindex="-1"></a> x <span class="op">=</span> cp.Variable(<span class="dv">3</span>, nonneg<span class="op">=</span><span class="va">True</span>)</span>
|
||||
<span id="cb34-84"><a href="#cb34-84" aria-hidden="true" tabindex="-1"></a> problem <span class="op">=</span> cp.Problem(cp.Maximize(np.array(ZIEL) <span class="op">@</span> x),</span>
|
||||
<span id="cb34-85"><a href="#cb34-85" aria-hidden="true" tabindex="-1"></a> [np.array(MATRIX) <span class="op">@</span> x <span class="op"><=</span> np.array(KAPAZITAET)])</span>
|
||||
<span id="cb34-86"><a href="#cb34-86" aria-hidden="true" tabindex="-1"></a> problem.solve()</span>
|
||||
<span id="cb34-87"><a href="#cb34-87" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> <span class="bu">float</span>(problem.value), [<span class="bu">float</span>(v) <span class="cf">for</span> v <span class="kw">in</span> x.value]</span>
|
||||
<span id="cb34-88"><a href="#cb34-88" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb34-89"><a href="#cb34-89" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb34-90"><a href="#cb34-90" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">"__main__"</span>:</span>
|
||||
<span id="cb34-91"><a href="#cb34-91" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"="</span> <span class="op">*</span> <span class="dv">78</span>)</span>
|
||||
<span id="cb34-92"><a href="#cb34-92" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" EIN SYSTEM - VIER ANSAETZE (je eigener Prozess)"</span>)</span>
|
||||
<span id="cb34-93"><a href="#cb34-93" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"="</span> <span class="op">*</span> <span class="dv">78</span>)</span>
|
||||
<span id="cb34-94"><a href="#cb34-94" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f"</span><span class="sc">{</span><span class="st">'Bibliothek'</span><span class="sc">:<26}</span><span class="ss"> </span><span class="sc">{</span><span class="st">'Z*'</span><span class="sc">:>10}</span><span class="ss"> </span><span class="sc">{</span><span class="st">'x1'</span><span class="sc">:>7}</span><span class="ss"> </span><span class="sc">{</span><span class="st">'x2'</span><span class="sc">:>7}</span><span class="ss"> </span><span class="sc">{</span><span class="st">'x3'</span><span class="sc">:>7}</span><span class="ss"> </span><span class="sc">{</span><span class="st">'Zeit'</span><span class="sc">:>10}</span><span class="ss">"</span>)</span>
|
||||
<span id="cb34-95"><a href="#cb34-95" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"-"</span> <span class="op">*</span> <span class="dv">78</span>)</span>
|
||||
<span id="cb34-96"><a href="#cb34-96" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb34-97"><a href="#cb34-97" aria-hidden="true" tabindex="-1"></a> werte <span class="op">=</span> []</span>
|
||||
<span id="cb34-98"><a href="#cb34-98" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> name, quelltext <span class="kw">in</span> ANSAETZE.items():</span>
|
||||
<span id="cb34-99"><a href="#cb34-99" aria-hidden="true" tabindex="-1"></a> t0 <span class="op">=</span> time.perf_counter()</span>
|
||||
<span id="cb34-100"><a href="#cb34-100" aria-hidden="true" tabindex="-1"></a> <span class="cf">try</span>:</span>
|
||||
<span id="cb34-101"><a href="#cb34-101" aria-hidden="true" tabindex="-1"></a> wert, x <span class="op">=</span> fuehre_in_eigenem_prozess_aus(quelltext)</span>
|
||||
<span id="cb34-102"><a href="#cb34-102" aria-hidden="true" tabindex="-1"></a> <span class="cf">except</span> <span class="pp">RuntimeError</span> <span class="im">as</span> fehler:</span>
|
||||
<span id="cb34-103"><a href="#cb34-103" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f"</span><span class="sc">{</span>name<span class="sc">:<26}</span><span class="ss"> nicht verfuegbar: </span><span class="sc">{</span>fehler[:<span class="dv">40</span>]<span class="sc">}</span><span class="ss">"</span>)</span>
|
||||
<span id="cb34-104"><a href="#cb34-104" aria-hidden="true" tabindex="-1"></a> <span class="cf">continue</span></span>
|
||||
<span id="cb34-105"><a href="#cb34-105" aria-hidden="true" tabindex="-1"></a> dauer <span class="op">=</span> time.perf_counter() <span class="op">-</span> t0</span>
|
||||
<span id="cb34-106"><a href="#cb34-106" aria-hidden="true" tabindex="-1"></a> werte.append(wert)</span>
|
||||
<span id="cb34-107"><a href="#cb34-107" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f"</span><span class="sc">{</span>name<span class="sc">:<26}</span><span class="ss"> </span><span class="sc">{</span>wert<span class="sc">:>10.2f}</span><span class="ss"> </span><span class="sc">{</span>x[<span class="dv">0</span>]<span class="sc">:>7.2f}</span><span class="ss"> </span><span class="sc">{</span>x[<span class="dv">1</span>]<span class="sc">:>7.2f}</span><span class="ss"> </span><span class="sc">{</span>x[<span class="dv">2</span>]<span class="sc">:>7.2f}</span><span class="ss"> "</span></span>
|
||||
<span id="cb34-108"><a href="#cb34-108" aria-hidden="true" tabindex="-1"></a> <span class="ss">f"</span><span class="sc">{</span>dauer<span class="sc">:>8.2f}</span><span class="ss"> s"</span>)</span>
|
||||
<span id="cb34-109"><a href="#cb34-109" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb34-110"><a href="#cb34-110" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"-"</span> <span class="op">*</span> <span class="dv">78</span>)</span>
|
||||
<span id="cb34-111"><a href="#cb34-111" aria-hidden="true" tabindex="-1"></a> spanne <span class="op">=</span> <span class="bu">max</span>(werte) <span class="op">-</span> <span class="bu">min</span>(werte)</span>
|
||||
<span id="cb34-112"><a href="#cb34-112" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f"Spannweite zwischen den Bibliotheken: </span><span class="sc">{</span>spanne<span class="sc">:.2e}</span><span class="ss">"</span>)</span>
|
||||
<span id="cb34-113"><a href="#cb34-113" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f"Abweichung zur Handrechnung (</span><span class="sc">{</span>ERWARTET<span class="sc">:.0f}</span><span class="ss">): "</span></span>
|
||||
<span id="cb34-114"><a href="#cb34-114" aria-hidden="true" tabindex="-1"></a> <span class="ss">f"</span><span class="sc">{</span><span class="bu">abs</span>(werte[<span class="dv">0</span>] <span class="op">-</span> ERWARTET)<span class="sc">:.2e}</span><span class="ss">"</span>)</span>
|
||||
<span id="cb34-115"><a href="#cb34-115" aria-hidden="true" tabindex="-1"></a> <span class="cf">assert</span> spanne <span class="op"><</span> <span class="fl">1e-6</span>, <span class="st">"Die Bibliotheken widersprechen sich!"</span></span>
|
||||
<span id="cb34-116"><a href="#cb34-116" aria-hidden="true" tabindex="-1"></a> <span class="cf">assert</span> <span class="bu">abs</span>(werte[<span class="dv">0</span>] <span class="op">-</span> ERWARTET) <span class="op"><</span> <span class="fl">1e-6</span>, <span class="st">"Ergebnis weicht von der Handrechnung ab!"</span></span>
|
||||
<span id="cb34-117"><a href="#cb34-117" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"Alle Wege fuehren zum selben, von Hand bestaetigten Optimum."</span>)</span>
|
||||
<span id="cb34-118"><a href="#cb34-118" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"(Die Zeiten enthalten den Prozessstart und den Import - sie messen"</span>)</span>
|
||||
<span id="cb34-119"><a href="#cb34-119" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" NICHT die reine Solverleistung, siehe Uebung 3.5.)"</span>)</span>
|
||||
<span id="cb34-120"><a href="#cb34-120" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"="</span> <span class="op">*</span> <span class="dv">78</span>)</span></code></pre></div>
|
||||
<span id="cb34-90"><a href="#cb34-90" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> loese_mit_ortools() <span class="op">-></span> <span class="bu">tuple</span>[<span class="bu">float</span>, <span class="bu">list</span>[<span class="bu">float</span>]]:</span>
|
||||
<span id="cb34-91"><a href="#cb34-91" aria-hidden="true" tabindex="-1"></a> <span class="im">from</span> ortools.linear_solver <span class="im">import</span> pywraplp</span>
|
||||
<span id="cb34-92"><a href="#cb34-92" aria-hidden="true" tabindex="-1"></a> s <span class="op">=</span> pywraplp.Solver.CreateSolver(<span class="st">"GLOP"</span>)</span>
|
||||
<span id="cb34-93"><a href="#cb34-93" aria-hidden="true" tabindex="-1"></a> x <span class="op">=</span> [s.NumVar(<span class="dv">0</span>, s.infinity(), <span class="ss">f"x</span><span class="sc">{</span>j<span class="op">+</span><span class="dv">1</span><span class="sc">}</span><span class="ss">"</span>) <span class="cf">for</span> j <span class="kw">in</span> <span class="bu">range</span>(<span class="dv">3</span>)]</span>
|
||||
<span id="cb34-94"><a href="#cb34-94" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> i, kapazitaet <span class="kw">in</span> <span class="bu">enumerate</span>(KAPAZITAET):</span>
|
||||
<span id="cb34-95"><a href="#cb34-95" aria-hidden="true" tabindex="-1"></a> s.Add(<span class="bu">sum</span>(MATRIX[i][j] <span class="op">*</span> x[j] <span class="cf">for</span> j <span class="kw">in</span> <span class="bu">range</span>(<span class="dv">3</span>)) <span class="op"><=</span> kapazitaet)</span>
|
||||
<span id="cb34-96"><a href="#cb34-96" aria-hidden="true" tabindex="-1"></a> s.Maximize(<span class="bu">sum</span>(ZIEL[j] <span class="op">*</span> x[j] <span class="cf">for</span> j <span class="kw">in</span> <span class="bu">range</span>(<span class="dv">3</span>)))</span>
|
||||
<span id="cb34-97"><a href="#cb34-97" aria-hidden="true" tabindex="-1"></a> s.Solve()</span>
|
||||
<span id="cb34-98"><a href="#cb34-98" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> s.Objective().Value(), [v.solution_value() <span class="cf">for</span> v <span class="kw">in</span> x]</span>
|
||||
<span id="cb34-99"><a href="#cb34-99" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb34-100"><a href="#cb34-100" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb34-101"><a href="#cb34-101" aria-hidden="true" tabindex="-1"></a>ANSAETZE <span class="op">=</span> {</span>
|
||||
<span id="cb34-102"><a href="#cb34-102" aria-hidden="true" tabindex="-1"></a> <span class="st">"scipy.optimize.linprog"</span>: loese_mit_scipy,</span>
|
||||
<span id="cb34-103"><a href="#cb34-103" aria-hidden="true" tabindex="-1"></a> <span class="st">"highspy (natives HiGHS)"</span>: loese_mit_highspy,</span>
|
||||
<span id="cb34-104"><a href="#cb34-104" aria-hidden="true" tabindex="-1"></a> <span class="st">"cvxpy"</span>: loese_mit_cvxpy,</span>
|
||||
<span id="cb34-105"><a href="#cb34-105" aria-hidden="true" tabindex="-1"></a> <span class="st">"ortools / GLOP"</span>: loese_mit_ortools,</span>
|
||||
<span id="cb34-106"><a href="#cb34-106" aria-hidden="true" tabindex="-1"></a>}</span>
|
||||
<span id="cb34-107"><a href="#cb34-107" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb34-108"><a href="#cb34-108" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb34-109"><a href="#cb34-109" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">"__main__"</span>:</span>
|
||||
<span id="cb34-110"><a href="#cb34-110" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"="</span> <span class="op">*</span> <span class="dv">78</span>)</span>
|
||||
<span id="cb34-111"><a href="#cb34-111" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" EIN SYSTEM - VIER ANSAETZE (je eigener Prozess)"</span>)</span>
|
||||
<span id="cb34-112"><a href="#cb34-112" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"="</span> <span class="op">*</span> <span class="dv">78</span>)</span>
|
||||
<span id="cb34-113"><a href="#cb34-113" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f"</span><span class="sc">{</span><span class="st">'Bibliothek'</span><span class="sc">:<26}</span><span class="ss"> </span><span class="sc">{</span><span class="st">'Z*'</span><span class="sc">:>10}</span><span class="ss"> </span><span class="sc">{</span><span class="st">'x1'</span><span class="sc">:>7}</span><span class="ss"> </span><span class="sc">{</span><span class="st">'x2'</span><span class="sc">:>7}</span><span class="ss"> </span><span class="sc">{</span><span class="st">'x3'</span><span class="sc">:>7}</span><span class="ss"> </span><span class="sc">{</span><span class="st">'Zeit'</span><span class="sc">:>10}</span><span class="ss">"</span>)</span>
|
||||
<span id="cb34-114"><a href="#cb34-114" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"-"</span> <span class="op">*</span> <span class="dv">78</span>)</span>
|
||||
<span id="cb34-115"><a href="#cb34-115" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb34-116"><a href="#cb34-116" aria-hidden="true" tabindex="-1"></a> werte <span class="op">=</span> []</span>
|
||||
<span id="cb34-117"><a href="#cb34-117" aria-hidden="true" tabindex="-1"></a> <span class="co"># Ein Pool, vier Aufgaben, vier frische Prozesse. Der Kontext muss</span></span>
|
||||
<span id="cb34-118"><a href="#cb34-118" aria-hidden="true" tabindex="-1"></a> <span class="co"># "spawn" sein - siehe Modulkommentar.</span></span>
|
||||
<span id="cb34-119"><a href="#cb34-119" aria-hidden="true" tabindex="-1"></a> <span class="cf">with</span> ProcessPoolExecutor(</span>
|
||||
<span id="cb34-120"><a href="#cb34-120" aria-hidden="true" tabindex="-1"></a> max_workers<span class="op">=</span><span class="dv">1</span>,</span>
|
||||
<span id="cb34-121"><a href="#cb34-121" aria-hidden="true" tabindex="-1"></a> mp_context<span class="op">=</span>multiprocessing.get_context(<span class="st">"spawn"</span>),</span>
|
||||
<span id="cb34-122"><a href="#cb34-122" aria-hidden="true" tabindex="-1"></a> max_tasks_per_child<span class="op">=</span><span class="dv">1</span>) <span class="im">as</span> pool:</span>
|
||||
<span id="cb34-123"><a href="#cb34-123" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> name, funktion <span class="kw">in</span> ANSAETZE.items():</span>
|
||||
<span id="cb34-124"><a href="#cb34-124" aria-hidden="true" tabindex="-1"></a> beginn <span class="op">=</span> time.perf_counter()</span>
|
||||
<span id="cb34-125"><a href="#cb34-125" aria-hidden="true" tabindex="-1"></a> <span class="cf">try</span>:</span>
|
||||
<span id="cb34-126"><a href="#cb34-126" aria-hidden="true" tabindex="-1"></a> wert, x <span class="op">=</span> pool.submit(funktion).result(timeout<span class="op">=</span><span class="dv">120</span>)</span>
|
||||
<span id="cb34-127"><a href="#cb34-127" aria-hidden="true" tabindex="-1"></a> <span class="cf">except</span> <span class="pp">Exception</span> <span class="im">as</span> fehler: <span class="co"># Bibliothek fehlt o. Ae.</span></span>
|
||||
<span id="cb34-128"><a href="#cb34-128" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f"</span><span class="sc">{</span>name<span class="sc">:<26}</span><span class="ss"> nicht verfuegbar: </span><span class="sc">{</span><span class="bu">str</span>(fehler)[:<span class="dv">40</span>]<span class="sc">}</span><span class="ss">"</span>)</span>
|
||||
<span id="cb34-129"><a href="#cb34-129" aria-hidden="true" tabindex="-1"></a> <span class="cf">continue</span></span>
|
||||
<span id="cb34-130"><a href="#cb34-130" aria-hidden="true" tabindex="-1"></a> dauer <span class="op">=</span> time.perf_counter() <span class="op">-</span> beginn</span>
|
||||
<span id="cb34-131"><a href="#cb34-131" aria-hidden="true" tabindex="-1"></a> werte.append(wert)</span>
|
||||
<span id="cb34-132"><a href="#cb34-132" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f"</span><span class="sc">{</span>name<span class="sc">:<26}</span><span class="ss"> </span><span class="sc">{</span>wert<span class="sc">:>10.2f}</span><span class="ss"> </span><span class="sc">{</span>x[<span class="dv">0</span>]<span class="sc">:>7.2f}</span><span class="ss"> </span><span class="sc">{</span>x[<span class="dv">1</span>]<span class="sc">:>7.2f}</span><span class="ss"> </span><span class="sc">{</span>x[<span class="dv">2</span>]<span class="sc">:>7.2f}</span><span class="ss"> "</span></span>
|
||||
<span id="cb34-133"><a href="#cb34-133" aria-hidden="true" tabindex="-1"></a> <span class="ss">f"</span><span class="sc">{</span>dauer<span class="sc">:>8.2f}</span><span class="ss"> s"</span>)</span>
|
||||
<span id="cb34-134"><a href="#cb34-134" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb34-135"><a href="#cb34-135" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"-"</span> <span class="op">*</span> <span class="dv">78</span>)</span>
|
||||
<span id="cb34-136"><a href="#cb34-136" aria-hidden="true" tabindex="-1"></a> spanne <span class="op">=</span> <span class="bu">max</span>(werte) <span class="op">-</span> <span class="bu">min</span>(werte)</span>
|
||||
<span id="cb34-137"><a href="#cb34-137" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f"Spannweite zwischen den Bibliotheken: </span><span class="sc">{</span>spanne<span class="sc">:.2e}</span><span class="ss">"</span>)</span>
|
||||
<span id="cb34-138"><a href="#cb34-138" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f"Abweichung zur Handrechnung (</span><span class="sc">{</span>ERWARTET<span class="sc">:.0f}</span><span class="ss">): "</span></span>
|
||||
<span id="cb34-139"><a href="#cb34-139" aria-hidden="true" tabindex="-1"></a> <span class="ss">f"</span><span class="sc">{</span><span class="bu">abs</span>(werte[<span class="dv">0</span>] <span class="op">-</span> ERWARTET)<span class="sc">:.2e}</span><span class="ss">"</span>)</span>
|
||||
<span id="cb34-140"><a href="#cb34-140" aria-hidden="true" tabindex="-1"></a> <span class="cf">assert</span> spanne <span class="op"><</span> <span class="fl">1e-6</span>, <span class="st">"Die Bibliotheken widersprechen sich!"</span></span>
|
||||
<span id="cb34-141"><a href="#cb34-141" aria-hidden="true" tabindex="-1"></a> <span class="cf">assert</span> <span class="bu">abs</span>(werte[<span class="dv">0</span>] <span class="op">-</span> ERWARTET) <span class="op"><</span> <span class="fl">1e-6</span>, <span class="st">"Ergebnis weicht von der Handrechnung ab!"</span></span>
|
||||
<span id="cb34-142"><a href="#cb34-142" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"Alle Wege fuehren zum selben, von Hand bestaetigten Optimum."</span>)</span>
|
||||
<span id="cb34-143"><a href="#cb34-143" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"(Die Zeiten enthalten Prozessstart und Import - sie messen NICHT die"</span>)</span>
|
||||
<span id="cb34-144"><a href="#cb34-144" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" reine Solverleistung. Die Uebungsaufgabe 'Laufzeitvergleich' trennt beides.)"</span>)</span>
|
||||
<span id="cb34-145"><a href="#cb34-145" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"="</span> <span class="op">*</span> <span class="dv">78</span>)</span></code></pre></div>
|
||||
<p><strong>Erwartete Ausgabe (Zeiten hardwareabhängig):</strong></p>
|
||||
<pre><code>==============================================================================
|
||||
EIN SYSTEM - VIER ANSAETZE (je eigener Prozess)
|
||||
==============================================================================
|
||||
Bibliothek Z* x1 x2 x3 Zeit
|
||||
------------------------------------------------------------------------------
|
||||
scipy.optimize.linprog 530.00 0.00 12.00 14.00 0.55 s
|
||||
highspy (natives HiGHS) 530.00 0.00 12.00 14.00 0.17 s
|
||||
cvxpy 530.00 0.00 12.00 14.00 1.52 s
|
||||
ortools / GLOP 530.00 0.00 12.00 14.00 0.09 s
|
||||
scipy.optimize.linprog 530.00 0.00 12.00 14.00 0.59 s
|
||||
highspy (natives HiGHS) 530.00 0.00 12.00 14.00 0.12 s
|
||||
cvxpy 530.00 0.00 12.00 14.00 1.24 s
|
||||
ortools / GLOP 530.00 0.00 12.00 14.00 0.33 s
|
||||
------------------------------------------------------------------------------
|
||||
Spannweite zwischen den Bibliotheken: 2.41e-08
|
||||
Abweichung zur Handrechnung (530): 0.00e+00
|
||||
Alle Wege fuehren zum selben, von Hand bestaetigten Optimum.
|
||||
(Die Zeiten enthalten den Prozessstart und den Import - sie messen
|
||||
NICHT die reine Solverleistung, siehe Uebung 3.5.)
|
||||
(Die Zeiten enthalten Prozessstart und Import - sie messen NICHT die
|
||||
reine Solverleistung. Die Uebungsaufgabe 'Laufzeitvergleich' trennt beides.)
|
||||
==============================================================================</code></pre>
|
||||
<blockquote>
|
||||
<p><strong>🎯 Merksatz zur Spannweite</strong> Die vier Bibliotheken stimmen <strong>nicht auf die letzte Stelle</strong> überein, sondern nur bis auf <span class="math inline">2{,}4 \times 10^{-8}</span>. Das ist normal: Solver arbeiten mit endlicher Genauigkeit und brechen ab, sobald ihre eigene Toleranz erreicht ist. <strong>Vergleichen Sie Solver-Ergebnisse deshalb nie mit <code>==</code></strong>, sondern immer mit einer Toleranz — <code>abs(a - b) < 1e-6</code> oder <code>np.isclose()</code>. Wer auf exakte Gleichheit prüft, baut sich Tests, die zufällig mal bestehen und mal nicht.</p>
|
||||
|
|
@ -27339,9 +27394,9 @@ Domaenenschicht.
|
|||
<span id="cb213-36"><a href="#cb213-36" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb213-37"><a href="#cb213-37" aria-hidden="true" tabindex="-1"></a><span class="im">from</span> __future__ <span class="im">import</span> annotations</span>
|
||||
<span id="cb213-38"><a href="#cb213-38" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb213-39"><a href="#cb213-39" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> subprocess</span>
|
||||
<span id="cb213-40"><a href="#cb213-40" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> sys</span>
|
||||
<span id="cb213-41"><a href="#cb213-41" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> time</span>
|
||||
<span id="cb213-39"><a href="#cb213-39" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> multiprocessing</span>
|
||||
<span id="cb213-40"><a href="#cb213-40" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> time</span>
|
||||
<span id="cb213-41"><a href="#cb213-41" aria-hidden="true" tabindex="-1"></a><span class="im">from</span> concurrent.futures <span class="im">import</span> ProcessPoolExecutor</span>
|
||||
<span id="cb213-42"><a href="#cb213-42" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb213-43"><a href="#cb213-43" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> numpy <span class="im">as</span> np</span>
|
||||
<span id="cb213-44"><a href="#cb213-44" aria-hidden="true" tabindex="-1"></a><span class="im">from</span> pydantic <span class="im">import</span> BaseModel, Field, model_validator</span>
|
||||
|
|
@ -27544,83 +27599,87 @@ Domaenenschicht.
|
|||
<span id="cb213-241"><a href="#cb213-241" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> <span class="bu">any</span>(loesung.werte[problem.schluessel(i, j)] <span class="op">></span> <span class="fl">0.5</span> <span class="cf">for</span> j <span class="kw">in</span> <span class="bu">range</span>(m))]</span>
|
||||
<span id="cb213-242"><a href="#cb213-242" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb213-243"><a href="#cb213-243" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb213-244"><a href="#cb213-244" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> loese_in_eigenem_prozess(name: <span class="bu">str</span>) <span class="op">-></span> Loesung:</span>
|
||||
<span id="cb213-245"><a href="#cb213-245" aria-hidden="true" tabindex="-1"></a> <span class="co">"""Startet dieses Programm noch einmal - mit genau einem Solverimport."""</span></span>
|
||||
<span id="cb213-246"><a href="#cb213-246" aria-hidden="true" tabindex="-1"></a> ergebnis <span class="op">=</span> subprocess.run([sys.executable, <span class="va">__file__</span>, name],</span>
|
||||
<span id="cb213-247"><a href="#cb213-247" aria-hidden="true" tabindex="-1"></a> capture_output<span class="op">=</span><span class="va">True</span>, text<span class="op">=</span><span class="va">True</span>, timeout<span class="op">=</span><span class="dv">300</span>)</span>
|
||||
<span id="cb213-248"><a href="#cb213-248" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> ergebnis.returncode <span class="op">!=</span> <span class="dv">0</span>:</span>
|
||||
<span id="cb213-249"><a href="#cb213-249" aria-hidden="true" tabindex="-1"></a> <span class="cf">raise</span> <span class="pp">RuntimeError</span>(ergebnis.stderr.strip().splitlines()[<span class="op">-</span><span class="dv">1</span>])</span>
|
||||
<span id="cb213-250"><a href="#cb213-250" aria-hidden="true" tabindex="-1"></a> <span class="co"># Das DTO als JSON - genau dafuer ist ein Datenobjekt ohne Solverbezug gut.</span></span>
|
||||
<span id="cb213-251"><a href="#cb213-251" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> Loesung.model_validate_json(ergebnis.stdout.strip().splitlines()[<span class="op">-</span><span class="dv">1</span>])</span>
|
||||
<span id="cb213-244"><a href="#cb213-244" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> loese_in_eigenem_prozess(name: <span class="bu">str</span>, problem: Standortproblem) <span class="op">-></span> Loesung:</span>
|
||||
<span id="cb213-245"><a href="#cb213-245" aria-hidden="true" tabindex="-1"></a> <span class="co">"""Laesst genau einen Modellbauer in einem frischen Prozess rechnen.</span></span>
|
||||
<span id="cb213-246"><a href="#cb213-246" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb213-247"><a href="#cb213-247" aria-hidden="true" tabindex="-1"></a><span class="co"> 'spawn' statt des Linux-Standards 'fork': Der Kindprozess startet mit</span></span>
|
||||
<span id="cb213-248"><a href="#cb213-248" aria-hidden="true" tabindex="-1"></a><span class="co"> einem leeren Interpreter und importiert nur den Solver, den SEIN</span></span>
|
||||
<span id="cb213-249"><a href="#cb213-249" aria-hidden="true" tabindex="-1"></a><span class="co"> Modellbauer braucht. max_tasks_per_child=1 sorgt dafuer, dass der Pool</span></span>
|
||||
<span id="cb213-250"><a href="#cb213-250" aria-hidden="true" tabindex="-1"></a><span class="co"> seinen Arbeiter nicht wiederverwendet - sonst saessen beim zweiten Aufruf</span></span>
|
||||
<span id="cb213-251"><a href="#cb213-251" aria-hidden="true" tabindex="-1"></a><span class="co"> wieder beide Bibliotheken im selben Prozess.</span></span>
|
||||
<span id="cb213-252"><a href="#cb213-252" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb213-253"><a href="#cb213-253" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb213-254"><a href="#cb213-254" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">"__main__"</span>:</span>
|
||||
<span id="cb213-255"><a href="#cb213-255" aria-hidden="true" tabindex="-1"></a> problem <span class="op">=</span> beispielproblem()</span>
|
||||
<span id="cb213-256"><a href="#cb213-256" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb213-257"><a href="#cb213-257" aria-hidden="true" tabindex="-1"></a> <span class="co"># --- Kindprozess: rechnen und das DTO als JSON ausgeben ---------------</span></span>
|
||||
<span id="cb213-258"><a href="#cb213-258" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> <span class="bu">len</span>(sys.argv) <span class="op">></span> <span class="dv">1</span>:</span>
|
||||
<span id="cb213-259"><a href="#cb213-259" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(MODELLBAUER[sys.argv[<span class="dv">1</span>]](problem).model_dump_json())</span>
|
||||
<span id="cb213-260"><a href="#cb213-260" aria-hidden="true" tabindex="-1"></a> sys.exit(<span class="dv">0</span>)</span>
|
||||
<span id="cb213-253"><a href="#cb213-253" aria-hidden="true" tabindex="-1"></a><span class="co"> Hin und zurueck wandert das Domaenenmodell bzw. das Loesungs-DTO. Beide</span></span>
|
||||
<span id="cb213-254"><a href="#cb213-254" aria-hidden="true" tabindex="-1"></a><span class="co"> kennen keinen Solver, sind also serialisierbar - genau dafuer sind sie da.</span></span>
|
||||
<span id="cb213-255"><a href="#cb213-255" aria-hidden="true" tabindex="-1"></a><span class="co"> """</span></span>
|
||||
<span id="cb213-256"><a href="#cb213-256" aria-hidden="true" tabindex="-1"></a> <span class="cf">with</span> ProcessPoolExecutor(</span>
|
||||
<span id="cb213-257"><a href="#cb213-257" aria-hidden="true" tabindex="-1"></a> max_workers<span class="op">=</span><span class="dv">1</span>,</span>
|
||||
<span id="cb213-258"><a href="#cb213-258" aria-hidden="true" tabindex="-1"></a> mp_context<span class="op">=</span>multiprocessing.get_context(<span class="st">"spawn"</span>),</span>
|
||||
<span id="cb213-259"><a href="#cb213-259" aria-hidden="true" tabindex="-1"></a> max_tasks_per_child<span class="op">=</span><span class="dv">1</span>) <span class="im">as</span> pool:</span>
|
||||
<span id="cb213-260"><a href="#cb213-260" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> pool.submit(MODELLBAUER[name], problem).result(timeout<span class="op">=</span><span class="dv">300</span>)</span>
|
||||
<span id="cb213-261"><a href="#cb213-261" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb213-262"><a href="#cb213-262" aria-hidden="true" tabindex="-1"></a> <span class="co"># --- Hauptprozess: beide Solver anstossen und vergleichen -------------</span></span>
|
||||
<span id="cb213-263"><a href="#cb213-263" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"="</span> <span class="op">*</span> <span class="dv">82</span>)</span>
|
||||
<span id="cb213-264"><a href="#cb213-264" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" DERSELBE FALL, ZWEI SOLVER - UND EIN AUSWERTUNGSCODE"</span>)</span>
|
||||
<span id="cb213-265"><a href="#cb213-265" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"="</span> <span class="op">*</span> <span class="dv">82</span>)</span>
|
||||
<span id="cb213-266"><a href="#cb213-266" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f"Standortplanung: </span><span class="sc">{</span><span class="bu">len</span>(problem.lager)<span class="sc">}</span><span class="ss"> moegliche Lager, "</span></span>
|
||||
<span id="cb213-267"><a href="#cb213-267" aria-hidden="true" tabindex="-1"></a> <span class="ss">f"</span><span class="sc">{</span><span class="bu">len</span>(problem.kunden)<span class="sc">}</span><span class="ss"> Kunden, </span><span class="sc">{</span><span class="bu">sum</span>(problem.bedarf)<span class="sc">}</span><span class="ss"> Paletten Bedarf."</span>)</span>
|
||||
<span id="cb213-268"><a href="#cb213-268" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f"Kapazitaet je Lager: </span><span class="sc">{</span>problem<span class="sc">.</span>kapazitaet[<span class="dv">0</span>]<span class="sc">}</span><span class="ss"> Paletten "</span></span>
|
||||
<span id="cb213-269"><a href="#cb213-269" aria-hidden="true" tabindex="-1"></a> <span class="ss">f"-> mindestens 3 Lager noetig.</span><span class="ch">\n</span><span class="ss">"</span>)</span>
|
||||
<span id="cb213-270"><a href="#cb213-270" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb213-271"><a href="#cb213-271" aria-hidden="true" tabindex="-1"></a> loesungen: <span class="bu">dict</span>[<span class="bu">str</span>, Loesung] <span class="op">=</span> {}</span>
|
||||
<span id="cb213-272"><a href="#cb213-272" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> name, beschriftung <span class="kw">in</span> [(<span class="st">"cpsat"</span>, <span class="st">"OR-Tools CP-SAT"</span>),</span>
|
||||
<span id="cb213-273"><a href="#cb213-273" aria-hidden="true" tabindex="-1"></a> (<span class="st">"highs"</span>, <span class="st">"HiGHS (highspy)"</span>)]:</span>
|
||||
<span id="cb213-274"><a href="#cb213-274" aria-hidden="true" tabindex="-1"></a> loesung <span class="op">=</span> loesungen[name] <span class="op">=</span> loese_in_eigenem_prozess(name)</span>
|
||||
<span id="cb213-275"><a href="#cb213-275" aria-hidden="true" tabindex="-1"></a> beanstandungen <span class="op">=</span> pruefe_zuordnung(problem, loesung)</span>
|
||||
<span id="cb213-276"><a href="#cb213-276" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb213-277"><a href="#cb213-277" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f"</span><span class="sc">{</span>beschriftung<span class="sc">}</span><span class="ss">"</span>)</span>
|
||||
<span id="cb213-278"><a href="#cb213-278" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f" </span><span class="sc">{</span>loesung<span class="sc">.</span>als_bericht()<span class="sc">}</span><span class="ss">"</span>)</span>
|
||||
<span id="cb213-279"><a href="#cb213-279" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f" eroeffnete Lager: </span><span class="sc">{</span><span class="st">', '</span><span class="sc">.</span>join(geoeffnete_lager(problem, loesung))<span class="sc">}</span><span class="ss">"</span>)</span>
|
||||
<span id="cb213-280"><a href="#cb213-280" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f" Abnahmepruefung: "</span></span>
|
||||
<span id="cb213-281"><a href="#cb213-281" aria-hidden="true" tabindex="-1"></a> <span class="ss">f"</span><span class="sc">{</span><span class="st">'bestanden'</span> <span class="cf">if</span> <span class="kw">not</span> beanstandungen <span class="cf">else</span> beanstandungen<span class="sc">}</span><span class="ss">"</span>)</span>
|
||||
<span id="cb213-282"><a href="#cb213-282" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb213-283"><a href="#cb213-283" aria-hidden="true" tabindex="-1"></a> <span class="co"># --- Was der Vergleich zeigt -----------------------------------------</span></span>
|
||||
<span id="cb213-284"><a href="#cb213-284" aria-hidden="true" tabindex="-1"></a> zielwerte <span class="op">=</span> [loesung.zielwert <span class="cf">for</span> loesung <span class="kw">in</span> loesungen.values()]</span>
|
||||
<span id="cb213-285"><a href="#cb213-285" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"-"</span> <span class="op">*</span> <span class="dv">82</span>)</span>
|
||||
<span id="cb213-286"><a href="#cb213-286" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f"Zielwertdifferenz: </span><span class="sc">{</span><span class="bu">abs</span>(zielwerte[<span class="dv">0</span>] <span class="op">-</span> zielwerte[<span class="dv">1</span>])<span class="sc">:.6f}</span><span class="ss"> EUR"</span>)</span>
|
||||
<span id="cb213-287"><a href="#cb213-287" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb213-288"><a href="#cb213-288" aria-hidden="true" tabindex="-1"></a> gleich_belegt <span class="op">=</span> <span class="bu">all</span>(</span>
|
||||
<span id="cb213-289"><a href="#cb213-289" aria-hidden="true" tabindex="-1"></a> <span class="bu">round</span>(loesungen[<span class="st">"cpsat"</span>].werte[s]) <span class="op">==</span> <span class="bu">round</span>(loesungen[<span class="st">"highs"</span>].werte[s])</span>
|
||||
<span id="cb213-290"><a href="#cb213-290" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> s <span class="kw">in</span> loesungen[<span class="st">"cpsat"</span>].werte)</span>
|
||||
<span id="cb213-291"><a href="#cb213-291" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f"Identische Zuordnung: </span><span class="sc">{</span><span class="st">'ja'</span> <span class="cf">if</span> gleich_belegt <span class="cf">else</span> <span class="st">'nein'</span><span class="sc">}</span><span class="ss">"</span>)</span>
|
||||
<span id="cb213-292"><a href="#cb213-292" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb213-293"><a href="#cb213-293" aria-hidden="true" tabindex="-1"></a> <span class="cf">assert</span> <span class="bu">abs</span>(zielwerte[<span class="dv">0</span>] <span class="op">-</span> zielwerte[<span class="dv">1</span>]) <span class="op"><</span> <span class="fl">0.5</span>, <span class="st">"Die Solver widersprechen sich!"</span></span>
|
||||
<span id="cb213-294"><a href="#cb213-294" aria-hidden="true" tabindex="-1"></a> <span class="cf">assert</span> <span class="bu">all</span>(l.status <span class="kw">is</span> SolverStatus.OPTIMAL <span class="cf">for</span> l <span class="kw">in</span> loesungen.values())</span>
|
||||
<span id="cb213-295"><a href="#cb213-295" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb213-296"><a href="#cb213-296" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"</span><span class="ch">\n</span><span class="st">"</span> <span class="op">+</span> <span class="st">"="</span> <span class="op">*</span> <span class="dv">82</span>)</span>
|
||||
<span id="cb213-297"><a href="#cb213-297" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" WAS DER WECHSEL GEKOSTET HAT"</span>)</span>
|
||||
<span id="cb213-298"><a href="#cb213-298" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"="</span> <span class="op">*</span> <span class="dv">82</span>)</span>
|
||||
<span id="cb213-299"><a href="#cb213-299" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"Ausgetauscht wurde EINE Funktion. Domaenenmodell, Abnahmepruefung und"</span>)</span>
|
||||
<span id="cb213-300"><a href="#cb213-300" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"Bericht sind woertlich dieselben - sie sehen den Solver nie."</span>)</span>
|
||||
<span id="cb213-301"><a href="#cb213-301" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>()</span>
|
||||
<span id="cb213-302"><a href="#cb213-302" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"Nicht umsonst ist der Wechsel trotzdem:"</span>)</span>
|
||||
<span id="cb213-303"><a href="#cb213-303" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" * CP-SAT rechnet ausschliesslich GANZZAHLIG. Alle Kosten sind hier"</span>)</span>
|
||||
<span id="cb213-304"><a href="#cb213-304" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" deshalb int. Wer in Euro und Cent rechnet, skaliert vorher auf Cent -"</span>)</span>
|
||||
<span id="cb213-305"><a href="#cb213-305" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" und muss das im Bericht wieder zuruecknehmen."</span>)</span>
|
||||
<span id="cb213-306"><a href="#cb213-306" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" * HiGHS braucht die Restriktionen als Matrixzeilen, CP-SAT nimmt sie"</span>)</span>
|
||||
<span id="cb213-307"><a href="#cb213-307" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" als Ausdruecke. Das ist der Grund, warum der HiGHS-Modellbauer"</span>)</span>
|
||||
<span id="cb213-308"><a href="#cb213-308" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" laenger ist, obwohl er dasselbe Modell beschreibt."</span>)</span>
|
||||
<span id="cb213-309"><a href="#cb213-309" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" * Beide Bibliotheken bringen eine eigene HiGHS-Kopie mit und lassen"</span>)</span>
|
||||
<span id="cb213-310"><a href="#cb213-310" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" sich nicht gemeinsam importieren - daher die zwei Prozesse."</span>)</span>
|
||||
<span id="cb213-311"><a href="#cb213-311" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>()</span>
|
||||
<span id="cb213-312"><a href="#cb213-312" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"Der Ertrag: Beide beweisen denselben optimalen Zielwert, und die"</span>)</span>
|
||||
<span id="cb213-313"><a href="#cb213-313" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"Entscheidung zwischen ihnen ist eine Frage der Laufzeit geworden -"</span>)</span>
|
||||
<span id="cb213-314"><a href="#cb213-314" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"nicht eine Frage, wie viel Code man neu schreiben muss."</span>)</span>
|
||||
<span id="cb213-262"><a href="#cb213-262" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb213-263"><a href="#cb213-263" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">"__main__"</span>:</span>
|
||||
<span id="cb213-264"><a href="#cb213-264" aria-hidden="true" tabindex="-1"></a> problem <span class="op">=</span> beispielproblem()</span>
|
||||
<span id="cb213-265"><a href="#cb213-265" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb213-266"><a href="#cb213-266" aria-hidden="true" tabindex="-1"></a> <span class="co"># --- Beide Solver anstossen und vergleichen ---------------------------</span></span>
|
||||
<span id="cb213-267"><a href="#cb213-267" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"="</span> <span class="op">*</span> <span class="dv">82</span>)</span>
|
||||
<span id="cb213-268"><a href="#cb213-268" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" DERSELBE FALL, ZWEI SOLVER - UND EIN AUSWERTUNGSCODE"</span>)</span>
|
||||
<span id="cb213-269"><a href="#cb213-269" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"="</span> <span class="op">*</span> <span class="dv">82</span>)</span>
|
||||
<span id="cb213-270"><a href="#cb213-270" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f"Standortplanung: </span><span class="sc">{</span><span class="bu">len</span>(problem.lager)<span class="sc">}</span><span class="ss"> moegliche Lager, "</span></span>
|
||||
<span id="cb213-271"><a href="#cb213-271" aria-hidden="true" tabindex="-1"></a> <span class="ss">f"</span><span class="sc">{</span><span class="bu">len</span>(problem.kunden)<span class="sc">}</span><span class="ss"> Kunden, </span><span class="sc">{</span><span class="bu">sum</span>(problem.bedarf)<span class="sc">}</span><span class="ss"> Paletten Bedarf."</span>)</span>
|
||||
<span id="cb213-272"><a href="#cb213-272" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f"Kapazitaet je Lager: </span><span class="sc">{</span>problem<span class="sc">.</span>kapazitaet[<span class="dv">0</span>]<span class="sc">}</span><span class="ss"> Paletten "</span></span>
|
||||
<span id="cb213-273"><a href="#cb213-273" aria-hidden="true" tabindex="-1"></a> <span class="ss">f"-> mindestens 3 Lager noetig.</span><span class="ch">\n</span><span class="ss">"</span>)</span>
|
||||
<span id="cb213-274"><a href="#cb213-274" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb213-275"><a href="#cb213-275" aria-hidden="true" tabindex="-1"></a> loesungen: <span class="bu">dict</span>[<span class="bu">str</span>, Loesung] <span class="op">=</span> {}</span>
|
||||
<span id="cb213-276"><a href="#cb213-276" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> name, beschriftung <span class="kw">in</span> [(<span class="st">"cpsat"</span>, <span class="st">"OR-Tools CP-SAT"</span>),</span>
|
||||
<span id="cb213-277"><a href="#cb213-277" aria-hidden="true" tabindex="-1"></a> (<span class="st">"highs"</span>, <span class="st">"HiGHS (highspy)"</span>)]:</span>
|
||||
<span id="cb213-278"><a href="#cb213-278" aria-hidden="true" tabindex="-1"></a> loesung <span class="op">=</span> loesungen[name] <span class="op">=</span> loese_in_eigenem_prozess(name, problem)</span>
|
||||
<span id="cb213-279"><a href="#cb213-279" aria-hidden="true" tabindex="-1"></a> beanstandungen <span class="op">=</span> pruefe_zuordnung(problem, loesung)</span>
|
||||
<span id="cb213-280"><a href="#cb213-280" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb213-281"><a href="#cb213-281" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f"</span><span class="sc">{</span>beschriftung<span class="sc">}</span><span class="ss">"</span>)</span>
|
||||
<span id="cb213-282"><a href="#cb213-282" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f" </span><span class="sc">{</span>loesung<span class="sc">.</span>als_bericht()<span class="sc">}</span><span class="ss">"</span>)</span>
|
||||
<span id="cb213-283"><a href="#cb213-283" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f" eroeffnete Lager: </span><span class="sc">{</span><span class="st">', '</span><span class="sc">.</span>join(geoeffnete_lager(problem, loesung))<span class="sc">}</span><span class="ss">"</span>)</span>
|
||||
<span id="cb213-284"><a href="#cb213-284" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f" Abnahmepruefung: "</span></span>
|
||||
<span id="cb213-285"><a href="#cb213-285" aria-hidden="true" tabindex="-1"></a> <span class="ss">f"</span><span class="sc">{</span><span class="st">'bestanden'</span> <span class="cf">if</span> <span class="kw">not</span> beanstandungen <span class="cf">else</span> beanstandungen<span class="sc">}</span><span class="ss">"</span>)</span>
|
||||
<span id="cb213-286"><a href="#cb213-286" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb213-287"><a href="#cb213-287" aria-hidden="true" tabindex="-1"></a> <span class="co"># --- Was der Vergleich zeigt -----------------------------------------</span></span>
|
||||
<span id="cb213-288"><a href="#cb213-288" aria-hidden="true" tabindex="-1"></a> zielwerte <span class="op">=</span> [loesung.zielwert <span class="cf">for</span> loesung <span class="kw">in</span> loesungen.values()]</span>
|
||||
<span id="cb213-289"><a href="#cb213-289" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"-"</span> <span class="op">*</span> <span class="dv">82</span>)</span>
|
||||
<span id="cb213-290"><a href="#cb213-290" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f"Zielwertdifferenz: </span><span class="sc">{</span><span class="bu">abs</span>(zielwerte[<span class="dv">0</span>] <span class="op">-</span> zielwerte[<span class="dv">1</span>])<span class="sc">:.6f}</span><span class="ss"> EUR"</span>)</span>
|
||||
<span id="cb213-291"><a href="#cb213-291" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb213-292"><a href="#cb213-292" aria-hidden="true" tabindex="-1"></a> gleich_belegt <span class="op">=</span> <span class="bu">all</span>(</span>
|
||||
<span id="cb213-293"><a href="#cb213-293" aria-hidden="true" tabindex="-1"></a> <span class="bu">round</span>(loesungen[<span class="st">"cpsat"</span>].werte[s]) <span class="op">==</span> <span class="bu">round</span>(loesungen[<span class="st">"highs"</span>].werte[s])</span>
|
||||
<span id="cb213-294"><a href="#cb213-294" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> s <span class="kw">in</span> loesungen[<span class="st">"cpsat"</span>].werte)</span>
|
||||
<span id="cb213-295"><a href="#cb213-295" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f"Identische Zuordnung: </span><span class="sc">{</span><span class="st">'ja'</span> <span class="cf">if</span> gleich_belegt <span class="cf">else</span> <span class="st">'nein'</span><span class="sc">}</span><span class="ss">"</span>)</span>
|
||||
<span id="cb213-296"><a href="#cb213-296" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb213-297"><a href="#cb213-297" aria-hidden="true" tabindex="-1"></a> <span class="cf">assert</span> <span class="bu">abs</span>(zielwerte[<span class="dv">0</span>] <span class="op">-</span> zielwerte[<span class="dv">1</span>]) <span class="op"><</span> <span class="fl">0.5</span>, <span class="st">"Die Solver widersprechen sich!"</span></span>
|
||||
<span id="cb213-298"><a href="#cb213-298" aria-hidden="true" tabindex="-1"></a> <span class="cf">assert</span> <span class="bu">all</span>(l.status <span class="kw">is</span> SolverStatus.OPTIMAL <span class="cf">for</span> l <span class="kw">in</span> loesungen.values())</span>
|
||||
<span id="cb213-299"><a href="#cb213-299" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb213-300"><a href="#cb213-300" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"</span><span class="ch">\n</span><span class="st">"</span> <span class="op">+</span> <span class="st">"="</span> <span class="op">*</span> <span class="dv">82</span>)</span>
|
||||
<span id="cb213-301"><a href="#cb213-301" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" WAS DER WECHSEL GEKOSTET HAT"</span>)</span>
|
||||
<span id="cb213-302"><a href="#cb213-302" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"="</span> <span class="op">*</span> <span class="dv">82</span>)</span>
|
||||
<span id="cb213-303"><a href="#cb213-303" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"Ausgetauscht wurde EINE Funktion. Domaenenmodell, Abnahmepruefung und"</span>)</span>
|
||||
<span id="cb213-304"><a href="#cb213-304" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"Bericht sind woertlich dieselben - sie sehen den Solver nie."</span>)</span>
|
||||
<span id="cb213-305"><a href="#cb213-305" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>()</span>
|
||||
<span id="cb213-306"><a href="#cb213-306" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"Nicht umsonst ist der Wechsel trotzdem:"</span>)</span>
|
||||
<span id="cb213-307"><a href="#cb213-307" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" * CP-SAT rechnet ausschliesslich GANZZAHLIG. Alle Kosten sind hier"</span>)</span>
|
||||
<span id="cb213-308"><a href="#cb213-308" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" deshalb int. Wer in Euro und Cent rechnet, skaliert vorher auf Cent -"</span>)</span>
|
||||
<span id="cb213-309"><a href="#cb213-309" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" und muss das im Bericht wieder zuruecknehmen."</span>)</span>
|
||||
<span id="cb213-310"><a href="#cb213-310" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" * HiGHS braucht die Restriktionen als Matrixzeilen, CP-SAT nimmt sie"</span>)</span>
|
||||
<span id="cb213-311"><a href="#cb213-311" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" als Ausdruecke. Das ist der Grund, warum der HiGHS-Modellbauer"</span>)</span>
|
||||
<span id="cb213-312"><a href="#cb213-312" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" laenger ist, obwohl er dasselbe Modell beschreibt."</span>)</span>
|
||||
<span id="cb213-313"><a href="#cb213-313" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" * Beide Bibliotheken bringen eine eigene HiGHS-Kopie mit und lassen"</span>)</span>
|
||||
<span id="cb213-314"><a href="#cb213-314" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" sich nicht gemeinsam importieren - daher die zwei Prozesse."</span>)</span>
|
||||
<span id="cb213-315"><a href="#cb213-315" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>()</span>
|
||||
<span id="cb213-316"><a href="#cb213-316" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"Verglichen wird deshalb der ZIELWERT, nicht der Plan: Gibt es mehrere"</span>)</span>
|
||||
<span id="cb213-317"><a href="#cb213-317" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"gleich teure Loesungen, darf jeder Solver eine andere davon liefern."</span>)</span>
|
||||
<span id="cb213-318"><a href="#cb213-318" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"Hier stimmen sie zufaellig ueberein - darauf zu testen waere trotzdem"</span>)</span>
|
||||
<span id="cb213-319"><a href="#cb213-319" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"ein unzuverlaessiger Test (siehe JobShop_Intervalle.py)."</span>)</span>
|
||||
<span id="cb213-320"><a href="#cb213-320" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"="</span> <span class="op">*</span> <span class="dv">82</span>)</span></code></pre></div>
|
||||
<span id="cb213-316"><a href="#cb213-316" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"Der Ertrag: Beide beweisen denselben optimalen Zielwert, und die"</span>)</span>
|
||||
<span id="cb213-317"><a href="#cb213-317" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"Entscheidung zwischen ihnen ist eine Frage der Laufzeit geworden -"</span>)</span>
|
||||
<span id="cb213-318"><a href="#cb213-318" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"nicht eine Frage, wie viel Code man neu schreiben muss."</span>)</span>
|
||||
<span id="cb213-319"><a href="#cb213-319" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>()</span>
|
||||
<span id="cb213-320"><a href="#cb213-320" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"Verglichen wird deshalb der ZIELWERT, nicht der Plan: Gibt es mehrere"</span>)</span>
|
||||
<span id="cb213-321"><a href="#cb213-321" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"gleich teure Loesungen, darf jeder Solver eine andere davon liefern."</span>)</span>
|
||||
<span id="cb213-322"><a href="#cb213-322" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"Hier stimmen sie zufaellig ueberein - darauf zu testen waere trotzdem"</span>)</span>
|
||||
<span id="cb213-323"><a href="#cb213-323" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"ein unzuverlaessiger Test (siehe JobShop_Intervalle.py)."</span>)</span>
|
||||
<span id="cb213-324"><a href="#cb213-324" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"="</span> <span class="op">*</span> <span class="dv">82</span>)</span></code></pre></div>
|
||||
<p><strong>Erwartete Ausgabe</strong> (Laufzeiten hardwareabhängig):</p>
|
||||
<pre><code>==================================================================================
|
||||
DERSELBE FALL, ZWEI SOLVER - UND EIN AUSWERTUNGSCODE
|
||||
|
|
@ -28834,173 +28893,184 @@ moeglichen Fehler. Was zaehlt, ist die LISTE der Ueberlebenden.
|
|||
<span id="cb225-33"><a href="#cb225-33" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb225-34"><a href="#cb225-34" aria-hidden="true" tabindex="-1"></a><span class="im">from</span> __future__ <span class="im">import</span> annotations</span>
|
||||
<span id="cb225-35"><a href="#cb225-35" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb225-36"><a href="#cb225-36" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> json</span>
|
||||
<span id="cb225-37"><a href="#cb225-37" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> subprocess</span>
|
||||
<span id="cb225-38"><a href="#cb225-38" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> sys</span>
|
||||
<span id="cb225-39"><a href="#cb225-39" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> textwrap</span>
|
||||
<span id="cb225-36"><a href="#cb225-36" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> multiprocessing</span>
|
||||
<span id="cb225-37"><a href="#cb225-37" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> resource</span>
|
||||
<span id="cb225-38"><a href="#cb225-38" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> time</span>
|
||||
<span id="cb225-39"><a href="#cb225-39" aria-hidden="true" tabindex="-1"></a><span class="im">from</span> concurrent.futures <span class="im">import</span> ProcessPoolExecutor</span>
|
||||
<span id="cb225-40"><a href="#cb225-40" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb225-41"><a href="#cb225-41" aria-hidden="true" tabindex="-1"></a>GROESSEN <span class="op">=</span> [(<span class="dv">10</span>, <span class="dv">10</span>), (<span class="dv">32</span>, <span class="dv">32</span>), (<span class="dv">100</span>, <span class="dv">100</span>)] <span class="co"># (Lager, Kunden) -> 100 / 1.024 / 10.000 Variablen</span></span>
|
||||
<span id="cb225-41"><a href="#cb225-41" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> numpy <span class="im">as</span> np</span>
|
||||
<span id="cb225-42"><a href="#cb225-42" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb225-43"><a href="#cb225-43" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb225-44"><a href="#cb225-44" aria-hidden="true" tabindex="-1"></a><span class="co"># Jeder Eintrag ist ein eigenstaendiges Programm: Instanz aufbauen, loesen,</span></span>
|
||||
<span id="cb225-45"><a href="#cb225-45" aria-hidden="true" tabindex="-1"></a><span class="co"># Ergebnis als JSON ausgeben. Die Instanz wird in jedem Kindprozess aus</span></span>
|
||||
<span id="cb225-46"><a href="#cb225-46" aria-hidden="true" tabindex="-1"></a><span class="co"># derselben Saat neu erzeugt - so reist nichts ueber die Prozessgrenze,</span></span>
|
||||
<span id="cb225-47"><a href="#cb225-47" aria-hidden="true" tabindex="-1"></a><span class="co"># was das Ergebnis verfaelschen koennte.</span></span>
|
||||
<span id="cb225-48"><a href="#cb225-48" aria-hidden="true" tabindex="-1"></a>VORSPANN <span class="op">=</span> <span class="st">"""</span></span>
|
||||
<span id="cb225-49"><a href="#cb225-49" aria-hidden="true" tabindex="-1"></a><span class="st">import json, time, resource</span></span>
|
||||
<span id="cb225-50"><a href="#cb225-50" aria-hidden="true" tabindex="-1"></a><span class="st">import numpy as np</span></span>
|
||||
<span id="cb225-51"><a href="#cb225-51" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb225-52"><a href="#cb225-52" aria-hidden="true" tabindex="-1"></a><span class="st">def instanz(m, n):</span></span>
|
||||
<span id="cb225-53"><a href="#cb225-53" aria-hidden="true" tabindex="-1"></a><span class="st"> rng = np.random.default_rng(20)</span></span>
|
||||
<span id="cb225-54"><a href="#cb225-54" aria-hidden="true" tabindex="-1"></a><span class="st"> kosten = rng.integers(5, 95, (m, n)).astype(float)</span></span>
|
||||
<span id="cb225-55"><a href="#cb225-55" aria-hidden="true" tabindex="-1"></a><span class="st"> angebot = rng.integers(50, 150, m).astype(float)</span></span>
|
||||
<span id="cb225-56"><a href="#cb225-56" aria-hidden="true" tabindex="-1"></a><span class="st"> bedarf = angebot.sum() * rng.dirichlet(np.ones(n))</span></span>
|
||||
<span id="cb225-57"><a href="#cb225-57" aria-hidden="true" tabindex="-1"></a><span class="st"> return kosten, angebot, bedarf</span></span>
|
||||
<span id="cb225-43"><a href="#cb225-43" aria-hidden="true" tabindex="-1"></a>GROESSEN <span class="op">=</span> [(<span class="dv">10</span>, <span class="dv">10</span>), (<span class="dv">32</span>, <span class="dv">32</span>), (<span class="dv">100</span>, <span class="dv">100</span>)] <span class="co"># (Lager, Kunden) -> 100 / 1.024 / 10.000 Variablen</span></span>
|
||||
<span id="cb225-44"><a href="#cb225-44" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb225-45"><a href="#cb225-45" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb225-46"><a href="#cb225-46" aria-hidden="true" tabindex="-1"></a><span class="co"># Instanz und Speichermessung stehen als gewoehnliche Funktionen hier - nicht</span></span>
|
||||
<span id="cb225-47"><a href="#cb225-47" aria-hidden="true" tabindex="-1"></a><span class="co"># in einem String, den ein Kindprozess ausfuehrt. Jede Messfunktion baut die</span></span>
|
||||
<span id="cb225-48"><a href="#cb225-48" aria-hidden="true" tabindex="-1"></a><span class="co"># Instanz aus derselben Saat neu auf, damit ueber die Prozessgrenze nichts</span></span>
|
||||
<span id="cb225-49"><a href="#cb225-49" aria-hidden="true" tabindex="-1"></a><span class="co"># reist, was das Ergebnis verfaelschen koennte.</span></span>
|
||||
<span id="cb225-50"><a href="#cb225-50" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb225-51"><a href="#cb225-51" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> instanz(m: <span class="bu">int</span>, n: <span class="bu">int</span>):</span>
|
||||
<span id="cb225-52"><a href="#cb225-52" aria-hidden="true" tabindex="-1"></a> rng <span class="op">=</span> np.random.default_rng(<span class="dv">20</span>)</span>
|
||||
<span id="cb225-53"><a href="#cb225-53" aria-hidden="true" tabindex="-1"></a> kosten <span class="op">=</span> rng.integers(<span class="dv">5</span>, <span class="dv">95</span>, (m, n)).astype(<span class="bu">float</span>)</span>
|
||||
<span id="cb225-54"><a href="#cb225-54" aria-hidden="true" tabindex="-1"></a> angebot <span class="op">=</span> rng.integers(<span class="dv">50</span>, <span class="dv">150</span>, m).astype(<span class="bu">float</span>)</span>
|
||||
<span id="cb225-55"><a href="#cb225-55" aria-hidden="true" tabindex="-1"></a> bedarf <span class="op">=</span> angebot.<span class="bu">sum</span>() <span class="op">*</span> rng.dirichlet(np.ones(n))</span>
|
||||
<span id="cb225-56"><a href="#cb225-56" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> kosten, angebot, bedarf</span>
|
||||
<span id="cb225-57"><a href="#cb225-57" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb225-58"><a href="#cb225-58" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb225-59"><a href="#cb225-59" aria-hidden="true" tabindex="-1"></a><span class="st">def speicher_mb():</span></span>
|
||||
<span id="cb225-60"><a href="#cb225-60" aria-hidden="true" tabindex="-1"></a><span class="st"> # ru_maxrss ist unter Linux in Kilobyte</span></span>
|
||||
<span id="cb225-61"><a href="#cb225-61" aria-hidden="true" tabindex="-1"></a><span class="st"> return resource.getrusage(resource.RUSAGE_SELF).ru_maxrss / 1024</span></span>
|
||||
<span id="cb225-62"><a href="#cb225-62" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb225-63"><a href="#cb225-63" aria-hidden="true" tabindex="-1"></a><span class="st">M, N = </span><span class="sc">{m}</span><span class="st">, </span><span class="sc">{n}</span></span>
|
||||
<span id="cb225-64"><a href="#cb225-64" aria-hidden="true" tabindex="-1"></a><span class="st">kosten, angebot, bedarf = instanz(M, N)</span></span>
|
||||
<span id="cb225-65"><a href="#cb225-65" aria-hidden="true" tabindex="-1"></a><span class="st">"""</span></span>
|
||||
<span id="cb225-66"><a href="#cb225-66" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb225-67"><a href="#cb225-67" aria-hidden="true" tabindex="-1"></a>ANSAETZE <span class="op">=</span> {</span>
|
||||
<span id="cb225-68"><a href="#cb225-68" aria-hidden="true" tabindex="-1"></a> <span class="st">"scipy.linprog"</span>: <span class="st">"""</span></span>
|
||||
<span id="cb225-69"><a href="#cb225-69" aria-hidden="true" tabindex="-1"></a><span class="st"> from scipy.optimize import linprog</span></span>
|
||||
<span id="cb225-70"><a href="#cb225-70" aria-hidden="true" tabindex="-1"></a><span class="st"> t0 = time.perf_counter()</span></span>
|
||||
<span id="cb225-71"><a href="#cb225-71" aria-hidden="true" tabindex="-1"></a><span class="st"> c = kosten.reshape(-1)</span></span>
|
||||
<span id="cb225-72"><a href="#cb225-72" aria-hidden="true" tabindex="-1"></a><span class="st"> A_ub = np.zeros((M, M * N)); A_eq = np.zeros((N, M * N))</span></span>
|
||||
<span id="cb225-73"><a href="#cb225-73" aria-hidden="true" tabindex="-1"></a><span class="st"> for i in range(M):</span></span>
|
||||
<span id="cb225-74"><a href="#cb225-74" aria-hidden="true" tabindex="-1"></a><span class="st"> A_ub[i, i * N:(i + 1) * N] = 1.0</span></span>
|
||||
<span id="cb225-75"><a href="#cb225-75" aria-hidden="true" tabindex="-1"></a><span class="st"> for j in range(N):</span></span>
|
||||
<span id="cb225-76"><a href="#cb225-76" aria-hidden="true" tabindex="-1"></a><span class="st"> A_eq[j, j::N] = 1.0</span></span>
|
||||
<span id="cb225-77"><a href="#cb225-77" aria-hidden="true" tabindex="-1"></a><span class="st"> aufbau = time.perf_counter() - t0</span></span>
|
||||
<span id="cb225-78"><a href="#cb225-78" aria-hidden="true" tabindex="-1"></a><span class="st"> t0 = time.perf_counter()</span></span>
|
||||
<span id="cb225-79"><a href="#cb225-79" aria-hidden="true" tabindex="-1"></a><span class="st"> r = linprog(c=c, A_ub=A_ub, b_ub=angebot, A_eq=A_eq, b_eq=bedarf,</span></span>
|
||||
<span id="cb225-80"><a href="#cb225-80" aria-hidden="true" tabindex="-1"></a><span class="st"> bounds=(0, None), method="highs")</span></span>
|
||||
<span id="cb225-81"><a href="#cb225-81" aria-hidden="true" tabindex="-1"></a><span class="st"> loesen = time.perf_counter() - t0</span></span>
|
||||
<span id="cb225-82"><a href="#cb225-82" aria-hidden="true" tabindex="-1"></a><span class="st"> ausgabe = (float(r.fun), aufbau, loesen, speicher_mb())</span></span>
|
||||
<span id="cb225-83"><a href="#cb225-83" aria-hidden="true" tabindex="-1"></a><span class="st"> """</span>,</span>
|
||||
<span id="cb225-84"><a href="#cb225-84" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb225-85"><a href="#cb225-85" aria-hidden="true" tabindex="-1"></a> <span class="st">"highspy"</span>: <span class="st">"""</span></span>
|
||||
<span id="cb225-86"><a href="#cb225-86" aria-hidden="true" tabindex="-1"></a><span class="st"> import highspy</span></span>
|
||||
<span id="cb225-87"><a href="#cb225-87" aria-hidden="true" tabindex="-1"></a><span class="st"> t0 = time.perf_counter()</span></span>
|
||||
<span id="cb225-88"><a href="#cb225-88" aria-hidden="true" tabindex="-1"></a><span class="st"> h = highspy.Highs(); h.setOptionValue("output_flag", False)</span></span>
|
||||
<span id="cb225-89"><a href="#cb225-89" aria-hidden="true" tabindex="-1"></a><span class="st"> h.addVars(M * N, np.zeros(M * N), np.full(M * N, highspy.kHighsInf))</span></span>
|
||||
<span id="cb225-90"><a href="#cb225-90" aria-hidden="true" tabindex="-1"></a><span class="st"> for k in range(M * N):</span></span>
|
||||
<span id="cb225-91"><a href="#cb225-91" aria-hidden="true" tabindex="-1"></a><span class="st"> h.changeColCost(k, float(kosten.reshape(-1)[k]))</span></span>
|
||||
<span id="cb225-92"><a href="#cb225-92" aria-hidden="true" tabindex="-1"></a><span class="st"> for i in range(M):</span></span>
|
||||
<span id="cb225-93"><a href="#cb225-93" aria-hidden="true" tabindex="-1"></a><span class="st"> idx = np.arange(i * N, (i + 1) * N, dtype=np.int32)</span></span>
|
||||
<span id="cb225-94"><a href="#cb225-94" aria-hidden="true" tabindex="-1"></a><span class="st"> h.addRow(-highspy.kHighsInf, float(angebot[i]), N, idx, np.ones(N))</span></span>
|
||||
<span id="cb225-95"><a href="#cb225-95" aria-hidden="true" tabindex="-1"></a><span class="st"> for j in range(N):</span></span>
|
||||
<span id="cb225-96"><a href="#cb225-96" aria-hidden="true" tabindex="-1"></a><span class="st"> idx = np.arange(j, M * N, N, dtype=np.int32)</span></span>
|
||||
<span id="cb225-97"><a href="#cb225-97" aria-hidden="true" tabindex="-1"></a><span class="st"> h.addRow(float(bedarf[j]), float(bedarf[j]), M, idx, np.ones(M))</span></span>
|
||||
<span id="cb225-98"><a href="#cb225-98" aria-hidden="true" tabindex="-1"></a><span class="st"> aufbau = time.perf_counter() - t0</span></span>
|
||||
<span id="cb225-99"><a href="#cb225-99" aria-hidden="true" tabindex="-1"></a><span class="st"> t0 = time.perf_counter(); h.run(); loesen = time.perf_counter() - t0</span></span>
|
||||
<span id="cb225-100"><a href="#cb225-100" aria-hidden="true" tabindex="-1"></a><span class="st"> ausgabe = (h.getInfo().objective_function_value, aufbau, loesen, speicher_mb())</span></span>
|
||||
<span id="cb225-101"><a href="#cb225-101" aria-hidden="true" tabindex="-1"></a><span class="st"> """</span>,</span>
|
||||
<span id="cb225-102"><a href="#cb225-102" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb225-103"><a href="#cb225-103" aria-hidden="true" tabindex="-1"></a> <span class="st">"ortools/GLOP"</span>: <span class="st">"""</span></span>
|
||||
<span id="cb225-104"><a href="#cb225-104" aria-hidden="true" tabindex="-1"></a><span class="st"> from ortools.linear_solver import pywraplp</span></span>
|
||||
<span id="cb225-105"><a href="#cb225-105" aria-hidden="true" tabindex="-1"></a><span class="st"> t0 = time.perf_counter()</span></span>
|
||||
<span id="cb225-106"><a href="#cb225-106" aria-hidden="true" tabindex="-1"></a><span class="st"> s = pywraplp.Solver.CreateSolver("GLOP")</span></span>
|
||||
<span id="cb225-107"><a href="#cb225-107" aria-hidden="true" tabindex="-1"></a><span class="st"> x = [[s.NumVar(0, s.infinity(), f"x</span><span class="sc">{i}</span><span class="st">_</span><span class="sc">{j}</span><span class="st">") for j in range(N)]</span></span>
|
||||
<span id="cb225-108"><a href="#cb225-108" aria-hidden="true" tabindex="-1"></a><span class="st"> for i in range(M)]</span></span>
|
||||
<span id="cb225-109"><a href="#cb225-109" aria-hidden="true" tabindex="-1"></a><span class="st"> for i in range(M):</span></span>
|
||||
<span id="cb225-110"><a href="#cb225-110" aria-hidden="true" tabindex="-1"></a><span class="st"> s.Add(sum(x[i]) <= float(angebot[i]))</span></span>
|
||||
<span id="cb225-111"><a href="#cb225-111" aria-hidden="true" tabindex="-1"></a><span class="st"> for j in range(N):</span></span>
|
||||
<span id="cb225-112"><a href="#cb225-112" aria-hidden="true" tabindex="-1"></a><span class="st"> s.Add(sum(x[i][j] for i in range(M)) == float(bedarf[j]))</span></span>
|
||||
<span id="cb225-113"><a href="#cb225-113" aria-hidden="true" tabindex="-1"></a><span class="st"> s.Minimize(sum(float(kosten[i, j]) * x[i][j]</span></span>
|
||||
<span id="cb225-114"><a href="#cb225-114" aria-hidden="true" tabindex="-1"></a><span class="st"> for i in range(M) for j in range(N)))</span></span>
|
||||
<span id="cb225-115"><a href="#cb225-115" aria-hidden="true" tabindex="-1"></a><span class="st"> aufbau = time.perf_counter() - t0</span></span>
|
||||
<span id="cb225-116"><a href="#cb225-116" aria-hidden="true" tabindex="-1"></a><span class="st"> t0 = time.perf_counter(); s.Solve(); loesen = time.perf_counter() - t0</span></span>
|
||||
<span id="cb225-117"><a href="#cb225-117" aria-hidden="true" tabindex="-1"></a><span class="st"> ausgabe = (s.Objective().Value(), aufbau, loesen, speicher_mb())</span></span>
|
||||
<span id="cb225-118"><a href="#cb225-118" aria-hidden="true" tabindex="-1"></a><span class="st"> """</span>,</span>
|
||||
<span id="cb225-59"><a href="#cb225-59" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> speicher_mb() <span class="op">-></span> <span class="bu">float</span>:</span>
|
||||
<span id="cb225-60"><a href="#cb225-60" aria-hidden="true" tabindex="-1"></a> <span class="co"># ru_maxrss ist unter Linux in Kilobyte. Gemessen wird der Kindprozess -</span></span>
|
||||
<span id="cb225-61"><a href="#cb225-61" aria-hidden="true" tabindex="-1"></a> <span class="co"># deshalb muss jede Messung einen eigenen bekommen.</span></span>
|
||||
<span id="cb225-62"><a href="#cb225-62" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> resource.getrusage(resource.RUSAGE_SELF).ru_maxrss <span class="op">/</span> <span class="dv">1024</span></span>
|
||||
<span id="cb225-63"><a href="#cb225-63" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb225-64"><a href="#cb225-64" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb225-65"><a href="#cb225-65" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> messe_scipy(m: <span class="bu">int</span>, n: <span class="bu">int</span>):</span>
|
||||
<span id="cb225-66"><a href="#cb225-66" aria-hidden="true" tabindex="-1"></a> <span class="im">from</span> scipy.optimize <span class="im">import</span> linprog</span>
|
||||
<span id="cb225-67"><a href="#cb225-67" aria-hidden="true" tabindex="-1"></a> kosten, angebot, bedarf <span class="op">=</span> instanz(m, n)</span>
|
||||
<span id="cb225-68"><a href="#cb225-68" aria-hidden="true" tabindex="-1"></a> t0 <span class="op">=</span> time.perf_counter()</span>
|
||||
<span id="cb225-69"><a href="#cb225-69" aria-hidden="true" tabindex="-1"></a> c <span class="op">=</span> kosten.reshape(<span class="op">-</span><span class="dv">1</span>)</span>
|
||||
<span id="cb225-70"><a href="#cb225-70" aria-hidden="true" tabindex="-1"></a> A_ub <span class="op">=</span> np.zeros((m, m <span class="op">*</span> n))<span class="op">;</span> A_eq <span class="op">=</span> np.zeros((n, m <span class="op">*</span> n))</span>
|
||||
<span id="cb225-71"><a href="#cb225-71" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> i <span class="kw">in</span> <span class="bu">range</span>(m):</span>
|
||||
<span id="cb225-72"><a href="#cb225-72" aria-hidden="true" tabindex="-1"></a> A_ub[i, i <span class="op">*</span> n:(i <span class="op">+</span> <span class="dv">1</span>) <span class="op">*</span> n] <span class="op">=</span> <span class="fl">1.0</span></span>
|
||||
<span id="cb225-73"><a href="#cb225-73" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> j <span class="kw">in</span> <span class="bu">range</span>(n):</span>
|
||||
<span id="cb225-74"><a href="#cb225-74" aria-hidden="true" tabindex="-1"></a> A_eq[j, j::n] <span class="op">=</span> <span class="fl">1.0</span></span>
|
||||
<span id="cb225-75"><a href="#cb225-75" aria-hidden="true" tabindex="-1"></a> aufbau <span class="op">=</span> time.perf_counter() <span class="op">-</span> t0</span>
|
||||
<span id="cb225-76"><a href="#cb225-76" aria-hidden="true" tabindex="-1"></a> t0 <span class="op">=</span> time.perf_counter()</span>
|
||||
<span id="cb225-77"><a href="#cb225-77" aria-hidden="true" tabindex="-1"></a> r <span class="op">=</span> linprog(c<span class="op">=</span>c, A_ub<span class="op">=</span>A_ub, b_ub<span class="op">=</span>angebot, A_eq<span class="op">=</span>A_eq, b_eq<span class="op">=</span>bedarf,</span>
|
||||
<span id="cb225-78"><a href="#cb225-78" aria-hidden="true" tabindex="-1"></a> bounds<span class="op">=</span>(<span class="dv">0</span>, <span class="va">None</span>), method<span class="op">=</span><span class="st">"highs"</span>)</span>
|
||||
<span id="cb225-79"><a href="#cb225-79" aria-hidden="true" tabindex="-1"></a> loesen <span class="op">=</span> time.perf_counter() <span class="op">-</span> t0</span>
|
||||
<span id="cb225-80"><a href="#cb225-80" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> <span class="bu">float</span>(r.fun), aufbau, loesen, speicher_mb()</span>
|
||||
<span id="cb225-81"><a href="#cb225-81" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb225-82"><a href="#cb225-82" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb225-83"><a href="#cb225-83" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> messe_highspy(m: <span class="bu">int</span>, n: <span class="bu">int</span>):</span>
|
||||
<span id="cb225-84"><a href="#cb225-84" aria-hidden="true" tabindex="-1"></a> <span class="im">import</span> highspy</span>
|
||||
<span id="cb225-85"><a href="#cb225-85" aria-hidden="true" tabindex="-1"></a> kosten, angebot, bedarf <span class="op">=</span> instanz(m, n)</span>
|
||||
<span id="cb225-86"><a href="#cb225-86" aria-hidden="true" tabindex="-1"></a> t0 <span class="op">=</span> time.perf_counter()</span>
|
||||
<span id="cb225-87"><a href="#cb225-87" aria-hidden="true" tabindex="-1"></a> h <span class="op">=</span> highspy.Highs()<span class="op">;</span> h.setOptionValue(<span class="st">"output_flag"</span>, <span class="va">False</span>)</span>
|
||||
<span id="cb225-88"><a href="#cb225-88" aria-hidden="true" tabindex="-1"></a> h.addVars(m <span class="op">*</span> n, np.zeros(m <span class="op">*</span> n), np.full(m <span class="op">*</span> n, highspy.kHighsInf))</span>
|
||||
<span id="cb225-89"><a href="#cb225-89" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> k <span class="kw">in</span> <span class="bu">range</span>(m <span class="op">*</span> n):</span>
|
||||
<span id="cb225-90"><a href="#cb225-90" aria-hidden="true" tabindex="-1"></a> h.changeColCost(k, <span class="bu">float</span>(kosten.reshape(<span class="op">-</span><span class="dv">1</span>)[k]))</span>
|
||||
<span id="cb225-91"><a href="#cb225-91" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> i <span class="kw">in</span> <span class="bu">range</span>(m):</span>
|
||||
<span id="cb225-92"><a href="#cb225-92" aria-hidden="true" tabindex="-1"></a> idx <span class="op">=</span> np.arange(i <span class="op">*</span> n, (i <span class="op">+</span> <span class="dv">1</span>) <span class="op">*</span> n, dtype<span class="op">=</span>np.int32)</span>
|
||||
<span id="cb225-93"><a href="#cb225-93" aria-hidden="true" tabindex="-1"></a> h.addRow(<span class="op">-</span>highspy.kHighsInf, <span class="bu">float</span>(angebot[i]), n, idx, np.ones(n))</span>
|
||||
<span id="cb225-94"><a href="#cb225-94" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> j <span class="kw">in</span> <span class="bu">range</span>(n):</span>
|
||||
<span id="cb225-95"><a href="#cb225-95" aria-hidden="true" tabindex="-1"></a> idx <span class="op">=</span> np.arange(j, m <span class="op">*</span> n, n, dtype<span class="op">=</span>np.int32)</span>
|
||||
<span id="cb225-96"><a href="#cb225-96" aria-hidden="true" tabindex="-1"></a> h.addRow(<span class="bu">float</span>(bedarf[j]), <span class="bu">float</span>(bedarf[j]), m, idx, np.ones(m))</span>
|
||||
<span id="cb225-97"><a href="#cb225-97" aria-hidden="true" tabindex="-1"></a> aufbau <span class="op">=</span> time.perf_counter() <span class="op">-</span> t0</span>
|
||||
<span id="cb225-98"><a href="#cb225-98" aria-hidden="true" tabindex="-1"></a> t0 <span class="op">=</span> time.perf_counter()<span class="op">;</span> h.run()<span class="op">;</span> loesen <span class="op">=</span> time.perf_counter() <span class="op">-</span> t0</span>
|
||||
<span id="cb225-99"><a href="#cb225-99" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> h.getInfo().objective_function_value, aufbau, loesen, speicher_mb()</span>
|
||||
<span id="cb225-100"><a href="#cb225-100" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb225-101"><a href="#cb225-101" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb225-102"><a href="#cb225-102" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> messe_ortools(m: <span class="bu">int</span>, n: <span class="bu">int</span>):</span>
|
||||
<span id="cb225-103"><a href="#cb225-103" aria-hidden="true" tabindex="-1"></a> <span class="im">from</span> ortools.linear_solver <span class="im">import</span> pywraplp</span>
|
||||
<span id="cb225-104"><a href="#cb225-104" aria-hidden="true" tabindex="-1"></a> kosten, angebot, bedarf <span class="op">=</span> instanz(m, n)</span>
|
||||
<span id="cb225-105"><a href="#cb225-105" aria-hidden="true" tabindex="-1"></a> t0 <span class="op">=</span> time.perf_counter()</span>
|
||||
<span id="cb225-106"><a href="#cb225-106" aria-hidden="true" tabindex="-1"></a> s <span class="op">=</span> pywraplp.Solver.CreateSolver(<span class="st">"GLOP"</span>)</span>
|
||||
<span id="cb225-107"><a href="#cb225-107" aria-hidden="true" tabindex="-1"></a> x <span class="op">=</span> [[s.NumVar(<span class="dv">0</span>, s.infinity(), <span class="ss">f"x</span><span class="sc">{</span>i<span class="sc">}</span><span class="ss">_</span><span class="sc">{</span>j<span class="sc">}</span><span class="ss">"</span>) <span class="cf">for</span> j <span class="kw">in</span> <span class="bu">range</span>(n)]</span>
|
||||
<span id="cb225-108"><a href="#cb225-108" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> i <span class="kw">in</span> <span class="bu">range</span>(m)]</span>
|
||||
<span id="cb225-109"><a href="#cb225-109" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> i <span class="kw">in</span> <span class="bu">range</span>(m):</span>
|
||||
<span id="cb225-110"><a href="#cb225-110" aria-hidden="true" tabindex="-1"></a> s.Add(<span class="bu">sum</span>(x[i]) <span class="op"><=</span> <span class="bu">float</span>(angebot[i]))</span>
|
||||
<span id="cb225-111"><a href="#cb225-111" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> j <span class="kw">in</span> <span class="bu">range</span>(n):</span>
|
||||
<span id="cb225-112"><a href="#cb225-112" aria-hidden="true" tabindex="-1"></a> s.Add(<span class="bu">sum</span>(x[i][j] <span class="cf">for</span> i <span class="kw">in</span> <span class="bu">range</span>(m)) <span class="op">==</span> <span class="bu">float</span>(bedarf[j]))</span>
|
||||
<span id="cb225-113"><a href="#cb225-113" aria-hidden="true" tabindex="-1"></a> s.Minimize(<span class="bu">sum</span>(<span class="bu">float</span>(kosten[i, j]) <span class="op">*</span> x[i][j]</span>
|
||||
<span id="cb225-114"><a href="#cb225-114" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> i <span class="kw">in</span> <span class="bu">range</span>(m) <span class="cf">for</span> j <span class="kw">in</span> <span class="bu">range</span>(n)))</span>
|
||||
<span id="cb225-115"><a href="#cb225-115" aria-hidden="true" tabindex="-1"></a> aufbau <span class="op">=</span> time.perf_counter() <span class="op">-</span> t0</span>
|
||||
<span id="cb225-116"><a href="#cb225-116" aria-hidden="true" tabindex="-1"></a> t0 <span class="op">=</span> time.perf_counter()<span class="op">;</span> s.Solve()<span class="op">;</span> loesen <span class="op">=</span> time.perf_counter() <span class="op">-</span> t0</span>
|
||||
<span id="cb225-117"><a href="#cb225-117" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> s.Objective().Value(), aufbau, loesen, speicher_mb()</span>
|
||||
<span id="cb225-118"><a href="#cb225-118" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb225-119"><a href="#cb225-119" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb225-120"><a href="#cb225-120" aria-hidden="true" tabindex="-1"></a> <span class="st">"cvxpy"</span>: <span class="st">"""</span></span>
|
||||
<span id="cb225-121"><a href="#cb225-121" aria-hidden="true" tabindex="-1"></a><span class="st"> import cvxpy as cp</span></span>
|
||||
<span id="cb225-122"><a href="#cb225-122" aria-hidden="true" tabindex="-1"></a><span class="st"> t0 = time.perf_counter()</span></span>
|
||||
<span id="cb225-123"><a href="#cb225-123" aria-hidden="true" tabindex="-1"></a><span class="st"> x = cp.Variable((M, N), nonneg=True)</span></span>
|
||||
<span id="cb225-124"><a href="#cb225-124" aria-hidden="true" tabindex="-1"></a><span class="st"> problem = cp.Problem(cp.Minimize(cp.sum(cp.multiply(kosten, x))),</span></span>
|
||||
<span id="cb225-125"><a href="#cb225-125" aria-hidden="true" tabindex="-1"></a><span class="st"> [cp.sum(x, axis=1) <= angebot,</span></span>
|
||||
<span id="cb225-126"><a href="#cb225-126" aria-hidden="true" tabindex="-1"></a><span class="st"> cp.sum(x, axis=0) == bedarf])</span></span>
|
||||
<span id="cb225-127"><a href="#cb225-127" aria-hidden="true" tabindex="-1"></a><span class="st"> aufbau = time.perf_counter() - t0</span></span>
|
||||
<span id="cb225-128"><a href="#cb225-128" aria-hidden="true" tabindex="-1"></a><span class="st"> t0 = time.perf_counter(); problem.solve(); loesen = time.perf_counter() - t0</span></span>
|
||||
<span id="cb225-129"><a href="#cb225-129" aria-hidden="true" tabindex="-1"></a><span class="st"> ausgabe = (float(problem.value), aufbau, loesen, speicher_mb())</span></span>
|
||||
<span id="cb225-130"><a href="#cb225-130" aria-hidden="true" tabindex="-1"></a><span class="st"> """</span>,</span>
|
||||
<span id="cb225-131"><a href="#cb225-131" aria-hidden="true" tabindex="-1"></a>}</span>
|
||||
<span id="cb225-120"><a href="#cb225-120" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> messe_cvxpy(m: <span class="bu">int</span>, n: <span class="bu">int</span>):</span>
|
||||
<span id="cb225-121"><a href="#cb225-121" aria-hidden="true" tabindex="-1"></a> <span class="im">import</span> cvxpy <span class="im">as</span> cp</span>
|
||||
<span id="cb225-122"><a href="#cb225-122" aria-hidden="true" tabindex="-1"></a> kosten, angebot, bedarf <span class="op">=</span> instanz(m, n)</span>
|
||||
<span id="cb225-123"><a href="#cb225-123" aria-hidden="true" tabindex="-1"></a> t0 <span class="op">=</span> time.perf_counter()</span>
|
||||
<span id="cb225-124"><a href="#cb225-124" aria-hidden="true" tabindex="-1"></a> x <span class="op">=</span> cp.Variable((m, n), nonneg<span class="op">=</span><span class="va">True</span>)</span>
|
||||
<span id="cb225-125"><a href="#cb225-125" aria-hidden="true" tabindex="-1"></a> problem <span class="op">=</span> cp.Problem(cp.Minimize(cp.<span class="bu">sum</span>(cp.multiply(kosten, x))),</span>
|
||||
<span id="cb225-126"><a href="#cb225-126" aria-hidden="true" tabindex="-1"></a> [cp.<span class="bu">sum</span>(x, axis<span class="op">=</span><span class="dv">1</span>) <span class="op"><=</span> angebot,</span>
|
||||
<span id="cb225-127"><a href="#cb225-127" aria-hidden="true" tabindex="-1"></a> cp.<span class="bu">sum</span>(x, axis<span class="op">=</span><span class="dv">0</span>) <span class="op">==</span> bedarf])</span>
|
||||
<span id="cb225-128"><a href="#cb225-128" aria-hidden="true" tabindex="-1"></a> aufbau <span class="op">=</span> time.perf_counter() <span class="op">-</span> t0</span>
|
||||
<span id="cb225-129"><a href="#cb225-129" aria-hidden="true" tabindex="-1"></a> t0 <span class="op">=</span> time.perf_counter()<span class="op">;</span> problem.solve()<span class="op">;</span> loesen <span class="op">=</span> time.perf_counter() <span class="op">-</span> t0</span>
|
||||
<span id="cb225-130"><a href="#cb225-130" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> <span class="bu">float</span>(problem.value), aufbau, loesen, speicher_mb()</span>
|
||||
<span id="cb225-131"><a href="#cb225-131" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb225-132"><a href="#cb225-132" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb225-133"><a href="#cb225-133" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb225-134"><a href="#cb225-134" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> messe(name: <span class="bu">str</span>, quelltext: <span class="bu">str</span>, m: <span class="bu">int</span>, n: <span class="bu">int</span>):</span>
|
||||
<span id="cb225-135"><a href="#cb225-135" aria-hidden="true" tabindex="-1"></a> <span class="co">"""Fuehrt einen Ansatz in einem eigenen Prozess aus."""</span></span>
|
||||
<span id="cb225-136"><a href="#cb225-136" aria-hidden="true" tabindex="-1"></a> programm <span class="op">=</span> (VORSPANN.<span class="bu">format</span>(m<span class="op">=</span>m, n<span class="op">=</span>n) <span class="op">+</span> textwrap.dedent(quelltext)</span>
|
||||
<span id="cb225-137"><a href="#cb225-137" aria-hidden="true" tabindex="-1"></a> <span class="op">+</span> <span class="st">"</span><span class="ch">\n</span><span class="st">print(json.dumps(ausgabe))</span><span class="ch">\n</span><span class="st">"</span>)</span>
|
||||
<span id="cb225-138"><a href="#cb225-138" aria-hidden="true" tabindex="-1"></a> ergebnis <span class="op">=</span> subprocess.run([sys.executable, <span class="st">"-c"</span>, programm],</span>
|
||||
<span id="cb225-139"><a href="#cb225-139" aria-hidden="true" tabindex="-1"></a> capture_output<span class="op">=</span><span class="va">True</span>, text<span class="op">=</span><span class="va">True</span>, timeout<span class="op">=</span><span class="dv">600</span>)</span>
|
||||
<span id="cb225-140"><a href="#cb225-140" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> ergebnis.returncode <span class="op">!=</span> <span class="dv">0</span>:</span>
|
||||
<span id="cb225-141"><a href="#cb225-141" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> <span class="va">None</span>, ergebnis.stderr.strip().splitlines()[<span class="op">-</span><span class="dv">1</span>][:<span class="dv">60</span>]</span>
|
||||
<span id="cb225-142"><a href="#cb225-142" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> json.loads(ergebnis.stdout.strip().splitlines()[<span class="op">-</span><span class="dv">1</span>]), <span class="va">None</span></span>
|
||||
<span id="cb225-143"><a href="#cb225-143" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb225-144"><a href="#cb225-144" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb225-145"><a href="#cb225-145" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">"__main__"</span>:</span>
|
||||
<span id="cb225-146"><a href="#cb225-146" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"="</span> <span class="op">*</span> <span class="dv">92</span>)</span>
|
||||
<span id="cb225-147"><a href="#cb225-147" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" SKALIERUNGSVERGLEICH: TRANSPORTPROBLEM, VIER BIBLIOTHEKEN"</span>)</span>
|
||||
<span id="cb225-148"><a href="#cb225-148" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"="</span> <span class="op">*</span> <span class="dv">92</span>)</span>
|
||||
<span id="cb225-149"><a href="#cb225-149" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"Jede Zeile ein eigener Prozess. Zeiten und Speicher sind "</span></span>
|
||||
<span id="cb225-150"><a href="#cb225-150" aria-hidden="true" tabindex="-1"></a> <span class="st">"hardwareabhaengig,"</span>)</span>
|
||||
<span id="cb225-151"><a href="#cb225-151" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"die Zielwerte und ihr Verhaeltnis zueinander nicht.</span><span class="ch">\n</span><span class="st">"</span>)</span>
|
||||
<span id="cb225-152"><a href="#cb225-152" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb225-153"><a href="#cb225-153" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> m, n <span class="kw">in</span> GROESSEN:</span>
|
||||
<span id="cb225-154"><a href="#cb225-154" aria-hidden="true" tabindex="-1"></a> kopf <span class="op">=</span> <span class="ss">f"--- </span><span class="sc">{</span>m<span class="sc">}</span><span class="ss"> Lager x </span><span class="sc">{</span>n<span class="sc">}</span><span class="ss"> Kunden = </span><span class="sc">{</span>m <span class="op">*</span> n<span class="sc">:,}</span><span class="ss"> Variablen "</span></span>
|
||||
<span id="cb225-155"><a href="#cb225-155" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(kopf <span class="op">+</span> <span class="st">"-"</span> <span class="op">*</span> <span class="bu">max</span>(<span class="dv">3</span>, <span class="dv">92</span> <span class="op">-</span> <span class="bu">len</span>(kopf)))</span>
|
||||
<span id="cb225-156"><a href="#cb225-156" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f" </span><span class="sc">{</span><span class="st">'Bibliothek'</span><span class="sc">:<16}</span><span class="ss"> </span><span class="sc">{</span><span class="st">'Zielwert'</span><span class="sc">:>14}</span><span class="ss"> </span><span class="sc">{</span><span class="st">'Aufbau'</span><span class="sc">:>9}</span><span class="ss"> "</span></span>
|
||||
<span id="cb225-157"><a href="#cb225-157" aria-hidden="true" tabindex="-1"></a> <span class="ss">f"</span><span class="sc">{</span><span class="st">'Loesen'</span><span class="sc">:>9}</span><span class="ss"> </span><span class="sc">{</span><span class="st">'Anteil'</span><span class="sc">:>8}</span><span class="ss"> </span><span class="sc">{</span><span class="st">'Speicher'</span><span class="sc">:>10}</span><span class="ss">"</span>)</span>
|
||||
<span id="cb225-158"><a href="#cb225-158" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" "</span> <span class="op">+</span> <span class="st">"-"</span> <span class="op">*</span> <span class="dv">72</span>)</span>
|
||||
<span id="cb225-159"><a href="#cb225-159" aria-hidden="true" tabindex="-1"></a> zielwerte <span class="op">=</span> {}</span>
|
||||
<span id="cb225-160"><a href="#cb225-160" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> name, quelltext <span class="kw">in</span> ANSAETZE.items():</span>
|
||||
<span id="cb225-161"><a href="#cb225-161" aria-hidden="true" tabindex="-1"></a> werte, fehler <span class="op">=</span> messe(name, quelltext, m, n)</span>
|
||||
<span id="cb225-162"><a href="#cb225-162" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> werte <span class="kw">is</span> <span class="va">None</span>:</span>
|
||||
<span id="cb225-163"><a href="#cb225-163" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f" </span><span class="sc">{</span>name<span class="sc">:<16}</span><span class="ss"> nicht verfuegbar: </span><span class="sc">{</span>fehler<span class="sc">}</span><span class="ss">"</span>)</span>
|
||||
<span id="cb225-164"><a href="#cb225-164" aria-hidden="true" tabindex="-1"></a> <span class="cf">continue</span></span>
|
||||
<span id="cb225-165"><a href="#cb225-165" aria-hidden="true" tabindex="-1"></a> ziel, aufbau, loesen, speicher <span class="op">=</span> werte</span>
|
||||
<span id="cb225-166"><a href="#cb225-166" aria-hidden="true" tabindex="-1"></a> zielwerte[name] <span class="op">=</span> ziel</span>
|
||||
<span id="cb225-167"><a href="#cb225-167" aria-hidden="true" tabindex="-1"></a> anteil <span class="op">=</span> aufbau <span class="op">/</span> (aufbau <span class="op">+</span> loesen) <span class="op">*</span> <span class="dv">100</span></span>
|
||||
<span id="cb225-168"><a href="#cb225-168" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f" </span><span class="sc">{</span>name<span class="sc">:<16}</span><span class="ss"> </span><span class="sc">{</span>ziel<span class="sc">:>14,.2f}</span><span class="ss"> </span><span class="sc">{</span>aufbau<span class="sc">:>8.3f}</span><span class="ss">s "</span></span>
|
||||
<span id="cb225-169"><a href="#cb225-169" aria-hidden="true" tabindex="-1"></a> <span class="ss">f"</span><span class="sc">{</span>loesen<span class="sc">:>8.3f}</span><span class="ss">s </span><span class="sc">{</span>anteil<span class="sc">:>7.0f}</span><span class="ss">% </span><span class="sc">{</span>speicher<span class="sc">:>9.0f}</span><span class="ss"> MB"</span>)</span>
|
||||
<span id="cb225-170"><a href="#cb225-170" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb225-171"><a href="#cb225-171" aria-hidden="true" tabindex="-1"></a> <span class="co"># Die wichtigste Zeile: Rechnen alle dasselbe aus?</span></span>
|
||||
<span id="cb225-172"><a href="#cb225-172" aria-hidden="true" tabindex="-1"></a> spanne <span class="op">=</span> <span class="bu">max</span>(zielwerte.values()) <span class="op">-</span> <span class="bu">min</span>(zielwerte.values())</span>
|
||||
<span id="cb225-173"><a href="#cb225-173" aria-hidden="true" tabindex="-1"></a> bezug <span class="op">=</span> <span class="bu">max</span>(<span class="bu">abs</span>(v) <span class="cf">for</span> v <span class="kw">in</span> zielwerte.values())</span>
|
||||
<span id="cb225-174"><a href="#cb225-174" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f" </span><span class="sc">{</span><span class="st">''</span><span class="sc">:16}</span><span class="ss"> Spannweite der Zielwerte: </span><span class="sc">{</span>spanne<span class="sc">:.2e}</span><span class="ss"> "</span></span>
|
||||
<span id="cb225-175"><a href="#cb225-175" aria-hidden="true" tabindex="-1"></a> <span class="ss">f"(relativ </span><span class="sc">{</span>spanne <span class="op">/</span> bezug<span class="sc">:.1e}</span><span class="ss">)"</span>)</span>
|
||||
<span id="cb225-176"><a href="#cb225-176" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> spanne <span class="op">/</span> bezug <span class="op">></span> <span class="fl">1e-6</span>:</span>
|
||||
<span id="cb225-177"><a href="#cb225-177" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" ACHTUNG: Die Bibliotheken widersprechen sich - "</span></span>
|
||||
<span id="cb225-178"><a href="#cb225-178" aria-hidden="true" tabindex="-1"></a> <span class="st">"der Zeitvergleich ist wertlos."</span>)</span>
|
||||
<span id="cb225-179"><a href="#cb225-179" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>()</span>
|
||||
<span id="cb225-180"><a href="#cb225-180" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb225-181"><a href="#cb225-181" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"="</span> <span class="op">*</span> <span class="dv">92</span>)</span>
|
||||
<span id="cb225-182"><a href="#cb225-182" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" WAS MAN AUS SO EINER TABELLE ABLESEN DARF - UND WAS NICHT"</span>)</span>
|
||||
<span id="cb225-183"><a href="#cb225-183" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"="</span> <span class="op">*</span> <span class="dv">92</span>)</span>
|
||||
<span id="cb225-184"><a href="#cb225-184" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"DARF man ablesen:"</span>)</span>
|
||||
<span id="cb225-185"><a href="#cb225-185" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" * Die Spalte 'Anteil' - wie viel der Zeit in den AUFBAU geht statt"</span>)</span>
|
||||
<span id="cb225-186"><a href="#cb225-186" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" ins Loesen. Wenn dort 80 </span><span class="sc">% s</span><span class="st">tehen, ist ein schnellerer Solver die"</span>)</span>
|
||||
<span id="cb225-187"><a href="#cb225-187" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" falsche Antwort; dann gehoert das Modell vektorisiert aufgebaut"</span>)</span>
|
||||
<span id="cb225-188"><a href="#cb225-188" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" (Kapitel Oekosystem)."</span>)</span>
|
||||
<span id="cb225-189"><a href="#cb225-189" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" * Die Groessenordnung des Speicherbedarfs. Sie entscheidet, was auf"</span>)</span>
|
||||
<span id="cb225-190"><a href="#cb225-190" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" einer bestimmten Maschine ueberhaupt laeuft."</span>)</span>
|
||||
<span id="cb225-191"><a href="#cb225-191" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" * Wie sich beides mit der Groesse ENTWICKELT. Der Trend ist"</span>)</span>
|
||||
<span id="cb225-192"><a href="#cb225-192" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" uebertragbarer als der Absolutwert."</span>)</span>
|
||||
<span id="cb225-193"><a href="#cb225-193" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>()</span>
|
||||
<span id="cb225-194"><a href="#cb225-194" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"NICHT ablesen darf man:"</span>)</span>
|
||||
<span id="cb225-195"><a href="#cb225-195" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" * 'Bibliothek X ist schneller als Y.' Gemessen wurde EIN"</span>)</span>
|
||||
<span id="cb225-196"><a href="#cb225-196" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" Problemtyp in EINER Formulierung. Ein MILP, ein QP oder eine"</span>)</span>
|
||||
<span id="cb225-197"><a href="#cb225-197" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" andere Modellierung desselben Problems koennen die Reihenfolge"</span>)</span>
|
||||
<span id="cb225-198"><a href="#cb225-198" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" umdrehen."</span>)</span>
|
||||
<span id="cb225-199"><a href="#cb225-199" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" * Etwas ueber Ihre Maschine. Diese Zahlen stammen von einer"</span>)</span>
|
||||
<span id="cb225-200"><a href="#cb225-200" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" anderen. Der Sinn des Programms ist, dass Sie es auf Ihrer"</span>)</span>
|
||||
<span id="cb225-201"><a href="#cb225-201" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" laufen lassen."</span>)</span>
|
||||
<span id="cb225-202"><a href="#cb225-202" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"="</span> <span class="op">*</span> <span class="dv">92</span>)</span></code></pre></div>
|
||||
<span id="cb225-133"><a href="#cb225-133" aria-hidden="true" tabindex="-1"></a>ANSAETZE <span class="op">=</span> {<span class="st">"scipy.linprog"</span>: messe_scipy, <span class="st">"highspy"</span>: messe_highspy,</span>
|
||||
<span id="cb225-134"><a href="#cb225-134" aria-hidden="true" tabindex="-1"></a> <span class="st">"ortools/GLOP"</span>: messe_ortools, <span class="st">"cvxpy"</span>: messe_cvxpy}</span>
|
||||
<span id="cb225-135"><a href="#cb225-135" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb225-136"><a href="#cb225-136" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb225-137"><a href="#cb225-137" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> messe(funktion, m: <span class="bu">int</span>, n: <span class="bu">int</span>):</span>
|
||||
<span id="cb225-138"><a href="#cb225-138" aria-hidden="true" tabindex="-1"></a> <span class="co">"""Fuehrt eine Messfunktion in einem FRISCHEN Prozess aus.</span></span>
|
||||
<span id="cb225-139"><a href="#cb225-139" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb225-140"><a href="#cb225-140" aria-hidden="true" tabindex="-1"></a><span class="co"> 'spawn' und max_tasks_per_child=1 zusammen garantieren, was Regel 1</span></span>
|
||||
<span id="cb225-141"><a href="#cb225-141" aria-hidden="true" tabindex="-1"></a><span class="co"> verlangt: Jede Messung sieht einen leeren Interpreter. Ohne das</span></span>
|
||||
<span id="cb225-142"><a href="#cb225-142" aria-hidden="true" tabindex="-1"></a><span class="co"> zweite wuerde der Pool seinen Arbeiter wiederverwenden - dann waere</span></span>
|
||||
<span id="cb225-143"><a href="#cb225-143" aria-hidden="true" tabindex="-1"></a><span class="co"> der Speicherwert der zweiten Bibliothek um die erste zu hoch, und</span></span>
|
||||
<span id="cb225-144"><a href="#cb225-144" aria-hidden="true" tabindex="-1"></a><span class="co"> ortools und highspy saessen im selben Prozess.</span></span>
|
||||
<span id="cb225-145"><a href="#cb225-145" aria-hidden="true" tabindex="-1"></a><span class="co"> """</span></span>
|
||||
<span id="cb225-146"><a href="#cb225-146" aria-hidden="true" tabindex="-1"></a> <span class="cf">with</span> ProcessPoolExecutor(</span>
|
||||
<span id="cb225-147"><a href="#cb225-147" aria-hidden="true" tabindex="-1"></a> max_workers<span class="op">=</span><span class="dv">1</span>,</span>
|
||||
<span id="cb225-148"><a href="#cb225-148" aria-hidden="true" tabindex="-1"></a> mp_context<span class="op">=</span>multiprocessing.get_context(<span class="st">"spawn"</span>),</span>
|
||||
<span id="cb225-149"><a href="#cb225-149" aria-hidden="true" tabindex="-1"></a> max_tasks_per_child<span class="op">=</span><span class="dv">1</span>) <span class="im">as</span> pool:</span>
|
||||
<span id="cb225-150"><a href="#cb225-150" aria-hidden="true" tabindex="-1"></a> <span class="cf">try</span>:</span>
|
||||
<span id="cb225-151"><a href="#cb225-151" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> pool.submit(funktion, m, n).result(timeout<span class="op">=</span><span class="dv">600</span>), <span class="va">None</span></span>
|
||||
<span id="cb225-152"><a href="#cb225-152" aria-hidden="true" tabindex="-1"></a> <span class="cf">except</span> <span class="pp">Exception</span> <span class="im">as</span> fehler:</span>
|
||||
<span id="cb225-153"><a href="#cb225-153" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> <span class="va">None</span>, <span class="bu">str</span>(fehler).strip().splitlines()[<span class="op">-</span><span class="dv">1</span>][:<span class="dv">60</span>]</span>
|
||||
<span id="cb225-154"><a href="#cb225-154" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb225-155"><a href="#cb225-155" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb225-156"><a href="#cb225-156" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">"__main__"</span>:</span>
|
||||
<span id="cb225-157"><a href="#cb225-157" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"="</span> <span class="op">*</span> <span class="dv">92</span>)</span>
|
||||
<span id="cb225-158"><a href="#cb225-158" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" SKALIERUNGSVERGLEICH: TRANSPORTPROBLEM, VIER BIBLIOTHEKEN"</span>)</span>
|
||||
<span id="cb225-159"><a href="#cb225-159" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"="</span> <span class="op">*</span> <span class="dv">92</span>)</span>
|
||||
<span id="cb225-160"><a href="#cb225-160" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"Jede Zeile ein eigener Prozess. Zeiten und Speicher sind "</span></span>
|
||||
<span id="cb225-161"><a href="#cb225-161" aria-hidden="true" tabindex="-1"></a> <span class="st">"hardwareabhaengig,"</span>)</span>
|
||||
<span id="cb225-162"><a href="#cb225-162" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"die Zielwerte und ihr Verhaeltnis zueinander nicht.</span><span class="ch">\n</span><span class="st">"</span>)</span>
|
||||
<span id="cb225-163"><a href="#cb225-163" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb225-164"><a href="#cb225-164" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> m, n <span class="kw">in</span> GROESSEN:</span>
|
||||
<span id="cb225-165"><a href="#cb225-165" aria-hidden="true" tabindex="-1"></a> kopf <span class="op">=</span> <span class="ss">f"--- </span><span class="sc">{</span>m<span class="sc">}</span><span class="ss"> Lager x </span><span class="sc">{</span>n<span class="sc">}</span><span class="ss"> Kunden = </span><span class="sc">{</span>m <span class="op">*</span> n<span class="sc">:,}</span><span class="ss"> Variablen "</span></span>
|
||||
<span id="cb225-166"><a href="#cb225-166" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(kopf <span class="op">+</span> <span class="st">"-"</span> <span class="op">*</span> <span class="bu">max</span>(<span class="dv">3</span>, <span class="dv">92</span> <span class="op">-</span> <span class="bu">len</span>(kopf)))</span>
|
||||
<span id="cb225-167"><a href="#cb225-167" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f" </span><span class="sc">{</span><span class="st">'Bibliothek'</span><span class="sc">:<16}</span><span class="ss"> </span><span class="sc">{</span><span class="st">'Zielwert'</span><span class="sc">:>14}</span><span class="ss"> </span><span class="sc">{</span><span class="st">'Aufbau'</span><span class="sc">:>9}</span><span class="ss"> "</span></span>
|
||||
<span id="cb225-168"><a href="#cb225-168" aria-hidden="true" tabindex="-1"></a> <span class="ss">f"</span><span class="sc">{</span><span class="st">'Loesen'</span><span class="sc">:>9}</span><span class="ss"> </span><span class="sc">{</span><span class="st">'Anteil'</span><span class="sc">:>8}</span><span class="ss"> </span><span class="sc">{</span><span class="st">'Speicher'</span><span class="sc">:>10}</span><span class="ss">"</span>)</span>
|
||||
<span id="cb225-169"><a href="#cb225-169" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" "</span> <span class="op">+</span> <span class="st">"-"</span> <span class="op">*</span> <span class="dv">72</span>)</span>
|
||||
<span id="cb225-170"><a href="#cb225-170" aria-hidden="true" tabindex="-1"></a> zielwerte <span class="op">=</span> {}</span>
|
||||
<span id="cb225-171"><a href="#cb225-171" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> name, funktion <span class="kw">in</span> ANSAETZE.items():</span>
|
||||
<span id="cb225-172"><a href="#cb225-172" aria-hidden="true" tabindex="-1"></a> werte, fehler <span class="op">=</span> messe(funktion, m, n)</span>
|
||||
<span id="cb225-173"><a href="#cb225-173" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> werte <span class="kw">is</span> <span class="va">None</span>:</span>
|
||||
<span id="cb225-174"><a href="#cb225-174" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f" </span><span class="sc">{</span>name<span class="sc">:<16}</span><span class="ss"> nicht verfuegbar: </span><span class="sc">{</span>fehler<span class="sc">}</span><span class="ss">"</span>)</span>
|
||||
<span id="cb225-175"><a href="#cb225-175" aria-hidden="true" tabindex="-1"></a> <span class="cf">continue</span></span>
|
||||
<span id="cb225-176"><a href="#cb225-176" aria-hidden="true" tabindex="-1"></a> ziel, aufbau, loesen, speicher <span class="op">=</span> werte</span>
|
||||
<span id="cb225-177"><a href="#cb225-177" aria-hidden="true" tabindex="-1"></a> zielwerte[name] <span class="op">=</span> ziel</span>
|
||||
<span id="cb225-178"><a href="#cb225-178" aria-hidden="true" tabindex="-1"></a> anteil <span class="op">=</span> aufbau <span class="op">/</span> (aufbau <span class="op">+</span> loesen) <span class="op">*</span> <span class="dv">100</span></span>
|
||||
<span id="cb225-179"><a href="#cb225-179" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f" </span><span class="sc">{</span>name<span class="sc">:<16}</span><span class="ss"> </span><span class="sc">{</span>ziel<span class="sc">:>14,.2f}</span><span class="ss"> </span><span class="sc">{</span>aufbau<span class="sc">:>8.3f}</span><span class="ss">s "</span></span>
|
||||
<span id="cb225-180"><a href="#cb225-180" aria-hidden="true" tabindex="-1"></a> <span class="ss">f"</span><span class="sc">{</span>loesen<span class="sc">:>8.3f}</span><span class="ss">s </span><span class="sc">{</span>anteil<span class="sc">:>7.0f}</span><span class="ss">% </span><span class="sc">{</span>speicher<span class="sc">:>9.0f}</span><span class="ss"> MB"</span>)</span>
|
||||
<span id="cb225-181"><a href="#cb225-181" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb225-182"><a href="#cb225-182" aria-hidden="true" tabindex="-1"></a> <span class="co"># Die wichtigste Zeile: Rechnen alle dasselbe aus?</span></span>
|
||||
<span id="cb225-183"><a href="#cb225-183" aria-hidden="true" tabindex="-1"></a> spanne <span class="op">=</span> <span class="bu">max</span>(zielwerte.values()) <span class="op">-</span> <span class="bu">min</span>(zielwerte.values())</span>
|
||||
<span id="cb225-184"><a href="#cb225-184" aria-hidden="true" tabindex="-1"></a> bezug <span class="op">=</span> <span class="bu">max</span>(<span class="bu">abs</span>(v) <span class="cf">for</span> v <span class="kw">in</span> zielwerte.values())</span>
|
||||
<span id="cb225-185"><a href="#cb225-185" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f" </span><span class="sc">{</span><span class="st">''</span><span class="sc">:16}</span><span class="ss"> Spannweite der Zielwerte: </span><span class="sc">{</span>spanne<span class="sc">:.2e}</span><span class="ss"> "</span></span>
|
||||
<span id="cb225-186"><a href="#cb225-186" aria-hidden="true" tabindex="-1"></a> <span class="ss">f"(relativ </span><span class="sc">{</span>spanne <span class="op">/</span> bezug<span class="sc">:.1e}</span><span class="ss">)"</span>)</span>
|
||||
<span id="cb225-187"><a href="#cb225-187" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> spanne <span class="op">/</span> bezug <span class="op">></span> <span class="fl">1e-6</span>:</span>
|
||||
<span id="cb225-188"><a href="#cb225-188" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" ACHTUNG: Die Bibliotheken widersprechen sich - "</span></span>
|
||||
<span id="cb225-189"><a href="#cb225-189" aria-hidden="true" tabindex="-1"></a> <span class="st">"der Zeitvergleich ist wertlos."</span>)</span>
|
||||
<span id="cb225-190"><a href="#cb225-190" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>()</span>
|
||||
<span id="cb225-191"><a href="#cb225-191" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb225-192"><a href="#cb225-192" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"="</span> <span class="op">*</span> <span class="dv">92</span>)</span>
|
||||
<span id="cb225-193"><a href="#cb225-193" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" WAS MAN AUS SO EINER TABELLE ABLESEN DARF - UND WAS NICHT"</span>)</span>
|
||||
<span id="cb225-194"><a href="#cb225-194" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"="</span> <span class="op">*</span> <span class="dv">92</span>)</span>
|
||||
<span id="cb225-195"><a href="#cb225-195" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"DARF man ablesen:"</span>)</span>
|
||||
<span id="cb225-196"><a href="#cb225-196" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" * Die Spalte 'Anteil' - wie viel der Zeit in den AUFBAU geht statt"</span>)</span>
|
||||
<span id="cb225-197"><a href="#cb225-197" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" ins Loesen. Wenn dort 80 </span><span class="sc">% s</span><span class="st">tehen, ist ein schnellerer Solver die"</span>)</span>
|
||||
<span id="cb225-198"><a href="#cb225-198" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" falsche Antwort; dann gehoert das Modell vektorisiert aufgebaut"</span>)</span>
|
||||
<span id="cb225-199"><a href="#cb225-199" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" (Kapitel Oekosystem)."</span>)</span>
|
||||
<span id="cb225-200"><a href="#cb225-200" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" * Die Groessenordnung des Speicherbedarfs. Sie entscheidet, was auf"</span>)</span>
|
||||
<span id="cb225-201"><a href="#cb225-201" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" einer bestimmten Maschine ueberhaupt laeuft."</span>)</span>
|
||||
<span id="cb225-202"><a href="#cb225-202" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" * Wie sich beides mit der Groesse ENTWICKELT. Der Trend ist"</span>)</span>
|
||||
<span id="cb225-203"><a href="#cb225-203" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" uebertragbarer als der Absolutwert."</span>)</span>
|
||||
<span id="cb225-204"><a href="#cb225-204" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>()</span>
|
||||
<span id="cb225-205"><a href="#cb225-205" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"NICHT ablesen darf man:"</span>)</span>
|
||||
<span id="cb225-206"><a href="#cb225-206" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" * 'Bibliothek X ist schneller als Y.' Gemessen wurde EIN"</span>)</span>
|
||||
<span id="cb225-207"><a href="#cb225-207" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" Problemtyp in EINER Formulierung. Ein MILP, ein QP oder eine"</span>)</span>
|
||||
<span id="cb225-208"><a href="#cb225-208" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" andere Modellierung desselben Problems koennen die Reihenfolge"</span>)</span>
|
||||
<span id="cb225-209"><a href="#cb225-209" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" umdrehen."</span>)</span>
|
||||
<span id="cb225-210"><a href="#cb225-210" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" * Etwas ueber Ihre Maschine. Diese Zahlen stammen von einer"</span>)</span>
|
||||
<span id="cb225-211"><a href="#cb225-211" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" anderen. Der Sinn des Programms ist, dass Sie es auf Ihrer"</span>)</span>
|
||||
<span id="cb225-212"><a href="#cb225-212" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">" laufen lassen."</span>)</span>
|
||||
<span id="cb225-213"><a href="#cb225-213" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">"="</span> <span class="op">*</span> <span class="dv">92</span>)</span></code></pre></div>
|
||||
<p><strong>Erwartete Ausgabe</strong> (Zeiten und Speicher hardwareabhängig, die Zielwerte nicht):</p>
|
||||
<pre><code>============================================================================================
|
||||
SKALIERUNGSVERGLEICH: TRANSPORTPROBLEM, VIER BIBLIOTHEKEN
|
||||
|
|
@ -29011,28 +29081,28 @@ die Zielwerte und ihr Verhaeltnis zueinander nicht.
|
|||
--- 10 Lager x 10 Kunden = 100 Variablen ---------------------------------------------------
|
||||
Bibliothek Zielwert Aufbau Loesen Anteil Speicher
|
||||
------------------------------------------------------------------------
|
||||
scipy.linprog 13,509.48 0.000s 0.004s 1% 78 MB
|
||||
highspy 13,509.48 0.001s 0.002s 34% 41 MB
|
||||
ortools/GLOP 13,509.48 0.002s 0.001s 80% 54 MB
|
||||
scipy.linprog 13,509.48 0.000s 0.004s 1% 79 MB
|
||||
highspy 13,509.48 0.001s 0.002s 36% 44 MB
|
||||
ortools/GLOP 13,509.48 0.003s 0.001s 80% 56 MB
|
||||
cvxpy 13,509.48 0.001s 0.009s 9% 229 MB
|
||||
Spannweite der Zielwerte: 1.33e-06 (relativ 9.8e-11)
|
||||
|
||||
--- 32 Lager x 32 Kunden = 1,024 Variablen -------------------------------------------------
|
||||
Bibliothek Zielwert Aufbau Loesen Anteil Speicher
|
||||
------------------------------------------------------------------------
|
||||
scipy.linprog 35,744.25 0.000s 0.009s 4% 80 MB
|
||||
highspy 35,744.25 0.004s 0.005s 47% 42 MB
|
||||
ortools/GLOP 35,744.25 0.015s 0.002s 85% 55 MB
|
||||
cvxpy 35,744.25 0.001s 0.016s 5% 230 MB
|
||||
scipy.linprog 35,744.25 0.000s 0.009s 3% 81 MB
|
||||
highspy 35,744.25 0.004s 0.005s 44% 45 MB
|
||||
ortools/GLOP 35,744.25 0.014s 0.002s 85% 58 MB
|
||||
cvxpy 35,744.25 0.001s 0.017s 5% 231 MB
|
||||
Spannweite der Zielwerte: 9.54e-05 (relativ 2.7e-09)
|
||||
|
||||
--- 100 Lager x 100 Kunden = 10,000 Variablen ----------------------------------------------
|
||||
Bibliothek Zielwert Aufbau Loesen Anteil Speicher
|
||||
------------------------------------------------------------------------
|
||||
scipy.linprog 72,220.34 0.002s 0.070s 3% 120 MB
|
||||
highspy 72,220.34 0.029s 0.034s 45% 47 MB
|
||||
ortools/GLOP 72,220.34 0.123s 0.036s 77% 66 MB
|
||||
cvxpy 72,220.34 0.001s 0.103s 1% 242 MB
|
||||
scipy.linprog 72,220.34 0.004s 0.072s 5% 122 MB
|
||||
highspy 72,220.34 0.026s 0.032s 45% 50 MB
|
||||
ortools/GLOP 72,220.34 0.141s 0.043s 77% 68 MB
|
||||
cvxpy 72,220.34 0.001s 0.108s 1% 242 MB
|
||||
Spannweite der Zielwerte: 3.65e-04 (relativ 5.0e-09)
|
||||
|
||||
============================================================================================
|
||||
|
|
@ -32374,7 +32444,7 @@ Insgesamt 2874 Solveraufrufe fuer die gesamte Diagnose.
|
|||
<h2 id="c9-importfehler">C9 — Importfehler</h2>
|
||||
<pre><code>ImportError: .../highspy/_core...so: undefined symbol: _ZN5Highs13releaseMemoryEv</code></pre>
|
||||
<p><strong>Ursache.</strong> <code>ortools</code> und <code>highspy</code> bringen beide eine eigene HiGHS-Kopie mit; sie lassen sich auf vielen Systemen <strong>nicht im selben Prozess</strong> importieren (siehe <a href="#sec:oekosystem-ein-system-vier-programmieransaetze">Abschnitt 3.5</a>). Der Konflikt entsteht auch <strong>indirekt</strong>: <code>cvxpy</code> importiert ein installiertes <code>highspy</code> bei der Solver-Erkennung selbst mit — ein Skript, das erst <code>cvxpy</code> und dann <code>ortools</code> importiert, crasht daher mit derselben Meldung.</p>
|
||||
<p><strong>Abhilfen (in dieser Reihenfolge):</strong> 1. Nur eines von beiden im selben Skript verwenden. 2. Getrennte Prozesse (<code>subprocess</code>) — siehe <code>Ein_System_Vier_Ansaetze.py</code>. 3. Auf <code>highspy</code> verzichten: HiGHS ist ohnehin Backend von <code>scipy.optimize.linprog</code> und CVXPY. 4. Getrennte virtuelle Umgebungen.</p>
|
||||
<p><strong>Abhilfen (in dieser Reihenfolge):</strong> 1. Nur eines von beiden im selben Skript verwenden. 2. Getrennte Prozesse — ein <code>ProcessPoolExecutor</code> mit <code>mp_context="spawn"</code> und <code>max_tasks_per_child=1</code>, siehe <code>Ein_System_Vier_Ansaetze.py</code>. 3. Auf <code>highspy</code> verzichten: HiGHS ist ohnehin Backend von <code>scipy.optimize.linprog</code> und CVXPY. 4. Getrennte virtuelle Umgebungen.</p>
|
||||
<hr />
|
||||
<h2 id="c10-verdächtig-guter-backtest">C10 — Verdächtig guter Backtest</h2>
|
||||
<p><strong>Faustregel:</strong> Eine Sharpe Ratio über 2 bei einer einfachen Strategie ist fast immer ein Fehler, kein Fund.</p>
|
||||
|
|
|
|||
Loading…
Reference in a new issue