Prolog代码错误

时间:2014-03-22 13:08:17

标签: prolog

我的代码应输出竞争计划,谓词scheduleround2用于生成game(player1,player2,round)列表。 但是,对于Z的统一,最有可能出现错误。

这是代码:

示例输入:

schedule_round([player(alex,2), player(jane,5), player(djokovich,1), player(nadal,3), player(anderson,4), player(jack,6), player(nilson,7), player(pete,8)], R).

,输出应为

R=[game(pete,djokovich,quarter_final), game(nilson,alex,quarter_final), game(jack,nadal,quarter_final), game(jack,jane,quarter_final)]

实际发生的事情就是计算永远不会产生任何东西

%gets the maximum player rating 
maxf([H|T], R) :- maximum(T, H, R).

maximum([], R, R).
maximum([player(X,Y)|T], player(_,R), F) :-
    Y > R,
    maximum(T, player(X,Y), F).
maximum([player(_,Y)|T], player(Z,R), F) :-
    R > Y,
    maximum(T, player(Z,R), F).

%gets the minimum player rating
minf([H|T], R) :- minimum(T, H, R).

minimum([], R, R).
minimum([player(X,Y)|T], player(_,R), F):-
    Y < R,
    minimum(T, player(X,Y), F).
minimum([player(_,Y)|T], player(Z,R), F):-
    R < Y,
    minimum(T, player(Z,R), F).

%removes players who are scheduled from the list
del(X, [X|L], L).
del(X, [A|L], [A|L1]) :- del(X, L, L1).

%gets size of the list
size([], 0).
size([_|T], N) :- size(T, M), N is M+1.

%scheduling predicate
schedule_round(X, R) :-
    size(X, N),
    schedule_round2(N, X, R).

%helper
schedule_round2(0, _, []).
schedule_round2(N, H, Z) :-
    N2 is N-2,
    maxf(H, F),
    minf(H, B),
    del(F, H, L),
    del(B, L, J),
    append(Z, game(F, B, quarter_final), K), 
    schedule_round2(N2, J, K).

1 个答案:

答案 0 :(得分:0)

schedule_round的定义存在一些问题。

终止案例schedule_round(0, _, []).失败,因为对schedule_round的递归调用中的第三个参数始终是非空列表。另外,我原来的append/3声明确实是个问题。由于您的第二个参数不是列表而且应该是[game(F, B, quarter_final)]而不仅仅是game(F, B, quarter_final),因此它将在第一次出现后失败。当append失败时,schedule_round代码会回溯其他谓词查询,提出另一种可能的解决方案,并再次无效append失败。另外,什么被附加到翻转的东西。我们希望对schedule_round2的递归调用是任何给定调用的解决方案的尾部,因此新元素会在当前调用中为尾部提供新解决方案。

所以“快速修复”只是将schedule_round2递归子句改为:

schedule_round2(N, H, Z) :-
    N2 is N-2,
    maxf(H, F),
    minf(H, B),
    del(F, H, L),
    del(B, L, J),
    append([game(F, B, quarter_final)], K, Z),
    schedule_round2(N2, J, K).

这样可行,但事实证明您不需要append/3,因为append([X], In, Out)Out = [X|List]相同。我们可以将其减少为:

%helper
schedule_round2(0, _, []).
schedule_round2(N, H, [game(F,B,quater_final)|Z]) :-
    N > 1,              % This ensures N2 won't go negative due to bad input
    N2 is N-2,
    maxf(H, F),
    minf(H, B),
    del(F, H, L),
    del(B, L, J),
    schedule_round2(N2, J, Z).  % Schedule round for rest of the list

此版本将使用第三个参数(解决方案的尾部)递归到schedule_round2未实例化,直到它到达基本子句。此时,第三个参数(解决方案尾部)将实例化为[]并将您的解决方案回滚到递归返回的所需结果。

以下是一些其他可选的建议更改:

(1)您的minimummaximum假设比较的值永远不会相等。也许情况就是这样。但你可能会考虑:

maximum([player(_,Y)|T], player(Z,R), F) :-
    R >= Y,
    ...

minimum([player(_,Y)|T], player(Z,R), F):-
    R =< Y,
    ...

(2)在schedule_round2/3我添加了对N > 1的检查。如果你总是给它一个偶数奇偶校验列表(这是预期的)是没有必要的,但是如果你确实给它一个奇数奇偶校验列表,它将导致谓词优雅地失败而不是在负N上递归很长一段时间。

(3)由于Prolog已提供列表长度谓词size/2,因此您的length/2谓词是不必要的。