【问题标题】:Prolog Infinite loop on circular factsProlog关于循环事实的无限循环
【发布时间】:2019-04-17 00:57:02
【问题描述】:

这是我事实的循环部分(定义人与人之间的关系):

connection(harry, ron).
connection(ron, harry).
connection(hermione, harry).

我想知道是否存在直接或通过其他人使用递归的连接。

这段代码在上述情况下会陷入死循环:

connected(A, B) :-
   connection(A, B).
connected(A, B) :- 
   connection(A, C),
   connected(C, B).

我希望递归在遇到以前的搜索时停止。 例如:

?- connected(hermione, X).
X = harry ;
X = ron.

谢谢!

【问题讨论】:

    标签: prolog transitive-closure failure-slice


    【解决方案1】:

    Prolog 的执行机制非常不直观。它将递归(正如您从其他语言中知道的那样)与回溯相结合。但有一个很好的出路。您可以考虑使用更小的程序来代替原来的程序。

    为了更好地理解实际的循环,这里是称为 的最小程序片段,它是不终止的原因。其中有一些额外的虚假:一些目标false。有了这些目标,推理的数量就会减少(或保持不变)。因此,当生成的程序循环时,这也是您的原始程序循环的原因。

    连接(哈利,罗恩)。
    连接(罗恩,哈利)。
    connection(herminone, harry) :- false已连接(A,B):- false,连接(A,B)。
    已连接(A,B):-
        连接(A,C),
        连接(C,B),。
    
    ?- 连接(A,B)。

    查询仍然循环。请注意,当询问合适的人(我想你知道谁)时,它会失败(因此终止):

    ?- connected(tom, B).
       false.
    

    要解决这个问题,最简单的方法是像这样使用closure/3

    connected(A, B) :-
       closure(connection, A, B).
    

    【讨论】:

    • 你真的很喜欢你的昵称,不是吗? ;-)
    • Falsework我只学到了很多recently
    • 这很有帮助。
    【解决方案2】:

    你可以试试桌子。许多 Prolog 系统都有 table/1 指令。您只需将它放在要制表的谓词之前。

    :- table connected/2.
    connected(A, B) :-
       connection(A, B).
    connected(A, B) :- 
       connection(A, C),
       connected(C, B).
    

    如果您随后运行查询,递归将自动停止。以下是使用 SWI-Prolog 表运行的示例:

    Welcome to SWI-Prolog (threaded, 64 bits, version 8.1.4)
    
    ?- connected(hermione, X).
    X = harry ;
    X = ron.
    

    【讨论】:

    • 对于 SWI-Prolog::- use_module(library(tabling)). :- table connected/2, connection/2.
    • connection/2 已经是一个表,所以你不需要表它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多