如何为SymPy自定义函数指定导数?

2024-10-01 07:12:51 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在使用Symphy来帮助自动化使用Euler-Lagrange方法为某些系统寻找运动方程的过程。如果我能定义一个函数q并指定它的时间导数qd-->;d/dt(q)=qd。同样,我想指定d/dt(qd)=qdd。这是很有帮助的,因为作为寻找运动方程过程的一部分,我需要得到作为q和qd函数的表达式的导数(关于时间、q和qd)。最后,我将以q,qd和qdd的形式给出一个方程,我希望能够整洁地打印它,或者使用lambdify将其转换为整洁的numpy函数,以便在模拟中使用

目前,我已经通过将q定义为一个函数并将qd定义为该函数的导数来实现了这一点,这是一种非常迂回和恼人的方式:

q = sympy.Function('q', real=True)(t)
q_diff = diff(q,t)

这在大多数过程中都很好,但最后我得到了一个混乱的表达式,其中填充了“导数(q,t)”和“导数(导数(q,t),t)”,很难将其转换为整洁的打印格式,也很难使用lambdify将其转换为numpy函数。因此,我当前的解决方案是使用subs函数,并分别用sympy符号qd和qdd替换q_diff和diff(q_diff,t),这将清理问题并使表达式的操作更加容易。不过,这似乎是一个糟糕的技巧,对于包含大量状态变量的更复杂的方程来说,这需要花费大量的时间

我想定义一个函数q,它的时间导数有一个特定的值。我会在创建函数时传入该值,sympy可以将其视为通用函数对象,但会使用我为时间导数给定的任何值,而不仅仅是说“导数(q,t)”。我想要这样的东西:

qdd = sympy.symbols('qdd')
qd = my_func(name='qd', time_deriv=qdd)
q = my_func(name='q', time_deriv=qd)

diff(q, t)
>>> qd
diff(q**2, t)
>>> 2*q*qd
diff(diff(q**2, t))
>>> 2*q*qdd + 2*qd**2
expr = q*qd**2
expr.subs(q, 5)
>>> 5*qd**2

这样的话,我仍然可以使用subs命令和lambdify命令来替换q和qd的数值,这将非常有用。我一直在尝试这样做,但我不太了解基本symphy.Function类是如何工作的。这就是我现在拥有的:

class func(sp.Function):
    def __init__(self, name, deriv):
        self.deriv = deriv
        self.name = name

    def diff(self, *args, **kwargs):
        return self.deriv

    def fdiff(self, argindex=1):
        assert argindex == 1
        return self.deriv

到目前为止,这段代码还没有真正起作用,我不知道如何具体说明q的时间导数是qd。现在q的所有导数都返回q

我不知道这是不是一个非常糟糕的解决方案,我是否应该完全避免这个问题,或者是否已经有一个干净的方法来解决这个问题。任何建议都将不胜感激


Tags: 函数nameself定义表达式过程时间diff