如何让Prolog的OR运算符在首个谓词为真时停止后续检查?
Prolog避免反向border重复检查的解决方案
方法1:用cut(!)阻断回溯
直接在border(X,Y)匹配成功后切断回溯,让Prolog不再尝试分号后的border(Y,X)分支:
border(de, fr). neighbor(X, Y) :- border(X, Y), !; border(Y, X).
只要border(X,Y)能匹配到事实,!就会阻止后续回溯,直接返回结果;只有当border(X,Y)匹配失败时,才会去尝试反向的border(Y,X)。
方法2:给border添加有序约束
统一规定border/2的事实只存储参数字典序更小在前的条目,比如de的字典序小于fr,所以只存border(de, fr),然后通过neighbor处理两种方向:
border(de, fr). neighbor(X, Y) :- border(X, Y). neighbor(X, Y) :- border(Y, X).
如果想更严谨,还可以加一个辅助谓词确保事实的有序性,避免误加反向事实:
border(de, fr). % 确保X字典序小于Y的border事实 ordered_border(X, Y) :- border(X, Y), @<(X, Y). neighbor(X, Y) :- ordered_border(X, Y). neighbor(X, Y) :- ordered_border(Y, X).
这种方式从根源上避免了重复事实,也不会出现无限循环。
为什么递归定义会无限循环
你之前尝试的border(X, Y) :- border(Y, X).会触发无限递归:查询border(fr, de)时,Prolog会调用border(de, fr),而border(de, fr)又会递归调用border(fr, de),如此反复陷入死循环,所以这种方式不可行。
内容的提问来源于stack exchange,提问作者capyman1701
相关产品推荐
相关产品推荐

