2

我目前正在做一些关于多变量函数微积分的练习,并认为我会尝试制作自己的函数来确定任何函数在定义点处的梯度和粗麻布。我目前在尝试将结果矩阵替换为任意函数的坐标值时遇到问题。我已经设法解决了具体的例子,但是我尝试创建一个函数来解决用户定义的函数并不能正常工作。

def multivariable_function(function, variables, substitute=(0,0)):
"""Determines Gradient and Hessian vectors for multivariable function.

  Args:
    function: Enter the multivariable function
    variables: Enter list of variable names
    substitute: Default = (0,0)

  Returns:
    gradient/hessian matrices for given coordinate 

  To do:
    Include sympy symbol() generation within function
  """

  #derive_by_array returns a gradient matrix for multivariable function
  Gradient = simplify(derive_by_array(function, variables))

  #derive_by_array returns a Hessian matrix for multivariable function                   
  Hessian = simplify(derive_by_array(derive_by_array(function, variables), variables))

  #Line currently isn't doing anything
  Gradient.subs(zip(variables, substitute))

  return Gradient, Hessian

这是迄今为止运行的基本功能。

multivariable_function((x**2)*(y**3) + exp(2*x + x*y - 1) - (x**3 + 3*y**2)**2, (x,y))`

这会产生以下结果,但是我的目标是将所需的值代入梯度和 hessian 矩阵以实现以下所需的结果。我设法使用以下方法达到了预期的结果。

from sympy import *

x, y, z, K, T, r, σ, h, a, f, μ, c, t, m, x1, x2, x3 = symbols('x, y, z, K, T, r, σ, h, a, f, μ, c, t, m, x1, x2, x3') # Variables used must be defined in sympy.
init_printing(use_unicode=False) #Print the answers in unicode characters

function = (x**2)*(y**3) + exp(2*x + x*y - 1) - (x**3 + 3*y**2)**2

Gradient_1 = simplify(derive_by_array(function, (x, y)))
Hessian_1 = simplify(derive_by_array(derive_by_array(function, (x, y)), (x, y)))

Gradient_1.subs(x, 0).subs(y,0), Hessian_1.subs(x,0).subs(y,0)

查看此处提出的问题后,似乎压缩两个列表应该使 subs() 函数能够工作,但它目前不适合我。我试图遍历“变量”和“替换”以顺序应用 .subs(),但是我发现该函数仅在该方法链接到所有替换变量时才有效,如上面的示例所示。

有谁知道我如何为给定坐标应用 .subs() n 次以产生相关的梯度/粗麻布矩阵?

4

1 回答 1

2

变量Gradient的类型

sympy.tensor.array.dense_ndim_array.ImmutableDenseNDimArray

像几乎所有 SymPy 对象一样,除了可变矩阵之外,它是不可变的。该方法subs没有就地修改它;它返回一个需要分配的新对象。

  Gradient = Gradient.subs(zip(variables, substitute))
  Hessian = Hessian.subs(zip(variables, substitute))

然后函数按预期工作,返回

([2*exp(-1), 0], [[4*exp(-1), exp(-1)], [exp(-1), 0]])

但我建议不要将生成器传递给subs; 有涉及这方面的悬而未决的问题。为了安全起见,首先转换为列表或字典。(这里也有区别:替换应该是连续的还是同时的,尽管在用数字代替符号时这并不重要。)

  subs_dict = dict(zip(variables, substitute))
  Gradient = Gradient.subs(subs_dict)
  Hessian = Hessian.subs(subs_dict)
于 2018-03-28T13:29:11.473 回答