Skip to content

[Solution Soundness Bug] Incorrect SAT in Float32 FP/Real round-trip arithmetic. #10176

Description

Z3 reports sat for an unsat formula.

Input:

(set-logic ALL)
(declare-const F Int)

(assert
  (and
    (< F 1)
    (>
      (let ((f ((_ to_fp 8 24) RTN (to_real F))))
        (ite
          (fp.isInfinite f)
          0
          (to_int
            (fp.to_real
              (fp.roundToIntegral RTN f)))))
      0)))

(check-sat)

Output:

$ z3 test.smt2 model_validate=true
sat
(error "line 18 column 10: an invalid model was generated")
$ cvc5 test.smt2
unsat

The formula is unsatisfiable.

Because F is an integer and F < 1, we have F <= 0. Converting it to Float32 with RTN therefore produces either -oo or a finite non-positive float.
In the former case the ite returns 0; in the latter case, fp.roundToIntegral RTN, fp.to_real, and to_int cannot make the value positive. Thus the asserted expression cannot be greater than 0.

Without model validation, adding (get-model) produces the following model:

sat
(
  (define-fun F () Int
    0)
  (define-fun /0 ((x!0 Real) (x!1 Real)) Real
    (ite (and (= x!0 1.0) (= x!1 17592186044416.0)) (/ 1.0 17592186044416.0)
      (/ 1.0 85070591730234615865843651857942052864.0)))
)

With a debug build the same behavior takes noticeably longer to trigger, but the outcome is identical. cvc5 returns unsat on this input. On release builds, 4.16.0 answers unknown, while 5.0.0 answers sat.

Commit: 1c89937

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions