首页 > 编程语言 >线性方程组迭代算法的Python实现

线性方程组迭代算法的Python实现

时间:2024-08-07 21:53:10浏览次数:9  
标签:errors 迭代 Python 线性方程组 dot maxIter np norm ndarray

更多精彩,关注博客园主页,不断学习!不断进步!

我的主页

csdn很少看私信,有事请b站私信

博客园主页-发文字笔记-常用

有限元鹰的主页 内容:

  1. ABAQUS数值模拟相关
  2. Python科学计算
  3. 开源框架,编程学习笔记

哔哩哔哩主页-发视频-常用

FE-有限元鹰的个人空间 内容:

  1. 模拟案例
  2. 网格划分
  3. 游戏视频,及其他搬运视频

文章目录

线性方程组迭代算法的Python实现

jacobi,GS,SOR迭代法

def JacobiIter(A:np.ndarray,
                b:np.ndarray,
                tol:float=1e-5,
                maxIter:int=100)->Tuple[np.ndarray,np.ndarray]:
    """使用Jacobi迭代法求解线性方程组Ax=b
    
    input:
    A: np.ndarray, 系数矩阵
    b: np.ndarray, 右端常数
    tol: float, 误差限
    maxIter: int, 最大迭代次数
    
    output:
    x: np.ndarray, 解向量
    errors: np.ndarray, 误差序列
    """
    from numpy import dot
    from numpy.linalg import norm
    x0=np.zeros(b.shape)
    L=-1*np.tril(A,k=-1).copy()
    U=-1*np.triu(A,k=1).copy()
    D=np.diag(np.diag(A)).copy()
    Dinv=np.linalg.inv(D)
    errors=[]
    for i in range(maxIter):
        x_next=dot(Dinv,(dot((L+U),x0)+b))
        # error check
        error=norm(b-dot(A,x_next),2)/norm(b,2)
        errors.append(error)
        if error<tol:
            return x_next,np.array(errors)
        else:
            x0=x_next

def GaussIter(A:np.ndarray,
                b:np.ndarray,
                tol:float=1e-5,
                maxIter:int=100)->Tuple[np.ndarray,np.ndarray]:
    """使用Gauss-Seidel迭代法求解线性方程组Ax=b
    
    input:
    A: np.ndarray, 系数矩阵
    b: np.ndarray, 右端常数
    tol: float, 误差限
    maxIter: int, 最大迭代次数
    
    output:
    x: np.ndarray, 解向量
    errors: np.ndarray, 误差序列
    """
    from numpy import dot
    from numpy.linalg import norm
    x0=np.zeros(b.shape)
    L=-1*np.tril(A,k=-1).copy()
    U=-1*np.triu(A,k=1).copy()
    D=np.diag(np.diag(A)).copy()
    DsubLinv=np.linalg.inv(D-L)
    errors=[]
    for i in range(maxIter):
        x_next=DsubLinv.dot(U).dot(x0)+DsubLinv.dot(b)
        # error check
        error=norm(b-dot(A,x_next),2)/norm(b,2)
        errors.append(error)
        if error<tol:
            return x_next,np.array(errors)
        else:
            x0=x_next

def SORIter(A:np.ndarray,
                b:np.ndarray,
                w:float=1.0,
                tol:float=1e-5,
                maxIter:int=100)->Tuple[np.ndarray,np.ndarray]:
    """使用SOR迭代法求解线性方程组Ax=b
    
    input:
    A: np.ndarray, 系数矩阵
    b: np.ndarray, 右端常数
    w: float, 松弛因子(0~2.0)
    tol: float, 误差限
    maxIter: int, 最大迭代次数
    
    output:
    x: np.ndarray, 解向量
    errors: np.ndarray, 误差序列
    """
    from numpy import dot
    from numpy.linalg import norm
    x0=np.zeros(b.shape)
    L=-1*np.tril(A,k=-1).copy()
    U=-1*np.triu(A,k=1).copy()
    D=np.diag(np.diag(A)).copy()
    
    DsubOmegaLinv=np.linalg.inv(D-w*L)
    errors=[]
    for i in range(maxIter):
        x_next=DsubOmegaLinv.dot((1-w)*D+w*U).dot(x0)+w*DsubOmegaLinv.dot(b)
        # error check
        error=norm(b-dot(A,x_next),2)/norm(b,2)
        errors.append(error)
        if error<tol:
            return x_next,np.array(errors)
        else:
            x0=x_next
  • 验证
import numpy as np
from formu_lib import *
A=np.array([[2,-1,0],
            [-1,3,-1],
            [0,-1,2]])
b=np.array([1,8,-5])
extractVal=np.array([2,3,-1])

x1,er1=JacobiIter(A,b)
x2,er2=GaussIter(A,b)
x3,er3=SORIter(A,b,1.2)

ind1,ind2,ind3=list(range(len(er1))),list(range(len(er2))),list(range(len(er3)))
plotLines([ind1,ind2,ind3],[er1,er2,er3],["Jacobi iter error","Gauss iter error","SOR iter error"])

showError(x1,extractVal)
showError(x2,extractVal)
showError(x3,extractVal)

img

# 雅可比迭代法
数值解: [ 1.9999746   2.99999435 -1.0000254 ],
精确解: [ 2  3 -1],
误差: 9.719103983280175e-06
# GS迭代法
数值解: [ 1.9999619  2.9999746 -1.0000127],
精确解: [ 2  3 -1],
误差: 1.2701315856479742e-05
# SOR迭代法
数值解: [ 2.00001461  2.999993   -1.00000098],
精确解: [ 2  3 -1],
误差: 4.338862621105977e-06

正定对称线性方程组的不定常迭代:最速下降法,共轭梯度法

def SPDmethodSolve(A:np.ndarray,
                    b:np.ndarray,
                    tol:float=1e-5,
                    maxIter:int=200)->Tuple[np.ndarray,np.ndarray]:
    """使用最速下降法求解线性方程组Ax=b
    
    input:
    A: np.ndarray, 系数矩阵,必须是对称正定矩阵
    b: np.ndarray, 右端常数
    tol: float, 误差限
    maxIter: int, 最大迭代次数
    
    output:
    x: np.ndarray, 解向量
    errors: np.ndarray, 误差序列
    """
    from numpy import dot
    from numpy.linalg import norm
    x0=np.zeros(b.shape)
    i,errors=0,[]
    while True :
        if i>maxIter:
            maxIter=1.5*maxIter
            print(f"迭代次数过多,自动调整为 {maxIter}")
        # 计算残量r^k作为前进方向.
        r=b-dot(A,x0)
        # 计算前进距离a_k
        a=InnerProduct(r,r)/InnerProduct(dot(A,r),r)
        x_next=x0+a*r
        error=norm(b-dot(A,x_next),2)/norm(b,2)
        errors.append(error)
        if errors[-1]<tol:
            return x_next,np.array(errors)
        else:
            x0=x_next
            i+=1
        
def conjGrad(A:np.ndarray,
                b:np.ndarray,
                tol:float=1e-5,
                maxIter:int=200)->Tuple[np.ndarray,np.ndarray]:
    """使用共轭梯度法求解线性方程组Ax=b
    
    input:
    A: np.ndarray, 系数矩阵,必须是对称正定矩阵
    b: np.ndarray, 右端常数
    tol: float, 误差限
    maxIter: int, 最大迭代次数
    
    output:
    x: np.ndarray, 解向量
    errors: np.ndarray, 误差序列
    """
    from numpy import dot
    from numpy.linalg import norm
    # 选择初值x0,初始方向p0=r0=b-Ax0
    x0=np.zeros(b.shape)
    i,errors=0,[]
    r0=b-dot(A,x0)
    p_0=b-dot(A,x0)
    errors.append(norm(r0,2)/norm(b,2))
    while True :
        if i>maxIter:
            maxIter=1.5*maxIter
            print(f"迭代次数过多,自动调整为 {maxIter}")
        # 计算a_k,x^{k+1}=x_k+a_k*p_k
        a_k=InnerProduct(r0,p_0)/InnerProduct(dot(A,p_0),p_0)
        x_next=x0+a_k*p_0
        # 计算下一步的残量
        r_k_next=b-dot(A,x_next)
        errors.append(norm(r_k_next,ord=2)/norm(b,2))
        # 如果残量足够小,则停止迭代
        if errors[-1]<tol:
            return x_next,np.array(errors)
        else:
            # 计算下一步的搜索方向
            beta_k=-1*InnerProduct(r_k_next,A.dot(p_0))/InnerProduct(p_0,A.dot(p_0))
            p_0=r_k_next+beta_k*p_0
            x0=x_next
            i+=1
  • 验证

img

from formu_lib import *
import numpy as np

A=np.array([[4,-1,0],
            [-1,4,-1],
            [0,-1,4]])
b=np.array([3,2,3])
extractVal=np.array([1,1,1])

x1,er1=SPDmethodSolve(A,b,1e-6)
x2,er2=conjGrad(A,b,1e-6)

plotLines([list(range(len(er1))),list(range(len(er2)))],[er1,er2],["SPD method error","conjugate gradient error"])

showError(x1,extractVal)
showError(x2,extractVal)

