求matlab或vb关于追赶法的源程序
小弟最近在作论文时遇到了“追赶法求解三对角矩阵”的问题,在此小弟向各位大哥大姐求追赶法的matlab或vb源程序,哪位大侠快救救俺啊!小弟要是这块解决不了,下面就没有办法进行了啊 !!!!!!!!!!!===========eight============
请不要使用“跪求”等字眼
==========================
[ 本帖最后由 eight 于 2007-2-6 23:09 编辑 ] function x = tridisolve(a,b,c,d)
% TRIDISOLVESolve tridiagonal system of equations.
% x = TRIDISOLVE(a,b,c,d) solves the system of linear equations
% b(1)*x(1) + c(1)*x(2) = d(1),
% a(j-1)*x(j-1) + b(j)*x(j) + c(j)*x(j+1) = d(j), j = 2:n-1,
% a(n-1)*x(n-1) + b(n)*x(n) = d(n).
%
% The algorithm does not use pivoting, so the results might
% be inaccurate if abs(b) is much smaller than abs(a)+abs(c).
% More robust, but slower, alternatives with pivoting are:
% x = T\d where T = diag(a,-1) + diag(b,0) + diag(c,1)
% x = S\d where S = spdiags([ b ],[-1 0 1],n,n)
x = d;
n = length(x);
for j = 1:n-1
mu = a(j)/b(j);
b(j+1) = b(j+1) - mu*c(j);
x(j+1) = x(j+1) - mu*x(j);
end
x(n) = x(n)/b(n);
for j = n-1:-1:1
x(j) = (x(j)-c(j)*x(j+1))/b(j);
end
说明:a为主对角线下面的次对角线,b为主对角线,c为主对角线上面的次对角线,d为右端向量
请教高人
% More robust, but slower, alternatives with pivoting are:% x = T\d where T = diag(a,-1) + diag(b,0) + diag(c,1)
% x = S\d where S = spdiags([ b ],[-1 0 1],n,n)
这三句是不是表示在“abs(b) is much smaller than abs(a)+abs(c)”这种情况下,程序要想继续运行,则需要用x = T\d或 x = S\d 来代替x = d? 实际问题提出的三对角方程组,系数矩阵往往严格对角占优,所以不选主元,就可保证顺利,稳定运行
至于那些不是对角占优的abs(b) is much smaller than abs(a)+abs(c)”,此方法求出的误差就会比较大,此方法可能会失效
T = diag(a,-1) + diag(b,0) + diag(c,1)这个是转换成正常的格式
x = T\d 直接解估计是不行的,用高斯消元法或其他方法解吧
你先弄清楚你要解的是不是严格对角占优吧
个人意见,仅供参考
致谢
jimin(敏敏) 真是位人心的大侠啊!小弟对你的佩服之心犹如滔滔江水连绵不绝啊:)呵呵!谢过了啊求助:各位大侠帮我来调一下程序
我编了如下一个程序(主要是用追赶法求解),但就在程序算参数 b 的时候,每次 b(1) 的值正确,而 b(2) 以后的值都不对(我想实现 b(i)=2*(Y(i)+L(i+1)*I(i)*Y(i+1)/(L(i)*I(i+1))),为啥还会出错?郁闷),求大侠快来救命!!!小弟在线等!!!!!!!!!输入参数:
gaoding(2,147000,1000,10,0.244,0.244,0.184)
输入各跨的长度:
10
10
10
输入个跨惯性矩:
5e-5
5e-5
5e-5
运行程序:
%————————定义输入参数————————
function gaoding(n,PB,omega,bita,D0,DS,DC)
%————————定义已知条件————————
for j=1:n+1
L(j)=input('请输入各跨的长度\n');
end
for j=1:n+1
I(j)=input('请输入各跨的惯性矩\n');
end
for j=1:n
pi=3.14159265;
P(1)=PB;
w=omega;
bt=bita*pi/180;
E=2e11;
q=w*sin(bt);
P(j+1)=P(j)-0.5*w*L(j)*cos(bt)-0.5*w*L(j+1)*cos(bt);
end
%———————求u(j),X(j),Y(j),Z(j)———————
for j=1:n+1
u(j)=L(j)*sqrt(P(j)/(E*I(j)))/2;
X(j)=3*(tan(u(j))-u(j))/u(j)^3;
Y(j)=1.5*(0.5/u(j)-1/tan(2*u(j)))/u(j);
Z(j)=3*(1/(sin(2*u(j)))-0.5/u(j))/u(j);
end
%————在求d时要用到个e(0),故在此转化一下————
e(1:n+1)=0.5*(D0-DS);
f(1:n+1)=;
%————追赶法求解弯矩主程序————
for j=1:n-1
a(j)=Z(j+1);
c(j)=L(j+1)*I(j)*Z(j+1)/(L(j)*I(j+1));
end
a=;
c=;
for j=1:n
b(j)=2*(Y(j)+L(j+1)*I(j)*Y(j+1)/(L(j)*I(j+1))); %这就是b的一般表达式
d(j)=-q*L(j)^2*X(j)/4-q*L(j+1)^2*L(j+1)*I(j)*X(j+1)/(4*L(j)*I(j+1))+6*E*I(j)*(e(j)-f(j))/L(j)^2-6*E*I(j)*(e(j+1)-e(j))/(L(j)*L(j+1));
end
b=;
d=';
m = d;
k= length(m);
for j = 1:k-1
mu = a(j)/b(j);
b(j+1) = b(j+1) - mu*c(j);
m(j+1) = m(j+1) - mu*m(j);
end
m(k) = m(k)/b(k);
for j = k-1:-1:1
m(j) = (m(j)-c(j)*m(j+1))/b(j);
end
%————输出参数————
Pa=P(1)*e(1)/L(1)-m(1)/L(1)-q*L(1)/2;
P,u,X,Y,Z,a,b,c,d,m,Pa
得到结果:
P =
1.0e+005 *
1.4700 1.3701 1.2703
u =
0.6062 0.5853 0.5635
X =
1.1727 1.1591 1.1458
Y =
1.1141 1.1052 1.0964
Z =
1.2028 1.1867 1.1710
a =
1.1867
b =
4.4385 4.0859
c =
1.1867
d =
1.0e+003 *
-3.0509
-3.0156
m =
-543.4104
-538.4268
Pa =
-207.3387
按我编程的原意,算出来 b=,但为何域运行出来是 b=??????
有哪位好心的大侠原意帮我看看,调试一下?小弟不胜感激啊!!! function y=chase(a,b,c,d) %追赶法
=size(d);
d(1)=d(1)/b(1);
c(1)=c(1)/b(1);
for k=2:n
b(k)=b(k)-a(k)*c(k-1);
c(k)=c(k)/b(k);
d(k)=(d(k)-a(k)*d(k-1))/b(k);
end
for k=n-1:-1:1
d(k)=d(k)-c(k)*d(k+1);
end
for k=1:n
disp(d(k));
end
再加几个其他的数值分析方面的程序
% exp3_1.m --- 解线性方程组左除命令‘\’的学习
% ----------example1-----------
% Ax = b (x,b是列向量),当A是可逆矩阵时 x = A\b 产生该方程组的解
% 其算法基于LU分解相当于列主元Gauss消去法
A = [ 15 -9
064
111];
b = [-16 24 6]';
x1 = A\b
% [注] 该命令适用求解中小型稠密线性方程,而且性态是较好的(非病态),是最常用的命令
% 对于大型矩阵或病态的还有其它一些命令pcg,gmres,qmr等
% ----------example2-----------
% Ax = b ,当A是列满秩矩阵时 x = A\b 产生该方程组唯一的最小二乘解
% 其算法基于解法方程组 A'*A x = A'*b (见P125-126, 例11)
A = [211
1 -2 -3
3 -41
13 -2];
b = [-4 5 3 -2]';
x2 = A\b
% -----------example3----------
% 解矩阵方程AX = B ,当A可逆或列满秩
A = [ 13
14];
B = [ 12
34];
X = A\B
% exp3_2.m --- 矩阵分解命令的学习
% ---------- LU分解 ----------
% [简介] 设A是非奇异矩阵,则有如下列主元的LU分解
% PA = LU
% 其中P是置换矩阵(又称排列矩阵),L是单位下三角矩阵且|l(ij)|<=1,U是上三角矩阵
% 矩阵A如果有了上述分解则求解线性方程组 Ax = b 就等价于分别求解两个三角方程组
% Ly = Pb和Ux=y
% 而求解三角方程组是非常容易的.用这种方法求解方程组与列主元的Gauss消去法是等价的
% 但 LU 分解还有其它优点. 参见 P65 例9 和 P70 实验课题(一)
A = [10-70
-3 26
5-15];
= lu(A)
% 如果再给b,则下面是解两个三角方程组的程序. 参见P49(3-15)式
b = ';
=size(A);
x = zeros(n,1);
% 前代求解:Ly = Pb(解用x储存)
b = P*b;
x(1) = b(1);
for k = 2:n
x(k) = b(k)-L(k,1:k-1)*x(1:k-1);
end
% 回代求解:Ux = y (这里先y=x,解仍用x储存)
x(n) = x(n)/U(n,n);
for k = n-1:-1:1
x(k) = ( x(k)-U(k,k+1:n)*x(k+1:n) ) / U(k,k);
end
x
% ---------- Cholesky分解 ----------
% [简介] 设A是(实对称)正定矩阵,则有如下唯一的分解
% A = R'*R
% 其中 R 是上三角矩阵且主对角元全为正
% 例
A = [4 -1 1
-14.252.75
12.75 3.5];
R = chol(A)
% exp3_3.mGauss列主元消去法(示范程序)
function try_gauss
A = [ 15 -9
064
111];
b=[-3;10;3];
x=gauss(A,b) % 调用下面函数
function x = gauss(A,b)
% 输入: Ax = b 的系数矩阵 A (可逆)和右端项 b
% 输出:方程组的解 x
= size(A);
x = zeros(n,1);
Aug = ; % 增广矩阵
for k = 1:n-1
= max(abs(Aug(k:n,k)));% 找列主元所在子矩阵的行 r
r = r + k - 1; % 列主元所在大矩阵的行
if r>k
Aug(,:) = Aug(,:); % 对增广矩阵实施行交换
end
if Aug(k,k)==0,
error('这是奇异矩阵!') % 程序遇到error会中断执行并显示其中的提示内容
end
% 把增广矩阵消元成为上三角
for p = k+1:n
mult = Aug(p,k)/Aug(k,k); % 消元乘子
Aug(p,k:n+1) = Aug(p,k:n+1) - mult * Aug(k,k:n+1);
end
end
% 解上三角方程组
A = Aug(:,1:n); b = Aug(:,n+1);
x(n) = b(n)/A(n,n);
for k = n-1:-1:1
x(k) = ( b(k) - A(k,k+1:n)*x(k+1:n) ) / A(k,k);
end
% exp3_4.m --- 病态矩阵试验
% Hilbert矩阵是严重的病态的矩阵(见P56),求解病态方程组是相当困难
% 一般的方法都会失效,例如列主元Gauss消去法,要采取特殊的方法和技术
% 例如 (1) pcg (预处理共轭梯度法,只适用正定方程组),
% (2) gmres (广义最残差法,适用一般的大型疏矩阵)
n = 15;
A = hilb(n); % n 阶Hilbert矩阵
x = ones(n,1); % 指定精确解全是1
b = A*x;
c = cond(A,inf); % 求条件数,范数取最大值范数
x1 = A\b; % 用Gauss列主元消去法求解或者调用你编的 x1 = gauss(A,b)
x2 = pcg(A,b); % 用pcg法求解(A必须是正定矩阵)
x3=gmres(A,b); % gmres法求解结果
% 显示结果
clc
fprintf('A 的条件数 =%f\n',c)
fprintf('\nGauss法求解结果 pcg法求解结果 gmres法求解结果')
for i = 1:n
fprintf('\n%6.2f %6.2f %6.2f',x1(i),x2(i),x3(i))
end
% 注:范德蒙(Vandermonde)矩阵也是严重病态矩阵
% A = vander(V),其中V是一向量
% 对于维数较大的V,看一下范德蒙矩阵的条件数
% exp3_5.m --- SOR迭代法收敛速度受松驰因子的影响试验
function try_sor_and_relaxation
% 参见 P64例8 和 P65表3-4
A = [ 2-1 0 0
-1 2-1 0
0-1 2-1
0 0-1 2];
b = ';
tol = 1e-6;
maxiter = 1000;
P = ';
clc
fprintf('** SOR迭代:松驰因子与迭代次数的关系 **\n'),
fprintf('\n 松驰因子 迭代次数')
fprintf('\n---------------------------------')
for W = 1:0.1:1.9
= sor(A,b,tol,maxiter,P,W);
fprintf('\n %3.2f %4.0f',W,iternum)
end
% 通过以上结果,你认为最佳松驰因子大致为多少?
% ----------说明----------
% 对于对称正定三对角矩阵(上面矩阵就是),其最佳松驰因子是可以求得的
% Wopt = 2 / ( 1+sqrt(1-rho^2) )
% 其中rho是Jacobi迭代矩阵 Mj 的谱半径
% 下面求之,应该与我们实验的结果差不多吧,看看
D = diag(diag(A));
Mj = eye(4) - inv(D)*A;
rho = max(abs(eig(Mj)));
Wopt = 2 / ( 1+sqrt(1-rho^2) );
fprintf('\n---------------------------------')
fprintf('\n理论上最佳松驰因子是 Wopt = %3.2f',Wopt)
% ---------- SOR 迭代法 -----------
function = sor(A,B,tol,maxiter,P,W)
% = sor(A,B,tol,maxiter,P,W) SOR迭代法解线性方程组 AX=B
% 输入 ---- tol: 相对残向量的容差,当norm(B-AX)/norm(B) <= tol 终止迭代
% maxiter: 最大迭代次数;
% P: 初值
% W: 松驰因子,必须 0 < W < 2(当 W = 1 时为G-S迭代法)
% 输出 ---- X: 解向量
% iternum: 收敛迭代次数
N = length(B);X = P;tol = tol*norm(B);
for k = 1:maxiter
for i=1:N
if i == 1
X(1) = (B(1)-A(1,2:N)*P(2:N))/A(1,1);
elseif i == N
X(N) = (B(N)-A(N,1:N-1)*X(1:N-1))/A(N,N);
else
X(i) = (B(i)-A(i,1:i-1)*X(1:i-1)-A(i,i+1:N)*P(i+1:N))/A(i,i);
end
X(i) = (1-W)*P(i) + W*X(i);
end
if norm(B-A*X) <= tol, break,end;
P=X;
end
iternum=k;
return
本贴转自:星火学术论坛
页:
[1]