feat: Zielwert-Zerlegung als Reparaturgrund, SOLVER_TIMEOUT, Summenzeilen-Fehlalarm behoben

- check_objective_decomposition: bei LP/MILP/CP muss eine objective_column den Zielwert
  belegen, eine abweichende Beitragsspalte ist überall ein Befund -> Solver-Reparatur,
  bleibt es: Warnung. 90 von 90 linearen Läufen seit 17.09. hätten bestanden.
- Summenzeilen: „Gesamt…“/„Nutzen…“ nur noch in der letzten Zeile, einzelne Zeile nie,
  Zwischensummen nicht gegen die Gesamtsumme. Vorher 15 Rucksack-Läufe mit falschem
  „Summe (0) weicht vom Zielwert (51) ab“; von 17 Abweichungen bleibt 1 echte.
- SOLVER_TIMEOUT (Default 60) für alle Programmläufe und als {ZEITLIMIT} im Solver-Prompt
- Benchmark: dirty zählt nur versionierte Dateien; SOLVER_TIMEOUT in der Konfiguration

Ändert die Prompt-Kennung (Solver-Prompt.txt).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Dieter Schlüter 2026-09-18 13:24:46 +02:00
commit 6ecfdf6ae0

View file

@ -78,7 +78,7 @@ Ergebnisausgabe:
- sensitivity: Wirkung der bindenden Restriktionen, durch NEULÖSEN ermittelt (nicht aus Solver-Attributen ablesen). Für höchstens 8 bindende Restriktionen (linke Seite erreicht die Grenze genau), am besten die inhaltlich wichtigsten:
{"name": "<wie in constraints>", "delta": <Verschiebung > 0>, "objective_plus": <Zielwert mit rhs+delta oder null>, "objective_minus": <Zielwert mit rhs-delta oder null>, "unit": "€ je Einheit"}
- delta klein wählen (etwa 1 % der rechten Seite, mindestens eine sinnvolle Einheit), das Modell je Richtung einmal neu lösen und den Zielwert eintragen; bei unlösbar null.
- Nur ausführen, wenn das Neulösen schnell geht (Gesamtlaufzeit unter 60 s), sonst leere Liste.
- Nur ausführen, wenn das Neulösen schnell geht (Gesamtlaufzeit unter {ZEITLIMIT} s), sonst leere Liste.
- relaxation_bound: bei ganzzahligen/binären Variablen der Zielwert der stetigen Relaxation (alle Ganzzahligkeitsforderungen aufgehoben), sonst null. Zeigt, was die Ganzzahligkeit kostet.
- answers: Die Rückprojektion auf die gestellte Aufgabe – genau ein Eintrag je Teilfrage aus der Liste im Auftrag, mit deren question_id. Das gilt auch dann, wenn es nur EINE Teilfrage gibt: answers bleibt nie leer.
[{"question_id": "a", "text": "…"}, {"question_id": "b", "text": "…"}]
@ -94,7 +94,7 @@ Ergebnisausgabe:
- data_override enthält genau die Einträge von DATA, die sich ändern. Das Programm rechnet jedes Szenario selbst und trägt seinen objective_value ein.
- Die Pipeline führt dein Programm anschließend mit jedem data_override ERNEUT aus und vergleicht – abweichende Werte fallen auf. Kein LLM ist daran beteiligt. [→ verify_scenarios]
- Damit das funktioniert, muss das Programm ausschließlich aus DATA lesen; höchstens fünf Szenarien werden nachgerechnet.
- Jedes Szenario braucht einen objective_value – null nur, wenn es bewiesen unlösbar ist. Unterscheiden sich Szenarien nur in Zielgewichten, ist die Lösung eines Szenarios für die anderen zulässig: übergib sie als Startlösung, dann endet keines im Zeitlimit ohne Ergebnis. Zeitlimits so wählen, dass alle Läufe zusammen unter 60 s bleiben. [→ check_scenarios_solved]
- Jedes Szenario braucht einen objective_value – null nur, wenn es bewiesen unlösbar ist. Unterscheiden sich Szenarien nur in Zielgewichten, ist die Lösung eines Szenarios für die anderen zulässig: übergib sie als Startlösung, dann endet keines im Zeitlimit ohne Ergebnis. Zeitlimits so wählen, dass alle Läufe zusammen unter {ZEITLIMIT} s bleiben. [→ check_scenarios_solved]
- graph: NUR bei Graphenproblemen (Stack NetworkX), sonst null. Grundlage für die Zeichnung im Report:
{"nodes": ["0", "1", "2", "3"],
"arcs": [{"source": "0", "target": "1", "weight": 8}, ...],
@ -120,7 +120,7 @@ Ergebnisausgabe:
- Entscheidungswerte als formatierte Texte, Beiträge als Zahlen; Dezimalkomma im Text ist erlaubt.
- unit: Einheit der objective_column für die Diagrammbeschriftung (z. B. " €", " %"), sonst weglassen.
- note: ein Satz, wie die Tabelle zu lesen ist.
Erzeuge nach Möglichkeit diese drei Tabellen (in dieser Reihenfolge):
Erzeuge nach Möglichkeit diese drei Tabellen (in dieser Reihenfolge). Bei LP, MILP und CP ist die Zielwert-Zerlegung Pflicht (die Zielfunktion ist dort immer eine Summe), und jede objective_column muss sich zum Zielwert summieren – sonst wird das Programm zur Reparatur zurückgegeben. [→ check_objective_decomposition]
1. Die Objekttabelle wie oben beschrieben.
2. "Zielwert-Zerlegung": Zeilen für die Bestandteile der Zielfunktion (z. B. "Erwartete Rendite", "Risiko (λ·Varianz)", "Transaktionskosten") mit Spalten ["Bestandteil", "Wert", "Einheit"], Vorzeichen wie in der Zielfunktion (Abzüge negativ), objective_column "Wert", danach die Summenzeile "Zielwert". Alle Bestandteile müssen dieselbe Einheit haben; steht dort Unterschiedliches (z. B. "€" neben "dimensionslos"), ist das Modell fehlerhaft.
3. "Bindende Restriktionen": welche Grenzen die Lösung ausreizt, mit Spalten ["Restriktion", "Wert", "Grenze", "bindend"] und Werten aus der Lösung (z. B. "Höchstgewicht A02" | "30,00 %" | "30,00 %" | "ja"). Nur Tatsachen aus der Lösung, keine Bewertung; ohne objective_column. Die note erklärt „bindend" in Alltagssprache („die Lösung schöpft diese Grenze voll aus") – ohne Fachbegriffe. [→ check_text_quality]