img

# SPD method
数值解: [0.99999951 0.99999951 0.99999951],
精确解: [1 1 1],
误差: 4.891480784863234e-07
# conjugate gradient method
数值解: [1. 1. 1.],
精确解: [1 1 1],
误差: 0.0

标签:errors,迭代,Python,线性方程组,dot,maxIter,np,norm,ndarray
From: https://blog.csdn.net/weixin_46037068/article/details/141001471

相关文章

  • 最小二乘法原理推导+代码实现[Python]
    0.前言本文主要介绍了最小二乘法公式推导,并且使用Python语言实现线性拟合。读者需要具备高等数学、线性代数、Python编程知识。请读者按照文章顺序阅读。绘图软件为:geogebra5。1.原理推导1.1应用最小二乘法在购房中的应用通常涉及房价预测和房屋定价方面。这种统计方法通......
  • python opencv图片简单操作
    一、从文件读取图片cv2.imread(filename,flags) 参数: filepath:读入image的完整路径 flags:标志位,{cv2.IMREAD_COLOR,cv2.IMREAD_GRAYSCALE,cv2.IMREAD_UNCHANGED} cv2.IMREAD_COLOR:默认参数,读入一副彩色图片,忽略alpha通道,可用1作为实参替代 cv2.IMREAD_GRAYSCALE:读入......
  • Python 中的排序与 ASCII 编码解析
    1.引言    不知道你有没有想过用Python进行一些排序的工作,对于一些数量比较小的数字集合(例如:1、15、32、79、6、55)我们可以迅速发现最大的79和最小的1,但当这个数量非常大的时候,我们找大小就很费劲了,而这种繁琐的工作就应该派计算机出马了2.比大小  a.常规数字比......
  • for 循环入门:迭代与应用
    1.引言    在之前我们讨论了while循环,while循环会在每次循环前进行检验,符合标准才会进行循环,这种循环是不定循环,有不定循环就会有定循环,现在让我们来讨论一下定循环2.for键    for键是定循环的关键字(keyword)让我们来看一下下面的代码foriin[5,4,3,2,1]......
  • Python使用Memcached示例
    关注我,持续分享逻辑思维&管理思维&面试题;可提供大厂面试辅导、及定制化求职/在职/管理/架构辅导;推荐专栏《10天学会使用asp.net编程AI大模型》,目前已完成所有内容。一顿烧烤不到的费用,让人能紧跟时代的浪潮。从普通网站,到公众号、小程序,再到AI大模型网站。干货满满。学成后可......
  • 2024年华为OD机试真题-欢乐的周末-Python-OD统一考试(C卷D卷)
    2024年OD统一考试(D卷)完整题库:华为OD机试2024年最新题库(Python、JAVA、C++合集) 题目描述:小华和小为是很要好的朋友,他们约定周末一起吃饭。通过手机交流,他们在地图上选择了多个聚餐地点(由于自然地形等原因,部分聚餐地点不可达),求小华和小为都能到达的聚餐地点有多少个?输入描述......
  • Python并发编程
    简介多线程:threading,利用cpu和io可以同时执行的原理,让CPU不会等待IO完成多进程:multiprocess,利用多核CPU的能力,真正的并行执行任务异步IO:asynio,在单线程利用CPU和IO同时执行的原理,实现函数异步执行 使用Lock对共享资源加锁,防止冲突访问使用Queue实现不......
  • 19.python之自定义函数
    python之自定义函数一、函数的介绍1、函数定义:函数是一个组织好,可重复使用,实现单一或联合的代码段。2、函数作用:a、降低代码的冗余、b、增加代码的复用性c、提高程序的拓展性d、封装二、python的结构三、函数的使用1、格式:def函数名(变量):执行语句函数名(实际参数)#调......
  • python装饰器提高代码复用,减少代码量,简洁易懂
    装饰器提高代码复用,减少代码量对于一个程序程序,无论是c、java、go还是python,组成这段程序的代码需要越简单越好,要知道程序的代码越简单,代码量越少,出错的概率就小,维护起来也简单。针对python语言,装饰器是我最近发现的针对简化代码,特别有帮助的工具。下面我用两段代码,演示一下同样......
  • python,怎么用工厂模式设计代码?
    工厂模式打造工厂模式,需要抽象工厂和具体工厂。怎么理解?抽象工厂就是接口的定义,但不负责具体的实现。而具体工厂则需要负责定义的接口的实现。就好比你爸爸让你上街时带一瓶酱油,而具体买什么牌子的由你决定。”你爸爸让带一瓶酱油“就是接口的定义函数,这个函数只负责定义”要求“......