Prolog SAT 求解器
我正在尝试构建一个简单的 Prolog SAT 求解器。我的想法是,用户应该使用 Prolog 列表输入要在 CNF(合取范式)中求解的布尔公式,例如 (A 或 B) 和 (B 或 C) 应表示为 sat([[A, B] ,[B,C]])和 Prolog 继续查找 A、B、C 的值。
我的以下代码不起作用,我不明白为什么。在跟踪的这一行 Call: (7) sat([[true, true]]) ? 我期待 start_solve_clause([_G609, _G612]])。
免责声明:抱歉,代码很糟糕,几天前我什至不知道 Prolog 或 SAT 问题。
PS:欢迎提供有关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).
I'm trying to build a simple Prolog SAT solver. My idea is that the user should enter the boolean formula to be solved in CNF (Conjuctive Normal Form) using Prolog lists, for example (A or B) and (B or C) should be presented as sat([[A, B], [B, C]]) and Prolog procedes to find the values for A, B, C.
My following code is not working and I'm not understanding why. On this line of the trace Call: (7) sat([[true, true]]) ? I was expecting start_solve_clause([_G609, _G612]]).
Disclaimer: Sorry for the crappy code I didn't even know about Prolog or the SAT problem a few days ago.
P.S.: Advice on solving the SAT is welcome.
Trace
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 Source
% 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).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
可以使用 CLP(FD) 来解决 SAT。从 CNF 开始
然后观察一个子句:
可以表示为约束:
进一步对于负文字:
只需使用:
您需要将变量限制在域 0..1 内
并调用标签。一旦标签返回一些
变量的值,你知道你原来的
式可满足。
这是一个运行示例,运行 Joe Lehmann 的测试:
再见
有限域上的约束逻辑编程
http://www.swi-prolog.org/man/clpfd.html
One can use CLP(FD) to solve SAT. Just start with a CNF
and then observe that a clause:
Can be represented as a constraint:
Further for a negative literal:
Simply use:
You need to restrict the variables to the domain 0..1
and invoke labeling. As soon as labeling returns some
value for the variables, you know that your original
formula is satisfiable.
Here is an example run, running the test of Joe Lehmann:
Bye
Constraint Logic Programming over Finite Domains
http://www.swi-prolog.org/man/clpfd.html
有时会发现以下编码。条款是
通过分配不同的正非零来表示
整数到命题变量:
似乎以下 Prolog 代码运行得很好:
这是 Joe Lehmanns 测试用例运行的示例:
受 https://gist.github.com/rla/4634264 .
我猜现在它是 DPLL 算法 的变体。
Sometimes the following coding is found. Clauses are
represented by assigning distinct positive non-zero
integers to propositional variables:
It seems that the following Prolog code works quite well:
Here is an example run for Joe Lehmanns test case:
Code inspired by https://gist.github.com/rla/4634264 .
I guess it is a variant of the DPLL algorithm now.
我希望我的序言解释器在我面前......但是为什么你不能写一个规则
,然后你可以通过执行(btw ; 是或)
也许你需要一些东西来限制它们是真还是假,所以添加这些规则......
并查询
顺便说一句 - 这个实现只是简单地做一个 DFS 来找到满意的术语。没有智能启发法或任何东西。
i wish i had my prolog interpreter in front of me... but why cant you write a rule like
and then you would invoke your example by doing (btw ; is or)
maybe you need something to constrain that they are either true or false so add these rules...
and querying
BTW -- this impl simply would simply be doing a DFS to find satisfying terms. no smart heuristic or anything.
Howe 和 King 在 (SICStus) Prolog 中有一篇关于 SAT 求解的精彩论文(参见 http://www.soi.city.ac.uk/~jacob/solver/index.html)。
CNF 中的条款如下:
There is a wonderful paper by Howe and King about SAT Solving in (SICStus) Prolog (see http://www.soi.city.ac.uk/~jacob/solver/index.html).
The clauses are given in CNF like this: