MATLAB 共轭梯度法求解线性方程组(附代码)

ops/2024/10/18 13:25:48/

共轭梯度法求解线性方程组

在这里插入图片描述

1. 引言

共轭梯度法(Conjugate Gradient Method)是一种用于求解大型稀疏对称正定线性方程组的迭代算法。该方法结合了梯度下降法和共轭方向的概念,以达到更快速的收敛。共轭梯度法 是介于最速下降法与牛顿法之间的一个方法,它仅需利用一阶导数信息,但克服了最速下降法收敛慢的缺点,又避免了牛顿法需要存储和计算Hesse矩阵并求逆的缺点,在有限元求解中经常用到此方法求解椭圆问题。

2. 数学原理

2.1 问题描述

给定一个对称正定矩阵 ( A ) 和一个向量 ( b ),我们需要求解线性方程组 ( Ax = b )。

2.2 目标函数

我们可以通过最小化二次型函数来求解上述线性方程组:

f ( x ) = 1 2 x T A x − b T x f(x) = \frac{1}{2} x^T A x - b^T x f(x)=21xTAxbTx

其梯度为:

∇ f ( x ) = A x − b \nabla f(x) = A x - b f(x)=Axb

2.3 梯度下降法

梯度下降法的更新公式为:

x k + 1 = x k − α k ∇ f ( x k ) x_{k+1} = x_k - \alpha_k \nabla f(x_k) xk+1=xkαkf(xk)

其中 α k \alpha_k αk 是步长。

2.4 共轭方向

共轭方向是一组特殊的搜索方向,满足以下条件:

p i T A p j = 0 for i ≠ j p_i^T A p_j = 0 \quad \text{for} \quad i \neq j piTApj=0fori=j.

2.5 共轭梯度法的迭代公式

  1. 初始化:选择初始点 x 0 x_0 x0,计算 r 0 = b − A x 0 r_0 = b - A x_0 r0=bAx0,并令 p 0 = r 0 p_0 = r_0 p0=r0.
  2. 迭代步骤:
    • 计算步长 α k \alpha_k αk
      α k = r k T r k p k T A p k \alpha_k = \frac{r_k^T r_k}{p_k^T A p_k} αk=pkTApkrkTrk.
    • 更新解向量 x k + 1 x_{k+1} xk+1
      x k + 1 = x k + α k p k x_{k+1} = x_k + \alpha_k p_k xk+1=xk+αkpk.
    • 更新残差 r k + 1 r_{k+1} rk+1
      r k + 1 = r k − α k A p k r_{k+1} = r_k - \alpha_k A p_k rk+1=rkαkApk.
    • 计算方向更新系数 β k \beta_k βk
      β k = r k + 1 T r k + 1 r k T r k \beta_k = \frac{r_{k+1}^T r_{k+1}}{r_k^T r_k} βk=rkTrkrk+1Trk+1.
    • 更新搜索方向 p k + 1 p_{k+1} pk+1
      p k + 1 = r k + 1 + β k p k p_{k+1} = r_{k+1} + \beta_k p_k pk+1=rk+1+βkpk.
  3. 检查收敛:如果 r k + 1 r_{k+1} rk+1 足够小,则停止迭代。

3. MATLAB 实现

以下是详细的 MATLAB 程序实现共轭梯度法

matlab">function [u,iter,res_norms] = conjugate_gradient(A, F, tol, maxIter)
%% 使用共轭梯度法求解 A * u = F
% A - 系数矩阵
% F - 右端向量
% tol - 收敛容差
% maxIter - 最大迭代次数% 初始化解向量
u = zeros(size(F));
r = F - A * u;  % 初始残差
p = r;  % 初始方向向量
rsold = r' * r;  % 初始残差范数res_norms = zeros(maxIter, 1);res_norms(1) = sqrt(rsold);for iter = 1:maxIterAp = A * p;alpha = rsold / (p' * Ap);u = u + alpha * p;  % 更新解r = r - alpha * Ap;  % 更新残差rsnew = r' * r;  % 新的残差范数res_norms(iter+1) = sqrt(rsnew);% 检查收敛性if sqrt(rsnew) < tolres_norms = res_norms(1:iter+1);break;endp = r + (rsnew / rsold) * p;  % 更新方向向量rsold = rsnew;
end

