私は単純なProlog SATソルバーを構築しようとしています。私が考えているのは、ユーザが、Prologリスト(例えばAまたはB)を使ってCNF(Conjuctive Normal Form)で解決される論理式を入力し、sat([A、B] 、[B、C]])とPrologがA、B、Cの値を見つけようとします。Prolog SAT Solver
私の次のコードは機能しません。トレースのこの行で呼び出し:(7)sat([[true、true]])?私はstart_solve_clause([_ G609、_G612])を期待していました。
免責事項:申し訳ありませんが、私は数日前にPrologやSATの問題について知りませんでした。
P.S .: SATの解決に関するアドバイスは大歓迎です。
トレース
sat([[X, Y, Z], [X, Y]]).
Call: (6) sat([[_G609, _G612, _G615], [_G609, _G612]]) ? creep
Call: (7) start_solve_clause([_G609, _G612, _G615]) ? creep
Call: (8) solve_clause([_G615], _G726) ? creep
Call: (9) or(_G725, _G615, true) ? creep
Exit: (9) or(true, true, true) ? creep
Exit: (8) solve_clause([true], true) ? creep
Call: (8) or(_G609, _G612, true) ? creep
Exit: (8) or(true, true, true) ? creep
Exit: (7) start_solve_clause([true, true, true]) ? creep
Call: (7) sat([[true, true]]) ?
のPrologソース
% Knowledge base
or(true, true, true).
or(false, false, false).
or(true, false, true).
or(false, true, true).
or(not(true), true, true).
or(not(false), false, true).
or(not(true), false, false).
or(not(false), true, true).
or(true, not(true), true).
or(false, not(false), true).
or(true, not(false), true).
or(false, not(true), false).
% SAT solver
sat([]).
sat([Clause | Tail]) :- start_solve_clause(Clause), sat(Tail).
% Clause solver
start_solve_clause([Var1, Var2 | Tail]) :- solve_clause(Tail, Result), or(Var1, Var2, Result).
solve_clause([X | []], Result) :- or(Result, X, true).
solve_clause([X | Tail], Result) :- solve_clause(Tail, Result2), or(Result, X, Result2).
'sat(Stmt): - call(Stmt).'の代わりに' sat(Stmt): - Stmt'だけすることができます。変数を目標として使用することは、変数を引数として 'call/1'と同等です。 – arnsholt
@arnsholt - ああ、なぜ私はそれをするとは思わなかったのか分かりません。とにかく「sat/1」のルール全体が余計に残っていたので、いい名前だったと思う。 – DaveEdelstein
非常に良い提案!また、SATインスタンスを制約問題に整数で直接マッピングし、SICStus、SWI、YAP(およびGNU PrologやB-Prologなどの他のシステムの組み込み制約)でlibrary(clpfd)を使用して解決することもできます。制約ソルバーは、一般に、より単純な(私はそれを意味するわけではありません!)検索よりも、より多くの値を推論し、より速く実行することができます。 SICStusには、専用のSAT制約ソルバー、ライブラリ(clpb)もあります。 – mat