通过 "for loop" 在 Maple 中定义递归关系
Defining recursive relation in Maple by "for loop"
我正在尝试通过 "for loop" 在 Maple 中建立递归关系。假设我们有两个序列 M[i](x)
和 N[i](x)
,即 N[0](x)=x^2
和 M[i](x)=N[i-1](x)+1
以及 N[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
来定义我的函数。有没有办法修改这段代码?
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
创建一个,它允许 i
和 x
的两个参数?
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
[edited] 我应该告诉你为什么你最初的尝试失败了。
当您尝试最初的尝试时,出现在两个过程主体中的 i
并未简化为循环索引的当前值 i
。当您随后尝试 运行 任何构造的过程时,它只会获取全局 i
仍然具有的任何值。名称 N[2]
的索引值与其指定过程中的 i
之间没有 link,无论何时随后调用 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
您可以通过构造一个递归过程序列来修复您的原件。以下"works"。但它在 运行 时效率极低,因为每次调用任何 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
命令,我们可以解决一般公式的递归关系(根据 i
和 x
关闭)。然后从那个封闭的公式我们可以利用 unapply
命令为 N
构造一个双参数过程,为 M
.
构造一个双参数过程
我正在尝试通过 "for loop" 在 Maple 中建立递归关系。假设我们有两个序列 M[i](x)
和 N[i](x)
,即 N[0](x)=x^2
和 M[i](x)=N[i-1](x)+1
以及 N[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
来定义我的函数。有没有办法修改这段代码?
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
创建一个,它允许 i
和 x
的两个参数?
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
[edited] 我应该告诉你为什么你最初的尝试失败了。
当您尝试最初的尝试时,出现在两个过程主体中的 i
并未简化为循环索引的当前值 i
。当您随后尝试 运行 任何构造的过程时,它只会获取全局 i
仍然具有的任何值。名称 N[2]
的索引值与其指定过程中的 i
之间没有 link,无论何时随后调用 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
您可以通过构造一个递归过程序列来修复您的原件。以下"works"。但它在 运行 时效率极低,因为每次调用任何 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
命令,我们可以解决一般公式的递归关系(根据 i
和 x
关闭)。然后从那个封闭的公式我们可以利用 unapply
命令为 N
构造一个双参数过程,为 M
.