当我使用ForAll量词时,我得到了一些奇怪的结果。我的目标是将函数foo的解释限制为以下内容:
\Ax,y. foo(x,y)= if x=A && y=B then C1 else C2
因此,如果我将上述内容置于上下文中,我应该回到foo的解释,这基本上等同于上面的内容。但是我没有。我得到的回报是
foo(x,y)= if x=A && y=B then C1 else C1
我不知道为什么。我正在使用的代码如下(通过.net API访问Z3)
let ctx = new Context()
let Sort1 = ctx.MkEnumSort("S1", [|"A";"AA"|])
let Sort2 = ctx.MkEnumSort("S2", [|"B"|])
let Sort3 = ctx.MkEnumSort("S3", [|"C1";"C2"|])
let s1 = ctx.MkSymbol "s1"
let s2 = ctx.MkSymbol "s2"
let types = [|Sort1:>Sort; Sort2:>Sort |]
let names = [|s1:>Symbol ; s2:>Symbol|]
let vars = [| ctx.MkConst(names.[0],types.[0]);ctx.MkConst(names.[1],types.[1])|]
let FDecl = ctx.MkFuncDecl("foo", [|Sort1:>Sort;Sort2:>Sort|], Sort3)
let f_body = ctx.MkITE(ctx.MkAnd(ctx.MkEq(vars.[0],getZ3Id("A",Sort1)),
ctx.MkEq(vars.[1], getZ3Id("B",Sort2))),
getZ3Id("C1",Sort3),
getZ3Id("C2",Sort3))
let f_app = FDecl.Apply vars //ctx.MkApp(FDecl, vars)
let body = ctx.MkEq(f_app, f_body)
let std_weight = uint32 1
let form = ctx.MkForall(types, names, body, std_weight, null, null, null, null)
:> BoolExpr
let s = ctx.MkSolver()
satisfy s [|form|]
s.Model
其中getZ3Id
将给定字符串转换为Enum
let getZ3Id (id,sort:EnumSort) =
let matchingConst zconst = zconst.ToString().Equals(id)
Array.find matchingConst sort.Consts
satisfy
是:
let satisfy (s:Solver) formula =
s.Assert (formula)
let res = s.Check()
assert (res = Status.SATISFIABLE)
s.Model
模型返回foo的解释,无论什么
返回C1(define-fun foo ((x!1 S1) (x!2 S2)) S3
(ite (and (= x!1 A) (= x!2 B)) C1
C1))
有人能指出我哪里出错吗? 谢谢 PS对MkForAll的两个API调用之间的区别是什么 - 一个采用排序和名称,另一个采用“绑定常量”?
这是我的进一步问题: 如果我定义
let set1 = Set.map (fun (p:string)-> ctx.MkConst(p,Sort3))
(new Set<string>(["C1"]))
并改变f的主体
let f_body = ctx.MkITE(ctx.MkAnd(ctx.MkEq(vars.[0],getZ3Id("A",Sort1))),
ctx.MkEq(vars.[1], getZ3Id("B",Sort2))),
mkZ3Set ctx set1,
ctx.MkEmptySet Sort3)
其中
let mkZ3Set (ctx:Context) exprs sort =
Set.fold (fun xs x-> ctx.MkSetAdd(xs,x)) (ctx.MkEmptySet(sort)) exprs
Z3公式看起来合理
form= (forall ((s1 S1))
(= (foo s1)
(ite (and (= s1 A))
(store ((as const (Array S3 Bool)) false) C1 true)
((as const (Array S3 Bool)) false))))
然而Z3返回不满意。你能告诉我为什么吗?
答案 0 :(得分:1)
问题在于量词抽象。它不会抽象你想要的变量。
let form = ctx.MkForall(types, names, body, std_weight, null, null, null, null)
:> BoolExpr
应改为:
let form = ctx.MkForall(vars, body, std_weight, null, null, null, null)
:> BoolExpr
背景是Z3为您量化变量提供了两种不同的方式。
选项1:您可以抽象出现在公式中的常量。您应该将这些常量的数组传递给量词抽象。这是我的修正使用的版本。
选项2:您可以抽象出在公式中看似自由的de-Brujin指数。然后,您可以使用您在示例中使用的ctx.MkForall的重载。但它要求无论何时引用绑定变量,都要使用绑定索引(使用ctx.MkBound创建的东西)。