【问题标题】:Is calling check twice supposed to work?两次打电话检查应该有效吗?
【发布时间】:2013-01-07 17:29:48
【问题描述】:

http://rise4fun.com/Z3Py/GTYu 上查看 PyZ3 程序。第一次调用check() 工作正常,但如果我们向求解器添加约束并再次调用check(),我们会得到一个不一致的模型!

sy_i = Bool('sy_i')
s0_v, s1_v, s2_v, sx_v, sy_v = Reals('s0_v s1_v s2_v sx_v sy_v')

c = [s0_v >= 1,
     sx_v >= 1,

     s1_v >= s0_v * sx_v,

     sy_v >= 1,

     Or(Not(sy_i), s1_v == RealVal(0.0)),

     s2_v >= s1_v * sy_v
]

solver = Solver()
solver.add(c)
print solver.check()
print solver.model()

solver.add(True)
solver.check()
print solver.model()

有人知道发生了什么吗?

不稳定的Z3版本也一样。

附加上下文:

该程序是使用 nlsatbool 组合求解器的更大程序的简化,遵循答案的伟大建议:Z3 real arithmetics and data types theories integrating not that well

请注意,该方法似乎工作得很好,但是当尝试添加更多约束并重用求解器时,就会出现此问题。可能是检测错了求解方法?

【问题讨论】:

  • 请注意,不鼓励仅链接答案。你的代码 sn-p 真的很小,你应该把它包含在一个问题中

标签: python z3


【解决方案1】:

默认求解器对象Solver() 本质上是一组求解器。它还尝试检测使用模式(增量或非增量)。如果执行了多个check(),则假定用户处于“增量”模式,并使用不完整的非线性算术的通用增量求解器。

要强制 Z3 始终使用 nlsat,我们应该使用创建求解器对象

solver = Tactic('qfnra-nlsat').solver()

如果我们这样做,我们仍然可以使用push()pop()、多个check()。但是,nlsat 不会“重用”以前的 check() 调用的工作。 Here is the new version of your script.

【讨论】:

  • 很棒的莱昂纳多,非常感谢!! [我们怀疑这一点]
  • 顺便说一句,除了 describe_tactics() 之外是否还有其他文档,例如很难知道 qfnra-nlsat 是否适用于 bool 组合,与 qfnra-nlsat 有什么区别nlsat等……当然可以看源码!
  • 策略qfnra-nlsat使用策略nlsat。它在调用nlsat 之前应用了几个预处理步骤。这样做是因为 nlsat 策略只能处理 CNF 格式的公式。
  • 以下链接包含qfnra-nlsat的实现。它只是使用组合器z3.codeplex.com/SourceControl/changeset/view/c430fe26aa30#src/… 组合了几种现有策略
  • 再次非常感谢您的帮助,莱昂纳多!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-11
  • 1970-01-01
  • 1970-01-01
  • 2015-06-05
  • 1970-01-01
  • 2021-06-06
相关资源
最近更新 更多