Подставить значения для переменных в результате производных_по_массиву в SymPy

В настоящее время я работаю над некоторыми упражнениями по исчислению функций с несколькими переменными и подумал, что попробую создать свою собственную функцию для определения градиента и гессиана в определенной точке для любой функции. В настоящее время у меня возникают проблемы при попытке заменить полученные матрицы значениями координат для произвольной функции. Мне уже удалось решить конкретные примеры, но моя попытка сделать функцию для решения пользовательской функции работает неправильно.

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))`

который дает следующий результат, однако я стремлюсь подставить нужные значения в градиент и матрицы гессиана для достижения следующего желаемого результата. Мне удалось добиться желаемого результата, используя следующее.

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() n раз для заданной координаты, чтобы получить соответствующие матрицы градиента/гессе?


person Josmoor98    schedule 28.03.2018    source источник


Ответы (1)


Переменная 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)
person Community    schedule 28.03.2018