可以通过命名表达式实现软约束吗?

时间:2013-02-25 05:36:22

标签: z3

我想知道是否可以使用命名表达式来实现软约束,而无需明确使用手动“跟踪”变量。

使用上面第一条消息中描述的手动跟踪相当麻烦,因为它需要多次调用求解器(事实上,在最坏的情况下可能需要调用2^n以获得最大可能的软件集 - 当我们有n软约束时,约束得到满足。 是否有可能将这两个想法结合起来让Z3以更简单的方式实现软约束?根据这两条消息的想法,我天真地尝试了以下内容:

(set-option :produce-models true)
(set-option :produce-unsat-cores true)
(assert (! false :named absurd))
(check-sat)

我希望z3会告诉我sat,因为在模型中将absurd作为false会满足这个人为的例子;但它产生了unsat;这是合理的,但没有那么有用..

我很感激您提供的任何见解;或者给我一些关于z3如何更详细地使用命名表达式的文档。 (我浏览了手册,但没有在任何地方看到它们的详细解释。)

1 个答案:

答案 0 :(得分:1)

命名表达式是SMT-LIB 2.0标准的一部分。 在Z3中,它们只是使用辅助布尔常量的方法的“语法糖”。

在SMT-LIB 2.0标准中,命名表达式用于“跟踪”(get-unsat-core)等命令的断言(参见SMT-LIB 2.0 reference manual的第5.1.5节)。在您的示例中,如果我们在(get-unsat-core)之后执行(check-sat),则会获得(absurd)Here是在线示例的链接。

关于软/硬限制,似乎你想要MaxSAT。 Z3附带了一个使用2种不同算法的示例,使用C API和辅助布尔常量来实现MaxSAT。最简单的就是使用以下基本思想。

  • 对于每个软约束C_i,它断言b_i implies C_i,其中b_i是一个新的布尔变量。

  • b_i为false的作业基本上忽略约束C_i

  • 使用AtMostK形式的约束来强制最多K b_i为假。 然后,我们可以使用线性搜索来找到可以满足的最大软约束数。我们也可以使用二分搜索(在这种情况下,只需要log N调用,其中N是软约束的数量)。在许多伪布尔解算器中使用了这种方法的变体。

examples\maxsat的示例还包含Fu和Malik建议的更智能的算法。该示例还说明了如何对约束AtMostK进行编码。