首页 > 解决方案 > 用数值替换 Sympy 索引符号

问题描述

我有一个同情的表达式,我想在区分后输入数值。我要替换的变量是最后一个表达式中的所有 x[i]、y[i] 和 R_abs[i],并且是 numpy 数组

rx=np.array([-0.357, -0.742, -1.078,  0.206])

但是尝试 subs 或 replace 都不会做任何事情或引发 Symbols 不允许索引的错误,例如 e1.subs(x[1],rx[0])。我几乎经历了我能想到的每一次迭代,但都无济于事。

import sympy as sp
    
r0,ge_x,ge_y,bx,by = sp.symbols('r0,ge_x,ge_y,bx,by', real=True) #Main symbols

i,x,y,R_abs = sp.symbols('i,x,y,R_abs', real=True) #Helper symbols
n=4

s2=sp.Sum((bx+r0*sp.Indexed('x',i)/sp.Indexed('R_abs',i)+ge_x*sp.Indexed('x',i)+ge_y*sp.Indexed('y',i)-sp.Indexed('x',i))**2+(by+r0*sp.Indexed('y',i)/sp.Indexed('R_abs',i)-ge_x*sp.Indexed('y',i)+ge_y*sp.Indexed('x',i)-sp.Indexed('y',i))**2,(i,1,n))

e1=sp.Eq(sp.diff(s2,bx).doit(),0)

然后用 e1

Eq(8*bx + 2*ge_x*x[1] + 2*ge_x*x[2] + 2*ge_x*x[3] + 2*ge_x*x[4] + 2*ge_y*y[1] + 2*ge_y*y[2] + 2*ge_y*y[3] + 2*ge_y*y[4] + 2*r0*x[4]/R_abs[4] + 2*r0*x[3]/R_abs[3] + 2*r0*x[2]/R_abs[2] + 2*r0*x[1]/R_abs[1] - 2*x[1] - 2*x[2] - 2*x[3] - 2*x[4], 0)

在这里,我想用它们的数值替换所有的 x、y 和 R_abs。

标签: pythonsympy

解决方案


我一直在为 SymPy 中的索引而苦苦挣扎。事实证明,创建Function实例比索引Symbol. 它还使符号更简单。

另请注意,通过在表达式中使用字符串,我认为 SymPy 会使用相同的字符串名称创建自己的符号,但由于您的符号不同,因此无法使用您的符号访问它们。至少这就是我有时会发生的事情。

这是一个工作示例:

import sympy as sp

r0, ge_x, ge_y, bx, by = sp.symbols("r0 ge_x ge_y bx by", real=True)  # main symbols

# define functions that will take the role of indexed symbols
x = sp.Function("x")
y = sp.Function("y")
R_abs = sp.Function("R_abs")
i = sp.Symbol("i", positive=True, integer=True)
n = 4

s2 = sp.Sum((bx + r0 * x(i) / R_abs(i) + ge_x * x(i) + ge_y * y(i) - x(i)) ** 2 +
            (by + r0 * y(i) / R_abs(i) - ge_x * y(i) + ge_y * x(i) - y(i)) ** 2, (i, 1, n))

s2_prime = sp.diff(s2, bx).doit().simplify()
print(s2_prime)

# whatever lists you want. Can even be an instance of `np.ndarray`
# note that you summed from 1 to n so the 0th element will not be used
x_array = [0, 1, 2, 3, 4]
y_array = [4, 3, 2, 1, 0]
R_abs_array = [-10, 10, 5, 4, 3]

# define a function to access these array elements
x_function = lambda index: x_array[index]
y_function = lambda index: y_array[index]
R_abs_function = lambda index: R_abs_array[index]

# no idea why subs does not work and you MUST keep the same name for the variable.
# you can't have for example `evaluated_s2_prime = ...`.
# Probably something to do with forcing sp to remove references to `x`?
s2_prime = s2_prime.replace(x, x_function).replace(y, y_function).replace(R_abs, R_abs_function)
print(s2_prime)

生产:

8*bx + 2*ge_x*x(1) + 2*ge_x*x(2) + 2*ge_x*x(3) + 2*ge_x*x(4) + 2*ge_y*y(1) + 2*ge_y*y(2) + 2*ge_y*y(3) + 2*ge_y*y(4) + 2*r0*x(4)/R_abs(4) + 2*r0*x(3)/R_abs(3) + 2*r0*x(2)/R_abs(2) + 2*r0*x(1)/R_abs(1) - 2*x(1) - 2*x(2) - 2*x(3) - 2*x(4)
8*bx + 20*ge_x + 12*ge_y + 31*r0/6 - 20

推荐阅读