Пример #1
0
 def is_invalid(
         self,
         matrix):  #tests the last row to see if it has a contradiction
     # should I use more conditions to test? Test row 1 and row 2?
     return MyDecimal(matrix[2][1]).is_near_zero() and MyDecimal(
         matrix[2][2]).is_near_zero() and not MyDecimal(
             matrix[2][3]).is_near_zero()
Пример #2
0
 def invalid_plane(self):
     if not MyDecimal(self.constant_term).is_near_zero():
         for i in range(self.dimension):
             if not MyDecimal(self[i]).is_near_zero():
                 return False
         return True
     return False
Пример #3
0
 def __eq__(self, p):
     if self.dimension != p.dimension:
         return False
     for i in range(self.dimension):
         if not MyDecimal(
                 float(self.normal_vector[i]) -
                 float(p.normal_vector[i])).is_near_zero():
             return False
     if not MyDecimal(self.constant_term - p.constant_term).is_near_zero():
         return False
     return True
Пример #4
0
 def __eq__(self, v):
     if self.dimension != v.dimension:
         return False
     for i in range(self.dimension):
         if not MyDecimal(self.coordinates[i] - v.coordinates[i]).is_near_zero():
             return False
     return True
Пример #5
0
 def swap_with_highest_nonzero_row(self, row, column): #swap row with the highest row that's nonzero in the same column
     changed = False
     for i in range(row+1, len(self.planes)):
         if not MyDecimal(self.planes[i][column]).is_near_zero():
             self.swap_rows(row, i)
             changed = True
             break
     return changed
Пример #6
0
 def reduce_matrix(self, matrix):
     # get [0][0] to 1, [1][0] to 0, [2][0] to 0, [1][1] to 1, [2][1] to 0, and [2][1] to 0 in that order.
     # if stuck, swap. If [0][0] is 0, swap with the highest row with a nonzero in that column
     # If [1][1] is 0, swap with row 3 
         
     #get [0][0] to 1
     if MyDecimal(matrix[0][0]).is_near_zero():
         if not MyDecimal(matrix[1][0]).is_near_zero():
             matrix = self.swap_rows(matrix, 0, 1)
         elif not MyDecimal(matrix[2][0]).is_near_zero():
             matrix = self.swap_rows(matrix, 0, 2)
     
     leadCoefficient = matrix[0][0]
     if not MyDecimal(leadCoefficient).is_near_zero():
         for i in range(4):
             matrix[0][i] /= leadCoefficient
     
     #get [1][0] to 0
     leadCoefficient = matrix[1][0]
     for i in range(4):
         matrix[1][i] -= leadCoefficient*matrix[0][i]
     
     #get [2][0] to 0
     leadCoefficient = matrix[2][0]
     for i in range(4):
         matrix[2][i] -= leadCoefficient*matrix[0][i]
     
     #get [1][1] to 1
     if MyDecimal(matrix[1][1]).is_near_zero():
         if not MyDecimal(matrix[2][1]).is_near_zero():
             matrix = self.swap_rows(matrix, 1, 2)
     leadCoefficient = matrix[1][1]
     if not MyDecimal(leadCoefficient).is_near_zero():
         for i in range(3):
             matrix[1][i+1] /= leadCoefficient
     
     #get [2][1] to 0
     leadCoefficient = matrix[2][1]
     if not MyDecimal(leadCoefficient).is_near_zero():
         for i in range(4):
             matrix[2][i] -= leadCoefficient*matrix[1][i]
     
     #get [2][2] to 1
     
     leadCoefficient = matrix[2][2]
     if not MyDecimal(leadCoefficient).is_near_zero():
         for i in range(2):
             matrix[2][i+2] /= leadCoefficient
     
     return matrix
Пример #7
0
    def solve_line(self, system): #should I update for x = 0 in all columns?
        # remember pivot vs free variables
        # identify whether y or z can be solved for
        if MyDecimal(system[1][1]).is_near_zero(): # z can be solved for
            #solve for z: z = c/x3
           z = Decimal(round(system[1][3]/system[1][2], 3))
          # modify c: c += (y * x2) 
           c = Decimal(round(system[0][3] - (z*system[0][2]), 3))

           return str(system[0][0]) + "x + " + str(system[0][1]) + "y = " + str(c) + " and z = " + str(z)
        elif MyDecimal(system[1][2]).is_near_zero(): # y can be solved for
            # solve for y: y = c
            y = Decimal(round(system[1][3], 3))
            # modify c: c += (y * x2) 
            c = Decimal(round(system[0][3] - (y*system[0][1]), 3))
            return str(system[0][0]) + "x + " + str(system[0][2]) + "z = " + str(c) + " and y = " + str(y)
        else:
            return "Error. Could not solve."
Пример #8
0
 def angle(self, v, radians):
     dotProduct = self.dot_product(v)
     magnitudeProduct = self.magnitude() * v.magnitude()
     if MyDecimal(Decimal(magnitudeProduct)).is_near_zero():
             return 0
     elif radians:
         return math.acos(dotProduct/magnitudeProduct)
     else:
         if round(dotProduct/magnitudeProduct, 6) == 1.0000:
             return 0
         else:
             return math.degrees(math.acos(dotProduct/magnitudeProduct))
Пример #9
0
 def compute_rref(self):
     system = self.compute_triangular_form()
     system.extract_basepoint()
     system.extract_direction_vectors()
     
     for current_row in range(len(system.planes)):
         pivot_found = False
         for current_col in range(system.planes[0].dimension):
             if not MyDecimal(system.planes[current_row][current_col]).is_near_zero():
                 if not pivot_found:
                     pivot_found = True
                     system.clear_above(current_row, current_col)
                     system.set_pivot_to_one(current_row, current_col)
     return system
