1. 程式人生 > >線性代數-矩陣-【5】矩陣化簡 C和C++實現

線性代數-矩陣-【5】矩陣化簡 C和C++實現

tar tput c++ spec 但是 exc c++語言 emp opened

點擊這裏可以跳轉至

【1】矩陣匯總:http://www.cnblogs.com/HongYi-Liang/p/7287369.html

【2】矩陣生成:http://www.cnblogs.com/HongYi-Liang/p/7275278.html

【3】矩陣加減:http://www.cnblogs.com/HongYi-Liang/p/7287403.html

【4】矩陣點乘:http://www.cnblogs.com/HongYi-Liang/p/7287324.html

【5】矩陣化簡:現在的位置

(待續)

...


C++語言:

高斯消元法:

繼續使用這個矩陣

技術分享

當我們使用高斯消元(無回代)化簡這個矩陣,是這樣算的:

技術分享

上述過程歸納為:

  1. 找到第一行行的主元(第一行第一個數:1)
  2. 消除第而三行的的第一個數(r2-2*r1;r3-4*r1)
  3. 找到第二行的主元(第二行第二個數:-2)
  4. 消除第三行的第二個數(r3-3/2*r2)

可以發現實際上是1和2兩個步驟的循環,所以寫成循環的形式

  • 從第一行開始到最後一行
  1. 找主元:找出第i的主元(第i行第i個數)
  2. 消元:消除下面所有行的第i個數(下面每一行減去x倍的第一行來消除第i列)

到目前為止,基本達到消元的目的了,但是有一些小小的瑕疵

我們可能碰到一個這樣矩陣,有一行全是0,例如這個:

技術分享

那麽我們在步驟1中搜索到主元為0的話,0的任意倍數都是0,會導致第2步無法進行。所以我們需要添加換行

的操作,計算方法為:

技術分享

所以我們把代碼邏輯修改成這樣:

  • 從第一行開始到最後一行
  1. 找主元:找出第i的主元(第i行第i個數),若主元為0,把第i行向下換行,直到找到有主元的行。若找不到主元,就開始找下一個
  2. 消元:消除下面所有行的第i個數(下面每一行減去x倍的第一行來消除第i列)

下面就是高斯消元的主程序:

