Esempio n. 1
0
        private LUDecompositionResults LUDecompose()
        {
            Debug.Assert(m_nNumColumns == m_nNumRows);

            // Using Crout Decomp with P

            //

            //  Ax = b   //By definition of problem variables.

            //

            //  LU = PA   //By definition of L, U, and P.

            //

            //  LUx = Pb  //By substition for PA.

            //

            //  Ux = d   //By definition of d

            //

            //  Ld = Pb   //By subsitition for d.

            //



            //For 4x4 with P = I



            //  [l11 0   0   0  ]  [1 u12 u13 u14]   [a11 a12 a13 a14]

            //  [l21 l22 0   0  ]  [0 1   u23 u24] = [a21 a22 a23 a24]

            //  [l31 l32 l33 0  ]  [0 0   1   u34]   [a31 a32 a33 a34]

            //  [l41 l42 l43 l44]  [0 0   0   1  ]   [a41 a42 a43 a44]



            LUDecompositionResults resRet = new LUDecompositionResults();

            int[] nP = new int[m_nNumRows]; //Pivot matrix.

            MatrixNumeric mU = new MatrixNumeric(m_nNumRows, m_nNumColumns);

            MatrixNumeric mL = new MatrixNumeric(m_nNumRows, m_nNumColumns);

            MatrixNumeric mUWorking = Clone();

            MatrixNumeric mLWorking = new MatrixNumeric(m_nNumRows, m_nNumColumns);

            for (int i = 0; i < m_nNumRows; i++)
            {
                nP[i] = i;
            }



            //Iterate down the number of rows in the U matrix.

            for (int i = 0; i < m_nNumRows; i++)
            {
                //Do pivots first.

                //I want to make the matrix diagnolaly dominate.



                //Initialize the variables used to determine the pivot row.

                double dMaxRowRatio = double.NegativeInfinity;

                int nMaxRow = -1;

                int nMaxPosition = -1;

                //Check all of the rows below and including the current row

                //to determine which row should be pivoted to the working row position.

                //The pivot row will be set to the row with the maximum ratio

                //of the absolute value of the first column element divided by the

                //sum of the absolute values of the elements in that row.



                for (int j = i; j < m_nNumRows; j++)
                {
                    //Store the sum of the absolute values of the row elements in

                    //dRowSum.  Clear it out now because I am checking a new row.

                    double dRowSum = 0.0;

                    //Go across the columns, add the absolute values of the elements in

                    //that column to dRowSum.

                    for (int k = i; k < m_nNumColumns; k++)
                    {
                        dRowSum += Math.Abs(mUWorking[nP[j], k]);
                    }



                    //Check to see if the absolute value of the ratio of the lead

                    //element over the sum of the absolute values of the elements is larger

                    //that the ratio for preceding rows.  If it is, then the current row

                    //becomes the new pivot candidate.

                    if (Math.Abs(mUWorking[nP[j], i] / dRowSum) > dMaxRowRatio)
                    {
                        dMaxRowRatio = Math.Abs(mUWorking[nP[j], i] / dRowSum);

                        nMaxRow = nP[j];

                        nMaxPosition = j;
                    }
                }



                //If the pivot candidate isn't the current row, update the

                //pivot array to swap the current row with the pivot row.

                if (nMaxRow != nP[i])
                {
                    int nHold = nP[i];

                    nP[i] = nMaxRow;

                    nP[nMaxPosition] = nHold;
                }



                //Store the value of the left most element in the working U

                //matrix in dRowFirstElementValue.

                double dRowFirstElementValue = mUWorking[nP[i], i];

                //Update the columns of the working row.  j is the column index.

                for (int j = 0; j < m_nNumRows; j++)
                {
                    if (j < i)
                    {
                        //If j<1, then the U matrix element value is 0.

                        mUWorking[nP[i], j] = 0.0;
                    }
                    else if (j == i)
                    {
                        //If i == j, the L matrix value is the value of the

                        //element in the working U matrix.

                        mLWorking[nP[i], j] = dRowFirstElementValue;

                        //The value of the U matrix for i == j is 1

                        mUWorking[nP[i], j] = 1.0;
                    }
                    else // j>i

                    {
                        //Divide each element in the current row of the U matrix by the

                        //value of the first element in the row

                        mUWorking[nP[i], j] /= dRowFirstElementValue;

                        //The element value of the L matrix for j>i is 0

                        mLWorking[nP[i], j] = 0.0;
                    }
                }



                //For the working U matrix, subtract the ratioed active row from the rows below it.

                //Update the columns of the rows below the working row.  k is the row index.

                for (int k = i + 1; k < m_nNumRows; k++)
                {
                    //Store the value of the first element in the working row

                    //of the U matrix.

                    dRowFirstElementValue = mUWorking[nP[k], i];

                    //Go accross the columns of row k.

                    for (int j = 0; j < m_nNumRows; j++)
                    {
                        if (j < i)
                        {
                            //If j<1, then the U matrix element value is 0.

                            mUWorking[nP[k], j] = 0.0;
                        }
                        else if (j == i)
                        {
                            //If i == j, the L matrix value is the value of the

                            //element in the working U matrix.

                            mLWorking[nP[k], j] = dRowFirstElementValue;

                            //The element value of the L matrix for j>i is 0

                            mUWorking[nP[k], j] = 0.0;
                        }
                        else //j>i

                        {
                            mUWorking[nP[k], j] = mUWorking[nP[k], j] - dRowFirstElementValue * mUWorking[nP[i], j];
                        }
                    }
                }
            }



            for (int i = 0; i < m_nNumRows; i++)
            {
                for (int j = 0; j < m_nNumRows; j++)
                {
                    mU[i, j] = mUWorking[nP[i], j];

                    mL[i, j] = mLWorking[nP[i], j];
                }
            }



            resRet.U = mU;

            resRet.L = mL;

            resRet.PivotArray = nP;



            return(resRet);
        }
Esempio n. 2
0
        public MatrixNumeric SolveFor(MatrixNumeric mRight)
        {
            Debug.Assert(mRight.NumRows == m_nNumColumns);

            Debug.Assert(m_nNumColumns == m_nNumRows);

            MatrixNumeric mRet = new MatrixNumeric(m_nNumColumns, mRight.NumColumns);



            LUDecompositionResults resDecomp = LUDecompose();

            int[] nP = resDecomp.PivotArray;

            MatrixNumeric mL = resDecomp.L;

            MatrixNumeric mU = resDecomp.U;



            double dSum = 0.0;



            for (int k = 0; k < mRight.NumColumns; k++)
            {
                //Solve for the corresponding d Matrix from Ld=Pb

                MatrixNumeric D = new MatrixNumeric(m_nNumRows, 1);

                D[0, 0] = mRight[nP[0], k] / mL[0, 0];

                for (int i = 1; i < m_nNumRows; i++)
                {
                    dSum = 0.0;

                    for (int j = 0; j < i; j++)
                    {
                        dSum += mL[i, j] * D[j, 0];
                    }

                    D[i, 0] = (mRight[nP[i], k] - dSum) / mL[i, i];
                }



                //Solve for x using Ux = d

                //DMatrix X = new DMatrix(m_nNumRows, 1);

                mRet[m_nNumRows - 1, k] = D[m_nNumRows - 1, 0];

                for (int i = m_nNumRows - 2; i >= 0; i--)
                {
                    dSum = 0.0;

                    for (int j = i + 1; j < m_nNumRows; j++)
                    {
                        dSum += mU[i, j] * mRet[j, k];
                    }

                    mRet[i, k] = D[i, 0] - dSum;
                }
            }



            return(mRet);
        }