mirror of
https://github.com/Z3Prover/z3
synced 2026-07-15 03:25:43 +00:00
## Summary Reverts #10052, whose eager-commit of infinitesimal LP hints is **unsound** for shared-symbol objectives. #10052 added, in `opt_solver::maximize_objective`: ```cpp if (val.is_finite() && !val.get_infinitesimal().is_zero() && val > m_objective_values[i]) m_objective_values[i] = val; ``` on the premise that *"a non-zero infinitesimal ⇒ an exact, unattainable strict optimum, so the LP hint is authoritative."* That holds for a **pure LP**, but is **false when the objective is a shared symbol** with another theory (e.g. the auxiliary uninterpreted function used to encode a `distinct` with > 32 arguments). There the LP relaxation only yields a *hint* that can be a strict **over-estimate**, and #10052 commits it without validation — exactly the class of bound that #10028's `check_bound` exists to reject. ## Counterexample A 6-mark Golomb ruler over integers `x0..x5`, with the `distinct` padded to > 32 arguments so `x5` becomes a shared symbol; objective is a real `obj` with `obj > x5` (full file attached to #5720): - Ground truth: `minimize x5` (integer) ⇒ **17**; since `obj > x5`, the true optimum is **`17 + ε`**. - With #10052, z3 reports **`(obj (+ 5.0 epsilon))`** — wrong and **infeasible** (`obj < 6` is `unsat`; the returned model itself has `x5 = 35, obj = 49.5`). | benchmark | with #10052 (master) | after this revert | | --- | --- | --- | | Golomb `bug.smt2` (shared symbol) | `(obj (+ 5.0 epsilon))` ❌ infeasible | `(obj 18)` ✅ consistent | | #5720 (`max r < 1`) | `1 - epsilon` ✅ | `0` ❌ (regression returns) | ## Tradeoff / follow-up This revert restores soundness on the shared-symbol case but **reintroduces the #5720 regression** (`max r<1` ⇒ `0`), which is why **#5720 has been reopened**. A correct fix should preserve the strict single-objective supremum **without** trusting an unvalidated shared-symbol hint — e.g. gate the eager commit on `!has_shared` (pure LP only), or validate the rational part of the hint while keeping the infinitesimal. The same blind spot affects the alternative `check_bound` guard proposed in #10051. Re: #5720 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|---|---|---|
| .. | ||
| ackermannization | ||
| api | ||
| ast | ||
| cmd_context | ||
| math | ||
| model | ||
| muz | ||
| nlsat | ||
| opt | ||
| params | ||
| parsers | ||
| qe | ||
| sat | ||
| shell | ||
| smt | ||
| solver | ||
| tactic | ||
| test | ||
| util | ||
| CMakeLists.txt | ||