草庐IT

基于MATLAB的迭代求解线性方程组(附完整代码与算法)

唠嗑! 2023-04-12 原文

前言

在之前的文章中更新了线性方程组的基本解法,大型方程组的分解求法。本节将介绍线性方程组的迭代求解。

一. 三个变换

在线性方程组的迭代求解中,会用到系数矩阵A的上三角矩阵对角矩阵下三角矩阵。这三种变化在MATLAB中,可以直接利用函数实现。

1.1 上三角变换

triu(A,1)

1.2 对角变换

diag(A)

1.3 下三角变换

tril(A,-1)

针对此类矩阵的解释,可以参看这篇文章:

MATLAB:矩阵基础_唠嗑!的博客-CSDN博客

例题1

对以下矩阵A做此三种变换。

解:

MATLAB代码如下:

clc;clear;
A=[1 2 -3;1 1 1;2 2 1];

%上三角变换
up=triu(A,1)

%对角变换
diag=diag(A)

%下三角变换
down=tril(A,-1)

运行结果:

up =

     0     2    -3
     0     0     1
     0     0     0


diag =

     1
     1
     1


down =

     0     0     0
     1     0     0
     2     2     0
分析:

二. Sylvester方程

 Sylvester方程的形式如下:

此方程中,A是矩阵,B是矩阵,C和X都是矩阵。

在MATLAB中可以直接调用函数求解,如下:

X=sylvester(A,B,C)

例题2

求解Sylvester方程AX+XB=C的解X。其中A,B,C矩阵如下:

解:

MATLAB代码如下:

clc;clear;
A=[1 0 2 3;4 1 0 2;0 5 5 6;1 7 9 0];
B=[0 -1;1 0];
C=[1 0;2 0;0 3;1 1];

X=sylvester(A,B,C)

运行结果如下:

X =

    0.4732   -0.3664
   -0.4006    0.3531
    0.3305   -0.1142
    0.0774    0.3560

三. Jacobi迭代法

原方程组Ax=b中的矩阵A可以写成,如下:

上式子中-L和-U分别为A矩阵的严格下,上三角部分,当然不包含对角元素。其中矩阵D的表达如下:

根据迭代的思想,x可得如下表达式:

上式子中的B,f理解如下:

为了更好理解这种迭代形式,将原线性方程组写全,如下:

如果系数矩阵非奇异,即,那么可得: 

运用迭代公式,最终的方程组如下: 

在调用jacobi()函数之前,需要提前编码,我们来看下jacobi函数的内部结构,如下:

function y=jacobi(a,b,x0)
D=diag(diag(a));
U=-triu(a,1);
L=-tril(a,-1);
B=D\(L+U);
f=D\b;
y=B*x0+f;
n=1;
while(norm(y-x0))>=1.0e-6
x0=y;
y=B*x0+f;
n=n+1;
end
n
end

例题3

设x0=0,精度为,利用Jacobi方法求解以下方程组。

解:

MATLAB代码如下:


clc;clear;
a=[10 -1 0;-1 10 -2;0 -2 10];
b=[9;7;6];
jacobi(a,b,[0;0;0])  %注意初始值也为一个矩阵

%对jacobi函数的定义
function y=jacobi(a,b,x0)
D=diag(diag(a));
U=-triu(a,1);
L=-tril(a,-1);
B=D\(L+U);
f=D\b;
y=B*x0+f;
n=1;
while(norm(y-x0))>=1.0e-6
x0=y;
y=B*x0+f;
n=n+1;
end
n
end

运行结果:


n =

    11


ans =

    0.9958
    0.9579
    0.7916

四. Gauss-Seidel迭代法

借助Jacobi的方法,迭代方程也可以如下形式:

同样地,-L、-U分别为A的严格下、上三角部分,且不包含对角线元素。G,f,D的定义如下:

为了深入理解此种迭代方式,可列出矩阵中的元素。

在迭代计算过程中,需要同时保留两个近似解向量。由此可以把迭代公式改写为如下:

备注:由于显示的原因,上式子中的“L"代表省略号

由此可以在MATLAB中编码seidel()函数,如下:

