二项式系数[Prolog]

时间:2017-11-09 23:51:07

标签: prolog binomial-coefficients

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.

为什么会返回false?

任务是:编写递归过程C(M,N) (0 ≤ m ≤ n )以使用此公式找出二项式系数:

C(m,0)=C(0,n)=C(n,n)=1
C(m,n)=C(m−1,n−1)+C(m−1,n)

P.S。:我使用在线编译器SWISH。

1 个答案:

答案 0 :(得分:4)

首先,让我们正确地说明二项式系数的公式。 c(M, N)的传统定义将M >= N >= 0,而不是N >= M >= 0。这很重要,因为给出了公式:

  

C(m,0)=C(0,n)=C(n,n)=1 C(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

然后根据给定的公式递归处理更一般的情况:

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.

编写Prolog谓词时的一些原则:

  • 确保准确无误地说明您的问题。这听起来很明显,但在这种情况下是一个问题。

  • 使用CLP(FD)进行整数推理。这是Prolog所关注的更多关系。使用is/2更多是命令式。例如,如果X is Y * 2未绑定,Y将生成实例化错误。但X #= Y * 2会产生潜在的解决方案。如果由于任意要求而必须使用is/2,则可以将其替换回来。

  • 在谓词子句中应用约束,使它们互斥。也就是说,除非它是您想要的,否则不要让您的谓词对于给定的解决方案获得多种方式。特别是,使您的不同子句不重叠。例如,如果你有一个谓词,其中第一个参数是一个自然数(非负整数),并且你的基本情况是foo(0, 1).,那么在你的递归情况foo(N, R) :-中你需要约束N > 0N #> 0,假设在递归情况下没有其他可能需要和/或不同的副作用或其他参数。

  • 您可以在解决方案空间内约束或绑定变量的次数越多,您的代码就会越少尝试不是有效解决方案的选项,并且在最坏的情况下,由于缺少绑定而不会终止关于这种非解决方案的选择。例如,在此问题中,我们添加了约束R #>= M,该约束在N > 0N < M时为真。如果没有这个约束,Prolog将探索R < M无限的情况,并在某些情况下导致无终止。

运行查询:

| ?- bc(3,2,R).

R = 3 ? ;

no
| ?- bc(4,2,R).

R = 6 ? ;

no
| ?-

等等...

通过使用CLP(FD)运算符,您还可以运行如下查询:

| ?- bc(4,X,6).

X = 2 ? ;

no
| ?-

和...

| ?- bc(N, K, 6).

N = 6
K = 1 ? ;

N = 4
K = 2 ? ;

N = 6
K = 5 ? ;

no
| ?- ;