【问题标题】:Walking through the recursive factorial program in Prolog?遍历 Prolog 中的递归阶乘程序?
【发布时间】:2014-12-06 18:44:35
【问题描述】:

我真的很难理解递归在 Prolog 中的工作原理。

factorial(0,1).   
factorial(N,F) :-  
   N>0, 
   N1 is N-1, 
   factorial(N1,F1), 
   F is N * F1.

我知道第一部分是基本情况,这将结束程序的继续。但是,让我感到困惑的是第二个阶乘调用(N1,F1)的参数。有人能解释一下一切是如何执行和计算的吗?

【问题讨论】:

  • 步行通常不是理想的方法:而是阅读规则right-to-left。请参考我之前的回答。

标签: recursion prolog factorial


【解决方案1】:

第二条规则基本上说FN的阶乘如果N大于零并且有一个数字N1N-1 的结果F1N1的阶乘 FNF1的乘积。

示例

假设你想找到 3 的阶乘。

-? factorial(3,F).

Prolog 将factorial(3,F) 放在目标堆栈中,然后查找与第一个目标匹配的规则。 factorial/2 有两条规则(factorial(0,1) 可以看作是一条没有body 的规则),但是对于第一个0 和5 不统一所以不能使用。第二个与 N 被实例化为 5 相结合,Prolog 将条件添加到堆栈中,变为:

3 > 0, N1 is 3-1, factorial(N1,F1), F is 3*F1

第一个目标得到满足,因为 3 大于零。第二个是通过将N1 绑定到3-1 的算术评估结果来满足的,因此现在的目标堆栈是:

factorial(2,F1), F is 3*F1

再次,Prolog 寻找可能用于满足 factorial(2,F1) 的规则并使用第二个规则(N 与 2 统一,FF1 统一,变量使用不同的名称):

2 > 0, N2 is 2-1, factorial(N2,F2), F1 is 2*F2, F is 3*F1

接下来,2 > 0 为真,N22-1 的算术结果统一,因此目标堆栈变为:

factorial(1,F2), F1 is 2*F2, F is 3*F1

factorial/2再次使用第二条规则:

1 > 0, N3 is 1-1, factorial(N3,F3), F2 is 1*F3, F1 is 2*F2, F is 3*F1

N3 变为零(满足N3 is 1-1 时):

factorial(0,F3), F2 is 1 * F3, F1 is 2*F2, F is 3*F1

此时,factorial/2 的第一条规则可以用来满足factorial(0, F3),但是由于可以使用的规则更多,所以创建了一个选择点。因此,factorial(0,F3) 通过将F3 实例化为 1 成功。

F2 is 1 * 1, F1 is 2 * F2, F is 3 * F3

通过满足堆栈中剩余的所有目标,F 变为 6,您将获得第一个解决方案。但是,factorial(0, F3) 有一个选择点。此时可以使用第二条规则:

0>0, N4 is 0-1, factorial(N4,F4), F3 is 0*F4, F2 is 1*F3, F1 is 2*F2, F is 3*F3

但是0>0 失败并且执行停止,因为没有其他选择指向回溯。

您可以通过使用 [green] 剪切运算符来避免为 factorial(0,_) 留下无用的选择点。

factorial(0, 1) :- !.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-20
    • 2019-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-28
    • 2015-04-19
    相关资源
    最近更新 更多