要计算梯度,我的建议是调用makelist 和diff,如我的第一个答案所示。让我借此机会谈谈一些相关的话题。
我将粘贴问题陈述中显示的grad 的定义,并用它来制作一些 cmets。
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 主要用于表达式而不是函数。这不会在这里造成问题,我只想说清楚。例如。一般来说,当f 是一个函数时,必须说diff(f(x), x),而不是diff(f, x),同样,integrate(f(x), ...) 而不是integrate(f, ...)。
(2) 当gradient 和Dfdx 是局部变量时,你必须在block 的变量列表中命名它们。例如。 block([gradient, Dfdx], ...) -- Maxima 不会理解 block([aux], aux: ...)。
(3) 请注意,使用方括号而不是括号定义的函数,例如f[x] := ...而不是f(x) := ...,是Maxima中所谓的数组函数。数组函数是一个记忆函数,即如果f[x]被调用两次或多次,则返回值只计算一次,然后每次返回。有时,当函数的域包含有限集时,这是一种有用的优化。
(4) 请记住,x_1、x_2、x_3 是不同的符号,彼此无关,与x[1]、x[2]、x[3] 无关,即使它们显示相同。我的建议是在 i 是变量时使用下标符号 x[i]。
(5) 关于建立返回值,尝试安排一次计算整个事情,而不是逐步增加结果。在这种情况下,makelist 优于 for 加上 append。
(6) Maxima 中的return 函数与其他编程语言中的行为不同;这有点难以解释。一个函数返回最后一个被计算的表达式的值,所以如果gradient是最后一个表达式,你可以写grad(var, f) := block(..., gradient)。
希望这会有所帮助,我知道它晦涩难懂且复杂。 Maxima 编程语言在实施之前并不是设计出来的,而且在 50 多年(!)之后的很长一段时间内,一些决定显然是有问题的。没关系,他们一边走一边想办法。没有一整套既定结果可以提供参考;原作者正在为今天被认为是常识的东西做出贡献。