Sympy重命名表达式的一部分

2024-03-28 13:48:23 发布

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

假设我定义了以下表达式:

from sympy import *
N, D, i, j, d = symbols("N D i j d", integer=True)
beta, gamma = symbols(r'\beta \gamma')
X = IndexedBase("X", shape=(N, D))

# r(i, j) = euclidian distance between X[i] and X[j]
r = lambda i, j: sqrt(Sum((X[i, d] - X[j, d])**2, (d, 1, D)))
expr = r(i, j)**2 + r(i, j)

expr变量现在显示如下:

虽然这对于这个最小的例子来说很好,但是在较大的表达式中会变得相当混乱。这确实妨碍了我以后计算所有r(i,j),导数等的和时会发生什么

我的问题:有没有一种方法可以告诉SymPy关于r(i, j),这样它就可以这样显示:

而在随后的表达式中仍然表现得像以前一样?在

我知道我可以使raFunction,这将显示为想要的,但是在随后的计算中它将不能正常工作(例如,导数将是抽象的,而不是求值的)。在

如有任何帮助,将不胜感激!在


Tags: fromimporttrue定义表达式integerbeta导数
2条回答

可以生成一个默认情况下不求值的自定义函数子类:

class r(Function):
    @classmethod
    def eval(cls, i, j):
        return

    def doit(self, **kwargs):
        i, j = self.args
        return sqrt(Sum((X[i, d] - X[j, d])**2, (d, 1, D)))

eval告诉它何时计算。因为它总是返回None,所以从不求值。它还告诉SymPy函数有两个参数。如果您愿意,您也可以让它在某些情况下返回显式值。例如,您可能希望它计算i和{}是否是显式数字。在

^{pr2}$

有了它,您可以根据需要使用它,并在需要计算时调用expr.doit()。您还可以专门为某些函数定义求值以避免doit。例如,衍生品:

def _eval_derivative(self, x):
    return self.doit()._eval_derivative(x)

这将使r(i, j).diff(i)立即求值,而不必调用doit。在

其他函数有类似的方法可以定义。请参阅SymPy文档。在

我不知道这是否对你有帮助,但是这个呢:

from sympy import *
from sympy.utilities.lambdify import lambdify, implemented_function
N, D, i, j, d = symbols("N D i j d", integer=True)
beta, gamma = symbols(r'\beta \gamma')
X = IndexedBase("X", shape=(N, D))

r = implemented_function('r', lambda i, j: sqrt(Sum((X[i, d] - X[j, d])**2, (d, 1, D))));
expr = r(i, j)**2 + r(i, j)
print(expr)
r = lambdify((i,j), r(i,j))
print(diff(r(i,j), X[i,j]))

您可以根据需要显示您的表达式,然后使用^{}并使其正常工作。只是猜测一下,也许这对你没用,因为你可能更喜欢在代码中维护相同的表达式。在

相关问题 更多 >