これは、assert-softコマンドを使用する別の回答です。
代替エンコーディング #1
最初にOptiMathSATのエンコーディングを提供し、次にこれらの式を変更してz3で同じ結果を得る方法を説明します。他のアプローチと比較して、このエンコーディングは、同じ優先度レベルを共有する多くのブール変数がある場合により適しています。これにより、OMT ソルバーは辞書式検索の各ステップに専用の MaxSAT エンジンを使用するか、カーディナリティ ネットワークを使用してパフォーマンスを向上させることができます。標準の OMT ベースの検索。
次のように、他の回答で示した2つのおもちゃの例を1つの増分式で混同しました。
(set-option :produce-models true)
(set-option :opt.priority lex)
(declare-const a Bool)
(declare-const b Bool)
(declare-const c Bool)
(assert (= a true))
(assert (or
(and (= b true) (not (= c true)))
(and (= c true) (not (= b true)))
))
(assert-soft a :weight 1 :id highest_priority)
(assert-soft b :weight 1 :id medium_priority)
(assert-soft c :weight 1 :id lowest_priority)
(minimize highest_priority)
(minimize medium_priority)
(minimize lowest_priority)
; First Solution
(check-sat)
(get-objectives)
(get-model)
; Second Solution
(push 1)
(assert (not (and a b)))
(check-sat)
(get-objectives)
(get-model)
(pop 1)
(exit)
これは出力です:
~$ optimathsat test.smt2
sat
(objectives
(highest_priority 0)
(medium_priority 0)
(lowest_priority 1)
)
( (a true)
(b true)
(c false)
(highest_priority 0)
(medium_priority 0)
(lowest_priority 1) )
sat
(objectives
(highest_priority 0)
(medium_priority 1)
(lowest_priority 0)
)
( (a true)
(b false)
(c true)
(highest_priority 0)
(medium_priority 1)
(lowest_priority 0) )
このエンコーディングをz3で使用するには、次の 3 行をコメント アウトするだけで十分です。
;(minimize highest_priority)
;(minimize medium_priority)
;(minimize lowest_priority)
これは、z3がコマンドの目的を暗黙的に定義し、assert-softそれを暗黙的に最小化するためです。その出力は次のとおりです。
~$ z3 test.smt2
sat
(objectives
(highest_priority 0)
(medium_priority 0)
(lowest_priority 1)
)
(model
(define-fun b () Bool
true)
(define-fun c () Bool
false)
(define-fun a () Bool
true)
)
sat
(objectives
(highest_priority 0)
(medium_priority 1)
(lowest_priority 0)
)
(model
(define-fun b () Bool
false)
(define-fun c () Bool
true)
(define-fun a () Bool
true)
)
z3は暗黙的に最小化目標を宣言するため、assert-softコマンドは関連する目的関数に割り当てたい優先順位と同じ順序で表示される必要があることに注意してください。
incipit で述べたように、このエンコーディングは、いくつかの変数が同じレベルの優先度を共有している場合、他の回答のエンコーディングよりもはるかに優れています。2 つの変数a1をa2同じレベルの優先度で配置するにはid、それらのassert-softコマンドに同じものを使用できます。
例えば:
(set-option :produce-models true)
(set-option :opt.priority lex)
(declare-const a1 Bool)
(declare-const a2 Bool)
(declare-const a3 Bool)
(declare-const b1 Bool)
(declare-const b2 Bool)
(declare-const c Bool)
(assert (= a1 true))
(assert (or
(and (= b1 true) (not (= c true)))
(and (= c true) (not (= b1 true)))
))
(assert (or (not a1) (not a2) (not a3) ))
(assert (or (not b1) (not b2) ))
(assert-soft a1 :weight 1 :id highest_priority)
(assert-soft a2 :weight 1 :id highest_priority)
(assert-soft a3 :weight 1 :id highest_priority)
(assert-soft b1 :weight 1 :id medium_priority)
(assert-soft b2 :weight 1 :id medium_priority)
(assert-soft c :weight 1 :id lowest_priority)
(minimize highest_priority)
(minimize medium_priority)
(minimize lowest_priority)
; First Solution
(check-sat)
(get-objectives)
(get-model)
; Second Solution
(push 1)
(assert (not (and a1 b1)))
(check-sat)
(get-objectives)
(get-model)
(pop 1)
(exit)
出力で
~$ optimathsat test.smt2
sat
(objectives
(highest_priority 1)
(medium_priority 1)
(lowest_priority 0)
)
( (a1 true)
(a2 true)
(a3 false)
(b1 false)
(b2 true)
(c true)
(highest_priority 1)
(medium_priority 1)
(lowest_priority 0) )
sat
(objectives
(highest_priority 1)
(medium_priority 1)
(lowest_priority 0)
)
( (a1 true)
(a2 true)
(a3 false)
(b1 false)
(b2 true)
(c true)
(highest_priority 1)
(medium_priority 1)
(lowest_priority 0) )
代替エンコーディング #2
興味深い事実は、辞書式最適化エンジンなしで辞書式最適化assert-soft問題を解決するために使用できることです。同じ結果を得るには、重みを少し操作するだけで十分です。これは、SAT/MaxSAT 解法の場合に伝統的に行われていることです。唯一の注意点は、ウェイトを慎重に配置する必要があることです。それ以外では、このアプローチは上記のエンコーディングよりもさらに効率的である可能性があります。これは、最適化の問題全体が内部の単一目的エンジンへの単一の呼び出しで解決されるためです。
(set-option :produce-models true)
(set-option :opt.priority lex)
(declare-const a Bool)
(declare-const b Bool)
(declare-const c Bool)
(assert (= a true))
(assert (or
(and (= b true) (not (= c true)))
(and (= c true) (not (= b true)))
))
(assert-soft a :weight 4 :id obj) ; highest priority
(assert-soft b :weight 2 :id obj)
(assert-soft c :weight 1 :id obj) ; lowest priority
(minimize obj)
; First Solution
(check-sat)
(get-objectives)
(get-model)
; Second Solution
(push 1)
(assert (not (and a b)))
(check-sat)
(get-objectives)
(get-model)
(pop 1)
(exit)
これは出力です:
~$ optimathsat test.smt2
sat
(objectives
(obj 1)
)
( (a true)
(b true)
(c false)
(obj 1) )
sat
(objectives
(obj 2)
)
( (a true)
(b false)
(c true)
(obj 2) )
他の回答へのコメントでこれについて言及しましたが、別の潜在的に興味深い解決策は、式のビットベクターエンコーディングを試してから、OBVBS ( Nadel et al. による「ビットベクター最適化」を参照) を BVに使用することです。 - 最上位ビットが優先度の最も高い変数を表し、最下位ビットが優先度の最も低い変数を表すベクトルの最適化。
試してみたい場合は、少し前に OptiMathSAT に論文で説明されている OBVBS エンジンの再実装を導入しました。Z3 はビットベクター最適化もサポートしています。