Prolog无限循环循环事实
Prolog Infinite loop on circular facts
这是我的循环部分(定义人与人之间的关系):
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 的执行机制非常不直观。它将递归(正如您从其他语言中了解到的那样)与回溯相结合。但是有一个很好的出路。您可以考虑使用更小的程序来代替原来的程序。
为了更好地理解实际的循环,这里是称为 failure-slice 的最小程序片段,它是未终止的原因。其中有一些额外的伪造:一些目标 false
。有了这些目标,推理的数量就会减少(或保持不变)。因此,当生成的程序循环时,这也是您的原始程序循环的原因。
connection(harry, ron).
connection(ron, harry).
connection(herminone, harry) :- false.
connected(A, B) :- false, connection(A, B).
connected(A, B) :-
connection(A, C),
connected(C, B), false.
?- connected(A, B).
查询仍在循环。请注意,当询问合适的人(我想你知道是谁)时,它会失败(并因此终止):
?- connected(tom, B).
false.
要解决这个问题,最简单的方法是像这样使用closure/3
:
connected(A, B) :-
closure(connection, A, B).
您可以尝试制表。许多 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.
这是我的循环部分(定义人与人之间的关系):
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 的执行机制非常不直观。它将递归(正如您从其他语言中了解到的那样)与回溯相结合。但是有一个很好的出路。您可以考虑使用更小的程序来代替原来的程序。
为了更好地理解实际的循环,这里是称为 failure-slice 的最小程序片段,它是未终止的原因。其中有一些额外的伪造:一些目标 false
。有了这些目标,推理的数量就会减少(或保持不变)。因此,当生成的程序循环时,这也是您的原始程序循环的原因。
connection(harry, ron). connection(ron, harry).connection(herminone, harry) :- false.connected(A, B) :- false, connection(A, B). connected(A, B) :- connection(A, C), connected(C, B), false. ?- connected(A, B).
查询仍在循环。请注意,当询问合适的人(我想你知道是谁)时,它会失败(并因此终止):
?- connected(tom, B).
false.
要解决这个问题,最简单的方法是像这样使用closure/3
:
connected(A, B) :-
closure(connection, A, B).
您可以尝试制表。许多 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.