Prolog sld树叶上的写入失败,无解决方案

Prolog sld树叶上的写入失败,无解决方案,prolog,Prolog,我把这段代码贴在下面。现在我想实现在这个prolog树中失败的叶子上打印FAIL的函数。这基本上是元解释器,它将整个sld树以点格式转换为文件 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(

我把这段代码贴在下面。现在我想实现在这个prolog树中失败的叶子上打印FAIL的函数。这基本上是元解释器,它将整个sld树以点格式转换为文件

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

编辑: 因为这段代码稍长,所以这里是完整的程序

它是这样工作的。您可以在prolog启动时查阅此文件。然后在另一个文件中是您想要可视化的程序,所以您调用
为什么/3
,然后它将点输出到单独的文件中。您可以使用此网站可视化点输出-

编辑2: 这是我的测试程序:

v(X):-p(X), s(X).
v(n).

p(a).
p(b).

s(a).
s(c).

唯一的解决方案是v(n)和s(a),但在目标s(a)中,当只有
true
应该存在时,它在叶的末尾写入
true
fail

程序不完整。如果没有谓词gv_-answer/2、gv_-stop/1、gv_-node/3以及代码中没有包含的其他谓词,我只能给出部分答案,这是基于我对代码中缺少的内容的理解。 我认为你需要在prove_d/3谓词中添加一个新子句,即最后一个子句,如果另一个子句失败,它将成功。此外,您必须修改最后一个子句prove_d/3,以避免新子句的回溯。 因此,谓词proveu 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中):

这个目标是:

?- why(multiply([1,2,3],X), './sldtree.pl', './multiply.pl').
SLD树在我看来还不错。只有一个成功,而显示的leaf失败是因为Prolog无法在这些条件下进行回溯。
可能问题出在您的输入程序中,或者生成的SLD树超过了默认深度(10级),在这种情况下,您将永远看不到成功。

您能否举例说明如何查阅此程序?首先,@false我考虑了我之前的问题。在检查了跟踪后,我发现我似乎以某种方式阻止了这一次的回溯。我尝试了几种解决方案,比如抛出异常并捕获它们,在最后剪切或添加另一个谓词
prove_d/3
,但它仍然打印出
fail
不应该打印的地方。嘿,现在,我需要一个prolog元解释器,它可以生成查询的SLD树。我发现了这篇文章,当时我正准备创建一篇自己的文章。我想问一下你们的解释器现在是否已经完成了,我是否可以使用它。我的元解释器被窃听了。切割处理非常糟糕,有些叶片每个叶片产生2次失败,有时叶片结束时没有正确或错误。还有兴趣吗?我编辑了我的问题。我也在考虑类似的东西,但可能是由于
sld/4
的失败驱动循环,它不起作用。“它只会让几乎每一片叶子都失败。”Đrakenus我用一个简单的程序测试了这个程序,看起来还可以。我在回答的最后添加了一些细节,所以你可以使用相同的例子。谢谢,我真的很感谢你的工作。也许我不知道如何制作SLD树。但我试着做的是,它应该只在不正确的leaf末尾写fail。所以在乘法/2中不应该有任何失败。
?- why(multiply([1,2,3],X), './sldtree.pl', './multiply.pl').