Learn-to-Compress / headers / matrix_inverse.h
matrix_inverse.h
Raw
#ifndef MATRIX_IN_sizeVERSE
#define MATRIX_IN_sizeVERSE
#include "common.h"

#define N_size 3
double** mat_T(int m,int n, double **a){
    double **result=new double*[m];
        for(int i=0;i<m;i++){
            result[i]= new double[n];
        }
    
    for(int i=0;i<m;i++){//m is the column number of a
        for(int j=0;j<n;j++){
            result[i][j]=a[j][i];
        }
    }
    return result;
}
double** multi(int m, int n,int q, double **a, double **b )
{
        double **result=new double*[m];
        for(int i=0;i<m;i++){
            result[i]= new double[q];
            
        }
    
        for (int i = 0; i < m; i++)  
        {
            for (int j = 0; j < q; j++)      
            {
                for (int k = 0; k < n; k++)  
                {

                    result[i][j] += a[i][k] * b[k][j];
                    
                }
            }
        }
    return result;
}








//LUP分解
void LUP_Descomposition(double A[N_size*N_size],double L[N_size*N_size],double U[N_size*N_size],int P[N_size])
{
    int row=0;
    for(int i=0;i<N_size;i++)
    {
        P[i]=i;
    }
    for(int i=0;i<N_size-1;i++)
    {
        double p=0.0;
        for(int j=i;j<N_size;j++)
        {
            if(abs(A[j*N_size+i])>p)
            {
                p=abs(A[j*N_size+i]);
                row=j;
            }
        }
        if(0==p)
        {
            std::cout<< "矩阵奇异,无法计算逆" <<std::endl;
            return ;
        }

        //交换P[i]和P[row]
        int tmp=P[i];
        P[i]=P[row];
        P[row]=tmp;

        double tmp2=0.0;
        for(int j=0;j<N_size;j++)
        {
            //交换A[i][j]和 A[row][j]
            tmp2=A[i*N_size+j];
            A[i*N_size+j]=A[row*N_size+j];
            A[row*N_size+j]=tmp2;
        }

        //以下同LU分解
        double u=A[i*N_size+i],l=0.0;
        for(int j=i+1;j<N_size;j++)
        {
            l=A[j*N_size+i]/u;
            A[j*N_size+i]=l;
            for(int k=i+1;k<N_size;k++)
            {
                A[j*N_size+k]=A[j*N_size+k]-A[i*N_size+k]*l;
            }
        }

    }

    //构造L和U
    for(int i=0;i<N_size;i++)
    {
        for(int j=0;j<=i;j++)
        {
            if(i!=j)
            {
                L[i*N_size+j]=A[i*N_size+j];
            }
            else
            {
                L[i*N_size+j]=1;
            }
        }
        for(int k=i;k<N_size;k++)
        {
            U[i*N_size+k]=A[i*N_size+k];
        }
    }

}

//LUP求解方程
double * LUP_Solve(double L[N_size*N_size],double U[N_size*N_size],int P[N_size],double b[N_size])
{
    double *x=new double[N_size]();
    double *y=new double[N_size]();

    //正向替换
    for(int i = 0;i < N_size;i++)
    {
        y[i] = b[P[i]];
        for(int j = 0;j < i;j++)
        {
            y[i] = y[i] - L[i*N_size+j]*y[j];
        }
    }
    //反向替换
    for(int i = N_size-1;i >= 0; i--)
    {
        x[i]=y[i];
        for(int j = N_size-1;j > i;j--)
        {
            x[i] = x[i] - U[i*N_size+j]*x[j];
        }
        x[i] /= U[i*N_size+i];
    }
    return x;
}

/*****************矩阵原地转置BEGIN_size********************/

int getN_sizeext(int i, int m, int n)
{
  return (i%n)*m + i/n;
}


int getPre(int i, int m, int n)
{
  return (i%m)*n + i/m;
}

/* 处理以下标i为起点的环 */
void movedata(double *mtx, int i, int m, int n)
{
  double temp = mtx[i]; // 暂存
  int cur = i;    // 当前下标
  int pre = getPre(cur, m, n);
  while(pre != i)
  {
    mtx[cur] = mtx[pre];
    cur = pre;
    pre = getPre(cur, m, n);
  }
  mtx[cur] = temp;
}

/* 转置,即循环处理所有环 */
void transpose(double *mtx, int m, int n)
{
  for(int i=0; i<m*n; ++i)
  {
    int next = getN_sizeext(i, m, n);
    while(next > i) 
      next = getN_sizeext(next, m, n);
    if(next == i)  
      movedata(mtx, i, m, n);
  }
}
/*****************矩阵原地转置EN_sizeD********************/

//LUP求逆(将每列b求出的各列x进行组装)
double * LUP_solve_inverse(double A[N_size*N_size])
{
    //创建矩阵A的副本,注意不能直接用A计算,因为LUP分解算法已将其改变
    double *A_mirror = new double[N_size*N_size]();
    double *inv_A=new double[N_size*N_size]();//最终的逆矩阵(还需要转置)
    double *inv_A_each=new double[N_size]();//矩阵逆的各列
    //double *B    =new double[N_size*N_size]();
    double *b    =new double[N_size]();//b阵为B阵的列矩阵分量

    for(int i=0;i<N_size;i++)
    {
        double *L=new double[N_size*N_size]();
        double *U=new double[N_size*N_size]();
        int *P=new int[N_size]();

        //构造单位阵的每一列
        for(int i=0;i<N_size;i++)
        {
            b[i]=0;
        }
        b[i]=1;

        //每次都需要重新将A复制一份
        for(int i=0;i<N_size*N_size;i++)
        {
            A_mirror[i]=A[i];
        }

        LUP_Descomposition(A_mirror,L,U,P);

        inv_A_each=LUP_Solve (L,U,P,b);
        memcpy(inv_A+i*N_size,inv_A_each,N_size*sizeof(double));//将各列拼接起来
    }
    transpose(inv_A,N_size,N_size);//由于现在根据每列b算出的x按行存储,因此需转置

    return inv_A;
}





#endif