function y=seidel(a,b,x0)
D=diag(diag(a));
U=-triu(a,1);
L=-tril(a,-1);
G=(D-L)\U;
f=(D-L)\b;
y=G*x0+f;
n=1;
while norm(y-x0)>=1.0e-6
    x0=y;
    y=G*x0+f;
    n=n+1;
end
n
end

 例题4

设x0=0,精度为,利用Gauss-Seidel方法求解以下方程组。

 

解:

MATLAB代码如下:

clc;clear;
a=[10 -1 0;-1 10 -2;0 -2 10];
b=[9;7;6];
seidel(a,b,[0;0;0])

function y=seidel(a,b,x0)
D=diag(diag(a));
U=-triu(a,1);
L=-tril(a,-1);
G=(D-L)\U;
f=(D-L)\b;
y=G*x0+f;
n=1;
while norm(y-x0)>=1.0e-6
    x0=y;
    y=G*x0+f;
    n=n+1;
end
n
end

运行结果:

n =

     7


ans =

    0.9958
    0.9579
    0.7916

分析:此例子可以直接求解。也可能会出现使用Seidel迭代时,结果不收敛的情况。

五. SOR迭代法

在某些情况下,Jacobi法和Gauss-Seidel法收敛的过程较慢,为了进一步改进,可以引入一种新的迭代法:逐次超松弛迭代法(Succesise Over Relaxation),简记为SQR法。

迭代的公式如下:

上式子中,w的最佳值一般在[1,2)之间,具体视情况而定。

松弛法的主题思想是将乘上一个参数因子w来作为修正项,从而得到新的近似解。迭代公式可见如下:

上式子中的的计算,可见如下:

由此可得迭代的化简过程,如下:

按照上述式子计算Ax=b的近似解序列的方法,就被称之为松弛法,其中w为松弛因子。当w<1时称为低松弛;当w>1时称为超松弛;当w=1时,其实就是Gauss-Seidel迭代。

根据以上过程构造sor函数,MATLAB代码如下:

function y=sor(a,b,w,x0)
D=diag(diag(a)); %形成对角矩阵,其余元素为0
U=-triu(a,1);
L=-tril(a,-1);
M=(D-w*L)\((1-w)*D+w*U);
f=(D-w*L)\b*w;
y=M*x0+f;
n=1;
while norm(y-x0)>=1.0e-6
    x0=y;
    y=M*x0+f;
    n=n+1;
end
n
end

例题5

 设x0=0,精度为,w=1.103,利用SOR方法求解以下方程组。

解:

MATLAB代码如下:

clc;clear;
a=[10 -1 0;-1 10 -2;0 -2 10];
b=[9;7;6];
sor(a,b,1.103,[0;0;0])

%函数部分
function y=sor(a,b,w,x0)
D=diag(diag(a)); %形成对角矩阵,其余元素为0
U=-triu(a,1);
L=-tril(a,-1);
M=(D-w*L)\((1-w)*D+w*U);
f=(D-w*L)\b*w;
y=M*x0+f;
n=1;
while norm(y-x0)>=1.0e-6
    x0=y;
    y=M*x0+f;
    n=n+1;
end
n
end

运行结果:

n =

     8


ans =

    0.9958
    0.9579
    0.7916

六. 两步迭代法

当线性方程系数矩阵为对称正定时,还可以使用一种特殊的迭代法来解决:两步迭代法。迭代的公式,如下:

首先可得:

进一步推导可得:

根据以上计算过程,可以编写twostp()函数,MATLAB代码如下:

function y=twostp(a,b,x0)
D=diag(diag(a));
U=-triu(a,1);
L=-tril(a,-1);
G1=(D-L)\U;f1=(D-L)\b;
G2=(D-U)\L;f2=(D-U)\b;
y=G1*x0+f1;
y=G2*y+f2;
n=1;
while norm(y-x0)>=1.0e-6
    x0=y;
    y=G1*x0+f1;
    y=G2*y+f2;
    n=n+1;
end
n
end

例题6

利用两步法,求解如下方程组:

解:

MATLAB代码如下:

clc;clear;
a=[10 -1 2 0;-1 11 -1 3;2 -1 10 3;0 3 -1 8];
b=[6;25;-11;15];
twostp(a,b,[0;0;0;0])

