【问题标题】:Summing vector products in SymPySymPy 中的向量积求和
【发布时间】:2019-09-15 12:20:55
【问题描述】:

以下代码首先以符号方式计算 $\sum_{i=1}^3 x_i y_i$,然后将特定数值代入表达式以生成单个数字。 (我还添加了一些行来显示中间结果。)

IPython console for SymPy 1.4 (Python 3.7.4-64-bit) (ground types: gmpy)

These commands were executed:
>>> from __future__ import division
>>> from sympy import *
>>> x, y, z, t = symbols('x y z t')
>>> k, m, n = symbols('k m n', integer=True)
>>> f, g, h = symbols('f g h', cls=Function)
>>> init_printing()

In [1]: i = symbols('i')                                                                                                
In [2]: x = IndexedBase('x')                                                                                            
In [3]: y = IndexedBase('y')                                                                                            
In [4]: xes = [(x[1], 9), (x[2], 8), (x[3], 7)]                                                                         
In [5]: ys = [(y[1], 4), (y[2], 5), (y[3], 6)]                                                                          
In [6]: Snum = Sum(x[i] * y[i],(i,1,3))                                                                                 
In [7]: Snum.doit()                                                                                                     
Out[7]: x[1]⋅y[1] + x[2]⋅y[2] + x[3]⋅y[3]
In [8]: Sx = Snum.doit().subs(xes)                                                                                      
In [9]: Sx                                                                                                              
Out[9]: 9⋅y[1] + 8⋅y[2] + 7⋅y[3]
In [10]: Sxy = Sx.subs(ys)                                                                                              
In [11]: Sxy                                                                                                            
Out[11]: 118

我一直试图将这个想法转移到一个涉及向量而不是标量和叉积而不是乘法的案例中,但没有成功。

In [12]: from sympy.vector import *                                                                                     
In [13]: N = CoordSys3D('N')                                                                                            
In [14]: r = IndexedBase('r')                                                                                           
In [15]: F = IndexedBase('F')                                                                                           
In [16]: rs = [(r[1], N.i + 2*N.j + 4*N.k), (r[2], 3*N.i - 3*N.j + 4*N.k), (r[3], -N.i + 5*N.j + 2*N.k)]                
In [17]: Fs = [(F[1], -2*N.i - 1*N.j + 4*N.k), (F[2], -3*N.i - 2*N.j + 1*N.k), (F[3], N.i - 2*N.j - 3*N.k)]             
In [18]: rs[0][1] ^ Fs[0][1]                                                                                            
Out[18]: 12*N.i + (-12)*N.j + 3*N.k
In [19]: Svec = Sum(r[i] ^ F[i],(i,1,3))                                                                                
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-19-08e9d4fdd092> in <module>
----> 1 Svec = Sum(r[i] ^ F[i],(i,1,3))

TypeError: unsupported operand type(s) for ^: 'Indexed' and 'Indexed'

索引对象似乎不支持向量运算,例如叉积。

我的问题是,SymPy 中是否有任何方法可以执行类似于我上面涉及向量和向量运算的纯数字示例的计算?我想以这样的方式计算 $T = \sum_{i=1}^3 r_i x F_i$,首先我得到 r_1 x F_1 + r_2 x F_2 + r_3 x F_3,然后我可以进行适当的替换结果得到单个向量 6*N.i + (-28)*N.j + (-15)*N.k 。这可能吗?如果有,怎么做?

【问题讨论】:

    标签: vector sum sympy indexed cross-product


    【解决方案1】:

    你能把总和作为一个产品,然后result.replace(lambda x: x.is_Mul, lambda x: reps[x.args[0]]^reps[x.args[1]])reps = dict(rs); reps.update(dict(Fs))?例如使用整数和按位运算有效:

    >>> rs = [(r[1], 1), (r[2], 2), (r[3], 3)]
    >>> Fs = [(F[1], 4), (F[2], 5), (F[3], 6)]
    >>> Sum(r[i]*F[i], (i, 1, 3)).doit().replace(
    ...    lambda x: x.is_Mul,
    ...    lambda x: int(reps[x.args[0]])^int(reps[x.args[1]]))
    ... 
    17
    

    然而,这样做的一个问题是(当前)不能将 IndexedBase 声明为不可交换的。代替 IndexedBase 你可以使用 Function:

    >>> f=Function('f', commutative=False)
    >>> g=Function('g', commutative=False)
    >>> Sum(f(i)*g(i), (i, 1, 3)).doit()
    f(1)*g(1) + f(2)*g(2) + f(3)*g(3)
    >>> Sum(g(i)*f(i), (i, 1, 3)).doit()
    g(1)*f(1) + g(2)*f(2) + g(3)*f(3)
    

    在您的情况下,您将它们命名为 rF 而不是 fg 并将 *them( 映射到像 rs = [(r(1), N.i + 2*N.j + 4*N.k), ... 这样的向量。

    如果将以下差异应用于 SymPy,那么我认为声明为 commutative=FalseIndexedBase 会起作用:

    diff --git a/sympy/tensor/indexed.py b/sympy/tensor/indexed.py
    index 9024f21..f02aa3e 100644
    --- a/sympy/tensor/indexed.py
    +++ b/sympy/tensor/indexed.py
    @@ -138,7 +138,6 @@ class Indexed(Expr):
         True
    
         """
    -    is_commutative = True
         is_Indexed = True
         is_symbol = True
         is_Atom = True
    @@ -419,7 +418,6 @@ class IndexedBase(Expr, NotIterable):
         >>> C_inherit == C_explicit
         True
         """
    -    is_commutative = True
         is_symbol = True
         is_Atom = True
    

    例如:

    >>> I=IndexedBase('i', commutative=False)
    >>> I[1]*I[2]
    i[1]*i[2]
    >>> I[2]*I[1]
    i[2]*i[1]
    

    您可能想为此 here 打开一个问题。

    【讨论】:

    • 谢谢您的回答;它工作并产生正确的 -6⋅N_i + (28) N_j + (15) N_k 值。
    • 编辑:我太仓促了。我刚刚注意到结果正好是 (-1) 乘以正确的总和 6*N_i + (-28)*N_j + (-15)*N_k。我想这是因为与实际产品相反,叉积不是可交换的,即 a x b = -(b x a)。显然,评估没有考虑到这一事实。不过,您的建议是朝着正确方向迈出的非常有用的一步,再次感谢。
    • 虽然 IndexedBase 似乎是正确的使用类型,但可以保留交换性假设的简单函数会更好。我会更新答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-30
    • 2016-06-03
    • 1970-01-01
    • 1970-01-01
    • 2017-09-27
    • 1970-01-01
    相关资源
    最近更新 更多