Erste öffentliche Fassung: Math Model Generator & Solver
Übersetzt natürlichsprachige Optimierungsaufgaben (Deutsch) per LLM in eine geprüfte Modellspezifikation, erzeugt Solver-Code und führt ihn in einer bubblewrap-Sandbox aus. Deterministische Prüfungen ohne LLM, Report als Markdown/HTML, Benchmark mit 19 verifizierten Fällen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
commit
b74445b8d6
39 changed files with 7655 additions and 0 deletions
11
benchmark/cases/daten_portfolio_csv/aktien.csv
Normal file
11
benchmark/cases/daten_portfolio_csv/aktien.csv
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
Aktie;Rendite;Varianz;Gebuehr
|
||||
A01;6,9;2,04;0,68
|
||||
A02;14,4;1,63;0,74
|
||||
A03;11,5;3,62;0,39
|
||||
A04;9,8;3,01;0,27
|
||||
A05;4,0;3,30;0,34
|
||||
A06;4,0;3,33;0,46
|
||||
A07;2,8;3,24;0,69
|
||||
A08;13,3;1,97;0,72
|
||||
A09;9,8;3,26;0,20
|
||||
A10;11,2;2,52;0,51
|
||||
|
9
benchmark/cases/daten_portfolio_csv/expected.json
Normal file
9
benchmark/cases/daten_portfolio_csv/expected.json
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"problem_class": "Mixed-Integer Quadratic Programming (MIQP)",
|
||||
"target_stack": "SCIP (pyscipopt)",
|
||||
"sense": "maximize",
|
||||
"objective_value": 12.03,
|
||||
"tolerance": 1e-4,
|
||||
"min_sub_questions": 2,
|
||||
"source": "Unabhängig durch Enumeration aller 385 Teilmengen mit höchstens 4 Titeln verifiziert (je Teilmenge ein konvexes QP über scipy.optimize.minimize, Anteile in [0.05, 1] mit Summe 1). Optimum: nur A02 mit Anteil 1,0 -> 14,4 - 1,63 - 0,74 = 12,03. Zum Vergleich A02+A08: 11,634."
|
||||
}
|
||||
15
benchmark/cases/daten_portfolio_csv/task.txt
Normal file
15
benchmark/cases/daten_portfolio_csv/task.txt
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
Ein Investor verteilt sein gesamtes Kapital auf Aktien. Die Kennzahlen stehen in der beigelegten Datei aktien.csv mit den Spalten: Aktie, Rendite (erwartete Jahresrendite in Prozentpunkten), Varianz (Risikokennzahl in Prozentpunkten), Gebuehr (feste Kaufgebühr in Prozentpunkten des Kapitals, die einmal je gekaufter Aktie anfällt).
|
||||
|
||||
Sei w_i der Kapitalanteil von Aktie i (0 ≤ w_i ≤ 1) und z_i = 1, falls Aktie i gekauft wird, sonst 0.
|
||||
|
||||
Zu maximieren ist der Nutzen
|
||||
|
||||
U = Summe über i von ( Rendite_i * w_i ) − 1,0 * Summe über i von ( Varianz_i * w_i^2 ) − Summe über i von ( Gebuehr_i * z_i )
|
||||
|
||||
unter diesen Bedingungen:
|
||||
- Die Anteile summieren sich zu genau 1.
|
||||
- Es dürfen höchstens 4 Aktien gekauft werden.
|
||||
- Wird eine Aktie gekauft, beträgt ihr Anteil mindestens 5 % (w_i ≥ 0,05 * z_i); wird sie nicht gekauft, ist ihr Anteil 0 (w_i ≤ z_i).
|
||||
|
||||
a) Bestimmen Sie das nutzenmaximale Portfolio: welche Aktien mit welchen Anteilen, und wie hoch ist der Nutzen?
|
||||
b) Begründen Sie, warum die Gebühren dazu führen, dass nicht beliebig viele Aktien gekauft werden.
|
||||
9
benchmark/cases/graph_ersatz_dijkstra/expected.json
Normal file
9
benchmark/cases/graph_ersatz_dijkstra/expected.json
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"problem_class": "Kürzeste Wege im Graphen (Shortest Path)",
|
||||
"target_stack": "NetworkX (Dijkstra)",
|
||||
"sense": "minimize",
|
||||
"objective_value": 29,
|
||||
"tolerance": 1e-06,
|
||||
"min_sub_questions": 2,
|
||||
"source": "Ersatzproblem als kürzester Weg. Optimum unabhängig durch Enumeration aller vier Wege von 0 nach 3 verifiziert: 0-1-3 = 8+21 = 29 (Minimum), 0-1-2-3 = 30, 0-2-3 = 30, 0-3 = 31. Die Aufgabe verlangt ausdrücklich Dijkstra, deshalb ist der Stack Teil der Erwartung."
|
||||
}
|
||||
16
benchmark/cases/graph_ersatz_dijkstra/task.txt
Normal file
16
benchmark/cases/graph_ersatz_dijkstra/task.txt
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
## Ersatzplanung für ein Lieferfahrzeug
|
||||
|
||||
Ein Kurierdienst braucht für die nächsten drei Jahre ein Lieferfahrzeug. Danach stellt er auf eine gemietete Elektroflotte um, das Fahrzeug wird dann nicht mehr benötigt. Weil das Fahrzeug im Stadtverkehr stark beansprucht wird, steigen Reparatur- und Betriebskosten mit dem Alter deutlich an. Es kann sich deshalb lohnen, das Fahrzeug nach einem und/oder nach zwei Jahren gegen ein neues gleichen Typs auszutauschen.
|
||||
|
||||
Die folgende Kostenmatrix C gibt an, welche Kosten (Wertverlust, Reparatur- und Betriebskosten, in Tausend Euro) entstehen, wenn am Ende von Jahr i = 0,1,2 (also zu Beginn von Jahr i+1) ein neues Fahrzeug gekauft und bis zum Ende von Jahr j = 1,2,3 genutzt wird.
|
||||
|
||||
Zu welchen Zeitpunkten sollte das Fahrzeug gegebenenfalls ersetzt werden, damit die Fahrzeugkosten der nächsten drei Jahre möglichst gering sind?
|
||||
|
||||
| i \ j | 1 | 2 | 3 |
|
||||
|---------|-----|-----|-----|
|
||||
| 0 | 8 | 18 | 31 |
|
||||
| 1 | - | 10 | 21 |
|
||||
| 2 | - | - | 12 |
|
||||
|
||||
- a) Beschreiben Sie die Situation als Kürzeste-Wege-Problem und zeichnen Sie den zugehörigen Graphen!
|
||||
- b) Bestimmen Sie die Lösung mit dem Dijkstra-Algorithmus!
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"problem_class": "Mixed-Integer Quadratic Programming (MIQP)",
|
||||
"target_stack": "SCIP (pyscipopt)",
|
||||
"sense": "maximize",
|
||||
"objective_value": 9.755769,
|
||||
"tolerance": 0.0001,
|
||||
"source": "Unabhängig durch Enumeration aller Teilmengen mit 5 bis 10 Titeln verifiziert (je Teilmenge ein konvexes QP über scipy.optimize.minimize, Anteile in [0.05, 0.30] mit Summe 1): 9.755769 Prozentpunkte mit A02, A03, A04, A08, A09. Identisch mit dem früher notierten Wert 0.097558 – das ist derselbe Optimalpunkt als Anteil statt in Prozentpunkten. Die Aufgabe nennt die Einheit seit 2026-09-17 ausdrücklich, weil beide Lesarten zulässig waren."
|
||||
}
|
||||
44
benchmark/cases/hard_portfolio_kardinalitaet/task.txt
Normal file
44
benchmark/cases/hard_portfolio_kardinalitaet/task.txt
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
Problem: Komplexes Portfolio-Management:
|
||||
|
||||
Ein Investor möchte sein Geld auf mindestens 5 und maximal 10 verschiedene Aktien aufteilen.
|
||||
|
||||
Er möchte den erwarteten Nutzen maximieren und gleichzeitig das Risiko (die Varianz) minimieren.
|
||||
|
||||
Maximieren Sie den Nutzen (Rendite abzüglich des Risikos und der Fixkosten)!
|
||||
Alle Angaben der Tabelle sind Prozentpunkte des Kapitals; geben Sie den Nutzen in derselben Einheit an.
|
||||
|
||||
Unter folgenden Nebenbedingungen:
|
||||
|
||||
- 1. Kardinalitätsbedingungen: Er darf maximal 10 verschiedene Aktien auswählen (um Transaktionskosten zu sparen).
|
||||
- 2. Er muss mindestens in 5 verschiedene Aktien investieren, um das Risiko zu verteilen.
|
||||
- 3. Mindest- und Höchstgrenzen: Wenn er in eine Aktie investiert, dann müssen es mindestens 5 % und maximal 30 % des Gesamtkapitals sein.
|
||||
- 4. Transaktionskosten: Beim Kauf fallen feste Grundgebühren (Transaktionskosten) an.
|
||||
- 5. Das gesamte Geld muss investiert werden.
|
||||
|
||||
|
||||
Wir setzen folgende Rahmenbedingungen fest:
|
||||
|
||||
Maximale Anzahl Aktien im Portfolio: 10
|
||||
Mindestgewichtung pro gewählte Aktie: 0.05 (Fünf Prozent)
|
||||
Maximalgewichtung pro gewählte Aktie: 0.30 (Dreißig Prozent)
|
||||
Risikoaversations-Faktor: 1.0
|
||||
|
||||
|
||||
Hier sind die erwarteten Renditen und die fixen Transaktionskosten und die eigene Varianz (Risiko) für die 10 Aktien:
|
||||
|
||||
Aktie | Erwartete Rendite | Transaktionskosten | Varianz (Risiko)
|
||||
--------|---------------|---------------|--------------------------------
|
||||
A01 | 6,9 % | 0,68 % | 2,04 %
|
||||
A02 | 14,4 % | 0,74 % | 1,63 %
|
||||
A03 | 11,5 % | 0,39 % | 3,62 %
|
||||
A04 | 9,8 % | 0,27 % | 3,01 %
|
||||
A05 | 4,0 % | 0,34 % | 3,30 %
|
||||
A06 | 4,0 % | 0,46 % | 3,33 %
|
||||
A07 | 2,8 % | 0,69 % | 3,24 %
|
||||
A08 | 13,3 % | 0,72 % | 1,97 %
|
||||
A09 | 9,8 % | 0,20 % | 3,26 %
|
||||
A10 | 11,2 % | 0,51 % | 2,52 %
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"target_stack": "CVXPY",
|
||||
"sense": "minimize",
|
||||
"objective_value": 0.1172905494,
|
||||
"tolerance": 1e-06,
|
||||
"source": "cvxpy und scipy SLSQP übereinstimmend: Volatilität 0.11729055 (Varianz 0.01375707 wäre falsch); Klasse QP oder SOCP beide zulässig | 2026-09-17 unabhängig mit cvxpy nachgerechnet: 0.1172905494 bei Anteilen [0.231939, 0.263325, 0.289207, 0.215529]. Die Aufgabe nennt die Einheit jetzt ausdrücklich, weil Anteil und Prozentpunkte beide zulässige Lesarten waren (Faktor 100)."
|
||||
}
|
||||
18
benchmark/cases/hard_portfolio_volatilitaet/task.txt
Normal file
18
benchmark/cases/hard_portfolio_volatilitaet/task.txt
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
Eine Stiftung legt ihr gesamtes Kapital in vier Fonds A, B, C und D an. Leerverkäufe sind nicht erlaubt.
|
||||
Erwartete Jahresrenditen: A 7 %, B 10 %, C 4 %, D 12 %.
|
||||
|
||||
Kovarianzmatrix der Jahresrenditen (Reihenfolge A, B, C, D):
|
||||
|
||||
A B C D
|
||||
A 0.0225 0.0090 0.0012 0.0150
|
||||
B 0.0090 0.0400 0.0032 0.0250
|
||||
C 0.0012 0.0032 0.0064 0.0020
|
||||
D 0.0150 0.0250 0.0020 0.0625
|
||||
|
||||
Anlagerichtlinien:
|
||||
- Kein Fonds darf mehr als 40 % des Kapitals erhalten.
|
||||
- Die Fonds A und B stammen aus derselben Branche und dürfen zusammen höchstens 50 % ausmachen.
|
||||
- Die erwartete Portfoliorendite muss mindestens 8 % betragen.
|
||||
|
||||
Bestimme die Aufteilung mit der geringsten Volatilität, also der kleinsten Standardabweichung der Portfoliorendite, und gib diese Volatilität an.
|
||||
Geben Sie die Volatilität als Anteil an (z. B. 0,1234), nicht in Prozent.
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
{"problem_class": "Mixed-Integer Linear Programming (MILP)", "target_stack": "HiGHS", "sense": "maximize", "objective_value": 3000, "tolerance": 1e-6,
|
||||
"source": "Brute Force über alle ganzzahligen (P1, P2) mit optimalem P3; Optimum P1=80, P2=0, P3=50"}
|
||||
11
benchmark/cases/hard_produktion_ruestkosten/task.txt
Normal file
11
benchmark/cases/hard_produktion_ruestkosten/task.txt
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
Ein Maschinenbaubetrieb plant die Produktion von drei Bauteilen P1, P2 und P3 für den kommenden Monat. Gefertigt werden nur ganze Stück.
|
||||
|
||||
Bauteil | Deckungsbeitrag [€/Stück] | Maschine M1 [h/Stück] | Maschine M2 [h/Stück] | Rüstkosten [€] | Mindestlosgröße [Stück] | maximaler Absatz [Stück]
|
||||
--------|---------------------------|-----------------------|-----------------------|----------------|-------------------------|-------------------------
|
||||
P1 | 40 | 2 | 1 | 1200 | 30 | 80
|
||||
P2 | 55 | 3 | 2 | 2000 | 20 | 50
|
||||
P3 | 30 | 1 | 2 | 500 | 40 | 100
|
||||
|
||||
Maschine M1 steht im Monat 240 Stunden zur Verfügung, Maschine M2 180 Stunden.
|
||||
Die Rüstkosten fallen einmalig an, wenn ein Bauteil im Monat überhaupt gefertigt wird. Wird ein Bauteil gefertigt, muss mindestens die Mindestlosgröße produziert werden; mehr als der maximale Absatz wird nicht produziert.
|
||||
Welches Produktionsprogramm maximiert den Gesamtdeckungsbeitrag nach Abzug der Rüstkosten, und wie hoch ist dieser?
|
||||
2
benchmark/cases/hard_schichtplan_woche/expected.json
Normal file
2
benchmark/cases/hard_schichtplan_woche/expected.json
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
{"problem_class": "Constraint Programming (CP)", "target_stack": "Google OR-Tools (CP-SAT)", "sense": "minimize", "objective_value": 475, "tolerance": 1e-6,
|
||||
"source": "Brute Force über alle 3^12 Pläne (236 zulässig)"}
|
||||
20
benchmark/cases/hard_schichtplan_woche/task.txt
Normal file
20
benchmark/cases/hard_schichtplan_woche/task.txt
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
Eine Apotheke plant die Besetzung für Montag, Dienstag und Mittwoch. Jeden Tag gibt es eine Frühschicht und eine Spätschicht. Vier Mitarbeitende stehen zur Verfügung: Anna, Ben, Clara und David.
|
||||
|
||||
Regeln:
|
||||
- Jede Frühschicht ist mit mindestens einer und höchstens zwei Personen besetzt. Jede Spätschicht ist mit mindestens einer Person besetzt.
|
||||
- Niemand arbeitet an einem Tag mehr als eine Schicht.
|
||||
- Über die drei Tage arbeitet jede Person mindestens eine und höchstens zwei Schichten.
|
||||
- Wer an einem Tag Spätschicht hat, darf am folgenden Tag nicht Frühschicht haben.
|
||||
- Anna und Ben dürfen nie in derselben Schicht arbeiten.
|
||||
- Clara arbeitet nur an Tagen, an denen auch David arbeitet (egal in welcher Schicht).
|
||||
- David ist am Mittwoch nicht verfügbar.
|
||||
|
||||
Kosten je eingesetzter Schicht [€]:
|
||||
Person | Frühschicht | Spätschicht
|
||||
-------|-------------|------------
|
||||
Anna | 80 | 90
|
||||
Ben | 70 | 95
|
||||
Clara | 85 | 75
|
||||
David | 90 | 80
|
||||
|
||||
Erstelle einen Plan mit minimalen Gesamtkosten.
|
||||
2
benchmark/cases/hard_transport_lagerwahl/expected.json
Normal file
2
benchmark/cases/hard_transport_lagerwahl/expected.json
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
{"problem_class": "Mixed-Integer Linear Programming (MILP)", "target_stack": "HiGHS", "sense": "minimize", "objective_value": 9900, "tolerance": 1e-6,
|
||||
"source": "Enumeration der Lagerkombinationen + scipy linprog: nur L1 = 9900, nur L2 unzulässig, beide = 10750"}
|
||||
18
benchmark/cases/hard_transport_lagerwahl/task.txt
Normal file
18
benchmark/cases/hard_transport_lagerwahl/task.txt
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
Ein Händler beliefert drei Großkunden aus zwei Werken. Jede Lieferung muss über eines von zwei möglichen Zwischenlagern laufen; Direktlieferungen vom Werk zum Kunden sind nicht möglich. Die Mengen sind beliebig teilbar.
|
||||
|
||||
Werk W1 kann höchstens 500 Einheiten liefern, Werk W2 höchstens 400 Einheiten. Mit Werk W2 besteht ein Mindestabnahmevertrag: Aus W2 müssen mindestens 150 Einheiten abgenommen werden.
|
||||
Kunde K1 benötigt genau 250 Einheiten, K2 genau 300 Einheiten und K3 genau 200 Einheiten.
|
||||
|
||||
Die Lager müssen erst angemietet werden. Lager L1 kostet 3000 € Miete und kann höchstens 800 Einheiten umschlagen, Lager L2 kostet 2500 € Miete und kann höchstens 700 Einheiten umschlagen. Nicht angemietete Lager können nicht genutzt werden. Ein Lager gibt genau die Menge weiter, die es erhält.
|
||||
|
||||
Transportkosten Werk → Lager [€/Einheit]:
|
||||
| L1 | L2
|
||||
W1 | 4 | 6
|
||||
W2 | 5 | 3
|
||||
|
||||
Transportkosten Lager → Kunde [€/Einheit]:
|
||||
| K1 | K2 | K3
|
||||
L1 | 3 | 5 | 7
|
||||
L2 | 6 | 4 | 3
|
||||
|
||||
Welche Lager sollen angemietet werden und wie sollen die Warenströme verlaufen, damit die Summe aus Miet- und Transportkosten minimal ist?
|
||||
2
benchmark/cases/hard_unloesbar_besetzung/expected.json
Normal file
2
benchmark/cases/hard_unloesbar_besetzung/expected.json
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
{"sense": "minimize", "status": "infeasible",
|
||||
"source": "4 Projekte mit je genau einer Leitung, aber nur 3 Beraterinnen mit je höchstens einem Projekt -> unzulässig; das Modell darf die Aufgabe nicht umdeuten"}
|
||||
11
benchmark/cases/hard_unloesbar_besetzung/task.txt
Normal file
11
benchmark/cases/hard_unloesbar_besetzung/task.txt
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
Eine Unternehmensberatung muss vier neue Kundenprojekte (Projekt 1 bis 4) besetzen. Zur Verfügung stehen drei Beraterinnen: Maria, Nina und Olga.
|
||||
Jedes der vier Projekte muss von genau einer Beraterin geleitet werden; kein Projekt darf unbesetzt bleiben. Wegen der hohen Auslastung darf jede Beraterin höchstens ein Projekt übernehmen.
|
||||
|
||||
Kosten der Projektleitung [Tsd. €]:
|
||||
Beraterin | Projekt 1 | Projekt 2 | Projekt 3 | Projekt 4
|
||||
----------|-----------|-----------|-----------|----------
|
||||
Maria | 12 | 15 | 9 | 14
|
||||
Nina | 11 | 13 | 10 | 16
|
||||
Olga | 14 | 12 | 11 | 13
|
||||
|
||||
Bestimme die kostenminimale Besetzung der Projekte.
|
||||
9
benchmark/cases/implikation_falle/expected.json
Normal file
9
benchmark/cases/implikation_falle/expected.json
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"problem_class": "Mixed-Integer Linear Programming (MILP)",
|
||||
"target_stack": "HiGHS",
|
||||
"sense": "maximize",
|
||||
"objective_value": 85,
|
||||
"tolerance": 1e-6,
|
||||
"min_sub_questions": 1,
|
||||
"source": "Falle im Modell: die Bedingung ist eine Implikation (Maschine -> Zubehör, also x_Maschine <= x_Zubehör), keine Äquivalenz. Beide Lesarten unabhängig durch Enumeration aller 16 Teilmengen verifiziert. RICHTIG (Implikation): 85 mit Zubehör + Prüfgerät + Werkbank, Kosten 95 - das Zubehör darf ohne die Maschine gekauft werden. FALSCH (Äquivalenz x_Maschine = x_Zubehör, verbietet Zubehör allein): 70 mit Maschine + Zubehör, Kosten 90. Ein gemeldeter Zielwert von 70 bedeutet genau diesen Modellierungsfehler; 70 ist zugleich die zweitbeste korrekte Auswahl, die Diagnose ist also eindeutig. Der Prüf-Prompt hat die Regel ('Wenn A, dann B ist eine Implikation, keine Äquivalenz'), bis zu diesem Fall prüfte sie kein Benchmarkfall."
|
||||
}
|
||||
11
benchmark/cases/implikation_falle/task.txt
Normal file
11
benchmark/cases/implikation_falle/task.txt
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
Eine Werkstatt hat ein Investitionsbudget von 100 Tausend Euro und kann aus vier Posten auswählen. Jeder Posten wird entweder ganz gekauft oder nicht gekauft; Teilkäufe sind nicht möglich.
|
||||
|
||||
Posten | Nutzwert | Kosten in Tausend Euro
|
||||
Maschine | 30 | 50
|
||||
Zubehör | 40 | 40
|
||||
Prüfgerät | 25 | 30
|
||||
Werkbank | 20 | 25
|
||||
|
||||
Für die Maschine gilt eine technische Bedingung: Wird die Maschine gekauft, dann muss auch das Zubehör gekauft werden, weil die Maschine ohne das Zubehör nicht betrieben werden kann.
|
||||
|
||||
Welche Posten soll die Werkstatt kaufen, damit die Summe der Nutzwerte maximal wird, und welchen Gesamtnutzwert erreicht sie dabei?
|
||||
9
benchmark/cases/losgroessen_mehrperiodig/expected.json
Normal file
9
benchmark/cases/losgroessen_mehrperiodig/expected.json
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"problem_class": "Mixed-Integer Linear Programming (MILP)",
|
||||
"target_stack": "HiGHS",
|
||||
"sense": "minimize",
|
||||
"objective_value": 320,
|
||||
"tolerance": 1e-6,
|
||||
"min_sub_questions": 1,
|
||||
"source": "Unabhängig durch Enumeration aller 8 zulässigen Rüstmuster verifiziert (Periode 1 muss produzieren, Startbestand 0): Optimum 320 Euro mit Rüstmuster (1,1,0,1) und Mengen [20, 60, 0, 40] = 3 Rüstvorgänge (300) + 10 Stück eine Periode auf Lager (20). Eindeutig, der nächstbeste Plan kostet 340."
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue