MATLAB--非线性、线性方程组的求解

%%牛顿法和牛顿下山法
% h=@(x) x.^3+x.^2-1;
% x = newton_eq(h,1,1000);

function result=newton_eq(h,x,n)
%x为初始值
%n为迭代次数
f = matlabFunction(h);%转化为句柄形式
f1=matlabFunction(diff(h));%weishixian
X(1)=x;
i=2;
while 1
    X(i)=X(i-1)-lamda*f(X(i-1))/f1(X(i-1));
    if abs(f(X(i)))<1e-6
        result=X(i);
        return;
    end
    if abs(f(X(i)))         lamda=1;
    else
        lamda=lamda/2;
    end
    if i> n
        result=X(i);
        return;
    end
    i=i+1;
end

%%弦截法

h=@(x) x.^3+x.^2-1;
[x,tol] = xianjie(h,[1,2],1000);

function [result,to]=xianjie(f,x,n)
if nargout==1
    flag=1;
elseif nargout==2
    flag=2;
end
x1=x(1);
x2=x(2);
i=1;
while i < n
    x3=x2-f(x2)*(x2-x1)/(f(x2)-f(x1));
    if abs(f(x3))<1e-6
        if flag==1
        result=x3;
        return;
        elseif flag==2
        result=x3;
        to=abs(f(x3));
        return;
        end   
    end
    x1=x2;
    x2=x3;
    i=i+1;
end

%%抛物线法

h=@(x) x.^3+x.^2-1;
[x,tol] = paowuxian(h,[-5,0,5]);

function [result,tol]=paowuxian(h,x)
if nargout==1||nargout==0
    flag=1;
elseif nargout==2
    flag=2;
end
f=h;
x1=x(1);
x2=x(2);
x3=x(3);
while 1
    y1=f(x1);
    y2=f(x2);
    y3=f(x3);
    f1=lagrange([x1,x2,x3],[y1,y2,y3]);
    a=f1(1);b=f1(2);c=f1(3);
    if b^2-4*a*c<=0
        disp('初值不合适');
        result=[];
        tol=[];
        return;
    end
        x4_1=(-b+sqrt(b^2-4*a*c))/(2*a);
        x4_2=(-b-sqrt(b^2-4*a*c))/(2*a);
        if abs(x1-x4_1)             x4=x4_1;
        else
            x4=x4_2;
        end
        if abs(f(x4))<1e-6
            if flag==1||flag==0
                result=x4;
                return;
            elseif flag==2
                result=x4;
                tol=abs(f(x4));
                return;
            end
        end
        x1=x2;
        x2=x3;
        x3=x4;
end

%% fzero
% 用法1
x1=fzero('x.^2-2',1);%根趋近于1
x2=fzero('x.^2-2',[0,3]);%根在【0,3】区间里
%用法二
x3=fzero(@myfun,2)
%新建一个脚本文件
% function y=myfun(x)
% y=x.^2-2+x.^3;

fun=@(x) x.^2-2+x.^3;
x4=fzero(fun,2);

options=optimset('Display','Final')%notify
fun=@(x) x.^2-2+x.^3;
x5=fzero(fun,2,options);

[x6,fval]=fzero(fun,2);
[x6,fval,exitflag]=fzero(fun,2);

%% solve
%第一种
%re=sovle('2*x==a','x') 将会移除
syms a x
rel=solve(2*x^2==a,x)
%第二种
syms a b c x
y=a*x^2+b*x+c  %y==0
re2=solve(y,x)
%第三种
syms a b c x
y=a*x^2+b*x+c==2  %y==0
re2=solve(y,x)
%第四种
syms x
y=sin(x)*cos(x)
re3=solve(y,x)%求解一个解
[re3,pa,cond]=solve(y,x,'ReturnConditions',true)%pa返回的是参数,cond返回的是参数条件
assume(cond)
interval=[re3>0,re3<2*pi]
s=solve(interval,pa)
v=subs(re3,pa,s)
%多变量
syms a b c x1 x2
y1=a*x1^2+b*x2+c;
y2=a*x1^2-2*b*x2-c^2;
[x1,x2]=solve([y1,y2],[x1,x2])

syms x
y=x^3+1==0;
x1=solve(y,x,'Real',ture)
%多项式
syms x
y=x^3+x^2+1==0
x1=solve(y,x)
x1=vpa(x1,10)%显示计算后的精度
x2=solve(y,x,'MaxDegree',3)%显示三阶的结果

%
syms x y
f1=x+2*y==1
f2=x^2-y==0
[x,y]=solve([f1,f2],[x,y])

%% fsolve
% global x3
% x3=2;
[x,fval]=fsolve('demo_fsolve1',[1 1])
%
[x,fval]=fsolve('demo_fsolve1',[1 1],[],2)
% 函数形式:function f=demo_fsolve(x0,x3)

my.options=optimoptions('fsolve','Display','none');
my.objective=@demo_fsolve1;
my.x0=[1 1];
my.solver='fsolve';
x=fsolve(my)

function f=demo_fsolve1(x0)
% global x3
x1=x0(1);
x2=x0(2);
f(1)=x1.^3+x2.^2-5;
% f(1)=x1.^3+x2.^2-5+x3;
f(2)=(x1+1)*x2-(3*x1+1);

x10=[0 0;0 0];
option=optimoptions('fsolve','Display','iter');%final最后输出
%MaxIterations 迭代次数若求不出结果可设的大一点
%Algorithm 若求不出结果,算法同样可改变 trust-region-doglag  trust-region  L-M levenberg-marquardt

x=fsolve('demo_fsolve2',x10);

function f=demo_fsolve2(x)
x1=x;
f=x1*x1+x1-[2 3;4 5];

x=[0,0];
[x,fval]=fsolve('mymain',x,option,2,3)

function f=mymain(x,y1,y2)
r=myfun1(x);
f(1)=r(1)^2++r(3)-y1^2-y2;
f(2)=r(2)^2*y2+y1-r(1);

function r=myfun1(x)
x1=x(1);
x2=x(2);
r(1)=x1*x2+6*x1+x2^2;
r(2)=x1*x2-x2+x1*x2^2;
r(3)=x2-x2^3+x1*x2^2;

%% 线性方程组--高斯消元法
A=[1 2 3 5;5 2 3 1;8 4 1 3;8 5 2 1;];
b=[5;8;2;4;];
x=GS(A,b)

function X=GS(A,b)
%高斯消元法,本例仅计算有唯一解的非线性齐次方程
if det(A)==0,error('行列式为0,求解终止');end
m=size(A,1);
A=[A,b];
%% 消元
for i=1:m-1
    a=A(i,i);
    if a==0
        fprintf('第%d个主元为0,求解结束',i);
        return;
    end
    for j =i+1:m
        k=A(j,i)/a;
        A(j,:)=A(j,:)-k*A(i,:);
    end
end
%% 回代
for i=m:-1:2 %共有m-1列需要回代
    a=A(i,i);
    for j=i-1:-1:1
        k=A(j,i)/A(i,i);
         A(j,:)=A(j,:)-k*A(i,:);
    end
end
%% 对角线单位化,求X的值
for i=1:m
    A(i,:)=A(i,:)/A(i,i);
    X(i)=A(i,end);
end

%% 线性方程组--列主元法
A=[0.001 2 3;-1 3.712 4.623;-2 1.072 5.643];
b=[1 2 3]';
x1=A\b;
x=GS_col(A,b);

function X=GS_col(A,b)
%高斯消元法,列主元消去法
if det(A)==0,error('行列式为0,求解终止');end
m=size(A,1);
A=[A,b];
%% 消元
for i=1:m-1
    %寻找第一列最大主元
    c=A(i:end,i);%取出第i列的第i个到最后一个元素
    id=find(abs(c)==max(abs(c)));%计算绝对值最大的位置
    row=id(1)+i-1;%因为可能有相同的最大元素,取第一个
    %交换行
    temp=A(i,:);
    A(i,:)=A(row,:);
    A(row,:)=temp;
    a=A(i,i);
    if a==0
        fprintf('第%d个主元为0,求解结束',i);
        return;
    end
    for j =i+1:m
        k=A(j,i)/a;
        A(j,:)=A(j,:)-k*A(i,:);
    end
end
%% 回代
for i=m:-1:2 %共有m-1列需要回代
    for j=i-1:-1:1
        k=A(j,i)/A(i,i);
         A(j,:)=A(j,:)-k*A(i,:);
    end
end
%% 对角线单位化,求X的值
X=zeros(m,1);
for i=1:m
    A(i,:)=A(i,:)/A(i,i);
    X(i)=A(i,end);
end

%% 线性方程组--三角分解法
A=[2 2 -1;1 2 -3;1 -2 1];
b=[2;6;10];
x=A\b;
x1=inv(A)*b;
%% lu
[l,u]=lu(A);
x2=u\(l\b);
%% qr
[q,r]=qr(A);
x3=r\(q\b);
%% LDU
[l,d,u]=LDU(A);%自己写的函数LDU
x4=u\(d\(l\b));

%% 线性方程组--迭代法
B0=[0 3/8 -2/8;-4/11 0 1/11;-6/12 -3/12 0];
f=[20/8 33/11 36/12]';
x0=[0 0 0]';
for i=1:10
    x1=B0*x0+f;
    x0=x1;
end

%% 线性方程组--雅克比迭代法
A=[8 -3 2;4 11 -1;6 3 12];
b=[20 33 36]';
x0=[0 0 0]';
[x,k]=jacobi(A,b,x0,200)%k迭代哪一次得出的结果

function [result,k]=jacobi(A,b,x0,n)
%线性方程组迭代求解,雅克比迭代
%A为系数矩阵
%b为常数向量
%x0为初始值
D=diag(diag(A));
L=-tril(A,-1);%下三角矩阵,-1表示从对角线下一行开始取
U=-triu(A,1);%上三角矩阵,1表示从对角线上一行开始取
B=D^(-1)*(L+U);
r=vrho(B);%谱半径,特征值绝对值最大的那一个,小于1收敛
if r>1
    disp('无法收敛');
    return;
end
f=D^(-1)*b;
i=1
while i     x1=B*x0+f;
    if norm(x1-x0)<1e-6
        result=x1;
        k=i;
        return;
    end
    x0=x1;
    i=i+1;
end
%% 线性方程组--高斯-赛德尔迭代法
A=[8 -3 2;4 11 -1;6 3 12];
b=[20 33 36]';
x0=[0 0 0]';
x=gauss_seidel(A,b,x0)%k迭代哪一次得出的结果

function result=gauss_seidel(A,b,x0)
%线性方程组迭代求解,高斯-赛德尔,可以利用当前解得前面的分量求解后面的分量
%A为系数矩阵
%b为常数向量
%x0为初始值
D=diag(diag(A));
L=-tril(A,-1);%下三角矩阵,-1表示从对角线下一行开始取
U=-triu(A,1);%上三角矩阵,1表示从对角线上一行开始取
B=(D-L)^(-1)*U;
r=vrho(B);%谱半径,特征值绝对值最大的那一个,小于1收敛
if r>1
    disp('无法收敛');
    return;
end
f=(D-L)^(-1)*b;
i=1;
while 1
    x1=B*x0+f;
    if norm(x1-x0)<1e-8
        result=x1;
        return;
    end
    if i>1000
        return;
    end
    x0=x1;
    i=i+1;
end

%% 线性方程组--Sor迭代法
A=[8 -3 2;4 11 -1;6 3 12];
b=[20 33 36]';
x0=[0 0 0]';
[x,k]=Sor(A,b,x0,1);

function [result,k]=Sor(A,b,x0,w)
%线性方程组迭代求解,逐次超松弛,successive over relaxation method M=1/w*(D-wL)
%w=1,为gauss_seidel迭代,w>1为超松弛迭代,w<1为低松弛迭代,松弛迭代因子只有在0-2范围内才可能收敛
%A为系数矩阵
%b为常数向量
%x0为初始值
D=diag(diag(A));
L=-tril(A,-1);%下三角矩阵,-1表示从对角线下一行开始取
U=-triu(A,1);%上三角矩阵,1表示从对角线上一行开始取
B=(D-w*L)^(-1)*((1-w)*D+w*U);
r=vrho(B);%谱半径,特征值绝对值最大的那一个,小于1收敛
if r>1
    disp('无法收敛');
    return;
end
f=w*(D-w*L)^(-1)*b;
i=1;
while 1
    x1=B*x0+f;
    if norm(x1-x0)<1e-8
        result=x1;
        k=i;
        return;
    end
    if i>1000
        return;
    end
    x0=x1;
    i=i+1;
end

A=[5 2 6 0 0 1 0;
   4 5 1 0 0 0 0;
   0 0 0 2 3 1 0;
   1 0 2 3 1 0 0;
   5 2 0 1 2 3 0;
   0 0 0 1 2 0 3;
   2 0 3 0 1 0 0;];
b=[1 2 5 6 3 4 0]';
%% bicg
x1=A\b;
x=bicg(A,b);
maxit=15;
x=bicg(A,b,1e-14,maxit);%1e-14是自己指定的相对残差,不一定能达到,maxit是自定义迭代次数,范围在min(阶数,20)
M1=rand(7);%预处理器
M2=rand(7);%inv(M)*Ax=inv(M)*b
x=bicg(A,b,1e-14,maxit,M1,M2);

[x,flag,relres,iter,resvec]=bicg(A,b,1e-14,maxit,M1,M2);%flag为验证指标,若为0,则是比较成功收敛的
%relres是相对残差 norm(b-Ax)/norm(b),iter为迭代次数,resvec为每次迭代的相对残差
%% cgs 与上一个函数用法类似
x=cgs(A,b);
maxit=15;
x=cgs(A,b,1e-14,maxit);%1e-14是自己指定的相对残差,不一定能达到,maxit是自定义迭代次数,范围在min(阶数,20)
M1=rand(7);%预处理器
M2=rand(7);%inv(M)*Ax=inv(M)*b
x=bicg(A,b,1e-14,maxit,M1,M2);

[x,flag,relres,iter,resvec]=cgs(A,b,1e-14,maxit,M1,M2);%flag为验证指标,若为0,则是比较成功收敛的
%relres是相对残差 norm(b-Ax)/norm(b),iter为迭代次数,resvec为每次迭代的相对残差

A=[5 2 6 0 0 1 0;
   4 5 1 0 0 0 0;
   0 0 0 2 3 1 0;
   1 0 2 3 1 0 0;
   5 2 0 1 2 3 0;
   0 0 0 1 2 0 3;
   2 0 3 0 1 0 0;];
b=[1 2 5 6 3 4 0]';
%% lsqr
x=lsqr(A,b);
maxit=15;
x=lsqr(A,b,1e-14,maxit);%1e-14是自己指定的相对残差,不一定能达到,maxit是自定义迭代次数,范围在min(阶数,20)
M1=rand(7);%预处理器
M2=rand(7);%inv(M)*Ax=inv(M)*b
x=lsqr(A,b,1e-15,maxit,M1,M2);
x0=[0.1 0.2 0.2 0.3 0.2 0.1 0.3]';
x=lsqr(A,b,1e-15,maxit,M1,M2,x0);%给定一个初值,比较靠近真实值,默认的都是给定0
[x,flag,relres,iter,resvec]=lsqr(A,b,1e-14,maxit,M1,M2);%flag为验证指标,若为0,则是比较成功收敛的
%relres是相对残差 norm(b-Ax)/norm(b),iter为迭代次数,resvec为每次迭代的相对残差
%% minres
A=[5 2 6 0 0 1 0;
   2 5 1 0 0 0 0;
   6 1 0 2 3 1 0;
   0 0 2 3 1 0 0;
   0 0 3 1 2 2 1;
   1 0 1 0 2 0 0;
   0 0 0 0 1 0 0;];%需对称,若不对称相对残差则比较大
b=[1 2 5 6 3 4 0]';
x=minres(A,b)%默认1e-6
x1=minres(A,b,1e-15);%指定相对残差
x2=minres(A,b,1e-15,13);%指定迭代次数
M1=rand(7);%预处理器
M2=rand(7);
M1=tril(M1,-1)+triu(M1',0);%使其对称
M2=tril(M2,-1)+triu(M2',0);
M1=M1'*M1;%使其为正定矩阵,特征值不能小于0
M2=M2'*M2;
x3=minres(A,b,1e-15,maxit,M1);%使用一个,M1*M2可能就不是对称正定矩阵了
x0=[0.1 0.2 0.2 0.3 0.2 0.1 0.3]';
x=minres(A,b,1e-15,maxit,M1,[],x0);%给定一个初值,比较靠近真实值,默认的都是给定0
[x,flag,relres,iter,resvec]=minres(A,b,1e-14,maxit,M1);
%% gmr      用法类似
%% gmres  用法类似

%% 非线性方程组-不动点迭代
[X,tol]=budongdian_system(@mybudongdian,[1 0.1],800)
x=fsolve(@mybudongdian,[1,0.1]);%与上式等价,这里利用fsolve函数求解

function x=mybudongdian(x0)
x1=x0(1);
x2=x0(2);
x(1)=0.5*sin(x1)+0.1*cos(x1*x2)-x1;
x(2)=0.5*cos(x1)-0.1*cos(x2)-x2;

function [X,Tol]=budongdian_system(f,x0,n)
e=1e-6;
x0=x0(:);
i=1;
while 1
    x1=f(x0)'+x0;
    if norm(x0-x1)         X=x1;
        Tol=f(X);
        return;
    end
    x0=x1;
    i=i+1;
    if i>n
        X=x0;
        Tol=f(X);
        return;
    end
end

syms x1 x2
F=[x1^2-2*x1-x2+0.5;x1^2+4*x2^2-4];
[X,tol]=newton_sys(F,[1,1],20)
% t=matlabFuntion(F)
% x=fsolve(@my_newton,[1,1])%不完整需写成文件的形式

function [X,tol]=newton_sys(f,x0,n)
e=1e-6;
F=matlabFunction(f);%函数句柄,仍未实现
F1=jacobi(f,symvar(f))^(-1);
B=symval(F1);
F1=matlabFunction(F1);%雅克比矩阵的句柄

i=1;
h=length(x0);
m=length(B);
FF='F(';
FF1='F1(';
for k=1:h
    FF=[FF,'x0(',num2str(k),')'];
    for j=1:m
        A=char(B(j))
        if A==['x',num2str(k)]
            FF1=[FF1,'x0(',num2str,'),']
        end
    end
end
FF(end)=')';
FF1(end)=')';
while 1
    x1=x0(:)-eval(FF1)*eval(FF);
    if norm(x0-x)         X=x1;
        tol=eval(FF);
        return;
    end
    if i>n
         X=x0;
        tol=eval(FF);
        return;
    end
    i=i+1;
    x0=x1;
end

你可能感兴趣的:(MATLAB)