求逆矩阵的方法

一般求逆矩阵的方法有两种,伴随阵法和初等变换法。但是这两种方法都不太适合编程。伴随阵法的计算量大,初等变换法又难以编程实现。
适合编程的求逆矩阵的方法如下:
1、对可逆矩阵A进行QR分解:A=QR
2、求上三角矩阵R的逆矩阵
3、求出A的逆矩阵:A^(-1)=R^(-1)Q^(H)
以上三步都有具体的公式与之对应,适合编程实现。
C语言实现代码:

#include <stdio.h>
#include <math.h>

#define SIZE  8

double b[SIZE][SIZE]={0};//应该读作“贝尔塔”,注释中用B表示
double t[SIZE][SIZE]={0};//求和的那项
double Q[SIZE][SIZE]={0};//正交矩阵
double QH[SIZE][SIZE]={0};//正交矩阵的转置共轭
double R[SIZE][SIZE]={0};//
double invR[SIZE][SIZE]={0};//R的逆矩阵
double invA[SIZE][SIZE]={0};//A的逆矩阵,最终的结果
//={0};//
double matrixR1[SIZE][SIZE]={0};
double matrixR2[SIZE][SIZE]={0};

//double init[3][3]={3,14,9,6,43,3,6,22,15};
double init[8][8]={  
    0.0938  ,  0.5201 ,   0.4424  ,  0.0196  ,  0.3912  ,  0.9493 ,   0.9899  ,  0.8256,
    0.5254  ,  0.3477 ,   0.6878  ,  0.3309 ,   0.7691  ,  0.3276 ,   0.5144  ,  0.7900,
    0.5303  ,  0.1500 ,   0.3592  ,  0.4243 ,   0.3968  ,  0.6713 ,   0.8843  ,  0.3185,
    0.8611  ,  0.5861 ,   0.7363  ,  0.2703 ,   0.8085  ,  0.4386 ,   0.5880  ,  0.5341,
    0.4849  ,  0.2621 ,   0.3947  ,  0.1971 ,   0.7551  ,  0.8335 ,   0.1548  ,  0.0900,
    0.3935  ,  0.0445 ,   0.6834  ,  0.8217 ,   0.3774  ,  0.7689 ,   0.1999  ,  0.1117,
    0.6714  ,  0.7549 ,   0.7040  ,  0.4299 ,   0.2160  ,  0.1673 ,   0.4070  ,  0.1363,
    0.7413  ,  0.2428 ,   0.4423  ,  0.8878 ,   0.7904  ,  0.8620 ,   0.7487  ,  0.6787
};
/*/////////////////////////////////////////////////////////////////////
函数名:int main()
输入:
输出:
功能:求矩阵的逆 pure C language
     首先对矩阵进行QR分解之后求上三角矩阵R的逆阵最后A-1=QH*R-1,得到A的逆阵。
作者:HLdongdong
*//////////////////////////////////////////////////////////////////////
int main()
{
    int i;//数组  行
    int j;//数组  列
    int k;//代表B的角标
    int l;//数组  列
    double dev;
    double numb;//计算的中间变量
    double numerator,denominator;
    double ratio;
    /////////////////求B/////////////////
    for(i=0;i<SIZE;++i)
    {
        for(j=0;j<SIZE;++j)
        {
            b[j][i]=init[j][i];
        }
        for(k=0;k<i;++k)
        {
            if(i)
            {
                numerator=0.0;
                denominator=0.0;
                for(l=0;l<SIZE;++l)
                {
                    numerator+=init[l][i]*b[l][k];
                    denominator+=b[l][k]*b[l][k];
                }
                dev=numerator/denominator;
                t[k][i]=dev;
                for(j=0;j<SIZE;++j)
                {
                    b[j][i]-=t[k][i]*b[j][k];//t  init  =0  !!!
                }
            }
        }
    }
    ///////////////////对B单位化,得到正交矩阵Q矩阵////////////////////
    for(i=0;i<SIZE;++i)
    {
        numb=0.0;
        for(j=0;j<SIZE;++j)
        {
            numb+=(b[j][i]*b[j][i]);
        }
        dev=sqrt(numb);
        for(j=0;j<SIZE;++j)
        {
            Q[j][i]=b[j][i]/dev;
        }
        matrixR1[i][i]=dev;
    }
    /////////////////////求上三角R阵///////////////////////
    for(i=0;i<SIZE;++i)
    {
        for(j=0;j<SIZE;++j)
        {
            if(j<i)
            {
                matrixR2[j][i]=t[j][i];
            }
            else if(j==i)   
            {
                matrixR2[j][i]=1;
            }
            else
            {
                matrixR2[j][i]=0;
            }
        }
    }
    mulMatrix(matrixR1,matrixR2,SIZE,SIZE,SIZE,R);
///////////////////////QR分解完毕//////////////////////////
    printf("QR分解:\n");
    printf("Q=\n");
    for(i=0;i<SIZE;++i)
    {
        for(j=0;j<SIZE;++j)
        {
            printf("%2.4f    ",Q[i][j]);
        //  
        }
        printf("\n");
    }
    printf("R=\n");
    for(i=0;i<SIZE;++i)
    {
        for(j=0;j<SIZE;++j)
        {
            printf("%2.4f    ",R[i][j]);
        //  
        }
        printf("\n");
    }
/////////////////////求R的逆阵//////////////////////////
    for(i=SIZE-1;i>=0;--i)
    {
        invR[i][i]=1/R[i][i];
        //R[i][i]=invR[i][i];
        if(i!=(SIZE-1))//向右
        {
            for(j=i+1;j<SIZE;++j)
            {
                invR[i][j]=invR[i][j]*invR[i][i];
                R[i][j]=R[i][j]*invR[i][i];
            }
        }
        if(i)//向上
        {
            for(j=i-1;j>=0;--j)
            {
                ratio=R[j][i];
                for(k=i;k<SIZE;++k)
                {
                    invR[j][k]-=ratio*invR[i][k];
                    R[j][k]-=ratio*R[i][k];
                }
            }   
        }
    }

///////////////////////////////////////////////////////

    printf("inv(R)=\n");
    for(i=0;i<SIZE;++i)
    {
        for(j=0;j<SIZE;++j)
        {
            printf(" %2.4f  ",invR[i][j]);
        //  
        }
        printf("\n");
    }
////////////////////结果和MATLAB差一个负号,神马鬼????????/////////////////////
/////////////////////求QH//////////////////////////
    for(i=0;i<SIZE;++i)//实矩阵就是转置
    {
        for(j=0;j<SIZE;++j)
        {
            QH[i][j]=Q[j][i];
        }
    }
///////////////////////求A的逆阵invA/////////////////////////////

    mulMatrix(invR,QH,SIZE,SIZE,SIZE,invA);

    printf("inv(A)=\n");
    for(i=0;i<SIZE;++i)
    {
        for(j=0;j<SIZE;++j)
        {
            printf(" %2.4f  ",invA[i][j]);
        //  
        }
        printf("\n");
    }

///////////////////////结果与MATLAB的结果在千分位后有出入,但是负号都是对的^v^///////////////////////////
    return 0;
}

