在使用.smt2文件时,我注意到Z3 4.3.1有一些奇怪的行为。
如果我做(assert (= 0 0.5))
,那将是令人满意的。但是,如果我切换订单并执行(assert (= 0.5 0))
则不满意。
我对正在发生的事情的猜测是,如果第一个参数是一个整数,它将它们都转换为整数(将0.5舍入为0),然后进行比较。如果我将“0”更改为“0.0”,它将按预期工作。这与我使用的大多数编程语言形成对比,如果其中一个参数是浮点数,它们都被转换为浮点数并进行比较。这真的是Z3中的预期行为吗?
答案 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_real
和to_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