如何简化sympy向量?

时间:2019-05-21 08:12:34

标签: python sympy symbolic-math simplify

我正在使用sympy进行一些符号矢量计算,但是我不能以适当的方式简化矢量类的参数。考虑以下代码:

from sympy.physics.mechanics import ReferenceFrame, dot, cross
from sympy import symbols, sin, cos, simplify

alpha, theta, l = symbols('alpha theta l')

def Rodrigues(v, k, angle):
    return cos(angle) * v + cross(k, v) * sin(angle) + k * dot(k, v) * (1- cos(angle))

N = ReferenceFrame('N')
P0 = -l * N.y

P2 = Rodrigues(
    Rodrigues(P0, -N.z, alpha), 
    Rodrigues(N.x, -N.z, alpha), 
    theta)

返回:

         

尝试simplify(P2)时收到错误消息:

  

AttributeError:“函数”对象没有属性“ x”

我认为这是因为simplify需要一个sympy表达式对象。尝试dir(P2)时,有一个simplify方法返回:

<bound method Vector.simplify of - l*sin(alpha)*cos(theta)*N.x - l*cos(alpha)*cos(theta)*N.y + (-l*sin(alpha)**2 - l*cos(alpha)**2)*sin(theta)*N.z>

我不知道这是什么!尝试P2.args我得到:

[(Matrix([
  [                       -l*sin(alpha)*cos(theta)],
  [                       -l*cos(alpha)*cos(theta)],
  [(-l*sin(alpha)**2 - l*cos(alpha)**2)*sin(theta)]]), N)]

这是带有嵌套3x1 sympy矩阵的2D元组的1D列表!我不知道谁的选择是使向量类变得如此晦涩难懂,但是现在我可以使用simplify(P2.args[0][0][2])简化最后一个元素并将函数更改为:

def Rodrigues(v, k, angle):
    tmpVec = cos(angle) * v + cross(k, v) * sin(angle) + k * dot(k, v) * (1- cos(angle))
    tmpFrame = tmpVec.args[0][1]
    return simplify(tmpVec.args[0][0][0]) * tmpFrame.x + simplify(tmpVec.args[0][0][1]) * tmpFrame.y + simplify(tmpVec.args[0][0][2]) * tmpFrame.z

在我看来这是一个非常糟糕的解决方案。

我想知道您是否可以帮助我知道是否还有更多的Python方式可以做到这一点。例如,默认情况下强制sympy简化所有表达式。还是我以错误的方式使用了vector.simplify方法?感谢您的提前支持。

P.S。 Rodrigues旋转公式

2 个答案:

答案 0 :(得分:1)

您需要调用print(P2.simplify)之类的方法来代替print(P2.simplify())。之后,您将获得- l*sin(alpha)*cos(theta)*N.x - l*cos(alpha)*cos(theta)*N.y - l*sin(theta)*N.z作为输出,与您的def Rodrigues的最新版本相同。

答案 1 :(得分:0)

另一种解决方案是默认情况下强制sympy简化所有向量:

from sympy.physics.vector import Vector
Vector.simp = True

更多信息here