예제 #1
0
    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()
예제 #2
0
    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()
예제 #3
0
    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
예제 #4
0
 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
예제 #5
0
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
예제 #6
0
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, '行简化阶梯化后方程')
예제 #7
0
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('*******************************')
예제 #8
0
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')
예제 #9
0
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))