[英]Get linear and quadratic terms from sympy expression
我有一个通用表达式E
,它依赖于X(t)
(变量数组)和dX(t)
。 有没有一种简单的方法可以从E
获得linear
和quadratic
项? 我的实际代码仅在E
简单时才有效。
我的目标是得到矩阵M
, V
, K
, A
, B
和C
使得E = dX @ M @ dX + dX @ V @ X + X @ K @ X + A @ dX + B @ X + C
举个例子
import sympy as sp
t = sp.symbols("t")
x = sp.Function("x")(t)
y = sp.Function("y")(t)
dx = sp.diff(x, t)
dy = sp.diff(y, t)
X = sp.Array([x, y])
dX = sp.Array([dx, dy])
E = 7*(dx**2) + 2*dx*dy + 6*(dy**2) # M = [[7, 1],
# [1, 6]]
E += 4*dx*x + 6*dx*y + 3*dy*x + 5*dy*y # V = [[4, 6],
# [3, 5]]
E += (-3)*x**2 + (-4)*x*y + (-5)*y**2 # K = [[-3, -2],
# [-2, -5]]
E += 1*dx + (-7)*dy # A = [1, -7]
E += (-5)*x + 9*y # B = [-5, 9]
E += 80 # C = 80
到目前为止,我所做的只是取导数并手动减去这些项。 当我有常量值时,以下代码可以正常工作:
diff = sp.derive_by_array
def dot(A, B):
# Matrix multiplication of A and B
ndimA = len(sp.shape(A))
C = sp.tensorproduct(A, B)
D = sp.tensorcontraction(C, (ndimA-1, ndimA))
return D
M = diff( diff(E, dX), dX)/2
E -= dot(dX, dot(M, dX))
V = diff( diff(E, X), dX)
E -= dot(dX, dot(V, X))
K = diff( diff(E, X), X)/2
E -= dot(X, dot(K, X))
A = diff(E, dX)
E -= dot(A, dX)
B = diff(E, X)
E -= dot(B, X)
C = sp.expand(E)
但是当我输入非常数项时,结果是错误的。 例如E = cos(x)
:
# expected
M = [[0, 0],
[0, 0]]
V = [[0, 0],
[0, 0]]
K = [[0, 0],
[0, 0]]
A = [0, 0]
B = [0, 0]
C = cos(x)
# gotten
M = [[0, 0],
[0, 0]]
V = [[0, 0],
[0, 0]]
K = [[-cos(x)/2, 0],
[0, 0]]
A = [0, 0]
B = [-x(t)**2*sin(x(t))/2 + x(t)*cos(x(t)) - sin(x(t)), 0]
C = x(t)**3*sin(x(t))/2 - x(t)**2*cos(x(t))/2 + x(t)*sin(x(t)) + cos(x(t))
我期待使用高级表达式操作和 function srepr
来分解E
的解决方案,但我认为它应该存在一种更简单的方法来做到这一点。
我找到了一个使用符号矩阵的解决方案,并使用sympy.solve
来找到解决方案。 我创建symbolic function arrays
,然后计算标量Esup
作为所需的表达式,并求解以找到每个矩阵内的值。
import numpy as np
all_variables = []
def MatrixFunction(name, shape):
ndim = len(shape)
M = np.zeros(shape, dtype="object")
if ndim == 1:
for i in range(shape[0]):
M[i] = sp.Function(f"{name}{i}")(x, y)
all_variables.append(M[i])
elif ndim == 2:
for i in range(shape[0]):
for j in range(shape[1]):
M[i, j] = sp.Function(f"{name}{i}{j}")(x, y)
all_variables.append(M[i, j])
return sp.MutableDenseNDimArray(M)
M = MatrixFunction("M", [len(X), len(X)])
V = MatrixFunction("V", [len(X), len(X)])
K = MatrixFunction("K", [len(X), len(X)])
A = MatrixFunction("A", [len(X)])
B = MatrixFunction("B", [len(X)])
C = sp.Function("C")(x, y)
all_variables.append(C)
equations = []
for i in range(len(X)):
for j in range(i+1, len(X)):
equations.append(M[i, j] - M[j, i])
equations.append(K[i, j] - K[j, i])
Esup = dot(dX, dot(M, dX))
Esup += dot(dX, dot(V, X))
Esup += dot(X, dot(K, X))
Esup += dot(A, dX)
Esup += dot(B, X)
Esup += C
dife = E - Esup
poly = sp.Poly(dife, (x, y, dx, dy))
equations += poly.coeffs()
solution = sp.solve(equations, all_variables)
for var, val in solution.items():
C = C.subs(var, val)
for i in range(len(X)):
A[(i,)] = A[(i,)].subs(var, val)
B[(i,)] = B[(i,)].subs(var, val)
for j in range(len(X)):
M[i, j] = M[i, j].subs(var, val)
V[i, j] = V[i, j].subs(var, val)
K[i, j] = K[i, j].subs(var, val)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.