在Prolog中找到无限循环的原因

时间:2013-04-29 06:11:55

标签: debugging loops prolog infinite

我很遗憾地问这个问题是愚蠢的,但是我被困住了,我不确定是什么导致了这个问题。这是一个存储桶问题,该计划应该找到一条路径,使用一个4加仑的桶和一个3加仑的桶来填充一个正好2加仑的桶。

我在Swipl中使用了trace,发现它在桶填充和桶清空子句(前4个谓词)中无限循环问题是我不确定为什么会这样做。

它可能是愚蠢的东西,我没有得到的东西,但如果有人能指出我正确的方向或用一堆砖块给我一些感觉,我会非常感激。

抱歉浪费你的时间。

 :-dynamic bucket/4.

 printIt([]).
 printIt([X,Y|Xs]) :-write("bucket("),write(X),write(Y), write(")"), printIt(Xs).

 go(X,Y) :- bucket(0,0,[0,0],X,Y),printIt([X,Y]).

 /*tests if we have been to this state before*/
 memPairs(X,Y,[X,Y|_]).
 memPairs(X,Y, [_,_|Tail]) :- memPairs(X,Y,Tail).

/*Fill the first bucket*/
bucket(X,Y,T,G1,G2) :- X<4,not(memPairs(4,Y,T)),bucket(4,Y,[4,Y|T],G1,G2).
/*fill the second bucket*/
bucket(X,Y,T,G1,G2) :- Y<3,not(memPairs(X,3,T)),bucket(X,3,[X,3|T],G1,G2).
/*if X is full and Y is not, then empty X*/
/* if X+Y is greater than or equal to 4 then fill Y from X*/
bucket(X,Y,T,G1,G2) :- (X+Y) >= 4, X>0, Z is (Y-(4-X)),not(memPairs(4,Z,T)),bucket(4,Z,[4,Z|T],G1,G2).
/*if X+Y is greater than or equal to 3, then fill X from Y*/
bucket(X,Y,T,G1,G2) :- (X+Y) >=3, Z is (X-(3-Y)), Y>0, not(memPairs(Z,3,T)),bucket(Z,3,[Z,3|T],G1,G2).
/* if it is less, then empty Y */
bucket(X,Y,T,G1,G2) :-(X+Y) =< 3,Z is (X + Y), X>0,not(memPairs(Z,0,[T])),bucket(Z,0,[Z,0|T],G1,G2).
/*if it is less than 4, empty X*/
bucket(X,Y,T,G1,G2) :-(X+Y) =< 4, Y>0, Z is (X + Y),not(memPairs(0,Z,[T])),bucket(0,Z,[0,Z|T],G1,G2).
bucket(4,Y,T,G1,G2) :- not(memPairs(0,Y,T)),bucket(0,Y,[0,Y|T],G1,G2).
/*if Y is full and X is not, then empty Y*/
bucket(X,3,T,G1,G2) :-not(memPairs(X,0,T)),bucket(X,0,[X,0|T],G1,G2).

bucket(X,2,T,G1,G2) :- not(memPairs(X,Y,[T])), bucket(2,X,[X,Y|T],G1,G2).
bucket(2,Y,T,G1,G2) :- not(memPairs(2,Y,[T])),G1,G2.

作为注释,桶谓词从0,0(空桶)开始并尝试到达(2,0),同时它正在检查以前的状态列表以确保它不存在之前。实际上,它可能是memPair的错误(一个自定义谓词来检查一对值(这种情况下的先前状态是否在列表中)。但树证明似乎证明我错了。

1 个答案:

答案 0 :(得分:2)

您还没有使用更简单的表示来解决此问题,然后您的算法应该更加复杂。因此,乍看之下我可以发现一些问题 - 但我不确定纠正它们会使你的程序运行。

  • 你不总是将相同的模式传递给memPairs并递归调用存储桶,例如not(memPairs(X,Z,T)),bucket(4,Z,[4,Z|T],G1,G2).
  • not(memPairs(Z,0,[T]))应为not(memPairs(Z,0,T))

另请注意:- dynamic bucket/4.声明无用。

编辑我建议以更多类似Prolog的方式重新编写程序:使用进行配对:这里有一个工作样本

go(Actions) :- buckets([0-0], Actions).

buckets(Actions, Actions) :- Actions = [2-_|_] ; Actions = [_-2|_].
buckets([Buckets|SoFar], Steps) :-
    action(Buckets, Updated),
    \+ memberchk(Updated, SoFar),
    buckets([Updated,Buckets|SoFar], Steps).

action(B1-B2, C1-C2) :-
    B1 = 0, C1 =  3, C2 = B2 ; % fill Bucket 1
    B2 = 0, C2 =  4, C1 = B1 ; % fill Bucket 2
    B1 > 0, C1 =  0, C2 = B2 ; % empty Bucket 1
    B2 > 0, C2 =  0, C1 = B1 ; % empty Bucket 2
    B1 > 0, B2 < 4, T is min(B1, 4 - B2), C1 is B1 - T, C2 is B2 + T ; % pour Bucket 1 to 2
    B2 > 0, B1 < 3, T is min(B2, 3 - B1), C2 is B2 - T, C1 is B1 + T . % pour Bucket 2 to 1

编辑在析区周围有无用的括号,现在已被删除。