Why does 0 = 0.5?

2019-06-21 17:40发布

I noticed some strange behavior with Z3 4.3.1 when working with .smt2 files.

If I do (assert (= 0 0.5)) it will be satisfiable. However, if I switch the order and do (assert (= 0.5 0)) it's not satisfiable.

My guess as to what is happening is that if the first parameter is an integer, it casts both of them to integers (rounding 0.5 down to 0), then does the comparison. If I change "0" to "0.0" it works as expected. This is in contrast to most programming languages I've worked with where if either of the parameters is a floating-point number, they are both cast to floating-point numbers and compared. Is this really the expected behavior in Z3?

标签: z3
7条回答
Animai°情兽
2楼-- · 2019-06-21 18:21

Do not rely on the implicit type conversion of any solver. Instead, use to_real and to_int to do explicit type conversions. Only send well-typed formulas to the solver. Then Mohamed Iguernelala's examples become the following.

(set-logic AUFLIRA)
(declare-fun x () Int)
(assert (= (to_real x) 1.5))
(check-sat)
(exit)

(set-logic AUFLIRA)
(declare-fun x () Int)
(assert (= 1.5 (to_real x)))
(check-sat)
(exit)

Both of these return UNSAT in Z3 and CVC4. If instead, you really wanted to find the model where x = 1 you should have instead used one of the following.

(set-option :produce-models true)
(set-logic AUFLIRA)
(declare-fun x () Int)
(assert (= (to_int 1.5) x))
(check-sat)
(get-model)
(exit)

(set-option :produce-models true)
(set-logic AUFLIRA)
(declare-fun x () Int)
(assert (= x (to_int 1.5)))
(check-sat)
(get-model)
(exit)

Both of these return SAT with x = 1 in Z3 and CVC4.

Once you make all the type conversions explicit and deal only in well-typed formulas, the order of arguments to equality no longer matters (for correctness).

查看更多
混吃等死
3楼-- · 2019-06-21 18:23

One possible solution is

(declare-fun x () Real)
(declare-fun y () Real)
(assert (= x 0))
(assert (= y 0.5))
(check-sat)
(push)
(assert (= x y) )
(check-sat)
(pop)

and the output is

sat
unsat
查看更多
唯我独甜
4楼-- · 2019-06-21 18:30

I think this is a consequence of lack of type-checking; z3 is being too lenient. It should simply reject such queries as they are simply not well formed.

According to the SMT-Lib standard, v2 (http://smtlib.cs.uiowa.edu/papers/smt-lib-reference-v2.0-r10.12.21.pdf); page 30; the core theory is defined thusly:

(theory Core
:sorts ((Bool 0))
:funs ((true Bool) (false Bool) (not Bool Bool)
      (=> Bool Bool Bool :right-assoc) (and Bool Bool Bool :left-assoc)
      (or Bool Bool Bool :left-assoc) (xor Bool Bool Bool :left-assoc)
      (par (A) (= A A Bool :chainable))
      (par (A) (distinct A A Bool :pairwise))
      (par (A) (ite Bool A A A))
      )
:definition
"For every expanded signature Sigma, the instance of Core with that signature
is the theory consisting of all Sigma-models in which:
  - the sort Bool denotes the set {true, false} of Boolean values;
  - for all sorts s in Sigma,
       - (= s s Bool) denotes the function that
         returns true iff its two arguments are identical;
       - (distinct s s Bool) denotes the function that
         returns true iff its two arguments are not identical;
       - (ite Bool s s) denotes the function that
         returns its second argument or its third depending on whether
         its first argument is true or not;
       - the other function symbols of Core denote the standard Boolean operators
         as expected.
       "
  :values "The set of values for the sort Bool is {true, false}."
)

So, by definition equality requires the input sorts to be the same; and hence the aforementioned query should be rejected as invalid.

There might be a switch to z3 or some other setting that forces more strict type-checking than it does by default; but I would've expected this case to be caught even with the most relaxed of the implementations.

查看更多
不美不萌又怎样
5楼-- · 2019-06-21 18:31

Jochen Hoenicke gived the answer (on SMT-LIB mailing list) regarding "mixing reals and integers". Here it is:

I just wanted to point out, that the syntax may be officially correct. There is an extension in AUFLIRA and AUFNIRA.

From http://smtlib.cs.uiowa.edu/logics/AUFLIRA.smt2

"For every operator op with declaration (op Real Real s) for some sort s, and every term t1, t2 of sort Int and t of sort Real, the expression - (op t1 t) is syntactic sugar for (op (to_real t1) t) - (op t t1) is syntactic sugar for (op t (to_real t1)) - (/ t1 t2) is syntactic sugar for (/ (to_real t1) (to_real t2)) "

查看更多
Lonely孤独者°
6楼-- · 2019-06-21 18:32

One of our interns, who worked on a conservative extension of SMT2 with polymorphism has noticed the same strange behavior, when he tried the understand how formulas mixing integers and reals are type-checked:

z3 (http://rise4fun.com/z3) says that the following example is SAT, and finds a model x = 1

(set-logic AUFLIRA)
(declare-fun x () Int)
(assert (= x 1.5))
(check-sat)
(get-model)
(exit)

But, it says that the following "equivalent" example in UNSAT

(set-logic AUFLIRA)
(declare-fun x () Int)
(assert (= 1.5 x))
(check-sat)
(exit)

So, this does not comply with the symmetric property of equality predicate. So, I think it's a bug.

查看更多
Emotional °昔
7楼-- · 2019-06-21 18:35

Strictly speaking, Z3 is not SMT 2.0 compliant by default, and this is one of those cases. We can add

(set-option :smtlib2-compliant true) 

and then this query is indeed rejected correctly.

查看更多
登录 后发表回答