====== Mátrix osztály megvalósítás ====== Matrix.cs namespace matrix { /* Általános double típusú elemekből álló Mátrix osztály megvalósítás. Tulajdonságok Row : a mátrix sorainak száma (int) - csak olvasható Col : a mátrix oszlopainak száma (int) - csak olvasható [int i, int j] : nulla bázisú indexer Debug : bool - nyomkövetés bekapcsolva Konstruktorok public Matrix() - alapértelmezett méretű (jelen esetben 5x5-ös)) nullmátrix létrehozása public Matrix(int r, int c) - r x c méretű nullmátrix léterhozása public Matrix(double[,] D) - mátrix létrehozása a megadott tömb alapján public Matrix(int[,] D) - mátrix létrehozása a megadott tömb alapján public Matrix(Matrix M) - mátrix létrehozása egy másik mátrix másolataként Metódusok public Matrix Duplicate() public Matrix Transpose() public string ToString() public double getElement(int i, int j) public void setElement(int i, int j, double value) public bool Equals(object obj) public override int GetHashCode() public void multiplyRow(int i, double multiplier) public void addRow(int targetRow, int addedRow, double multiplier) public void swapRows(int row1, int row2) public static Matrix Concatenate(Matrix A, Matrix B) public Matrix subMatrix(int r, int c) public Matrix EchelonForm() Operátorok public static bool operator == (Matrix A, Matrix B) public static bool operator != (Matrix A, Matrix B) public static Matrix operator + (Matrix A, Matrix B) public static Matrix operator - (Matrix A, Matrix B) public static Matrix operator * (T multiplier, Matrix A) public static Matrix operator * (Matrix A, T multiplier) public static Matrix operator * (Matrix A, Matrix B) */ public class Matrix { static int defaultRow = 5; static int defaultCol = 5; public static bool Debug { get; set; } = false; public readonly int Row; public readonly int Col; protected double[,] Data; public Matrix(){ Row = defaultRow; Col = defaultCol; Data = new double[Row, Col]; } public Matrix(int r, int c) { Row = r; Col = c; Data = new double[Row, Col]; } public Matrix(int[,] D) { Row = D.GetLength(0); Col = D.GetLength(1); Data = new double[Row,Col]; for (int i = 0; i < Row; i++) for (int j = 0; j < Col; j++) Data[i,j] = System.Convert.ToDouble(D[i,j]); } public Matrix(double[,] D) { Row = D.GetLength(0); Col = D.GetLength(1); Data = new double[Row,Col]; for (int i = 0; i < Row; i++) for (int j = 0; j < Col; j++) Data[i,j] = D[i,j]; } public Matrix(Matrix B) { Row = B.Row; Col = B.Col; Data = new double[Row,Col]; for (int i = 0; i < Row; i++) for (int j = 0; j < Col; j++) Data[i,j] = System.Convert.ToDouble(B[i, j]); } public Matrix Duplicate() { Matrix D = new Matrix(Row, Col); for (int i = 0; i < Row; i++) for (int j = 0; j < Col; j++) D[i, j] = this[i, j]; return D; } public Matrix Transpose() { Matrix D = new Matrix(Col, Row); for (int i = 0; i < Row; i++) for (int j = 0; j < Col; j++) D[i, j] = this[j, i]; return D; } public override string ToString() { string str = ""; for (int i = 0; i < Row; i++) { for (int j = 0; j < Col; j++) str += this[i,j].ToString("F2")+" "; str += "\n"; } return str; } private double getElement(int i, int j) { if (i < 0 || i >= Row || j < 0 || j >= Col) throw new MatrixException("Invalid index"); return Data[i, j]; } private void setElement(int i, int j, double value) { if (i < 0 || i >= Row || j < 0 || j >= Col) throw new MatrixDimensionException("Invalid index"); Data[i, j] = value; } public override bool Equals(object obj){ if (object.ReferenceEquals(this, obj)) return true; if ((obj == null) || !this.GetType().Equals(obj.GetType())) { return false; } else { Matrix M = (Matrix) obj; bool ok = (Row == M.Row && Col == M.Col); int i = 0; while (i < Row && ok) { int j = 0; while (j < Col && this[i,j] == M[i, j]) j++; if (j < Col) ok = false; } return ok; } } public override int GetHashCode() { if (this != null) { unchecked { int hash = 17; hash = (hash * 23 + Row.GetHashCode()) * 23 + Row.GetHashCode(); foreach (var item in Data) { hash = hash * 23 + ((item != null) ? item.GetHashCode() : 0); } return hash; } } return 0; } public double this[int i, int j] { get { return getElement(i, j); } set { setElement(i, j, value); } } public static bool operator == (Matrix A, Matrix B) { return A.Equals(B); } public static bool operator != (Matrix A, Matrix B) { return !A.Equals(B); } public static Matrix operator + (Matrix A, Matrix B) { if (A.Row != B.Row || A.Col != B.Col) throw new MatrixDimensionException("["+A.Row+"; "+A.Col+"] <> ["+B.Row+"; "+B.Col+"]"); Matrix R = new Matrix(A.Row, A.Col); for (int i = 0; i < A.Row; i++) for (int j = 0; j < A.Col; j++) R[i,j] = A[i,j] + B[i,j]; return R; } public static Matrix operator - (Matrix A, Matrix B) { if (A.Row != B.Row || A.Col != B.Col) throw new MatrixDimensionException("["+A.Row+"; "+A.Col+"] <> ["+B.Row+"; "+B.Col+"]"); Matrix R = new Matrix(A.Row, A.Col); for (int i = 0; i < A.Row; i++) for (int j = 0; j < A.Col; j++) R[i,j] = A[i,j] - B[i,j]; return R; } public static Matrix operator * (double multiplier, Matrix A) { Matrix R = new Matrix(A.Row, A.Col); for (int i = 0; i < A.Row; i++) for (int j = 0; j < A.Col; j++) R[i,j] = A[i,j] * System.Convert.ToDouble(multiplier); return R; } public static Matrix operator *(Matrix A, double multiplier) => multiplier * A; public static Matrix operator * (Matrix A, Matrix B) { if (A.Col != B.Row) throw new MatrixDimensionException("A.Col ("+A.Col+") <> B.Row ("+B.Row+") "); Matrix R = new Matrix(A.Row, B.Col); for (int i = 0; i < A.Row; i++) for (int j = 0; j < B.Col; j++) { R[i,j] = 0; for (int k = 0; k < A.Col; k++) R[i,j] += A[i,k] * B[k,j]; } return R; } public void multiplyRow(int i, double multiplier) { if (i < 0 || i >= Row) throw new MatrixException("Invalid index ("+i+")"); for (int j = 0; j < Col; j++) this[i, j] *= multiplier; } public void addRow(int targetRow, int addedRow, double multiplier) { if (targetRow < 0 || targetRow >= Row || addedRow < 0 || addedRow >= Row) throw new MatrixException("Invalid index ("+targetRow+" or "+addedRow+")"); for (int j = 0; j < Col; j++) this[targetRow, j] += multiplier * this[addedRow, j]; } public void swapRows(int row1, int row2) { if (row1 < 0 || row1 >= Row || row2 < 0 || row2 >= Row) throw new MatrixException("Illegal index ("+row1+" or "+row2+")"); for (int j = 0; j < Col; j++) { double temp = this[row1, j]; this[row1, j] = this[row2, j]; this[row2, j] = temp; } } public static Matrix Concatenate(Matrix A, Matrix B) { if (A.Row != B.Row) throw new MatrixDimensionException("Matrix dimension (A.Row != B.Row)"); Matrix C = new Matrix(A.Row, A.Col + B.Col); for (int i = 0; i < C.Row; i++) for (int j = 0; j < C.Col; j++) { if (j < A.Col) C[i, j] = A[i, j]; else C[i, j] = B[i, j - A.Col]; } return C; } public Matrix subMatrix(int r, int c) { if (r < 0 || r >= Row) throw new MatrixException("Illegal index (row = "+r+")"); if (c < 0 || c >= Col) throw new MatrixException("Illegal index (col = "+c+")"); Matrix Sub = new Matrix(Row-1, Col-1); int k = 0; int l = 0; for (int i = 0; i < Row; i++) { if (i == r) continue; l = 0; for (int j = 0; j < Col; j++) { if (j == c) continue; Sub[k, l] = this[i, j]; l++; } k++; } return Sub; } public Matrix EchelonForm() { try { if (Row > Col) throw new MatrixException(); Matrix ReducedEchelonMatrix = new Matrix(this); for (int i = 0; i < Row; i++) { int j = i; // search for non-zero entry while (j < Row && ReducedEchelonMatrix[j,i] == 0) j++; if (j >= Row) continue; // if not found --> next column int k = i; // search for 1 entry while (k < Row && ReducedEchelonMatrix[k,i] != 1) k++; if (k < Row && k != i) ReducedEchelonMatrix.swapRows(i, k); else { if (j != i) ReducedEchelonMatrix.swapRows(i, j); ReducedEchelonMatrix.multiplyRow(i, 1 / ReducedEchelonMatrix[i, i]); } for (j = i + 1; j < ReducedEchelonMatrix.Row; j++) ReducedEchelonMatrix.addRow(j, i, -ReducedEchelonMatrix[j, i]); for (j = i - 1; j >= 0; j--) ReducedEchelonMatrix.addRow(j, i, -ReducedEchelonMatrix[j, i]); if (Debug) { System.Console.WriteLine(ReducedEchelonMatrix); System.Console.WriteLine("------------"); } } return new Matrix(ReducedEchelonMatrix); } catch (System.Exception) { throw new MatrixException("Matrix can not be reduced to Echelon form"); } } } }