高斯列主消元法 (python实现)

高斯列主消元法

1. 高斯列主消元法的基本思想

列主元素消去法是为控制舍入误差而提出来的一种算法。列主元素消去法计算基本上能控制舍入误差的影响,其基本思想是:在进行第 k ( k = 1 , 2 , ... , n − 1 ) k(k=1,2,...,n-1) k(k=1,2,...,n−1)步消元时,从第 k k k列的 a k k a_{kk} akk及其以下的各元素中选取绝对值最大的元素 ,然后通过行变换将它交换到主元素 a k k a_{kk} akk的位置上,再进行消元。

误差来源:由于计算机表示浮点数有位数限制(IEEE 754 标准中,单精度浮点数(float)是16位,双精度浮点数(double)为32位),在高斯消元法中,计算行乘数 m i j = a i j a i i m_{ij}=\frac{a_{ij}}{a_{ii}} mij=aiiaij,如果 a i i a_{ii} aii很小,那么行乘数就可能溢出。例如:
( A , b ) = ( 1 0 − 8 2 3 1 − 1 3.712 4.623 2 − 2 1.072 5.643 3 ) , \begin{aligned}(A,b)&=\left(\begin{array}{llll}10^{-8}&2&3&1\\-1&3.712&4.623&2\\-2&1.072&5.643&3\end{array}\right),\end{aligned} (A,b)= 10−8−1−223.7121.07234.6235.643123 ,

如果直接使用 1 0 − 8 10^{-8} 10−8作为 a i i a_{ii} aii,假设计算机使用的是8位十进制尾数,那么在计算 a 22 a_{22} a22时, a 22 = a 22 − m 21 a 12 = a 22 − a 21 a 11 a 12 = 3.712 − − 1 1 0 − 8 × 2 = 0.0000000 × 1 0 9 + 0.2 × 1 0 9 = 0.2 × 1 0 9 , a_{22}=a_{22}-m_{21}a_ {12}=a_{22}-\frac{a_{21}}{a_{11}}a_{12}=3.712-\frac{-1}{10^{-8}}\times 2=0.0000000\times10^9+0.2\times10^9=0.2\times10^9, a22=a22−m21a12=a22−a11a21a12=3.712−10−8−1×2=0.0000000×109+0.2×109=0.2×109,

由于减数在规格化以后为 1 0 9 10^9 109,导致3.712在进行浮点运算的对阶操作时阶码为9,尾数右移为机器0,这样在进行后续的消元后导致方程的解误差过大甚至是错误:经过两步消元后,有:
( A ( 3 ) , b ( 3 ) ) = ( 1 0 − 8 2 3 1 0.2 × 1 0 9 0.3 × 1 0 9 0.1 × 1 0 9 0 0 ) . (A^{(3)},b^{(3)})=\left(\begin{array}{cccc}10^{-8}&2&3&1\\&0.2\times10^9&0.3\times10^9&0.1\times10^9\\&&0&0\end{array}\right). (A(3),b(3))= 10−820.2×10930.3×109010.1×1090 .

该方程在使用很小的数作为主元时导致方程没有唯一解,实际上该方程是有解的( d e t A ≠ 0 detA\neq 0 detA=0)。因此需要在进行高斯消元法时选择该列的绝对值最大元素作为主元,然后在进行消元

2. 高斯列主消元法的基本步骤

其中 e p s eps eps是一个阈值,当某一列的所有列主元都小于 e p s eps eps时,该方程的解误差会很大,因此直接放弃使用计算机求解

3. 高斯列主消元法的程序设计

python 复制代码
# 高斯列主消元法

import numpy as np

eps=1e-8

def gaussian_elimination_with_pivoting(A, b):

    n = A.shape[0]

    # 增广矩阵

    Ab = np.hstack([A, b.reshape(-1, 1)])

    for i in range(n):

        # 找到列主元的行号

        max_row_index = np.argmax(np.abs(Ab[i:n, i])) + i

        if abs(Ab[max_row_index][i]) <eps:

            print(Ab[max_row_index][i])

            print("数值不稳定/无解")

            return None

        # 交换当前行和列主元所在的行

        if i != max_row_index:

            Ab[[i, max_row_index]] = Ab[[max_row_index, i]]

        # 消元

        for j in range(i + 1, n):

            factor = Ab[j, i] / Ab[i, i]

            Ab[j, i:] = Ab[j, i:] - factor * Ab[i, i:]

    # 回带求答案

    x = np.zeros(n)

    for i in range(n-1, -1, -1):

        x[i] = (Ab[i, -1] - Ab[i, i+1:n]@x[i+1:]) / Ab[i, i]

    return x

4.计算复杂度

根据算法中的消元过程中,第 k k k步运算做乘法 ( n − k )( n − k + 1 ) (n-k)(n-k+1) (n−k)(n−k+1)次,做除法 n − k n-k n−k 次,完成 n − 1 n-1 n−1 步消元共需做乘除法的总次数为 ∑ k = 1 n − 1 ( n − k ) ( n − k + 2 ) = n 3 3 + n 2 2 − 5 n 6 , \sum_{k=1}^{n-1}(\left.n-k\right)(\left.n-k+2\right)=\frac{n^3}3+\frac{n^2}2-\frac{5n}6, k=1∑n−1(n−k)(n−k+2)=3n3+2n2−65n,

在回带带计算解时,乘除法计算次数为 ∑ i = 1 n ( n − i + 1 ) = n 2 2 + n 2 \sum_{i=1}^n (n-i+1)=\frac{n^2}{2}+\frac{n}{2} i=1∑n(n−i+1)=2n2+2n

因此全部乘除法运算次数为 M D = n 3 3 + n 2 − n 3 MD=\frac{n^3}{3}+n^2-\frac{n}{3} MD=3n3+n2−3n

相关推荐
2401_858120263 小时前
探索sklearn文本向量化:从词袋到深度学习的转变
开发语言·python·机器学习
bigbearxyz5 小时前
Java实现图片的垂直方向拼接
java·windows·python
立秋67895 小时前
使用Python绘制堆积柱形图
开发语言·python
jOkerSdl5 小时前
第三十章 方法大全(Python)
python
小白学大数据6 小时前
HTML内容爬取:使用Objective-C进行网页数据提取
大数据·爬虫·python·html·objective-c·cocoa
逆境清醒6 小时前
开源数据科学平台Anaconda简介
人工智能·python·深度学习·机器学习·anaconda
SleepingBug6 小时前
[python][Anaconda]使用jupyter打开F盘或其他盘文件
开发语言·python·jupyter
mm_exploration7 小时前
torch常用函数
pytorch·python·深度学习
c实例7 小时前
爬虫 属性 方法
爬虫·python
爱煲汤的夏二7 小时前
CI脚本的python基础
java·python·ci/cd