web-dev-qa-db-ja.com

Z3:すべての満足のいくモデルを見つける

Microsoft Researchによって開発されたSMTソルバーであるZ3を使用して、いくつかの一次理論のすべての可能なモデルを取得しようとしています。最小限の作業例を次に示します。

(declare-const f Bool)
(assert (or (= f true) (= f false)))

この提案の場合、2つの満足のいく割り当てがあります:f->truef->false。 Z3(および一般的なSMTソルバー)は1つの満足のいくモデルのみを見つけようとするため、すべてのソリューションを見つけることは直接不可能です。 ここ(next-sat)という便利なコマンドを見つけましたが、最新バージョンのZ3ではサポートされなくなったようです。これは私にとって少し残念なことであり、一般的に、このコマンドは非常に便利だと思います。これを行う別の方法はありますか?

25
marczoid

これを実現する1つの方法は、モデル生成機能とともにAPIの1つを使用することです。次に、1つの充足可能性チェックから生成されたモデルを使用して制約を追加し、満足のいく割り当てがなくなるまで、前のモデル値が後続の充足可能性チェックで使用されないようにします。もちろん、有限ソートを使用する必要があります(またはこれを保証するいくつかの制約があります)が、すべての可能なモデルを見つけたくない場合(つまり、束を生成した後に停止する場合)、無限ソートでもこれを使用できます。 。

これはz3pyを使用した例です(z3pyスクリプトへのリンク: http://rise4fun.com/Z3Py/a6MC ):

a = Int('a')
b = Int('b')

s = Solver()
s.add(1 <= a)
s.add(a <= 20)
s.add(1 <= b)
s.add(b <= 20)
s.add(a >= 2*b)

while s.check() == sat:
  print s.model()
  s.add(Or(a != s.model()[a], b != s.model()[b])) # prevent next model from using the same assignment as a previous model

一般に、関連するすべての定数の分離を使用すると機能するはずです(たとえば、ここではab)。これは、1を満たすab20a >= 2bの間)のすべての整数割り当てを列挙します。たとえば、ab15の間にあるように制限すると、出力は次のようになります。

[b = 1, a = 2]
[b = 2, a = 4]
[b = 1, a = 3]
[b = 2, a = 5]
[b = 1, a = 4]
[b = 1, a = 5]
28