【发布时间】:2023-01-13 01:48:50
【问题描述】:
我在 Z3-Py 中使用 Skolem 函数。在接下来的几行中,我描述了 Skolem 函数,它满足在整数上解释的公式 Forall x. Exists y. (x>=2) --> (y>1) /\ (y<=x):
x = Int('x')
skolem = Function('skolem', IntSort(), IntSort())
ct_0 = (x >= 2)
ct_1 = (skolem(x) > 1)
ct_2 = (skolem(x) <= x)
phi = ForAll([x], Implies(ct_0, And(ct_1,ct_2)))
s = Solver()
s.add(phi)
print(s.check())
print(s.model())
据我所知,它可能输出唯一的“模型”:y=2(即f(x)=2)。打印如下:
sat
[skolem = [else -> 2]]
我有一个初步的问题:为什么函数使用else?我想这是因为如果先行词(x>=2)成立,“它只会被激活”。但是,如果激活的不是else分支(输出2),而是if分支,那么哪个是函数的共同域?
但现在我的实际问题来了.我解决了相同的公式,但解释了实数:
x = Real('x')
skolem = Function('skolem', RealSort(), RealSort())
ct_0 = (x >= 2.0)
ct_1 = (skolem(x) > 1.0)
ct_2 = (skolem(x) <= x)
phi = ForAll([x], Implies(ct_0, And(ct_1,ct_2)))
s = Solver()
s.add(phi)
print(s.check())
print(s.model())
这输出...相同的 Skolem 函数!这是正确的吗?
万一是,它仍然很好奇,因为它本可以选择许多其他的;例如,y=1.5。然后,我想为 Z3 请求另一个 Skolem 函数,所以我继续处理,就好像我在请求 5 个新模型:
phi = ForAll([x], Implies(ct_0, And(ct_1,ct_2)))
s = Solver()
s.add(phi)
for i in range(0,5):
if s.check() == sat:
m = s.model()
print(m)
s.add(Not(m))
但我收到以下错误:Z3Exception: True, False or Z3 Boolean expression expected. Received [skolem = [else -> 2]] of type <class 'z3.z3.ModelRef'>. 我的意思是,我看到 Z3 期望布尔值用于否定(这很明显呵呵),所以我如何编码“我将此 Skolem 函数的否定添加到公式中”这一事实,即,我想找到另一个 Skolem 函数?
【问题讨论】:
-
你的公式说
y <= 2,但你的 skolem 函数说skolem(x) <= x。可能没什么大不了的;但让我们先解决这个问题! -
Not(m)毫无意义:你不能对模型进行逻辑否定。但你走在正确的道路上;确保您告诉求解器给定值处的 skolem 函数的值与之前得到的值不同。