template <typename T>
bool Matrix<T>::GaussianElimination()
{
    Matrix<T> outputMatrix = *this;

    /*Gaussian elmiation*/
    for
(int k=0;k<outputMatrix.m_iRows;k++) { /*if all the pivot have been found*/ if(k>=m_iColumns) { break; } /*exchange rows downward to find the row‘s pivot*/ for(int i=k+1;i<outputMatrix.m_iRows;i++) { /*pivot is non-zero*/ if(outputMatrix.m_vecMatrix[k][k] != 0) { //T temp = outputMatrix.m_vecMatrix[0][0]; break; } else { if(i < outputMatrix.m_iRows) { outputMatrix.exchangeRows(k,i); } } } /*if there is no pivot in this row*/ if(outputMatrix.m_vecMatrix[k][k] == 0) { break; } /*elimination:The rows below pivot row subtract times of pivot row*/ for(int i=k+1;i<outputMatrix.m_iRows;i++) { double RowsfirstData = outputMatrix.m_vecMatrix[i][k]/outputMatrix.m_vecMatrix[k][k];//Save the first data of next(k+1) rows if(RowsfirstData != 0) { outputMatrix.m_vecMatrix[i][k]=0; for(int j=k+1;j<outputMatrix.m_iColumns;j++) { outputMatrix.m_vecMatrix[i][j] -= RowsfirstData*outputMatrix.m_vecMatrix[k][j] ; } } } } *this = outputMatrix; return true; }

高斯-若爾當法

若爾當在高斯消元的基礎上加上了回代過程,把矩陣化簡成行最簡式。我們在高斯消元的基礎上加上和回代,方法跟高斯消元相反,用上面的行減下面的行,這裏就不詳細描述(展開查看代碼)

rref()//化簡矩陣成行最簡

技術分享
template <typename T>
bool Matrix<T>::rref()
{
    Matrix<T> outputMatrix = *this;
    int rank=0;//the rank of the matrix, how many columns‘s pivot will it has(-1)

    /*Gaussian elmiation*/
    for(int k=0;k<outputMatrix.m_iRows;k++)
    {
        /*if all the pivot elem have been found*/
        if(k>=m_iColumns)
        {
            break;
        }

        /*exchange rows downward to find the pivot row*/
        for(int i=k+1;i<outputMatrix.m_iRows;i++)
        {
            /*pivot is non-zero*/
            if(outputMatrix.m_vecMatrix[k][k] != 0)
            {
                //T temp = outputMatrix.m_vecMatrix[0][0];
                rank++;
                break;
            }
            else
            {            
                if(i < outputMatrix.m_iRows)
                {
                    outputMatrix.exchangeRows(k,i);
                }
            }
        }

        /*if there is no pivot in this row*/
        if(outputMatrix.m_vecMatrix[k][k] == 0)
        {
            break;
        }

        /*elimination:The rows below pivot row subtract times of pivot row*/
        for(int i=k+1;i<outputMatrix.m_iRows;i++)
        {
            double RowsfirstData = outputMatrix.m_vecMatrix[i][k]/outputMatrix.m_vecMatrix[k][k];//Save the first data of next(k+1) rows 
            if(RowsfirstData != 0) 
            {
                outputMatrix.m_vecMatrix[i][k]=0;
                for(int j=k+1;j<outputMatrix.m_iColumns;j++)
                {
                    outputMatrix.m_vecMatrix[i][j] -= RowsfirstData*outputMatrix.m_vecMatrix[k][j] ;
                }
            }
        }
    }

    /*normalizing:set all pivots to 1*/
    for(int i=0;i<outputMatrix.m_iRows;i++)
    {
        for(int j=0;j<outputMatrix.m_iColumns;j++)
        {
            if(outputMatrix.m_vecMatrix[i][j] !=0 )//pivot has been foound
            {
                double pivot = outputMatrix.m_vecMatrix[i][j];//get pivot
                for(int k=i;k<outputMatrix.m_iColumns;k++)
                {
                    outputMatrix.m_vecMatrix[i][k] /=pivot;
                }
                break;
            }
        }
    }

    /*Back substitution*/
    for(int i = rank;i>=1;i--)
    {
        /*find a first non-zero elem (It is pivot)*/
        for(int j=0;j<outputMatrix.m_iColumns;j++)
        {
            double times=0;
            if(outputMatrix.m_vecMatrix[i][j] !=0)//pivot found
            {
                for(int l=i-1;l>=0;l--)
                {
                    times = outputMatrix.m_vecMatrix[l][j]/outputMatrix.m_vecMatrix[i][j]; 
                    for(int k=j;k<outputMatrix.m_iColumns;k++)//tims of this row subtract by each columns in upon row 
                    {
                        outputMatrix.m_vecMatrix[l][k] -= times*outputMatrix.m_vecMatrix[i][k];
                    }
                }
                break;
            }
        }
    }

    *this = outputMatrix;
    return true;
}
View Code

rrefmovie()//化簡矩陣成行最簡,並打印過程

技術分享
template <typename T>
bool Matrix<T>::rrefmovie()
{
    Matrix<T> outputMatrix = *this;
    int rank=0;//the rank of the matrix, how many columns‘s pivot will it has(-1)

    /*Gauss elmiation*/
    cout<<"Gauss elimination:"<<endl;
    outputMatrix.printfAll();
    for(int k=0;k<outputMatrix.m_iRows;k++)
    {
        /*If all the pivot elem have been found*/
        if(k>=m_iColumns)
        {
            break;
        }

        /*Exchange rows downward to find the pivot row*/
        for(int i=k+1;i<outputMatrix.m_iRows;i++)
        {
            /*Pivot is non-zero*/
            if(outputMatrix.m_vecMatrix[k][k] != 0)
            {
                rank++;
                break;
            }
            else
            {            
                if(i < outputMatrix.m_iRows)
                {
                    outputMatrix.exchangeRows(k,i);
                }
            }
            if(k!=i)
            {
                cout<<"row"<<k+1<<" exchange row"<<i+1<<endl;//Debug
                outputMatrix.printfAll();
            }
        }

        /*If there is no pivot in this row*/
        if(outputMatrix.m_vecMatrix[k][k] == 0)
        {
            break;
        }

        /*Elimination:The rows below pivot row subtract times of pivot row*/
        for(int i=k+1;i<outputMatrix.m_iRows;i++)
        {
            double RowsfirstData = outputMatrix.m_vecMatrix[i][k]/outputMatrix.m_vecMatrix[k][k];//Save the first data of next(k+1) rows 
            if(RowsfirstData != 0) 
            {
                outputMatrix.m_vecMatrix[i][k]=0;
                for(int j=k+1;j<outputMatrix.m_iColumns;j++)
                {
                    outputMatrix.m_vecMatrix[i][j] -= RowsfirstData*outputMatrix.m_vecMatrix[k][j] ;
                }
            }
            cout<<"row"<<i+1<<" - "<<RowsfirstData<<"*"<<"row"<<k+1<<endl;//Debug
            outputMatrix.printfAll();
        }
    }

    /*Normalizing:set all rows pivot to 1*/
    for(int i=0;i<outputMatrix.m_iRows;i++)
    {
        for(int j=0;j<outputMatrix.m_iColumns;j++)
        {
            if(outputMatrix.m_vecMatrix[i][j] !=0 )//pivot has been foound
            {
                double pivot = outputMatrix.m_vecMatrix[i][j];//get pivot
                for(int k=i;k<outputMatrix.m_iColumns;k++)
                {
                    outputMatrix.m_vecMatrix[i][k] /=pivot;
                }
                cout<<"row"<<i+1<<" / "<<pivot<<endl;//Debug
                outputMatrix.printfAll();//Debug
                break;
            }
        }
    }


    /*Back substitution*/
    cout<<"Back substitution:"<<endl;
    for(int i = rank;i>=1;i--)
    {
        /*find a first non-zero elem (It is pivot)*/
        for(int j=0;j<outputMatrix.m_iColumns;j++)
        {
            double times=0;
            if(outputMatrix.m_vecMatrix[i][j] !=0)//pivot found
            {
                for(int l=i-1;l>=0;l--)
                {
                    times = outputMatrix.m_vecMatrix[l][j]/outputMatrix.m_vecMatrix[i][j]; 
                    for(int k=j;k<outputMatrix.m_iColumns;k++)//tims of this row subtract by each columns in upon row 
                    {
                        outputMatrix.m_vecMatrix[l][k] -= times*outputMatrix.m_vecMatrix[i][k];
                    }
                    cout<<"row"<<l+1<<" - "<<times<<"*"<<"row"<<i+1<<endl;
                    outputMatrix.printfAll();
                }
                break;
            }
        }
    }

    *this = outputMatrix;
    return true;
}
View Code

使用我們開始的矩陣測試:

技術分享

    Matrix<double> matrix(3,3);
    matrix.setSpecifiedElem(0,0,1);
    matrix.setSpecifiedElem(0,1,2);
    matrix.setSpecifiedElem(0,2,3);
    matrix.setSpecifiedElem(1,0,2);
    matrix.setSpecifiedElem(1,1,2);
    matrix.setSpecifiedElem(1,2,2);
    matrix.setSpecifiedElem(2,0,4);
    matrix.setSpecifiedElem(2,1,5);
    matrix.setSpecifiedElem(2,2,6);
    matrix.printfAll();

    matrix.rrefmovie();
    matrix.printfAll();
    system("pause");

結果:

技術分享

線性代數-矩陣-【5】矩陣化簡 C和C++實現