数值分析——线性方程组求解

这篇具有很好参考价值的文章主要介绍了数值分析——线性方程组求解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

缘起

清理磁盘的时候偶然发现大二下数值分析的实验作业还在,本着在丢弃之前可以放在网上以备不时之需的原则,我便发了上来。

题目1

分别用直接法、Jacobi迭代法、Gauss-Seidel迭代法求解下列线性方程组AX = b,其中A为五对角矩阵(n=20),b是除第一个分量是1外,其他分量都是0的列向量。
数值分析——线性方程组求解
(1) 直接法:观察到该题是形式特殊的五对角矩阵,利用matlab内置的用于产生稀疏矩阵的spdiags函数可以很容易生成系数矩阵A, A的产生代码如下:

e=ones(20,1);
A=spdiags([e -2*e 5*e -2*e e],-2:2,20,20);

利用追赶法(Thomas)可以较合适的解决问题,如果直接利用matlab内置的LU分解函数,显然是毫不费力的。

[L U]=lu(A);

利用上(下)对角系数矩阵在解决线性方程时的优良性质,可以在计算机上轻易得到结果:

b=zeros(20,1);
b(1)=1;
x=U\(L\b);

输出结果为(为了文本美观,输出了x的转置):

x =

  1110.2421    0.0944   -0.0218   -0.0314   -0.0069    0.0049    0.0036    0.0002   -0.0008   -0.0004    0.0001   
  12200.0001    0.0000   -0.0000   -0.0000   -0.0000    0.0000    0.0000   -0.0000   -0.0000

或者为了更好地理解LU分解的细节,我们可以自行编写LU代码,如下:

function [x]=LU(A,b)
 
n=length(b);
U=zeros(n);
L=eye(n);
 
for i=1:n
    U(1,i)=A(1,i);
end
 
for i=1:(n-1)
    for k=(i+1):n
           L(k,i)=(A(k,i)-sum(L(k,1:(i-1))*U(1:(i-1),i)))/U(i,i);
    end
    for k=(i+1):n
        U(i+1,k)=A(i+1,k)-sum(L(i+1,1:i)*U(1:i,k));
    end
end
 
x=zeros(n,1);
y=zeros(n,1);
y(1)=b(1);
 
for i=2:n
    s=0;
    for r=1:(i-1)
        s=s+L(i,r)*y(r);
        y(i)=b(i)-s;
    end
end
 
x(n)=y(n)/U(n,n);
for i=(n-1):-1:1
    s1=0;
    for r=(i+1):n
        s1=s1+U(i,r)*x(r);
        x(i)=(y(i)-s1)/U(i,i);
    end
end

经检验,运行 LU 函数可得相同结果
(2)Jacobi迭代法:

function [ ]=jacobi(A,b,x,iter_max)
 
D=diag(diag(A));
U=-triu(A,1);
L=-tril(A,-1);
B=D\(L+U);
f=D\b;
 
y=B*x+f;
r=@(x)norm(A*x-b);
n=1;
x_axis=[n];
y_axis=[r(x)];
z_axis=[norm(x)];
 
while norm(y-x)>=1.0e-6 && n<iter_max
  % fprintf('%f\n',r(x));
    x=y;
    x_axis=[x_axis n+1];
    y_axis=[y_axis r(x)];
    z_axis=[z_axis norm(x)];
    y=B*x+f;
    n=n+1;
end
fprintf('\n共迭代了%d次\n',n);
subplot(1,2,1);
plot(x_axis,y_axis);
xlabel('第i次迭代:(i=1,2,3...)');
ylabel('第i次迭代的残量:(i=1,2,3...)');
subplot(1,2,2);
plot(x_axis,z_axis);
xlabel('第i次迭代:(i=1,2,3...)');
ylabel('第i次迭代x的量:(i=1,2,3...)');
end

