我在下面发布了这段代码。现在我想实现在这个序言树中失败的叶子上打印FAIL的函数。这基本上是元解释器,它使整个sld树以DOT格式存档。
prove_d(true,Goal,N,_):-!,
gv_answer(N,Goal). %writtes TRUE at the end of leaf
prove_d(_,_Goal,N,D):-
D=0, !, gv_stop(N). %writes ending brackets and closes file
prove_d((A,B),Goal,N,D):-!,
D>0, D1 is D-1,
resolve(A,C),
conj_append(C,B,E),
gv_node(N,(?-E),N1), %writes node and connects with parent node
prove_d(E,Goal,N1,D1).
prove_d(_,_Goal,N,D):- % HL
D=0, !, gv_stop(N).
prove_d(A,Goal,N,D):-
D>0, D1 is D-1,
resolve(A,B),
gv_node(N,(?-B),N1),
prove_d(B,Goal,N1,D1).
resolve(!, true):-
!, (true ; throw(cut)).
resolve(A,true):-
predicate_property(A,built_in),!,
call(A).
resolve(A,B):-
clause(A,B).
gv_fail(N0):- %where to place this?
gv_id(N), %gets id for parent node
writes([N,' [label="fail", shape=plaintext];']),
writes([N0,' -> ',N,' [style=dotted, length=0];']).
最接近解决方案的是
prove_d((A,B),Goal,N,D):-!,
D>0, D1 is D-1,
resolve(A,C),
conj_append(C,B,E),
gv_node(N,(?-E),N1),
(prove_d(E,Goal,N1,D1) ; gv_fail(N1)).
但是即使在叶子的末尾有true
,这个打印也会在每个叶子的末尾失败。
我使用swi-prolog。
编辑: 由于此代码的时间较长,因此这是完整的程序。http://pastebin.com/bQKD1Cyi
它的工作原理如下。您可以在prolog启动时查阅此文件。然后在其他文件中是您想要可视化的程序,因此您调用why/3
,然后它将DOT输出分离为文件。您可以使用此网站可视化DOT输出 - http://webgraphviz.com/
EDIT2: 这是我测试它的程序:
v(X):-p(X), s(X).
v(n).
p(a).
p(b).
s(a).
s(c).
唯一的解决方案是v(n)和s(a),但是在目标s(a),只有true
时,它会在叶子的末尾写fail
和true
应该在那里。
答案 0 :(得分:1)
该计划不完整。如果没有谓词gv_answer / 2,gv_stop / 1,gv_node / 3以及代码中没有包含的其他许多其他内容,我只能根据您对代码中缺少的内容进行部分回答。 我认为你需要在你的prove_d / 3谓词中使用一个新的子句,最后一个,如果另一个失败,它将成功。此外,您必须修改最后一个子句prove_d / 3,以避免新子句的回溯。 因此,谓词prove_d / 3将是这样的:
prove_d(true,Goal,N,_):-!,
gv_answer(N,Goal). %writtes TRUE at the end of leaf
prove_d(_,_Goal,N,D):-
D=0, !, gv_stop(N). %writes ending brackets and closes file
prove_d((A,B),Goal,N,D):-!,
D>0, D1 is D-1,
resolve(A,C),
conj_append(C,B,E),
gv_node(N,(?-E),N1), %writes node and connects with parent node
prove_d(E,Goal,N1,D1).
prove_d(_,_Goal,N,D):- % HL
D=0, !, gv_stop(N).
prove_d(A,Goal,N,D):-
D>0,!, D1 is D-1,
resolve(A,B),
gv_node(N,(?-B),N1),
prove_d(B,Goal,N1,D1).
prove_d(_,_,N,_):- gv_fail(N).
我尝试了这个谓词(保存在文件multiply.pl中):
%Multiply members of a list
multiply([X], X):-!.
multiply([H|T], X):-multiply(T, M), X is M *H.
和这个目标:
?- why(multiply([1,2,3],X), './sldtree.pl', './multiply.pl').
SLD树看起来不错。只有一个成功,并且显示失败的叶子是因为Prolog无法在这些条件上进行回溯。 也许问题出在您的输入程序中,或者生成的SLD树超过了默认深度(10级),在这种情况下,您永远不会看到成功。