1. 程式人生 > >python 自定義 計算向量投影 正交 函式

python 自定義 計算向量投影 正交 函式

# coding=utf-8
from math import sqrt, acos, pi


class Vector(object):
    """docstring for Vector"""
    """根據座標軸列表輸入 建立向量, 並建立該向量所處的空間維度"""
    CANNOT_NORMALIZE_ZERO_VECTOR_MSG = 'Cannot normalize the zero vector'
    def __init__(self, coordinates):
        super(Vector, self).__init__()
        try:
            if not coordinates:
                raise ValueError
            self.coordinates = tuple(coordinates)
            self.dimension = len(coordinates)    
        except ValueError:
            raise ValueError('The coordinates must be nonempty')
        except TypeError:
            raise TypeError('The coordinates must be an iterable')

    # '''能夠使python的內建print函式 輸出向量座標軸'''

    def __str__(self):
        return 'Vector: {}'.format(self.coordinates)
    
    def scalarMultiply(self,num):  
        new_corrdinate =[num * x for x in self.coordinates]  
        return Vector(new_corrdinate)  
   
    def minus(self,v):  
        new_corrdinate = [x-y for x,y in zip(self.coordinates, v.coordinates)]  
        return Vector(new_corrdinate)  

    # 將向量歸一化
    def normalized(self):
        try:
            magnitude = self.magnitude()
            return  Vector([x *1.0/ magnitude for x in self.coordinates])
        except ZeroDivisionError:
            raise Exception('Cannot normalized the zero myVector2')

    # 點積
    def dot(self, v):
        # print([x*y for x,y in zip(self.coordinates, v.coordinates)])
        return sum([round(x*y,3) for x,y in zip(self.coordinates, v.coordinates)])
   
    # 投影
    def projection(self, b):
        ub = b.normalized()
        dot_num = self.dot(ub)
        new_cordinates = ub.scalarMultiply(dot_num)
        return new_cordinates
    # 垂直
    def vertical(self,b):
        projection_v = self.projection(b)
        new_cordinates = self.minus(projection_v)
        return new_cordinates
        

v1 = Vector([3.039, 1.879])
v2 = Vector([0.825, 2.036])
print v1.projection(v2)

v3 = Vector([-9.88, -3.264, -8.159])
v4 = Vector([-2.155, -9.353, -9.473])
print v3.vertical(v4)


v5 = Vector([3.009,-6.172,3.692,-2.51])
v6 = Vector([6.404,-9.144,2.759,8.718])
print v5.projection(v6)
print v5.vertical(v6)

# 輸出
# Vector: (1.0823253260174353, 2.671047713662422)
# Vector: (-8.350069611957737, 3.3761108674521076, -1.4336957930745413)
# Vector: (1.968617063395022, -2.810904813817002, 0.8481284319030084, 2.679950586926578)
# Vector: (1.040382936604978, -3.3610951861829976, 2.8438715680969917, -5.189950586926578)
# [Finished in 0.2s]

優化後

    def component_parallel_to(self, basis):
        try:
            u = basis.normalized()
            weight = self.dot(u)
            return u.scalarMultiply(weight)
        except Exception as e:
            if str(e) == self.CANNOT_NORMALIZE_ZERO_VECTOR_MSG:
               raise Exception(self.CANNOT_NORMALIZE_ZERO_VECTOR_MSG)
        else:
            raise e

    def component_orthogonal_to(self, basis):
        try:
            projection = self.component_parallel_to(basis)
            return self.minus(projection)
        except Exception, e:
            if str(e) == self.NO_UNIQUE_ORTHOGONAL_COMPONENT_MSG:
                raise Exception(self.NO_UNIQUE_ORTHOGONAL_COMPONENT_MSG)
            else:
                raise e