布尔公式的强力Prolog SAT解算器

布尔公式的强力Prolog SAT解算器,prolog,sat,clpb,Prolog,Sat,Clpb,我试图编写一个算法,天真地寻找布尔公式(NNF,但不是CNF)的模型 我的代码可以检查现有的模型,但当要求查找模型时,它将失败(或无法完成),这似乎是因为它为成员(X,Y)生成了无限多的解决方案,其思路是[X |.],\ux,X |.],\uu,X,X |]… 到目前为止,我得到的是: :- op(100, fy, ~). :- op(200, xfx, /\). :- op(200, xfx, \/). :- op(300, xfx, =>). :- op(300,

我试图编写一个算法,天真地寻找布尔公式(NNF,但不是CNF)的模型

我的代码可以检查现有的模型,但当要求查找模型时,它将失败(或无法完成),这似乎是因为它为
成员(X,Y)
生成了无限多的解决方案,其思路是
[X |.],\ux,X |.],\uu,X,X |]…

到目前为止,我得到的是:

:- op(100, fy, ~).    
:- op(200, xfx, /\).  
:- op(200, xfx, \/).  
:- op(300, xfx, =>).  
:- op(300, xfx, <=>). 

formula(X) :- atom(X).
formula(~X) :- formula(X).
formula(X /\ Y) :- formula(X), formula(Y).
formula(X \/ Y) :- formula(X), formula(Y).
formula(X => Y) :- formula(X), formula(Y).
formula(X <=> Y) :- formula(X), formula(Y).

model(1, _).
model(X, F) :- atom(X), member([X, 1], F).
model(~X, F) :- atom(X), member([X, 0], F). % NNF
model(A /\ B, F) :- model(A, F), model(B, F).
model(A \/ B, F) :- (model(A, F); model(B, F)).
model(A => B, F) :- model(~A \/ B, F).
model(A <=> B, F) :- model((A => B) /\ (B => A), F).

sat(A) :- model(A, F), \+ (member([X, 1], F), member([X, 0], F)).


%%% examples:
% formula(~(~ (a /\ b) \/ (c => d))).
% model(a, [[a,1]]).
:-op(100,fy,~)。
:-op(200,xfx,/\)。
:-op(200,xfx,\/)。
:-op(300,xfx,=>)。
:-op(300,xfx,)。
式(X):-原子(X)。
公式(~X):-公式(X)。
公式(X/\Y):-公式(X),公式(Y)。
公式(X\/Y):-公式(X),公式(Y)。
公式(X=>Y):-公式(X),公式(Y)。
公式(xy):-公式(X),公式(Y)。
模型(1,1)。
模型(X,F):-原子(X),成员([X,1],F)。
模型(~X,F):-原子(X),成员([X,0],F)。%NNF
模型(A/\B,F):-模型(A,F),模型(B,F)。
模型(A\/B,F):-(模型(A,F);模型(B,F))。
模型(A=>B,F):-model(~A\/B,F)。
模型(ab,F):-model((A=>B)/\(B=>A),F)。
sat(A):-模型(A,F),\+(成员([X,1],F),成员([X,0],F))。
%%%示例:
%公式((~(a/\b)\/(c=>d)))。
%模型(a,[[a,1]])。
对于
F
,是否有更好的数据结构,或者以其他方式切断部分实例化的列表


编辑:添加了定义和示例。

我通过编写一个
generate\u model
谓词解决了这个问题,该谓词创建了一个预定义列表,每个变量只有一个元素:

generate_model([], []).
generate_model([X|T], [[X,_]|T2]) :- generate_model(T, T2).

sat(A) :- 
  var_list(A, Vars),
  generate_model(Vars, F),
  model(A, F).
使用

:- use_module(library(clpb)). 一些变量(
A
B
)已经绑定到一个布尔值(在上面的查询中),但搜索尚未完成(由剩余目标指示)

要触发所有解决方案的智能暴力枚举,请如下所示:

?sat(~(A*B)+(C*D)),([A,B,C,D])。 A=B,B=1,C=D,D=0 ; A=B,B=D,D=1,C=0 ; A=B,B=C,C=1,D=0。
我是否了解你,你对单一型号感到满意。你 不需要贴标签或计数。这里有一个替代方案,与您的类似,但只返回一致的模型

因为它可以找到计数器模型,所以您需要提供公式的否定式来找到模型。谓词迷宫/3是作为肯定谓词证明/2的否定实现开发的:

% Find a counter model.
% maze(+Norm,+List,-List)
maze(or(A,_),L,_) :- member(A,L), !, fail.
maze(or(A,B),L,R) :- !, inv(A,C), maze(B,[C|L],R).
maze(and(A,_),L,R) :- maze(A,L,R), !.
maze(and(_,B),L,R) :- !, maze(B,L,R).
maze(A,L,_) :- member(A,L), !, fail.
maze(A,L,M) :- oneof(L,B,R), connective(B), !, 
                 inv(A,C), inv(B,D), maze(D,[C|R],M).
maze(A,L,[B|L]) :- inv(A,B).
它可以找到以下所有谬误的对应模型:

Affirming a Disjunct: (p v q) & p => ~q.
Affirming the Consequent: (p => q) & q => p.
Commutation of Conditionals: (p => q) => (q => p).
Denying a Conjunct: ~(p & q) & ~p => q.
Denying the Antecedent: (p => q) & ~p => ~q.
Improper Transposition: (p => q) => (~p => ~q).
下面是一个运行示例:

Jekejeke Prolog 2, Runtime Library 1.2.5
(c) 1985-2017, XLOG Technologies GmbH, Switzerland

?- negcase(_,N,F), norm(F,G), maze(G,[],L), 
   write(N), write(': '), sort(L,R), write(R), nl, fail; true.
Affirming a Disjunct: [pos(p),pos(q)]
Affirming the Consequent: [neg(p),pos(q)]
Commutation of Conditionals: [neg(p),pos(q)]
Denying a Conjunct: [neg(p),neg(q)]
Denying the Antecedent: [neg(p),pos(q)]
Improper Transposition: [neg(p),pos(q)]
有趣的是,这比中电(B)快得多。以下是在CLP(B)和迷宫中运行相同问题的一些计时:

?- time((between(1,1000,_), negcaseclp(_,N,F,L),
   sat(~F), once(labeling(L)), fail; true)).
% Up 296 ms, GC 3 ms, Thread Cpu 250 ms (Current 01/27/18 00:34:20)
Yes 
?- time((between(1,1000,_), negcase(_,_,F),
   norm(F,G), maze(G,[],_), fail; true)).
% Up 82 ms, GC 0 ms, Thread Cpu 78 ms (Current 01/27/18 00:30:21)
Yes 

DanielLyons说:“我觉得生成模型很像,我是不是遗漏了什么?”。我同意。是的<代码>术语变量/2加上一些合适的
地图列表/3
。。。直接使用逻辑变量会更惯用(而且很可能更快)。另外,它还可以防止使用
F
[[x,0],[x,1],…]
(这很糟糕!)哦,太好了!虽然在这种特殊情况下,公式本身并不包含真正的Prolog变量,但每个“变量”都由一个原子项(通常是字符串)表示。然后,我的
var\u list
谓词列出唯一原子的方式与
term\u variables
列出变量的方式相同。是的,我想逻辑变量在这种情况下会更好——但我们正在做的大部分工作是符号操作,而不是求值。我需要它来自动检查Equisatisfability,以验证某些Tseytin实现的正确性。如果您的语义与Prolog的足够相似,您可以允许它为您执行提升操作。:)请使您的代码自包含,以便其他人可以实际尝试。抱歉,我在代码的其余部分进行了编辑。关于表示法的一条注释:您知道每个这样的列表正好有2个元素。在这种情况下,最好使用诸如
x=0
x=1
这样的术语来更简洁地表示绑定:
[x,0]
(x,.(0,[])
,为每个这样的结构浪费一个额外的函子
/2
和一个原子
[/code>。相反,
x=0
=(x,0)
,即只有一个函子和它的两个参数。不过,正如其他人所说的,您可以使用实际的逻辑变量来轻松地将绑定委托给Prolog。您可以存储符号/变量对应关系,而不是变量/值对应关系!
Jekejeke Prolog 2, Runtime Library 1.2.5
(c) 1985-2017, XLOG Technologies GmbH, Switzerland

?- negcase(_,N,F), norm(F,G), maze(G,[],L), 
   write(N), write(': '), sort(L,R), write(R), nl, fail; true.
Affirming a Disjunct: [pos(p),pos(q)]
Affirming the Consequent: [neg(p),pos(q)]
Commutation of Conditionals: [neg(p),pos(q)]
Denying a Conjunct: [neg(p),neg(q)]
Denying the Antecedent: [neg(p),pos(q)]
Improper Transposition: [neg(p),pos(q)]
?- time((between(1,1000,_), negcaseclp(_,N,F,L),
   sat(~F), once(labeling(L)), fail; true)).
% Up 296 ms, GC 3 ms, Thread Cpu 250 ms (Current 01/27/18 00:34:20)
Yes 
?- time((between(1,1000,_), negcase(_,_,F),
   norm(F,G), maze(G,[],_), fail; true)).
% Up 82 ms, GC 0 ms, Thread Cpu 78 ms (Current 01/27/18 00:30:21)
Yes