MATLAB中bicgstabl函数用法

目录

语法

说明

示例

线性系统的迭代解

[使用指定了预条件子的 bicgstabl](#使用指定了预条件子的 bicgstabl)

提供初始估计值

使用函数句柄代替数值矩阵


bicgstabl函数的功能是求解线性系统 - 稳定双共轭梯度 (l) 法。

语法

cs 复制代码
x = bicgstabl(A,b)
x = bicgstabl(A,b,tol)
x = bicgstabl(A,b,tol,maxit)
x = bicgstabl(A,b,tol,maxit,M)
x = bicgstabl(A,b,tol,maxit,M1,M2)
x = bicgstabl(A,b,tol,maxit,M1,M2,x0)
[x,flag] = bicgstabl(___)
[x,flag,relres] = bicgstabl(___)
[x,flag,relres,iter] = bicgstabl(___)
[x,flag,relres,iter,resvec] = bicgstabl(___)

说明

**x = bicgstabl(A,b)**尝试使用双共轭梯度稳定法 (l)求解关于 x 的线性系统 A*x = b。如果尝试成功,bicgstabl 会显示一条消息来确认收敛。如果 bicgstabl 无法在达到最大迭代次数后收敛或出于任何原因暂停,则会显示一条包含相对残差 norm(b-A*x)/norm(b) 以及该方法停止时的迭代次数的诊断消息。

**x = bicgstabl(A,b,tol)**指定该方法的容差。默认容差是 1e-6。

**x = bicgstabl(A,b,tol,maxit)**指定要使用的最大迭代次数。如果 bicgstabl 无法在 maxit 次迭代内收敛,将显示诊断消息。

x = bicgstabl(A,b,tol,maxit,M) 指定预条件子矩阵 M 并通过有效求解关于 y 的方程组 AM^−1y=b 来计算 x,其中 y=Mx。使用预条件子矩阵可以改善问题的数值属性和计算的效率。

x = bicgstabl(A,b,tol,maxit,M1,M2) 指定预条件子矩阵 M 的因子,使得 M = M1*M2。

**x = bicgstabl(A,b,tol,maxit,M1,M2,x0)**指定解向量 x 的初始估计值。默认值为由零组成的向量。

**[x,flag] = bicgstabl(___)**返回一个标志,指示算法是否成功收敛。当 flag = 0 时,收敛成功。您可以将此输出语法用于之前的任何输入参数组合。如果指定了 flag 输出,bicgstabl 将不会显示任何诊断消息。

**[x,flag,relres] = bicgstabl(___)**还会返回相对残差 norm(b-A*x)/norm(b)。如果 flag 为 0,则 relres <= tol。

**[x,flag,relres,iter] = bicgstabl(___)**还会返回计算出 x 时的迭代次数 iter。

**[x,flag,relres,iter,resvec] = bicgstabl(___)**还会在每个四分之一迭代中返回残差范数向量(包括第一个残差 norm(b-A*x0))。

示例

线性系统的迭代解

使用采用默认设置的 bicgstabl 求解系数矩阵为方阵的线性系统,然后在求解过程中调整使用的容差和迭代次数。

创建密度为 50% 的随机稀疏矩阵 A。另为 Ax=b 的右侧创建随机向量 b

cs 复制代码
rng default
A = sprand(400,400,.5);
A = A'*A;
b = rand(400,1);

使用 bicgstabl 求解 Ax=b。输出显示包括相对残差 的值。

cpp 复制代码
x = bicgstabl(A,b);

bicgstabl stopped at iteration 20 without converging to the desired tolerance 1e-06
because the maximum number of iterations was reached.
The iterate returned (number 20) has relative residual 0.095.

默认情况下,bicgstabl 使用 20 次迭代和容差 1e-6,对于此矩阵,算法无法在 20 次迭代后收敛。由于残差仍然很大,这说明需要更多的迭代(或预条件子矩阵)。您也可以使用更大的容差,使算法更容易收敛。

使用容差 1e-4 和 100 次迭代再次求解方程组。

cs 复制代码
x = bicgstabl(A,b,1e-4,100);

bicgstabl stopped at iteration 100 without converging to the desired tolerance 0.0001
because the maximum number of iterations was reached.
The iterate returned (number 100) has relative residual 0.028.

即使采用更宽松的容差和更多迭代,残差也并未改进多少。当迭代算法以这种方式停滞时,显然需要预条件子矩阵。

计算 A 的不完全 Cholesky 分解,并使用 L' 因子作为 bicgstabl 的预条件子输入。

cs 复制代码
L = ichol(A);
x = bicgstabl(A,b,1e-4,100,L');
bicgstabl converged at iteration 15.5 to a solution with relative residual 2.5e-05.

使用预条件子可以充分改进问题的数值属性,使 bicgstabl 能够收敛。

使用指定了预条件子的 bicgstabl

检查使用指定了预条件子矩阵的 bicgstabl 来求解线性系统的效果。

加载 west0479,它是一个非对称的 479×479 实稀疏矩阵。

cs 复制代码
load west0479
A = west0479;

定义b以使 Ax=b 的实际解是全为 1 的向量。

cs 复制代码
b = sum(A,2);

设置容差和最大迭代次数。

cs 复制代码
tol = 1e-12;
maxit = 20;

使用 bicgstabl 根据请求的容差和迭代次数求解。指定五个输出以返回有关求解过程的信息:

  • x 是计算 A*x = b 所得的解。

  • fl0 是指示算法是否收敛的标志。

  • rr0 是计算的解 x 的相对残差。

  • it0 是计算 x 时所用的迭代次数。

  • rv0 是 ‖b−Ax‖ 的残差历史记录组成的向量。

cs 复制代码
[x,fl0,rr0,it0,rv0] = bicgstabl(A,b,tol,maxit);
fl0
fl0 = 1
rr0
rr0 = 1
it0
it0 = 0

bicgstabl 未在请求的 20 次迭代内收敛至请求的容差 1e-12,因此 fl0 为 1。实际上,bicgstabl 的行为太差,因此初始估计值 x0 = zeros(size(A,2),1) 是最佳解,并会返回最佳解(如 it0 = 0 所示)。

为了有助于缓慢收敛,可以指定预条件子矩阵。由于 A 是非对称的,请使用 ilu 生成预条件子 M=L U。指定调降容差,以忽略值小于 1e-6 的非对角线元。通过指定 L 和 U 作为 bicgstabl 的输入,求解预条件方程组 A M^−1M x=b。

cs 复制代码
setup = struct('type','ilutp','droptol',1e-6);
[L,U] = ilu(A,setup);
[x1,fl1,rr1,it1,rv1] = bicgstabl(A,b,tol,maxit,L,U);
fl1
fl1 = 0
rr1
rr1 = 1.0652e-15
it1
it1 = 2

在第二次迭代中,使用 ilu 预条件子产生的相对残差小于规定的容差 1e-12。输出 rv1(1) 为 norm(b),输出 rv1(end) 为 norm(b-A*x1)。

可以通过绘制每次迭代的相对残差来跟踪 bicgstabl 的进度。绘制每个解的残差历史记录图,并添加一条表示指定容差的线。

cpp 复制代码
semilogy(0:length(rv0)-1,rv0/norm(b),'-o')
hold on
semilogy(0:length(rv1)-1,rv1/norm(b),'-o')
yline(tol,'r--');
legend('No preconditioner','ILU preconditioner','Tolerance','Location','East')
xlabel('Iteration number')
ylabel('Relative residual')

如图所示:

提供初始估计值

检查向 bicgstabl 提供解的初始估计值的效果。

创建一个三对角稀疏矩阵。使用每行的总和作为 Ax=b 右侧的向量,使 x 的预期解是由 1 组成的向量。

cpp 复制代码
n = 900;
e = ones(n,1);
A = spdiags([e 2*e e],-1:1,n,n);
b = sum(A,2);

使用 bicgstabl 求解 Ax=b 两次:一次是使用默认的初始估计值,一次是使用解的良好初始估计值。对两次求解均使用 20 次迭代和默认容差。将第二种求解中的初始估计值指定为所有元素都等于 0.99 的向量。

cs 复制代码
maxit = 20;
x1 = bicgstabl(A,b,[],maxit);
bicgstabl converged at iteration 9.2 to a solution with relative residual 9.5e-07.
x0 = 0.99*e;
x2 = bicgstabl(A,b,[],maxit,[],[],x0);
bicgstabl converged at iteration 2 to a solution with relative residual 5.4e-07.

在这种情况下,提供初始估计值可以使 bicgstabl 更快地收敛。

返回中间结果

还可以通过在 for 循环中调用 bicgstabl 来使用初始估计值获得中间结果。每次调用求解器都会执行几次迭代,并存储计算出的解。然后,将该解用作下一批迭代的初始向量。

例如,以下代码会循环执行四次,每次执行 100 次迭代,并在 for 循环中每通过一次后均存储解向量:

cs 复制代码
x0 = zeros(size(A,2),1);
tol = 1e-8;
maxit = 100;
for k = 1:4
    [x,flag,relres] = bicgstabl(A,b,tol,maxit,[],[],x0);
    X(:,k) = x;
    R(k) = relres;
    x0 = x;
end

X(:,k) 是在 for 循环的第 k 次迭代时计算的解向量,R(k) 是该解的相对残差。

使用函数句柄代替数值矩阵

通过为 bicgstabl 提供用来计算 A*x 的函数句柄(而非系数矩阵 A)来求解线性系统。

gallery 生成的 Wilkinson 测试矩阵之一是 21×21 三对角矩阵。预览该矩阵。

cs 复制代码
A = gallery('wilk',21)
A = 21×21

    10     1     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0
     1     9     1     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0
     0     1     8     1     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0
     0     0     1     7     1     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0
     0     0     0     1     6     1     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0
     0     0     0     0     1     5     1     0     0     0     0     0     0     0     0     0     0     0     0     0     0
     0     0     0     0     0     1     4     1     0     0     0     0     0     0     0     0     0     0     0     0     0
     0     0     0     0     0     0     1     3     1     0     0     0     0     0     0     0     0     0     0     0     0
     0     0     0     0     0     0     0     1     2     1     0     0     0     0     0     0     0     0     0     0     0
     0     0     0     0     0     0     0     0     1     1     1     0     0     0     0     0     0     0     0     0     0
      ⋮

Wilkinson 矩阵有特殊的结构,因此您可以用函数句柄来表示 A*x 运算。当 A 乘以向量时,所得向量中的大多数元素为零。结果中的非零元素对应于 A 的非零三对角元素。此外,只有主对角线具有不等于 1 的非零值。

表达式 Ax 变为:

结果向量可以写为三个向量的和:

在 MATLAB® 中,编写一个函数来创建这些向量并将它们相加,从而给出 A*x 的值:

cs 复制代码
function y = afun(x)
y = [0; x(1:20)] + ...
    [(10:-1:0)'; (1:10)'].*x + ...
    [x(2:21); 0];
end

(该函数作为局部函数保存在示例的末尾。)

现在,通过为 bicgstabl 提供用于计算 A*x 的函数句柄,求解线性系统 Ax=b。使用容差 1e-12 和 50 次迭代。

cs 复制代码
b = ones(21,1);
tol = 1e-12;  
maxit = 50;
x1 = bicgstabl(@afun,b,tol,maxit)
bicgstabl converged at iteration 5.2 to a solution with relative residual 2e-15.
x1 = 21×1

    0.0910
    0.0899
    0.0999
    0.1109
    0.1241
    0.1443
    0.1544
    0.2383
    0.1309
    0.5000
      ⋮

检查 afun(x1) 是否产生由 1 组成的向量。

cs 复制代码
afun(x1)
ans = 21×1

    1.0000
    1.0000
    1.0000
    1.0000
    1.0000
    1.0000
    1.0000
    1.0000
    1.0000
    1.0000
      ⋮

局部函数

cs 复制代码
function y = afun(x)
y = [0; x(1:20)] + ...
    [(10:-1:0)'; (1:10)'].*x + ...
    [x(2:21); 0];
end

双共轭梯度稳定法 (l)

双共轭梯度稳定 l (BiCGSTABL) 算法是为了改进 BiCGSTAB 方法而开发的,后者本身是为了改进 BiCG 方法而开发的。

像 BiCGSTAB 一样,BiCGSTABL 算法使用 GMRES 步骤来减轻 BiCG 中引入的不规则收敛行为。然而,BiCGSTABL 使用 BiCGSTAB 的 GMRES(2) 步骤而不是 GMRES(1) 步骤,因此能够提供更好的校正,减少频繁停滞的情况 [1]

提示

  • ​大多数迭代方法的收敛取决于系数矩阵的条件数 cond(A)。当 A 是方阵时,您可以使用 equilibrate 来改进其条件数,它本身就能使大多数迭代求解器更容易收敛。但如果您随后会对经平衡处理的矩阵 B = R*P*A*C 进行因式分解,使用 equilibrate 还可以获得质量更好的预条件子矩阵。

  • 可以使用矩阵重新排序函数(如 dissect 和 symrcm)来置换系数矩阵的行和列,并在系数矩阵被分解以生成预条件子时最小化非零值的数量。这可以减少后续求解预条件线性系统所需的内存和时间。

参考

[1] Barrett, R., M. Berry, T. F. Chan, et al., Templates for the Solution of Linear Systems: Building Blocks for Iterative Methods, SIAM, Philadelphia, 1994.

相关推荐
喵叔哟8 分钟前
重构代码中引入外部方法和引入本地扩展的区别
java·开发语言·重构
尘浮生14 分钟前
Java项目实战II基于微信小程序的电影院买票选座系统(开发文档+数据库+源码)
java·开发语言·数据库·微信小程序·小程序·maven·intellij-idea
hopetomorrow28 分钟前
学习路之PHP--使用GROUP BY 发生错误 SELECT list is not in GROUP BY clause .......... 解决
开发语言·学习·php
小牛itbull37 分钟前
ReactPress vs VuePress vs WordPress
开发语言·javascript·reactpress
请叫我欧皇i1 小时前
html本地离线引入vant和vue2(详细步骤)
开发语言·前端·javascript
闲暇部落1 小时前
‌Kotlin中的?.和!!主要区别
android·开发语言·kotlin
GIS瞧葩菜1 小时前
局部修改3dtiles子模型的位置。
开发语言·javascript·ecmascript
chnming19871 小时前
STL关联式容器之set
开发语言·c++
带多刺的玫瑰1 小时前
Leecode刷题C语言之统计不是特殊数字的数字数量
java·c语言·算法
爱敲代码的憨仔1 小时前
《线性代数的本质》
线性代数·算法·决策树