/// <summary> /// Kopierkonstruktor /// </summary> /// <param name="other">Original</param> internal MatrixEx(MatrixEx other) { m_cmps = new Fraction[other.Rows][]; for (int i = 0; i < other.Rows; i++) { m_cmps[i] = new Fraction[other.Columns]; for (int j = 0; j < other.Columns; j++) { m_cmps[i][j] = new Fraction(other.m_cmps[i][j]); } } }
private static bool SolveFromPivot(ref MatrixEx matrix, uint row, uint col) { bool result = true; //int max = 0; //if rad_equation.Checked then max := edt_Dimension.Value else if rad_inverse.Checked then max := edt_Dimension.Value*2-1; //Pivotelement ist Null - tausche Pivotzeile mit anderer Zeile if (matrix[row, col].Numerator == 0) { bool valid = false; //gültige Zeile ohne Null suchen for (uint i = row + 1; i < matrix.Rows; i++) { if (matrix[i, col].Numerator != 0) { valid = true; //Zeilenelemente tauschen for (uint j = 0; j < /*max*/ matrix.Columns; j++) { Fraction h = matrix[row, j]; matrix[row, j] = matrix[i, j]; matrix[i, j] = h; } break; } } result = valid; } // Erzeugen von Nullen unterhalb des Pivotelements if (result) { for (uint i = row + 1; i < matrix.Rows; i++) { if (matrix[i, col].Numerator != 0) { // Zeilenmodifikator bestimmen Fraction mul = matrix[i, col] / matrix[row, col] * -1; for (uint j = col; j < /*col*/ matrix.Columns; j++) { matrix[i, j] = matrix[row, j] * mul + matrix[i, j]; } } } } // Mit nächster Spalte weitermachen if (row + 1 < matrix.Rows - 1 && result) { result = SolveFromPivot(ref matrix, row + 1, col + 1); } return(result); }
/// <summary> /// Transponierte Matrix /// </summary> /// <returns>Transponierte Matrix</returns> public MatrixEx Transpone() { MatrixEx trans = new MatrixEx(Columns, Rows); for (int i = 0; i < Rows; i++) { for (int j = 0; j < Columns; j++) { trans.m_cmps[j][i] = m_cmps[i][j]; } } return(trans); }
/// <summary> /// Division durch Skalar /// </summary> /// <param name="v"></param> /// <param name="skalar"></param> /// <returns></returns> public static MatrixEx operator /(MatrixEx m, Fraction skalar) { MatrixEx matrix = new MatrixEx(m); for (int i = 0; i < matrix.Rows; i++) { for (int j = 0; j < matrix.Columns; j++) { matrix.m_cmps[i][j] /= skalar; } } return(matrix); }
private static bool ReverseSolveFromPivot(ref MatrixEx matrix, uint row, uint col) { bool result = true; //max := 0; //if rad_equation.Checked then max := edt_Dimension.Value else if rad_inverse.Checked then max := edt_Dimension.Value*2-1; //Pivotelement ist nicht Eins - gesamte Zeile dividieren if (matrix[row, col].Equals(1) == false) { Fraction h = new Fraction(matrix[row, col]); for (uint j = /*max*/ matrix.Columns - 1; j >= 0; j--) { matrix[row, j] /= h; if (j == 0) { break; } } } // Erzeugen von Nullen überhalb des Pivotelements if (row > 0) { for (uint i = row - 1; ; i--) { // Zeilenmodifikator bestimmen //mul := Matrix.Element[i,Col]/Matrix.Element[Row,Col]*-1; Fraction mul = new Fraction(matrix[i, col]) / matrix[row, col] * -1; for (uint j = matrix.Columns - 1; ; j--) { //Matrix.Element[i,j] := mul*Matrix.Element[Row,j]+Matrix.Element[i,j]; Fraction h = new Fraction(matrix[row, j]) * mul + matrix[i, j]; matrix[i, j] = h; if (j == 0) { break; } } if (i == 0) { break; } } } // Mit kleinerer Matrix fortsetzen if (row > 0 && result) { result = ReverseSolveFromPivot(ref matrix, row - 1, col - 1); } return(result); }
private static Fraction CalcDeterminant(MatrixEx matrix) { if (matrix.Rows != matrix.Columns) { //Determinante nur für quadr. Matrizen throw new NotSupportedException("Determinant only applicable to quadratic matrices."); } if (matrix.Columns == 2) { return(matrix[0, 0] * matrix[1, 1] - matrix[1, 0] * matrix[0, 1]); } else { Fraction sum = new Fraction(0); //Laplace'scher Entwicklungssatz for (uint i = 0; i < matrix.Columns; i++) { //Matrix nach Spalte i entwickeln MatrixEx eMat = new MatrixEx(matrix.Rows - 1, matrix.Columns - 1); for (uint m = 1; m < matrix.Rows; m++) { for (uint n = 0; n < matrix.Columns; n++) { if (n < i) { eMat[m - 1, n] = new Fraction(matrix[m, n]); } else if (n > i) { eMat[m - 1, n - 1] = new Fraction(matrix[m, n]); } } } //rekursiver Aufruf if (matrix[0, i].Numerator != 0) { Fraction det = matrix[0, i] * CalcDeterminant(eMat); // odd(i) if (i % 2 != 0) { sum -= det; } else { sum += det; } } } return(sum); } }
/// <summary> /// Invertiert eine Matrix /// </summary> /// <param name="A">Zu intertierende Matrix</param> /// <returns>Inverse Matrix 1/A</returns> public static Matrix InvertMatrix(Matrix A) { if (A == null) { throw new ArgumentNullException("Matrix must not be null."); } if (A.Rows != A.Columns) { throw new NotSupportedException("Only quadratic matrices are invertable."); } //erweiterte Matrix erzeugen MatrixEx enhMat = new MatrixEx(A.Rows, A.Columns * 2); for (uint i = 0; i < A.Rows; i++) { for (uint j = 0; j < A.Columns; j++) { enhMat[i, j] = new Fraction(A[i, j]); if (i == j) { enhMat[i, j + A.Columns] = new Fraction(1); } else { enhMat[i, j + A.Columns] = new Fraction(0); } } } if (SolveFromPivot(ref enhMat, 0, 0)) { //Rang der Matrix prüfen (wenn kleiner Rows -> nicht eindeutig lösbar) if (Rank(enhMat, A.Rows, A.Columns) != A.Rows) { return(null); } ReverseSolveFromPivot(ref enhMat, A.Rows - 1, A.Columns - 1); } //Ergebnis aus erw. Matrix lesen Matrix result = new Matrix(A.Rows, A.Columns); for (uint i = 0; i < A.Rows; i++) { for (uint j = 0; j < A.Columns; j++) { result[i, j] = enhMat[i, j + A.Columns].Value; } } return(result); }
/// <summary> /// Subtraktion /// </summary> /// <param name="v1"></param> /// <param name="v2"></param> /// <returns></returns> public static MatrixEx operator -(MatrixEx m1, MatrixEx m2) { if (m1.Columns != m2.Columns || m1.Rows != m2.Rows) { throw new ArgumentException("Dimensions of matrices do not match."); } MatrixEx matrix = new MatrixEx(m1); for (int i = 0; i < matrix.Rows; i++) { for (int j = 0; j < matrix.Columns; j++) { matrix.m_cmps[i][j] -= m2.m_cmps[i][j]; } } return(matrix); }
private static uint Rank(MatrixEx enhMat, uint rows, uint columns) { uint count = 0; Fraction rowsum; for (uint i = 0; i < rows; i++) { rowsum = new Fraction(0); for (uint j = 0; i < columns; j++) { rowsum += enhMat[i, j]; } if (rowsum.Numerator != 0) { count++; } } return(count); }
/// <summary> /// Löst ein Gleichungssystem "A*x=b" und gibt den Lösungsvektor x zurück. /// </summary> /// <param name="A">Matrix A</param> /// <param name="b">Vektor b</param> /// <returns>Lösungsvektor x</returns> public static Vector SolveEquation(Matrix A, Vector b) { if (A == null || b == null) { throw new ArgumentNullException("Parameters must not be null."); } if (A.Rows != b.Dimensions) { throw new NotSupportedException("Dimensions of matrix and vector do not match."); } //erweiterte Matrix erzeugen MatrixEx enhMat = new MatrixEx(A.Rows, A.Columns + 1); for (uint i = 0; i < A.Rows; i++) { for (uint j = 0; j < A.Columns; j++) { enhMat[i, j] = new Fraction(A[i, j]); } enhMat[i, A.Columns] = new Fraction(b[i]); } if (SolveFromPivot(ref enhMat, 0, 0)) { //Rang der Matrix prüfen (wenn kleiner Rows -> nicht eindeutig lösbar) if (Rank(enhMat, A.Rows, A.Columns) != A.Rows) { return(null); } ReverseSolveFromPivot(ref enhMat, A.Rows - 1, A.Columns - 1); } //Ergebnis aus erw. Matrix lesen Vector result = new Vector(b.Dimensions); for (uint i = 0; i < A.Rows; i++) { result[i] = enhMat[i, A.Columns].Value; } return(result); }
/// <summary> /// Multiplikation /// </summary> /// <param name="v1"></param> /// <param name="v2"></param> /// <returns></returns> public static MatrixEx operator *(MatrixEx m1, MatrixEx m2) { if (m1.Columns != m2.Rows) { throw new ArgumentException("Inner dimensions of matrices need to match."); } MatrixEx matrix = new MatrixEx(m1.Rows, m2.Columns); for (uint i = 0; i < matrix.Rows; i++) { for (uint j = 0; j < matrix.Columns; j++) { Fraction sum = new Fraction(0); for (uint k = 0; k < m1.Columns; k++) { sum += m1[i, k] * m2[k, j]; } matrix.m_cmps[i][j] = sum; } } return(matrix); }
public override bool Equals(object other) { if (other is MatrixEx == false) { return(false); } MatrixEx oMatrix = (MatrixEx)other; bool equal = Columns == oMatrix.Columns; equal &= Rows == oMatrix.Rows; if (!equal) { return(false); } for (int i = 0; i < oMatrix.Rows; i++) { for (int j = 0; j < oMatrix.Columns; j++) { equal &= m_cmps[i][j] == oMatrix.m_cmps[i][j]; } } return(equal); }