充足可能性問題について |
SATソルバって何。 |
a3 | a2 | a1 | ||
× | b2 | b1 | ||
(a3∧b1) | (a2∧b1) | (a1∧b1) | ||
(a3∧b2) | (a2∧b2) | (a1∧b2) | ||
+ | c2 | c1 | ||
0 | 1 | 0 | 1 |
式 | CNF式 |
---|---|
X = 1 | X |
X = 0 | X |
Y = X | (X∨Y) ∧ (X∨Y) |
Y = X | (X∨Y) ∧ (X∨Y) |
Z = X ∧ Y | (X∨Z) ∧ (Y∨Z) ∧ (X∨Y∨Z) |
Z = X ∨ Y | (X∨Z) ∧ (Y∨Z) ∧ (X∨Y∨Z) |
Z = X ⊕ Y | (X∨Y∨Z) ∧ (X∨Y∨Z) ∧ (X∨Y∨Z) ∧ (X∨Y∨Z) |
SATソルバの作り方。 手法1 - バックトラック |
def doit(): for a in [0, 1]: for b in [0, 1]: for c in [0, 1]: for d in [0, 1]: for e in [0, 1]: if f(a,b,c,d,e): return SAT return UNSAT
decisions = [] # 決めた値 implications = [] # 推論した値 while 未定義の変数がある: decide() # ひとつ決める bcp() # 推論する if 失敗: undo() # もとに戻す flip() # 別の選択肢を試す if 失敗: return UNSAT # もう試すものがない return SAT
decide
)。
bcp
)。
bcp
)。
decide
)。
decide
)。
bcp
)。
bcp
失敗)。
undo
)。
flip
)。
decide
)。
decide()
# 未定義の変数の値をひとつ決める
def decide():
for v in 各変数:
if v == 未定義:
decisions.append((v, 1))
break
decisions
に記録される。
bcp()
# 推論して値を決める def bcp(): for C in 各CNF節: if Cはすでに充足している: continue # Cはまだ充足していない。 U = [ C中の変数で、未定義なもの ] if len(U) == 0: # 変更の余地なし return 失敗 elif len(U) == 1: # テンパってる implications.append((v, 0または1)) return 成功
while level < N: # level = 現在の段階 decide(level) # ひとつ決める bcp(level) # 推論する if 成功: level += 1 # 次の段階へ else: level = まだ選択肢がある段階 undo(level) # その状態に戻す flip(level) # 別の選択肢を試す if 失敗: return UNSAT return SAT
bcp()
が遅い。
def bcp():for C in 各CNF節: # ループ1 if Cはすでに充足している: continue U = [ C中の変数で、未定義なもの ] # ループ2...
SATソルバの作り方。 手法2 - Resolution |
SATソルバの作り方。 手法3 - 学習する |
# Conflict Driven Clause Learning 法 decisions = [] # 決めた値 implications = [] # 推論した値 while 未定義の変数がある: decide() # ひとつ決める bcp() # 推論する if 失敗:learn(decisions) # 失敗から学ぶundo() # もとに戻す flip() # 別の選択肢を試す if 失敗: return UNSAT # もう試すものがない return SAT
decide
) とする。
decide()
する
順番をより賢く決める (a la DPLL法)。
SATソルバとSMTソルバ。 |
a1 | a2 | a3 |
a4 | a5 | a6 |
a7 | a8 | a9 |
(declare-const a1 Int) ; a1は整数型。 ... (assert (<= 1 a1 9)) ; 1 <= a1 <= 9 ... (assert (distinct a1 a2 ... a9)) ; a1...a9は異なる。 ... (assert (= (+ a1 a2 a3) ... (+ a3 a5 a7))) (check-sat) ; 制約充足可能性をチェック。 (get-model) ; 可能なときの値を表示。
まとめ。 |
cdcl.py