/// <summary> /// Method is used to get a minor of the matrix. /// </summary> /// <param name="matrix">initial matrix.</param> /// <param name="rowIndex">Row index to exclude.</param> /// <param name="columnIndex">Column index to exclude</param> /// <returns></returns> public static MatrixT <T> GetMinor(MatrixT <T> matrix, int rowIndex, int columnIndex) { MatrixT <T> result = new MatrixT <T>(matrix.Rows - 1, matrix.Columns - 1); int ki = 0; for (int i = 0; i < matrix.Rows; i++) { if (i != rowIndex) { for (int j = 0, kj = 0; j < matrix.Columns; j++) { if (j != columnIndex) { result[ki, kj] = matrix[i, j]; kj++; } } ki++; } } return(result); }
private void SortRows(MatrixT <double> matrix, ref double[] rightPart, int sortIndex) { double maxElement = matrix[sortIndex, sortIndex]; int maxElementIndex = sortIndex; for (int i = sortIndex + 1; i < this.Matrix.Rows; i++) { if (matrix[i, sortIndex] > maxElement) { maxElement = matrix[i, sortIndex]; maxElementIndex = i; } } if (maxElement > sortIndex) { double temp; temp = rightPart[maxElementIndex]; rightPart[maxElementIndex] = rightPart[sortIndex]; rightPart[sortIndex] = temp; for (int i = 0; i < this.Matrix.Columns; i++) { temp = matrix[maxElementIndex, i]; matrix[maxElementIndex, i] = matrix[sortIndex, i]; matrix[sortIndex, i] = temp; } } }
/// <summary> /// Summarizing operator overloading. /// </summary> /// <param name="A">Left operand.</param> /// <param name="B">Right operand.</param> /// <returns>The result of summarizing operator.</returns> public static MatrixT <T> operator +(MatrixT <T> A, MatrixT <T> B) { if (Paral) { MatrixT <T> ans = new MatrixT <T>(new T[A.Elements.GetLength(0), A.Elements.GetLength(1)]); Parallel.For(0, A.Elements.GetLength(0), (i) => { for (int j = 0; j < A.Elements.GetLength(1); j++) { ans.Elements[i, j] = (dynamic)(A.Elements[i, j]) + (dynamic)(B.Elements[i, j]); } }); return(ans); } else { MatrixT <T> ans = new MatrixT <T>(new T[A.Elements.GetLength(0), A.Elements.GetLength(1)]); for (int i = 0; i < A.Elements.GetLength(0); i++) { for (int j = 0; j < A.Elements.GetLength(1); j++) { ans.Elements[i, j] = (dynamic)(A.Elements[i, j]) + (dynamic)(B.Elements[i, j]); } } return(ans); } }
/// <summary> /// Method is used to get a determinant of the required matrix. /// </summary> /// <param name="matrix">Initial matrix to get determinant.</param> /// <returns>Matrix determinant.</returns> public static double GetMatrixDeterminant(MatrixT <T> matrix) { if (matrix.Elements.Length == 1) { return((dynamic)matrix[0, 0]); } if (matrix.Elements.Length == 4) { return((dynamic)matrix[0, 0] * (dynamic)matrix[1, 1] - (dynamic)matrix[0, 1] * (dynamic)matrix[1, 0]); } double sign = 1; double result = 0; for (int i = 0; i < matrix.Elements.GetLength(1); i++) { T[,] minor = MatrixT <T> .GetMinor(matrix.Elements, i); result += sign * (dynamic)matrix[0, i] * GetMatrixDeterminant(new MatrixT <T>(minor)); sign = -sign; } return(result); }
private LAEAnswer CalculateKramerMethodAsync(out List <LAEVariable> lAEVariables) { bool systemCompatible = this.CheckLinearAlgebraicEquationSystemCompatibility(); if (!systemCompatible) { lAEVariables = null; return(LAEAnswer.NoSolutions); } double matrixDeterminant = MatrixT <double> .GetMatrixDeterminant(this.Matrix); ConcurrentBag <LAEVariable> result = new ConcurrentBag <LAEVariable>(); Parallel.For(0, this.Matrix.Columns, (i) => { MatrixT <double> currentMatrix = MatrixT <double> .SubstituteMatrixColumn(this.Matrix, i, this.RightPartEquations); double currentDeterminant = MatrixT <double> .GetMatrixDeterminant(currentMatrix); result.Add(new LAEVariable(this.Variables[i].Name, currentDeterminant / matrixDeterminant)); }); lAEVariables = result.Cast <LAEVariable>().ToList(); return(LAEAnswer.OneSolution); }
/// <summary> /// Method is used to get matrix rang. /// </summary> /// <param name="matrix">Initial matrix to get its rang.</param> /// <returns>Matrix rang.</returns> public static int GetRang(MatrixT <T> matrix) { int rank = 0; int q = 1; while (q <= MatrixT <int> .GetMinValue(matrix.Elements.GetLength(0), matrix.Elements.GetLength(1))) { MatrixT <T> matbv = new MatrixT <T>(q, q); for (int i = 0; i < (matrix.Elements.GetLength(0) - (q - 1)); i++) { for (int j = 0; j < (matrix.Elements.GetLength(1) - (q - 1)); j++) { for (int k = 0; k < q; k++) { for (int c = 0; c < q; c++) { matbv[k, c] = matrix[i + k, j + c]; } } if (MatrixT <T> .GetMatrixDeterminant(matbv) != 0) { rank = q; } } } q++; } return(rank); }
private LAEAnswer CalculateKramerMethod(out List <LAEVariable> lAEVariables) { bool systemCompatible = this.CheckLinearAlgebraicEquationSystemCompatibility(); if (!systemCompatible) { lAEVariables = null; return(LAEAnswer.NoSolutions); } double matrixDeterminant = MatrixT <double> .GetMatrixDeterminant(this.Matrix); List <LAEVariable> result = new List <LAEVariable>(); for (int i = 0; i < this.Matrix.Columns; i++) { MatrixT <double> currentMatrix = MatrixT <double> .SubstituteMatrixColumn(this.Matrix, i, this.RightPartEquations); double currentDeterminant = MatrixT <double> .GetMatrixDeterminant(currentMatrix); result.Add(new LAEVariable(this.Variables[i].Name, currentDeterminant / matrixDeterminant)); } lAEVariables = result; return(LAEAnswer.OneSolution); }
/// <summary> /// Method is used to transpone the required matrix. /// </summary> /// <param name="matrix">Initial matrix.</param> /// <returns>Transponed matrix of the initial one.</returns> public static MatrixT <T> TransponeMatrix(MatrixT <T> matrix) { MatrixT <T> result = new MatrixT <T>(matrix.Columns, matrix.Rows); for (int i = 0; i < matrix.Rows; i++) { for (int j = 0; j < matrix.Columns; j++) { result[j, i] = matrix[i, j]; } } return(result); }
/// <summary> /// Method is used to check the compatibility of linear algebraic equation system. /// </summary> /// <returns>The flag which represents if this system is compatibile</returns> public bool CheckLinearAlgebraicEquationSystemCompatibility() { int matrixRank = MatrixT <double> .GetRang(this.Matrix); MatrixT <double> extendedMatrix = MatrixT <double> .ExtendMatrix(this.Matrix, this.RightPartEquations.ToArray()); int extendedMatrixRank = MatrixT <double> .GetRang(extendedMatrix); if (matrixRank == extendedMatrixRank) { return(true); } return(false); }
public static void CopyMatrixItems(MatrixT <T> sourceMatrix, MatrixT <T> destinationMatrix) { if (sourceMatrix.Columns != destinationMatrix.Columns || sourceMatrix.Rows != destinationMatrix.Rows) { throw new ArgumentException("Matrixes don't have the same amount of rows and columns!"); } for (int i = 0; i < sourceMatrix.Rows; i++) { for (int j = 0; j < sourceMatrix.Columns; j++) { destinationMatrix[i, j] = sourceMatrix[i, j]; } } }
/// <summary> /// Method is used to add one column to a matrix. /// </summary> /// <param name="matrix">Initial matrix.</param> /// <param name="extension">Extra column which will be added.</param> /// <returns>The extended matrix.</returns> public static MatrixT <T> ExtendMatrix(MatrixT <T> matrix, T[] extension) { MatrixT <T> result = new MatrixT <T>(matrix.Rows, matrix.Columns + 1); for (int i = 0; i < matrix.Rows; i++) { for (int j = 0; j < matrix.Columns; j++) { result[i, j] = matrix[i, j]; } result[i, result.Columns - 1] = extension[i]; } return(result); }
/// <summary> /// Method is used to set a basis for a scpecified matrix. /// </summary> /// <param name="matrix">The matrix to set a basis there.</param> public static void SetBaseMatrix(MatrixT <T> matrix) { for (int i = 0; i < matrix.Rows; i++) { for (int j = 0; j < matrix.Columns; j++) { if (i == j) { matrix[i, j] = (dynamic)1; } else { matrix[i, j] = (dynamic)0; } } } }
private LAEAnswer CalculateMatrixMethod(out List <LAEVariable> lAEVariables) { bool systemCompatible = this.CheckLinearAlgebraicEquationSystemCompatibility(); if (!systemCompatible) { lAEVariables = null; return(LAEAnswer.NoSolutions); } MatrixT <double> inversedMatrix = MatrixT <double> .GetInverseMatrix(this.Matrix); MatrixT <double> resultMatrix = inversedMatrix * new MatrixT <double>(this.RightPartEquations.ToArray()); lAEVariables = LAEVariable.FillLAEVariablesWithMatrix(resultMatrix, this.Variables); return(LAEAnswer.OneSolution); }
internal static List <LAEVariable> FillLAEVariablesWithMatrix <T>(MatrixT <T> matrix, List <Variable> lAEVariables) { if (matrix != null && matrix.Columns == 1 && matrix.Rows == lAEVariables.Count) { List <LAEVariable> result = new List <LAEVariable>(); for (int i = 0; i < lAEVariables.Count; i++) { result.Add(new LAEVariable(lAEVariables[i].Name, (dynamic)matrix[i, 0])); } return(result); } else { throw new ArgumentException("Inapropriate matrix to fill the list of variables!"); } }
/// <summary> /// Method is used to substitute matrix column with other values. /// </summary> /// <param name="matrix">Initial matrix for substitution.</param> /// <param name="columnIndex">Index of a column which will be substituted.</param> /// <param name="newColumn">New values of the column.</param> /// <returns></returns> public static MatrixT <T> SubstituteMatrixColumn(MatrixT <T> matrix, int columnIndex, List <T> newColumn) { if (newColumn.Count != matrix.Rows) { throw new ArgumentException($"Amount of matrix rows: {matrix.Rows} and amount of matrix columns: {newColumn.Count}"); } MatrixT <T> result = new MatrixT <T>(matrix.Rows, matrix.Columns); MatrixT <T> .CopyMatrixItems(matrix, result); for (int i = 0; i < result.Rows; i++) { result[i, columnIndex] = newColumn[i]; } return(result); }
public static void PrintMatrix(MatrixT <T> matrix, StreamWriter streamWriter = null) { if (streamWriter == null) { streamWriter = new StreamWriter(Console.OpenStandardOutput()); streamWriter.AutoFlush = true; Console.SetOut(streamWriter); } for (int i = 0; i < matrix.Rows; i++) { for (int j = 0; j < matrix.Columns; j++) { streamWriter.Write($"{matrix[i, j]} "); } streamWriter.WriteLine(); } }
/// <summary> /// Multiplication by a number overloading. /// </summary> /// <param name="a">Number to multiply a matrix.</param> /// <param name="B">Matrix which will be multiplied.</param> /// <returns>The result of multiplication by a number.</returns> public static MatrixT <T> operator *(dynamic a, MatrixT <T> B) { Type type = a.GetType(); bool isNumber = (type.IsPrimitive && type != typeof(bool) && type != typeof(char)); if (isNumber) { MatrixT <T> result = new MatrixT <T>(B.Rows, B.Columns); for (int i = 0; i < B.Rows; i++) { for (int j = 0; j < B.Columns; j++) { result[i, j] = B[i, j] * a; } } return(result); } throw new ArgumentException($"Cannot multiply the matrix by a number {a}."); }
/// <summary> /// Method describes two matrixes equation process. /// </summary> /// <param name="obj">Matrix to compare.</param> /// <returns>Flag if two matrixes are equal.</returns> public override bool Equals(object obj) { MatrixT <T> inputMatrix = (MatrixT <T>)obj; if (this.Columns != inputMatrix.Columns || this.Rows != inputMatrix.Rows) { return(false); } for (int i = 0; i < this.Rows; i++) { for (int j = 0; j < this.Columns; j++) { if ((dynamic)this.Elements[i, j] != (dynamic)inputMatrix[i, j]) { return(false); } } } return(true); }
/// <summary> /// Method is used to take inversed matrix. /// </summary> /// <param name="matrix">Initial matrix.</param> /// <returns>Inversed matrix.</returns> public static MatrixT <T> GetInverseMatrix(MatrixT <T> matrix) { double determinant = MatrixT <T> .GetMatrixDeterminant(matrix); if (determinant != 0) { MatrixT <T> reversedMatrix = new MatrixT <T>(matrix.Rows, matrix.Columns); for (int i = 0; i < matrix.Rows; i++) { for (int j = 0; j < matrix.Columns; j++) { MatrixT <T> tempMatrix = MatrixT <T> .GetMinor(matrix, i, j); reversedMatrix[i, j] = (dynamic)Math.Pow(-1.0, i + j + 2) * (dynamic)MatrixT <T> .GetMatrixDeterminant(tempMatrix) / (dynamic)determinant; } } return(MatrixT <T> .TransponeMatrix(reversedMatrix)); } return(null); }
/// <summary> /// Multiplication operator overloading. /// </summary> /// <param name="A">Left operand.</param> /// <param name="B">Right operand.</param> /// <returns>The result of multiplication operand.</returns> public static MatrixT <T> operator *(MatrixT <T> A, MatrixT <T> B) { if (Paral) { MatrixT <T> ans = new MatrixT <T>(new T[A.Elements.GetLength(0), B.Elements.GetLength(1)]); Parallel.For(0, A.Elements.GetLength(0), (i) => { for (int j = 0; j < B.Elements.GetLength(1); j++) { ans.Elements[i, j] = (dynamic)0; for (int k = 0; k < A.Elements.GetLength(1); k++) { ans.Elements[i, j] += (dynamic)A.Elements[i, k] * (dynamic)B.Elements[k, j]; } } }); return(ans); } else { MatrixT <T> ans = new MatrixT <T>(new T[A.Elements.GetLength(0), B.Elements.GetLength(1)]); for (int i = 0; i < A.Elements.GetLength(0); i++) { for (int j = 0; j < B.Elements.GetLength(1); j++) { ans.Elements[i, j] = (dynamic)0; for (int k = 0; k < A.Elements.GetLength(1); k++) { ans.Elements[i, j] += (dynamic)A.Elements[i, k] * (dynamic)B.Elements[k, j]; } } } return(ans); } }
/// <summary> /// Method is used to set matrix of linear alebraic equation system. /// </summary> /// <param name="leftEquationsParts">parts of the left equations system.</param> /// <param name="variables">LAE system variables.</param> /// <param name="constants">LAE system constants.</param> /// <returns>matrix of the relevant linear alebraic equation system.</returns> private static MatrixT <double> SetMatrix(List <Expression> leftEquationsParts, List <Variable> variables, List <Variable> constants) { MatrixT <double> result = new MatrixT <double>(leftEquationsParts.Count, variables.Count); for (int i = 0; i < leftEquationsParts.Count; i++) { for (int j = 0; j < variables.Count; j++) { List <Variable> currentVariables = variables; LinearAlgebraicEquationSystem.SetVariablesWithValues(currentVariables, 0); currentVariables[j].Value = 1.0; if (constants != null && constants.Count > 0) { currentVariables.AddRange(constants); } result[i, j] = leftEquationsParts[i].GetResultValue(currentVariables); } } return(result); }
private LAEAnswer CalculateGaussMethod(out List <LAEVariable> results) { results = null; MatrixT <double> currentMatrix = new MatrixT <double>(this.Matrix.Rows, this.Matrix.Columns); MatrixT <double> .CopyMatrixItems(this.Matrix, currentMatrix); double[] rightPart = new double[this.RightPartEquations.Count]; for (int i = 0; i < this.RightPartEquations.Count; i++) { rightPart[i] = this.RightPartEquations[i]; } double[] answer = new double[this.Variables.Count]; if (currentMatrix.Rows != currentMatrix.Columns) { results = null; return(LAEAnswer.NoSolutions); } for (int i = 0; i < currentMatrix.Rows - 1; i++) { SortRows(currentMatrix, ref rightPart, i); for (int j = i + 1; j < currentMatrix.Rows; j++) { if (currentMatrix[i, i] != 0) { double multElement = currentMatrix[j, i] / currentMatrix[i, i]; for (int k = i; k < currentMatrix.Columns; k++) { currentMatrix[j, k] -= currentMatrix[i, k] * multElement; } rightPart[j] -= rightPart[i] * multElement; } } } for (int i = currentMatrix.Rows - 1; i >= 0; i--) { answer[i] = rightPart[i]; for (int j = currentMatrix.Rows - 1; j > i; j--) { answer[i] -= currentMatrix[i, j] * answer[j]; } if (currentMatrix[i, i] == 0) { if (rightPart[i] == 0) { return(LAEAnswer.ManySolutions); } else { return(LAEAnswer.NoSolutions); } } answer[i] /= currentMatrix[i, i]; } results = new List <LAEVariable>(); for (int i = 0; i < this.Variables.Count; i++) { results.Add(new LAEVariable(this.Variables[i].Name, answer[i])); } return(LAEAnswer.OneSolution); }
/// <summary> /// Method is used to take inversed matrix. /// </summary> /// <param name="matrix">Initial matrix.</param> /// <returns>Inversed matrix.</returns> public static MatrixT <T> GetInverseMatrix3(MatrixT <T> matrix) { if (matrix.Columns == matrix.Rows) { if (MatrixT <T> .GetMatrixDeterminant(matrix) != 0.0) { MatrixT <T> matrixCopy = new MatrixT <T>(matrix.Rows, matrix.Columns); for (int i = 0; i < matrix.Rows; i++) { for (int j = 0; j < matrix.Columns; j++) { matrixCopy[i, j] = matrix[i, j]; } } MatrixT <T> reverseMatrix = new MatrixT <T>(matrix.Rows, matrix.Columns); MatrixT <T> .SetBaseMatrix(reverseMatrix); for (int k = 0; k < matrix.Rows; k++) { T div = matrixCopy[k, k]; for (int m = 0; m < matrix.Columns; m++) { matrixCopy[k, m] /= (dynamic)div; reverseMatrix[k, m] /= (dynamic)div; } for (int i = k + 1; i < matrix.Rows; i++) { T multi = matrixCopy[i, k]; for (int j = 0; j < matrix.Columns; j++) { matrixCopy[i, j] -= (dynamic)multi * (dynamic)matrixCopy[k, j]; reverseMatrix[i, j] -= (dynamic)multi * (dynamic)reverseMatrix[i, j]; } } } for (int kk = matrix.Rows - 1; kk > 0; kk--) { matrixCopy[kk, matrix.Columns - 1] /= (dynamic)matrixCopy[kk, kk]; reverseMatrix[kk, matrix.Columns - 1] /= (dynamic)matrixCopy[kk, kk]; for (int i = kk - 1; i + 1 > 0; i--) { T multi2 = matrixCopy[i, kk]; for (int j = 0; j < matrix.Columns; j++) { matrixCopy[i, j] -= (dynamic)multi2 * (dynamic)matrixCopy[kk, j]; reverseMatrix[i, j] -= (dynamic)multi2 * (dynamic)reverseMatrix[kk, j]; } } } return(MatrixT <T> .TransponeMatrix(reverseMatrix)); } } return(null); }