为什么0 = 0.5?

时间:2014-07-16 20:46:27

标签: z3

在使用.smt2文件时,我注意到Z3 4.3.1有一些奇怪的行为。

如果我做(assert (= 0 0.5)),那将是令人满意的。但是,如果我切换订单并执行(assert (= 0.5 0))则不满意。

我对正在发生的事情的猜测是,如果第一个参数是一个整数,它将它们都转换为整数(将0.5舍入为0),然后进行比较。如果我将“0”更改为“0.0”,它将按预期工作。这与我使用的大多数编程语言形成对比,如果其中一个参数是浮点数,它们都被转换为浮点数并进行比较。这真的是Z3中的预期行为吗?

7 个答案:

答案 0 :(得分:5)

我认为这是缺乏类型检查的结果; z3太宽松了。它应该简单地拒绝这样的查询,因为它们没有很好地形成。

根据SMT-Lib标准,v2(http://smtlib.cs.uiowa.edu/papers/smt-lib-reference-v2.0-r10.12.21.pdf);第30页;核心理论如此定义:

(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}."
)

因此,根据定义,相等性要求输入排序相同;因此上述查询应被视为无效。

可能会切换到z3或某些其他设置强制进行比默认更严格的类型检查;但即使是最轻松的实施,我也希望能够抓住这个案例。

答案 1 :(得分:4)

不要依赖任何解算器的隐式类型转换。代替, 使用to_realto_int进行显式类型转换。只发送 解算器的良好类型公式。然后Mohamed Iguernelala的例子如下:

(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)

这两个都在Z3和CVC4中返回UNSAT。相反,你真的 想要找到你应该拥有x = 1的模型而不是一个 以下。

(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)

这两个都在Z3和CVC4中返回带有x = 1的SAT。

一旦你明确了所有的类型转换并只处理类型很好的公式,相等的参数顺序就不再重要了(为了正确)。

答案 2 :(得分:3)

我的一位实习生,他们使用多态性从事SMT2的保守扩展工作,当他尝试了解如何对整数和实数进行类型检查时,注意到同样的奇怪行为:

z3(http://rise4fun.com/z3)表示以下示例为SAT,并找到模型x = 1

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

但是,它表示以下"相当于" UNSAT中的例子

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

因此,这不符合等式谓词的对称属性。所以,我认为这是一个错误。

答案 3 :(得分:2)

严格地说,Z3默认不符合SMT 2.0,这是其中一种情况。我们可以添加

(set-option :smtlib2-compliant true) 

然后这个查询确实被正确拒绝了。

答案 4 :(得分:1)

Z3不是对这些示例进行类型检查的唯一SMT求解器:

  • CVC4也接受它们(即使使用选项--smtlib-strict),并在上述公式的两种情况下回答UNSAT。

  • Yices接受并回答UNSAT(将逻辑更改为QF_LIA后,因为它不支持AUFLIRA)。

  • 使用(设置逻辑QF_LIA),Z3发出错误:(错误"第3行第17列:逻辑不支持实数")。

  • Alt-Ergo说"输入错误:Int和Real无法统一"在这两种情况下。但Alt-Ergo的SMT2解析器非常有限且未经过严格测试,因为我们专注于其原生多态语言。因此,不应将其作为参考。

我认为开发人员通常会假设"隐含" Int和Real之间的子类型关系。这就是Z3,CVC4和Yices(以及可能还有其他人)成功检查这些示例的原因。

答案 5 :(得分:1)

Jochen Hoenicke给出了关于“混合实数和整数”的答案(在SMT-LIB邮件列表上)。这是:

  

我只想指出,语法可能正式正确。   AUFLIRA和AUFNIRA有一个扩展。

     

来自http://smtlib.cs.uiowa.edu/logics/AUFLIRA.smt2

     

“对于每个具有声明的操作符op(op Real Real s)   排序s,排序Int的每个项t1,t2和排序Real的t,t   表达      - (op t1 t)是(op(to_real t1)t)的语法糖      - (op t t1)是(op t(to_real t1))的语法糖      - (/ t1 t2)是(/(to_real t1)(to_real t2))的语法糖“

答案 6 :(得分:0)

一种可能的解决方案是

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

,输出

sat
unsat