2.3 非齐次方程组解集

文章目录

  • 反表示法
  • 计算机算法
  • Python代码

反表示法

  非齐次方程组如果系数矩阵的秩小于未知数的个数,那么就有了自由变量,这个时候就需要写出它的解集。对于这种线性代数的基本功,确实有不少算法,比如适合手算的反表示法,适合计算机的算法,还有广义逆法。这里先介绍考试用的反表示法,比如以下方程:
x + y + z = 1 x+y+z=1 x+y+z=1
  对于这个方程,有三个未知数,但是只有一个方程,所以就有两个自由变量,那么以 x , y x,y x,y为自由变量,用 x , y x,y x,y来反表示 z z z,就是以下结果:
z = 1 − x − y z=1-x-y z=1xy
  那么解就是这个样子:
( x y z ) = ( x y 1 − x − y ) \begin{pmatrix}x\\y\\z\end{pmatrix}=\begin{pmatrix}x\\y\\1-x-y\end{pmatrix} xyz = xy1xy
  到了这一步就是进行自由变量的分离了。于是将上式进一步写成:
( x y z ) = ( x y 1 − x − y ) = ( 0 0 1 ) + ( x 0 − x ) + ( 0 y − y ) \begin{pmatrix}x\\y\\z\end{pmatrix}=\begin{pmatrix}x\\y\\1-x-y\end{pmatrix}=\begin{pmatrix}0\\0\\1\end{pmatrix}+\begin{pmatrix}x\\0\\-x\end{pmatrix}+\begin{pmatrix}0\\y\\-y\end{pmatrix} xyz = xy1xy = 001 + x0x + 0yy
  所以解集就是:
( 0 0 1 ) + ( x 0 − x ) + ( 0 y − y ) = ( 0 0 1 ) + x ( 1 0 − 1 ) + y ( 0 1 − 1 ) \begin{pmatrix}0\\0\\1\end{pmatrix}+\begin{pmatrix}x\\0\\-x\end{pmatrix}+\begin{pmatrix}0\\y\\-y\end{pmatrix}=\begin{pmatrix}0\\0\\1\end{pmatrix}+x\begin{pmatrix}1\\0\\-1\end{pmatrix}+y\begin{pmatrix}0\\1\\-1\end{pmatrix} 001 + x0x + 0yy = 001 +x 101 +y 011

计算机算法

  这样反表示,计算并不快,需要一步步拆解,以上面的为例子,进一步研究解的结构,首先看第一部分:
( 0 0 1 ) \begin{pmatrix}0\\0\\1\end{pmatrix} 001
  这一部分是所有自由变量都为0的结果,所以它的坐标的前两项都是0,那么这个就很容易用程序求出来,也是第一步要求的向量。再看第二部分的其中一个向量:
y ( 0 1 − 1 ) y\begin{pmatrix}0\\1\\-1\end{pmatrix} y 011
  这是其余自由变量为0, y y y为1的结果。所以也容易求出来。计算机求解因为强制了系数为1,所以结果中容易出现小数,而反表示法由于是直接反表示拆解的,所以结果中一般不会出现小数,各有各的好处。
  不过需要注意行阶梯形的阶梯,如一下方程:
( 1 1 1 1 0 0 1 1 ) x = ( 2 1 ) \begin{pmatrix} 1 & 1 & 1 & 1\\ 0 & 0 & 1 & 1 \end{pmatrix}\bold x= \begin{pmatrix} 2 \\ 1 \end{pmatrix} (10101111)x=(21)
  这里有四个未知数, x 1 , x 2 x_1,x_2 x1,x2组成一个阶梯, x 3 , x 4 x_3,x_4 x3,x4组成一个阶梯。 x 1 , x 2 x_1,x_2 x1,x2不能同时是自由变量。等于是说每个阶梯里,至少有一个变量不是自由的。以上面的方程为例子,假如第一个阶梯全部为0,那么方程就变成了:
( 1 1 1 1 ) x = ( 2 1 ) \begin{pmatrix} 1 & 1\\ 1 & 1 \end{pmatrix}\bold x= \begin{pmatrix} 2 \\ 1 \end{pmatrix} (1111)x=(21)
  这就成了矛盾方程了。

Python代码

  代码比较长,我是以每个阶梯的后几个变量为自由变量的。

    # 非齐次线性方程组解集
    def non_homogeneous_solution(self, values):
        # 必须加上值组成增广矩阵
        vectors = copy.deepcopy(self.__vectors)
        vectors.append(values)
        augmented = Matrix(vectors)
        matrix = augmented.to_upper_triangle()
        n = len(self.__vectors)
        coefficients = Matrix(matrix.__vectors[0:-1])
        new_values = matrix.__vectors[-1]
        rank = coefficients.get_rank(new_values)
        if rank == n:
            # 满秩
            return matrix_utils.solve_upper_triangle(coefficients, new_values)
        # 不是满秩的
        return coefficients.solution_from_echelon(new_values)

    # 直接根据阶梯形求解
    def solution_from_echelon(self, values):
        # 先获取特解
        # 每个阶梯的前n-1个自由,最后一个不自由
        # 获得一个新方程
        # 自由的全部为0
        echelons = self.get_echelons()
        special = self.particular_solution(echelons, values)
        # 通解是那些自由变量,一个为1,其余为0
        free_columns = matrix_utils.free_columns(echelons)
        solutions = [special]

        for free_column in free_columns:
            # 组成一个新矩阵
            vectors = []
            for echelon in echelons:
                vectors.append(self.__vectors[echelon[0]])
            new_value = matrix_utils.sub(values, self.__vectors[free_column])
            # 解只是主元的解
            solution = matrix_utils.solve_upper_triangle(Matrix(vectors), new_value[0:len(echelons)])

            result = [0] * len(self.__vectors)
            result[free_column] = 1
            for i, echelon in enumerate(echelons):
                result[echelon[0]] = solution[i]
            solutions.append(matrix_utils.sub(result, special))
        return solutions

    # 非齐次方程组特解
    def particular_solution(self, echelons, values):
        # 自由变量全部为0的新方程
        # 必须保证是一个方阵
        vectors = [self.__vectors[echelon[0]][0:len(echelons)] for echelon in echelons]
        solution = matrix_utils.solve_upper_triangle(Matrix(vectors), values[0:len(echelons)])
        # 新方程的解
        # 特解是拼起来的
        result = [0] * len(self.__vectors)
        for i, echelon in enumerate(echelons):
            # 主元不自由,其余自由
            result[echelon[0]] = solution[i]
        return result

    # 获取矩阵的秩
    def get_rank(self, values):
        m = len(self.__vectors[0])
        n = len(self.__vectors)
        rank = 0
        # 非自由变量的集合
        for i in range(m - 1, -1, -1):
            # 获取非零元素的列
            non_zeros = []
            for j in range(n):
                if abs(self.__vectors[j][i]) > matrix_utils.MAX_ERROR:
                    non_zeros.append(self.__vectors[j][i])
            if len(non_zeros) == 0 and not matrix_utils.is_zero(values[i]):
                raise Exception('方程为矛盾方程组')
            elif len(non_zeros) == 1:
                rank += 1
            else:
                rank += 1
        return rank

    # 获取阶梯数组
    def get_echelons(self):
        echelons = []
        # 循环列
        echelon = []
        level = 0
        for j, e in enumerate(self.__vectors):
            m = len(e)
            # 如果是最后一行
            if level == m - 1:
                echelon.append(j)
            elif matrix_utils.is_zero(e[level + 1]) and not matrix_utils.is_zero(e[level]):
                echelon.append(j)
            else:
                level += 1
                echelons.append(echelon)
                echelon = [j]
        echelons.append(echelon)
        return echelons

你可能感兴趣的:(线性代数【更新中】,python,线性代数,开发语言)