3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2026-06-19 23:26:30 +00:00

fix edge case in algebraic number comparison (#9498)

So far, `algebraic_numbers compare_core ` handles an edge case
incorrectly:
- If the two compared numbers (`a`, `b`) are different,
- the intervals still overlap after refinements, and
- both a and b are a root of the second polynomial (`cell_b->m_p`), e.g.
they are the first and second root

then the method would return `sign_zero` (i.e. "equal"). This behavior
can be replicated with the provided test case (before the fix). This
requires `algebraic.factor=false`, though i first encountered it during
solver runs on QF_NRA instances with the default
`algebraic.factor=true`, which apparently means that the polynomials for
anums are still not always factored.

The fix is to compare the interval bounds of b to a and vice versa. Then
the Sturm-Tarski check is only run if `a` and `b` both lie in the
intersection of the intervals, because only then is it guaranteed to be
correct.
This commit is contained in:
ValentinPromies 2026-05-27 14:01:47 +02:00 committed by GitHub
parent 316d249b3f
commit f124cacf1e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 57 additions and 0 deletions

View file

@ -2028,6 +2028,20 @@ namespace algebraic_numbers {
}
IF_VERBOSE(9, verbose_stream() << "sturm 1\n");
// Check whether a can be separated from b's interval and vice versa
// this recognizes the case where the intervals overlap,
// but the anums do not lie in the intersection of the intervals.
mpq l_a, u_a, l_b, u_b;
to_mpq(qm(), la, l_a);
to_mpq(qm(), ua, u_a);
to_mpq(qm(), lb, l_b);
to_mpq(qm(), ub, u_b);
if (compare(cell_a, l_b) == sign_neg) return sign_neg;
if (compare(cell_a, u_b) == sign_pos) return sign_pos;
if (compare(cell_b, l_a) == sign_neg) return sign_pos;
if (compare(cell_b, u_a) == sign_pos) return sign_neg;
//
// EXPENSIVE CASE
// Let seq be the Sturm-Tarski sequence for