在实验中,我选取了零向量作为初始迭代点,A和b的产生与(1)中一模一样,这里不再叙述。iter_max是最大迭代步,当异常发生时,可以及时停止代码而不至于陷入死循环。为了清楚看到迭代的具体速度,这里进行了残量的可视化,输出结果如下:

输入:
>> e=ones(20,1);
>> A=spdiags([e -2*e 5*e -2*e e],-2:2,20,20);
>> b=zeros(20,1);
>> b(1)=1;
>> x=ones(20,1);
>> jacobi(A,b,x,100)
	
输出:
共迭代了100

数值分析——线性方程组求解
Jacobi法在这个具体问题中不收敛,这是一个意料之中的结果,要使用这种方法,前提是系数矩阵有良好的性质,使得迭代矩阵B的谱半径小于1,我们来算一算该题A的谱半径为多少:

>> D=diag(diag(A));
>> U=-triu(A,1);
>> L=-tril(A,-1);
>> B=D\(L+U);
>> max(abs(eig(B)))

ans =

    1.1743

根据jacobi法收敛的充要条件,我们知道大于1的话迭代将不收敛。顺便地,分享一下,我之前测试用时写地用于产生合适矩阵的函数:

%%
%   BG用于判断谱半径
%   size生成相应大小矩阵
%%
function A=jacobi_matrix(size)
BG=@(x)max(abs(eig(eye(size)-diag(x)\x)));
n=1;
while(n<=500)
    n=n+1;
    A=diag(diag(randn(size)));
    [Q,R]=qr(randn(size));
    a=max(max(abs(A)));
    a=1/(a+0.01);
    A=A*a;
    B=Q*A*Q';
    D=inv(diag(diag(B)));
    L=-triu(B,1);
    U=-tril(B,-1);
    A=D-L-U;
    if(BG(A)<=1.01)
        fprintf('\n success\n');
        return;
    end
end
fprintf('\nfail\n');
end

(3)Gauss_Seidel迭代法:(matlab代码如下:)

%%
%   function name:Gauss_Seidel
%%
function []=Gauss_Seidel(A,b,x,iter_max)
 
D=diag(diag(A));
U=-triu(A,1);
L=-tril(A,-1);
B=(D-L)\U;
f=(D-L)\b;
y=B*x+f;
r=@(x)norm(A*x-b);
n=1;
x_axis=[n];
y_axis=[r(x)];
z_axis=[norm(x)];
 
while norm(y-x)>=1.0e-6 && n<iter_max
  % fprintf('%f\n',r(x));
    x=y;
    x_axis=[x_axis n+1];
    y_axis=[y_axis r(x)];
    z_axis=[z_axis norm(x)];
    y=B*x+f;
    n=n+1;
end
fprintf('\n共迭代了%d次\n',n);
subplot(1,2,1);
plot(x_axis,y_axis);
xlabel('第i次迭代:(i=1,2,3...)');
ylabel('第i次迭代的残量:(i=1,2,3...)');
subplot(1,2,2);
plot(x_axis,z_axis);
xlabel('第i次迭代:(i=1,2,3...)');
ylabel('第i次迭代x的量:(i=1,2,3...)');
     
end

在运行出结果之前,我感觉大概率也不收敛,结果打脸了,只能说题目出得好啊,这也印证了对于同一个线性方程Ax=b,jacobi法与Gauss-Seidel法的收敛性之间没有必然的联系。

e=ones(20,1);
A=spdiags([e -2*e 5*e -2*e e],-2:2,20,20);
b=zeros(20,1);
b(1)=1;
x=ones(20,1);
Gauss_Seidel(A,b,x,500)

共迭代了19次
数值分析——线性方程组求解

x =

1110.2421    0.0944   -0.0218   -0.0314   -0.0069    0.0049    0.0036    0.0002   -0.0008   -0.0004    0.0001

  12200.0001    0.0000   -0.0000   -0.0000   -0.0000    0.0000    0.0000   -0.0000   -0.0000

让我们顺便算一下迭代矩阵的谱半径大小,反正又不用我算

