import random import copy EPS = 0.00001 class MatrixException( Exception ): pass class Matrix( object ): def __init__( self, rows, cols, values_list = None, description = None ): self.rows = rows self.cols = cols self.matrix = [ [ 0 for c in xrange( cols ) ] for r in xrange( rows ) ] if values_list: for r in xrange( rows ): for c in xrange( cols ): try: self.matrix[r][c] = values_list[cols * r + c] except IndexError: self.matrix[r][c] = 0 if description: self.description = description def __getitem__( self, index ): #以后写 if isinstance( index, str ): pass else: return self.matrix[index] def __repr__( self ): for r in xrange( self.rows ): print self.matrix[r] return '' def transpose( self ): M = Matrix( self.cols, self.rows ) for c in xrange( self.cols ): for r in xrange( self.rows ): M[c][r] = self.matrix[r][c] return M @property def T( self ): return self.transpose() @staticmethod def mul( M, factor ): res = Matrix( M.rows, M.cols ) for r in xrange( M.rows ): for c in xrange( M.cols ): res[r][c] = M[r][c] * factor res = Matrix.format_matrix( res ) return res def __sub__( self, other ): try: if self.rows != other.rows or self.cols != other.cols: raise MatrixException M = Matrix( self.rows, self.cols ) for r in xrange( self.rows ): for c in xrange( self.cols ): M[r][c] = self[r][c] - other[r][c] M = Matrix.format_matrix( M ) return M except MatrixException: print "two matrix must be the same size." def __rmul__( self, other ): try: if not isinstance( other, float ): raise TypeError return Matrix.mul( self, other ) except TypeError: print "factor must be float." def __mul__( self, other ): if isinstance( other, float ): return Matrix.mul( self, other ) elif isinstance( other, Matrix ): try: if self.cols != other.rows: raise MatrixException M = Matrix( self.rows, other.cols ) for r in xrange( self.rows ): for c in xrange( other.cols ): M[r][c] = cross_product( self[r], map( lambda x: x[c], other ) ) M = Matrix.format_matrix( M ) return M except MatrixException: print "self.cols must be equal to other.rows" else: pass @staticmethod def format_matrix( M ): global EPS for r in xrange( M.rows ): for c in xrange( M.cols ): if abs( M[r][c] ) < EPS: M[r][c] = 0.0 else: M[r][c] = round( M[r][c], 7 ) return M def random_create( self, min = 1, max = 20 ): for r in xrange( self.rows ): for c in xrange( self.cols ): self[r][c] = random.randint( min, max ) def get_col( self, col ): M = Matrix( self.rows, 1 ) for r in xrange( self.rows ): M[r][0] = self[r][col] return M def QR( self ): R = copy.deepcopy( self ) Q = IdentityMatrix( self.rows ) for c in xrange( self.cols ): col_matrix = R.get_col( c ) H = create_householder_matrix_by_cleared_to_zero( col_matrix, c ) Q = H * Q R = H * R return Q , R class IdentityMatrix( Matrix ): def __init__( self, size = 1 ): self.matrix = [ [ 1 if c == r else 0 for c in xrange( size ) ] for r in xrange( size ) ] self.rows = self.cols = size def __sub__( self, other ): try: if other.rows != other.cols: raise TypeError self.matrix = [ [ 1 if c == r else 0 for c in xrange( other.rows ) ] for r in xrange( other.rows ) ] self.rows = self.cols = other.rows return Matrix.__sub__( self, other ) except TypeError: print "matrix.rows must be equal to matrix.cols." def cross_product( a, b ): return reduce( lambda x, y : x + y, map( lambda x: x[0] * x[1], zip( a, b ) ) ) def create_householder_matrix_by_mirror_base( vector, mirror_base ): global I cut_index = mirror_base.index( 1 ) sign = -1 if vector[cut_index] < 0 else 1 sigma = sign * ( cross_product( vector, vector ) ) ** 0.5 U = vector[:cut_index] + [sigma + vector[cut_index]] + vector[cut_index + 1:] U = Matrix( len( U ), 1, U ) rho = 0.5 * ( U.transpose() * U )[0][0] H = I - ( 1.0 / rho ) * ( U * U.transpose() ) return H def create_householder_matrix_by_cleared_to_zero( vector, cut_index ): if isinstance( vector, Matrix ): res = [] for r in xrange( vector.rows ): res.append( vector[r][0] ) vector = res global I sign = -1 if vector[cut_index] < 0 else 1 sigma = sign * ( cross_product( vector[cut_index:], vector[cut_index:] ) ) ** 0.5 mirror = vector[:cut_index] + [-sigma] + [0] * ( len( vector ) - cut_index - 1 ) U = map( lambda x: x[0] - x[1], zip( vector, mirror ) ) U = Matrix( len( U ), 1, U ) rho = 0.5 * ( U.transpose() * U )[0][0] H = I - ( 1.0 / rho ) * ( U * U.transpose() ) return H I = IdentityMatrix() M1 = Matrix( 5, 5 ) M1.random_create() Q, R = M1.QR() print "Q:\n", Q print "R:\n", R
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-19 16:56:03