kleine Änderungen
195
bilder_04/erzeuge_3d_konvexitaet.py
Normal file
|
|
@ -0,0 +1,195 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# erzeuge_3d_konvexitaet.py
|
||||
"""
|
||||
Erzeugt die Landschaftsgrafik zum Abschnitt Konvexitaet:
|
||||
|
||||
bilder_04/kap02_konvexitaet_landschaft.svg
|
||||
|
||||
ERGAENZT das vorhandene kap02_konvexitaet.svg, ersetzt es nicht: Jenes zeigt die
|
||||
Sehnenbedingung - die Definition. Dieses zeigt ihre Folge - dass bei einer
|
||||
nicht-konvexen Funktion der Startpunkt darueber entscheidet, was am Ende
|
||||
herauskommt.
|
||||
|
||||
Beide Tafeln zeigen DIESELBE Funktion wie das Kapitelprogramm
|
||||
Konvexitaet_Demo.py:
|
||||
|
||||
links f(x) = x^2 + 3 sin(3x) - eindimensional
|
||||
rechts f(x1, x2) = x1^2 + 3 sin(3 x1) + x2^2 + 3 sin(3 x2) - separabel
|
||||
|
||||
Die rechte Funktion ist die separable Fortsetzung der linken: Auf jeder Achse
|
||||
liegt exakt die Kurve der linken Tafel. Deshalb ist die rechte Tafel keine neue
|
||||
Behauptung, sondern dieselbe eine Dimension weiter - und die Taeler, die links
|
||||
nebeneinander liegen, werden rechts zu einem Gitter aus Mulden.
|
||||
|
||||
Gerechnet wird mit BFGS aus denselben Startpunkten wie im Buchprogramm. Die
|
||||
fuenf Ergebnisse der linken Tafel muessen deshalb Ziffer fuer Ziffer der im
|
||||
Kapitel abgedruckten Tabelle entsprechen; pruefe_gegen_buch() bricht ab, wenn
|
||||
nicht. Ein Bild, das andere Minima zeigt als die Tabelle daneben, waere
|
||||
schlimmer als gar kein Bild.
|
||||
|
||||
Aufruf (aus dem Repository-Wurzelverzeichnis):
|
||||
python3 bilder_04/erzeuge_3d_konvexitaet.py
|
||||
|
||||
Benoetigt: numpy, scipy, matplotlib
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
import numpy as np
|
||||
from scipy.optimize import minimize
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||
from stil_04 import FARBEN, speichere # noqa: E402
|
||||
import matplotlib.pyplot as plt # noqa: E402
|
||||
|
||||
# Die Startpunkte des Buchprogramms - nicht selbst gewaehlt.
|
||||
STARTPUNKTE = [-3.0, -1.5, 0.0, 1.5, 3.0]
|
||||
|
||||
# Die im Kapitel abgedruckte Tabelle: Start -> (Minimum, Funktionswert).
|
||||
# Nur zum Gegenpruefen; gerechnet wird unabhaengig davon.
|
||||
TABELLE_IM_BUCH = {
|
||||
-3.0: (-2.4280, 3.3695),
|
||||
-1.5: (-0.4874, -2.7448),
|
||||
0.0: (-0.4874, -2.7448),
|
||||
1.5: (1.4606, -0.7042),
|
||||
3.0: (3.3817, 9.4570),
|
||||
}
|
||||
|
||||
|
||||
def welle(x):
|
||||
"""Die Funktion des Buchprogramms: Parabel mit aufmodulierter Welle."""
|
||||
return x ** 2 + 3.0 * np.sin(3.0 * x)
|
||||
|
||||
|
||||
def welle_1d(x):
|
||||
"""Dieselbe Funktion in der Form, die scipy.optimize erwartet."""
|
||||
return welle(x[0])
|
||||
|
||||
|
||||
def welle_2d(x):
|
||||
"""Separable Fortsetzung in zwei Dimensionen."""
|
||||
return welle(x[0]) + welle(x[1])
|
||||
|
||||
|
||||
def suche_1d():
|
||||
"""Lokale Suche von jedem Startpunkt - wie in Teil 2 des Buchprogramms."""
|
||||
ergebnisse = []
|
||||
for start in STARTPUNKTE:
|
||||
res = minimize(welle_1d, x0=[start], method="BFGS")
|
||||
ergebnisse.append((start, float(res.x[0]), float(res.fun)))
|
||||
return ergebnisse
|
||||
|
||||
|
||||
def suche_2d(start):
|
||||
"""Dieselbe lokale Suche in 2D, mit aufgezeichnetem Weg."""
|
||||
weg = [np.array(start, dtype=float)]
|
||||
minimize(welle_2d, x0=list(start), method="BFGS",
|
||||
callback=lambda xk: weg.append(np.array(xk, dtype=float)))
|
||||
return np.array(weg)
|
||||
|
||||
|
||||
def pruefe_gegen_buch(ergebnisse) -> None:
|
||||
"""Bild und abgedruckte Tabelle muessen dieselben Minima nennen."""
|
||||
for start, ort, wert in ergebnisse:
|
||||
soll_ort, soll_wert = TABELLE_IM_BUCH[start]
|
||||
if abs(ort - soll_ort) > 5e-4 or abs(wert - soll_wert) > 5e-4:
|
||||
raise SystemExit(
|
||||
f"Konvexitaets-Landschaft: Start {start:+.1f} fuehrt zu "
|
||||
f"x = {ort:.4f} (f = {wert:.4f}), das Kapitel druckt "
|
||||
f"x = {soll_ort:.4f} (f = {soll_wert:.4f}) ab.")
|
||||
gefunden = len({round(ort, 3) for _, ort, _ in ergebnisse})
|
||||
if gefunden != 4:
|
||||
raise SystemExit(
|
||||
f"Konvexitaets-Landschaft: {gefunden} verschiedene Minima, das "
|
||||
f"Kapitel druckt 4 ab.")
|
||||
|
||||
|
||||
def zeichne(ergebnisse, wege) -> None:
|
||||
figur, achsen = plt.subplots(1, 2, figsize=(10.0, 4.3))
|
||||
|
||||
# --- links: die Funktion des Buchprogramms mit ihren fuenf Laeufen -----
|
||||
links = achsen[0]
|
||||
x = np.linspace(-3.8, 3.8, 800)
|
||||
links.plot(x, welle(x), "-", color=FARBEN["haupt"], linewidth=2.0,
|
||||
zorder=3)
|
||||
bester = min(ergebnisse, key=lambda z: z[2])
|
||||
for start, ort, wert in ergebnisse:
|
||||
global_ = abs(ort - bester[1]) < 1e-3
|
||||
farbe = FARBEN["gut"] if global_ else FARBEN["fehler"]
|
||||
links.annotate("", xy=(ort, wert), xytext=(start, welle(start)),
|
||||
arrowprops=dict(arrowstyle="->", color=farbe,
|
||||
linewidth=1.4,
|
||||
connectionstyle="arc3,rad=0.18"),
|
||||
zorder=4)
|
||||
links.plot(start, welle(start), "o", color=farbe, markersize=6,
|
||||
zorder=5)
|
||||
links.plot(ort, wert, "*", color=farbe, markersize=13, zorder=6)
|
||||
links.set_xlabel("$x$")
|
||||
links.set_ylabel("$f(x)$")
|
||||
links.set_title("fünf Startpunkte, vier verschiedene Minima",
|
||||
fontsize=10.5, color=FARBEN["text"])
|
||||
links.annotate("grün: im tiefsten Tal gelandet\nrot: in einem anderen",
|
||||
xy=(0.36, 0.97), xycoords="axes fraction", fontsize=8.5,
|
||||
color=FARBEN["text"], va="top")
|
||||
|
||||
# --- rechts: dieselbe Funktion, eine Dimension weiter ------------------
|
||||
rechts = achsen[1]
|
||||
gitter = np.linspace(-3.8, 3.8, 420)
|
||||
xx, yy = np.meshgrid(gitter, gitter)
|
||||
zz = welle(xx) + welle(yy)
|
||||
rechts.contourf(xx, yy, zz, levels=28, cmap="Blues_r", alpha=0.7, zorder=1)
|
||||
rechts.contour(xx, yy, zz, levels=16, colors=[FARBEN["linie"]],
|
||||
linewidths=0.5, zorder=2)
|
||||
for name, weg, farbe, versatz, ausrichtung in wege:
|
||||
rechts.plot(weg[:, 0], weg[:, 1], "-", color=farbe, linewidth=2.2,
|
||||
zorder=4)
|
||||
rechts.plot(*weg[0], "o", color=farbe, markersize=7, zorder=5)
|
||||
rechts.plot(*weg[-1], "*", color=farbe, markersize=15, zorder=6)
|
||||
rechts.annotate(f"{name}\nf = {welle_2d(weg[-1]):.2f}",
|
||||
xy=weg[-1], xytext=versatz,
|
||||
textcoords="offset points", fontsize=8.5,
|
||||
color=farbe, fontweight="bold", ha=ausrichtung,
|
||||
zorder=7)
|
||||
rechts.set_xlabel("$x_1$")
|
||||
rechts.set_ylabel("$x_2$")
|
||||
rechts.set_title("dieselbe Funktion in zwei Dimensionen",
|
||||
fontsize=10.5, color=FARBEN["text"])
|
||||
rechts.grid(visible=False)
|
||||
|
||||
speichere(figur, "kap02_konvexitaet_landschaft")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
ergebnisse = suche_1d()
|
||||
for start, ort, wert in ergebnisse:
|
||||
print(f" Start {start:>5.1f} -> x = {ort:>8.4f} f = {wert:>8.4f}")
|
||||
pruefe_gegen_buch(ergebnisse)
|
||||
print(" stimmt mit der abgedruckten Tabelle überein (5 Zeilen, 4 Minima)")
|
||||
|
||||
weg_a = suche_2d((-1.4, -1.6))
|
||||
weg_b = suche_2d((2.9, 3.1))
|
||||
if welle_2d(weg_a[-1]) >= welle_2d(weg_b[-1]):
|
||||
raise SystemExit("Konvexitaets-Landschaft: Lauf A landet nicht "
|
||||
"tiefer als Lauf B - Farben und Aussage verkehrt.")
|
||||
if np.linalg.norm(weg_a[-1] - weg_b[-1]) < 1.0:
|
||||
raise SystemExit("Konvexitaets-Landschaft: Beide 2D-Laeufe enden im "
|
||||
"selben Tal - dann ist keine Falle zu sehen.")
|
||||
# Der Begleittext nennt diesen Abstand ("mehr als 24 Einheiten").
|
||||
abstand = welle_2d(weg_b[-1]) - welle_2d(weg_a[-1])
|
||||
if not 24.0 <= abstand < 25.0:
|
||||
raise SystemExit(
|
||||
f"Konvexitaets-Landschaft: Der Abstand der beiden Laeufe betraegt "
|
||||
f"{abstand:.2f} Einheiten. Der Text im Kapitel sagt 'mehr als 24' "
|
||||
f"- beides muss zusammenpassen.")
|
||||
print(f" 2D: Lauf A endet bei f = {welle_2d(weg_a[-1]):.2f}, "
|
||||
f"Lauf B bei f = {welle_2d(weg_b[-1]):.2f}")
|
||||
|
||||
# Versatz und Ausrichtung der Beschriftung: Lauf B endet in der oberen
|
||||
# rechten Ecke, dort muss der Text nach innen zeigen.
|
||||
zeichne(ergebnisse,
|
||||
[("Start A", weg_a, FARBEN["gut"], (16, 16), "left"),
|
||||
("Start B", weg_b, FARBEN["fehler"], (-14, -30), "right")])
|
||||
189
bilder_04/erzeuge_bnb_geometrie.py
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# erzeuge_bnb_geometrie.py
|
||||
"""
|
||||
Erzeugt die geometrische Tafel zum Branch-and-Bound im MILP-Kapitel:
|
||||
|
||||
bilder_04/kap_milp_bnb_geometrie.svg
|
||||
|
||||
ERGAENZT den Suchbaum kap_milp_suchbaum.svg, ersetzt ihn nicht: Der Baum zeigt,
|
||||
WELCHE Teilprobleme entstehen. Diese Tafel zeigt, WAS Verzweigen mit dem
|
||||
Loesungsraum macht - und warum es erlaubt ist.
|
||||
|
||||
Links das Polyeder der LP-Relaxation mit seinem Optimum (3; 1,5). Rechts
|
||||
dasselbe Polyeder, aus dem der Streifen 1 < x2 < 2 herausgeschnitten ist; uebrig
|
||||
bleiben die Aeste A (x2 <= 1) und B (x2 >= 2) mit ihren eigenen Optima.
|
||||
|
||||
Der Punkt, auf den es ankommt: In dem herausgeschnittenen Streifen liegt KEIN
|
||||
einziger ganzzahliger Punkt - es geht also nichts verloren. Der Streifen
|
||||
enthaelt aber das Optimum der Relaxation, und deshalb sinkt die Schranke von 21
|
||||
auf 20,67 bzw. 18. Verzweigen heisst, wertlosen Raum wegzuschneiden, bis der
|
||||
beste verbleibende Punkt ganzzahlig ist.
|
||||
|
||||
Modell und LP-Loeser stammen aus erzeuge_branch_and_bound.py, damit Baum und
|
||||
Geometrie nicht auseinanderlaufen koennen. pruefe_befund() rechnet nach, dass im
|
||||
Streifen wirklich kein ganzzahliger Punkt liegt und dass die drei Zielwerte die
|
||||
des Baums sind.
|
||||
|
||||
Aufruf (aus dem Repository-Wurzelverzeichnis):
|
||||
python3 bilder_04/erzeuge_bnb_geometrie.py
|
||||
|
||||
Benoetigt: numpy, scipy, matplotlib
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import itertools
|
||||
import os
|
||||
import sys
|
||||
|
||||
import numpy as np
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||
from stil_04 import FARBEN, speichere # noqa: E402
|
||||
import matplotlib.pyplot as plt # noqa: E402
|
||||
from erzeuge_branch_and_bound import A, B, C, loese # noqa: E402
|
||||
|
||||
# Die Verzweigung, die der Baum als Erstes vornimmt: x2 <= 1 gegen x2 >= 2.
|
||||
GRENZE = 1.0
|
||||
|
||||
# Was der Suchbaum ausweist; nur zum Gegenpruefen.
|
||||
SCHRANKEN_IM_BAUM = {"P0": 21.0, "A": 62.0 / 3.0, "B": 18.0}
|
||||
|
||||
|
||||
def gitter(masche: int = 420):
|
||||
x1 = np.linspace(0, 4.6, masche)
|
||||
x2 = np.linspace(0, 3.4, masche)
|
||||
return np.meshgrid(x1, x2)
|
||||
|
||||
|
||||
def zulaessig(xx1, xx2, unten=None, oben=None):
|
||||
"""Maske des zulaessigen Bereichs, wahlweise mit zusaetzlichen Schranken."""
|
||||
maske = np.ones_like(xx1, dtype=bool)
|
||||
for zeile, grenze in zip(A, B):
|
||||
maske &= (zeile[0] * xx1 + zeile[1] * xx2 <= grenze + 1e-9)
|
||||
if unten is not None:
|
||||
maske &= (xx2 >= unten - 1e-9)
|
||||
if oben is not None:
|
||||
maske &= (xx2 <= oben + 1e-9)
|
||||
return maske
|
||||
|
||||
|
||||
def ganzzahlige_punkte():
|
||||
"""Alle ganzzahligen zulaessigen Punkte - fuer die Tafel und den Test."""
|
||||
punkte = []
|
||||
for p1, p2 in itertools.product(range(0, 6), range(0, 5)):
|
||||
if np.all(A @ np.array([p1, p2], dtype=float) <= B + 1e-9):
|
||||
punkte.append((p1, p2))
|
||||
return punkte
|
||||
|
||||
|
||||
def pruefe_befund(loesungen, punkte) -> None:
|
||||
"""Die beiden Aussagen der Tafel muessen stimmen."""
|
||||
im_streifen = [p for p in punkte if GRENZE < p[1] < GRENZE + 1]
|
||||
if im_streifen:
|
||||
raise SystemExit(
|
||||
f"B&B-Geometrie: Im herausgeschnittenen Streifen liegen die "
|
||||
f"ganzzahligen Punkte {im_streifen}. Dann waere das Verzweigen "
|
||||
f"nicht verlustfrei, und die Tafel behauptete etwas Falsches.")
|
||||
for name, soll in SCHRANKEN_IM_BAUM.items():
|
||||
ist = loesungen[name][1]
|
||||
if abs(ist - soll) > 1e-6:
|
||||
raise SystemExit(
|
||||
f"B&B-Geometrie: {name} hat den Zielwert {ist:.4f}, der "
|
||||
f"Suchbaum weist {soll:.4f} aus.")
|
||||
|
||||
|
||||
def zahl(wert: float) -> str:
|
||||
return f"{wert:.2f}".rstrip("0").rstrip(".").replace(".", ",")
|
||||
|
||||
|
||||
def zeichne(loesungen, punkte) -> None:
|
||||
figur, achsen = plt.subplots(1, 2, figsize=(10.0, 4.5))
|
||||
xx1, xx2 = gitter()
|
||||
|
||||
for achse in achsen:
|
||||
for p1, p2 in punkte:
|
||||
achse.plot(p1, p2, "o", color=FARBEN["gedaempft"], markersize=4.5,
|
||||
zorder=5)
|
||||
for zeile, grenze in zip(A, B):
|
||||
x = np.linspace(0, 4.6, 100)
|
||||
achse.plot(x, (grenze - zeile[0] * x) / zeile[1], "--",
|
||||
color=FARBEN["linie"], linewidth=1.1, zorder=3)
|
||||
achse.set_xlim(0, 4.6)
|
||||
achse.set_ylim(0, 3.4)
|
||||
achse.set_xlabel("$x_1$")
|
||||
achse.grid(linestyle=":", alpha=0.4)
|
||||
|
||||
achsen[0].set_ylabel("$x_2$")
|
||||
|
||||
# --- links: die Relaxation, ungeschnitten -----------------------------
|
||||
achsen[0].contourf(xx1, xx2, zulaessig(xx1, xx2).astype(float),
|
||||
levels=[0.5, 1.5], colors=[FARBEN["haupt"]],
|
||||
alpha=0.20, zorder=1)
|
||||
x_p0, z_p0 = loesungen["P0"]
|
||||
achsen[0].plot(*x_p0, "*", color=FARBEN["fehler"], markersize=17, zorder=6)
|
||||
achsen[0].annotate(f"LP-Optimum ({zahl(x_p0[0])}; {zahl(x_p0[1])})\n"
|
||||
f"Z = {zahl(z_p0)} — nicht ganzzahlig",
|
||||
xy=x_p0, xytext=(12, 12), textcoords="offset points",
|
||||
fontsize=8.5, color=FARBEN["fehler"],
|
||||
fontweight="bold", zorder=7)
|
||||
achsen[0].set_title("$P_0$ — die Relaxation", fontsize=10.5,
|
||||
color=FARBEN["text"])
|
||||
|
||||
# --- rechts: derselbe Bereich, der Streifen heraus ---------------------
|
||||
for name, unten, oben, farbe, beschriftung in (
|
||||
("A", None, GRENZE, FARBEN["zweit"], f"Ast A: $x_2 \\leq 1$"),
|
||||
("B", GRENZE + 1, None, FARBEN["warnung"],
|
||||
f"Ast B: $x_2 \\geq 2$")):
|
||||
achsen[1].contourf(xx1, xx2,
|
||||
zulaessig(xx1, xx2, unten, oben).astype(float),
|
||||
levels=[0.5, 1.5], colors=[farbe], alpha=0.22,
|
||||
zorder=1)
|
||||
x_ast, z_ast = loesungen[name]
|
||||
achsen[1].plot(*x_ast, "*", color=farbe, markersize=15, zorder=6)
|
||||
# Ast A liegt an der Schnittkante; sein Text gehoert nach unten in die
|
||||
# eigene Flaeche, sonst laeuft er in den Streifen hinein.
|
||||
achsen[1].annotate(f"{beschriftung}\nZ = {zahl(z_ast)}",
|
||||
xy=x_ast,
|
||||
xytext=(-12, -30) if name == "A" else (12, 14),
|
||||
textcoords="offset points", fontsize=8.5,
|
||||
ha="right" if name == "A" else "left",
|
||||
color=farbe, fontweight="bold", zorder=7)
|
||||
|
||||
achsen[1].axhspan(GRENZE, GRENZE + 1, color=FARBEN["fehler"], alpha=0.11,
|
||||
zorder=2)
|
||||
achsen[1].axhline(GRENZE, color=FARBEN["fehler"], linewidth=1.3, zorder=4)
|
||||
achsen[1].axhline(GRENZE + 1, color=FARBEN["fehler"], linewidth=1.3,
|
||||
zorder=4)
|
||||
achsen[1].text(4.5, GRENZE + 0.5,
|
||||
"herausgeschnitten:\n$1 < x_2 < 2$\nkein ganzzahliger "
|
||||
"Punkt darin", fontsize=8, color=FARBEN["fehler"],
|
||||
ha="right", va="center", zorder=7)
|
||||
achsen[1].set_title("nach dem Verzweigen über $x_2$", fontsize=10.5,
|
||||
color=FARBEN["text"])
|
||||
|
||||
figur.suptitle(f"Verzweigen schneidet weg, wo kein ganzzahliger Punkt "
|
||||
f"liegt — die Schranke sinkt von {zahl(z_p0)} auf "
|
||||
f"{zahl(max(loesungen['A'][1], loesungen['B'][1]))}",
|
||||
fontsize=10.5, color=FARBEN["text"], y=1.02)
|
||||
speichere(figur, "kap_milp_bnb_geometrie")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unendlich = float("inf")
|
||||
loesungen = {
|
||||
"P0": loese([0.0, 0.0], [unendlich, unendlich]),
|
||||
"A": loese([0.0, 0.0], [unendlich, GRENZE]),
|
||||
"B": loese([0.0, GRENZE + 1], [unendlich, unendlich]),
|
||||
}
|
||||
punkte = ganzzahlige_punkte()
|
||||
for name, (x, z) in loesungen.items():
|
||||
print(f" {name:<3} x = ({x[0]:.4f}; {x[1]:.4f}) Z = {z:.4f}")
|
||||
print(f" {len(punkte)} ganzzahlige zulässige Punkte")
|
||||
|
||||
pruefe_befund(loesungen, punkte)
|
||||
print(" Streifen 1 < x₂ < 2 enthält keinen ganzzahligen Punkt")
|
||||
print(" Zielwerte stimmen mit dem Suchbaum überein")
|
||||
|
||||
zeichne(loesungen, punkte)
|
||||
190
bilder_04/erzeuge_dualitaets_bruecke.py
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# erzeuge_dualitaets_bruecke.py
|
||||
"""
|
||||
Erzeugt die Doppeltafel zum starken Dualitaetssatz:
|
||||
|
||||
bilder_04/kap_lp_dualitaets_bruecke.svg
|
||||
|
||||
ERGAENZT das vorhandene kap04_primal_dual.svg, ersetzt es nicht: Jenes stellt
|
||||
die beiden Probleme schematisch gegenueber - wer fragt was. Dieses zeigt ihre
|
||||
Geometrie und damit den Satz selbst.
|
||||
|
||||
Links der primale Mengenraum (x1, x2): ein beschraenktes Polyeder, das Maximum
|
||||
in einer Ecke. Rechts der duale Preisraum (y1, y2): ein nach oben offener
|
||||
Bereich, das Minimum ebenfalls in einer Ecke. Die beiden Bereiche haben nichts
|
||||
miteinander gemein - andere Achsen, andere Einheiten, der eine beschraenkt, der
|
||||
andere nicht. Trotzdem steht an beiden Optima dieselbe Zahl. Das ist der Satz,
|
||||
und das ist der einzige Grund fuer die Doppeltafel.
|
||||
|
||||
Der duale Raum hat drei Variablen; gezeichnet wird die Ebene y3 = 0. Das ist
|
||||
keine Vereinfachung, sondern folgt aus dem komplementaeren Schlupf: Das
|
||||
Marktlimit x1 <= 8 ist bei x1* = 7,5 nicht bindend, also ist y3* = 0. Der
|
||||
Selbsttest rechnet nach, dass das Minimum in dieser Ebene wirklich das Minimum
|
||||
des vollen Dualproblems ist - sonst zeigte die rechte Tafel einen zu grossen
|
||||
Wert und der optische Beweis waere keiner.
|
||||
|
||||
Modell und Loesung stammen aus dem Kapitelprogramm Dualitaet_Nachweis.py; hier
|
||||
wird nichts nachgebaut und nichts eingetragen.
|
||||
|
||||
Aufruf (aus dem Repository-Wurzelverzeichnis):
|
||||
python3 bilder_04/erzeuge_dualitaets_bruecke.py
|
||||
|
||||
Benoetigt: numpy, scipy, matplotlib
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import itertools
|
||||
import os
|
||||
import sys
|
||||
|
||||
import numpy as np
|
||||
|
||||
HIER = os.path.dirname(os.path.abspath(__file__))
|
||||
BASIS = os.path.dirname(HIER)
|
||||
sys.path.insert(0, HIER)
|
||||
sys.path.insert(0, os.path.join(
|
||||
BASIS, "Operations_Research_mit_Python_Version_04_Programme"))
|
||||
|
||||
from stil_04 import FARBEN, speichere # noqa: E402
|
||||
import matplotlib.pyplot as plt # noqa: E402
|
||||
from Dualitaet_Nachweis import (A_PRIMAL, B_PRIMAL, # noqa: E402
|
||||
C_PRIMAL, loese)
|
||||
|
||||
|
||||
def ecken(A: np.ndarray, b: np.ndarray) -> np.ndarray:
|
||||
"""Ecken des Bereichs {x >= 0 : A x <= b}, gegen den Uhrzeigersinn.
|
||||
|
||||
Alle Paare von Randgeraden schneiden (die Achsen zaehlen mit), die
|
||||
unzulaessigen Schnittpunkte verwerfen, den Rest um den Schwerpunkt
|
||||
sortieren. Fuer zwei Dimensionen ist das vollstaendig."""
|
||||
zeilen = np.vstack([A, [[-1.0, 0.0], [0.0, -1.0]]])
|
||||
rechte = np.concatenate([b, [0.0, 0.0]])
|
||||
punkte = []
|
||||
for i, j in itertools.combinations(range(len(zeilen)), 2):
|
||||
M = zeilen[[i, j]]
|
||||
if abs(np.linalg.det(M)) < 1e-9:
|
||||
continue
|
||||
p = np.linalg.solve(M, rechte[[i, j]])
|
||||
if np.all(zeilen @ p <= rechte + 1e-9):
|
||||
punkte.append(p)
|
||||
punkte = np.unique(np.round(punkte, 9), axis=0)
|
||||
mitte = punkte.mean(axis=0)
|
||||
winkel = np.arctan2(punkte[:, 1] - mitte[1], punkte[:, 0] - mitte[0])
|
||||
return punkte[np.argsort(winkel)]
|
||||
|
||||
|
||||
def zeichne(x_stern, z_stern, y_stern, w_stern) -> None:
|
||||
figur, achsen = plt.subplots(1, 2, figsize=(10.2, 4.6))
|
||||
beschriftung = f"{z_stern:,.0f} €".replace(",", ".")
|
||||
|
||||
# --- links: der primale Mengenraum ------------------------------------
|
||||
links = achsen[0]
|
||||
polygon = ecken(A_PRIMAL, B_PRIMAL)
|
||||
links.fill(polygon[:, 0], polygon[:, 1], color=FARBEN["haupt"],
|
||||
alpha=0.18, zorder=2)
|
||||
links.plot(np.append(polygon[:, 0], polygon[0, 0]),
|
||||
np.append(polygon[:, 1], polygon[0, 1]), "-",
|
||||
color=FARBEN["haupt"], linewidth=1.8, zorder=3)
|
||||
|
||||
x1 = np.linspace(0, 11, 200)
|
||||
# Ein Niveau unter dem Optimum, das Optimum selbst, eines darueber - das
|
||||
# obere liegt sichtbar ausserhalb des Polyeders, und genau das ist die
|
||||
# Aussage: weiter geht es nicht.
|
||||
for niveau, stil in ((1500.0, ":"), (z_stern, "--"), (3000.0, ":")):
|
||||
# 150 x1 + 250 x2 = niveau
|
||||
links.plot(x1, (niveau - C_PRIMAL[0] * x1) / C_PRIMAL[1], stil,
|
||||
color=FARBEN["warnung"], linewidth=1.4, zorder=4)
|
||||
links.annotate("", xy=(4.2, 4.2), xytext=(2.4, 3.1),
|
||||
arrowprops=dict(arrowstyle="-|>", color=FARBEN["warnung"],
|
||||
linewidth=2.0), zorder=5)
|
||||
links.text(4.35, 4.25, r"$\mathbf{c} = (150, 250)^\top$", fontsize=8.5,
|
||||
color=FARBEN["warnung"])
|
||||
|
||||
links.plot(*x_stern, "*", color=FARBEN["gut"], markersize=17, zorder=6)
|
||||
links.annotate(f"$\\mathbf{{x}}^* = ({x_stern[0]:.1f}\\,;\\,"
|
||||
f"{x_stern[1]:.0f})$\n$Z^* = {beschriftung}$",
|
||||
xy=x_stern, xytext=(4.55, 1.05), textcoords="data",
|
||||
fontsize=9, color=FARBEN["gut"], fontweight="bold",
|
||||
ha="left", zorder=7,
|
||||
arrowprops=dict(arrowstyle="-", color=FARBEN["gut"],
|
||||
linewidth=1.0, alpha=0.7))
|
||||
links.set_xlim(0, 11)
|
||||
links.set_ylim(0, 9)
|
||||
links.set_xlabel("$x_1$ — Bots Typ A")
|
||||
links.set_ylabel("$x_2$ — Bots Typ B")
|
||||
links.set_title("primal: Mengen — maximieren, beschränkt",
|
||||
fontsize=10.5, color=FARBEN["text"])
|
||||
|
||||
# --- rechts: der duale Preisraum, Ebene y3 = 0 ------------------------
|
||||
rechts = achsen[1]
|
||||
g1 = np.linspace(0, 55, 320)
|
||||
g2 = np.linspace(0, 55, 320)
|
||||
yy1, yy2 = np.meshgrid(g1, g2)
|
||||
# A^T y >= c, hier ohne y3: 2 y1 + 4 y2 >= 150 und 5 y1 + 6 y2 >= 250
|
||||
zulaessig = ((A_PRIMAL[0, 0] * yy1 + A_PRIMAL[1, 0] * yy2
|
||||
>= C_PRIMAL[0] - 1e-9)
|
||||
& (A_PRIMAL[0, 1] * yy1 + A_PRIMAL[1, 1] * yy2
|
||||
>= C_PRIMAL[1] - 1e-9))
|
||||
rechts.contourf(yy1, yy2, zulaessig.astype(float), levels=[0.5, 1.5],
|
||||
colors=[FARBEN["zweit"]], alpha=0.18, zorder=2)
|
||||
for spalte, farbe in ((0, FARBEN["zweit"]), (1, FARBEN["zweit"])):
|
||||
# A[0, spalte] * y1 + A[1, spalte] * y2 = c[spalte]
|
||||
rechts.plot(g1, (C_PRIMAL[spalte] - A_PRIMAL[0, spalte] * g1)
|
||||
/ A_PRIMAL[1, spalte], "-", color=farbe, linewidth=1.8,
|
||||
zorder=3)
|
||||
|
||||
for niveau, stil in ((1200.0, ":"), (w_stern, "--"), (3600.0, ":")):
|
||||
# 40 y1 + 60 y2 = niveau
|
||||
rechts.plot(g1, (niveau - B_PRIMAL[0] * g1) / B_PRIMAL[1], stil,
|
||||
color=FARBEN["warnung"], linewidth=1.4, zorder=4)
|
||||
|
||||
rechts.plot(y_stern[0], y_stern[1], "*", color=FARBEN["gut"],
|
||||
markersize=17, zorder=6)
|
||||
rechts.annotate(f"$\\mathbf{{y}}^* = ({y_stern[0]:.2f}\\,;\\,"
|
||||
f"{y_stern[1]:.2f})$\n$W^* = "
|
||||
f"{f'{w_stern:,.0f}'.replace(',', '.')}$ €",
|
||||
xy=(y_stern[0], y_stern[1]), xytext=(14, 16),
|
||||
textcoords="offset points", fontsize=9,
|
||||
color=FARBEN["gut"], fontweight="bold", zorder=7)
|
||||
rechts.annotate("zulässig: nach oben offen —\nteurer geht immer",
|
||||
xy=(0.04, 0.97), xycoords="axes fraction", fontsize=8.5,
|
||||
color=FARBEN["text"], va="top")
|
||||
rechts.set_xlim(0, 55)
|
||||
rechts.set_ylim(0, 55)
|
||||
rechts.set_xlabel("$y_1$ — Preis je vCPU-Stunde")
|
||||
rechts.set_ylabel("$y_2$ — Preis je GB RAM")
|
||||
rechts.set_title("dual: Preise — minimieren, unbeschränkt",
|
||||
fontsize=10.5, color=FARBEN["text"])
|
||||
|
||||
figur.suptitle(f"Zwei verschiedene Räume, ein gemeinsamer Wert: "
|
||||
f"{beschriftung}",
|
||||
fontsize=11.5, color=FARBEN["text"], y=1.01)
|
||||
speichere(figur, "kap_lp_dualitaets_bruecke")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
primal, dual = loese()
|
||||
x_stern, z_stern = primal.x, -primal.fun
|
||||
y_stern, w_stern = dual.x, dual.fun
|
||||
print(f" primal: x* = ({x_stern[0]:.4f}, {x_stern[1]:.4f}) "
|
||||
f"Z* = {z_stern:.4f}")
|
||||
print(f" dual: y* = ({y_stern[0]:.4f}, {y_stern[1]:.4f}, "
|
||||
f"{y_stern[2]:.4f}) W* = {w_stern:.4f}")
|
||||
|
||||
if abs(z_stern - w_stern) > 1e-6:
|
||||
raise SystemExit(
|
||||
f"Dualitaets-Bruecke: Z* = {z_stern:.6f}, W* = {w_stern:.6f}. "
|
||||
f"Die Tafel behauptet einen gemeinsamen Wert - er ist keiner.")
|
||||
# Die rechte Tafel zeigt die Ebene y3 = 0. Das ist nur zulaessig, wenn
|
||||
# das Optimum dort liegt.
|
||||
if abs(y_stern[2]) > 1e-9:
|
||||
raise SystemExit(
|
||||
f"Dualitaets-Bruecke: y3* = {y_stern[2]:.6f} ist nicht null. Die "
|
||||
f"gezeichnete Ebene y3 = 0 enthaelt das Optimum dann nicht.")
|
||||
print(f" starker Dualitätssatz bestätigt: "
|
||||
f"{z_stern:,.0f} €".replace(",", "."))
|
||||
print(f" y3* = 0 — die gezeichnete Ebene enthält das Optimum")
|
||||
|
||||
zeichne(x_stern, z_stern, y_stern, w_stern)
|
||||
|
|
@ -91,9 +91,43 @@ def loese() -> tuple[list[tuple[int, int, int, int]], int]:
|
|||
return plan, loeser.Value(makespan)
|
||||
|
||||
|
||||
def untere_schranke() -> int:
|
||||
"""Wie in JobShop_Intervalle.py: laengster Auftrag bzw. hoechste Maschinenlast.
|
||||
|
||||
Kein Plan kann kuerzer sein als der laengste Auftrag (seine Schritte laufen
|
||||
nacheinander) und auch nicht kuerzer als die am staerksten belegte Maschine
|
||||
(ihre Schritte koennen sich nicht ueberlappen)."""
|
||||
je_auftrag = max(sum(dauer for _, dauer in auftrag)
|
||||
for auftrag in AUFTRAEGE)
|
||||
last = [0] * len(MASCHINENNAMEN)
|
||||
for auftrag in AUFTRAEGE:
|
||||
for maschine, dauer in auftrag:
|
||||
last[maschine] += dauer
|
||||
return max(je_auftrag, max(last))
|
||||
|
||||
|
||||
def stillstaende(plan):
|
||||
"""Luecken ZWISCHEN zwei Arbeitsgaengen derselben Maschine.
|
||||
|
||||
Nur die inneren: Was eine Maschine vor ihrem ersten oder nach ihrem letzten
|
||||
Arbeitsgang tut, ist keine Luecke im Plan, sondern sein Rand."""
|
||||
luecken = []
|
||||
for maschine in range(len(MASCHINENNAMEN)):
|
||||
zeiten = sorted((beginn, beginn + dauer)
|
||||
for _, m, beginn, dauer in plan if m == maschine)
|
||||
for (_, ende), (naechster_beginn, _) in zip(zeiten, zeiten[1:]):
|
||||
if naechster_beginn > ende:
|
||||
luecken.append((maschine, ende, naechster_beginn))
|
||||
return luecken
|
||||
|
||||
|
||||
def zeichne_statisch(plan, makespan: int) -> None:
|
||||
"""Matplotlib-Fassung fuer das PDF."""
|
||||
figur, achse = plt.subplots(figsize=(9.0, 3.2))
|
||||
figur, achse = plt.subplots(figsize=(9.0, 3.4))
|
||||
for maschine, von, bis in stillstaende(plan):
|
||||
achse.barh(y=maschine, width=bis - von, left=von, height=0.55,
|
||||
facecolor="none", edgecolor="#be123c", linewidth=1.2,
|
||||
hatch="///", zorder=2)
|
||||
for auftrag, maschine, beginn, dauer in plan:
|
||||
achse.barh(y=maschine, width=dauer, left=beginn, height=0.55,
|
||||
color=FARBEN[auftrag % len(FARBEN)],
|
||||
|
|
@ -108,7 +142,21 @@ def zeichne_statisch(plan, makespan: int) -> None:
|
|||
achse.set_xlabel("Zeiteinheiten")
|
||||
achse.set_xlim(0, makespan)
|
||||
achse.set_xticks(range(makespan + 1))
|
||||
achse.set_title(f"Job-Shop-Plan, Makespan = {makespan}", fontsize=11)
|
||||
|
||||
schranke = untere_schranke()
|
||||
achse.axvline(schranke, color="#059669", linestyle="--", linewidth=1.5,
|
||||
zorder=5)
|
||||
# x in Datenkoordinaten, y als Anteil der Achsenhoehe: Die y-Achse ist
|
||||
# umgekehrt, ein fester y-Wert laege sonst ausserhalb des Bildes.
|
||||
unten = achse.get_xaxis_transform()
|
||||
# Der Makespan steht schon im Titel - hier nur die Schranke, sonst
|
||||
# stossen beide Beschriftungen aneinander.
|
||||
achse.text(schranke - 0.12, 0.03, f"untere Schranke {schranke}",
|
||||
transform=unten, fontsize=8.5, color="#059669", ha="right",
|
||||
va="bottom", zorder=6)
|
||||
achse.set_title(f"Job-Shop-Plan: Makespan {makespan}, untere Schranke "
|
||||
f"{schranke} — schraffiert steht die Maschine still",
|
||||
fontsize=11)
|
||||
achse.grid(axis="x", linestyle=":", alpha=0.5)
|
||||
for rand in ("top", "right", "left"):
|
||||
achse.spines[rand].set_visible(False)
|
||||
|
|
@ -170,6 +218,40 @@ def zeichne_interaktiv(plan, makespan: int) -> None:
|
|||
|
||||
if __name__ == "__main__":
|
||||
plan, makespan = loese()
|
||||
print(f"Makespan: {makespan}")
|
||||
schranke = untere_schranke()
|
||||
print(f"Makespan: {makespan}, untere Schranke: {schranke}")
|
||||
for maschine, von, bis in stillstaende(plan):
|
||||
print(f" Stillstand: {MASCHINENNAMEN[maschine]} von {von} bis {bis}")
|
||||
|
||||
# Gegenprobe zu den Zahlen, die das Kapitel abdruckt.
|
||||
if schranke > makespan:
|
||||
raise SystemExit(f"Gantt: Die untere Schranke {schranke} liegt ueber "
|
||||
f"dem Makespan {makespan} - eine der beiden Zahlen "
|
||||
f"ist falsch.")
|
||||
if (schranke, makespan) != (10, 11):
|
||||
raise SystemExit(f"Gantt: Schranke {schranke} / Makespan {makespan}; "
|
||||
f"das Kapitel druckt 10 / 11 ab.")
|
||||
if not any(m == 1 and von == 4 for m, von, _ in stillstaende(plan)):
|
||||
raise SystemExit("Gantt: Die Luecke in der Dreherei bei Zeitpunkt 4 "
|
||||
"fehlt - der Text daneben bespricht genau sie.")
|
||||
|
||||
# Der Text daneben rechnet vor: Die Engpassmaschine ist von 0 bis zum
|
||||
# Makespan belegt, ihre Arbeit ist die Schranke, der Rest Stillstand.
|
||||
last = [0] * len(MASCHINENNAMEN)
|
||||
for auftrag in AUFTRAEGE:
|
||||
for maschine, dauer in auftrag:
|
||||
last[maschine] += dauer
|
||||
engpass = last.index(max(last))
|
||||
leerlauf = sum(bis - von for m, von, bis in stillstaende(plan)
|
||||
if m == engpass)
|
||||
if last[engpass] + leerlauf != makespan:
|
||||
raise SystemExit(
|
||||
f"Gantt: {MASCHINENNAMEN[engpass]} arbeitet {last[engpass]} und "
|
||||
f"steht {leerlauf} still, zusammen "
|
||||
f"{last[engpass] + leerlauf} statt {makespan}. Der Text daneben "
|
||||
f"rechnet genau diese Summe vor.")
|
||||
print(f" Engpass {MASCHINENNAMEN[engpass]}: {last[engpass]} Arbeit + "
|
||||
f"{leerlauf} Stillstand = {makespan}")
|
||||
|
||||
zeichne_statisch(plan, makespan)
|
||||
zeichne_interaktiv(plan, makespan)
|
||||
|
|
|
|||
214
bilder_04/erzeuge_or_architektur.py
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# erzeuge_or_architektur.py
|
||||
"""
|
||||
Erzeugt das Schichtenbild der OR-Plattform im Kapitel Praxisfallen:
|
||||
|
||||
bilder_04/kap15_or_plattform.svg
|
||||
|
||||
ERSETZT die bisherige, von Hand gezeichnete Fassung. Der Anlass war ein
|
||||
Widerspruch: Die Tabelle im Abschnitt nennt SECHS Schichten, das gezeichnete
|
||||
Bild daneben zeigte nur FUENF. Die sechste - "Betrieb" mit Monitoring,
|
||||
Audit-Trail und Alarmen - fehlte; "Audit-Trail" kam nur noch als Beschriftung
|
||||
eines Pfeils vor. Genau so entstehen Bilder, die dem Text daneben
|
||||
widersprechen, und genau deshalb bekommt dieses hier einen Generator.
|
||||
|
||||
Die Schichten werden NICHT in diesem Skript aufgezaehlt, sondern aus der
|
||||
Tabelle des Kapitels gelesen. Damit gibt es nur eine Quelle: Wer eine Zeile in
|
||||
50_Praxis.md ergaenzt, ergaenzt das Bild mit. Fehlt die Tabelle oder aendert
|
||||
sich ihr Aufbau, bricht der Generator ab, statt ein halbes Bild zu schreiben.
|
||||
|
||||
Dargestellt wird die Kette als das, was sie ist: Die ersten fuenf Schichten
|
||||
sind ein Datenweg von den Quellsystemen bis zur Ausfuehrung. "Betrieb" ist
|
||||
keine Station auf diesem Weg, sondern liegt neben allen - Monitoring und
|
||||
Audit-Trail betreffen jede Schicht. Als sechster Kasten in der Reihe waere sie
|
||||
falsch dargestellt; deshalb steht sie als Spange daneben. Dass sie beim
|
||||
Handzeichnen ganz verschwand, hat vermutlich denselben Grund.
|
||||
|
||||
Aufruf (aus dem Repository-Wurzelverzeichnis):
|
||||
python3 bilder_04/erzeuge_or_architektur.py
|
||||
|
||||
Benoetigt: matplotlib
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||
from stil_04 import FARBEN, speichere # noqa: E402
|
||||
import matplotlib.pyplot as plt # noqa: E402
|
||||
from matplotlib.patches import FancyArrowPatch, FancyBboxPatch # noqa: E402
|
||||
|
||||
BASIS = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
KAPITEL = os.path.join(BASIS, "Operations_Research_mit_Python_Version_04",
|
||||
"50_Praxis.md")
|
||||
UEBERSCHRIFT = "## Architektur einer produktionsreifen OR-Plattform"
|
||||
|
||||
# Was zwischen den Schichten fliesst. Steht nicht in der Tabelle - die
|
||||
# beschreibt die Schichten, nicht die Uebergaenge. Fuenf Stationen in der
|
||||
# Kette ergeben VIER Pfeile; lies_schichten() rechnet das nach.
|
||||
UEBERGAENGE = [
|
||||
"Events · REST · Polling",
|
||||
"geprüfter Snapshot (JSON)",
|
||||
"Ergebnis + Kostenzerlegung",
|
||||
"Freigabe",
|
||||
]
|
||||
|
||||
# Die Schicht, die neben der Kette steht statt in ihr.
|
||||
QUERSCHNITT = "Betrieb"
|
||||
|
||||
|
||||
def saeubere(zelle: str) -> str:
|
||||
"""Markdown-Auszeichnung und Indexmarken aus einer Tabellenzelle nehmen."""
|
||||
zelle = re.sub(r"\{idx:[^}]*\}", "", zelle)
|
||||
zelle = zelle.replace("**", "").replace("`", "")
|
||||
return zelle.strip()
|
||||
|
||||
|
||||
def lies_schichten() -> list[tuple[str, str, str]]:
|
||||
"""Die Schichtentabelle des Kapitels als Liste (Schicht, Aufgabe, Werkzeuge).
|
||||
|
||||
Einzige Quelle fuer den Bildinhalt - siehe Modulkommentar."""
|
||||
with open(KAPITEL, encoding="utf-8") as datei:
|
||||
text = datei.read()
|
||||
if UEBERSCHRIFT not in text:
|
||||
raise SystemExit(f"OR-Architektur: Überschrift '{UEBERSCHRIFT}' nicht "
|
||||
f"in {os.path.basename(KAPITEL)} gefunden.")
|
||||
rest = text.split(UEBERSCHRIFT, 1)[1]
|
||||
|
||||
zeilen = []
|
||||
gefunden = False
|
||||
for zeile in rest.splitlines():
|
||||
if zeile.startswith("| Schicht |"):
|
||||
gefunden = True
|
||||
continue
|
||||
if not gefunden:
|
||||
continue
|
||||
if zeile.startswith("| ---"):
|
||||
continue
|
||||
if not zeile.startswith("|"):
|
||||
break
|
||||
felder = [saeubere(f) for f in zeile.strip().strip("|").split("|")]
|
||||
if len(felder) != 3:
|
||||
raise SystemExit(f"OR-Architektur: Tabellenzeile mit "
|
||||
f"{len(felder)} statt 3 Spalten: {zeile!r}")
|
||||
zeilen.append(tuple(felder))
|
||||
|
||||
if not zeilen:
|
||||
raise SystemExit("OR-Architektur: Die Schichtentabelle wurde nicht "
|
||||
"gefunden. Hat sich der Abschnitt geändert?")
|
||||
if zeilen[-1][0] != QUERSCHNITT:
|
||||
raise SystemExit(
|
||||
f"OR-Architektur: Die letzte Tabellenzeile heißt "
|
||||
f"'{zeilen[-1][0]}', erwartet wurde '{QUERSCHNITT}'. Diese "
|
||||
f"Schicht wird als Spange neben der Kette gezeichnet, nicht in "
|
||||
f"ihr - die Zuordnung muss stimmen.")
|
||||
# Die Kette sind alle Zeilen ausser der Querschnittsschicht; zwischen n
|
||||
# Stationen liegen n-1 Pfeile.
|
||||
if len(zeilen) - 2 != len(UEBERGAENGE):
|
||||
raise SystemExit(
|
||||
f"OR-Architektur: {len(zeilen) - 1} Stationen in der Kette "
|
||||
f"brauchen {len(zeilen) - 2} beschriftete Übergänge, es sind "
|
||||
f"aber {len(UEBERGAENGE)}. Beim Ergänzen einer Schicht gehört "
|
||||
f"ein Übergang dazu.")
|
||||
return zeilen
|
||||
|
||||
|
||||
def umbreche(text: str, breite: int) -> str:
|
||||
"""Einfacher Wortumbruch - textwrap.fill ohne den Import."""
|
||||
zeilen, aktuell = [], ""
|
||||
for wort in text.split():
|
||||
if aktuell and len(aktuell) + 1 + len(wort) > breite:
|
||||
zeilen.append(aktuell)
|
||||
aktuell = wort
|
||||
else:
|
||||
aktuell = f"{aktuell} {wort}".strip()
|
||||
if aktuell:
|
||||
zeilen.append(aktuell)
|
||||
return "\n".join(zeilen)
|
||||
|
||||
|
||||
def zeichne(schichten) -> None:
|
||||
kette = schichten[:-1]
|
||||
quer = schichten[-1]
|
||||
|
||||
figur, achse = plt.subplots(figsize=(8.8, 6.6))
|
||||
achse.set_axis_off()
|
||||
|
||||
kastenbreite, kastenhoehe = 6.4, 1.24
|
||||
abstand = 1.88
|
||||
links = 0.0
|
||||
|
||||
for stufe, (name, aufgabe, werkzeuge) in enumerate(kette):
|
||||
unten = -stufe * abstand
|
||||
achse.add_patch(FancyBboxPatch(
|
||||
(links, unten), kastenbreite, kastenhoehe,
|
||||
boxstyle="round,pad=0.02,rounding_size=0.10",
|
||||
facecolor=FARBEN["flaeche"], edgecolor=FARBEN["haupt"],
|
||||
linewidth=1.6, zorder=3))
|
||||
achse.text(links + 0.18, unten + kastenhoehe - 0.26, name,
|
||||
fontsize=10.5, color=FARBEN["haupt"], fontweight="bold",
|
||||
va="center", zorder=4)
|
||||
achse.text(links + 0.18, unten + kastenhoehe - 0.52,
|
||||
umbreche(aufgabe, 66), fontsize=8.5,
|
||||
color=FARBEN["text"], va="top", zorder=4)
|
||||
achse.text(links + 0.18, unten + 0.17,
|
||||
umbreche(werkzeuge, 70), fontsize=8,
|
||||
color=FARBEN["gedaempft"], va="bottom", style="italic",
|
||||
zorder=4)
|
||||
|
||||
if stufe < len(kette) - 1:
|
||||
pfeilspitze = unten - abstand + kastenhoehe
|
||||
achse.add_patch(FancyArrowPatch(
|
||||
(links + kastenbreite / 2, unten),
|
||||
(links + kastenbreite / 2, pfeilspitze),
|
||||
arrowstyle="-|>", mutation_scale=16,
|
||||
color=FARBEN["zweit"], linewidth=1.6, zorder=2))
|
||||
achse.text(links + kastenbreite / 2 + 0.16,
|
||||
(unten + pfeilspitze) / 2, UEBERGAENGE[stufe],
|
||||
fontsize=8, color=FARBEN["zweit"], va="center",
|
||||
zorder=4)
|
||||
|
||||
# Die Querschnittsschicht als Spange neben der ganzen Kette.
|
||||
unten_ganz = -(len(kette) - 1) * abstand
|
||||
spange_links = links + kastenbreite + 0.45
|
||||
achse.add_patch(FancyBboxPatch(
|
||||
(spange_links, unten_ganz), 0.92,
|
||||
(len(kette) - 1) * abstand + kastenhoehe,
|
||||
boxstyle="round,pad=0.02,rounding_size=0.10",
|
||||
facecolor=FARBEN["warnung"], alpha=0.13,
|
||||
edgecolor=FARBEN["warnung"], linewidth=1.6, zorder=3))
|
||||
achse.text(spange_links + 0.46,
|
||||
unten_ganz + ((len(kette) - 1) * abstand + kastenhoehe) / 2,
|
||||
f"{quer[0]} — {quer[1]}\n{quer[2]}",
|
||||
fontsize=9, color=FARBEN["warnung"], fontweight="bold",
|
||||
ha="center", va="center", rotation=90, zorder=4)
|
||||
|
||||
achse.text(links, kastenhoehe + 0.42,
|
||||
"Der Optimierer ist kein Skript, sondern ein Dienst",
|
||||
fontsize=11.5, color=FARBEN["text"], fontweight="bold")
|
||||
achse.text(links, -(len(kette) - 1) * abstand - 0.42,
|
||||
f"„{quer[0]}“ ist keine Station auf dem Weg — Monitoring und "
|
||||
f"Audit-Trail betreffen jede Schicht.\nDeshalb steht sie "
|
||||
f"neben der Kette, nicht in ihr.",
|
||||
fontsize=8.5, color=FARBEN["gedaempft"], va="top")
|
||||
|
||||
achse.set_xlim(-0.3, spange_links + 1.5)
|
||||
achse.set_ylim(-(len(kette) - 1) * abstand - 1.3, kastenhoehe + 0.85)
|
||||
achse.set_aspect("equal")
|
||||
|
||||
speichere(figur, "kap15_or_plattform")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
schichten = lies_schichten()
|
||||
for name, aufgabe, werkzeuge in schichten:
|
||||
markierung = " (Spange)" if name == QUERSCHNITT else ""
|
||||
print(f" {name:<22}{markierung}")
|
||||
print(f" {len(schichten)} Schichten aus der Tabelle in "
|
||||
f"{os.path.basename(KAPITEL)} gelesen — "
|
||||
f"{len(schichten) - 1} in der Kette, 1 quer.")
|
||||
zeichne(schichten)
|
||||
|
|
@ -107,6 +107,72 @@ def untere_huelle(punkte):
|
|||
return huelle
|
||||
|
||||
|
||||
def tiefste_delle(front, huelle):
|
||||
"""Der unerreichbare Punkt mit dem groessten Abstand zur Huelle.
|
||||
|
||||
Liefert (Punkt, linke Huellenecke, rechte Huellenecke, Abstand). Genau an
|
||||
diesem Punkt ist die Luecke am besten zu sehen, und genau dort wird sie
|
||||
beschriftet - gesucht wird sie, nicht ausgewaehlt.
|
||||
|
||||
Gemessen wird SENKRECHT zur Huellenkante, nicht senkrecht nach oben. Der
|
||||
senkrechte Abstand ist der Abstand eines Punktes zu einer Geraden; der
|
||||
Abstand in y-Richtung haengt dagegen davon ab, welche Zielgroesse man auf
|
||||
die Hochachse legt - bei vertauschten Achsen faende er eine andere Delle."""
|
||||
unerreichbar = [p for p in front if p not in huelle]
|
||||
if not unerreichbar:
|
||||
return None
|
||||
bestes = None
|
||||
for punkt in unerreichbar:
|
||||
for links, rechts in zip(huelle, huelle[1:]):
|
||||
if not links[0] <= punkt[0] <= rechts[0]:
|
||||
continue
|
||||
if rechts[0] == links[0]:
|
||||
continue
|
||||
steigung = (rechts[1] - links[1]) / (rechts[0] - links[0])
|
||||
auf_huelle = links[1] + steigung * (punkt[0] - links[0])
|
||||
abstand = (punkt[1] - auf_huelle) / np.hypot(1.0, steigung)
|
||||
if bestes is None or abstand > bestes[3]:
|
||||
bestes = (punkt, links, rechts, abstand)
|
||||
return bestes
|
||||
|
||||
|
||||
def zeichne_luecke(achse, front, huelle) -> None:
|
||||
"""Warum die gewichtete Summe die Delle nicht erreicht - und was hilft.
|
||||
|
||||
Gezeichnet werden zwei Geraden derselben Steigung: die Tangente an die
|
||||
Huelle und die parallele Gerade durch den unerreichbaren Punkt. Eine
|
||||
gewichtete Summe minimiert genau diese Steigung; sie waehlt also immer die
|
||||
untere der beiden Geraden und damit nie den Punkt darueber. Der
|
||||
waagerechte Strich zeigt die Alternative: eine CO2-Schranke, unter der
|
||||
dieser Punkt der billigste ist - so ist die Front oben ueberhaupt
|
||||
entstanden."""
|
||||
delle = tiefste_delle(front, huelle)
|
||||
if delle is None:
|
||||
return
|
||||
punkt, links, rechts, _abstand = delle
|
||||
steigung = ((rechts[1] - links[1]) / (rechts[0] - links[0])
|
||||
if rechts[0] != links[0] else 0.0)
|
||||
|
||||
x = np.array(achse.get_xlim())
|
||||
achse.plot(x, links[1] + steigung * (x - links[0]), "-", color=INDIGO,
|
||||
linewidth=1.1, alpha=0.75, zorder=1)
|
||||
achse.plot(x, punkt[1] + steigung * (x - punkt[0]), ":", color=AMBER,
|
||||
linewidth=1.6, zorder=2)
|
||||
achse.annotate("dieselbe Steigung, eine Stufe höher —\n"
|
||||
"jede gewichtete Summe nimmt die untere",
|
||||
xy=(punkt[0], punkt[1]), xytext=(12, 26),
|
||||
textcoords="offset points", fontsize=7.5, color=AMBER,
|
||||
zorder=6)
|
||||
|
||||
achse.axhline(punkt[1], color="#059669", linestyle="--", linewidth=1.2,
|
||||
alpha=0.9, zorder=1)
|
||||
achse.annotate(f"ε-Constraint: CO₂ ≤ {punkt[1]:,} kg".replace(",", ".")
|
||||
+ "\nfindet genau diesen Punkt",
|
||||
xy=(x[0], punkt[1]), xytext=(6, -22),
|
||||
textcoords="offset points", fontsize=7.5, color="#059669",
|
||||
zorder=6)
|
||||
|
||||
|
||||
# --- Statische Fassung ------------------------------------------------------
|
||||
|
||||
def zeichne_statisch(front, huelle) -> None:
|
||||
|
|
@ -132,6 +198,9 @@ def zeichne_statisch(front, huelle) -> None:
|
|||
achse.set_xlabel("Transportkosten (EUR)")
|
||||
achse.set_ylabel("CO₂-Ausstoß (kg)")
|
||||
achse.set_title("Pareto-Front: Kosten gegen CO₂", fontsize=11)
|
||||
# Erst jetzt, damit die Geraden die endgueltigen Achsengrenzen benutzen.
|
||||
achse.autoscale(enable=False)
|
||||
zeichne_luecke(achse, front, huelle)
|
||||
achse.grid(linestyle=":", alpha=0.5)
|
||||
for rand in ("top", "right"):
|
||||
achse.spines[rand].set_visible(False)
|
||||
|
|
@ -203,5 +272,49 @@ if __name__ == "__main__":
|
|||
huelle = untere_huelle(front)
|
||||
print(f"Pareto-Punkte: {len(front)}, davon gestuetzt: {len(huelle)}, "
|
||||
f"unerreichbar: {len(front) - len(huelle)}")
|
||||
|
||||
# Die beiden Behauptungen des Luecken-Bildes nachrechnen, statt sie
|
||||
# hinzuschreiben.
|
||||
delle = tiefste_delle(front, huelle)
|
||||
if delle is not None:
|
||||
punkt, links, rechts, abstand = delle
|
||||
steigung = (rechts[1] - links[1]) / (rechts[0] - links[0])
|
||||
|
||||
def auf_tangente(x):
|
||||
return links[1] + steigung * (x - links[0])
|
||||
|
||||
# Eine Stuetzgerade der UNTEREN Huelle liegt unter allen Punkten und
|
||||
# beruehrt die beiden Ecken der Kante. Beides zusammen macht sie zur
|
||||
# Tangente; nur eines davon reicht nicht.
|
||||
for ecke in huelle:
|
||||
if ecke[1] < auf_tangente(ecke[0]) - 1e-6:
|
||||
raise SystemExit(
|
||||
f"Pareto-Luecke: Die Huellenecke {ecke} liegt UNTER der "
|
||||
f"gezeichneten Geraden - dann stuetzt sie die Huelle "
|
||||
f"nicht.")
|
||||
for ecke in (links, rechts):
|
||||
if abs(ecke[1] - auf_tangente(ecke[0])) > 1e-6:
|
||||
raise SystemExit(
|
||||
f"Pareto-Luecke: Die Gerade beruehrt die Huellenecke "
|
||||
f"{ecke} nicht - dann ist sie keine Tangente an diese "
|
||||
f"Kante.")
|
||||
if punkt[1] <= auf_tangente(punkt[0]) + 1e-6:
|
||||
raise SystemExit(
|
||||
f"Pareto-Luecke: {punkt} liegt nicht ueber der Tangente - "
|
||||
f"dann waere der Punkt von einer gewichteten Summe erreichbar.")
|
||||
gefunden = plane(KOSTEN, co2_grenze=punkt[1])
|
||||
if gefunden != punkt:
|
||||
raise SystemExit(
|
||||
f"Pareto-Luecke: Die Schranke CO2 <= {punkt[1]} liefert "
|
||||
f"{gefunden}, nicht {punkt}. Die Bildunterschrift zum "
|
||||
f"ε-Constraint waere falsch.")
|
||||
# Die Zahl getrennt formatieren: Ein .replace(",", ".") auf den ganzen
|
||||
# f-String erwischt auch das Komma im Tupel.
|
||||
abstand_text = f"{abstand:.1f}".replace(".", ",")
|
||||
print(f" tiefste Delle: {punkt}, Abstand zur Hülle "
|
||||
f"{abstand_text} (senkrecht)")
|
||||
print(f" Tangente stützt die Hülle, der Punkt liegt darüber")
|
||||
print(f" ε-Constraint CO₂ ≤ {punkt[1]} liefert genau diesen Punkt")
|
||||
|
||||
zeichne_statisch(front, huelle)
|
||||
zeichne_interaktiv(front, huelle)
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ BASIS = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|||
BILDER = os.path.join(BASIS, "bilder_04")
|
||||
|
||||
INDIGO, CYAN, AMBER, GRUEN = "#4338ca", "#0891b2", "#b45309", "#059669"
|
||||
VIOLETT = "#7c3aed" # Niveaulinien und Zielfunktionsgradient
|
||||
|
||||
# Modell wortgleich zu Visualisierung_Loesungsraum.py
|
||||
C = np.array([150.0, 250.0])
|
||||
|
|
@ -200,12 +201,46 @@ def zeichne_polyeder(ecken: np.ndarray, bestes: np.ndarray) -> None:
|
|||
schreibe(figur, "kap_fundament_polyeder")
|
||||
|
||||
|
||||
def zeichne_niveaulinien(achse, besucht: list[np.ndarray]) -> None:
|
||||
"""Eine Niveaulinie der Zielfunktion durch JEDE besuchte Ecke.
|
||||
|
||||
Die Niveaus werden aus dem Weg gerechnet, nicht gewaehlt: Jede Ecke des
|
||||
Simplexwegs liegt damit auf genau einer Linie, und der Abstand der Linien
|
||||
ist der Fortschritt eines Schritts. Damit zeigt das Bild nicht nur, WELCHEN
|
||||
Weg der Simplex nimmt, sondern warum - er schiebt die Linie so weit nach
|
||||
aussen, wie das Polyeder es zulaesst."""
|
||||
x = np.linspace(-0.9, 11.4, 100)
|
||||
for punkt in besucht:
|
||||
niveau = float(C @ punkt)
|
||||
achse.plot(x, (niveau - C[0] * x) / C[1], linestyle=":",
|
||||
color=VIOLETT, linewidth=1.3, alpha=0.9, zorder=2)
|
||||
# Beschriftung dort, wo die Linie im Bild noch Platz hat. Die
|
||||
# Nulllinie laeuft nahe am unteren Rand - ihre Beschriftung gehoert
|
||||
# darueber, sonst wird sie abgeschnitten.
|
||||
unten = niveau < 500
|
||||
x_text = 1.7 if unten else 10.1
|
||||
y_linie = (niveau - C[0] * x_text) / C[1]
|
||||
achse.text(x_text, y_linie + (0.16 if unten else -0.28),
|
||||
f"Z = {euro(niveau)}", fontsize=7.5, color=VIOLETT,
|
||||
ha="center", va="bottom" if unten else "top", zorder=6)
|
||||
|
||||
# Der Gradient: die Richtung, in die sich die Linien verschieben lassen.
|
||||
start = np.array([2.6, 2.2])
|
||||
ende = start + C / np.linalg.norm(C) * 2.6
|
||||
achse.annotate("", xy=tuple(ende), xytext=tuple(start),
|
||||
arrowprops=dict(arrowstyle="-|>", color=VIOLETT,
|
||||
linewidth=2.2), zorder=6)
|
||||
achse.text(ende[0] + 0.15, ende[1], "$\\mathbf{c} = (150; 250)$",
|
||||
fontsize=8.5, color=VIOLETT, va="center", zorder=6)
|
||||
|
||||
|
||||
def zeichne_simplexweg(ecken: np.ndarray, bestes: np.ndarray) -> None:
|
||||
"""LP-Kapitel: derselbe Bereich, aber der Weg der Handrechnung."""
|
||||
figur, achse = plt.subplots(figsize=(7.2, 5.2))
|
||||
zeichne_rahmen(achse, ecken)
|
||||
|
||||
besucht = [np.array(p) for p in SIMPLEXWEG]
|
||||
zeichne_niveaulinien(achse, besucht)
|
||||
unbesucht = [e for e in ecken
|
||||
if not any(np.allclose(e, p) for p in besucht)]
|
||||
for ecke in unbesucht:
|
||||
|
|
|
|||
168
bilder_04/erzeuge_propagation_ablauf.py
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# erzeuge_propagation_ablauf.py
|
||||
"""
|
||||
Erzeugt die Ablaufgrafik zur Propagation im Kapitel CP-SAT:
|
||||
|
||||
bilder_04/kap_cpsat_propagation_ablauf.svg
|
||||
|
||||
ERGAENZT das vorhandene kap06_cp_sat_propagation.svg, ersetzt es nicht: Jenes
|
||||
zeigt schematisch das Zusammenspiel von Propagation und Konfliktlernen. Dieses
|
||||
zeigt die Propagation selbst - Runde fuer Runde, an Zahlen.
|
||||
|
||||
Gezeigt wird GENAU die Handrechnung des Kapitels:
|
||||
|
||||
x1 in {1,2,3,4}, x2 in {2,3,4,5}, Bedingung x1 + x2 = 7
|
||||
|
||||
Ausgangslage 4 x 4 = 16 Kombinationen
|
||||
nach Runde 1 x1 -> {2,3,4} 12 Kombinationen
|
||||
nach Runde 2 x2 -> {3,4,5} 9 Kombinationen
|
||||
|
||||
Bewusst nicht das Beispiel aus der Auftragsbeschreibung ([0,10] mit x1+x2<=6):
|
||||
Die Handrechnung steht unmittelbar neben dem Bild. Ein Bild mit anderen Zahlen
|
||||
als der Text daneben zwingt den Leser, beide zu vergleichen, statt eines zu
|
||||
verstehen.
|
||||
|
||||
Die Domains werden PROPAGIERT, nicht eingetragen: revidiere() streicht jeden
|
||||
Wert, fuer den es im Partner keinen Partner gibt - das ist Kantenkonsistenz,
|
||||
und zwar in derselben Reihenfolge wie in der Handrechnung. Der Selbsttest
|
||||
vergleicht das Ergebnis mit den drei im Kapitel abgedruckten Zahlen.
|
||||
|
||||
Aufruf (aus dem Repository-Wurzelverzeichnis):
|
||||
python3 bilder_04/erzeuge_propagation_ablauf.py
|
||||
|
||||
Benoetigt: matplotlib
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||
from stil_04 import FARBEN, speichere # noqa: E402
|
||||
import matplotlib.pyplot as plt # noqa: E402
|
||||
from matplotlib.patches import Rectangle # noqa: E402
|
||||
|
||||
# Die Aufgabe der Handrechnung.
|
||||
START_X1 = {1, 2, 3, 4}
|
||||
START_X2 = {2, 3, 4, 5}
|
||||
SUMME = 7
|
||||
ANZEIGE = range(1, 7) # 1 bis 6 - alle je vorkommenden Werte
|
||||
|
||||
# Was das Kapitel abdruckt; nur zum Gegenpruefen.
|
||||
KOMBINATIONEN_IM_BUCH = [16, 12, 9]
|
||||
ENDDOMAINS_IM_BUCH = ({2, 3, 4}, {3, 4, 5})
|
||||
|
||||
|
||||
def revidiere(eigene: set[int], partner: set[int]) -> set[int]:
|
||||
"""Streicht jeden Wert, zu dem es im Partner keinen Partner gibt."""
|
||||
return {v for v in eigene if (SUMME - v) in partner}
|
||||
|
||||
|
||||
def propagiere():
|
||||
"""Die zwei Runden der Handrechnung, jede als eigener Zustand."""
|
||||
d1, d2 = set(START_X1), set(START_X2)
|
||||
verlauf = [("Ausgangslage", set(d1), set(d2), None)]
|
||||
|
||||
d1 = revidiere(d1, d2)
|
||||
verlauf.append((f"Runde 1 — von $x_1$ aus", set(d1), set(d2), 0))
|
||||
|
||||
d2 = revidiere(d2, d1)
|
||||
verlauf.append((f"Runde 2 — von $x_2$ aus", set(d1), set(d2), 1))
|
||||
return verlauf
|
||||
|
||||
|
||||
def zeichne(verlauf) -> None:
|
||||
figur, achse = plt.subplots(figsize=(8.6, 4.6))
|
||||
achse.set_axis_off()
|
||||
|
||||
zellbreite, zellhoehe = 1.0, 0.62
|
||||
zeilenabstand = 1.05
|
||||
blockabstand = 2.6
|
||||
|
||||
for stufe, (titel, d1, d2, geaendert) in enumerate(verlauf):
|
||||
oben = -stufe * blockabstand
|
||||
achse.text(-0.4, oben + 0.75, titel, fontsize=10,
|
||||
color=FARBEN["text"], fontweight="bold", ha="left",
|
||||
va="center")
|
||||
|
||||
for reihe, (name, domain, vorher) in enumerate((
|
||||
("$x_1$", d1, verlauf[stufe - 1][1] if stufe else d1),
|
||||
("$x_2$", d2, verlauf[stufe - 1][2] if stufe else d2))):
|
||||
y = oben - reihe * zeilenabstand
|
||||
achse.text(-0.4, y + zellhoehe / 2, name, fontsize=11,
|
||||
color=FARBEN["text"], ha="left", va="center")
|
||||
for spalte, wert in enumerate(ANZEIGE):
|
||||
x = spalte * zellbreite
|
||||
gerade_gestrichen = wert in vorher and wert not in domain
|
||||
if wert in domain:
|
||||
flaeche, rand, schrift = (FARBEN["gut"], FARBEN["gut"],
|
||||
"white")
|
||||
alpha = 0.85
|
||||
elif gerade_gestrichen:
|
||||
flaeche, rand, schrift = (FARBEN["fehler"],
|
||||
FARBEN["fehler"], "white")
|
||||
alpha = 0.75
|
||||
else:
|
||||
flaeche, rand, schrift = (FARBEN["flaeche"],
|
||||
FARBEN["linie"],
|
||||
FARBEN["linie"])
|
||||
alpha = 1.0
|
||||
achse.add_patch(Rectangle((x, y), zellbreite * 0.9, zellhoehe,
|
||||
facecolor=flaeche, edgecolor=rand,
|
||||
alpha=alpha, linewidth=1.0))
|
||||
achse.text(x + zellbreite * 0.45, y + zellhoehe / 2, str(wert),
|
||||
fontsize=10, color=schrift, ha="center",
|
||||
va="center", fontweight="bold")
|
||||
if gerade_gestrichen:
|
||||
achse.plot([x + 0.1, x + zellbreite * 0.8],
|
||||
[y + zellhoehe - 0.08, y + 0.08], "-",
|
||||
color="white", linewidth=1.6)
|
||||
|
||||
anzahl = len(d1) * len(d2)
|
||||
achse.text(len(ANZEIGE) * zellbreite + 0.35, oben - 0.22,
|
||||
f"{len(d1)} × {len(d2)} = {anzahl}\nKombinationen",
|
||||
fontsize=9.5, color=FARBEN["text"], va="center")
|
||||
if geaendert is not None:
|
||||
gestrichen = sorted(verlauf[stufe - 1][1 + geaendert]
|
||||
- (d1, d2)[geaendert])
|
||||
achse.text(len(ANZEIGE) * zellbreite + 0.35, oben - 1.15,
|
||||
"gestrichen: "
|
||||
+ ", ".join(str(w) for w in gestrichen),
|
||||
fontsize=9, color=FARBEN["fehler"], va="center")
|
||||
|
||||
achse.text(-0.4, -2 * blockabstand - 1.65,
|
||||
f"Bedingung $x_1 + x_2 = {SUMME}$ — kein einziger Wert wurde "
|
||||
f"ausprobiert. Gestrichen wird,\nwofür es im Partner keinen "
|
||||
f"Partner gibt.",
|
||||
fontsize=9.5, color=FARBEN["text"], va="top")
|
||||
|
||||
achse.set_xlim(-0.6, len(ANZEIGE) * zellbreite + 2.6)
|
||||
achse.set_ylim(-2 * blockabstand - 2.5, 1.2)
|
||||
achse.set_aspect("equal")
|
||||
|
||||
speichere(figur, "kap_cpsat_propagation_ablauf")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
verlauf = propagiere()
|
||||
for titel, d1, d2, _ in verlauf:
|
||||
reintitel = titel.replace("$", "").replace("\\", "")
|
||||
print(f" {reintitel:<24} x1 = {sorted(d1)} x2 = {sorted(d2)} "
|
||||
f"-> {len(d1) * len(d2)} Kombinationen")
|
||||
|
||||
anzahlen = [len(d1) * len(d2) for _, d1, d2, _ in verlauf]
|
||||
if anzahlen != KOMBINATIONEN_IM_BUCH:
|
||||
raise SystemExit(
|
||||
f"Propagations-Ablauf: Die Propagation ergibt {anzahlen} "
|
||||
f"Kombinationen, das Kapitel druckt {KOMBINATIONEN_IM_BUCH} ab.")
|
||||
if (verlauf[-1][1], verlauf[-1][2]) != ENDDOMAINS_IM_BUCH:
|
||||
raise SystemExit(
|
||||
f"Propagations-Ablauf: Enddomains {sorted(verlauf[-1][1])} / "
|
||||
f"{sorted(verlauf[-1][2])} weichen von der Handrechnung "
|
||||
f"{sorted(ENDDOMAINS_IM_BUCH[0])} / "
|
||||
f"{sorted(ENDDOMAINS_IM_BUCH[1])} ab.")
|
||||
print(" stimmt mit der Handrechnung überein: 16 → 12 → 9")
|
||||
|
||||
zeichne(verlauf)
|
||||
169
bilder_04/erzeuge_var_vs_cvar.py
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# erzeuge_var_vs_cvar.py
|
||||
"""
|
||||
Erzeugt das Subadditivitaets-Bild zum Kapitel CVaR:
|
||||
|
||||
bilder_04/kap_cvar_subadditivitaet.svg
|
||||
|
||||
ERGAENZT kap_cvar_var_vergleich.svg, ersetzt es nicht: Jenes zeigt, WAS die
|
||||
beiden Kennzahlen sind - eine Schwelle und ein Mittelwert. Dieses zeigt, warum
|
||||
der Unterschied zaehlt.
|
||||
|
||||
Gerechnet wird das Gegenbeispiel aus Teil 2 von VaR_CVaR_Demo.py: zwei
|
||||
unabhaengige Anleihen, je 100 EUR Nominal, Ausfallwahrscheinlichkeit 4 %,
|
||||
sonst 2 EUR Kupon. Einzeln meldet der VaR fuer jede Anleihe einen GEWINN von
|
||||
2 EUR - denn 4 % liegen unter der 5-%-Schwelle, der Ausfall faellt also aus der
|
||||
Betrachtung heraus. Im Portfolio steigt die Wahrscheinlichkeit mindestens eines
|
||||
Ausfalls auf 7,8 % und damit UEBER die Schwelle; der VaR springt auf 98 EUR.
|
||||
|
||||
Das ist die Aussage des Bildes: Der VaR behauptet, Streuung habe das Risiko um
|
||||
102 EUR ERHOEHT. Der CVaR, der den ganzen Rand mittelt statt ihn abzuschneiden,
|
||||
kommt auf 101,33 EUR gegenueber 159,24 EUR - Streuung senkt das Risiko, wie es
|
||||
sein muss.
|
||||
|
||||
Die Ziehungsreihenfolge des Buchprogramms wird nachgespielt: default_rng(2026),
|
||||
und Teil 1 des Programms zieht nichts, also sind die beiden Anleihen die ersten
|
||||
Ziehungen. Deshalb stehen im Bild genau die Zahlen der abgedruckten Tabelle;
|
||||
pruefe_gegen_buch() bricht ab, wenn nicht.
|
||||
|
||||
Aufruf (aus dem Repository-Wurzelverzeichnis):
|
||||
python3 bilder_04/erzeuge_var_vs_cvar.py
|
||||
|
||||
Benoetigt: numpy, matplotlib
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
import numpy as np
|
||||
|
||||
HIER = os.path.dirname(os.path.abspath(__file__))
|
||||
BASIS = os.path.dirname(HIER)
|
||||
sys.path.insert(0, HIER)
|
||||
sys.path.insert(0, os.path.join(
|
||||
BASIS, "Operations_Research_mit_Python_Version_04_Programme"))
|
||||
|
||||
from stil_04 import FARBEN, speichere # noqa: E402
|
||||
import matplotlib.pyplot as plt # noqa: E402
|
||||
from VaR_CVaR_Demo import cvar_rockafellar, var_quantil # noqa: E402
|
||||
|
||||
# Instanz wortgleich zu Teil 2 von VaR_CVaR_Demo.py.
|
||||
SAAT = 2026
|
||||
ZIEHUNGEN = 2_000_000
|
||||
AUSFALLWAHRSCHEINLICHKEIT = 0.04
|
||||
VERLUST_BEI_AUSFALL = 100.0
|
||||
KUPON = 2.0
|
||||
|
||||
# Die im Kapitel abgedruckte Tabelle; nur zum Gegenpruefen.
|
||||
TABELLE_IM_BUCH = {
|
||||
"Anleihe A allein": (-2.00, 79.59),
|
||||
"Anleihe B allein": (-2.00, 79.66),
|
||||
"Portfolio A+B": (98.00, 101.33),
|
||||
"Summe der Einzelwerte": (-4.00, 159.24),
|
||||
}
|
||||
|
||||
|
||||
def rechne() -> dict[str, tuple[float, float]]:
|
||||
"""Dieselben Ziehungen wie im Buchprogramm - siehe Modulkommentar."""
|
||||
rng = np.random.default_rng(SAAT)
|
||||
verlust_a = np.where(rng.random(ZIEHUNGEN) < AUSFALLWAHRSCHEINLICHKEIT,
|
||||
VERLUST_BEI_AUSFALL, -KUPON)
|
||||
verlust_b = np.where(rng.random(ZIEHUNGEN) < AUSFALLWAHRSCHEINLICHKEIT,
|
||||
VERLUST_BEI_AUSFALL, -KUPON)
|
||||
|
||||
werte = {}
|
||||
for name, v in (("Anleihe A allein", verlust_a),
|
||||
("Anleihe B allein", verlust_b),
|
||||
("Portfolio A+B", verlust_a + verlust_b)):
|
||||
werte[name] = (var_quantil(v), cvar_rockafellar(v))
|
||||
werte["Summe der Einzelwerte"] = tuple(
|
||||
werte["Anleihe A allein"][i] + werte["Anleihe B allein"][i]
|
||||
for i in (0, 1))
|
||||
return werte
|
||||
|
||||
|
||||
def pruefe_gegen_buch(werte) -> None:
|
||||
"""Die Tafel muss dieselben Zahlen zeigen wie die Tabelle im Kapitel."""
|
||||
for name, (soll_var, soll_cvar) in TABELLE_IM_BUCH.items():
|
||||
ist_var, ist_cvar = werte[name]
|
||||
if abs(ist_var - soll_var) > 0.005 or abs(ist_cvar - soll_cvar) > 0.005:
|
||||
raise SystemExit(
|
||||
f"Subadditivitaets-Bild: '{name}' ergibt VaR {ist_var:.2f} / "
|
||||
f"CVaR {ist_cvar:.2f}, das Kapitel druckt {soll_var:.2f} / "
|
||||
f"{soll_cvar:.2f} ab.")
|
||||
# Die Aussage selbst - nicht nur die Zahlen.
|
||||
if not werte["Portfolio A+B"][0] > werte["Summe der Einzelwerte"][0]:
|
||||
raise SystemExit("Subadditivitaets-Bild: Der VaR verletzt die "
|
||||
"Subadditivitaet hier nicht - dann zeigt die Tafel "
|
||||
"das Gegenteil ihrer Überschrift.")
|
||||
if not werte["Portfolio A+B"][1] <= werte["Summe der Einzelwerte"][1]:
|
||||
raise SystemExit("Subadditivitaets-Bild: Der CVaR ist hier nicht "
|
||||
"subadditiv. Das widerspricht dem Kapiteltext.")
|
||||
|
||||
|
||||
def euro(wert: float) -> str:
|
||||
return f"{wert:,.2f} €".replace(",", "@").replace(".", ",").replace("@", ".")
|
||||
|
||||
|
||||
def zeichne(werte) -> None:
|
||||
figur, achsen = plt.subplots(1, 2, figsize=(10.2, 4.4))
|
||||
namen = ["Anleihe A allein", "Anleihe B allein",
|
||||
"Summe der Einzelwerte", "Portfolio A+B"]
|
||||
y = np.arange(len(namen))[::-1]
|
||||
|
||||
for achse, index, titel, urteil, farbe in (
|
||||
(achsen[0], 0, "VaR 95 %",
|
||||
"Portfolio teurer als die Summe —\nSubadditivität verletzt",
|
||||
FARBEN["fehler"]),
|
||||
(achsen[1], 1, "CVaR 95 %",
|
||||
"Portfolio billiger als die Summe —\nsubadditiv, also kohärent",
|
||||
FARBEN["gut"])):
|
||||
wert = [werte[n][index] for n in namen]
|
||||
farben = [FARBEN["gedaempft"], FARBEN["gedaempft"],
|
||||
FARBEN["zweit"], farbe]
|
||||
achse.barh(y, wert, height=0.6, color=farben, zorder=3)
|
||||
# Balken muessen bei null beginnen, sonst luegt ihre Laenge. Der Rand
|
||||
# links richtet sich nach der Spannweite, damit die Zahl an einem
|
||||
# negativen Balken nicht an der Achsenbeschriftung klebt.
|
||||
spanne = max(wert) - min(0.0, min(wert))
|
||||
achse.set_xlim(min(0.0, min(wert)) - 0.20 * spanne, max(wert) * 1.22)
|
||||
for stelle, w in enumerate(wert):
|
||||
abstand = 0.015 * spanne
|
||||
achse.text(w + (abstand if w >= 0 else -abstand), y[stelle],
|
||||
euro(w), va="center", ha="left" if w >= 0 else "right",
|
||||
fontsize=9, color=FARBEN["text"], zorder=4)
|
||||
achse.axvline(0, color=FARBEN["text"], linewidth=1.0, zorder=2)
|
||||
achse.set_yticks(y)
|
||||
achse.set_yticklabels(namen if index == 0 else [], fontsize=9,
|
||||
color=FARBEN["text"])
|
||||
achse.set_title(titel, fontsize=11, color=FARBEN["text"], pad=34)
|
||||
achse.set_xlabel("Verlust in € (negativ = Gewinn)")
|
||||
achse.grid(axis="y", visible=False)
|
||||
# Das Urteil ueber der Achse, nicht in ihr - sonst stoesst es an die
|
||||
# Zahl am obersten Balken.
|
||||
achse.text(0.5, 1.008, urteil, transform=achse.transAxes,
|
||||
fontsize=8.5, color=farbe, ha="center", va="bottom",
|
||||
fontweight="bold")
|
||||
|
||||
figur.suptitle("Zwei unabhängige Anleihen, je 4 % Ausfallrisiko — "
|
||||
"und zwei Urteile über dieselbe Diversifikation",
|
||||
fontsize=11, color=FARBEN["text"], y=1.02)
|
||||
speichere(figur, "kap_cvar_subadditivitaet")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
werte = rechne()
|
||||
print(f" {'':<24} {'VaR 95%':>10} {'CVaR 95%':>10}")
|
||||
for name in ("Anleihe A allein", "Anleihe B allein", "Portfolio A+B",
|
||||
"Summe der Einzelwerte"):
|
||||
print(f" {name:<24} {werte[name][0]:>10.2f} {werte[name][1]:>10.2f}")
|
||||
pruefe_gegen_buch(werte)
|
||||
print(" stimmt mit der abgedruckten Tabelle überein")
|
||||
print(f" VaR: Portfolio {werte['Portfolio A+B'][0]:.2f} > Summe "
|
||||
f"{werte['Summe der Einzelwerte'][0]:.2f} — verletzt")
|
||||
print(f" CVaR: Portfolio {werte['Portfolio A+B'][1]:.2f} ≤ Summe "
|
||||
f"{werte['Summe der Einzelwerte'][1]:.2f} — kohärent")
|
||||
zeichne(werte)
|
||||
71417
bilder_04/kap02_konvexitaet_landschaft.svg
Normal file
|
After Width: | Height: | Size: 1.7 MiB |
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns:xlink="http://www.w3.org/1999/xlink" width="648pt" height="230.4pt" viewBox="0 0 648 230.4" xmlns="http://www.w3.org/2000/svg" version="1.1">
|
||||
<svg xmlns:xlink="http://www.w3.org/1999/xlink" width="648pt" height="244.8pt" viewBox="0 0 648 244.8" xmlns="http://www.w3.org/2000/svg" version="1.1">
|
||||
<metadata>
|
||||
<rdf:RDF xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<cc:Work>
|
||||
|
|
@ -20,8 +20,8 @@
|
|||
</defs>
|
||||
<g id="figure_1">
|
||||
<g id="patch_1">
|
||||
<path d="M 0 230.4
|
||||
L 648 230.4
|
||||
<path d="M 0 244.8
|
||||
L 648 244.8
|
||||
L 648 0
|
||||
L 0 0
|
||||
z
|
||||
|
|
@ -29,83 +29,83 @@ z
|
|||
</g>
|
||||
<g id="axes_1">
|
||||
<g id="patch_2">
|
||||
<path d="M 72.79 188.44
|
||||
L 630.81 188.44
|
||||
<path d="M 72.79 202.84
|
||||
L 630.81 202.84
|
||||
L 630.81 25.44
|
||||
L 72.79 25.44
|
||||
z
|
||||
" style="fill: #ffffff"/>
|
||||
</g>
|
||||
<g id="patch_3">
|
||||
<path d="M 174.248182 32.849091
|
||||
L 326.435455 32.849091
|
||||
L 326.435455 64.809875
|
||||
L 174.248182 64.809875
|
||||
<path d="M 174.248182 33.503636
|
||||
L 326.435455 33.503636
|
||||
L 326.435455 68.28795
|
||||
L 174.248182 68.28795
|
||||
z
|
||||
" clip-path="url(#pce73ba693e)" style="fill: #4338ca; stroke: #ffffff; stroke-width: 1.2; stroke-linejoin: miter"/>
|
||||
" clip-path="url(#p3043647a47)" style="fill: #4338ca; stroke: #ffffff; stroke-width: 1.2; stroke-linejoin: miter"/>
|
||||
</g>
|
||||
<g id="patch_4">
|
||||
<path d="M 326.435455 90.959608
|
||||
L 427.893636 90.959608
|
||||
L 427.893636 122.920392
|
||||
L 326.435455 122.920392
|
||||
<path d="M 326.435455 96.747843
|
||||
L 427.893636 96.747843
|
||||
L 427.893636 131.532157
|
||||
L 326.435455 131.532157
|
||||
z
|
||||
" clip-path="url(#pce73ba693e)" style="fill: #4338ca; stroke: #ffffff; stroke-width: 1.2; stroke-linejoin: miter"/>
|
||||
" clip-path="url(#p3043647a47)" style="fill: #4338ca; stroke: #ffffff; stroke-width: 1.2; stroke-linejoin: miter"/>
|
||||
</g>
|
||||
<g id="patch_5">
|
||||
<path d="M 427.893636 149.070125
|
||||
L 529.351818 149.070125
|
||||
L 529.351818 181.030909
|
||||
L 427.893636 181.030909
|
||||
<path d="M 427.893636 159.99205
|
||||
L 529.351818 159.99205
|
||||
L 529.351818 194.776364
|
||||
L 427.893636 194.776364
|
||||
z
|
||||
" clip-path="url(#pce73ba693e)" style="fill: #4338ca; stroke: #ffffff; stroke-width: 1.2; stroke-linejoin: miter"/>
|
||||
" clip-path="url(#p3043647a47)" style="fill: #4338ca; stroke: #ffffff; stroke-width: 1.2; stroke-linejoin: miter"/>
|
||||
</g>
|
||||
<g id="patch_6">
|
||||
<path d="M 72.79 32.849091
|
||||
L 174.248182 32.849091
|
||||
L 174.248182 64.809875
|
||||
L 72.79 64.809875
|
||||
<path d="M 72.79 33.503636
|
||||
L 174.248182 33.503636
|
||||
L 174.248182 68.28795
|
||||
L 72.79 68.28795
|
||||
z
|
||||
" clip-path="url(#pce73ba693e)" style="fill: #0891b2; stroke: #ffffff; stroke-width: 1.2; stroke-linejoin: miter"/>
|
||||
" clip-path="url(#p3043647a47)" style="fill: #0891b2; stroke: #ffffff; stroke-width: 1.2; stroke-linejoin: miter"/>
|
||||
</g>
|
||||
<g id="patch_7">
|
||||
<path d="M 174.248182 149.070125
|
||||
L 224.977273 149.070125
|
||||
L 224.977273 181.030909
|
||||
L 174.248182 181.030909
|
||||
<path d="M 174.248182 159.99205
|
||||
L 224.977273 159.99205
|
||||
L 224.977273 194.776364
|
||||
L 174.248182 194.776364
|
||||
z
|
||||
" clip-path="url(#pce73ba693e)" style="fill: #0891b2; stroke: #ffffff; stroke-width: 1.2; stroke-linejoin: miter"/>
|
||||
" clip-path="url(#p3043647a47)" style="fill: #0891b2; stroke: #ffffff; stroke-width: 1.2; stroke-linejoin: miter"/>
|
||||
</g>
|
||||
<g id="patch_8">
|
||||
<path d="M 427.893636 90.959608
|
||||
L 630.81 90.959608
|
||||
L 630.81 122.920392
|
||||
L 427.893636 122.920392
|
||||
<path d="M 427.893636 96.747843
|
||||
L 630.81 96.747843
|
||||
L 630.81 131.532157
|
||||
L 427.893636 131.532157
|
||||
z
|
||||
" clip-path="url(#pce73ba693e)" style="fill: #0891b2; stroke: #ffffff; stroke-width: 1.2; stroke-linejoin: miter"/>
|
||||
" clip-path="url(#p3043647a47)" style="fill: #0891b2; stroke: #ffffff; stroke-width: 1.2; stroke-linejoin: miter"/>
|
||||
</g>
|
||||
<g id="patch_9">
|
||||
<path d="M 72.79 90.959608
|
||||
L 275.706364 90.959608
|
||||
L 275.706364 122.920392
|
||||
L 72.79 122.920392
|
||||
<path d="M 72.79 96.747843
|
||||
L 275.706364 96.747843
|
||||
L 275.706364 131.532157
|
||||
L 72.79 131.532157
|
||||
z
|
||||
" clip-path="url(#pce73ba693e)" style="fill: #b45309; stroke: #ffffff; stroke-width: 1.2; stroke-linejoin: miter"/>
|
||||
" clip-path="url(#p3043647a47)" style="fill: #b45309; stroke: #ffffff; stroke-width: 1.2; stroke-linejoin: miter"/>
|
||||
</g>
|
||||
<g id="patch_10">
|
||||
<path d="M 275.706364 149.070125
|
||||
L 427.893636 149.070125
|
||||
L 427.893636 181.030909
|
||||
L 275.706364 181.030909
|
||||
<path d="M 275.706364 159.99205
|
||||
L 427.893636 159.99205
|
||||
L 427.893636 194.776364
|
||||
L 275.706364 194.776364
|
||||
z
|
||||
" clip-path="url(#pce73ba693e)" style="fill: #b45309; stroke: #ffffff; stroke-width: 1.2; stroke-linejoin: miter"/>
|
||||
" clip-path="url(#p3043647a47)" style="fill: #b45309; stroke: #ffffff; stroke-width: 1.2; stroke-linejoin: miter"/>
|
||||
</g>
|
||||
<g id="matplotlib.axis_1">
|
||||
<g id="xtick_1">
|
||||
<g id="line2d_1">
|
||||
<path d="M 72.79 188.44
|
||||
<path d="M 72.79 202.84
|
||||
L 72.79 25.44
|
||||
" clip-path="url(#pce73ba693e)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/>
|
||||
" clip-path="url(#p3043647a47)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/>
|
||||
</g>
|
||||
<g id="line2d_2">
|
||||
<defs>
|
||||
|
|
@ -114,12 +114,12 @@ L 0 3.5
|
|||
" style="stroke: #000000; stroke-width: 0.8"/>
|
||||
</defs>
|
||||
<g>
|
||||
<use xlink:href="#mf0a04b41f8" x="72.79" y="188.44" style="stroke: #000000; stroke-width: 0.8"/>
|
||||
<use xlink:href="#mf0a04b41f8" x="72.79" y="202.84" style="stroke: #000000; stroke-width: 0.8"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="text_1">
|
||||
<!-- 0 -->
|
||||
<g transform="translate(69.60875 203.038437) scale(0.1 -0.1)">
|
||||
<g transform="translate(69.60875 217.438437) scale(0.1 -0.1)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-30" d="M 2034 4250
|
||||
Q 1547 4250 1301 3770
|
||||
|
|
@ -149,18 +149,18 @@ z
|
|||
</g>
|
||||
<g id="xtick_2">
|
||||
<g id="line2d_3">
|
||||
<path d="M 123.519091 188.44
|
||||
<path d="M 123.519091 202.84
|
||||
L 123.519091 25.44
|
||||
" clip-path="url(#pce73ba693e)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/>
|
||||
" clip-path="url(#p3043647a47)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/>
|
||||
</g>
|
||||
<g id="line2d_4">
|
||||
<g>
|
||||
<use xlink:href="#mf0a04b41f8" x="123.519091" y="188.44" style="stroke: #000000; stroke-width: 0.8"/>
|
||||
<use xlink:href="#mf0a04b41f8" x="123.519091" y="202.84" style="stroke: #000000; stroke-width: 0.8"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="text_2">
|
||||
<!-- 1 -->
|
||||
<g transform="translate(120.337841 203.038437) scale(0.1 -0.1)">
|
||||
<g transform="translate(120.337841 217.438437) scale(0.1 -0.1)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-31" d="M 794 531
|
||||
L 1825 531
|
||||
|
|
@ -183,18 +183,18 @@ z
|
|||
</g>
|
||||
<g id="xtick_3">
|
||||
<g id="line2d_5">
|
||||
<path d="M 174.248182 188.44
|
||||
<path d="M 174.248182 202.84
|
||||
L 174.248182 25.44
|
||||
" clip-path="url(#pce73ba693e)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/>
|
||||
" clip-path="url(#p3043647a47)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/>
|
||||
</g>
|
||||
<g id="line2d_6">
|
||||
<g>
|
||||
<use xlink:href="#mf0a04b41f8" x="174.248182" y="188.44" style="stroke: #000000; stroke-width: 0.8"/>
|
||||
<use xlink:href="#mf0a04b41f8" x="174.248182" y="202.84" style="stroke: #000000; stroke-width: 0.8"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="text_3">
|
||||
<!-- 2 -->
|
||||
<g transform="translate(171.066932 203.038437) scale(0.1 -0.1)">
|
||||
<g transform="translate(171.066932 217.438437) scale(0.1 -0.1)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-32" d="M 1228 531
|
||||
L 3431 531
|
||||
|
|
@ -227,18 +227,18 @@ z
|
|||
</g>
|
||||
<g id="xtick_4">
|
||||
<g id="line2d_7">
|
||||
<path d="M 224.977273 188.44
|
||||
<path d="M 224.977273 202.84
|
||||
L 224.977273 25.44
|
||||
" clip-path="url(#pce73ba693e)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/>
|
||||
" clip-path="url(#p3043647a47)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/>
|
||||
</g>
|
||||
<g id="line2d_8">
|
||||
<g>
|
||||
<use xlink:href="#mf0a04b41f8" x="224.977273" y="188.44" style="stroke: #000000; stroke-width: 0.8"/>
|
||||
<use xlink:href="#mf0a04b41f8" x="224.977273" y="202.84" style="stroke: #000000; stroke-width: 0.8"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="text_4">
|
||||
<!-- 3 -->
|
||||
<g transform="translate(221.796023 203.038437) scale(0.1 -0.1)">
|
||||
<g transform="translate(221.796023 217.438437) scale(0.1 -0.1)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-33" d="M 2597 2516
|
||||
Q 3050 2419 3304 2112
|
||||
|
|
@ -279,18 +279,18 @@ z
|
|||
</g>
|
||||
<g id="xtick_5">
|
||||
<g id="line2d_9">
|
||||
<path d="M 275.706364 188.44
|
||||
<path d="M 275.706364 202.84
|
||||
L 275.706364 25.44
|
||||
" clip-path="url(#pce73ba693e)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/>
|
||||
" clip-path="url(#p3043647a47)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/>
|
||||
</g>
|
||||
<g id="line2d_10">
|
||||
<g>
|
||||
<use xlink:href="#mf0a04b41f8" x="275.706364" y="188.44" style="stroke: #000000; stroke-width: 0.8"/>
|
||||
<use xlink:href="#mf0a04b41f8" x="275.706364" y="202.84" style="stroke: #000000; stroke-width: 0.8"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="text_5">
|
||||
<!-- 4 -->
|
||||
<g transform="translate(272.525114 203.038437) scale(0.1 -0.1)">
|
||||
<g transform="translate(272.525114 217.438437) scale(0.1 -0.1)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-34" d="M 2419 4116
|
||||
L 825 1625
|
||||
|
|
@ -318,18 +318,18 @@ z
|
|||
</g>
|
||||
<g id="xtick_6">
|
||||
<g id="line2d_11">
|
||||
<path d="M 326.435455 188.44
|
||||
<path d="M 326.435455 202.84
|
||||
L 326.435455 25.44
|
||||
" clip-path="url(#pce73ba693e)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/>
|
||||
" clip-path="url(#p3043647a47)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/>
|
||||
</g>
|
||||
<g id="line2d_12">
|
||||
<g>
|
||||
<use xlink:href="#mf0a04b41f8" x="326.435455" y="188.44" style="stroke: #000000; stroke-width: 0.8"/>
|
||||
<use xlink:href="#mf0a04b41f8" x="326.435455" y="202.84" style="stroke: #000000; stroke-width: 0.8"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="text_6">
|
||||
<!-- 5 -->
|
||||
<g transform="translate(323.254205 203.038437) scale(0.1 -0.1)">
|
||||
<g transform="translate(323.254205 217.438437) scale(0.1 -0.1)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-35" d="M 691 4666
|
||||
L 3169 4666
|
||||
|
|
@ -363,18 +363,18 @@ z
|
|||
</g>
|
||||
<g id="xtick_7">
|
||||
<g id="line2d_13">
|
||||
<path d="M 377.164545 188.44
|
||||
<path d="M 377.164545 202.84
|
||||
L 377.164545 25.44
|
||||
" clip-path="url(#pce73ba693e)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/>
|
||||
" clip-path="url(#p3043647a47)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/>
|
||||
</g>
|
||||
<g id="line2d_14">
|
||||
<g>
|
||||
<use xlink:href="#mf0a04b41f8" x="377.164545" y="188.44" style="stroke: #000000; stroke-width: 0.8"/>
|
||||
<use xlink:href="#mf0a04b41f8" x="377.164545" y="202.84" style="stroke: #000000; stroke-width: 0.8"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="text_7">
|
||||
<!-- 6 -->
|
||||
<g transform="translate(373.983295 203.038437) scale(0.1 -0.1)">
|
||||
<g transform="translate(373.983295 217.438437) scale(0.1 -0.1)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-36" d="M 2113 2584
|
||||
Q 1688 2584 1439 2293
|
||||
|
|
@ -413,18 +413,18 @@ z
|
|||
</g>
|
||||
<g id="xtick_8">
|
||||
<g id="line2d_15">
|
||||
<path d="M 427.893636 188.44
|
||||
<path d="M 427.893636 202.84
|
||||
L 427.893636 25.44
|
||||
" clip-path="url(#pce73ba693e)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/>
|
||||
" clip-path="url(#p3043647a47)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/>
|
||||
</g>
|
||||
<g id="line2d_16">
|
||||
<g>
|
||||
<use xlink:href="#mf0a04b41f8" x="427.893636" y="188.44" style="stroke: #000000; stroke-width: 0.8"/>
|
||||
<use xlink:href="#mf0a04b41f8" x="427.893636" y="202.84" style="stroke: #000000; stroke-width: 0.8"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="text_8">
|
||||
<!-- 7 -->
|
||||
<g transform="translate(424.712386 203.038437) scale(0.1 -0.1)">
|
||||
<g transform="translate(424.712386 217.438437) scale(0.1 -0.1)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-37" d="M 525 4666
|
||||
L 3525 4666
|
||||
|
|
@ -443,18 +443,18 @@ z
|
|||
</g>
|
||||
<g id="xtick_9">
|
||||
<g id="line2d_17">
|
||||
<path d="M 478.622727 188.44
|
||||
<path d="M 478.622727 202.84
|
||||
L 478.622727 25.44
|
||||
" clip-path="url(#pce73ba693e)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/>
|
||||
" clip-path="url(#p3043647a47)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/>
|
||||
</g>
|
||||
<g id="line2d_18">
|
||||
<g>
|
||||
<use xlink:href="#mf0a04b41f8" x="478.622727" y="188.44" style="stroke: #000000; stroke-width: 0.8"/>
|
||||
<use xlink:href="#mf0a04b41f8" x="478.622727" y="202.84" style="stroke: #000000; stroke-width: 0.8"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="text_9">
|
||||
<!-- 8 -->
|
||||
<g transform="translate(475.441477 203.038437) scale(0.1 -0.1)">
|
||||
<g transform="translate(475.441477 217.438437) scale(0.1 -0.1)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-38" d="M 2034 2216
|
||||
Q 1584 2216 1326 1975
|
||||
|
|
@ -502,18 +502,18 @@ z
|
|||
</g>
|
||||
<g id="xtick_10">
|
||||
<g id="line2d_19">
|
||||
<path d="M 529.351818 188.44
|
||||
<path d="M 529.351818 202.84
|
||||
L 529.351818 25.44
|
||||
" clip-path="url(#pce73ba693e)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/>
|
||||
" clip-path="url(#p3043647a47)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/>
|
||||
</g>
|
||||
<g id="line2d_20">
|
||||
<g>
|
||||
<use xlink:href="#mf0a04b41f8" x="529.351818" y="188.44" style="stroke: #000000; stroke-width: 0.8"/>
|
||||
<use xlink:href="#mf0a04b41f8" x="529.351818" y="202.84" style="stroke: #000000; stroke-width: 0.8"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="text_10">
|
||||
<!-- 9 -->
|
||||
<g transform="translate(526.170568 203.038437) scale(0.1 -0.1)">
|
||||
<g transform="translate(526.170568 217.438437) scale(0.1 -0.1)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-39" d="M 703 97
|
||||
L 703 672
|
||||
|
|
@ -552,18 +552,18 @@ z
|
|||
</g>
|
||||
<g id="xtick_11">
|
||||
<g id="line2d_21">
|
||||
<path d="M 580.080909 188.44
|
||||
<path d="M 580.080909 202.84
|
||||
L 580.080909 25.44
|
||||
" clip-path="url(#pce73ba693e)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/>
|
||||
" clip-path="url(#p3043647a47)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/>
|
||||
</g>
|
||||
<g id="line2d_22">
|
||||
<g>
|
||||
<use xlink:href="#mf0a04b41f8" x="580.080909" y="188.44" style="stroke: #000000; stroke-width: 0.8"/>
|
||||
<use xlink:href="#mf0a04b41f8" x="580.080909" y="202.84" style="stroke: #000000; stroke-width: 0.8"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="text_11">
|
||||
<!-- 10 -->
|
||||
<g transform="translate(573.718409 203.038437) scale(0.1 -0.1)">
|
||||
<g transform="translate(573.718409 217.438437) scale(0.1 -0.1)">
|
||||
<use xlink:href="#DejaVuSans-31"/>
|
||||
<use xlink:href="#DejaVuSans-30" transform="translate(63.623047 0)"/>
|
||||
</g>
|
||||
|
|
@ -571,18 +571,18 @@ L 580.080909 25.44
|
|||
</g>
|
||||
<g id="xtick_12">
|
||||
<g id="line2d_23">
|
||||
<path d="M 630.81 188.44
|
||||
<path d="M 630.81 202.84
|
||||
L 630.81 25.44
|
||||
" clip-path="url(#pce73ba693e)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/>
|
||||
" clip-path="url(#p3043647a47)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/>
|
||||
</g>
|
||||
<g id="line2d_24">
|
||||
<g>
|
||||
<use xlink:href="#mf0a04b41f8" x="630.81" y="188.44" style="stroke: #000000; stroke-width: 0.8"/>
|
||||
<use xlink:href="#mf0a04b41f8" x="630.81" y="202.84" style="stroke: #000000; stroke-width: 0.8"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="text_12">
|
||||
<!-- 11 -->
|
||||
<g transform="translate(624.4475 203.038437) scale(0.1 -0.1)">
|
||||
<g transform="translate(624.4475 217.438437) scale(0.1 -0.1)">
|
||||
<use xlink:href="#DejaVuSans-31"/>
|
||||
<use xlink:href="#DejaVuSans-31" transform="translate(63.623047 0)"/>
|
||||
</g>
|
||||
|
|
@ -590,7 +590,7 @@ L 630.81 25.44
|
|||
</g>
|
||||
<g id="text_13">
|
||||
<!-- Zeiteinheiten -->
|
||||
<g transform="translate(318.475 216.716562) scale(0.1 -0.1)">
|
||||
<g transform="translate(318.475 231.116562) scale(0.1 -0.1)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-5a" d="M 359 4666
|
||||
L 4025 4666
|
||||
|
|
@ -728,12 +728,12 @@ L -3.5 0
|
|||
" style="stroke: #000000; stroke-width: 0.8"/>
|
||||
</defs>
|
||||
<g>
|
||||
<use xlink:href="#mc0b9ff744f" x="72.79" y="48.829483" style="stroke: #000000; stroke-width: 0.8"/>
|
||||
<use xlink:href="#mc0b9ff744f" x="72.79" y="50.895793" style="stroke: #000000; stroke-width: 0.8"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="text_14">
|
||||
<!-- Fraese -->
|
||||
<g transform="translate(33.00875 52.628702) scale(0.1 -0.1)">
|
||||
<g transform="translate(33.00875 54.695012) scale(0.1 -0.1)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-46" d="M 628 4666
|
||||
L 3309 4666
|
||||
|
|
@ -842,12 +842,12 @@ z
|
|||
<g id="ytick_2">
|
||||
<g id="line2d_26">
|
||||
<g>
|
||||
<use xlink:href="#mc0b9ff744f" x="72.79" y="106.94" style="stroke: #000000; stroke-width: 0.8"/>
|
||||
<use xlink:href="#mc0b9ff744f" x="72.79" y="114.14" style="stroke: #000000; stroke-width: 0.8"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="text_15">
|
||||
<!-- Dreherei -->
|
||||
<g transform="translate(22.743125 110.739219) scale(0.1 -0.1)">
|
||||
<g transform="translate(22.743125 117.939219) scale(0.1 -0.1)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-44" d="M 1259 4147
|
||||
L 1259 519
|
||||
|
|
@ -883,12 +883,12 @@ z
|
|||
<g id="ytick_3">
|
||||
<g id="line2d_27">
|
||||
<g>
|
||||
<use xlink:href="#mc0b9ff744f" x="72.79" y="165.050517" style="stroke: #000000; stroke-width: 0.8"/>
|
||||
<use xlink:href="#mc0b9ff744f" x="72.79" y="177.384207" style="stroke: #000000; stroke-width: 0.8"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="text_16">
|
||||
<!-- Lackiererei -->
|
||||
<g transform="translate(11.013438 168.849736) scale(0.1 -0.1)">
|
||||
<g transform="translate(11.013438 181.183426) scale(0.1 -0.1)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-4c" d="M 628 4666
|
||||
L 1259 4666
|
||||
|
|
@ -951,13 +951,29 @@ z
|
|||
</g>
|
||||
</g>
|
||||
<g id="patch_11">
|
||||
<path d="M 72.79 188.44
|
||||
L 630.81 188.44
|
||||
<path d="M 275.706364 96.747843
|
||||
L 326.435455 96.747843
|
||||
L 326.435455 131.532157
|
||||
L 275.706364 131.532157
|
||||
z
|
||||
" clip-path="url(#p3043647a47)" style="fill: url(#h8ac0198506); stroke: #be123c; stroke-width: 1.2; stroke-linejoin: miter"/>
|
||||
</g>
|
||||
<g id="patch_12">
|
||||
<path d="M 224.977273 159.99205
|
||||
L 275.706364 159.99205
|
||||
L 275.706364 194.776364
|
||||
L 224.977273 194.776364
|
||||
z
|
||||
" clip-path="url(#p3043647a47)" style="fill: url(#h8ac0198506); stroke: #be123c; stroke-width: 1.2; stroke-linejoin: miter"/>
|
||||
</g>
|
||||
<g id="patch_13">
|
||||
<path d="M 72.79 202.84
|
||||
L 630.81 202.84
|
||||
" style="fill: none; stroke: #000000; stroke-width: 0.8; stroke-linejoin: miter; stroke-linecap: square"/>
|
||||
</g>
|
||||
<g id="text_17">
|
||||
<!-- A0 -->
|
||||
<g style="fill: #ffffff" transform="translate(242.993381 51.588858) scale(0.1 -0.1)">
|
||||
<g style="fill: #ffffff" transform="translate(242.993381 53.655168) scale(0.1 -0.1)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-Bold-41" d="M 3419 850
|
||||
L 1538 850
|
||||
|
|
@ -1003,21 +1019,21 @@ z
|
|||
</g>
|
||||
<g id="text_18">
|
||||
<!-- A0 -->
|
||||
<g style="fill: #ffffff" transform="translate(369.816108 109.699375) scale(0.1 -0.1)">
|
||||
<g style="fill: #ffffff" transform="translate(369.816108 116.899375) scale(0.1 -0.1)">
|
||||
<use xlink:href="#DejaVuSans-Bold-41"/>
|
||||
<use xlink:href="#DejaVuSans-Bold-30" transform="translate(77.392578 0)"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="text_19">
|
||||
<!-- A0 -->
|
||||
<g style="fill: #ffffff" transform="translate(471.27429 167.809892) scale(0.1 -0.1)">
|
||||
<g style="fill: #ffffff" transform="translate(471.27429 180.143582) scale(0.1 -0.1)">
|
||||
<use xlink:href="#DejaVuSans-Bold-41"/>
|
||||
<use xlink:href="#DejaVuSans-Bold-30" transform="translate(77.392578 0)"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="text_20">
|
||||
<!-- A1 -->
|
||||
<g style="fill: #ffffff" transform="translate(116.170653 51.588858) scale(0.1 -0.1)">
|
||||
<g style="fill: #ffffff" transform="translate(116.170653 53.655168) scale(0.1 -0.1)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-Bold-31" d="M 750 831
|
||||
L 1813 831
|
||||
|
|
@ -1040,21 +1056,21 @@ z
|
|||
</g>
|
||||
<g id="text_21">
|
||||
<!-- A1 -->
|
||||
<g style="fill: #ffffff" transform="translate(192.26429 167.809892) scale(0.1 -0.1)">
|
||||
<g style="fill: #ffffff" transform="translate(192.26429 180.143582) scale(0.1 -0.1)">
|
||||
<use xlink:href="#DejaVuSans-Bold-41"/>
|
||||
<use xlink:href="#DejaVuSans-Bold-31" transform="translate(77.392578 0)"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="text_22">
|
||||
<!-- A1 -->
|
||||
<g style="fill: #ffffff" transform="translate(522.003381 109.699375) scale(0.1 -0.1)">
|
||||
<g style="fill: #ffffff" transform="translate(522.003381 116.899375) scale(0.1 -0.1)">
|
||||
<use xlink:href="#DejaVuSans-Bold-41"/>
|
||||
<use xlink:href="#DejaVuSans-Bold-31" transform="translate(77.392578 0)"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="text_23">
|
||||
<!-- A2 -->
|
||||
<g style="fill: #ffffff" transform="translate(166.899744 109.699375) scale(0.1 -0.1)">
|
||||
<g style="fill: #ffffff" transform="translate(166.899744 116.899375) scale(0.1 -0.1)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-Bold-32" d="M 1844 884
|
||||
L 3897 884
|
||||
|
|
@ -1085,14 +1101,14 @@ z
|
|||
</g>
|
||||
<g id="text_24">
|
||||
<!-- A2 -->
|
||||
<g style="fill: #ffffff" transform="translate(344.451563 167.809892) scale(0.1 -0.1)">
|
||||
<g style="fill: #ffffff" transform="translate(344.451563 180.143582) scale(0.1 -0.1)">
|
||||
<use xlink:href="#DejaVuSans-Bold-41"/>
|
||||
<use xlink:href="#DejaVuSans-Bold-32" transform="translate(77.392578 0)"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="text_25">
|
||||
<!-- Job-Shop-Plan, Makespan = 11 -->
|
||||
<g transform="translate(267.519375 19.44) scale(0.11 -0.11)">
|
||||
<!-- Job-Shop-Plan: Makespan 11, untere Schranke 10 — schraffiert steht die Maschine still -->
|
||||
<g transform="translate(114.118359 19.44) scale(0.11 -0.11)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-4a" d="M 628 4666
|
||||
L 1259 4666
|
||||
|
|
@ -1246,14 +1262,18 @@ L 603 0
|
|||
L 603 4863
|
||||
z
|
||||
" transform="scale(0.015625)"/>
|
||||
<path id="DejaVuSans-2c" d="M 750 794
|
||||
<path id="DejaVuSans-3a" d="M 750 794
|
||||
L 1409 794
|
||||
L 1409 256
|
||||
L 897 -744
|
||||
L 494 -744
|
||||
L 750 256
|
||||
L 1409 0
|
||||
L 750 0
|
||||
L 750 794
|
||||
z
|
||||
M 750 3309
|
||||
L 1409 3309
|
||||
L 1409 2516
|
||||
L 750 2516
|
||||
L 750 3309
|
||||
z
|
||||
" transform="scale(0.015625)"/>
|
||||
<path id="DejaVuSans-20" transform="scale(0.015625)"/>
|
||||
<path id="DejaVuSans-4d" d="M 628 4666
|
||||
|
|
@ -1272,17 +1292,89 @@ L 628 0
|
|||
L 628 4666
|
||||
z
|
||||
" transform="scale(0.015625)"/>
|
||||
<path id="DejaVuSans-3d" d="M 678 2906
|
||||
L 4684 2906
|
||||
L 4684 2381
|
||||
L 678 2381
|
||||
L 678 2906
|
||||
<path id="DejaVuSans-2c" d="M 750 794
|
||||
L 1409 794
|
||||
L 1409 256
|
||||
L 897 -744
|
||||
L 494 -744
|
||||
L 750 256
|
||||
L 750 794
|
||||
z
|
||||
M 678 1631
|
||||
L 4684 1631
|
||||
L 4684 1100
|
||||
L 678 1100
|
||||
L 678 1631
|
||||
" transform="scale(0.015625)"/>
|
||||
<path id="DejaVuSans-75" d="M 544 1381
|
||||
L 544 3500
|
||||
L 1119 3500
|
||||
L 1119 1403
|
||||
Q 1119 906 1312 657
|
||||
Q 1506 409 1894 409
|
||||
Q 2359 409 2629 706
|
||||
Q 2900 1003 2900 1516
|
||||
L 2900 3500
|
||||
L 3475 3500
|
||||
L 3475 0
|
||||
L 2900 0
|
||||
L 2900 538
|
||||
Q 2691 219 2414 64
|
||||
Q 2138 -91 1772 -91
|
||||
Q 1169 -91 856 284
|
||||
Q 544 659 544 1381
|
||||
z
|
||||
M 1991 3584
|
||||
L 1991 3584
|
||||
z
|
||||
" transform="scale(0.015625)"/>
|
||||
<path id="DejaVuSans-2014" d="M 313 1978
|
||||
L 6088 1978
|
||||
L 6088 1528
|
||||
L 313 1528
|
||||
L 313 1978
|
||||
z
|
||||
" transform="scale(0.015625)"/>
|
||||
<path id="DejaVuSans-66" d="M 2375 4863
|
||||
L 2375 4384
|
||||
L 1825 4384
|
||||
Q 1516 4384 1395 4259
|
||||
Q 1275 4134 1275 3809
|
||||
L 1275 3500
|
||||
L 2222 3500
|
||||
L 2222 3053
|
||||
L 1275 3053
|
||||
L 1275 0
|
||||
L 697 0
|
||||
L 697 3053
|
||||
L 147 3053
|
||||
L 147 3500
|
||||
L 697 3500
|
||||
L 697 3744
|
||||
Q 697 4328 969 4595
|
||||
Q 1241 4863 1831 4863
|
||||
L 2375 4863
|
||||
z
|
||||
" transform="scale(0.015625)"/>
|
||||
<path id="DejaVuSans-64" d="M 2906 2969
|
||||
L 2906 4863
|
||||
L 3481 4863
|
||||
L 3481 0
|
||||
L 2906 0
|
||||
L 2906 525
|
||||
Q 2725 213 2448 61
|
||||
Q 2172 -91 1784 -91
|
||||
Q 1150 -91 751 415
|
||||
Q 353 922 353 1747
|
||||
Q 353 2572 751 3078
|
||||
Q 1150 3584 1784 3584
|
||||
Q 2172 3584 2448 3432
|
||||
Q 2725 3281 2906 2969
|
||||
z
|
||||
M 947 1747
|
||||
Q 947 1113 1208 752
|
||||
Q 1469 391 1925 391
|
||||
Q 2381 391 2643 752
|
||||
Q 2906 1113 2906 1747
|
||||
Q 2906 2381 2643 2742
|
||||
Q 2381 3103 1925 3103
|
||||
Q 1469 3103 1208 2742
|
||||
Q 947 2381 947 1747
|
||||
z
|
||||
" transform="scale(0.015625)"/>
|
||||
</defs>
|
||||
|
|
@ -1299,28 +1391,157 @@ z
|
|||
<use xlink:href="#DejaVuSans-6c" transform="translate(538.134766 0)"/>
|
||||
<use xlink:href="#DejaVuSans-61" transform="translate(565.917969 0)"/>
|
||||
<use xlink:href="#DejaVuSans-6e" transform="translate(627.197266 0)"/>
|
||||
<use xlink:href="#DejaVuSans-2c" transform="translate(690.576172 0)"/>
|
||||
<use xlink:href="#DejaVuSans-20" transform="translate(722.363281 0)"/>
|
||||
<use xlink:href="#DejaVuSans-4d" transform="translate(754.150391 0)"/>
|
||||
<use xlink:href="#DejaVuSans-61" transform="translate(840.429688 0)"/>
|
||||
<use xlink:href="#DejaVuSans-6b" transform="translate(901.708984 0)"/>
|
||||
<use xlink:href="#DejaVuSans-65" transform="translate(955.994141 0)"/>
|
||||
<use xlink:href="#DejaVuSans-73" transform="translate(1017.517578 0)"/>
|
||||
<use xlink:href="#DejaVuSans-70" transform="translate(1069.617188 0)"/>
|
||||
<use xlink:href="#DejaVuSans-61" transform="translate(1133.09375 0)"/>
|
||||
<use xlink:href="#DejaVuSans-6e" transform="translate(1194.373047 0)"/>
|
||||
<use xlink:href="#DejaVuSans-20" transform="translate(1257.751953 0)"/>
|
||||
<use xlink:href="#DejaVuSans-3d" transform="translate(1289.539062 0)"/>
|
||||
<use xlink:href="#DejaVuSans-20" transform="translate(1373.328125 0)"/>
|
||||
<use xlink:href="#DejaVuSans-31" transform="translate(1405.115234 0)"/>
|
||||
<use xlink:href="#DejaVuSans-31" transform="translate(1468.738281 0)"/>
|
||||
<use xlink:href="#DejaVuSans-3a" transform="translate(690.576172 0)"/>
|
||||
<use xlink:href="#DejaVuSans-20" transform="translate(724.267578 0)"/>
|
||||
<use xlink:href="#DejaVuSans-4d" transform="translate(756.054688 0)"/>
|
||||
<use xlink:href="#DejaVuSans-61" transform="translate(842.333984 0)"/>
|
||||
<use xlink:href="#DejaVuSans-6b" transform="translate(903.613281 0)"/>
|
||||
<use xlink:href="#DejaVuSans-65" transform="translate(957.898438 0)"/>
|
||||
<use xlink:href="#DejaVuSans-73" transform="translate(1019.421875 0)"/>
|
||||
<use xlink:href="#DejaVuSans-70" transform="translate(1071.521484 0)"/>
|
||||
<use xlink:href="#DejaVuSans-61" transform="translate(1134.998047 0)"/>
|
||||
<use xlink:href="#DejaVuSans-6e" transform="translate(1196.277344 0)"/>
|
||||
<use xlink:href="#DejaVuSans-20" transform="translate(1259.65625 0)"/>
|
||||
<use xlink:href="#DejaVuSans-31" transform="translate(1291.443359 0)"/>
|
||||
<use xlink:href="#DejaVuSans-31" transform="translate(1355.066406 0)"/>
|
||||
<use xlink:href="#DejaVuSans-2c" transform="translate(1418.689453 0)"/>
|
||||
<use xlink:href="#DejaVuSans-20" transform="translate(1450.476562 0)"/>
|
||||
<use xlink:href="#DejaVuSans-75" transform="translate(1482.263672 0)"/>
|
||||
<use xlink:href="#DejaVuSans-6e" transform="translate(1545.642578 0)"/>
|
||||
<use xlink:href="#DejaVuSans-74" transform="translate(1609.021484 0)"/>
|
||||
<use xlink:href="#DejaVuSans-65" transform="translate(1648.230469 0)"/>
|
||||
<use xlink:href="#DejaVuSans-72" transform="translate(1709.753906 0)"/>
|
||||
<use xlink:href="#DejaVuSans-65" transform="translate(1748.617188 0)"/>
|
||||
<use xlink:href="#DejaVuSans-20" transform="translate(1810.140625 0)"/>
|
||||
<use xlink:href="#DejaVuSans-53" transform="translate(1841.927734 0)"/>
|
||||
<use xlink:href="#DejaVuSans-63" transform="translate(1905.404297 0)"/>
|
||||
<use xlink:href="#DejaVuSans-68" transform="translate(1960.384766 0)"/>
|
||||
<use xlink:href="#DejaVuSans-72" transform="translate(2023.763672 0)"/>
|
||||
<use xlink:href="#DejaVuSans-61" transform="translate(2064.876953 0)"/>
|
||||
<use xlink:href="#DejaVuSans-6e" transform="translate(2126.15625 0)"/>
|
||||
<use xlink:href="#DejaVuSans-6b" transform="translate(2189.535156 0)"/>
|
||||
<use xlink:href="#DejaVuSans-65" transform="translate(2243.820312 0)"/>
|
||||
<use xlink:href="#DejaVuSans-20" transform="translate(2305.34375 0)"/>
|
||||
<use xlink:href="#DejaVuSans-31" transform="translate(2337.130859 0)"/>
|
||||
<use xlink:href="#DejaVuSans-30" transform="translate(2400.753906 0)"/>
|
||||
<use xlink:href="#DejaVuSans-20" transform="translate(2464.376953 0)"/>
|
||||
<use xlink:href="#DejaVuSans-2014" transform="translate(2496.164062 0)"/>
|
||||
<use xlink:href="#DejaVuSans-20" transform="translate(2596.164062 0)"/>
|
||||
<use xlink:href="#DejaVuSans-73" transform="translate(2627.951172 0)"/>
|
||||
<use xlink:href="#DejaVuSans-63" transform="translate(2680.050781 0)"/>
|
||||
<use xlink:href="#DejaVuSans-68" transform="translate(2735.03125 0)"/>
|
||||
<use xlink:href="#DejaVuSans-72" transform="translate(2798.410156 0)"/>
|
||||
<use xlink:href="#DejaVuSans-61" transform="translate(2839.523438 0)"/>
|
||||
<use xlink:href="#DejaVuSans-66" transform="translate(2900.802734 0)"/>
|
||||
<use xlink:href="#DejaVuSans-66" transform="translate(2936.007812 0)"/>
|
||||
<use xlink:href="#DejaVuSans-69" transform="translate(2971.212891 0)"/>
|
||||
<use xlink:href="#DejaVuSans-65" transform="translate(2998.996094 0)"/>
|
||||
<use xlink:href="#DejaVuSans-72" transform="translate(3060.519531 0)"/>
|
||||
<use xlink:href="#DejaVuSans-74" transform="translate(3101.632812 0)"/>
|
||||
<use xlink:href="#DejaVuSans-20" transform="translate(3140.841797 0)"/>
|
||||
<use xlink:href="#DejaVuSans-73" transform="translate(3172.628906 0)"/>
|
||||
<use xlink:href="#DejaVuSans-74" transform="translate(3224.728516 0)"/>
|
||||
<use xlink:href="#DejaVuSans-65" transform="translate(3263.9375 0)"/>
|
||||
<use xlink:href="#DejaVuSans-68" transform="translate(3325.460938 0)"/>
|
||||
<use xlink:href="#DejaVuSans-74" transform="translate(3388.839844 0)"/>
|
||||
<use xlink:href="#DejaVuSans-20" transform="translate(3428.048828 0)"/>
|
||||
<use xlink:href="#DejaVuSans-64" transform="translate(3459.835938 0)"/>
|
||||
<use xlink:href="#DejaVuSans-69" transform="translate(3523.3125 0)"/>
|
||||
<use xlink:href="#DejaVuSans-65" transform="translate(3551.095703 0)"/>
|
||||
<use xlink:href="#DejaVuSans-20" transform="translate(3612.619141 0)"/>
|
||||
<use xlink:href="#DejaVuSans-4d" transform="translate(3644.40625 0)"/>
|
||||
<use xlink:href="#DejaVuSans-61" transform="translate(3730.685547 0)"/>
|
||||
<use xlink:href="#DejaVuSans-73" transform="translate(3791.964844 0)"/>
|
||||
<use xlink:href="#DejaVuSans-63" transform="translate(3844.064453 0)"/>
|
||||
<use xlink:href="#DejaVuSans-68" transform="translate(3899.044922 0)"/>
|
||||
<use xlink:href="#DejaVuSans-69" transform="translate(3962.423828 0)"/>
|
||||
<use xlink:href="#DejaVuSans-6e" transform="translate(3990.207031 0)"/>
|
||||
<use xlink:href="#DejaVuSans-65" transform="translate(4053.585938 0)"/>
|
||||
<use xlink:href="#DejaVuSans-20" transform="translate(4115.109375 0)"/>
|
||||
<use xlink:href="#DejaVuSans-73" transform="translate(4146.896484 0)"/>
|
||||
<use xlink:href="#DejaVuSans-74" transform="translate(4198.996094 0)"/>
|
||||
<use xlink:href="#DejaVuSans-69" transform="translate(4238.205078 0)"/>
|
||||
<use xlink:href="#DejaVuSans-6c" transform="translate(4265.988281 0)"/>
|
||||
<use xlink:href="#DejaVuSans-6c" transform="translate(4293.771484 0)"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="line2d_28">
|
||||
<path d="M 580.080909 202.84
|
||||
L 580.080909 25.44
|
||||
" clip-path="url(#p3043647a47)" style="fill: none; stroke-dasharray: 5.55,2.4; stroke-dashoffset: 0; stroke: #059669; stroke-width: 1.5"/>
|
||||
</g>
|
||||
<g id="text_26">
|
||||
<!-- untere Schranke 10 -->
|
||||
<g style="fill: #059669" transform="translate(490.514121 195.750266) scale(0.085 -0.085)">
|
||||
<use xlink:href="#DejaVuSans-75"/>
|
||||
<use xlink:href="#DejaVuSans-6e" transform="translate(63.378906 0)"/>
|
||||
<use xlink:href="#DejaVuSans-74" transform="translate(126.757812 0)"/>
|
||||
<use xlink:href="#DejaVuSans-65" transform="translate(165.966797 0)"/>
|
||||
<use xlink:href="#DejaVuSans-72" transform="translate(227.490234 0)"/>
|
||||
<use xlink:href="#DejaVuSans-65" transform="translate(266.353516 0)"/>
|
||||
<use xlink:href="#DejaVuSans-20" transform="translate(327.876953 0)"/>
|
||||
<use xlink:href="#DejaVuSans-53" transform="translate(359.664062 0)"/>
|
||||
<use xlink:href="#DejaVuSans-63" transform="translate(423.140625 0)"/>
|
||||
<use xlink:href="#DejaVuSans-68" transform="translate(478.121094 0)"/>
|
||||
<use xlink:href="#DejaVuSans-72" transform="translate(541.5 0)"/>
|
||||
<use xlink:href="#DejaVuSans-61" transform="translate(582.613281 0)"/>
|
||||
<use xlink:href="#DejaVuSans-6e" transform="translate(643.892578 0)"/>
|
||||
<use xlink:href="#DejaVuSans-6b" transform="translate(707.271484 0)"/>
|
||||
<use xlink:href="#DejaVuSans-65" transform="translate(761.556641 0)"/>
|
||||
<use xlink:href="#DejaVuSans-20" transform="translate(823.080078 0)"/>
|
||||
<use xlink:href="#DejaVuSans-31" transform="translate(854.867188 0)"/>
|
||||
<use xlink:href="#DejaVuSans-30" transform="translate(918.490234 0)"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="pce73ba693e">
|
||||
<rect x="72.79" y="25.44" width="558.02" height="163"/>
|
||||
<clipPath id="p3043647a47">
|
||||
<rect x="72.79" y="25.44" width="558.02" height="177.4"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<defs>
|
||||
<pattern id="h8ac0198506" patternUnits="userSpaceOnUse" x="0" y="0" width="72" height="72">
|
||||
<rect x="0" y="0" width="73" height="73" fill="none"/>
|
||||
<path d="M -36 36
|
||||
L 36 -36
|
||||
M -32 40
|
||||
L 40 -32
|
||||
M -28 44
|
||||
L 44 -28
|
||||
M -24 48
|
||||
L 48 -24
|
||||
M -20 52
|
||||
L 52 -20
|
||||
M -16 56
|
||||
L 56 -16
|
||||
M -12 60
|
||||
L 60 -12
|
||||
M -8 64
|
||||
L 64 -8
|
||||
M -4 68
|
||||
L 68 -4
|
||||
M 0 72
|
||||
L 72 0
|
||||
M 4 76
|
||||
L 76 4
|
||||
M 8 80
|
||||
L 80 8
|
||||
M 12 84
|
||||
L 84 12
|
||||
M 16 88
|
||||
L 88 16
|
||||
M 20 92
|
||||
L 92 20
|
||||
M 24 96
|
||||
L 96 24
|
||||
M 28 100
|
||||
L 100 28
|
||||
M 32 104
|
||||
L 104 32
|
||||
M 36 108
|
||||
L 108 36
|
||||
" style="fill: #be123c; stroke: #be123c; stroke-width: 1.0; stroke-linecap: butt; stroke-linejoin: miter"/>
|
||||
</pattern>
|
||||
</defs>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 119 KiB |
2208
bilder_04/kap_cpsat_propagation_ablauf.svg
Normal file
|
After Width: | Height: | Size: 64 KiB |
2698
bilder_04/kap_cvar_subadditivitaet.svg
Normal file
|
After Width: | Height: | Size: 80 KiB |
3683
bilder_04/kap_lp_dualitaets_bruecke.svg
Normal file
|
After Width: | Height: | Size: 103 KiB |
|
|
@ -749,6 +749,260 @@ L 492.615285 242.66828
|
|||
<path d="M 380.229919 330.28
|
||||
L 380.229919 37.968
|
||||
" clip-path="url(#pe55ef05f0d)" style="fill: none; stroke-dasharray: 4.81,2.08; stroke-dashoffset: 0; stroke: #b45309; stroke-opacity: 0.8; stroke-width: 1.3"/>
|
||||
</g>
|
||||
<g id="line2d_29">
|
||||
<path d="M 46.82 294.907792
|
||||
L 51.474343 296.738929
|
||||
L 56.128687 298.570066
|
||||
L 60.78303 300.401203
|
||||
L 65.437374 302.23234
|
||||
L 70.091717 304.063477
|
||||
L 74.746061 305.894614
|
||||
L 79.400404 307.725751
|
||||
L 84.054747 309.556888
|
||||
L 88.709091 311.388025
|
||||
L 93.363434 313.219162
|
||||
L 98.017778 315.050299
|
||||
L 102.672121 316.881436
|
||||
L 107.326465 318.712573
|
||||
L 111.980808 320.54371
|
||||
L 116.635152 322.374847
|
||||
L 121.289495 324.205984
|
||||
L 125.943838 326.037121
|
||||
L 130.598182 327.868259
|
||||
L 135.252525 329.699396
|
||||
L 139.906869 331.530533
|
||||
L 144.561212 333.36167
|
||||
L 149.215556 335.192807
|
||||
L 153.869899 337.023944
|
||||
L 158.524242 338.855081
|
||||
L 163.178586 340.686218
|
||||
L 167.832929 342.517355
|
||||
L 172.487273 344.348492
|
||||
L 177.141616 346.179629
|
||||
L 181.79596 348.010766
|
||||
L 186.450303 349.841903
|
||||
L 191.104646 351.67304
|
||||
L 195.75899 353.504177
|
||||
L 200.413333 355.335314
|
||||
L 205.067677 357.166451
|
||||
L 209.72202 358.997588
|
||||
L 214.376364 360.828725
|
||||
L 219.030707 362.659862
|
||||
L 223.685051 364.491
|
||||
L 228.339394 366.322137
|
||||
L 232.993737 368.153274
|
||||
L 237.648081 369.984411
|
||||
L 242.302424 371.815548
|
||||
L 246.956768 373.646685
|
||||
L 251.413305 375.4
|
||||
" clip-path="url(#pe55ef05f0d)" style="fill: none; stroke-dasharray: 1.3,2.145; stroke-dashoffset: 0; stroke: #7c3aed; stroke-opacity: 0.9; stroke-width: 1.3"/>
|
||||
</g>
|
||||
<g id="line2d_30">
|
||||
<path d="M 46.82 98.395523
|
||||
L 51.474343 100.22666
|
||||
L 56.128687 102.057797
|
||||
L 60.78303 103.888934
|
||||
L 65.437374 105.720071
|
||||
L 70.091717 107.551208
|
||||
L 74.746061 109.382345
|
||||
L 79.400404 111.213482
|
||||
L 84.054747 113.044619
|
||||
L 88.709091 114.875756
|
||||
L 93.363434 116.706893
|
||||
L 98.017778 118.53803
|
||||
L 102.672121 120.369167
|
||||
L 107.326465 122.200304
|
||||
L 111.980808 124.031441
|
||||
L 116.635152 125.862578
|
||||
L 121.289495 127.693716
|
||||
L 125.943838 129.524853
|
||||
L 130.598182 131.35599
|
||||
L 135.252525 133.187127
|
||||
L 139.906869 135.018264
|
||||
L 144.561212 136.849401
|
||||
L 149.215556 138.680538
|
||||
L 153.869899 140.511675
|
||||
L 158.524242 142.342812
|
||||
L 163.178586 144.173949
|
||||
L 167.832929 146.005086
|
||||
L 172.487273 147.836223
|
||||
L 177.141616 149.66736
|
||||
L 181.79596 151.498497
|
||||
L 186.450303 153.329634
|
||||
L 191.104646 155.160771
|
||||
L 195.75899 156.991908
|
||||
L 200.413333 158.823045
|
||||
L 205.067677 160.654182
|
||||
L 209.72202 162.485319
|
||||
L 214.376364 164.316457
|
||||
L 219.030707 166.147594
|
||||
L 223.685051 167.978731
|
||||
L 228.339394 169.809868
|
||||
L 232.993737 171.641005
|
||||
L 237.648081 173.472142
|
||||
L 242.302424 175.303279
|
||||
L 246.956768 177.134416
|
||||
L 251.611111 178.965553
|
||||
L 256.265455 180.79669
|
||||
L 260.919798 182.627827
|
||||
L 265.574141 184.458964
|
||||
L 270.228485 186.290101
|
||||
L 274.882828 188.121238
|
||||
L 279.537172 189.952375
|
||||
L 284.191515 191.783512
|
||||
L 288.845859 193.614649
|
||||
L 293.500202 195.445786
|
||||
L 298.154545 197.276923
|
||||
L 302.808889 199.108061
|
||||
L 307.463232 200.939198
|
||||
L 312.117576 202.770335
|
||||
L 316.771919 204.601472
|
||||
L 321.426263 206.432609
|
||||
L 326.080606 208.263746
|
||||
L 330.734949 210.094883
|
||||
L 335.389293 211.92602
|
||||
L 340.043636 213.757157
|
||||
L 344.69798 215.588294
|
||||
L 349.352323 217.419431
|
||||
L 354.006667 219.250568
|
||||
L 358.66101 221.081705
|
||||
L 363.315354 222.912842
|
||||
L 367.969697 224.743979
|
||||
L 372.62404 226.575116
|
||||
L 377.278384 228.406253
|
||||
L 381.932727 230.23739
|
||||
L 386.587071 232.068527
|
||||
L 391.241414 233.899664
|
||||
L 395.895758 235.730802
|
||||
L 400.550101 237.561939
|
||||
L 405.204444 239.393076
|
||||
L 409.858788 241.224213
|
||||
L 414.513131 243.05535
|
||||
L 419.167475 244.886487
|
||||
L 423.821818 246.717624
|
||||
L 428.476162 248.548761
|
||||
L 433.130505 250.379898
|
||||
L 437.784848 252.211035
|
||||
L 442.439192 254.042172
|
||||
L 447.093535 255.873309
|
||||
L 451.747879 257.704446
|
||||
L 456.402222 259.535583
|
||||
L 461.056566 261.36672
|
||||
L 465.710909 263.197857
|
||||
L 470.365253 265.028994
|
||||
L 475.019596 266.860131
|
||||
L 479.673939 268.691268
|
||||
L 484.328283 270.522406
|
||||
L 488.982626 272.353543
|
||||
L 493.63697 274.18468
|
||||
L 498.291313 276.015817
|
||||
L 502.945657 277.846954
|
||||
L 507.6 279.678091
|
||||
" clip-path="url(#pe55ef05f0d)" style="fill: none; stroke-dasharray: 1.3,2.145; stroke-dashoffset: 0; stroke: #7c3aed; stroke-opacity: 0.9; stroke-width: 1.3"/>
|
||||
</g>
|
||||
<g id="line2d_31">
|
||||
<path d="M 46.82 61.549472
|
||||
L 51.474343 63.380609
|
||||
L 56.128687 65.211746
|
||||
L 60.78303 67.042883
|
||||
L 65.437374 68.87402
|
||||
L 70.091717 70.705158
|
||||
L 74.746061 72.536295
|
||||
L 79.400404 74.367432
|
||||
L 84.054747 76.198569
|
||||
L 88.709091 78.029706
|
||||
L 93.363434 79.860843
|
||||
L 98.017778 81.69198
|
||||
L 102.672121 83.523117
|
||||
L 107.326465 85.354254
|
||||
L 111.980808 87.185391
|
||||
L 116.635152 89.016528
|
||||
L 121.289495 90.847665
|
||||
L 125.943838 92.678802
|
||||
L 130.598182 94.509939
|
||||
L 135.252525 96.341076
|
||||
L 139.906869 98.172213
|
||||
L 144.561212 100.00335
|
||||
L 149.215556 101.834487
|
||||
L 153.869899 103.665624
|
||||
L 158.524242 105.496761
|
||||
L 163.178586 107.327899
|
||||
L 167.832929 109.159036
|
||||
L 172.487273 110.990173
|
||||
L 177.141616 112.82131
|
||||
L 181.79596 114.652447
|
||||
L 186.450303 116.483584
|
||||
L 191.104646 118.314721
|
||||
L 195.75899 120.145858
|
||||
L 200.413333 121.976995
|
||||
L 205.067677 123.808132
|
||||
L 209.72202 125.639269
|
||||
L 214.376364 127.470406
|
||||
L 219.030707 129.301543
|
||||
L 223.685051 131.13268
|
||||
L 228.339394 132.963817
|
||||
L 232.993737 134.794954
|
||||
L 237.648081 136.626091
|
||||
L 242.302424 138.457228
|
||||
L 246.956768 140.288365
|
||||
L 251.611111 142.119503
|
||||
L 256.265455 143.95064
|
||||
L 260.919798 145.781777
|
||||
L 265.574141 147.612914
|
||||
L 270.228485 149.444051
|
||||
L 274.882828 151.275188
|
||||
L 279.537172 153.106325
|
||||
L 284.191515 154.937462
|
||||
L 288.845859 156.768599
|
||||
L 293.500202 158.599736
|
||||
L 298.154545 160.430873
|
||||
L 302.808889 162.26201
|
||||
L 307.463232 164.093147
|
||||
L 312.117576 165.924284
|
||||
L 316.771919 167.755421
|
||||
L 321.426263 169.586558
|
||||
L 326.080606 171.417695
|
||||
L 330.734949 173.248832
|
||||
L 335.389293 175.079969
|
||||
L 340.043636 176.911106
|
||||
L 344.69798 178.742244
|
||||
L 349.352323 180.573381
|
||||
L 354.006667 182.404518
|
||||
L 358.66101 184.235655
|
||||
L 363.315354 186.066792
|
||||
L 367.969697 187.897929
|
||||
L 372.62404 189.729066
|
||||
L 377.278384 191.560203
|
||||
L 381.932727 193.39134
|
||||
L 386.587071 195.222477
|
||||
L 391.241414 197.053614
|
||||
L 395.895758 198.884751
|
||||
L 400.550101 200.715888
|
||||
L 405.204444 202.547025
|
||||
L 409.858788 204.378162
|
||||
L 414.513131 206.209299
|
||||
L 419.167475 208.040436
|
||||
L 423.821818 209.871573
|
||||
L 428.476162 211.70271
|
||||
L 433.130505 213.533848
|
||||
L 437.784848 215.364985
|
||||
L 442.439192 217.196122
|
||||
L 447.093535 219.027259
|
||||
L 451.747879 220.858396
|
||||
L 456.402222 222.689533
|
||||
L 461.056566 224.52067
|
||||
L 465.710909 226.351807
|
||||
L 470.365253 228.182944
|
||||
L 475.019596 230.014081
|
||||
L 479.673939 231.845218
|
||||
L 484.328283 233.676355
|
||||
L 488.982626 235.507492
|
||||
L 493.63697 237.338629
|
||||
L 498.291313 239.169766
|
||||
L 502.945657 241.000903
|
||||
L 507.6 242.83204
|
||||
" clip-path="url(#pe55ef05f0d)" style="fill: none; stroke-dasharray: 1.3,2.145; stroke-dashoffset: 0; stroke: #7c3aed; stroke-opacity: 0.9; stroke-width: 1.3"/>
|
||||
</g>
|
||||
<g id="patch_4">
|
||||
<path d="M 46.82 330.28
|
||||
|
|
@ -1728,7 +1982,7 @@ z
|
|||
<use xlink:href="#DejaVuSans-6c" transform="translate(1244.861328 0)"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="line2d_29">
|
||||
<g id="line2d_32">
|
||||
<path d="M 80.53561 308.17237
|
||||
L 80.53561 111.660101
|
||||
L 361.499024 185.352202
|
||||
|
|
@ -1776,7 +2030,7 @@ z
|
|||
</g>
|
||||
</g>
|
||||
<g id="legend_1">
|
||||
<g id="line2d_30">
|
||||
<g id="line2d_33">
|
||||
<path d="M 394.72 48.44675
|
||||
L 402.72 48.44675
|
||||
L 410.72 48.44675
|
||||
|
|
@ -1908,7 +2162,7 @@ z
|
|||
<use xlink:href="#DejaVuSans-30" transform="translate(977.255859 0.78125)"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="line2d_31">
|
||||
<g id="line2d_34">
|
||||
<path d="M 394.72 60.18925
|
||||
L 402.72 60.18925
|
||||
L 410.72 60.18925
|
||||
|
|
@ -1980,7 +2234,7 @@ z
|
|||
<use xlink:href="#DejaVuSans-30" transform="translate(938.925781 0.78125)"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="line2d_32">
|
||||
<g id="line2d_35">
|
||||
<path d="M 394.72 71.93175
|
||||
L 402.72 71.93175
|
||||
L 410.72 71.93175
|
||||
|
|
@ -2008,6 +2262,177 @@ L 410.72 71.93175
|
|||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="text_24">
|
||||
<!-- Z = 0 € -->
|
||||
<g style="fill: #7c3aed" transform="translate(130.162252 327.737673) scale(0.075 -0.075)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-5a" d="M 359 4666
|
||||
L 4025 4666
|
||||
L 4025 4184
|
||||
L 1075 531
|
||||
L 4097 531
|
||||
L 4097 0
|
||||
L 288 0
|
||||
L 288 481
|
||||
L 3238 4134
|
||||
L 359 4134
|
||||
L 359 4666
|
||||
z
|
||||
" transform="scale(0.015625)"/>
|
||||
<path id="DejaVuSans-3d" d="M 678 2906
|
||||
L 4684 2906
|
||||
L 4684 2381
|
||||
L 678 2381
|
||||
L 678 2906
|
||||
z
|
||||
M 678 1631
|
||||
L 4684 1631
|
||||
L 4684 1100
|
||||
L 678 1100
|
||||
L 678 1631
|
||||
z
|
||||
" transform="scale(0.015625)"/>
|
||||
<path id="DejaVuSans-20ac" d="M 3647 4306
|
||||
L 3647 3641
|
||||
Q 3363 3969 3098 4109
|
||||
Q 2834 4250 2516 4250
|
||||
Q 2025 4250 1709 3937
|
||||
Q 1394 3625 1294 3041
|
||||
L 3097 3041
|
||||
L 2925 2656
|
||||
L 1244 2656
|
||||
Q 1238 2581 1236 2509
|
||||
Q 1234 2438 1234 2328
|
||||
Q 1234 2228 1236 2156
|
||||
Q 1238 2084 1244 2009
|
||||
L 2638 2009
|
||||
L 2463 1625
|
||||
L 1294 1625
|
||||
Q 1394 1041 1709 725
|
||||
Q 2025 409 2516 409
|
||||
Q 2834 409 3098 550
|
||||
Q 3363 691 3647 1019
|
||||
L 3647 359
|
||||
Q 3369 134 3080 21
|
||||
Q 2791 -91 2491 -91
|
||||
Q 1750 -91 1267 362
|
||||
Q 784 816 659 1625
|
||||
L 0 1625
|
||||
L 172 2009
|
||||
L 606 2009
|
||||
Q 606 2081 604 2154
|
||||
Q 603 2228 603 2328
|
||||
Q 603 2438 604 2511
|
||||
Q 606 2584 606 2656
|
||||
L 0 2656
|
||||
L 172 3041
|
||||
L 659 3041
|
||||
Q 784 3844 1268 4297
|
||||
Q 1753 4750 2491 4750
|
||||
Q 2797 4750 3086 4639
|
||||
Q 3375 4528 3647 4306
|
||||
z
|
||||
" transform="scale(0.015625)"/>
|
||||
</defs>
|
||||
<use xlink:href="#DejaVuSans-5a"/>
|
||||
<use xlink:href="#DejaVuSans-20" transform="translate(68.505859 0)"/>
|
||||
<use xlink:href="#DejaVuSans-3d" transform="translate(100.292969 0)"/>
|
||||
<use xlink:href="#DejaVuSans-20" transform="translate(184.082031 0)"/>
|
||||
<use xlink:href="#DejaVuSans-30" transform="translate(215.869141 0)"/>
|
||||
<use xlink:href="#DejaVuSans-20" transform="translate(279.492188 0)"/>
|
||||
<use xlink:href="#DejaVuSans-20ac" transform="translate(311.279297 0)"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="text_25">
|
||||
<!-- Z = 2.000 € -->
|
||||
<g style="fill: #7c3aed" transform="translate(436.491667 273.094902) scale(0.075 -0.075)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-2e" d="M 684 794
|
||||
L 1344 794
|
||||
L 1344 0
|
||||
L 684 0
|
||||
L 684 794
|
||||
z
|
||||
" transform="scale(0.015625)"/>
|
||||
</defs>
|
||||
<use xlink:href="#DejaVuSans-5a"/>
|
||||
<use xlink:href="#DejaVuSans-20" transform="translate(68.505859 0)"/>
|
||||
<use xlink:href="#DejaVuSans-3d" transform="translate(100.292969 0)"/>
|
||||
<use xlink:href="#DejaVuSans-20" transform="translate(184.082031 0)"/>
|
||||
<use xlink:href="#DejaVuSans-32" transform="translate(215.869141 0)"/>
|
||||
<use xlink:href="#DejaVuSans-2e" transform="translate(279.492188 0)"/>
|
||||
<use xlink:href="#DejaVuSans-30" transform="translate(311.279297 0)"/>
|
||||
<use xlink:href="#DejaVuSans-30" transform="translate(374.902344 0)"/>
|
||||
<use xlink:href="#DejaVuSans-30" transform="translate(438.525391 0)"/>
|
||||
<use xlink:href="#DejaVuSans-20" transform="translate(502.148438 0)"/>
|
||||
<use xlink:href="#DejaVuSans-20ac" transform="translate(533.935547 0)"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="text_26">
|
||||
<!-- Z = 2.375 € -->
|
||||
<g style="fill: #7c3aed" transform="translate(436.491667 236.248852) scale(0.075 -0.075)">
|
||||
<use xlink:href="#DejaVuSans-5a"/>
|
||||
<use xlink:href="#DejaVuSans-20" transform="translate(68.505859 0)"/>
|
||||
<use xlink:href="#DejaVuSans-3d" transform="translate(100.292969 0)"/>
|
||||
<use xlink:href="#DejaVuSans-20" transform="translate(184.082031 0)"/>
|
||||
<use xlink:href="#DejaVuSans-32" transform="translate(215.869141 0)"/>
|
||||
<use xlink:href="#DejaVuSans-2e" transform="translate(279.492188 0)"/>
|
||||
<use xlink:href="#DejaVuSans-33" transform="translate(311.279297 0)"/>
|
||||
<use xlink:href="#DejaVuSans-37" transform="translate(374.902344 0)"/>
|
||||
<use xlink:href="#DejaVuSans-35" transform="translate(438.525391 0)"/>
|
||||
<use xlink:href="#DejaVuSans-20" transform="translate(502.148438 0)"/>
|
||||
<use xlink:href="#DejaVuSans-20ac" transform="translate(533.935547 0)"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="patch_6">
|
||||
<path d="M 179.285106 252.657412
|
||||
Q 202.992666 226.748642 225.039768 202.654502
|
||||
" style="fill: none; stroke: #7c3aed; stroke-width: 2.2; stroke-linecap: round"/>
|
||||
<path d="M 220.863976 204.255364
|
||||
L 225.039768 202.654502
|
||||
L 223.814983 206.955653
|
||||
z
|
||||
" style="fill: #7c3aed; stroke: #7c3aed; stroke-width: 2.2; stroke-linecap: round"/>
|
||||
</g>
|
||||
<g id="text_27">
|
||||
<!-- $\mathbf{c} = (150; 250)$ -->
|
||||
<g style="fill: #7c3aed" transform="translate(233.66775 201.711903) scale(0.085 -0.085)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-Bold-63" d="M 3366 3391
|
||||
L 3366 2478
|
||||
Q 3138 2634 2908 2709
|
||||
Q 2678 2784 2431 2784
|
||||
Q 1963 2784 1702 2511
|
||||
Q 1441 2238 1441 1747
|
||||
Q 1441 1256 1702 982
|
||||
Q 1963 709 2431 709
|
||||
Q 2694 709 2930 787
|
||||
Q 3166 866 3366 1019
|
||||
L 3366 103
|
||||
Q 3103 6 2833 -42
|
||||
Q 2563 -91 2291 -91
|
||||
Q 1344 -91 809 395
|
||||
Q 275 881 275 1747
|
||||
Q 275 2613 809 3098
|
||||
Q 1344 3584 2291 3584
|
||||
Q 2566 3584 2833 3536
|
||||
Q 3100 3488 3366 3391
|
||||
z
|
||||
" transform="scale(0.015625)"/>
|
||||
</defs>
|
||||
<use xlink:href="#DejaVuSans-Bold-63" transform="translate(0 0.125)"/>
|
||||
<use xlink:href="#DejaVuSans-3d" transform="translate(78.759766 0.125)"/>
|
||||
<use xlink:href="#DejaVuSans-28" transform="translate(182.03125 0.125)"/>
|
||||
<use xlink:href="#DejaVuSans-31" transform="translate(221.044922 0.125)"/>
|
||||
<use xlink:href="#DejaVuSans-35" transform="translate(284.667969 0.125)"/>
|
||||
<use xlink:href="#DejaVuSans-30" transform="translate(348.291016 0.125)"/>
|
||||
<use xlink:href="#DejaVuSans-3b" transform="translate(411.914062 0.125)"/>
|
||||
<use xlink:href="#DejaVuSans-32" transform="translate(465.087891 0.125)"/>
|
||||
<use xlink:href="#DejaVuSans-35" transform="translate(528.710938 0.125)"/>
|
||||
<use xlink:href="#DejaVuSans-30" transform="translate(592.333984 0.125)"/>
|
||||
<use xlink:href="#DejaVuSans-29" transform="translate(655.957031 0.125)"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 69 KiB |
|
|
@ -44,15 +44,25 @@ L 275.546558 234.022071
|
|||
L 399.362509 260.929849
|
||||
L 469.719463 263.503636
|
||||
" clip-path="url(#pc5415b3683)" style="fill: none; stroke-dasharray: 5.18,2.24; stroke-dashoffset: 0; stroke: #4338ca; stroke-width: 1.4"/>
|
||||
</g>
|
||||
<g id="line2d_2">
|
||||
<path d="M 57.44 85.651402
|
||||
L 363.250105 317.8
|
||||
" clip-path="url(#pc5415b3683)" style="fill: none; stroke: #4338ca; stroke-opacity: 0.75; stroke-width: 1.1; stroke-linecap: square"/>
|
||||
</g>
|
||||
<g id="line2d_3">
|
||||
<path d="M 57.44 168.507483
|
||||
L 489.351818 168.507483
|
||||
" clip-path="url(#pc5415b3683)" style="fill: none; stroke-dasharray: 4.44,1.92; stroke-dashoffset: 0; stroke: #059669; stroke-opacity: 0.9; stroke-width: 1.2"/>
|
||||
</g>
|
||||
<g id="matplotlib.axis_1">
|
||||
<g id="xtick_1">
|
||||
<g id="line2d_2">
|
||||
<g id="line2d_4">
|
||||
<path d="M 94.584785 274.84
|
||||
L 94.584785 25.44
|
||||
" clip-path="url(#pc5415b3683)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/>
|
||||
</g>
|
||||
<g id="line2d_3">
|
||||
<g id="line2d_5">
|
||||
<defs>
|
||||
<path id="mf0a04b41f8" d="M 0 0
|
||||
L 0 3.5
|
||||
|
|
@ -173,12 +183,12 @@ z
|
|||
</g>
|
||||
</g>
|
||||
<g id="xtick_2">
|
||||
<g id="line2d_4">
|
||||
<g id="line2d_6">
|
||||
<path d="M 156.031907 274.84
|
||||
L 156.031907 25.44
|
||||
" clip-path="url(#pc5415b3683)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/>
|
||||
</g>
|
||||
<g id="line2d_5">
|
||||
<g id="line2d_7">
|
||||
<g>
|
||||
<use xlink:href="#mf0a04b41f8" x="156.031907" y="274.84" style="stroke: #000000; stroke-width: 0.8"/>
|
||||
</g>
|
||||
|
|
@ -236,12 +246,12 @@ z
|
|||
</g>
|
||||
</g>
|
||||
<g id="xtick_3">
|
||||
<g id="line2d_6">
|
||||
<g id="line2d_8">
|
||||
<path d="M 217.479028 274.84
|
||||
L 217.479028 25.44
|
||||
" clip-path="url(#pc5415b3683)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/>
|
||||
</g>
|
||||
<g id="line2d_7">
|
||||
<g id="line2d_9">
|
||||
<g>
|
||||
<use xlink:href="#mf0a04b41f8" x="217.479028" y="274.84" style="stroke: #000000; stroke-width: 0.8"/>
|
||||
</g>
|
||||
|
|
@ -279,12 +289,12 @@ z
|
|||
</g>
|
||||
</g>
|
||||
<g id="xtick_4">
|
||||
<g id="line2d_8">
|
||||
<g id="line2d_10">
|
||||
<path d="M 278.92615 274.84
|
||||
L 278.92615 25.44
|
||||
" clip-path="url(#pc5415b3683)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/>
|
||||
</g>
|
||||
<g id="line2d_9">
|
||||
<g id="line2d_11">
|
||||
<g>
|
||||
<use xlink:href="#mf0a04b41f8" x="278.92615" y="274.84" style="stroke: #000000; stroke-width: 0.8"/>
|
||||
</g>
|
||||
|
|
@ -327,12 +337,12 @@ z
|
|||
</g>
|
||||
</g>
|
||||
<g id="xtick_5">
|
||||
<g id="line2d_10">
|
||||
<g id="line2d_12">
|
||||
<path d="M 340.373272 274.84
|
||||
L 340.373272 25.44
|
||||
" clip-path="url(#pc5415b3683)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/>
|
||||
</g>
|
||||
<g id="line2d_11">
|
||||
<g id="line2d_13">
|
||||
<g>
|
||||
<use xlink:href="#mf0a04b41f8" x="340.373272" y="274.84" style="stroke: #000000; stroke-width: 0.8"/>
|
||||
</g>
|
||||
|
|
@ -349,12 +359,12 @@ L 340.373272 25.44
|
|||
</g>
|
||||
</g>
|
||||
<g id="xtick_6">
|
||||
<g id="line2d_12">
|
||||
<g id="line2d_14">
|
||||
<path d="M 401.820393 274.84
|
||||
L 401.820393 25.44
|
||||
" clip-path="url(#pc5415b3683)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/>
|
||||
</g>
|
||||
<g id="line2d_13">
|
||||
<g id="line2d_15">
|
||||
<g>
|
||||
<use xlink:href="#mf0a04b41f8" x="401.820393" y="274.84" style="stroke: #000000; stroke-width: 0.8"/>
|
||||
</g>
|
||||
|
|
@ -371,12 +381,12 @@ L 401.820393 25.44
|
|||
</g>
|
||||
</g>
|
||||
<g id="xtick_7">
|
||||
<g id="line2d_14">
|
||||
<g id="line2d_16">
|
||||
<path d="M 463.267515 274.84
|
||||
L 463.267515 25.44
|
||||
" clip-path="url(#pc5415b3683)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/>
|
||||
</g>
|
||||
<g id="line2d_15">
|
||||
<g id="line2d_17">
|
||||
<g>
|
||||
<use xlink:href="#mf0a04b41f8" x="463.267515" y="274.84" style="stroke: #000000; stroke-width: 0.8"/>
|
||||
</g>
|
||||
|
|
@ -728,12 +738,12 @@ z
|
|||
</g>
|
||||
<g id="matplotlib.axis_2">
|
||||
<g id="ytick_1">
|
||||
<g id="line2d_16">
|
||||
<g id="line2d_18">
|
||||
<path d="M 57.44 241.509453
|
||||
L 489.351818 241.509453
|
||||
" clip-path="url(#pc5415b3683)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/>
|
||||
</g>
|
||||
<g id="line2d_17">
|
||||
<g id="line2d_19">
|
||||
<defs>
|
||||
<path id="mc0b9ff744f" d="M 0 0
|
||||
L -3.5 0
|
||||
|
|
@ -781,12 +791,12 @@ z
|
|||
</g>
|
||||
</g>
|
||||
<g id="ytick_2">
|
||||
<g id="line2d_18">
|
||||
<g id="line2d_20">
|
||||
<path d="M 57.44 194.713318
|
||||
L 489.351818 194.713318
|
||||
" clip-path="url(#pc5415b3683)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/>
|
||||
</g>
|
||||
<g id="line2d_19">
|
||||
<g id="line2d_21">
|
||||
<g>
|
||||
<use xlink:href="#mc0b9ff744f" x="57.44" y="194.713318" style="stroke: #000000; stroke-width: 0.8"/>
|
||||
</g>
|
||||
|
|
@ -802,12 +812,12 @@ L 489.351818 194.713318
|
|||
</g>
|
||||
</g>
|
||||
<g id="ytick_3">
|
||||
<g id="line2d_20">
|
||||
<g id="line2d_22">
|
||||
<path d="M 57.44 147.917184
|
||||
L 489.351818 147.917184
|
||||
" clip-path="url(#pc5415b3683)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/>
|
||||
</g>
|
||||
<g id="line2d_21">
|
||||
<g id="line2d_23">
|
||||
<g>
|
||||
<use xlink:href="#mc0b9ff744f" x="57.44" y="147.917184" style="stroke: #000000; stroke-width: 0.8"/>
|
||||
</g>
|
||||
|
|
@ -823,12 +833,12 @@ L 489.351818 147.917184
|
|||
</g>
|
||||
</g>
|
||||
<g id="ytick_4">
|
||||
<g id="line2d_22">
|
||||
<g id="line2d_24">
|
||||
<path d="M 57.44 101.121049
|
||||
L 489.351818 101.121049
|
||||
" clip-path="url(#pc5415b3683)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/>
|
||||
</g>
|
||||
<g id="line2d_23">
|
||||
<g id="line2d_25">
|
||||
<g>
|
||||
<use xlink:href="#mc0b9ff744f" x="57.44" y="101.121049" style="stroke: #000000; stroke-width: 0.8"/>
|
||||
</g>
|
||||
|
|
@ -844,12 +854,12 @@ L 489.351818 101.121049
|
|||
</g>
|
||||
</g>
|
||||
<g id="ytick_5">
|
||||
<g id="line2d_24">
|
||||
<g id="line2d_26">
|
||||
<path d="M 57.44 54.324914
|
||||
L 489.351818 54.324914
|
||||
" clip-path="url(#pc5415b3683)" style="fill: none; stroke-dasharray: 0.8,1.32; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"/>
|
||||
</g>
|
||||
<g id="line2d_25">
|
||||
<g id="line2d_27">
|
||||
<g>
|
||||
<use xlink:href="#mc0b9ff744f" x="57.44" y="54.324914" style="stroke: #000000; stroke-width: 0.8"/>
|
||||
</g>
|
||||
|
|
@ -1066,6 +1076,11 @@ z
|
|||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="line2d_28">
|
||||
<path d="M 57.44 52.148669
|
||||
L 407.383365 317.8
|
||||
" clip-path="url(#pc5415b3683)" style="fill: none; stroke-dasharray: 1.6,2.64; stroke-dashoffset: 0; stroke: #b45309; stroke-width: 1.6"/>
|
||||
</g>
|
||||
<g id="patch_3">
|
||||
<path d="M 57.44 274.84
|
||||
L 57.44 25.44
|
||||
|
|
@ -1406,7 +1421,7 @@ z
|
|||
</g>
|
||||
</g>
|
||||
<g id="legend_1">
|
||||
<g id="line2d_26">
|
||||
<g id="line2d_29">
|
||||
<path d="M 309.988068 35.91875
|
||||
L 317.988068 35.91875
|
||||
L 325.988068 35.91875
|
||||
|
|
@ -1778,6 +1793,341 @@ z
|
|||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="text_29">
|
||||
<!-- dieselbe Steigung, eine Stufe höher — -->
|
||||
<g style="fill: #b45309" transform="translate(222.719845 134.109124) scale(0.075 -0.075)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-64" d="M 2906 2969
|
||||
L 2906 4863
|
||||
L 3481 4863
|
||||
L 3481 0
|
||||
L 2906 0
|
||||
L 2906 525
|
||||
Q 2725 213 2448 61
|
||||
Q 2172 -91 1784 -91
|
||||
Q 1150 -91 751 415
|
||||
Q 353 922 353 1747
|
||||
Q 353 2572 751 3078
|
||||
Q 1150 3584 1784 3584
|
||||
Q 2172 3584 2448 3432
|
||||
Q 2725 3281 2906 2969
|
||||
z
|
||||
M 947 1747
|
||||
Q 947 1113 1208 752
|
||||
Q 1469 391 1925 391
|
||||
Q 2381 391 2643 752
|
||||
Q 2906 1113 2906 1747
|
||||
Q 2906 2381 2643 2742
|
||||
Q 2381 3103 1925 3103
|
||||
Q 1469 3103 1208 2742
|
||||
Q 947 2381 947 1747
|
||||
z
|
||||
" transform="scale(0.015625)"/>
|
||||
<path id="DejaVuSans-53" d="M 3425 4513
|
||||
L 3425 3897
|
||||
Q 3066 4069 2747 4153
|
||||
Q 2428 4238 2131 4238
|
||||
Q 1616 4238 1336 4038
|
||||
Q 1056 3838 1056 3469
|
||||
Q 1056 3159 1242 3001
|
||||
Q 1428 2844 1947 2747
|
||||
L 2328 2669
|
||||
Q 3034 2534 3370 2195
|
||||
Q 3706 1856 3706 1288
|
||||
Q 3706 609 3251 259
|
||||
Q 2797 -91 1919 -91
|
||||
Q 1588 -91 1214 -16
|
||||
Q 841 59 441 206
|
||||
L 441 856
|
||||
Q 825 641 1194 531
|
||||
Q 1563 422 1919 422
|
||||
Q 2459 422 2753 634
|
||||
Q 3047 847 3047 1241
|
||||
Q 3047 1584 2836 1778
|
||||
Q 2625 1972 2144 2069
|
||||
L 1759 2144
|
||||
Q 1053 2284 737 2584
|
||||
Q 422 2884 422 3419
|
||||
Q 422 4038 858 4394
|
||||
Q 1294 4750 2059 4750
|
||||
Q 2388 4750 2728 4690
|
||||
Q 3069 4631 3425 4513
|
||||
z
|
||||
" transform="scale(0.015625)"/>
|
||||
<path id="DejaVuSans-66" d="M 2375 4863
|
||||
L 2375 4384
|
||||
L 1825 4384
|
||||
Q 1516 4384 1395 4259
|
||||
Q 1275 4134 1275 3809
|
||||
L 1275 3500
|
||||
L 2222 3500
|
||||
L 2222 3053
|
||||
L 1275 3053
|
||||
L 1275 0
|
||||
L 697 0
|
||||
L 697 3053
|
||||
L 147 3053
|
||||
L 147 3500
|
||||
L 697 3500
|
||||
L 697 3744
|
||||
Q 697 4328 969 4595
|
||||
Q 1241 4863 1831 4863
|
||||
L 2375 4863
|
||||
z
|
||||
" transform="scale(0.015625)"/>
|
||||
<path id="DejaVuSans-f6" d="M 1959 3097
|
||||
Q 1497 3097 1228 2736
|
||||
Q 959 2375 959 1747
|
||||
Q 959 1119 1226 758
|
||||
Q 1494 397 1959 397
|
||||
Q 2419 397 2687 759
|
||||
Q 2956 1122 2956 1747
|
||||
Q 2956 2369 2687 2733
|
||||
Q 2419 3097 1959 3097
|
||||
z
|
||||
M 1959 3584
|
||||
Q 2709 3584 3137 3096
|
||||
Q 3566 2609 3566 1747
|
||||
Q 3566 888 3137 398
|
||||
Q 2709 -91 1959 -91
|
||||
Q 1206 -91 779 398
|
||||
Q 353 888 353 1747
|
||||
Q 353 2609 779 3096
|
||||
Q 1206 3584 1959 3584
|
||||
z
|
||||
M 2253 4850
|
||||
L 2888 4850
|
||||
L 2888 4219
|
||||
L 2253 4219
|
||||
L 2253 4850
|
||||
z
|
||||
M 1031 4850
|
||||
L 1666 4850
|
||||
L 1666 4219
|
||||
L 1031 4219
|
||||
L 1031 4850
|
||||
z
|
||||
" transform="scale(0.015625)"/>
|
||||
<path id="DejaVuSans-2014" d="M 313 1978
|
||||
L 6088 1978
|
||||
L 6088 1528
|
||||
L 313 1528
|
||||
L 313 1978
|
||||
z
|
||||
" transform="scale(0.015625)"/>
|
||||
</defs>
|
||||
<use xlink:href="#DejaVuSans-64"/>
|
||||
<use xlink:href="#DejaVuSans-69" transform="translate(63.476562 0)"/>
|
||||
<use xlink:href="#DejaVuSans-65" transform="translate(91.259766 0)"/>
|
||||
<use xlink:href="#DejaVuSans-73" transform="translate(152.783203 0)"/>
|
||||
<use xlink:href="#DejaVuSans-65" transform="translate(204.882812 0)"/>
|
||||
<use xlink:href="#DejaVuSans-6c" transform="translate(266.40625 0)"/>
|
||||
<use xlink:href="#DejaVuSans-62" transform="translate(294.189453 0)"/>
|
||||
<use xlink:href="#DejaVuSans-65" transform="translate(357.666016 0)"/>
|
||||
<use xlink:href="#DejaVuSans-20" transform="translate(419.189453 0)"/>
|
||||
<use xlink:href="#DejaVuSans-53" transform="translate(450.976562 0)"/>
|
||||
<use xlink:href="#DejaVuSans-74" transform="translate(514.453125 0)"/>
|
||||
<use xlink:href="#DejaVuSans-65" transform="translate(553.662109 0)"/>
|
||||
<use xlink:href="#DejaVuSans-69" transform="translate(615.185547 0)"/>
|
||||
<use xlink:href="#DejaVuSans-67" transform="translate(642.96875 0)"/>
|
||||
<use xlink:href="#DejaVuSans-75" transform="translate(706.445312 0)"/>
|
||||
<use xlink:href="#DejaVuSans-6e" transform="translate(769.824219 0)"/>
|
||||
<use xlink:href="#DejaVuSans-67" transform="translate(833.203125 0)"/>
|
||||
<use xlink:href="#DejaVuSans-2c" transform="translate(896.679688 0)"/>
|
||||
<use xlink:href="#DejaVuSans-20" transform="translate(928.466797 0)"/>
|
||||
<use xlink:href="#DejaVuSans-65" transform="translate(960.253906 0)"/>
|
||||
<use xlink:href="#DejaVuSans-69" transform="translate(1021.777344 0)"/>
|
||||
<use xlink:href="#DejaVuSans-6e" transform="translate(1049.560547 0)"/>
|
||||
<use xlink:href="#DejaVuSans-65" transform="translate(1112.939453 0)"/>
|
||||
<use xlink:href="#DejaVuSans-20" transform="translate(1174.462891 0)"/>
|
||||
<use xlink:href="#DejaVuSans-53" transform="translate(1206.25 0)"/>
|
||||
<use xlink:href="#DejaVuSans-74" transform="translate(1269.726562 0)"/>
|
||||
<use xlink:href="#DejaVuSans-75" transform="translate(1308.935547 0)"/>
|
||||
<use xlink:href="#DejaVuSans-66" transform="translate(1372.314453 0)"/>
|
||||
<use xlink:href="#DejaVuSans-65" transform="translate(1407.519531 0)"/>
|
||||
<use xlink:href="#DejaVuSans-20" transform="translate(1469.042969 0)"/>
|
||||
<use xlink:href="#DejaVuSans-68" transform="translate(1500.830078 0)"/>
|
||||
<use xlink:href="#DejaVuSans-f6" transform="translate(1564.208984 0)"/>
|
||||
<use xlink:href="#DejaVuSans-68" transform="translate(1625.390625 0)"/>
|
||||
<use xlink:href="#DejaVuSans-65" transform="translate(1688.769531 0)"/>
|
||||
<use xlink:href="#DejaVuSans-72" transform="translate(1750.292969 0)"/>
|
||||
<use xlink:href="#DejaVuSans-20" transform="translate(1791.40625 0)"/>
|
||||
<use xlink:href="#DejaVuSans-2014" transform="translate(1823.193359 0)"/>
|
||||
</g>
|
||||
<!-- jede gewichtete Summe nimmt die untere -->
|
||||
<g style="fill: #b45309" transform="translate(222.719845 142.507483) scale(0.075 -0.075)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-6a" d="M 603 3500
|
||||
L 1178 3500
|
||||
L 1178 -63
|
||||
Q 1178 -731 923 -1031
|
||||
Q 669 -1331 103 -1331
|
||||
L -116 -1331
|
||||
L -116 -844
|
||||
L 38 -844
|
||||
Q 366 -844 484 -692
|
||||
Q 603 -541 603 -63
|
||||
L 603 3500
|
||||
z
|
||||
M 603 4863
|
||||
L 1178 4863
|
||||
L 1178 4134
|
||||
L 603 4134
|
||||
L 603 4863
|
||||
z
|
||||
" transform="scale(0.015625)"/>
|
||||
</defs>
|
||||
<use xlink:href="#DejaVuSans-6a"/>
|
||||
<use xlink:href="#DejaVuSans-65" transform="translate(27.783203 0)"/>
|
||||
<use xlink:href="#DejaVuSans-64" transform="translate(89.306641 0)"/>
|
||||
<use xlink:href="#DejaVuSans-65" transform="translate(152.783203 0)"/>
|
||||
<use xlink:href="#DejaVuSans-20" transform="translate(214.306641 0)"/>
|
||||
<use xlink:href="#DejaVuSans-67" transform="translate(246.09375 0)"/>
|
||||
<use xlink:href="#DejaVuSans-65" transform="translate(309.570312 0)"/>
|
||||
<use xlink:href="#DejaVuSans-77" transform="translate(371.09375 0)"/>
|
||||
<use xlink:href="#DejaVuSans-69" transform="translate(452.880859 0)"/>
|
||||
<use xlink:href="#DejaVuSans-63" transform="translate(480.664062 0)"/>
|
||||
<use xlink:href="#DejaVuSans-68" transform="translate(535.644531 0)"/>
|
||||
<use xlink:href="#DejaVuSans-74" transform="translate(599.023438 0)"/>
|
||||
<use xlink:href="#DejaVuSans-65" transform="translate(638.232422 0)"/>
|
||||
<use xlink:href="#DejaVuSans-74" transform="translate(699.755859 0)"/>
|
||||
<use xlink:href="#DejaVuSans-65" transform="translate(738.964844 0)"/>
|
||||
<use xlink:href="#DejaVuSans-20" transform="translate(800.488281 0)"/>
|
||||
<use xlink:href="#DejaVuSans-53" transform="translate(832.275391 0)"/>
|
||||
<use xlink:href="#DejaVuSans-75" transform="translate(895.751953 0)"/>
|
||||
<use xlink:href="#DejaVuSans-6d" transform="translate(959.130859 0)"/>
|
||||
<use xlink:href="#DejaVuSans-6d" transform="translate(1056.542969 0)"/>
|
||||
<use xlink:href="#DejaVuSans-65" transform="translate(1153.955078 0)"/>
|
||||
<use xlink:href="#DejaVuSans-20" transform="translate(1215.478516 0)"/>
|
||||
<use xlink:href="#DejaVuSans-6e" transform="translate(1247.265625 0)"/>
|
||||
<use xlink:href="#DejaVuSans-69" transform="translate(1310.644531 0)"/>
|
||||
<use xlink:href="#DejaVuSans-6d" transform="translate(1338.427734 0)"/>
|
||||
<use xlink:href="#DejaVuSans-6d" transform="translate(1435.839844 0)"/>
|
||||
<use xlink:href="#DejaVuSans-74" transform="translate(1533.251953 0)"/>
|
||||
<use xlink:href="#DejaVuSans-20" transform="translate(1572.460938 0)"/>
|
||||
<use xlink:href="#DejaVuSans-64" transform="translate(1604.248047 0)"/>
|
||||
<use xlink:href="#DejaVuSans-69" transform="translate(1667.724609 0)"/>
|
||||
<use xlink:href="#DejaVuSans-65" transform="translate(1695.507812 0)"/>
|
||||
<use xlink:href="#DejaVuSans-20" transform="translate(1757.03125 0)"/>
|
||||
<use xlink:href="#DejaVuSans-75" transform="translate(1788.818359 0)"/>
|
||||
<use xlink:href="#DejaVuSans-6e" transform="translate(1852.197266 0)"/>
|
||||
<use xlink:href="#DejaVuSans-74" transform="translate(1915.576172 0)"/>
|
||||
<use xlink:href="#DejaVuSans-65" transform="translate(1954.785156 0)"/>
|
||||
<use xlink:href="#DejaVuSans-72" transform="translate(2016.308594 0)"/>
|
||||
<use xlink:href="#DejaVuSans-65" transform="translate(2055.171875 0)"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="text_30">
|
||||
<!-- ε-Constraint: CO₂ ≤ 5.912 kg -->
|
||||
<g style="fill: #059669" transform="translate(63.44 182.109124) scale(0.075 -0.075)">
|
||||
<defs>
|
||||
<path id="DejaVuSans-3b5" d="M 1234 1888
|
||||
Q 884 1963 697 2166
|
||||
Q 509 2366 509 2656
|
||||
Q 509 3097 866 3344
|
||||
Q 1219 3588 1831 3588
|
||||
Q 2069 3588 2334 3550
|
||||
Q 2600 3513 2906 3438
|
||||
L 2906 2916
|
||||
Q 2603 3006 2353 3047
|
||||
Q 2100 3088 1878 3088
|
||||
Q 1506 3088 1291 2944
|
||||
Q 1072 2800 1072 2600
|
||||
Q 1072 2381 1284 2241
|
||||
Q 1494 2103 1856 2103
|
||||
L 2341 2103
|
||||
L 2341 1628
|
||||
L 1878 1628
|
||||
Q 1450 1628 1225 1469
|
||||
Q 981 1294 981 1019
|
||||
Q 981 738 1244 563
|
||||
Q 1509 388 1981 388
|
||||
Q 2272 388 2538 444
|
||||
Q 2803 503 3025 619
|
||||
L 3025 84
|
||||
Q 2744 -3 2481 -47
|
||||
Q 2216 -91 1966 -91
|
||||
Q 1222 -91 819 194
|
||||
Q 416 478 416 1019
|
||||
Q 416 1356 631 1584
|
||||
Q 847 1813 1234 1888
|
||||
z
|
||||
" transform="scale(0.015625)"/>
|
||||
<path id="DejaVuSans-2264" d="M 4684 3175
|
||||
L 1684 2309
|
||||
L 4684 1453
|
||||
L 4684 897
|
||||
L 678 2047
|
||||
L 678 2578
|
||||
L 4684 3725
|
||||
L 4684 3175
|
||||
z
|
||||
M 678 531
|
||||
L 4684 531
|
||||
L 4684 0
|
||||
L 678 0
|
||||
L 678 531
|
||||
z
|
||||
" transform="scale(0.015625)"/>
|
||||
</defs>
|
||||
<use xlink:href="#DejaVuSans-3b5"/>
|
||||
<use xlink:href="#DejaVuSans-2d" transform="translate(54.052734 0)"/>
|
||||
<use xlink:href="#DejaVuSans-43" transform="translate(90.136719 0)"/>
|
||||
<use xlink:href="#DejaVuSans-6f" transform="translate(159.960938 0)"/>
|
||||
<use xlink:href="#DejaVuSans-6e" transform="translate(221.142578 0)"/>
|
||||
<use xlink:href="#DejaVuSans-73" transform="translate(284.521484 0)"/>
|
||||
<use xlink:href="#DejaVuSans-74" transform="translate(336.621094 0)"/>
|
||||
<use xlink:href="#DejaVuSans-72" transform="translate(375.830078 0)"/>
|
||||
<use xlink:href="#DejaVuSans-61" transform="translate(416.943359 0)"/>
|
||||
<use xlink:href="#DejaVuSans-69" transform="translate(478.222656 0)"/>
|
||||
<use xlink:href="#DejaVuSans-6e" transform="translate(506.005859 0)"/>
|
||||
<use xlink:href="#DejaVuSans-74" transform="translate(569.384766 0)"/>
|
||||
<use xlink:href="#DejaVuSans-3a" transform="translate(608.59375 0)"/>
|
||||
<use xlink:href="#DejaVuSans-20" transform="translate(642.285156 0)"/>
|
||||
<use xlink:href="#DejaVuSans-43" transform="translate(674.072266 0)"/>
|
||||
<use xlink:href="#DejaVuSans-4f" transform="translate(743.896484 0)"/>
|
||||
<use xlink:href="#DejaVuSans-2082" transform="translate(822.607422 0)"/>
|
||||
<use xlink:href="#DejaVuSans-20" transform="translate(862.695312 0)"/>
|
||||
<use xlink:href="#DejaVuSans-2264" transform="translate(894.482422 0)"/>
|
||||
<use xlink:href="#DejaVuSans-20" transform="translate(978.271484 0)"/>
|
||||
<use xlink:href="#DejaVuSans-35" transform="translate(1010.058594 0)"/>
|
||||
<use xlink:href="#DejaVuSans-2e" transform="translate(1073.681641 0)"/>
|
||||
<use xlink:href="#DejaVuSans-39" transform="translate(1105.46875 0)"/>
|
||||
<use xlink:href="#DejaVuSans-31" transform="translate(1169.091797 0)"/>
|
||||
<use xlink:href="#DejaVuSans-32" transform="translate(1232.714844 0)"/>
|
||||
<use xlink:href="#DejaVuSans-20" transform="translate(1296.337891 0)"/>
|
||||
<use xlink:href="#DejaVuSans-6b" transform="translate(1328.125 0)"/>
|
||||
<use xlink:href="#DejaVuSans-67" transform="translate(1386.035156 0)"/>
|
||||
</g>
|
||||
<!-- findet genau diesen Punkt -->
|
||||
<g style="fill: #059669" transform="translate(63.44 190.507483) scale(0.075 -0.075)">
|
||||
<use xlink:href="#DejaVuSans-66"/>
|
||||
<use xlink:href="#DejaVuSans-69" transform="translate(35.205078 0)"/>
|
||||
<use xlink:href="#DejaVuSans-6e" transform="translate(62.988281 0)"/>
|
||||
<use xlink:href="#DejaVuSans-64" transform="translate(126.367188 0)"/>
|
||||
<use xlink:href="#DejaVuSans-65" transform="translate(189.84375 0)"/>
|
||||
<use xlink:href="#DejaVuSans-74" transform="translate(251.367188 0)"/>
|
||||
<use xlink:href="#DejaVuSans-20" transform="translate(290.576172 0)"/>
|
||||
<use xlink:href="#DejaVuSans-67" transform="translate(322.363281 0)"/>
|
||||
<use xlink:href="#DejaVuSans-65" transform="translate(385.839844 0)"/>
|
||||
<use xlink:href="#DejaVuSans-6e" transform="translate(447.363281 0)"/>
|
||||
<use xlink:href="#DejaVuSans-61" transform="translate(510.742188 0)"/>
|
||||
<use xlink:href="#DejaVuSans-75" transform="translate(572.021484 0)"/>
|
||||
<use xlink:href="#DejaVuSans-20" transform="translate(635.400391 0)"/>
|
||||
<use xlink:href="#DejaVuSans-64" transform="translate(667.1875 0)"/>
|
||||
<use xlink:href="#DejaVuSans-69" transform="translate(730.664062 0)"/>
|
||||
<use xlink:href="#DejaVuSans-65" transform="translate(758.447266 0)"/>
|
||||
<use xlink:href="#DejaVuSans-73" transform="translate(819.970703 0)"/>
|
||||
<use xlink:href="#DejaVuSans-65" transform="translate(872.070312 0)"/>
|
||||
<use xlink:href="#DejaVuSans-6e" transform="translate(933.59375 0)"/>
|
||||
<use xlink:href="#DejaVuSans-20" transform="translate(996.972656 0)"/>
|
||||
<use xlink:href="#DejaVuSans-50" transform="translate(1028.759766 0)"/>
|
||||
<use xlink:href="#DejaVuSans-75" transform="translate(1087.3125 0)"/>
|
||||
<use xlink:href="#DejaVuSans-6e" transform="translate(1150.691406 0)"/>
|
||||
<use xlink:href="#DejaVuSans-6b" transform="translate(1214.070312 0)"/>
|
||||
<use xlink:href="#DejaVuSans-74" transform="translate(1271.980469 0)"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 69 KiB |
6157
bilder_04/kap_milp_bnb_geometrie.svg
Normal file
|
After Width: | Height: | Size: 160 KiB |