>> D=diag(diag(A));
>> U=-triu(A,1);
>> L=-tril(A,-1);
>> B=(D-L)\U;
>> max(abs(eig(B)))

ans =

0.4501

题目2

A x = b Ax=b Ax=b 的解向量 x x x ,其中
A = ( 1 2 9 3000 2000 1000 4 / 1 0 6 3 / 1 0 6 2 / 1 0 6 ) , b = ( 1 2000 3 / 1 0 6 ) A=\begin{pmatrix} 1&2&9\\ 3000&2000&1000\\ 4/10^6 &3/10^6 &2/10^6 \end{pmatrix} ,b=\begin{pmatrix} 1\\ 2000\\ 3/10^6 \end{pmatrix} A=130004/106220003/106910002/106,b=120003/106
(1)求出系数矩阵 的条件数及解向量 x x x
(2)将 a 33 a_{33} a33 改为 3 / 1 0 6 3/10^6 3/106 b 3 b_3 b3 改为 4 / 1 0 6 4/10^6 4/106 ,求解向量 x ~ \tilde x x~.
(3)令 P = d i a g ( 1 , 1 0 − 3 , 1 0 6 ) P=diag(1,10^{-3},10^6) P=diag(1,103,106) 求解 P A X = P b PAX=Pb PAX=Pb,并求系数矩阵 P A PA PA 的条件数.
(4)对 P A PA PA 中的 a 33 a_{33} a33 P B PB PB 中的 b 3 b_3 b3 给以 1 0 − 6 10^{-6} 106 的扰动,求解向量 x ^ \hat x x^
结合上述计算结果,讨论以上方程组的性态.
解:
(1)

>> format long
>> A=[1 2 9;3000 2000 1000;4/(1e6) 3/(1e6) 2/(1e6)];
>> cond(A)

ans =

     1.920070697116523e+10

>> condest(A)

ans =

     2.300766669733331e+10

>> b=[1;2000;3/(1e6)];
>> x=A\b

x =

  -0.166666666666667
   1.333333333333333
  -0.166666666666667

(2)

>> A(3,3)=3/(1e6);
>> b(3)=4/(1e6);
>> x=A\b
x =
  -9.499999999999981
  16.499999999999968
  -2.499999999999995

(3)

>> P=diag([1,1e-3,1e6]);
>> x=(P*A)\(P*b)
x =
  -9.499999999999998
  16.499999999999996
  -2.500000000000000
>> cond(P*A)
ans =
     2.655782995863286e+02

>> condest(P*A)
ans =
     3.834999999999999e+02

(4)

>> A(3,3)=4/(1e6);
>> b(3)=5/(1e6);
>> x=(P*A)\(P*b)

x =
  18.500000000000004
 -29.000000000000007
   4.500000000000001

由上述结果可以看到对于病态矩阵(条件数过大),微小的扰动会使解向量的误差变得十分大,其相对误差会变得很大,求出来的解向量没有参考价值。而自行添加一个矩阵P,P起到平衡数量级的作用,可大大降低条件数的大小,虽然求出来的结果还是不精确,但其近似值与精确值已在同个数量级上,这样的解是有意义的,可为接下来的进一步精确提供信息。文章来源地址https://www.toymoban.com/news/detail-445676.html