function y=twostp(a,b,x0)
D=diag(diag(a));
U=-triu(a,1);
L=-tril(a,-1);
G1=(D-L)\U;f1=(D-L)\b;
G2=(D-U)\L;f2=(D-U)\b;
y=G1*x0+f1;
y=G2*y+f2;
n=1;
while norm(y-x0)>=1.0e-6
    x0=y;
    y=G1*x0+f1;
    y=G2*y+f2;
    n=n+1;
end
n
end

运行结果:

n =

     7


ans =

    1.0791
    1.9824
   -1.4044
    0.9560

有关基于MATLAB的迭代求解线性方程组(附完整代码与算法)的更多相关文章

  1. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  2. ruby-on-rails - Rails 源代码 : initialize hash in a weird way? - 2

    在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has

  3. ruby-on-rails - 浏览 Ruby 源代码 - 2

    我的主要目标是能够完全理解我正在使用的库/gem。我尝试在Github上从头到尾阅读源代码,但这真的很难。我认为更有趣、更温和的踏脚石就是在使用时阅读每个库/gem方法的源代码。例如,我想知道RubyonRails中的redirect_to方法是如何工作的:如何查找redirect_to方法的源代码?我知道在pry中我可以执行类似show-methodmethod的操作,但我如何才能对Rails框架中的方法执行此操作?您对我如何更好地理解Gem及其API有什么建议吗?仅仅阅读源代码似乎真的很难,尤其是对于框架。谢谢! 最佳答案 Ru

  4. ruby - 为什么 Ruby 的 each 迭代器先执行? - 2

    我在用Ruby执行简单任务时遇到了一件奇怪的事情。我只想用每个方法迭代字母表,但迭代在执行中先进行:alfawit=("a".."z")puts"That'sanalphabet:\n\n#{alfawit.each{|litera|putslitera}}"这段代码的结果是:(缩写)abc⋮xyzThat'sanalphabet:a..z知道为什么它会这样工作或者我做错了什么吗?提前致谢。 最佳答案 因为您的each调用被插入到在固定字符串之前执行的字符串文字中。此外,each返回一个Enumerable,实际上您甚至打印它。试试

  5. ruby - 模块嵌套代码风格偏好 - 2

    我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的

  6. ruby - 寻找通过阅读代码确定编程语言的ruby gem? - 2

    几个月前,我读了一篇关于ruby​​gem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:

  7. ruby - Net::HTTP 获取源代码和状态 - 2

    我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur

  8. 程序员如何提高代码能力? - 2

    前言作为一名程序员,自己的本质工作就是做程序开发,那么程序开发的时候最直接的体现就是代码,检验一个程序员技术水平的一个核心环节就是开发时候的代码能力。众所周知,程序开发的水平提升是一个循序渐进的过程,每一位程序员都是从“菜鸟”变成“大神”的,所以程序员在程序开发过程中的代码能力也是根据平时开发中的业务实践来积累和提升的。提高代码能力核心要素程序员要想提高自身代码能力,尤其是新晋程序员的代码能力有很大的提升空间的时候,需要针对性的去提高自己的代码能力。提高代码能力其实有几个比较关键的点,只要把握住这些方面,就能很好的、快速的提高自己的一部分代码能力。1、多去阅读开源项目,如有机会可以亲自参与开源

  9. 叮咚买菜基于 Apache Doris 统一 OLAP 引擎的应用实践 - 2

    导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵

  10. Matlab imread()读到了什么 (浅显 当复习文档了) - 2

    matlab打开matlab,用最简单的imread方法读取一个图像clcclearimg_h=imread('hua.jpg');返回一个数组(矩阵),往往是a*b*cunit8类型解释一下这个三维数组的意思,行数、数和层数,unit8:指数据类型,无符号八位整形,可理解为0~2^8的数三个层数分别代表RGB三个通道图像rgb最常用的是24-位实现方法,即RGB每个通道有256色阶(2^8)。基于这样的24-位RGB模型的色彩空间可以表现256×256×256≈1670万色当imshow传入了一个二维数组,它将以灰度方式绘制;可以把图像拆分为rgb三层,可以以灰度的方式观察它figure(1

随机推荐