简体   繁体   English

Python Z3 API 查询:当求解器返回未知状态时,我们能否使用 z3 python API 得到部分 model

[英]Python Z3 API Query : Can we get a partial model using the z3 python API when solver returns unkown status

I am pretty sure it has something to do with the python API. Is there a way to get back a partial model from z3 even when the status is unknown ?我很确定它与 python API 有关。即使状态unknown ,是否有办法从 z3 取回部分 model?

I am trying to get a model out of z3 even when the status returns unknown result.即使状态返回unknown结果,我也试图从 z3 中获取 model。 It fails with raising an exception for model not available .它失败并引发model not availableexception Any suggestions what can be done?有什么建议可以做什么?

I converted the assertions to smt-lib format using sexpr() method from the z3 Solver interface and it returns a partial model even when the status is unknown .我使用z3 Solver接口中的sexpr()方法将断言转换为 smt-lib 格式,即使状态unknown ,它也会返回部分 model 。 I have attached example below.我在下面附上了例子。

# -*- coding: utf-8 -*-
​
from z3 import *
​
x, y, z = Reals('x y z')
m, n, l = Reals('m n l')
u, v = Ints('u v')
​
S = SolverFor("NRA")
​
S.add(x >= 0)
S.add(y >= 30, z <= 50)
S.add(m >= 5, n >= 5)
S.add(m * x + n * y + l > 300)
​
S.add(ForAll([u, v], Implies(m * u + n * v + l > 300, u + v + z <= 50)))
​
print(S.check())
print(S.sexpr())

In SMMT-LIB Format采用 SMMT-LIB 格式

(set-option :print-success true) 
(set-option :produce-unsat-cores true) ; enable generation of unsat cores
(set-option :produce-models true) ; enable model generation
(set-option :produce-proofs true) ; enable proof generation
(declare-fun x () Real)
(declare-fun y () Real)
(declare-fun z () Real)
(declare-fun m () Real)
(declare-fun n () Real)
(declare-fun l () Real)
(assert (>= x 0.0))
(assert (>= y 30.0))
(assert (<= z 50.0))
(assert (>= m 5.0))
(assert (>= n 5.0))
(assert (not (<= (+ (* m x) (* n y) l) 300.0)))
(assert (forall ((u Int) (v Int))
  (let ((a!1 (<= (+ (* m (to_real u)) (* n (to_real v)) l) 300.0)))
    (or (<= (+ (to_real u) (to_real v) z) 50.0) a!1))))
(check-sat)
(get-model)

I am running this file like this from the command line (terminal)我正在从命令行(终端)像这样运行这个文件

$ z3 example.py

Output: Output:

success
success
success
success
success
success
success
success
success
success
success
success
success
success
success
success
success
unknown
(model 
  (define-fun z () Real
    20.0)
  (define-fun y () Real
    30.0)
  (define-fun l () Real
    145.0)
  (define-fun x () Real
    0.0)
  (define-fun n () Real
    5.0)
  (define-fun m () Real
    5.0)
)

Any suggestions on how to get this model via the python interface directly?关于如何直接通过 python 接口获取这个 model 有什么建议吗?

The exception which z3 raises after model() call on unknown status. z3 在model()调用unknown状态后引发的异常。

unknown
Traceback (most recent call last):

  File "C:\Python38\Lib\site-packages\z3\z3.py", line 6696, in model
    return ModelRef(Z3_solver_get_model(self.ctx.ref(), self.solver), self.ctx)

  File "C:\Python38\Lib\site-packages\z3\z3core.py", line 3759, in Z3_solver_get_model
    _elems.Check(a0)

  File "C:\Python38\Lib\site-packages\z3\z3core.py", line 1385, in Check
    raise self.Exception(self.get_error_message(ctx, err))

Z3Exception: b'there is no current model'


During handling of the above exception, another exception occurred:

Traceback (most recent call last):

  File "C:\Users\lahir\Documents\GitHub\codersguild\Research\tangram-solve\z3_tryouts.py", line 19, in <module>
    print(S.model())

  File "C:\Python38\Lib\site-packages\z3\z3.py", line 6698, in model
    raise Z3Exception("model is not available")

Z3Exception: model is not available

Thanks谢谢

I haven't yet found an alternate other than the one I mentioned above.除了我上面提到的那个,我还没有找到替代品。

You cannot rely on the model if the solver returned unknown .如果求解器返回unknown ,则不能依赖 model 。 That is, the model you get is not "partial" by any means: It may or may not satisfy some of the constraints, but otherwise, there's not much you can do with it.也就是说,您得到的 model 无论如何都不是“部分的”:它可能满足也可能不满足某些约束,但除此之外,您无能为力。 It's at best a representation of the internal state of the solver.它充其量是求解器内部 state 的表示。 But in general, it is not guaranteed to be a representation of anything.但总的来说,它不能保证代表任何东西。

Also, when I run your SMTLib script with z3, I get:此外,当我使用 z3 运行您的 SMTLib 脚本时,我得到:

unknown
(error "line 21 column 10: model is not available")

and I've z3 built from their github master about a week ago.大约一周前,我从他们的 github master 构建了 z3。 I gather you've an old version, I'd strongly recommend you upgrade.我知道你有一个旧版本,我强烈建议你升级。

For reference, when you get unknown as an answer, the only valid thing to do is to ask the solver why the result is unknown.作为参考,当您得到未知答案时,唯一有效的做法是询问求解器为什么结果未知。 This is typically done with code like:这通常使用如下代码完成:

r = S.check()
if r == sat:
    print(S.model())
elif r == unknown:
    print("Unknown, reason: %s" % S.reason_unknown())
else:
    print("Solver said: %s" % r)

For your Python program, I get:对于您的 Python 程序,我得到:

smt tactic failed to show goal to be sat/unsat (incomplete quantifiers)

and that's really the only information you have at this point: Any "extraction" of model values would be simply wrong if the solver state is unknown .这实际上是此时您拥有的唯一信息:如果求解器 state unknown ,则 model 值的任何“提取”都是错误的。

(A related question is also about "interrupting" the computation during a call to z3's optimizing solver. The "model" you get if you interrupt the solver will not be a "best" so far by any means, it may or may not satisfy the existing constraints. Long story short, unless solver reports sat , do not count on the model you get: z3 is doing the right thing here and telling you there's no viable model available.) (一个相关的问题也是关于在调用 z3 的优化求解器期间“中断”计算。如果你中断求解器你得到的“模型”无论如何都不是“最好的”,它可能满足也可能不满足现有的约束。长话短说,除非求解器报告sat ,否则不要指望你得到的 model:z3 在这里做正确的事情并告诉你没有可行的 model 可用。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM