我正在解决一个问题,在 Z3 中定义了大量变量(大约 500 个)。我有兴趣找到满足我的约束的多个模型(致力于多个解决方案),但我只需要这些变量的特定子集的值。
有没有办法指示 Z3 检查约束并生成仅包含特定变量集的模型?我正在寻找一种解决方案,可以避免为所有 500 个变量生成值,因为这对于我的问题来说是不必要的,并且可能会减慢求解器的速度。
任何带有简单示例的建议或指导将不胜感激。
谢谢你。
我正在为我的项目使用以下方法(一个简单的示例),如下所示。 API 模型将获得所有变量的解决方案,但有兴趣生成具有特定变量的模型。在获得所有解决方案时,它会变慢。
# Define a large number of variables
variables = [Int('x{}'.format(i)) for i in range(500)]
# Define some constraints
constraints = [var > 0 for var in variables]
# Create a solver and add the constraints
s = Solver()
s.add(constraints)
# Find 500 solutions
for i in range( 500 ):
if s.check() == sat:
m = s.model()
# Print the values of x0, x1, and x2
for j in range(3):
print(m[variables[j]])
# Add a constraint that negates the current solution for x0, x1, and x2
s.add(Or(variables[0] != m[variables[0]], variables[1] != m[variables[1]], variables[2] != m[variables[2]]))
else:
print("No more solutions")
break
一般来说,您不必担心对解决方案没有贡献的变量:如果它们不重要,那么底层求解器就会弄清楚这一点,并且不会浪费时间来确定问题是 SAT 还是 UNSAT。 (在模型创建过程中,它会为这些变量赋值,但一旦达到 SAT 状态,这是一个相对便宜的操作。)
然而,在我看来,你想要的有点不同。你是说,即使这些“额外”变量的改变可以给你一个新的模型,但你并不真正关心这些。在您的示例中,您唯一感兴趣的模型是当
x0
、x1
和 x2
不同时。也就是说,您不关心不同的模型,其中 x0
、x1
、x2
相同,并且更改在其余 497 个变量中。
如果是这种情况(这确实是一个合法的用例),您应该改用快速全卫星算法。请参阅 https://theory.stanford.edu/~nikolaj/programmingz3.html#sec-blocking-evaluations,特别是函数
all_smt
。 (另请参阅https://stackoverflow.com/a/70656700/936310)。请注意,编程 z3 文档已被修复,因此您可以逐字使用那里的定义。
特别是,
all_smt
的第二个参数(名为initial_terms
)正是您想要使用的。您想将 [x0, x1, x2]
作为参数传递给它。有关正确使用 all_smt
的讨论,请参阅 https://stackoverflow.com/a/76494971/936310。