mirror of
https://github.com/Z3Prover/z3
synced 2026-07-27 09:22:41 +00:00
opt: preserve strict supremum/infimum optima with infinitesimal component
Maximizing a real objective under a strict inequality (e.g. `maximize r`
subject to `r < 1`) must yield the strict supremum `1 - epsilon`, but z3
was reporting a plain feasible model value (`0`).
Regression from commit fdc32d0e6 ("Fix inconsistent optimization result
with unvalidated LP bound", #10028), which stopped committing the LP
optimization hint to m_objective_values up front and instead defers the
commit until check_bound() validates it. That fix targets plain-rational
over-estimates produced by shared uninterpreted symbols (e.g. large
`distinct` encodings), which have a zero infinitesimal.
For a strict real supremum/infimum the hint has a non-zero infinitesimal
(`1 - epsilon`). check_bound() can never validate it because
opt_solver::mk_ge drops the negative infinitesimal, turning the bound
`r >= 1 - epsilon` into the unsatisfiable `r >= 1`. Validation therefore
fails, maximize_objective() returns false, and m_objective_values is left
holding the strictly smaller current model value, which callers such as
optsmt::geometric_lex report as the optimum.
Restore the pre-#10028 eager commit, scoped to finite values with a
non-zero infinitesimal. Such values are strict optima that no concrete
model can attain and that check_bound() cannot validate, so the arithmetic
hint is authoritative. Plain-rational (zero-infinitesimal) values,
including all integer objectives and the #10028 shared-symbol case, are
untouched and continue through the deferred-commit validation path.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
parent
557a0cadab
commit
d1a85c4e81
1 changed files with 18 additions and 0 deletions
|
|
@ -342,6 +342,24 @@ namespace opt {
|
|||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// A finite hint with a non-zero infinitesimal is a strict
|
||||
// supremum/infimum (e.g. maximizing r subject to r < 1 yields
|
||||
// 1 - epsilon). No concrete model can attain such a value, and
|
||||
// check_bound() below cannot validate it either: opt_solver::mk_ge
|
||||
// drops the negative infinitesimal, turning the bound r >= 1 - epsilon
|
||||
// into the unsatisfiable r >= 1. Commit it eagerly here so that it is
|
||||
// neither overwritten by the strictly smaller current model value in
|
||||
// update_objective() nor lost when validation fails and this routine
|
||||
// returns false (callers such as optsmt::geometric_lex then report
|
||||
// m_objective_values as the optimum). This restores the pre-#10028
|
||||
// behavior for strict optima while leaving the plain-rational
|
||||
// (zero-infinitesimal) over-estimates that #10028 fixed to the
|
||||
// deferred-commit logic below.
|
||||
//
|
||||
if (val.is_finite() && !val.get_infinitesimal().is_zero() && val > m_objective_values[i])
|
||||
m_objective_values[i] = val;
|
||||
|
||||
//
|
||||
// retrieve value of objective from current model and update
|
||||
// current optimal.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue