def mult_vec_upper_symmetric_by_axpy(self, vec): """ This function implements a matrix vector mult based on AXPY using an upper simmetrix matric :vec: Vector, the vector to work on :returns: Vector """ result = Vector([0]* self.rows()) it = self.full_iterator() vit = result.vector_iterator() for i,data in enumerate(it): #slicing the vector tl, value, bl = vit.next() #computing the diagonal value value = data["a11"] * vec[i] + value #we perform two different axpy and we make up for the missing part #by using the equivalent transposed of the column below the diagonal #aka the row after the diagonal tl = data["a01"].axpy(tl,vec[i]) bl = data["at12"].axpy(bl,vec[i]) #merging the result back in vit.merge(tl,value,bl) return result
def mult_vec_lower_symmetric_by_axpy(self, vec): """ This function implements a matrix vector mult based on AXPY using an upper simmetrix matric :vec: Vector, the vector to work on :returns: Vector """ result = Vector([0]* self.rows()) it = self.full_iterator() vit = result.vector_iterator() for i,data in enumerate(it): #slicing the vector tl, value, bl = vit.next() #computing the diagonal value value = data["a11"] * vec[i] + value tl = data["at10"].axpy(tl,vec[i]) bl = data["a21"].axpy(bl,vec[i]) #merging the result back in vit.merge(tl,value,bl) return result
def mult_vec_lower_triangular_by_axpy(self, vec): """ This function implements a lower triangular matrix vector mult based on AXPY :vec: Vector, the vector to work on :returns: Vector """ result = Vector([0]* self.rows()) it = self.full_iterator() vit = result.vector_iterator() for i,data in enumerate(it): #slicing the vector tl, value, bl = vit.next() #computing the diagonal value value = data["a11"] * vec[i] + value #computing the upper diagonal value, using an axpy #and accumulating in the up vector bl = data["a21"].axpy(bl,vec[i]) #merging the result back in vit.merge(tl,value,bl) return result
def mult_vec_upper_symmetric_by_axpy(self, vec): """ This function implements a matrix vector mult based on AXPY using an upper simmetrix matric :vec: Vector, the vector to work on :returns: Vector """ result = Vector([0] * self.rows()) it = self.full_iterator() vit = result.vector_iterator() for i, data in enumerate(it): #slicing the vector tl, value, bl = vit.next() #computing the diagonal value value = data["a11"] * vec[i] + value #we perform two different axpy and we make up for the missing part #by using the equivalent transposed of the column below the diagonal #aka the row after the diagonal tl = data["a01"].axpy(tl, vec[i]) bl = data["at12"].axpy(bl, vec[i]) #merging the result back in vit.merge(tl, value, bl) return result
def mult_vec_lower_symmetric_by_axpy(self, vec): """ This function implements a matrix vector mult based on AXPY using an upper simmetrix matric :vec: Vector, the vector to work on :returns: Vector """ result = Vector([0] * self.rows()) it = self.full_iterator() vit = result.vector_iterator() for i, data in enumerate(it): #slicing the vector tl, value, bl = vit.next() #computing the diagonal value value = data["a11"] * vec[i] + value tl = data["at10"].axpy(tl, vec[i]) bl = data["a21"].axpy(bl, vec[i]) #merging the result back in vit.merge(tl, value, bl) return result
def mult_vec_lower_triangular_by_axpy(self, vec): """ This function implements a lower triangular matrix vector mult based on AXPY :vec: Vector, the vector to work on :returns: Vector """ result = Vector([0] * self.rows()) it = self.full_iterator() vit = result.vector_iterator() for i, data in enumerate(it): #slicing the vector tl, value, bl = vit.next() #computing the diagonal value value = data["a11"] * vec[i] + value #computing the upper diagonal value, using an axpy #and accumulating in the up vector bl = data["a21"].axpy(bl, vec[i]) #merging the result back in vit.merge(tl, value, bl) return result
def next(self): """ This is the function used to step the iterator forward :returns: Vector, float, Vector, which are in order the column vector above the diagonal, the diagonal value, and the vector below the diagonal """ if self.counter < self.columns: #if we did not extinguish the iterator we check if the counter #is 0, meaning the first iteration. #if this is the case the TL (top left part) of the matrix #will be an empty vector #todo: probably the check is useless the slice operation would retunr an empty #list anyway if self.counter == 0: TL = Vector([]) else: TL = Vector(self.data[self.counter][:self.counter]) #we extrapolate out the diagonal value , here is where we lose the reference #to the original value value = self.data[self.counter][self.counter] #the BL (bottom left part) is nothing more then the remaining column vector #below the the diagonal BL = Vector(self.data[self.counter][self.counter+1:]) self.counter +=1 return [TL, value, BL] else: raise StopIteration()
def test_solve_upper_triangular_system(self): mat = SquareMatrix.from_list(3, [-2, 0, 0, -1, -3, 0, 1, -2, 1]) vec = Vector([6, 9, 3]) it = vec.vector_iterator(True) res = mat.solve_upper_triangular_system(vec) self.is_vector_equal_to_list(res, [1, -5, 3])
def test_creation_from_vectors(self): vec1 = Vector(self.lsF2[:4]) vec2 = Vector.copy(vec1) vec3 = Vector.copy(vec1) vec4 = Vector.copy(vec1) mat = matrix.Matrix.from_vectors([vec1, vec2, vec3, vec4]) self.is_matrix_equal(self.matF2, mat)
def test_creation_from_vectors(self): vec1 = Vector(self.lsF2[:4]) vec2 = Vector.copy(vec1) vec3 = Vector.copy(vec1) vec4 = Vector.copy(vec1) mat = matrix.Matrix.from_vectors([vec1,vec2,vec3,vec4]) self.is_matrix_equal(self.matF2, mat)
def test_mult_vec_by_axpy_parted(self): res = self.matF1.mult_vec_by_axpy_parted(Vector([1, 2, 3, 4])) self.is_vector_equal_to_list(res, [0, 0, 0, 0]) res = self.matF2.mult_vec_by_axpy_parted(Vector([1, 2, 3, 4])) self.is_vector_equal_to_list(res, [10, 20, 30, 40]) res = self.matF3.mult_vec_by_axpy_parted(Vector([5, 4, 3])) self.is_vector_equal_to_list(res, [41, 16, 38])
def test_mult_vec_lower_symmetric_by_axpy(self): vec = Vector([3, 5, 3, 4]) res = self.matF11.mult_vec_lower_symmetric_by_axpy(vec) self.is_vector_equal_to_list(res, [38, 41, 49, 60]) self.matF11.set_upper_simmetry() vec = Vector([3, 5, 3, 4]) res = self.matF11.mult_vec_lower_symmetric_by_axpy(vec) self.is_vector_equal_to_list(res, [38, 41, 49, 60])
def test_solve_upper_triangular_system(self): mat = SquareMatrix.from_list(3, [-2,0,0,-1,-3,0,1,-2,1]) vec = Vector([6,9,3]) it = vec.vector_iterator(True) res = mat.solve_upper_triangular_system(vec) self.is_vector_equal_to_list(res,[1,-5,3])
def test_mult_by_transposed_matrix_axpy(self): res = self.matF1.mult_vec_by_transposed_matrix_axpy( Vector([1, 2, 3, 4])) self.is_vector_equal_to_list(res, [0, 0, 0, 0]) res = self.matF2.mult_vec_by_transposed_matrix_axpy( Vector([1, 2, 3, 4])) self.is_vector_equal_to_list(res, [30, 30, 30, 30]) res = self.matF3.mult_vec_by_transposed_matrix_axpy(Vector([5, 4, 3])) self.is_vector_equal_to_list(res, [31, 42, 20])
def test_mult_vec_by_axpy(self): res = self.matF1.mult_vec_by_dot(Vector([1, 2, 3, 4])) self.is_vector_equal_to_list(res, [0, 0, 0, 0]) res = self.matF2.mult_vec_by_dot(Vector([1, 2, 3, 4])) self.is_vector_equal_to_list(res, [10, 20, 30, 40]) #mat = self.matF2.mult_matrix_update_by_column(self.matF9) #self.is_matrix_equal_to_matrix(mat, self.matF2) res = self.matF3.mult_vec_by_dot(Vector([5, 4, 3])) self.is_vector_equal_to_list(res, [41, 16, 38])
def test_creation(self): mat = SquareMatrix(4, None, True) self.is_matrix_equal(self.matF8, mat) mat = SquareMatrix(4, [ Vector([1, 0, 0, 0]), Vector([0, 1, 0, 0]), Vector([0, 0, 1, 0]), Vector([0, 0, 0, 1]) ], False) self.is_matrix_equal(self.matF8, mat)
def next(self): if (self.end_condition()): #top matrix #column above diagonal self.a01 = Vector(self.data[self.counter][:self.counter]) #diagonal value self.a11= self.data[self.counter][self.counter] #columb below diagonal self.a21= Vector(self.data[self.counter][self.counter+1:]) #row before diagonal self.at10= Vector(Vector([self.data[x][self.counter] for x in range(self.counter)])) #row after diagonal self.at12 = Vector([self.data[x][self.counter] for x in range(self.counter+1,self.columns)]) ##matirces if self.counter == 0: self.A00 = matrix.Matrix(0,0) self.A20 = matrix.Matrix(0,0) else: self.A00 = matrix.Matrix.from_vectors([Vector(self.data[c][:self.counter] ) for c in range(self.counter)]) #here we check first if there is no zero column or row in the matrix we would create, if so we create an empty #matrix if (self.counter+1 < (self.rows) and self.counter <(self.columns)): self.A20 = matrix.Matrix.from_vectors([Vector(self.data[c][self.counter+1:] ) for c in range(self.counter)]) else: self.A20 = matrix.Matrix(0,0) #here we need to check if we are not going out of bound if (self.counter+1 <self.columns) and self.counter > 0 : self.A02 = matrix.Matrix.from_vectors([Vector(self.data[c][:self.counter] ) for c in range(self.counter+1,self.columns)]) else: self.A02= matrix.Matrix(0,0) #here we check first if there is no zero column or row in the matrix we would create, if so we create an empty #matrix if (self.counter+1 < (self.rows) and self.counter+1 <(self.columns)): self.A22 = matrix.Matrix.from_vectors([Vector(self.data[c][self.counter+1:] ) for c in range(self.counter+1,self.columns)]) else: self.A22 = matrix.Matrix(0,0) self.counter += self.counter_speed to_return = {"A00": self.A00, "a01": self.a01, "A02": self.A02, "at10":self.at10, "a11": self.a11, "at12":self.at12, "A20": self.A20, "a21": self.a21, "A22": self.A22} return to_return else: raise StopIteration()
def test_solve_lower_triangular_system(self): mat = SquareMatrix.from_list(3, [2, 4, 6, 4, -2, -4, -2, 6, 2]) L, U = mat.lu_factorization() vec = Vector([-10, 20, 18]) res = L.solve_lower_triangular_system(vec) self.is_vector_equal_to_list(res, [-10, 40, -16])
def test_gaussian_appended_reduction_upper_triangular(self): mat = SquareMatrix.from_list(3, [2, 4, 6, 4, -2, -4, -2, 6, 2]) res = mat.gaussian_reduction_upper_triangular(True) vec = Vector([-10, 20, 18]) res = res.gaussian_appended_reduction_upper_triangular(vec) self.is_vector_equal_to_list(res, [-10, 40, -16])
def test_solve_linear_system(self): mat = SquareMatrix.from_list( 4, [2, -2, 4, -4, 0, -1, -1, 1, 1, 1, 5, -3, 2, -1, 4, -8]) vec = Vector([2, 2, 11, -3]) res = mat.solve_linear_system(vec) self.is_vector_equal_to_list(res, [1, -1, 2, -1])
def next(self): """ Function to setp forward the iterator """ #first we check if finised the iteration if self.counter < self.rows: #we slice the data and upgrade the counter to_return = Vector([self.data[c][self.counter] for c in xrange(self.columns)]) self.counter +=1 return to_return else: #if we are done we rise a stop iteration exception raise StopIteration()
def from_list(cls, size=4, data=None): """ Alternative constuctor used to build a square matrix from a list of elements Args: :size: integer, the size of the NxN matrix :data: float[], the data used for thea matrix columns """ vectors = [] for c in range(size): vec = Vector([data[c * size + r] for r in range(size)]) vectors.append(vec) inst = cls(size, vectors, False) return inst
def test_gaussian_reduction_upper_triangular(self): mat = SquareMatrix.from_list(3, [2, 4, 6, 4, -2, -4, -2, 6, 2]) res = mat.gaussian_reduction_upper_triangular() self.is_matrix_equal_to_list(res, [2, 0, 0, 4, -10, 0, -2, 10, -8]) res = mat.gaussian_reduction_upper_triangular(True) self.is_matrix_equal_to_list(res, [2, 2, 3, 4, -10, 1.6, -2, 10, -8]) vec = Vector([-10, 20, 18]) res = mat.gaussian_reduction_upper_triangular(True, vec) self.is_matrix_equal_to_list(res, [2, 2, 3, 4, -10, 1.6, -2, 10, -8]) self.is_vector_equal_to_list(vec, [-10, 40, -16]) mat = SquareMatrix.from_list(3, [1, -3, 1, 1, 0, 13, 2, -3, 20]) res = mat.gaussian_reduction_upper_triangular() self.is_matrix_equal_to_list(res, [1, 0, 0, 1, 3, 0, 2, 3, 6])
def mult_vec_lower_symmetric_by_dot(self, vec): """ This funtion transforms a vector using a lower simmetric matrix, means we don't neet to use the upper traingular matrix which might old other data, we use dot product under the hood to perform the computation :vec: Vector, the vector to be transformed """ result = Vector([0] * self.rows()) it = self.full_iterator() vit = vec.vector_iterator() for i, data in enumerate(it): #we slice the vector calling manually the iterator next tl, value, bl = vit.next() #here instead of the upper column before the diagonal we use the #row before the diagonal result[i] = (data["at10"].dot(tl) + data["a11"] * value + data["a21"].dot(bl)) return result
def mult_vec_upper_symmetric_by_dot(self, vec): """ This function multiplies the given vector by an upper simmetric matrix, this will allow to perform less computation by exploiting the simmetry :vec: Vector, the vector to be transformed :returns: Vector """ result = Vector([0] * self.rows()) it = self.full_iterator() vit = vec.vector_iterator() for i, data in enumerate(it): #we slice the vector calling manually the iterator next tl, value, bl = vit.next() #to nothe here instead the first part of the row (before the diagonal #we use the column before the diagona, exploiting the simmetry result[i] = (data["a01"].dot(tl) + data["a11"] * value + data["at12"].dot(bl)) return result
def solve_lower_triangular_system(self, b): """ This function is going to solve for L*z = b where we solve for z, b is given and L is a lower unit triangular matrix (most likely the result of a LU operation) :b: Vector, the vector needed to solve the system :returns: Vector """ res = Vector.copy(b) bit = res.vector_iterator() it = self.full_iterator() for TL, value, BL in bit: data = it.next() BL = BL + (-(value * data["a21"])) bit.merge(TL, value, BL) return res
def solve_lower_triangular_system(self, b): """ This function is going to solve for L*z = b where we solve for z, b is given and L is a lower unit triangular matrix (most likely the result of a LU operation) :b: Vector, the vector needed to solve the system :returns: Vector """ res = Vector.copy(b) bit = res.vector_iterator() it = self.full_iterator() for TL,value,BL in bit: data = it.next() BL = BL + (-(value * data["a21"])) bit.merge(TL,value,BL) return res
def mult_vec_lower_triangular_by_dot(self, vec): """ This function is multiplying a vector by an upper triangular matrix using a parted matrix and the dot product approach, the optimmization comes from the fact we don't need to perform the computation of the row after the current diagonal index :vec: Vector, the value to multiply :returns: Vector """ result = Vector([0] * self.rows()) it = self.full_iterator() vit = vec.vector_iterator() for i, data in enumerate(it): #we slice the vector calling manually the iterator next tl, value, bl = vit.next() #we accumualte the result in the proper index of the result vector #the result is composed of the result of diagonal value being multiplied #plus the row before the diagonal result[i] = (data["a11"] * value + tl.dot(data["at10"])) return result
def solve_upper_triangular_system(self,b): """ This function is the complementary one for solving a liner equation system based on LU, with solve_lower_triangular_system we solved L* z = b where now we can solve U* x = b where z = U*x and U is the upper triangular matrix from the factoriazition, basically we are performing a backward sostiuition :b: Vector, the vector needed to solve the system :returns: Vector """ res = Vector.copy(b) bit = res.vector_iterator(True) it = self.full_iterator(True) for TL,value,BL in bit: data = it.next() value -= data["at12"].dot(BL) value /= data["a11"] bit.merge(TL,value,BL) return res
def solve_upper_triangular_system(self, b): """ This function is the complementary one for solving a liner equation system based on LU, with solve_lower_triangular_system we solved L* z = b where now we can solve U* x = b where z = U*x and U is the upper triangular matrix from the factoriazition, basically we are performing a backward sostiuition :b: Vector, the vector needed to solve the system :returns: Vector """ res = Vector.copy(b) bit = res.vector_iterator(True) it = self.full_iterator(True) for TL, value, BL in bit: data = it.next() value -= data["at12"].dot(BL) value /= data["a11"] bit.merge(TL, value, BL) return res
def copy(cls, mat): """ Alternative constructor to generate a matrix identical to the given one """ return cls(mat.columns(), [Vector.copy(v) for v in mat.column_iterator()], False)
def test_mult_vec_upper_triangular_by_axpy(self): vec = Vector([1, 2, 3, 4]) res = self.matF9.mult_vec_upper_triangular_by_axpy(vec) self.is_vector_equal_to_list(res, [10, 18, 21, 16])
def test_mult_vec_lower_triangular_by_axpy(self): vec = Vector([1, 2, 3, 4]) res = self.matF11.mult_vec_lower_triangular_by_axpy(vec) self.is_vector_equal_to_list(res, [1, 6, 18, 40])
def merge(self, TL, value, BL): self.data[self.counter -1] = Vector(TL.values + [value] + BL.values)
def copy(cls, mat): """ Alternative constructor to generate a matrix identical to the given one """ return cls(mat.columns(),[Vector.copy(v) for v in mat.column_iterator()],False)