另附上矩阵乘法的子函数

/*/////////////////////////////////////////////////////////////////////
函数名:void mulMatrix(double matrix1[SIZE][SIZE],double matrix2[SIZE][SIZE],int high1,int weight,int weight2,double mulMatrixOut[SIZE][SIZE])
输入:依次是 左矩阵,右矩阵,左矩阵高度,左矩阵宽度,右矩阵宽度,输出矩阵
输出:
功能:矩阵乘法
作者:HLdongdong
*//////////////////////////////////////////////////////////////////////
void mulMatrix(double matrix1[SIZE][SIZE],double matrix2[SIZE][SIZE],int high1,int weight,int weight2,double mulMatrixOut[SIZE][SIZE])
{
    int i,j,k;
    for(i=0;i<high1;++i)
    {
        for(j=0;j<weight2;j++)
        {
            for(k=0;k<weight;++k)
            {
                mulMatrixOut[i][j]+=matrix1[i][k]*matrix2[k][j];
            }
        }
    }
}
### PyTorch 中计算逆矩阵方法 在 PyTorch 中,可以通过函数 `torch.inverse` 或者 `torch.linalg.inv` 来完成对一个可方阵的操作。这些方法适用于那些非奇异(即满秩)的方阵。如果输入的是奇异矩阵,则会抛出异常或返回不合理的数值。 #### 函数介绍 - **`torch.inverse(input, out=None)`** - 功能描述:此功能接受一个二维张量作为参数,并返回该张量的逆矩阵- 参数详情: - `input`: 待的方阵型张量。 - `out`(可选): 输出结果存储的位置。 - 返回值:与输入具有相同类型的张量表示原矩阵[^1]。 - **`torch.linalg.inv(A, *, out=None)`** (推荐) - 新版 API 提供了更为统一和现代化的设计风格,在未来版本中可能会逐渐取代旧有的 `inverse` 方法- 它同样支持批量处理多个独立的小规模矩阵的情况。 - 注意事项:对于不可逆矩阵,它也会引发相应的错误提示[^2]。 #### 示例代码 下面是利用这两种方式分别实现逆矩阵计算的例子: ```python import torch # 创建一个3x3随机正定矩阵K K = torch.tensor([[4., 9., 2.], [8., 7., 6.], [3., 5., 0.]]) det_K = torch.det(K) # 检查行列式是否为零来判断能否成功逆矩阵 if det_K != 0: inv_K_v1 = torch.inverse(K) # 使用传统 inverse 方法获取逆矩阵 inv_K_v2 = torch.linalg.inv(K) # 推荐的新 linalg 模块下的 inv 方法 print("Inverse via torch.inverse:\n", inv_K_v1) print("\nInverse via torch.linalg.inv:\n", inv_K_v2) else: raise ValueError('Matrix is singular and cannot be inverted.') ``` 上述例子先构建了一个具体的三阶实数方阵 K 并检测其行列式的值。只有当行列式非零时才继续执行后续步骤去实际获得逆矩阵;否则立即终止程序并给出适当警告信息。 #### 关键点提醒 需要注意的是,无论是哪种途径都要传入的数据结构必须是一个有效的、非退化的方形数组才行。而且考虑到浮点精度误差的影响,在某些极端情况下即使理论上应该是可的也可能因为舍入等问题而被认为不可--- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值