在没有解决方案的情况下在sld树上写入FAIL

时间:2015-03-09 17:51:57

标签: prolog

我在下面发布了这段代码。现在我想实现在这个序言树中失败的叶子上打印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时,它会在叶子的末尾写failtrue应该在那里。

1 个答案:

答案 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级),在这种情况下,您永远不会看到成功。