【问题标题】:prolog - recursive predicate sum(J,K,N)prolog - 递归谓词总和(J,K,N)
【发布时间】:2020-03-08 00:10:19
【问题描述】:

我正在尝试解决“Prolog Programming In Depth”一书中的练习。

定义一个递归谓词 sum(J,K,N),将 N 实例化为 J 中的整数的 sum K 包括在内:

?- sum(-1,1,What).
What = 0
?- sum(1,3,What).
What = 6
?- sum(6,7,What).
What = 13

我的谓词在下面。

sum(J, K, N) :- sum_iter(J, K, N, J, 0).   % clause_1

sum_iter(J, K, N, I, S) :-                 % clause_2
  Kn is K+1,                               % clause_X
  I = Kn,
  N = S,!.

sum_iter(J, K, N, I, S) :-     % clause_2, I - index, S - SumTmp
  I =< K,
  NewI is I+1,
  NewS is S+I,
  sum_iter(J, K, N, NewI, NewS).

它工作正常,但我不明白:

  • 为什么我应该使用clause_X(为什么+1)
  • 以及为什么我不能将条款_2 替换为

sum_iter(J, K, N, K, N) :- !.

在这种情况下,谓词停止上一步的工作。 例如,期望:

?- sum(1,3,What).
What = 6

但是 Prolog 输出:

?- sum(1,3,What).
What = 3

【问题讨论】:

  • 其实clause_2不是这个谓词的第二个子句。请注意,您创建了两个谓词 sumsum_iter

标签: recursion sum prolog


【解决方案1】:

打印出一些状态:

sum(J, K, N) :- sum_iter(J, K, N, J, 0).

% the rule at the end of the recursion

sum_iter(J, K, N, I, S) :-
  format("rule 1: J=~w K=~w N=~w I=~w S=~w\n", [J, K, N, I, S]),
  Kn is K+1,
  I = Kn,
  format("...pos 1 passed\n"),
  N = S,
  format("...pos 2 passed\n"),
  !.

% the rule perfoming the recursion

sum_iter(J, K, N, I, S) :-
  format("rule 2: J=~w K=~w N=~w I=~w S=~w\n", [J, K, N, I, S]),
  I =< K,
  format("...pos 3 passed\n"),
  NewI is I+1,
  NewS is S+I,
  sum_iter(J, K, N, NewI, NewS).
?- sum(1,3,What).
rule 1: J=1 K=3 N=_11338 I=1 S=0
rule 2: J=1 K=3 N=_11338 I=1 S=0
...pos 3 passed
rule 1: J=1 K=3 N=_11338 I=2 S=1
rule 2: J=1 K=3 N=_11338 I=2 S=1
...pos 3 passed
rule 1: J=1 K=3 N=_11338 I=3 S=3
rule 2: J=1 K=3 N=_11338 I=3 S=3
...pos 3 passed
rule 1: J=1 K=3 N=_11338 I=4 S=6
...pos 1 passed
...pos 2 passed
What = 6.

最后,I = Kn 变成了一个测试:IKn 都是 设置为实际值,I 一个“结束”。

你可以这样做,使用 I &gt; K "guard":

sum_iter(_, K, Res, I, Res) :- I > K,!.

但你也想这样做:

  • 如果适用,默认调用递归规则。
  • 如果不是,调用“递归结束规则”。

所以重新排列是最好的:

sum(J, K, N) :- sum_iter(J, K, N, J, 0).


% the rule perfoming the recursion, with a guard "I =< K", which, once
% successful, commits the computation to this one rule, so we add "!"

sum_iter(J, K, N, I, S) :-
  format("rule 2: J=~w K=~w N=~w I=~w S=~w\n", [J, K, N, I, S]),
  I =< K,!, 
  format("...pos 3 passed\n"),
  NewI is I+1,
  NewS is S+I,
  sum_iter(J, K, N, NewI, NewS).

% the rule at the end of the recursion, also with guard:

sum_iter(J, K, Res, I, Res) :-
  format("end: J=~w K=~w I=~w Res=~w\n", [J, K, I, Res]),
  I > K,!.

其实第二个中的“cut”是没有必要的 规则,因为它最后一条规则。没有必要 守卫在这种情况下,这只是守卫的否定 第一条规则。但为了清楚起见,让我们将两者都保留。

?- sum(1,3,What).
rule 2: J=1 K=3 N=_15630 I=1 S=0
...pos 3 passed
rule 2: J=1 K=3 N=_15630 I=2 S=1
...pos 3 passed
rule 2: J=1 K=3 N=_15630 I=3 S=3
...pos 3 passed
rule 2: J=1 K=3 N=_15630 I=4 S=6
end: J=1 K=3 I=4 Res=6
What = 6.

【讨论】:

    猜你喜欢
    • 2018-10-09
    • 1970-01-01
    • 1970-01-01
    • 2011-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-08
    相关资源
    最近更新 更多