Prolog中的无限循环。如何防止这种情况发生?

时间:2016-11-18 20:40:08

标签: prolog

我正在Prolog中编写一个代表纸牌游戏规则的程序。但是,我正在使用以下代码进入无限循环。

succ(seven_of_hearts,eight_of_hearts).
succ(eight_of_hearts,nine_of_hearts).
succ(nine_of_hearts,ten_of_hearts).
succ(ten_of_hearts,jack_of_hearts).
succ(jack_of_hearts,queen_of_hearts).
succ(queen_of_hearts,king_of_hearts).
succ(king_of_hearts,ace_of_hearts).
succ(X,Y) :-
   succ(X,Z),
   succ(Z,Y),
   !.

beats(X,Y) :-
   succ(Y,X).

基本上,我尝试这几行是根据我建立的succ(或继承)关系建立一个系统,用于确定一张牌是否胜过另一张牌。所以我运行的查询是节拍(X,Y),其中X和Y以及与卡相对应的原子。如果为true,则此查询将成功终止。例如,如果我查询节拍(jack_of_hearts,seven_of_hearts),它将返回true并终止。

但是,如果查询为false,则查询将进入无限循环。例如,当我查询节拍(seven_of_hearts,jack_of_hearts)时。我跟踪查询并发现由于最后一个succ语句的递归性质,查询跟随succ语句链一直到seven_of_hearts,或一直到ace_of_hearts,然后不断尝试评估succ (seven_of_hearts,X)或succ(ace_of_hearts,X)而不是返回false。

我有两个问题:使用这个当前结构,我该如何防止这种情况?或者,如果那不可能,我可以用什么替代结构来实现我的目标?

编辑: 以下是我对其中一个失败查询的跟踪截图:

    Call: (267) beats(seven_of_hearts, jack_of_hearts) ? creep
Call: (268) succ(jack_of_hearts, seven_of_hearts) ? creep
   Call: (269) succ(jack_of_hearts, _G7104) ? creep
   Exit: (269) succ(jack_of_hearts, queen_of_hearts) ? creep
   Call: (269) succ(queen_of_hearts, seven_of_hearts) ? creep
   Call: (270) succ(queen_of_hearts, _G7104) ? creep
   Exit: (270) succ(queen_of_hearts, king_of_hearts) ? creep
   Call: (270) succ(king_of_hearts, seven_of_hearts) ? creep
   Call: (271) succ(king_of_hearts, _G7104) ? creep
   Exit: (271) succ(king_of_hearts, ace_of_hearts) ? creep
   Call: (271) succ(ace_of_hearts, seven_of_hearts) ? creep
   Call: (272) false ? creep
   Fail: (272) false ? creep
   Redo: (271) succ(ace_of_hearts, seven_of_hearts) ? creep
   Call: (272) succ(ace_of_hearts, _G7104) ? creep
   Call: (273) false ? creep
   Fail: (273) false ? creep
   Redo: (272) succ(ace_of_hearts, _G7104) ? creep
   Call: (273) succ(ace_of_hearts, _G7104) ? creep
   Call: (274) false ? creep
   Fail: (274) false ? creep
   Redo: (273) succ(ace_of_hearts, _G7104) ? creep
   Call: (274) succ(ace_of_hearts, _G7104) ? creep
   Call: (275) false ? creep

1 个答案:

答案 0 :(得分:1)

你的谓词显然一直在呼唤自己:succ(X, Y) :- succ(Y, X), ...。一个简单的解决方案是不要像使用事实那样为谓词使用相同的名称。摆脱你的succ/2谓词(留下事实),支持:

successor(X, Y) :- succ(X, Y).
successor(X, Y) :- succ(X, Z), succ(Z, Y).

beats(X, Y) :- successor(Y, X).