fix: Fachwort Fluss nicht mehr aus eigenen Prompts; englische Zahlen und Teilfragen

- Routing-Prompt verlangt bei Dijkstra Restriktionsnamen in der Sprache der Aufgabe
  statt Flusserhaltung; Solver-Prompt ohne Fachwort (löste Korrekturrunden aus)
- JARGON_EVERYDAY: beeinflusst/Einfluss/Überfluss zählen weder als Vorkommen noch als
  Erklärung eines Fachbegriffs
- normalize_number liest eindeutige englische Zahlen (1,234.56; 12,345,678) richtig
- QUESTION_PATTERN erkennt Part/Question/Task N

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Dieter Schlüter 2026-09-17 16:38:45 +02:00
commit 0582737b22

View file

@ -30,7 +30,7 @@ API je target_stack:
Startlösung (Warmstart): `sol = model.createSol(); model.setSolVal(sol, var, wert)` für jede Variable, dann `model.addSol(sol)` vor `model.optimize()`.
- NetworkX (Dijkstra): `import networkx as nx`; `G = nx.DiGraph()`; Bögen mit `G.add_edge(i, j, weight=c)`; `laenge, pfad = nx.single_source_dijkstra(G, quelle, ziel, weight="weight")` liefert Weglänge und Knotenfolge; alle endgültigen Marken in der Reihenfolge ihrer Vergabe: `marken = nx.single_source_dijkstra_path_length(G, quelle, weight="weight")` (das Wörterbuch ist in genau dieser Reihenfolge gefüllt). Ist das Ziel nicht erreichbar, wirft `single_source_dijkstra` `nx.NetworkXNoPath` – dann Status "infeasible" melden.
WICHTIG: Bei negativen Bogengewichten wirft networkx KEINEN Fehler, liefert aber ein falsches Ergebnis (geprüft: 3 statt 2). Prüfe die Gewichte im Programm und melde Status "error" mit einem Hinweis, falls eines negativ ist.
Melde den Graphen im Argument graph (siehe unten) – ohne ihn kann der Report die verlangte Zeichnung nicht erzeugen. Die Restriktionen der Spezifikation (Flusserhaltung) sind trotzdem in constraints auszuweisen, ausgewertet am gefundenen Weg.
Melde den Graphen im Argument graph (siehe unten) – ohne ihn kann der Report die verlangte Zeichnung nicht erzeugen. Die Restriktionen der Spezifikation (Start, Ende und Weiterführung an jedem Zwischenknoten) sind trotzdem in constraints auszuweisen, ausgewertet am gefundenen Weg.
- Ipopt (cyipopt): `from cyipopt import minimize_ipopt`; `res = minimize_ipopt(zielfunktion, x0=startwerte, bounds=[(lo, hi), ...], constraints=[{"type": "ineq"|"eq", "fun": g}], options={"print_level": 0, "sb": "yes"})`; minimiert immer (bei Maximierung Vorzeichen drehen und Zielwert zurückrechnen); `g(x) >= 0` bei "ineq", `g(x) == 0` bei "eq"; Erfolg `res.success`, Werte `res.x`, Zielwert `res.fun`.
Ipopt findet nur LOKALE Optima: Starte von mindestens 5 verschiedenen, zulässigen Startpunkten und behalte das beste Ergebnis. Melde status "optimal" nur, wenn das Problem nachweislich konvex ist (dann ist lokal = global), sonst "feasible" und erwähne in note bzw. headline, dass es sich um die beste gefundene lokale Lösung handelt. Findet kein Startpunkt eine Lösung, melde "infeasible" bzw. "error".
Berichte die Streuung über die Startpunkte im Argument multistart (siehe unten) – sie ist der einzige Hinweis darauf, ob das Optimum stabil ist. Verwende feste Startpunkte oder einen festen Zufallsstartwert (z. B. `np.random.default_rng(0)`), damit derselbe Lauf dasselbe Ergebnis liefert.