z3解决方案的数量

时间:2013-03-06 19:37:41

标签: python z3 solver

如何使用z3计算解决方案的数量?例如,我想证明对于任何n,方程组{x^2 == 1, y_1 == 1, ..., y_n == 1}有2个解。以下代码显示给定n的可满足性,这不是我想要的(我想要任意n的解决方案的数量。)

#!/usr/bin/env python

from z3 import *

# Add the equations { x_1^2 == 1, x_2 == 1, ... x_n == 1 } to s and return it.
def add_constraints(s, n):
    assert n > 1
    X = IntVector('x', n)
    s.add(X[0]*X[0] == 1)
    for i in xrange(1, n):
        s.add(X[i] == 1)
    return s

s = Solver()
add_constraints(s, 3)
s.check()
s.model()

1 个答案:

答案 0 :(得分:7)

如果存在有限数量的解,则可以使用不等于其指定模型值的常量(您的x_i)的析取来枚举所有这些。如果有无限的解决方案(如果你想为所有自然数n证明这一点就是这种情况),你可以使用相同的技术,但当然不能全部枚举它们,但可以使用它来生成许多解决方案,直到你挑选一些约束。如果你想为所有n>证明这一点1,你需要使用量词。我在下面添加了对此的讨论。

虽然你没有提出这个问题,但你也应该看到这个问题/答案:Z3: finding all satisfying models

以下是您执行此操作的示例(此处为z3py链接:http://rise4fun.com/Z3Py/643M):

    # Add the equations { x_1^2 == 1, x_2 == 1, ... x_n == 1 } to s and return it.
def add_constraints(s, n, model):
    assert n > 1
    X = IntVector('x', n)
    s.add(X[0]*X[0] == 1)
    for i in xrange(1, n):
        s.add(X[i] == 1)

    notAgain = []
    i = 0
    for val in model:
      notAgain.append(X[i] != model[val])
      i = i + 1
    if len(notAgain) > 0:
      s.add(Or(notAgain))
      print Or(notAgain)
    return s

for n in range(2,5):
  s = Solver()
  i = 0
  add_constraints(s, n, [])
  while s.check() == sat:
    print s.model()
    i = i + 1
    add_constraints(s, n, s.model())
  print i # solutions

如果你想证明没有其他解决方案可以选择n,你需要使用量词,因为前面的方法只适用于有限n(并且它很快就会变得非常昂贵)。这是一个显示此证明的编码。您可以对此进行概括,以在前一部分中结合模型生成功能,为更通用的公式提供+/- 1解决方案。如果方程有许多独立于n的解(如在你的例子中),这将允许你证明方程有一些有限数量的解。如果解决方案的数量是n的函数,则必须将该函数计算出来。 z3py链接:http://rise4fun.com/Z3Py/W9En

x = Function('x', IntSort(), IntSort())
s = Solver()
n = Int('n')
# theorem says that x(1)^2 == 1 and that x(1) != +/- 1, and forall n >= 2, x(n) == 1
# try removing the x(1) != +/- constraints
theorem = ForAll([n], And(Implies(n == 1, And(x(n) * x(n) == 1, x(n) != 1, x(n) != -1) ), Implies(n > 1, x(n) == 1)))
#s.add(Not(theorem))
s.add(theorem)
print s.check()
#print s.model() # unsat, no model available, no other solutions