Z3 找到的模型中未显示新变量

Z3 找到的模型中未显示新变量,z3,smt,z3py,Z3,Smt,Z3py,我正在使用z3编写一个静态检查器。我有以下问题: >>> from z3 import * >>> s = Solver() >>> s.add(FreshInt() + FreshInt() > 0) >>> s.check() sat >>> s.model() [] 如您所见,模型中没有显示新的变量。我也无法得到它们的价值: >>> a = FreshInt() >&g

我正在使用z3编写一个静态检查器。我有以下问题:

>>> from z3 import *
>>> s = Solver()
>>> s.add(FreshInt() + FreshInt() > 0)
>>> s.check()
sat
>>> s.model()
[]
如您所见,模型中没有显示新的变量。我也无法得到它们的价值:

>>> a = FreshInt()
>>> s.add(a > 3)
>>> s.check()
sat
>>> s.model()
[]
>>> s.model()[a]

我查看了文档,但找不到改变这种行为的方法。我可以自己生成唯一的变量,但如果z3能帮我解决这个问题就好了。有人能给我指出正确的方向吗?或者在z3py中无法更改此设置?

您可以通过以下方式绕过此限制:

freshIntIdx = 0

def myFreshInt():
    global freshIntIdx
    freshIntIdx += 1;
    return Int('fi' + str(freshIntIdx))

a = myFreshInt()
b = myFreshInt()
s = Solver()
s.add(a + b > 5, a > 0, b > 0, a + b < 10)
print(s.check())
m = s.model()
print("a = %s" % m[a])
print("b = %s" % m[b])
freshIntIdx=0
def myFreshInt():
全球freshIntIdx
freshIntIdx+=1;
返回Int('fi'+str(freshIntIdx))
a=myFreshInt()
b=myFreshInt()
s=解算器()
s、 加上(a+b>5,a>0,b>0,a+b<10)
打印(s.check())
m=s.模型()
打印(“a=%s”%m[a])
打印(“b=%s”%m[b])

FreshInt
/
FreshReal
等用于创建用户不可见的内部变量。您应该改为使用
Int('name')
Real('name')
来创建将在模型中显示的用户级变量

如果您确实想查看值,可以添加一个
observer
函数,并按如下方式使用它:

从z3导入*
def观察者:
obs=Int(‘观察者’)
s、 添加(obs==a)
#可能要检查以下真的返回sat!
s、 检查()
打印s.模型()[obs]
s=解算器()
a=FreshInt()
s、 添加(a+FreshInt()>0)
s、 添加(a>12)
打印s.检查()
观察者(s,a)
这张照片是:

sat
13

这显然不便宜(因为它需要调用
check
),但它是安全的,只要在调试情况下使用它,就像您所说的那样,它就应该起作用。

我认为这是由于
FreshInt
;这些可以被认为是“内部的”。使用
a=Int('a')
,该示例可以正常工作。我理解。因此,没有办法告诉解算器/模型“我知道这些不应该是用户可见的,但是你可以向我展示它们吗?”,即使这不是预期的行为?我没有遵循。如果您想查看它们,为什么不直接使用
Int
/
Real
?这是唯一的区别。(换句话说,如果您想让z3向您展示它们,只需使用
Int
/
Real
,如果您不想自己创建名称,可以使用Axel的技巧。)Axel的技巧并不保证变量是唯一的。当然,您可以有一个计数器,但是如果您在某个地方有一个bug,您可能会因为字符串匹配而意外地重用该名称。通过使用z3的工具,只有在z3中存在错误或者我传递对该变量的引用时,才可能重用名称。我想在我的检查中使用这个额外的保证。我明白你的意思,并在我的答案中添加了一个“强力防护”z3技巧。希望它对你有用!这确实是我现在对需要唯一变量结果的部分代码所做的。但我更愿意,如果我能强迫z3告诉我新变量的值。