参数关系的 z3 编码 table

z3 encoding table of relations for parameters

假设 A,B,C 的参数关系 table 如下所示

╔══════════╦═══╦════════════╗
║    A     ║ B ║     C      ║
╠══════════╬═══╬════════════╣
║ [0...10] ║ 2 ║ [0...10]%4 ║
║ [0...10] ║ 3 ║ [0...10]%3 ║
╚══════════╩═══╩════════════╝

表示对于A,B,C的任意一个值,至少要满足table中的一行。例如,这确实隐含地意味着 B 受 2 <= B <= 3 限制。我如何在 z3 求解器中对此进行编码?

我目前的方法是使用 z3.Implies 并采用参数组合:

import z3
# encode only the first row
A_cond = z3.And(A>=0, A<=10)
B_cond = B==2
C_cond = z3.And(z3.And(C>=0, C<=10), C%4==0)
s = z3.Solver()
s.add([z3.Implies(z3.And(A_cond, B_cond), C_cond),
       z3.Implies(z3.And(A_cond, C_cond), B_cond),
       z3.Implies(z3.And(B_cond, C_cond), A_cond),]
# solve some real constraint
s.add(A + B - C > 0)
s.check()

返回的模型不属于条件的第一行,因为它只是 implies。 对于这种情况,有没有更有效的方法?

我认为单独说明每一行并进行析取要容易得多:

from z3 import *

A, B, C = Ints('A B C')

row1 = And(A >= 0, A <= 10, B == 2, C >= 0, C <= 10, C % 4 == 0);
row2 = And(A >= 0, A <= 10, B == 3, C >= 0, C <= 10, C % 3 == 0);
rows = [row1, row2]

s = Solver()
s.add(Or(rows))

s.add(A+B-C > 0)
print (s.check())
print (s.model())

这很容易扩展到许多行,并且您可以根据需要以编程方式简化常见条件。当 运行 时,它打印:

sat
[A = 10, B = 2, C = 4]

您甚至可以找出 运行ning 满足了哪一行:

m = s.model()
print([i+1 for i, row in enumerate(rows) if m.evaluate(row)])

打印:

[1]

这意味着 row1 满意,但 row2 不满意。