首页 文章

我可以在同情中使用符号交叉产品操作吗?

提问于
浏览
1

嗨,

我正在尝试编写一个符号库,用于以分析方式计算3D多项式(变量是实数值t,多项式的单项式是3D矢量) . 特别是,我想计算两个多项式的叉积(在that question的后续中) . 在Sympy,我发现我可以:

  • 使用来自sympy.physics.mechanics包的显式向量变量(带有实数值),在这种情况下,定义了叉积 .

  • 使用矩阵符号,但没有为这些符号定义叉积 .

有什么方法可以象征性地代表交叉产品吗?

编辑:特别是,我感兴趣的是使两个相同向量的交叉乘积无效,并考虑在用一个向量分解多项式时的反交换性质 .

新编辑:为了让自己更清楚,我希望保持“符号层面” . 也就是说,我不想在每个变量上开发向量的项 .

例如,以下是计算贝塞尔曲线的代码:

from sympy import *

init_printing(use_unicode=True)

from scipy.special import binom

#default control points of a Bezier curve
p_is = [symbols('p'+str(i))  for i in range(5)] 


class Bezier:    
    #eq is the equation of the curve, pis are the stored control point
    #for special purpose such as the derivatives
    def __init__(self, deg, eq = None, pis = None):
        assert(deg)
        self.deg = deg;
        n_pts = deg +1 
        if pis == None:
            self.pis = p_is[:n_pts]
        else:
            self.pis = pis[:]; 
        if eq == None:
            #computing the bernstein polynoms for a given degree
            factors = [binom(deg,i) * t**i * (1-t)**(deg-i)*pis[i] for i in range(n_pts)]
            self.eq = sum(factors);
        else:
            self.eq = eq


    def __repr__(self):
        res  = "Degree : "        + str(self.deg) 
        res += "\nEquation : "    + self.eq.__repr__()
        res += "\nwaypoints :\n"  + str(self.pis) 
        return res


    def __str__(self):
        return self.__repr__()


b = Bezier(3)

print b 
# Degree : 3
# Equation : 1.0*p0*(-t + 1)**3 + 3.0*p1*t*(-t + 1)**2 + 3.0*p2*t**2*(-t + 1) + 1.0*p3*t**3
# waypoints :
# [p0, p1, p2, p3]

print b.eq
# 1.0*p0*(-t + 1)**3 + 3.0*p1*t*(-t + 1)**2 + 3.0*p2*t**2*(-t + 1) + 1.0*p3*t**3

可以看出,变量p_is是向量的事实并不是真正相关的,除了出现叉积的情况 . 如果我要计算b与自身的交叉乘积,那么几个项就会消失,因为有些向量会与自身交叉 .

我试图做的是用简单的乘法“模拟”交叉乘积,然后迭代得到的等式去除所有平方项(对应于零) . 但这还不够,因为该产品不能保持交叉产品的反交换方面 .

我真正想要的是实际的交叉乘积符号(比如X)出现在等式中 . 我希望我更清楚

非常感谢你的帮助

史蒂夫

1 回答

  • 1

    我发现了一个适用于我的案例的解决方案(我只使用一次交叉产品,需要一些反思才能考虑扩展) . 我们的想法是使用额外的符号来表示实现交叉积的偏斜对称矩阵 . 例如,p0 ^ p1将被写为Cp0 * p1 . 我实现了一个实现此目的的方法,并确保如果pi ^ pi = 0 .

    为了更好的分解,我基于符号的字母顺序引入了任意变换顺序 . 这意味着将写入p2 ^ p1 -Cp1 * p2这是因为其他简化,例如Cp2 ^ p1 Cp1 ^ p2 = 0将不会被sympy检测到 .

    无论如何,这是相当hacky但在我的情况下,它允许我写我的库,所以在这里 .

    执行交叉产品的方法是“交叉”,位于文件末尾 .

    #declaring vector symbols variables
    p_is = [symbols('p'+str(i))  for i in range(20)]
    #the cross product will be represented 
    #by the skew symmetric matrix Cpi for a vector pi.
    #Since in the resulting equation, symbols seem to appeer
    #in alphabetic order, the matrix multiplication will be coherent
    p_isX = [symbols('Cp'+str(i)+'')  for i in range(20)]
    
    #achieves the cross product between two elements
    #s0 and s1 are the considered vector symbols (here, two pis)
    #e0 and e1 are the scalar multiplier of each term
    def crossElement(s0,e0,s1,e1):
        if s0 == s1:
            return 0
        else:
            # here, take order of apparition into account to allow 
            # future factorization. Otherwise
            # something like p0 X p1 + p1 X p0 will not be dientified as zero
            id0 = p_is.index(s0)
            id1 = p_is.index(s1)
            if(id0 < id1):
                return simplify(e1*e0*p_isX[id0]*s1)
            else:
                return simplify((-e1)*e0*p_isX[id1]*s0)
    
    #retrieve all the pis and associate scalar factors
    #from an equation
    def getAllSymbols(eq):
        res = []
        for el in p_is:
            dic = eq.as_poly(el).as_dict()
            if(len(dic) > 1): 
                res += [(el, dic[(1,)])]
        return res;
    
    #generates the cross product of two equations,
    #where each pi term is a vector, and others
    #are scalar variable.
    #cross product
    def cross(eq1,eq2):
        decomp1 = getAllSymbols(eq1)
        decomp2 = getAllSymbols(eq2)
        res = 0
        #applies distributive cross product between
        #all terms of both equations
        for (s0, e0) in decomp1:
            for (s1, e1) in decomp2:
                res += crossElement(s0,e0,s1,e1)
        return res
    

相关问题