Prolog 二项式系数
为什么它返回false 任务是:编写递归过程Prolog 二项式系数,prolog,binomial-coefficients,swi-prolog-for-sharing,Prolog,Binomial Coefficients,Swi Prolog For Sharing,为什么它返回false 任务是:编写递归过程C(M,N)(0≤ M≤ n)使用此公式计算二项式系数: bc(0,N,R,R):- N>0,R is 1,!. bc(M,0,R,R):- M>0,R is 1,!. bc(N,N,R,R):- R is 1,!. bc(M,N,R,R1):- M1 is M - 1, N1 is N - 1, bc(M1,N1,R,R2), bc(M1,N,R,R3), R1 is R2+R3. 附言:我
C(M,N)(0≤ M≤ n)
使用此公式计算二项式系数:
bc(0,N,R,R):- N>0,R is 1,!.
bc(M,0,R,R):- M>0,R is 1,!.
bc(N,N,R,R):- R is 1,!.
bc(M,N,R,R1):-
M1 is M - 1,
N1 is N - 1,
bc(M1,N1,R,R2),
bc(M1,N,R,R3),
R1 is R2+R3.
附言:我使用在线编译器SWISH。首先,让我们正确说明二项式系数的公式。
c(M,N)
的常规定义是M>=N>=0
,而不是如上所述的N>=M>=0
。这一点很重要,因为给出的公式如下:
C(m,0)=C(0,n)=C(n,n)=1c(m,n)=C(m−1,n−1) +C(m)−1,n)
假设0≤ N≤ m
,不是所述内容(0≤ M≤ n
)。所以它是不正确的(要么是给出的不正确,要么是你写的不正确)。此外,C(0,n)
不是有效的系数,除非n=0
。因此,这种情况没有意义,可以省略。它已经被C(m,0)
所覆盖
问题的不正确表述可能是导致结果“错误”的主要原因
C(n,0)=C(n,n)=1
将包含在以下基本(非递归)情况中:
然后根据给定公式递归处理更一般的情况:
bc(N, 0, 1) :- N #>= 0.
bc(N, N, 1) :- N #> 0. % The N = 0 case is already covered in the first base case
编写Prolog谓词时的几个原则:
- 确保你的问题陈述准确无误。这听起来很明显,但在本案中是个问题
- 使用CLP(FD)进行整数推理。Prolog所涉及的是更多的关系。使用
更为必要。例如,如果is/2
未绑定,Y
将生成实例化错误。但是X是Y*2
将产生潜在的解决方案。如果由于任意要求而必须使用X#=Y*2
,则可以将其替换回中is/2
- 在谓词子句中应用使它们相互排斥的约束。也就是说,除非它是您想要的,否则对于给定的解决方案,不要允许谓词以多种方式成功。特别是,使你的不同条款不重叠。例如,如果您有一个谓词,其中第一个参数是一个自然数(非负整数),并且基本情况是
,那么在递归情况下foo(0,1)。
您需要一个约束foo(N,R):-
或N>0
,假设在递归情况下没有其他可能需要和/或不同的副作用或其他参数N#>0
- 在所需的解决方案空间中约束或绑定变量的次数越多,代码就越不会偏离尝试无效解决方案的选项,并且在最坏的情况下,不会因为缺少对此类非解决方案选项的绑定而终止。例如,在这个问题中,我们添加了约束
,这在R#>=M
和N>0
时是正确的。如果没有这个约束,Prolog将探索N
无限的情况,在某些情况下会导致不终止R
bc(M, N, R) :-
N #> 0, % The N = 0 case is already covered in the first base case
M #> N, % The M = N case is already covered in the second base case
R #>= M, % This constraint prevents unbounded search in non-solution space
M1 #= M - 1, % The rest of this is just the given formula
N1 #= N - 1,
bc(M1, N1, R1),
bc(M1, N, R2),
R #= R1 + R2.
等等
通过使用CLP(FD)运算符,您还可以运行如下查询:
| ?- bc(3,2,R).
R = 3 ? ;
no
| ?- bc(4,2,R).
R = 6 ? ;
no
| ?-
而且
| ?- bc(4,X,6).
X = 2 ? ;
no
| ?-
为什么需要4个参数?第四个似乎是多余的,可能会给你带来麻烦。把它扔掉。您的
bc(N,N,…)
案例应该具有条件N>0
,这样它的真值就不会与其他两个基本案例重叠。而bc(M,N,…)
应该具有M>N
的条件,因为这就是这种情况的目的。如果你的条件设置正确,你就不需要削减。你能用自己的话解释一下为什么你认为上述尝试会产生正确的结果吗?您运行的查询是什么?bc(2,4,RES,0),从那里开始:M=2,N=4,Result,每个结果。我需要计算一个参数为M的二项式系数,您的代码中有两个输入错误:目标N>0
和M>N
。使用这些示例查询?-bc(4,X,6)。
会导致实例化错误。你的意思可能是N#>0
和M#>N
。此外,如果在递归目标之前添加目标R#>=M
,则类似?-bc(X,2,15)的查询将终止。如果你看帕斯卡三角形,系数要么是1
(由你的事实覆盖)要么是R
,那么它出现的最后一行是与R
在第二个和倒数第二个位置选择N
。-)@谢谢你!我没有用我最新的“补丁”更新我的帖子,所以谢谢你抓到它们。我在比我展示的代码更晚的代码上运行了我的示例。我感觉到了你,因为我自己也容易发生这样的灾难:-)
| ?- bc(4,X,6).
X = 2 ? ;
no
| ?-
| ?- bc(N, K, 6).
N = 6
K = 1 ? ;
N = 4
K = 2 ? ;
N = 6
K = 5 ? ;
no
| ?- ;