Пример #10
0
 def solve_system(self): # this assumes no free variables
     '''
     algorithm:
     if all are parallel to each other, return infinite solutions
     if any plane is invalid, indicate no solution
     for each row, starting from len(system.planes) and going to 0
         for each col from len(system.planes[0) to 0
             if a saved value exists for that column's variable, multiply it by the column variable and add it to the constant
             if the saved value doesn't exist, is the furthest left 1, and all values right except for constant are 0, save the value as the constant
         find answers
         if some variables are unassigned at the end, parameterize
     '''
     system = self.compute_rref()
     saved_solutions = ["None"] * system.planes[0].dimension
     are_parallel = True
     first_plane = system.planes[0]
     for i in range(1, len(system.planes)):
         if system.planes[i].invalid_plane():
             return "The system is invalid; there is no intersection."
         if not first_plane.is_parallel(system.planes[i]) or system.planes[i].is_blank(): #blank planes shouldn't count as parallel. They can be paramterized
             are_parallel = False
             break
     if are_parallel:
         return "The lines are parallel; the system has an infinite number of solutions."
     for i in range(len(system.planes)-1, -1, -1):
         leftmost_one = system.leftmost_one(i)
         for j in range(system.planes[0].dimension-1, -1, -1):
             if saved_solutions[j] != "None" and not MyDecimal(system[i][j]).is_near_zero():
                 system[i][system.planes[0].dimension] += saved_solutions[j] * system[i][j]
                 system[i][j] = 0
             else:
                 if j == leftmost_one:
                     saved_solutions[j] = system[i][system.planes[0].dimension]
     for i in range(len(saved_solutions)):
         if saved_solutions[i] == "None":
             copy_system = self.compute_rref()
             direction_vectors = copy_system.extract_direction_vectors() 
             basepoint = copy_system.extract_basepoint()
             return Parametrization(basepoint, direction_vectors)
             #return "Infinitely many solutions."
     return saved_solutions
Пример #11
0
 def compute_triangular_form(self):
     system = deepcopy(self)
     
     num_equations = len(self.planes)
     num_variables = self.planes[0].dimension
     current_column = 0
     
     for current_row in range(num_equations):
         current_column = current_row
         first_nonzero = True
         while current_column < num_variables:
             current_coefficient = system[current_row][current_column]
             if MyDecimal(current_coefficient).is_near_zero():
                 # move the first nonzero term up high
                 if first_nonzero: # if all preceding values are 0
                     if system.swap_with_highest_nonzero_row(current_row, current_column): #if a swappable row exists
                         # set column below pivot to zeroes
                         system.clear_below(current_row, current_column)   
                         if current_column == num_variables - 1 and self.planes[current_row][current_column] == 0:
                             current_column += 1
                     else:
                         current_column += 1
                 else:
                     current_column += 1
             else:
                 if first_nonzero: # if all the prior columns in this row are zeroes
                     # clear the first valued column's values in other rows
                     system.clear_below(current_row, current_column)
                     first_nonzero = False
                 current_column+=1
                 continue
     # convert the redundant equations to all zeroes
     if num_equations > num_variables:
         for i in range(num_variables, num_equations):
             system[i] = Plane()
     return system
Пример #12
0
 def first_nonzero_index(iterable):
     for k, item in enumerate(iterable):
         if not MyDecimal(item).is_near_zero():
             return k
     raise Exception(Plane.NO_NONZERO_ELTS_FOUND_MSG)
Пример #13
0
 def redundant3(self, matrix): #tests the last row to see if it's redundant
     return MyDecimal(matrix[2][1]).is_near_zero() and MyDecimal(matrix[2][2]).is_near_zero() and MyDecimal(matrix[2][3]).is_near_zero()
Пример #14
0
 def clear_below(self, row, column): # set to 0 below a pivot
     for i in range(row+1, len(self.planes)):
         if not MyDecimal(self.planes[i][column]).is_near_zero():
             cancel_ratio = -(self.planes[i][column] / self.planes[row][column])
             self.add_multiple_times_row_to_row(cancel_ratio, row, i)
Пример #15
0
 def clear_above(self, row, column): # set to 0 above a pivot
     for i in range(row):
         if not MyDecimal(self.planes[i][column]).is_near_zero():
             coefficient = -(self.planes[i][column] / self.planes[row][column])
             self.add_multiple_times_row_to_row(coefficient, row, i) #cancel the value directly above pivot
Пример #16
0
 def orthogonal_to(self, v): #dot product is close enough to zero, adjusting for rounding error
     dotProduct = self.dot_product(v)        
     return MyDecimal(Decimal(dotProduct)).is_near_zero()
Пример #17
0
 def parallel_to(self, v): #angle is close enough to zero, adjusting for rounding error
     angle = self.angle(v, False)
     print angle
     return MyDecimal(Decimal(angle)).is_near_zero() or MyDecimal(Decimal(angle - 180)).is_near_zero()
Пример #18
0
 def leftmost_one(self, row):
     for i in range(0, self.planes[0].dimension):
         if MyDecimal(Decimal(self.planes[row][i]) - Decimal(1.0)).is_near_zero():
             return i
     return -1
Пример #19
0
 def first_nonzero_index(iterable): # iterates through vector to return index of first nonzero term OR throws an exception
     for k, item in enumerate(iterable):
         if not MyDecimal(item).is_near_zero():
             return k
     raise Exception(Line.NO_NONZERO_ELTS_FOUND_MSG)
Пример #20
0
 def is_blank(self):
     is_blank = True
     for i in range(self.dimension + 1):
         if not MyDecimal(self[i]).is_near_zero():
             is_blank = False
     return is_blank