通过“ for循环”定义Maple中的递归关系

时间:2018-10-25 12:56:42

标签: recursion maple

我正在尝试通过Maple中的“ for循环”建立一个递归关系。假设我们有两个序列M[i](x)N[i](x),其中N[0](x)=x^2M[i](x)=N[i-1](x)+1N[i](x)=M[i](x)+2。所以我尝试了这段代码:

N[0] := proc (x) options operator, arrow; x^2 end proc;
for i to 3 do M[i] := proc (x) options operator, arrow; N[i-1](x)+1 end proc; N[i] := proc (x) options operator, arrow; M[i](x)+2 end proc end do;

但是它没有给出正确的答案(例如N[1](x)必须为x^2+3)。顺便说一下,由于某些原因,我必须通过映射x来定义函数。反正有修改此代码吗?

1 个答案:

答案 0 :(得分:1)

rsolve命令可以轻松处理此示例,只是它需要自变量i的功能。

您所拥有的是包含x(不涉及递归)功能的方程,其中i仅作为索引出现。

您可以将方程式重新编写为i的函数,调用rsolve,然后重新代入原始函数。

只需手动输入以下内容即可构建下面的替换集S。但是为了好玩,我以编程方式构造了它。

restart;

R1 := N[0](x) = x^2;

                                       2
                      R1 := N[0](x) = x 

R2 := M[i](x) = N[i-1](x)+1;

               R2 := M[i](x) = N[i - 1](x) + 1

R3 := N[i](x) = M[i](x)+2;

                 R3 := N[i](x) = M[i](x) + 2

S := map( u->u=op([0,0],u)(op([0,1],u)),
          indets({R1,R2,R3},
                 specfunc(anything,{N,M})) );

       S := {M[i](x) = M(i), N[0](x) = N(0), N[i](x) = N(i),
             N[i - 1](x) = N(i - 1)}

newEqs := eval( {R1,R2,R3}, S );

                                               2                   
      newEqs := { M(i) = N(i - 1) + 1, N(0) = x , N(i) = M(i) + 2 }


newV := eval( {N[i](x),M[i](x)}, S );

                     newV := {M(i), N(i)}

tempans := rsolve( newEqs, newV );

                              2                    2        
         tempans := { M(i) = x  + 3 i - 2, N(i) = x  + 3 i }

ans := eval( tempans, map(rhs=lhs,S) );

                        2                       2        
    ans := { M[i](x) = x  + 3 i - 2, N[i](x) = x  + 3 i }

已经为M[i](x)N[i](x)的一般形式构造了方程,您可以在i的特定校准下评估其中任何一个。您还可以根据这些结果创建过程,然后进行分配。例如,

for k from 1 to 3 do
  N[k] := unapply(subs(i=k,eval(N[i](x),ans)), [x]);
end do:

N[3](11);

                          130

创建所有这些运算符(单独过程)似乎效率低下。为什么不只为N创建一个,而为M创建一个,为ix接受两个参数呢?

Nfunc := unapply(eval(N[i](x),ans), [i,x]);

                                  2      
              Nfunc := (i, x) -> x  + 3 i

Nfunc(3,x);

                          2    
                         x  + 9

Nfunc(3, 11);

                          130

[编辑]我应该告诉你为什么你最初的尝试失败了。

当您尝试原始尝试时,两个过程正文中出现的i不会简化为循环索引i的当前值。然后,当您随后尝试并运行任何已构造的过程时,它将只获取全局i仍然具有的任何值。每当您随后调用N[2]时,名称i的索引值与N[2](x)的分配过程之间就没有链接。

restart;
N[0] := x -> x^2:

for i to 2 do
   M[i] := x -> N[i-1](x)+1;
   N[i] := x -> M[i](x)+2;
end do;

              M[1] := x -> N[i - 1](x) + 1
                N[1] := x -> M[i](x) + 2
              M[2] := x -> N[i - 1](x) + 1
                N[2] := x -> M[i](x) + 2

N[2](11); # why this result, you might asK

                      M[3](11) + 2

i; # still the value coming out of that do-loop

                           3

unassign('i');

N[2](11); # no relation between the 2 and the `i`

                      M[i](11) + 2

可以通过构造一个递归过程序列来修复原始文件。以下是“作品”。但这在运行时效率极低,因为对N[..]M[..]过程中的任何一个的每次调用都会递归地调用链中的其他过程。整个递归调用集将在每次调用时发生。也就是说,这里的递归发生在每个过程的运行时。

restart;
N[0] := x -> x^2:
for i to 3 do
   M[i] := subs(ii=i, x -> N[ii-1](x)+1);
   N[i] := subs(ii=i,x -> M[ii](x)+2);
end do;

                M[1] := x -> N[0](x) + 1
                N[1] := x -> M[1](x) + 2
                M[2] := x -> N[1](x) + 1
                N[2] := x -> M[2](x) + 2
                M[3] := x -> N[2](x) + 1
                N[3] := x -> M[3](x) + 2

N[3](11);

                          130

运行这种方案的整体性能会很差。

更好的方法是利用unapply命令,使N[i]M[i](对于明确的i值)都是一个包含其明确公式的过程。当以以下方式使用unapply时,我们将递归计算到相应公式的函数调用传递给它。这里,递归仅在每个过程的构建时发生。

restart;
N[0] := x -> x^2:
for i to 3 do
   M[i] := unapply( N[i-1](x)+1, x);
   N[i] := unapply( M[i](x)+2, x);
end do;

                                2    
                  M[1] := x -> x  + 1
                                2    
                  N[1] := x -> x  + 3
                                2    
                  M[2] := x -> x  + 4
                                2    
                  N[2] := x -> x  + 6
                                2    
                  M[3] := x -> x  + 7
                                2    
                  N[3] := x -> x  + 9

N[3](11);

                          130

但是正如我在上面的答案中指出的那样,根本不需要构造所有这些过程。通过使用rsolve命令,我们可以解决通用公式的递归关系(以ix都闭合)。然后,根据该封闭式,我们可以利用unapply命令为N构造一个仅由2个参数组成的过程,为M构造一个由2个参数组成的过程。