public void Matrix_GetRowStandardTest() { Matrix testMatrix = new Matrix(2, 3); double[] rowTwoOfTestMatrix = { 7, 8, 9 }; testMatrix.SetRow(1, rowTwoOfTestMatrix); testMatrix.GetRow(1).ShouldBeEquivalentTo(rowTwoOfTestMatrix); }
public void Matrix_DecomposeTest3_DifferentSigns() { Matrix matrixA = new Matrix(9,9); //Set up matrix A double[] row1OfMatrixA = { 3, 0, 0, -7, 0, 0, 0, 0, 0 }; double[] row2OfMatrixA = { 0, 1, 8, 0, -4, 2, 0, 0, 0 }; double[] row3OfMatrixA = { 0, 2, 8, 0, -9, 3, 0, 0, 0 }; double[] row4OfMatrixA = { -5, 0, 0, 4, 0, 7, -1, 0, 3 }; double[] row5OfMatrixA = { 0, -3, -7, 0, 7, -8, 0, -3, 0 }; double[] row6OfMatrixA = { 0, 7, 2, 5, -3, 7, -2, 0, 4 }; double[] row7OfMatrixA = { 0, 0, 0, -2, 0, -8, 4, 0, 7 }; double[] row8OfMatrixA = { 0, 0, 0, 0, -9, 0, 0, 3, 0 }; double[] row9OfMatrixA = { 0, 0, 0, 1, 0, 4, 7, 0, 6 }; matrixA.SetRow(0, row1OfMatrixA); matrixA.SetRow(1, row2OfMatrixA); matrixA.SetRow(2, row3OfMatrixA); matrixA.SetRow(3, row4OfMatrixA); matrixA.SetRow(4, row5OfMatrixA); matrixA.SetRow(5, row6OfMatrixA); matrixA.SetRow(6, row7OfMatrixA); matrixA.SetRow(7, row8OfMatrixA); matrixA.SetRow(8, row9OfMatrixA); //The LUP Decomposition //Correct L Part Matrix correctLPartOfLUPDecomposition = new Matrix(9,9); double[] row1OfLMatrix = { 1, 0, 0, 0, 0, 0, 0, 0, 0 }; double[] row2OfLMatrix = { 0, 1, 0, 0, 0, 0, 0, 0, 0 }; double[] row3OfLMatrix = { 0, .143, 1, 0, 0, 0, 0, 0, 0 }; double[] row4OfLMatrix = { -.6, 0, 0, 1, 0, 0, 0, 0, 0 }; double[] row5OfLMatrix = { 0, 0, 0, 0, 1, 0, 0, 0, 0 }; double[] row6OfLMatrix = { 0, 0, 0, .435, 0, 1, 0, 0, 0 }; double[] row7OfLMatrix = { 0, 0, 0, -.217, 0, -.5, 1, 0, 0 }; double[] row8OfLMatrix = { 0, -.429, -.796, -.342, -.319, .282, -.226, 1, 0 }; double[] row9OfLMatrix = { 0.000, 0.286, 0.963, 0.161, 0.523, 0.065, 0.013, 0.767, 1.000 }; correctLPartOfLUPDecomposition.SetRow(0, row1OfLMatrix); correctLPartOfLUPDecomposition.SetRow(1, row2OfLMatrix); correctLPartOfLUPDecomposition.SetRow(2, row3OfLMatrix); correctLPartOfLUPDecomposition.SetRow(3, row4OfLMatrix); correctLPartOfLUPDecomposition.SetRow(4, row5OfLMatrix); correctLPartOfLUPDecomposition.SetRow(5, row6OfLMatrix); correctLPartOfLUPDecomposition.SetRow(6, row7OfLMatrix); correctLPartOfLUPDecomposition.SetRow(7, row8OfLMatrix); correctLPartOfLUPDecomposition.SetRow(8, row9OfLMatrix); //Correct U Part Matrix correctUPartOfLUPDecomposition = new Matrix(9,9); double[] row1OfUMatrix = { -5.000, 0.000, 0.000, 4.000, 0.000, 7.000, -1.000, 0.000, 3.000 }; double[] row2OfUMatrix = { 0.000, 7.000, 2.000, 5.000, -3.000, 7.000, -2.000, 0.000, 4.000 }; double[] row3OfUMatrix = { 0.000, 0.000, 7.714, -0.714, -3.571, 1.000, 0.286, 0.000, -0.571 }; double[] row4OfUMatrix = { 0.000, 0.000, 0.000, -4.600, 0.000, 4.200, -0.600, 0.000, 1.800 }; double[] row5OfUMatrix = { 0.000, 0.000, 0.000, 0.000, -9.000, 0.000, 0.000, 3.000, 0.000 }; double[] row6OfUMatrix = { 0.000, 0.000, 0.000, 0.000, 0.000, -9.826, 4.261, 0.000, 6.217 }; double[] row7OfUMatrix = { 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 9.000, 0.000, 9.500 }; double[] row8OfUMatrix = { 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, -2.043, 2.272 }; double[] row9OfUMatrix = { 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, -3.153 }; correctUPartOfLUPDecomposition.SetRow(0, row1OfUMatrix); correctUPartOfLUPDecomposition.SetRow(1, row2OfUMatrix); correctUPartOfLUPDecomposition.SetRow(2, row3OfUMatrix); correctUPartOfLUPDecomposition.SetRow(3, row4OfUMatrix); correctUPartOfLUPDecomposition.SetRow(4, row5OfUMatrix); correctUPartOfLUPDecomposition.SetRow(5, row6OfUMatrix); correctUPartOfLUPDecomposition.SetRow(6, row7OfUMatrix); correctUPartOfLUPDecomposition.SetRow(7, row8OfUMatrix); correctUPartOfLUPDecomposition.SetRow(8, row9OfUMatrix); //Calculate values for the above int[] permutationArray; int toggleValue; Matrix decomposeResult = matrixA.Decompose(out permutationArray, out toggleValue); Matrix calculatedLPartOfLUPDecomposition = decomposeResult.ExtractLower(); Matrix calculatedUPartOfLUPDecomposition = decomposeResult.ExtractUpper(); //Compare the two matrices double tolerance = .001; Matrix LDifferenceMatrix = calculatedLPartOfLUPDecomposition - correctLPartOfLUPDecomposition; Matrix UDifferenceMatrix = calculatedUPartOfLUPDecomposition - correctUPartOfLUPDecomposition; for (int i = 0; i < LDifferenceMatrix.NumberOfRows; i++) { for (int j = 0; j < LDifferenceMatrix.NumberOfColumns; j++) { (Math.Abs(LDifferenceMatrix.GetElement(i, j)) < tolerance).Should().BeTrue(); } } for (int i = 0; i < UDifferenceMatrix.NumberOfRows; i++) { for (int j = 0; j < UDifferenceMatrix.NumberOfColumns; j++) { (Math.Abs(UDifferenceMatrix.GetElement(i, j)) < tolerance).Should().BeTrue(); } } }
public void Matrix_InsertMatrixTest() { Matrix originalMatrix = new Matrix(3,3); double[] matrix1Row1 = { 1, 5, 6 }; double[] matrix1Row2 = { 2, 4, 7 }; double[] matrix1Row3 = { 3, 6, 8 }; originalMatrix.SetRow(0, matrix1Row1); originalMatrix.SetRow(1, matrix1Row2); originalMatrix.SetRow(2, matrix1Row3); Matrix matrixToInsert = Matrix.IdentityMatrix(2); Matrix expectedResult = new Matrix(3,3); double[] expectedResultRow1 = { 1, 5, 6 }; double[] expectedResultRow2 = { 1, 0, 7 }; double[] expectedResultRow3 = { 0, 1, 8 }; expectedResult.SetRow(0, expectedResultRow1); expectedResult.SetRow(1, expectedResultRow2); expectedResult.SetRow(2, expectedResultRow3); Matrix actualResult = originalMatrix.InsertMatrixAt(matrixToInsert, 1, 0); bool equalityResult = (actualResult == expectedResult); equalityResult.Should().BeTrue(); }
public void Matrix_RemoveColumnsTest() { Matrix testMatrix = new Matrix(2,5); double[] row1 = { 1, 2, 3, 4, 5 }; double[] row2 = { 1, 2, 3, 4, 5 }; testMatrix.SetRow(0, row1); testMatrix.SetRow(1, row2); int[] columnsToRemove = { 1, 3, 4 }; Matrix actualMatrix = testMatrix.RemoveColumns(columnsToRemove); Matrix expectedMatrix = new Matrix(2); double[] expectedRow1 = { 1, 3}; double[] expectedRow2 = { 1, 3}; expectedMatrix.SetRow(0, expectedRow1); expectedMatrix.SetRow(1, expectedRow2); (actualMatrix == expectedMatrix).Should().BeTrue(); }
public void MatricesMatrix_ConvertToMatrixTest_VariedDistances() { Matrix m1 = new Matrix(1,1); Matrix m2 = new Matrix(2,2); Matrix m3 = new Matrix(3,3); Matrix m4 = new Matrix(4,4); double[] m1Row1 = { 1}; double[] m2Row1 = { 2, 2 }; double[] m2Row2 = { 2, 2 }; double[] m3Row1 = { 3, 3, 3 }; double[] m3Row2 = { 3, 3, 3 }; double[] m3Row3 = { 3, 3, 3 }; double[] m4Row1 = { 4, 4, 4, 4 }; double[] m4Row2 = { 4, 4, 4, 4 }; double[] m4Row3 = { 4, 4, 4, 4 }; double[] m4Row4 = { 4, 4, 4, 4 }; m1.SetRow(0, m1Row1); m2.SetRow(0, m2Row1); m2.SetRow(1, m2Row2); m3.SetRow(0, m3Row1); m3.SetRow(1, m3Row2); m3.SetRow(2, m3Row3); m4.SetRow(0, m4Row1); m4.SetRow(1, m4Row2); m4.SetRow(2, m4Row3); m4.SetRow(3, m4Row4); MatricesMatrix testMatricesMatrix = new MatricesMatrix(2, 2); testMatricesMatrix.SetElement(0, 0, m1); testMatricesMatrix.SetElement(0, 1, m3); testMatricesMatrix.SetElement(1, 0, m2); testMatricesMatrix.SetElement(1, 1, m4); Matrix expectedResult = new Matrix(7, 6); double[] expectedRow1 = { 1, 0, 3, 3, 3, 0 }; double[] expectedRow2 = { 0, 0, 3, 3, 3, 0 }; double[] expectedRow3 = { 0, 0, 3, 3, 3, 0 }; double[] expectedRow4 = { 2, 2, 4, 4, 4, 4 }; double[] expectedRow5 = { 2, 2, 4, 4, 4, 4 }; double[] expectedRow6 = { 0, 0, 4, 4, 4, 4 }; double[] expectedRow7 = { 0, 0, 4, 4, 4, 4 }; expectedResult.SetRow(0, expectedRow1); expectedResult.SetRow(1, expectedRow2); expectedResult.SetRow(2, expectedRow3); expectedResult.SetRow(3, expectedRow4); expectedResult.SetRow(4, expectedRow5); expectedResult.SetRow(5, expectedRow6); expectedResult.SetRow(6, expectedRow7); Matrix actualResult = testMatricesMatrix.ConvertToMatrix(); (actualResult == expectedResult).Should().BeTrue(); }
public void MatricesMatrix_ConvertToMatrixTest() { Matrix m1 = new Matrix(2); Matrix m2 = new Matrix(2, 3); Matrix m3 = new Matrix(2); Matrix m4 = new Matrix(2, 3); double[] m1Row1 = { 1, 1 }; double[] m1Row2 = { 1, 1 }; double[] m2Row1 = { 2, 2, 2 }; double[] m2Row2 = { 2, 2, 2 }; double[] m3Row1 = { 3, 3 }; double[] m3Row2 = { 3, 3 }; double[] m4Row1 = { 4, 4, 4 }; double[] m4Row2 = { 4, 4, 4 }; m1.SetRow(0, m1Row1); m1.SetRow(1, m1Row2); m2.SetRow(0, m2Row1); m2.SetRow(1, m2Row2); m3.SetRow(0, m3Row1); m3.SetRow(1, m3Row2); m4.SetRow(0, m4Row1); m4.SetRow(1, m4Row2); MatricesMatrix testMatricesMatrix = new MatricesMatrix(2, 2); testMatricesMatrix.SetElement(0, 0, m1); testMatricesMatrix.SetElement(0, 1, m2); testMatricesMatrix.SetElement(1, 0, m3); testMatricesMatrix.SetElement(1, 1, m4); Matrix expectedResult = new Matrix(4, 5); double[] expectedRow1 = { 1, 1, 2, 2, 2 }; double[] expectedRow2 = { 1, 1, 2, 2, 2 }; double[] expectedRow3 = { 3, 3, 4, 4, 4 }; double[] expectedRow4 = { 3, 3, 4, 4, 4 }; expectedResult.SetRow(0, expectedRow1); expectedResult.SetRow(1, expectedRow2); expectedResult.SetRow(2, expectedRow3); expectedResult.SetRow(3, expectedRow4); Matrix actualResult = testMatricesMatrix.ConvertToMatrix(); (actualResult == expectedResult).Should().BeTrue(); }
// -------------------------------------------------------------------------------------------------------------- /// <summary> /// Performs Doolittle decomposition with partial pivoting and returns a combined LU matrix /// </summary> /// <param name="permutationArray">Keeps track of how the matrices have been rearranged during the calculation</param> /// <param name="toggle">is +1 or -1 (even or odd)</param> /// <returns></returns> public Matrix Decompose(out int[] permutationArray, out int toggle) { if (!this.IsSquare()) { throw new Exception("LU-Decomposition can only be found for a square matrix"); } Matrix decomposedMatrix = new Matrix(_matrix); // copy this matrix before messing with it permutationArray = new int[NumberOfRows]; // set up row permutation result for (int i = 0; i < NumberOfRows; ++i) { permutationArray[i] = i; } toggle = 1; // toggle tracks row swaps. +1 -> even, -1 -> odd //Loop through the columns for (int columnIndex = 0; columnIndex < NumberOfRows - 1; columnIndex++) { //Find largest value in the current column double maxOfColumn = Math.Abs(decomposedMatrix.GetElement(columnIndex, columnIndex)); int pivotRowIndex = columnIndex; // loop through all of the rows in this column for (int rowIndex = columnIndex + 1; rowIndex < NumberOfRows; rowIndex++) { if (Math.Abs(decomposedMatrix.GetElement(rowIndex, columnIndex)) > maxOfColumn) { maxOfColumn = Math.Abs(decomposedMatrix.GetElement(rowIndex, columnIndex)); pivotRowIndex = rowIndex; } } if (pivotRowIndex != columnIndex) // if largest value not on pivot, swap rows { double[] rowPtr = decomposedMatrix.GetRow(pivotRowIndex); decomposedMatrix.SetRow(pivotRowIndex, decomposedMatrix.GetRow(columnIndex)); decomposedMatrix.SetRow(columnIndex, rowPtr); int tmp = permutationArray[pivotRowIndex]; // and swap permutation info permutationArray[pivotRowIndex] = permutationArray[columnIndex]; permutationArray[columnIndex] = tmp; toggle = -toggle; // adjust the row-swap toggle } //Check to see if there is a zero on the diagonal. If so, try to get rid of it by swapping with a row that is beneath the row with a zero on the diagonal // double elementOnDiagonal = decomposedMatrix.GetElement(columnIndex, columnIndex); //if (Math.Round(elementOnDiagonal, 6) == 0.0) //{ // // find a good row to swap // int goodRow = -1; // for (int row = columnIndex + 1; row < decomposedMatrix.NumberOfRows; row++) // { // double element = decomposedMatrix.GetElement(row, columnIndex); // if (Math.Round(element, 6) != 0.0) // { // goodRow = row; // } // } // if (goodRow != -1) // { // // swap rows so 0.0 no longer on diagonal // double[] rowPtr = decomposedMatrix.GetRow(goodRow); // decomposedMatrix.SetRow(goodRow, decomposedMatrix.GetRow(columnIndex)); // decomposedMatrix.SetRow(columnIndex, rowPtr); // int tmp = permutationArray[goodRow]; // and swap perm info // permutationArray[goodRow] = permutationArray[columnIndex]; // permutationArray[columnIndex] = tmp; // toggle = -toggle; // adjust the row-swap toggle // } // else // { // // throw new Exception("Cannot use Doolittle's method on this matrix"); // } //} //Find the next value to insert into the decomposed matrix for (int rowIndex = columnIndex + 1; rowIndex < this.NumberOfRows; ++rowIndex) { double valueToStore = decomposedMatrix.GetElement(rowIndex, columnIndex)/decomposedMatrix.GetElement(columnIndex, columnIndex); decomposedMatrix.SetElement(rowIndex, columnIndex, valueToStore); for (int nextColumnIndex = columnIndex + 1; nextColumnIndex < NumberOfRows; ++nextColumnIndex) { double valueToStore2 = decomposedMatrix.GetElement(rowIndex, nextColumnIndex) - decomposedMatrix.GetElement(rowIndex, columnIndex)*decomposedMatrix.GetElement(columnIndex, nextColumnIndex); decomposedMatrix.SetElement(rowIndex, nextColumnIndex, valueToStore2); } } } // main column loop return decomposedMatrix; } // MatrixDecompose
/// <summary> /// Returns a matrix that can be multiplied by another matrix to represent a rotation of that matrix about the Z axis by the specified angle /// </summary> public static Matrix RotationMatrixAboutZ(Angle rotationAngle) { Matrix rotationMatrix = new Matrix(3); double[] row1 = {Math.Cos(rotationAngle.InRadians.Value), -Math.Sin(rotationAngle.InRadians.Value), 0}; double[] row2 = {Math.Sin(rotationAngle.InRadians.Value), Math.Cos(rotationAngle.InRadians.Value), 0}; double[] row3 = {0, 0, 1}; rotationMatrix.SetRow(0, row1); rotationMatrix.SetRow(1, row2); rotationMatrix.SetRow(2, row3); return rotationMatrix; }
/// <summary> /// Takes values from a matrix and determines a cofactor by removing a certain row and column from the matrix. /// Logic developed with help from Andrew Morton on stackoverflow: /// http://stackoverflow.com/questions/24416946/next-step-in-calculating-a-matrix-determinant /// </summary> public Matrix GetSubMatrix(int[] indicesOfRowsToKeep, int[] indicesOfColumnsToKeep) { Matrix subMatrix = new Matrix(indicesOfRowsToKeep.Length, indicesOfColumnsToKeep.Length); Matrix tempMatrix = new Matrix(indicesOfRowsToKeep.Length, this.NumberOfColumns); int insertRowAt = 0; foreach (int rowToKeep in indicesOfRowsToKeep) { tempMatrix.SetRow(insertRowAt, this.GetRow(rowToKeep)); insertRowAt++; } int insertColumnAt = 0; foreach (int columnToKeep in indicesOfColumnsToKeep) { subMatrix.SetColumn(insertColumnAt, tempMatrix.GetColumn(columnToKeep)); insertColumnAt++; } return subMatrix; }