Problem and root cause
The repository confuses successful configuration evaluation with a feasible witness, and backend completion with a mathematical conclusion about the source problem.
Problem::evaluate() can return Ok(Or(false)), Ok(Min(None)), Ok(Max(None)), or an infeasible Extremum. These are evaluable configurations, not witnesses. Yet validate_target_solution() in src/rules/traits.rs only returns Ok(target.evaluate(solution)?). Approximately 266 extraction sites use this shared boundary.
In src/solvers/resolver.rs, customized and ILP dispatch call evaluate_dyn() and construct SolveOutcome::Optimal. The current two-outcome API cannot express a feasible solution without established source optimality, or a numerical backend conclusion that does not establish source infeasibility.
The fix belongs in shared extraction and solve-result contracts, not individual model guards.
Concrete failure
For MaximumSetPacking<i64> -> ILP<bool> with one set, target configuration [2] evaluates to an infeasible ILP aggregate. The shared validator accepts it, and the extractor decodes 2 == 1 as false. The resulting empty source packing is feasible, so source-only validation cannot detect the invalid target input.
A separate numerical example is documented in #1145: individually representable integer coefficients can produce two distinct source objectives that collapse in floating-point arithmetic. Re-evaluating one feasible returned assignment cannot prove global optimality. See #1146 for consistent exact CVP evaluation and #1143 for search-space representation.
Required refactor
- Make
validate_target_solution() reject infeasible evaluated values using the existing SolutionAggregate::contributes_to_solution(&value, &value) semantics. Propagate the necessary bounds through shared callers. Preserve malformed/evaluation failures separately from infeasible-witness errors.
- Use existing
evaluate_witness_dyn() at the dynamic solve boundary. Validate the final source witness after extraction, before producing a successful outcome. Cover typed public solve entry points as well; fixing only the CLI is insufficient.
- Replace the two-state outcome contract with:
Optimal { solution, evaluation }: source optimality established under the documented exact algorithm contract, with a validated witness.
Feasible { solution, evaluation }: source witness validated; exact source optimality not established.
Infeasible: source infeasibility established under the exact algorithm contract.
Unknown: no established source conclusion.
Operational/construction/conversion/backend failures remain typed errors.
- Exact brute-force/customized algorithms retain their established conclusions when their contracts hold. A floating-point ILP backend's successful optimization generally yields
Feasible after source validation; a numerical infeasibility report alone yields Unknown, preserving the backend reason in execution diagnostics. A validated satisfying witness is sufficient to settle a decision problem positively.
- Update CLI, MCP, typed consumers, and decision-search consumers so they cannot turn
Feasible into exact optimality or Unknown into false/infeasible. A failed returned-witness validation is an explicit error, never silently discarded.
Extraction accepts feasible non-optimal target witnesses where allowed by the rule's mathematical mapping; validation must not run a second optimization.
Design references
Reuse existing aggregate/witness facilities. Do not add a solver abstraction framework, certificate infrastructure, automatic fallback, or difficulty-based rejection.
Acceptance tests
- The set-packing counterexample fails with an extraction error through direct, dynamic-chain, and CLI extraction.
- A feasible non-optimal witness remains accepted where the reduction permits it.
- Malformed input, infeasible witness, and unresolved solve remain distinguishable.
- No public solve path reports an infeasible returned witness as success.
- The integer objective rounding counterexample is never reported as exact
Optimal.
- Backend numerical infeasibility is not consumed as an exact negative decision.
- Small exact solver results retain optimal/infeasible behavior.
Run focused tests and make check, including ILP-feature tests. Keep regression names semantic, without issue numbers.
Problem and root cause
The repository confuses successful configuration evaluation with a feasible witness, and backend completion with a mathematical conclusion about the source problem.
Problem::evaluate()can returnOk(Or(false)),Ok(Min(None)),Ok(Max(None)), or an infeasibleExtremum. These are evaluable configurations, not witnesses. Yetvalidate_target_solution()insrc/rules/traits.rsonly returnsOk(target.evaluate(solution)?). Approximately 266 extraction sites use this shared boundary.In
src/solvers/resolver.rs, customized and ILP dispatch callevaluate_dyn()and constructSolveOutcome::Optimal. The current two-outcome API cannot express a feasible solution without established source optimality, or a numerical backend conclusion that does not establish source infeasibility.The fix belongs in shared extraction and solve-result contracts, not individual model guards.
Concrete failure
For
MaximumSetPacking<i64> -> ILP<bool>with one set, target configuration[2]evaluates to an infeasible ILP aggregate. The shared validator accepts it, and the extractor decodes2 == 1as false. The resulting empty source packing is feasible, so source-only validation cannot detect the invalid target input.A separate numerical example is documented in #1145: individually representable integer coefficients can produce two distinct source objectives that collapse in floating-point arithmetic. Re-evaluating one feasible returned assignment cannot prove global optimality. See #1146 for consistent exact CVP evaluation and #1143 for search-space representation.
Required refactor
validate_target_solution()reject infeasible evaluated values using the existingSolutionAggregate::contributes_to_solution(&value, &value)semantics. Propagate the necessary bounds through shared callers. Preserve malformed/evaluation failures separately from infeasible-witness errors.evaluate_witness_dyn()at the dynamic solve boundary. Validate the final source witness after extraction, before producing a successful outcome. Cover typed public solve entry points as well; fixing only the CLI is insufficient.Optimal { solution, evaluation }: source optimality established under the documented exact algorithm contract, with a validated witness.Feasible { solution, evaluation }: source witness validated; exact source optimality not established.Infeasible: source infeasibility established under the exact algorithm contract.Unknown: no established source conclusion.Operational/construction/conversion/backend failures remain typed errors.
Feasibleafter source validation; a numerical infeasibility report alone yieldsUnknown, preserving the backend reason in execution diagnostics. A validated satisfying witness is sufficient to settle a decision problem positively.Feasibleinto exact optimality orUnknowninto false/infeasible. A failed returned-witness validation is an explicit error, never silently discarded.Extraction accepts feasible non-optimal target witnesses where allowed by the rule's mathematical mapping; validation must not run a second optimization.
Design references
Reuse existing aggregate/witness facilities. Do not add a solver abstraction framework, certificate infrastructure, automatic fallback, or difficulty-based rejection.
Acceptance tests
Optimal.Run focused tests and
make check, including ILP-feature tests. Keep regression names semantic, without issue numbers.