我一直在使用ConstInterp来获取expr中常量文字的值。
model.ConstInterp(lit)
然而我遇到了一个奇怪的错误
... <body of some loop>
let x = model.ConstInterp(lit)
if solver.Check() == Status.SATISFIABLE
then model.ConstInterp(lit)
对ConstInterp的第二次调用产生错误
Unhandled Exception: Microsoft.Z3.Z3Exception: invalid argument
at Microsoft.Z3.Native.Z3_model_get_const_interp(IntPtr a0,IntPtr a1,IntPtr a2)
at Microsoft.Z3.Model.ConstInterp(FuncDecl f)
at Microsoft.Z3.Model.ConstInterp(Expr a)
然而与Eval相同的代码而不是ConstInterp它的罚款。我错误地使用了ConstInterp吗?
答案 0 :(得分:1)
对model.ConstInterp()的第一次调用使用了在前一次调用Check()期间构造的模型,因此它可能包含不同的常量解释,但这只是次要问题。
并不要求所有常量在每个模型中都有解释,例如,当不需要赋值来满足所有约束时,它可以保持未分配(因此在模型中缺失)。例如,请考虑以下程序:
Solver s = ctx.MkSolver();
s.Add(ctx.MkOr(
ctx.MkEq(x, ctx.MkTrue()),
ctx.MkEq(x, ctx.MkFalse()))); // Assert x = false OR x = true
s.Add(ctx.MkEq(y, ctx.MkTrue())); // Assert y = false
s.Check(); // Returns Status.SATISFIABLE
此程序不会限制x
,但会限制y
。因此,模型将不包含x
的值,而s.Model.ConstInterp(x)
将抛出一个断言。对s.Model.Eval(x)
的调用不会抛出断言,但也不会评估x
;在这个例子中,我们得到s.Model.Eval(x) == x
。通过将Eval()
的第二个参数设置为true可以更改此行为,从而启用模型完成,即
s.Model.Eval(x, true)
将返回false
。
作为替代方案,数组s.Model.ConstDecls
包含常量的所有函数声明,这些声明在模型中有解释。不在此集合中的常量没有解释,可以假设为“不关心”,即可以为其分配任何值。