【问题标题】:Partial symbolic derivative in PythonPython中的偏符号导数
【发布时间】:2016-05-10 11:04:57
【问题描述】:

我需要对我的方程进行部分推导,并从导数中形成一个矩阵。我的等式是: 虽然必须满足以下条件: 为此,我使用了 sympy 模块及其 diff() 函数。到目前为止我的代码是:

from sympy import*
import numpy as np
init_printing() #delete if you dont have LaTeX installed

logt_r, logt_a, T, T_a, a_0, a_1, a_2, logS, Taa_0, Taa_1, Taa_2  = symbols('logt_r, logt_a, T, T_a, a_0, a_1, a_2, logS, Taa_0, Taa_1, Taa_2')

A = (logt_r - logt_a - (T - T_a) * (a_0 + a_1 * logS + a_2 * logS**2) )**2
parametri = [logt_a, a_0, Taa_0, a_1, Taa_1, a_2, Taa_2]

M = expand(A)
M = M.subs(T_a*a_0, Taa_0)
M = M.subs(T_a*a_1, Taa_1)
M = M.subs(T_a*a_2, Taa_2)

K = zeros(len(parametri), len(parametri))
O = []

def odv(par):
    for j in range(len(par)):
        for i in range(len(par)):
            P = diff(M, par[i])/2
            B = P.coeff(par[j])
            K[i,j] = B
    return K 

odv(parametri)

我的结果:

我的问题

我遇到的问题在于产品的偏导数(T_aa_0、T_aa_1 和 T_a*a_2),因为通过使用 diff() 函数,您无法导出函数使用产品(显然),否则您会收到错误:

ValueError: 
Can't calculate 1-th derivative wrt T_a*a_0.

为了解决这个问题,我用系数代替了这个产品,比如:

M = M.subs(T_a*a_0, Taa_0)
M = M.subs(T_a*a_1, Taa_1)
M = M.subs(T_a*a_2, Taa_2)

但正如您在最终结果中看到的那样,这仅在某些情况下有效。我想知道是否有更好的方法来做到这一点,我不需要替代产品并且它适用于所有情况。

其他信息

让我重新表述我的问题。是否可以通过使用 python 或使用 sympy 模块以符号方式推导出具有函数的方程?

【问题讨论】:

  • 你能创建一个最小(更小)的例子来重现你的问题吗?
  • 我实际上需要解决更大的方程,这个是最小的,但我会尽量减少问题。但是我确切地知道问题是什么,因为我自己计算了每个元素。问题与产品的替换直接相关,因为它会丢失一些元素(你从 2 个元素的乘积中得到 1 个元素),因此我的矩阵中有一些 0。如果有人知道如何用 2 个元素的乘积或技巧来派生一个函数,那么我的代码将正常工作。
  • 重点是你应该本地化你的问题。删除与解决问题无关的部分。见minimal reproducible example

标签: python python-2.7 python-3.x matrix sympy


【解决方案1】:

所以我设法自己解决了我的问题。主要问题是如何用另一个函数象征性地推导出一个函数或方程。当我再次慢慢浏览 sympy 文档时,我看到了一些我以前错过的细节。 为了使用函数导出函数,您需要更改函数的设置,该设置将用于导出。例如:

x, y, z = symbols('x, y, z')
A = x*y*z
B = x*y

# This is the detail:
type(B)._diff_wrt = True
diff(A, B)

或者在我的例子中,代码如下:

koef = [logt_a, a_0, T_a*a_0, a_1, T_a*a_1, a_2, T_a*a_2]
M = expand(A)
K = zeros(len(koef), len(koef))
def odvod_mat(par):
    for j in range(len(par)):
        for i in range(len(par)):
            type(par[i])._diff_wrt = True
            P = diff(M, par[i])/2
            B = P.coeff(par[j])
            K[i,j] = B

            #Removal of T_a
            K[i,j] = K[i,j].subs(T_a, 0)
    return K  
odvod_mat(koef)

再次感谢所有花时间阅读本文的人。我希望这对任何与我有同样问题的人有所帮助。

【讨论】:

  • 在表达式上设置_diff_wrt = True 有点小技巧。即使在您给出的示例中,diff(A, B) 也是错误的(应该是z,但它给出了0)。请参阅 docs.sympy.org/latest/modules/… 了解 _diff_wrt 以及有关其工作原理的一些注意事项。
  • 更好的方法是使用 subs 将要区分的表达式替换为符号,区分该符号,然后将其替换回来。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多