首页 > 解决方案 > Maxima:有什么方法可以让 main 函数中定义的函数成为局部函数,类似于局部变量?

问题描述

我想知道是否有任何方法可以使 main 函数中定义的函数成为局部函数,类似于局部变量。例如,在这个计算标量函数梯度的函数中,

grad(var,f) := block([aux],
    aux : [gradient, DfDx[i]],
    gradient : [],
    DfDx[i] := diff(f(x_1,x_2,x_3),var[i],1),
    for i in [1,2,3] do (
        gradient : append(gradient, [DfDx[i]])
    ),
    return(gradient)
)$

gradient在主函数内部定义的变量在主函数grad(var,f)外部无效,因为它在aux列表内部。但是,我观察到 function DfDx,尽管在aux列表中,但确实在 main 函数之外产生了影响。

有什么方法可以使在主函数中定义的子函数仅是本地的,就像用局部变量可以做的一样?(我知道kill一旦使用它们就可以了,但也许有一种更优雅的方式)

标签: maximawxmaxima

解决方案


要计算梯度,我的建议是调用makelistdiff如我的第一个答案所示。让我借此机会谈谈一些相关的话题。

我将粘贴grad问题陈述中显示的定义并使用它来发表一些评论。

grad(var,f) := block([aux],
    aux : [gradient, DfDx[i]],
    gradient : [],
    DfDx[i] := diff(f(x_1,x_2,x_3),var[i],1),
    for i in [1,2,3] do (
        gradient : append(gradient, [DfDx[i]])
    ),
    return(gradient)
)$

(1) Maxima 主要使用表达式而不是函数。这不会在这里造成问题,我只想说清楚。例如,一般来说,必须说diff(f(x), x)whenf是一个函数,而不是diff(f, x),同样,integrate(f(x), ...)而不是integrate(f, ...)

(2) whengradientDfdxare 成为局部变量,你必须在变量列表中为它们命名block。例如block([gradient, Dfdx], ...)——千里马不会明白block([aux], aux: ...)的。

(3) 注意用方括号代替圆括号定义的函数,例如f[x] := ...代替f(x) := ...,是Maxima 中所谓的数组函数。数组函数是一个记忆函数,即如果f[x]被调用两次或多次,则返回值只计算一次,之后每次都返回。有时,当函数的域包含有限集时,这是一种有用的优化。

(4) 请记住,x_1, x_2, x_3, 是不同的符号,彼此不相关,也与 , , 不相关,x[1]即使它们显示相同。我的建议是使用下标符号when是一个变量。x[2]x[3]x[i]i

(5) 关于建立返回值,尽量安排一次计算整个事情,而不是逐步增加结果。在这种情况下,makelist最好是forplus append

(6) returnMaxima 中的功能与其他编程语言中的功能不同;这有点难以解释。函数返回最后一个被计算的表达式的值,所以如果gradient是最后一个表达式,你可以写grad(var, f) := block(..., gradient).

希望这会有所帮助,我知道它晦涩难懂。Maxima 编程语言不是在实施之前就设计好的,而且在 50 多年(!)之后的很长一段时间内,一些决定显然是有问题的。没关系,他们一边走一边想办法。没有一整套既定结果可以提供参考;最初的作者正在为今天被认为是常识的东西做出贡献。


推荐阅读