使用scala ^ z3在z3中有太多可能的配置

时间:2011-12-09 14:38:58

标签: scala logic z3 smt

这主要是一个逻辑问题我猜...

我使用这个smtlib公式:

(declare-fun a () Bool)
(declare-fun b () Bool)
(declare-fun c () Bool)
(declare-fun d () Bool)
(assert (xor (and a (xor b c)) d))

这个结构的一个术语(至少在我看来):

    XOR
    | |
  AND d
  | |
  a XOR
    | |
    b c

我的猜测:resultSet看起来像这样:

{ab, ac, d}

但它使用scala ^ z3 ctx.checkAndGetAllModels():

{ab, d, ac, ad, abcd}

为什么广告和abcd在那里? 是否有可能只获得我期望的结果?

1 个答案:

答案 0 :(得分:3)

使用Scala(不带Z3)来表明实际上有更多的约束解决方案:

val tf = Seq(true, false)
val allValid =
  for(a <- tf; b <- tf; c <- tf; d <- tf; 
      if((a && (b ^ c)) ^ d)) yield (
    (if(a) "a" else "") + (if(b) "b" else "") +
    (if(c) "c" else "") + (if(d) "d" else ""))

allValid.mkString("{ ", ", ", " }")

打印:

{ abcd, ab, ac, ad, bcd, bd, cd, d }

所以除非我遗漏了什么,问题是,为什么找到所有解决方案?现在这是答案。 (剧透警告:“getAllModels”并没有真正获得所有模型。)首先,让我们再现你观察到的内容:

import z3.scala._
val ctx = new Z3Context("MODEL" -> true)
val a = ctx.mkFreshConst("a", ctx.mkBoolSort)
val b = ctx.mkFreshConst("b", ctx.mkBoolSort)
val c = ctx.mkFreshConst("c", ctx.mkBoolSort)
val d = ctx.mkFreshConst("d", ctx.mkBoolSort)
val cstr0 = ctx.mkXor(b, c)
val cstr1 = ctx.mkAnd(a, cstr0)
val cstr2 = ctx.mkXor(cstr1, d)
ctx.assertCnstr(cstr2)

现在,如果我跑:ctx.checkAndGetAllModels.foreach(println(_)),我得到:

d!3 -> false
a!0 -> true
c!2 -> false
b!1 -> true

d!3 -> true    // this model is problematic
a!0 -> false

d!3 -> false
a!0 -> true
c!2 -> true
b!1 -> false

d!3 -> true
a!0 -> true
c!2 -> false
b!1 -> false

d!3 -> true
a!0 -> true
c!2 -> true
b!1 -> true

现在,问题是第二个模型是不完整的模型。 Z3可以返回它,因为无论bc的值是什么,约束都会得到满足(bc 不关心变量)。 checkAndGetAllModels的当前实现只是否定了模型以防止重复;在这种情况下,它会要求另一个模型(not (and d (not a)))成立。这将阻止返回具有这两个值的所有其他模型。从某种意义上说,不完整的模型实际上代表了四个有效的,完整的模型。

顺便说一下,如果你使用带有findAll函数的ScalaZ3的DSL,会发生什么情况,所有模型都将完成,当它们不完整时(以及之前)用于计算下一个)。在DSL的上下文中,我们可以这样做,因为我们知道公式中出现的变量集。在这种情况下,很难猜测模型应该如何完成。一种选择是让ScalaZ3记住使用了哪些变量。一个更好的解决方案是Z3可以选择始终返回无关变量的值,或者只是列出模型中的所有不关心变量。