Z3 中的部分赋值

partial assignments in Z3

我有一个布尔公式(格式:CNF),我使用 Z3 SAT 求解器检查其可满足性。当公式可满足时,我有兴趣获得部分分配。我在 OR 门的简单公式上尝试了 model.partial=true,但没有得到任何部分赋值。

你能建议如何做到这一点吗?除了它是部分的之外,我对分配没有任何限制。

Z3的部分模型模式只针对函数模型。对于命题公式,不能保证模型使用最少数量的赋值。相反,SAT 求解器的默认模式是找到完整的作业。

假设您对最小数量的文字感兴趣,这样文字的连词就暗示了公式。您可以使用 unsat cores 来获取此类子集。这个想法是,您首先找到公式 F 的模型作为文字 l1、l2、...、ln 的合取。然后鉴于这是 F 的模型,我们有 l1 & l2 & ... & ln & not F 是不可满足的。 所以想法是断言 "not F" 并检查 "not F" 模假设 l1, l2, .., ln 的可满足性。由于结果是不饱和的,您可以查询 Z3 以检索 l1、l2、..、ln 中的不饱和核心。

从 python 你要做的是创建两个求解器对象:

    s1 = Solver()
    s2 = Solver()

然后你分别加上F, Not(F):

    s1.add(F)
    s2.add(Not(F))

然后您使用两个求解器找到 F 的简化模型:

    is_Sat = s1.check()
    if is_Sat != sat:
       # do something else, return
    m = s1.model()
    literals = [sign(m, m[idx]()) for idx in range(len(m)) ]
    is_sat = s2.check(literals)
    if is_Sat != unsat:
       # should not happen
    core = s2.unsat_core()
    print core

哪里

    def sign(m, c):
        val = m.eval(c)
        if is_true(val):
           return c
        else if is_false(val):
           return Not(c)
        else:
           # should not happen for propositional variables.
           return BoolVal(True)

当然还有其他方法可以减少文字集。一种部分廉价的方法是急切地评估每个子句并从模型中添加文字,直到模型中的至少一个文字满足每个子句为止。换句话说,您正在寻找最小的击球集。你必须在 Z3 之外实现它。