搞个 250000阶的大矩阵测试一下:

matlab">% 测试案例
n = 250000; % 矩阵规模
A = gallery('poisson', sqrt(n)); % 生成对称正定矩阵
b = rand(n, 1); % 生成右侧向量
% x0 = zeros(n, 1); % 初始解
tol = 1e-8;
max_iter = 100000;% 调用共轭梯度法
[x, k, res_norms] = conjugate_gradient(A, b,  tol, max_iter);% 显示结果
fprintf('迭代次数 k: %d\n', k);% 可视化结果
figure;
semilogy(res_norms, 'o-');
xlabel('迭代次数');
ylabel('残差范数');
title('共轭梯度法残差范数收敛曲线');
grid on;
set(gca,'FontName','Monospaced');

画出收敛曲线:
在这里插入图片描述
残差设定 1 e − 8 1e-8 1e8量级,几秒就能算出结果,效果不错!

如果读者有需求,我们将通过一系列博客展示数值分析课程相关的丰富内容,所有文章均有相应代码实现。请持续关注!


作者 :计算小屋
个人主页 : 计算小屋的主页


http://www.ppmy.cn/ops/86383.html

相关文章

力扣SQL50 上级经理已离职的公司员工 一题双解

Problem: 1978. 上级经理已离职的公司员工 Code -- 方法 1 -- select e1.employee_id -- from employees e1 -- left join employees e2 -- on e1.manager_id e2.employee_id -- where e1.salary < 30000 -- and e1.manager_id is not null -- and e2.employee_id is…

Java每日一题 ~ 盛最多水的容器

. - 力扣&#xff08;LeetCode&#xff09; 1.题目解析 本题的要求就是&#xff1a;给定数组索引之间的差值为宽&#xff0c;元素值中小的为边长求面积。 2.算法分析 思路一&#xff1a;暴力枚举 暴力法的思路是对所有可能的容器组合进行穷举&#xff0c;计算它们能容纳的水…

web网站组成

web网站由四部分组成&#xff1a;浏览器 前端服务器 后端服务器 数据库服务器 流程&#xff1a; 1.浏览器输入网站后&#xff0c;向前端服务器发送请求&#xff0c;前端服务器响应&#xff0c;静态的数据给浏览器。 2.前端代码中script中有url,这个是向后台发送请求的网…

SQL注入

目录 引言 一.SQL注入的产生机制 1. 输入验证的缺失 2. 数据库查询的拼接 3. 应用程序架构不当 二.如何防止SQL注入 1. 使用参数化查询&#xff08;Prepared Statements&#xff09; 2. 输入验证与清理 3. 最小权限原则 4. 定期安全审计与监控 引言 随着信息技术的迅…

C# 代理模式

栏目总目录 概念 代理模式是一种结构型设计模式&#xff0c;它为其他对象提供一种代理以控制对这个对象的访问。在代理模式中&#xff0c;我们创建一个具有现有对象&#xff08;称为“真实对象”或“被代理对象”&#xff09;相同功能的代理对象。代理对象可以在客户端和目标对…

JAVAWeb实战(后端篇)

因为前后端代码内容过多&#xff0c;这篇只写后端的代码&#xff0c;前端的在另一篇写 项目实战一&#xff1a; 1.创建数据库,表等数据 创建数据库 create database schedule_system 创建表&#xff0c;并添加内容 SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS 0;-- ---------…

day 02

作业&#xff1a; 1> 写一个日志文件&#xff0c;将程序启动后&#xff0c;每一秒的时间写入到文件中 1、2024- 7-29 10:31:19 2、2024- 7-29 10:31:20 3、2024- 7-29 10:31:21 ctrlc:停止程序 ./a.out 4、2024- 7-29 10:35:06 5、2024- 7-29 10:35:07 6、2024- 7-29 10:3…

python每日学习13:pandas库的用法(2)

python每日学习13&#xff1a;pandas库的用法&#xff08;2&#xff09; 建立索引:所有的数据框默认都已经使用从 0 开始的自然数索引&#xff0c;因此这里的"建立”索引指的是自定义索引 import pandas as pd import numpy as np df pd.DataFrame( {varl : 1.0, var2 :…