【问题标题】:Z3py returns unknown for equation using pow() functionZ3py 使用 pow() 函数为方程返回未知数
【发布时间】:2015-05-04 19:41:23
【问题描述】:

Z3py 使用 pow() 函数为以下简单问题返回未知数。

import z3;

goal = z3.Goal();
goal = z3.Then('purify-arith','nlsat');
solver = goal.solver();

x = z3.Real('x');
solver.add(x <= 1.8);
solver.add(x >= 0);

z = 10**x;
#z = pow(10,x) returns same result

solver.add(z >= 0, z <= 1.8);
print solver.check()

返回

unknown

显然x = 0, z = 1 是一个令人满意的解决方案。任何关于改变方程式构造方式或修改策略的建议都值得赞赏。

【问题讨论】:

  • 当您编写 10x 时,您指定的是指数函数。你打算写 x10 吗?在这种情况下 Z3 返回 [x = 1]
  • @NikolajBjorner 感谢您的评论 Nikolaj,我确实打算写 '10^x',指数函数。

标签: z3 z3py


【解决方案1】:

可能存在一些错误,但以下返回模型为x = 0z = 1,即使它给出未知。假设 Python API 也显示此模型,您可以创建一个简单的 hack 来提取模型并将其添加到要检查的断言中,类似于防止未来模型重用旧模型值的方式:Z3: finding all satisfying models

这是示例(rise4fun 链接:http://rise4fun.com/Z3/dPnI):

(declare-const x Real)
(declare-const z Real)

(assert (>= x 0.0))
(assert (<= x 1.8))
(assert (= z (^ 10.0 x)))
(assert (<= z 1.8))
(assert (>= z 0.0))

(apply (repeat (then purify-arith simplify ctx-simplify ctx-solver-simplify nlsat qfnra-nlsat))) ; gives:
; (goals
;(goal
;  (>= x 0.0)
;  (<= x (/ 9.0 5.0))
;  (<= (^ 10.0 x) (/ 9.0 5.0))
;  (>= (^ 10.0 x) 0.0)
;  :precision precise :depth 44)
;)

; (apply (repeat (then (repeat purify-arith) (repeat simplify) (repeat ctx-simplify) (repeat ctx-solver-simplify)  (repeat nlsat)  (repeat qfnra-nlsat))))

(check-sat) ; unknown
;(check-sat-using qfnra-nlsat) ; unknown

(get-model) ; gives x = 0.0 and z = 1.0 even though unknown from check-sat

; could extract 0 and 1 in python API and check whether it's sat:
(assert (= x 0))
(assert (= z 1))

(check-sat) ; sat

您可能也对此相关帖子感兴趣:Z3 support for square root

为了完整起见,以下是 Python 中的模型提取想法似乎可行(使用 4.3.3,可能是从不稳定的构建,但可能是不久前):

import z3;

print z3.get_version_string();

goal = z3.Goal();
goal = z3.Then('purify-arith','nlsat');
#solver = goal.solver();

solver = z3.Solver();

x = z3.Real('x');
z = z3.Real('z');
solver.add(x <= 1.8);
solver.add(x >= 0);
solver.add(z == 10.0 ** x);

# z = 10**x;
#z = pow(10,x) returns same result

solver.add(z >= 0, z <= 1.8);

print solver

print solver.check()
print solver.model()

m = solver.model()

solver.add(x == m[x])
solver.add(z == m[z])

print solver

print solver.check()

这给出了:

D:\>python exponent.py
4.3.3
[x <= 9/5, x >= 0, z == 10**x, z >= 0, z <= 9/5]
unknown
[x = 0, z = 1]
[x <= 9/5,
 x >= 0,
 z == 10**x,
 z >= 0,
 z <= 9/5,
 x == 0,
 z == 1]
sat

【讨论】:

  • 基于其他一些奇怪的行为(例如,在平方根中)并且无法在 SMT-LIB 文档中找到^^ 是否意味着求幂? pow 和 ** 等其他东西似乎没有定义。
  • 非常感谢约翰逊教授的帮助。你的回答解决了我的问题。作为旁注,在您的 SMT 代码中,您使用了战术应用 (repeat (then (repeat purify-arith) (repeat simple) (repeat ctx-simplify) (repeat ctx-solver-simplify) (repeat nlsat) (repeat qfnra) -nlsat))))。您是否建议将其作为硬非线性问题的“默认”策略?你的“日常”战术设置是什么?谢谢!
  • 乐于助人!我不认为简化的东西有多大帮助:如果qfnra-nlsat 不能解决非线性实数(或强制整数)问题,那么简化器可能无济于事。我更多地包括了这个,因为找到一个模型有点奇怪,但结果未知(但 Z3 有一些选项用于部分模型构建并返回最后一个检查的模型,有趣的是它没有尝试破解什么正在做只是插入它找到的模型并检查它,我希望简化器可以尝试)。
猜你喜欢
  • 2018-02-05
  • 2018-05-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多