def __init__(self, normal_vector=None, constant_term=None): self.dimension = 3 if not normal_vector: all_zeros = ['0'] * self.dimension normal_vector = Vector(all_zeros) self.normal_vector = Vector(normal_vector) if not constant_term: constant_term = Decimal('0') self.constant_term = Decimal(constant_term) self.set_basepoint()
def __init__(self, normal_vector=None, constant_term=None): #normal_vector:法向量 constant_term:参数 self.dimension = 2 if not normal_vector: all_zeros = ['0'] * self.dimension normal_vector = Vector(all_zeros) self.normal_vector = Vector(normal_vector) #法向量的向量形式存储 if not constant_term: constant_term = Decimal('0') self.constant_term = Decimal(constant_term) self.set_basepoint()
def set_basepoint(self): try: n = self.normal_vector c = self.constant_term basepoint_coords = ['0'] * self.dimension initial_index = Line.first_nonzero_index(n) initial_coefficient = n[initial_index] basepoint_coords[initial_index] = c / initial_coefficient self.basepoint = Vector(basepoint_coords) except Exception as e: if str(e) == Line.NO_NONZERO_ELTS_FOUND_MSG: self.basepoint = None else: raise e
def calc_cross(self, l): #在2个向量既不平行也不重合的前提下,计算向量交点 try: result = self.is_parallel_to(l) if (not result): #获取2个法向量的坐标 a1 = self[0] b1 = self[1] a2 = l[0] b2 = l[1] #获取2个常参数 k1 = self.constant_term k2 = l.constant_term x = (b2 * k1 - b1 * k2) / (a1 * b2 - a2 * b1) y = (a1 * k2 - a2 * k1) / (a1 * b2 - a2 * b1) return Vector((x, y)) else: raise Exception(self.LINE_IS_PARALLEL) except Exception as e: if str(e) == self.LINE_IS_PARALLEL: raise Exception(self.LINE_IS_PARALLEL) else: raise e
class Line(object): NO_NONZERO_ELTS_FOUND_MSG = 'No nonzero elements found' LINE_IS_PARALLEL = 'Line is parallel' def __init__(self, normal_vector=None, constant_term=None): #normal_vector:法向量 constant_term:参数 self.dimension = 2 if not normal_vector: all_zeros = ['0'] * self.dimension normal_vector = Vector(all_zeros) self.normal_vector = Vector(normal_vector) #法向量的向量形式存储 if not constant_term: constant_term = Decimal('0') self.constant_term = Decimal(constant_term) self.set_basepoint() def set_basepoint(self): try: n = self.normal_vector c = self.constant_term basepoint_coords = ['0'] * self.dimension initial_index = Line.first_nonzero_index(n) initial_coefficient = n[initial_index] basepoint_coords[initial_index] = c / initial_coefficient self.basepoint = Vector(basepoint_coords) except Exception as e: if str(e) == Line.NO_NONZERO_ELTS_FOUND_MSG: self.basepoint = None else: raise e def __str__(self): num_decimal_places = 3 def write_coefficient(coefficient, is_initial_term=False): coefficient = round(coefficient, num_decimal_places) if coefficient % 1 == 0: coefficient = int(coefficient) output = '' if coefficient < 0: output += '-' if coefficient > 0 and not is_initial_term: output += '+' if not is_initial_term: output += ' ' if abs(coefficient) != 1: output += '{}'.format(abs(coefficient)) return output n = self.normal_vector try: initial_index = Line.first_nonzero_index(n) terms = [ write_coefficient(n[i], is_initial_term=(i == initial_index)) + 'x_{}'.format(i + 1) for i in range(self.dimension) if round(n[i], num_decimal_places) != 0 ] output = ' '.join(terms) except Exception as e: if str(e) == self.NO_NONZERO_ELTS_FOUND_MSG: output = '0' else: raise e constant = round(self.constant_term, num_decimal_places) if constant % 1 == 0: constant = int(constant) output += ' = {}'.format(constant) return output @staticmethod def first_nonzero_index(iterable): for k, item in enumerate(iterable): if not MyDecimal(item).is_near_zero(): return k raise Exception(Line.NO_NONZERO_ELTS_FOUND_MSG) # 以下代码均由本人编写 #返回法向量的坐标值 def __getitem__(self, item): return self.normal_vector.coordinates[item] #判断两直线是否重合 def __eq__(self, l): if (self.normal_vector.is_parallel_to(l.normal_vector)): minus_vector = self.basepoint.minus(l.basepoint) if (minus_vector.is_zero() or minus_vector.is_orthogonal_to( l.normal_vector)): #判断该向量是否与当前法向量正交 return True else: return False else: return False def is_parallel_to(self, l): return (self.normal_vector.is_parallel_to(l.normal_vector)) def calc_cross(self, l): #在2个向量既不平行也不重合的前提下,计算向量交点 try: result = self.is_parallel_to(l) if (not result): #获取2个法向量的坐标 a1 = self[0] b1 = self[1] a2 = l[0] b2 = l[1] #获取2个常参数 k1 = self.constant_term k2 = l.constant_term x = (b2 * k1 - b1 * k2) / (a1 * b2 - a2 * b1) y = (a1 * k2 - a2 * k1) / (a1 * b2 - a2 * b1) return Vector((x, y)) else: raise Exception(self.LINE_IS_PARALLEL) except Exception as e: if str(e) == self.LINE_IS_PARALLEL: raise Exception(self.LINE_IS_PARALLEL) else: raise e
def test3(): #线性方程组化简为行简化阶梯方程组 p1 = Plain(normal_vector=Vector(['1', '1', '1']), constant_term='1') p2 = Plain(normal_vector=Vector(['0', '1', '1']), constant_term='2') s = LinearSystem([p1, p2]) r = s.compute_rref() if not (r[0] == Plain(normal_vector=Vector(['1', '0', '0']), constant_term='-1') and r[1] == p2): print('test case 1 failed') else: print('test case 1 successed') LinearSystem_print(s, '原始方程') LinearSystem_print(r, '行简化阶梯化后方程') p1 = Plain(normal_vector=Vector(['1', '1', '1']), constant_term='1') p2 = Plain(normal_vector=Vector(['1', '1', '1']), constant_term='2') s = LinearSystem([p1, p2]) r = s.compute_rref() if not (r[0] == p1 and r[1] == Plain(constant_term='1')): print('test case 2 failed') else: print('test case 2 successed') LinearSystem_print(s, '原始方程') LinearSystem_print(r, '行简化阶梯化后方程') p1 = Plain(normal_vector=Vector(['1', '1', '1']), constant_term='1') p2 = Plain(normal_vector=Vector(['0', '1', '0']), constant_term='2') p3 = Plain(normal_vector=Vector(['1', '1', '-1']), constant_term='3') p4 = Plain(normal_vector=Vector(['1', '0', '-2']), constant_term='2') s = LinearSystem([p1, p2, p3, p4]) r = s.compute_rref() if not (r[0] == Plain(normal_vector=Vector(['1', '0', '0']), constant_term='0') and r[1] == p2 and r[2] == Plain(normal_vector=Vector(['0', '0', '-2']), constant_term='2') and r[3] == Plain()): print('test case 3 failed') else: print('test case 3 successed') LinearSystem_print(s, '原始方程') LinearSystem_print(r, '行简化阶梯化后方程') p1 = Plain(normal_vector=Vector(['0', '1', '1']), constant_term='1') p2 = Plain(normal_vector=Vector(['1', '-1', '1']), constant_term='2') p3 = Plain(normal_vector=Vector(['1', '2', '-5']), constant_term='3') s = LinearSystem([p1, p2, p3]) r = s.compute_rref() if not (r[0] == Plain(normal_vector=Vector(['1', '0', '0']), constant_term=Decimal('23') / Decimal('9')) and r[1] == Plain(normal_vector=Vector(['0', '1', '0']), constant_term=Decimal('7') / Decimal('9')) and r[2] == Plain(normal_vector=Vector(['0', '0', '1']), constant_term=Decimal('2') / Decimal('9'))): print('test case 4 failed') else: print('test case 4 successed') LinearSystem_print(s, '原始方程') LinearSystem_print(r, '行简化阶梯化后方程')
def test2(): #线性方程组阶梯化 p1 = Plain(normal_vector=Vector(['1', '1', '1']), constant_term='1') p2 = Plain(normal_vector=Vector(['0', '1', '1']), constant_term='2') s = LinearSystem([p1, p2]) t = s.compute_triangular_form() print('*******************************') if not (t[0] == p1 and t[1] == p2): print('test case 1 failed') else: print('test case 1 successed') LinearSystem_print(s, '原始方程') LinearSystem_print(t, '阶梯化后方程') print('*******************************') p1 = Plain(normal_vector=Vector(['1', '1', '1']), constant_term='1') p2 = Plain(normal_vector=Vector(['1', '1', '1']), constant_term='2') s = LinearSystem([p1, p2]) t = s.compute_triangular_form() print('*******************************') if not (t[0] == p1 and t[1] == Plain(constant_term='1')): print('test case 2 failed') else: print('test case 2 successed') LinearSystem_print(s, '原始方程') LinearSystem_print(t, '阶梯化后方程') print('*******************************') p1 = Plain(normal_vector=Vector(['1', '1', '1']), constant_term='1') p2 = Plain(normal_vector=Vector(['0', '1', '0']), constant_term='2') p3 = Plain(normal_vector=Vector(['1', '1', '-1']), constant_term='3') p4 = Plain(normal_vector=Vector(['1', '0', '-2']), constant_term='2') s = LinearSystem([p1, p2, p3, p4]) t = s.compute_triangular_form() print('*******************************') if not (t[0] == p1 and t[1] == p2 and t[2] == Plain(normal_vector=Vector(['0', '0', '-2']), constant_term='2') and t[3] == Plain()): print('test case 3 failed') else: print('test case 3 successed') LinearSystem_print(s, '原始方程') LinearSystem_print(t, '阶梯化后方程') print('*******************************') p1 = Plain(normal_vector=Vector(['0', '1', '1']), constant_term='1') p2 = Plain(normal_vector=Vector(['1', '-1', '1']), constant_term='2') p3 = Plain(normal_vector=Vector(['1', '2', '-5']), constant_term='3') s = LinearSystem([p1, p2, p3]) t = s.compute_triangular_form() print('*******************************') if not (t[0] == Plain(normal_vector=Vector(['1', '-1', '1']), constant_term='2') and t[1] == Plain(normal_vector=Vector(['0', '1', '1']), constant_term='1') and t[2] == Plain(normal_vector=Vector(['0', '0', '-9']), constant_term='-2')): print('test case 4 failed') else: print('test case 4 successed') LinearSystem_print(s, '原始方程') LinearSystem_print(t, '阶梯化后方程') print('*******************************')
def test1(): #测试线性方程组的基本操作 #******************************************** #判断两直线位置关系,如果相交,输出交点 p0 = Plain(normal_vector=Vector(['1', '1', '1']), constant_term='1') p1 = Plain(normal_vector=Vector(['0', '1', '0']), constant_term='2') p2 = Plain(normal_vector=Vector(['1', '1', '-1']), constant_term='3') p3 = Plain(normal_vector=Vector(['1', '0', '-2']), constant_term='2') s = LinearSystem([p0, p1, p2, p3]) print(s.indices_of_first_nonzero_terms_in_each_row()) print('{},{},{},{}'.format(s[0], s[1], s[2], s[3])) print(len(s)) print(s) s[0] = p1 print(s) print(MyDecimal('1e-9').is_near_zero()) print(MyDecimal('1e-11').is_near_zero()) p0 = Plain(normal_vector=Vector(['1', '1', '1']), constant_term='1') p1 = Plain(normal_vector=Vector(['0', '1', '0']), constant_term='2') p2 = Plain(normal_vector=Vector(['1', '1', '-1']), constant_term='3') p3 = Plain(normal_vector=Vector(['1', '0', '-2']), constant_term='2') s = LinearSystem([p0, p1, p2, p3]) LinearSystem_print(s, '原始方程组') #交换等式 s.swap_rows(0, 1) print(s[2].normal_vector.is_parallel_to(p2.normal_vector)) if not (s[0] == p1 and s[1] == p0 and s[2] == p2 and s[3] == p3): print('test case 1 failed') else: print('test case 1 successed') LinearSystem_print(s, '交换1-2行') s.swap_rows(1, 3) if not (s[0] == p1 and s[1] == p3 and s[2] == p2 and s[3] == p0): print('test case 2 failed') else: print('test case 2 successed') LinearSystem_print(s, '交换2-4行') s.swap_rows(3, 1) if not (s[0] == p1 and s[1] == p0 and s[2] == p2 and s[3] == p3): print('test case 3 failed') else: print('test case 3 successed') LinearSystem_print(s, '交换4-2行') s.multiply_coefficient_and_row(1, 0) if not (s[0] == p1 and s[1] == p0 and s[2] == p2 and s[3] == p3): print('test case 4 failed') else: print('test case 4 successed') LinearSystem_print(s, '方程1乘1') s.multiply_coefficient_and_row(-1, 2) if not (s[0] == p1 and s[1] == p0 and s[2] == Plain(normal_vector=Vector(['-1', '-1', '1']), constant_term='-3') and s[3] == p3): print('test case 5 failed') else: print('test case 5 successed') LinearSystem_print(s, '方程3乘-1') s.multiply_coefficient_and_row(10, 1) if not (s[0] == p1 and s[1] == Plain( normal_vector=Vector(['10', '10', '10']), constant_term='10') and s[2] == Plain(normal_vector=Vector(['-1', '-1', '1']), constant_term='-3') and s[3] == p3): print('test case 6 failed') else: print('test case 6 successed') LinearSystem_print(s, '方程2乘10') s.add_multiple_times_row_to_row(0, 0, 1) if not (s[0] == p1 and s[1] == Plain( normal_vector=Vector(['10', '10', '10']), constant_term='10') and s[2] == Plain(normal_vector=Vector(['-1', '-1', '1']), constant_term='-3') and s[3] == p3): print('test case 7 failed') else: print('test case 7 successed') LinearSystem_print(s, '方程1乘0,加到方程2') s.add_multiple_times_row_to_row(1, 0, 1) if not (s[0] == p1 and s[1] == Plain( normal_vector=Vector(['10', '11', '10']), constant_term='12') and s[2] == Plain(normal_vector=Vector(['-1', '-1', '1']), constant_term='-3') and s[3] == p3): print('test case 8 failed') else: print('test case 8 successed') LinearSystem_print(s, '方程1乘1,加到方程2') s.add_multiple_times_row_to_row(-1, 1, 0) if not (s[0] == Plain(normal_vector=Vector(['-10', '-10', '-10']), constant_term='-10') and s[1] == Plain(normal_vector=Vector(['10', '11', '10']), constant_term='12') and s[2] == Plain(normal_vector=Vector(['-1', '-1', '1']), constant_term='-3') and s[3] == p3): print('test case 9 failed') else: print('test case 9 successed') LinearSystem_print(s, '方程2乘-1,加到方程1')
class Plain(object): NO_NONZERO_ELTS_FOUND_MSG = 'No nonzero elements found' def __init__(self, normal_vector=None, constant_term=None): self.dimension = 3 if not normal_vector: all_zeros = ['0'] * self.dimension normal_vector = Vector(all_zeros) self.normal_vector = Vector(normal_vector) if not constant_term: constant_term = Decimal('0') self.constant_term = Decimal(constant_term) self.set_basepoint() def set_basepoint(self): try: n = self.normal_vector c = self.constant_term basepoint_coords = ['0'] * self.dimension initial_index = Plain.first_nonzero_index(n) initial_coefficient = n[initial_index] basepoint_coords[initial_index] = c / initial_coefficient self.basepoint = Vector(basepoint_coords) except Exception as e: if str(e) == Plain.NO_NONZERO_ELTS_FOUND_MSG: self.basepoint = None else: raise e def __str__(self): num_decimal_places = 3 def write_coefficient(coefficient, is_initial_term=False): coefficient = round(coefficient, num_decimal_places) if coefficient % 1 == 0: coefficient = int(coefficient) output = '' if coefficient < 0: output += '-' if coefficient > 0 and not is_initial_term: output += '+' if not is_initial_term: output += ' ' if abs(coefficient) != 1: output += '{}'.format(abs(coefficient)) return output n = self.normal_vector try: initial_index = Plain.first_nonzero_index(n) terms = [ write_coefficient(n[i], is_initial_term=(i == initial_index)) + 'x_{}'.format(i + 1) for i in range(self.dimension) if round(n[i], num_decimal_places) != 0 ] output = ' '.join(terms) except Exception as e: if str(e) == self.NO_NONZERO_ELTS_FOUND_MSG: output = '0' else: raise e constant = round(self.constant_term, num_decimal_places) if constant % 1 == 0: constant = int(constant) output += ' = {}'.format(constant) return output @staticmethod def first_nonzero_index(iterable): for k, item in enumerate(iterable): if not MyDecimal(item).is_near_zero(): return k raise Exception(Plain.NO_NONZERO_ELTS_FOUND_MSG) # 以下代码均由本人编写 #返回法向量的坐标值 def __getitem__(self, item): return self.normal_vector.coordinates[item] #判断两平面是否重合 def __eq__(self, l): if (self.normal_vector.is_zero() and l.normal_vector.is_zero()): #都是零向量 return True elif (self.normal_vector.is_zero() or l.normal_vector.is_zero()): #其中之一是零向量 return False elif (self.normal_vector.is_parallel_to(l.normal_vector)): minus_vector = self.basepoint.minus(l.basepoint) if (minus_vector.is_zero() or minus_vector.is_orthogonal_to( l.normal_vector)): #判断该向量是否与当前法向量正交 return True else: return False else: return False #平面方程倍乘函数 法向量和常数均乘以同一常数 def times_scalar(self, c): product_vector = self.normal_vector.times_scalar(c) product_constant = self.constant_term * c return Plain(product_vector, product_constant) #平面方程相加,法向量、常数均相加 def plus(self, v): sum_vector = self.normal_vector.plus(v.normal_vector) sum_constant = self.constant_term + v.constant_term return Plain(sum_vector, sum_constant) #平面方程相减,法向量、常数均相减 def minus(self, v): sum_vector = self.normal_vector.minus(v.normal_vector) sum_constant = self.constant_term - v.constant_term return Plain(sum_vector, sum_constant) #判断两平面是否平行 def is_parallel_to(self, l): return (self.normal_vector.is_parallel_to(l.normal_vector))