到了这里,关于数值分析——线性方程组求解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • <<数值分析>>第二章线性方程组的直接解法

              解线性方程组是工程数学中最常见的模型之一。所说的“最常见”有两方面的含义: 1)一部分工程问题的本身建立的就是线性方程组模型; 2)较多工程问题建立的非线性方程组模型需要转化为线性方程组的求解。           线性方程组为Ax=b,以下介绍

    2024年02月08日
    浏览(53)
  • <<数值分析>> 第三章线性方程组的迭代解法

            线性方程组的理论求解公式——,在实际应用中面临着两大问题,1是计算过程复杂,2是无法保证算法的稳定性。同时初始数据存在误差,需要寻求能达到精度要求的、操作和计算过程相对简单的求解方法—— 迭代法。    目录 一.迭代法的基本思想 二.基本迭代

    2024年01月25日
    浏览(53)
  • 【数值分析实验】(五)线性方程组的迭代解法(含matlab代码)

            迭代法就是用某种极限过程去逐步逼近线性方程精确解的方法。迭代法具有需要计算机的存储单元较少、程序设计简单、原始系数矩阵在计算过程中始终不变等优点,但存在收敛性及收敛速度问题。 3.1.1 算法过程 3.1.2 代码 3.1.3 计算结果 3.2.1 算法过程 3.2.2 代码

    2024年02月03日
    浏览(45)
  • 线性方程组的求解

    克莱姆法则 求解线性方程组有一种比较简单易行的方法就是用克莱姆法则 通过行列式的计算 以解出方程,下面给出行列式解方程的代码并分析优缺点; 对于一个n元一次方程组,如果可以将其化为n阶行列式就能使用克莱姆法则;例如: 有 D=    用(b1,b2,...bn)T替换D的第一列

    2024年02月05日
    浏览(39)
  • MATLAB-线性方程组求解

    线性方程组是线性代数中的重要内容之一,其理论发展的最为完善。MATLAB中包含多种处理线性方程组的命令,下面进行详细介绍。 对于形如AX=B的方程组来说,假设其系数矩阵A是m×n的矩阵,根据其维数可以将方程组分以下3种情况。 1)若m=n,则为恰定方程组,即方程数等于未知

    2023年04月16日
    浏览(42)
  • MATLAB 之 线性方程组求解

    在 MATLAB 中,关于线性方程组的解法一般分为两类:一类是直接法,就是在没有舍入误差的情况下,通过有限步的矩阵初等运算来求得方程组的解;另一类是迭代法,就是先给定一个解的初始值,然后按照一定的迭代算法进行逐步逼近,求出更精确的近似解。 线性方程组的直

    2024年02月08日
    浏览(48)
  • 线性代数代码实现(七)求解线性方程组(C++)

    前言:         上次博客,我写了一篇关于定义矩阵除法并且代码的文章。矩阵除法或许用处不大,不过在那一篇文章中,我认为比较好的一点是告诉了大家一种计算方法,即:若矩阵  已知且可逆,矩阵  已知,并且  ,求解矩阵 B 。我认为这种初等行变换的方法还是挺

    2023年04月23日
    浏览(46)
  • matlab使用教程(6)—线性方程组的求解

            进行科学计算时,最重要的一个问题是对联立线性方程组求解。在矩阵表示法中,常见问题采用以下形式:给定两个矩阵 A 和 b,是否存在一个唯一矩阵 x 使 Ax = b 或 xA = b?         考虑一维示例具有指导意义。例如,方程         7x = 21         是否具

    2024年02月14日
    浏览(41)
  • 【算法竞赛模板】求解线性方程组是否有解(求解矩阵的秩)

        在实际运用中需判断线性方程组有无解,可以通过矩阵运算判断线性方程组是否有解 线性方程组有无解总结: 矩阵求解秩流程:    所以:当我们遇到题目问线性方程组是否有解时,只需求解系数矩阵的秩与增广矩阵的秩的关系 。我们可以通过分别求系数矩阵与增

    2024年02月12日
    浏览(37)
  • 解线性方程组(一)——克拉默法则求解(C++)

    解线性方程组最基础的方法就是使用克拉默法则,需要注意的是,该方程组必须是线性方程组。 假设有方程组如下: { a 11 x 1 + a 12 x 2 + ⋯ + a 1 n x n = b 1 a 21 x 1 + a 22 x 2 + ⋯ + a 2 n x n = b 2 ⋯ ⋯ ⋯ a n 1 x 1 + a n 2 x 2 + ⋯ + a n n x n = b n begin{cases} a_{11}x_1+a_{12}x_2+cdots+a_{1n}x_n=b_1\\\\

    2024年02月20日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包