unsat コアは、「回答リテラル」(別名、仮定) を使用して追跡されます。unsat コア抽出を有効にして、次のようなアサーションを使用する場合
(assert (! (= x 10) :named a1))
Z3 は内部的に名前の新しいブール変数を作成し、a1
アサートします。
(assert (=> a1 (= x 10)))
が呼び出されると、check-sat
これらすべての補助変数が true であると見なされます。つまり、Z3 は問題が unsat/sat modulo これらの仮定であることを示そうとします。満足できるインスタンスの場合、通常どおりモデルで終了します。満たされないインスタンスの場合、これらの仮定されたブール変数のみを含むレンマを生成するたびに終了します。補題は、が想定されるブール変数のサブセットで(or (not a_i1) ... (not a_in))
ある形式です。a_i
私の知る限り、この手法は MiniSAT ソルバーによって導入されています。ここで説明します(セクション 3)。実装が簡単で、基本的に unsat コアの生成が無料でできるので、とても気に入っています。
ただし、この方法にはいくつかの欠点があります。まず、一部の前処理手順が適用できなくなりました。ただ主張するなら
(assert (= x 10))
Z3はどこでも置き換えx
られます。10
Z3 は「値の伝播」を行っていると言えます。アサーションが次の形式の場合、この前処理ステップは適用されません。
(assert (=> a1 (= x 10)))
これは単なる例であり、他の多くの前処理ステップが影響を受けます。計算中は、単純化ステップの一部も無効になります。Z3 ソース ファイルsmt_context.cppを調べると、次のようなコードが見つかります。
void context::simplify_clauses() {
// Remark: when assumptions are used m_scope_lvl >= m_search_lvl > m_base_lvl. Therefore, no simplification is performed.
if (m_scope_lvl > m_base_lvl)
return;
...
}
m_scope_lvl > m_base_lvl)
「回答リテラル」/仮定が使用されている場合、条件は常に真です。そのため、unsat コアの生成を有効にすると、パフォーマンスに大きな影響を与える可能性があります。本当に無料のものはないようです:)