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); }
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); }