//Метод возвращает матрицу - результат перемножения matrix2 с данной public NumericMatrix Multiple(NumericMatrix matrix2) { if (matrix2.size == size) { NumericMatrix result = new NumericMatrix(size); double buf = 0; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { for (int k = 0; k < width; k++) { buf += this.elements[i, k] * matrix2.GetElement(k, j); } result.SetElement(i, j, buf); buf = 0; } } return(result); } else { Console.WriteLine("ERROR using NumericMatrix.Multiply(NumericMatrix matrix)"); return(null); } }
//Получение матрицы смежности по матрице инцидентности //Обеспечивает более полное описание графа и дает больше гибкости при работе с данным классом private void GetAdjTable() { adj_table = new NumericMatrix(nodes_num); int from_node = 0; int to_node = 0; Console.WriteLine(rel_num); for (int j = 0; j < rel_num; j++) { for (int i = 0; i < nodes_num; i++) { if (inc_table.GetElement(i, j) == -1) { from_node = i; } else if (inc_table.GetElement(i, j) == 1) { to_node = i; } else if (inc_table.GetElement(i, j) == 2) { from_node = i; to_node = i; } } adj_table.SetElement(from_node, to_node, 1); } }
//Метод, возвращающий матрицу минора указанного элемента заданной матрицы matrix public static NumericMatrix GetMinorMatrixOfElement(NumericMatrix matrix, int i, int j) { int size = matrix.size; NumericMatrix result = new NumericMatrix(size - 1); int x = 0, y = 0; for (int k = 0; k < size; k++) { if (k != i) { for (int t = 0; t < size; t++) { if (t != j) { result.SetElement(y, x, matrix.GetElement(k, t)); x++; } } y++; x = 0; } } Console.WriteLine(result.ToString()); return(result); }
//Метод, преобразующий матрицу к треугольному виду и возвращающий ее ранг public static int GetRank(NumericMatrix matrix) { NumericMatrix.ToTriangular(matrix); int rank = 0; bool is_empty = true; for (int i = 0; i < matrix.height; i++) { for (int j = 0; j < matrix.width; j++) { if (matrix.GetElement(i, j) != 0) { is_empty = false; break; } } if (!is_empty) { rank++; } else { break; } is_empty = true; } return(rank); }
//Инициализация СНАУ с клавиатуры public void InitSNAE() { int maxValNumber = 0; variables = new Expr[0]; Console.WriteLine("Введите количество уравнений " + "(количество неизвестных должно совпадать с кол-вом уравнений или быть меньше): "); expressionsNumber = Convert.ToInt32(Console.ReadLine()); for (int i = 0; i < expressionsNumber; i++) { Console.WriteLine("Введите уравнение номер {0}:", i + 1); // expressions.Add(Console.ReadLine().Replace(' ', '\0')); TODO исправить удаление лишних пробелов freeTerms.Add(Double.Parse(expressions.Last().Split('=')[1])); symbolicExpressions.Add(Expr.Parse(expressions.Last().Split('=')[0] + "-" + freeTerms.Last().ToString())); Console.WriteLine(symbolicExpressions.Last().ToString()); if (symbolicExpressions.Last().CollectVariables().ToArray().Length > maxValNumber) { variables = symbolicExpressions.Last().CollectVariables().ToArray(); maxValNumber = variables.Length; } } varNumber = maxValNumber; if (varNumber > expressionsNumber) { Console.WriteLine("Ошибка! Количество неизвестных больше количества уравнений!"); } Console.WriteLine("Введите точность нахождения корня эпсилон:"); epsilon = Convert.ToDouble(Console.ReadLine()); currentJakobiMatrix = new Matrix <Expr>(expressionsNumber, varNumber); currentJakobiValues = new NumericMatrix(expressionsNumber, varNumber); }
//Метод, возвращающий обратную матрицу к переданной в метод матрице public static NumericMatrix GetInverseMatrix(NumericMatrix matrix) { int size = matrix.size; NumericMatrix result = new NumericMatrix(size); try { double det = GetDeterminant(matrix); if (det == 0) { throw new ZeroDetException("Исходная матрица вырожденная"); } for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) { result.SetElement(j, i, Math.Pow(-1, i + j) * GetDeterminant(GetMinorMatrixOfElement(matrix, i, j))); } } result.Multiple(1 / det); } catch (ZeroDetException ex) { Console.WriteLine("Ошибка: " + ex.Message); } return(result); }
//Иницализация графа с клавиатуры посредством матрицы смежности public void InitGraphAdj() { Console.WriteLine("Заполните матрицу смежности:"); adj_table = new NumericMatrix(nodes_num); adj_table.ConsoleInput(); GetIncTable(); CreateRelations(); }
public static void Solve(LinearProgrammingProblem lpTask) { NumericMatrix simplexTable = new NumericMatrix(lpTask.ineqNum, lpTask.ineqNum + lpTask.varNum); double[] deltaC = new double[lpTask.ineqNum]; double[] currentResultRow = new double[lpTask.ineqNum + lpTask.varNum + 1]; double[] AZero = lpTask.limitations.GetRow(lpTask.varNum + 1); }
//Конструктор класса, необходимый для инициализации графа через матрицу смежности public Graph(int nodes_num) { this.nodes_num = nodes_num; adj_table = new NumericMatrix(nodes_num); relations = new Dictionary <int, List <int> >(); rel_weights = new NumericMatrix(nodes_num); id = counter; counter++; }
//Иницализация графа с клавиатуры посредством матрицы инцидентности public void InitGraphInc() { Console.WriteLine("Введите количество отношений между узлами:"); rel_num = Convert.ToInt32(Console.ReadLine()); Console.WriteLine("Заполните матрицу инцидентности:"); inc_table = new NumericMatrix(nodes_num, rel_num); inc_table.ConsoleInput(); GetAdjTable(); CreateRelations(); }
private static void CheckRowsEquality(NumericMatrix matrix) { //double coeff = for (int i = 0; i < matrix.height; i++) { for (int k = i; k < matrix.height; k++) { for (int j = 0; j < matrix.width; j++) { } } } }
//Возвращает матрицу, лежащую в прямоугольнике с диагональю x1y1-x2y2 public new NumericMatrix GetArea(int x1, int y1, int x2, int y2) { NumericMatrix result = new NumericMatrix(y2 - y1 + 1, x2 - x1 + 1); for (int i = y1; i <= y2; i++) { for (int j = x1; j <= x2; j++) { result.SetElement(i - y1, j - x1, elements[i, j]); } } return(result); }
//Конструктор СЛАУ по расширенной матрице (добавлено для Задания 5) //Расширенная матрица и матрица коэффициентов сразу же приводятся к треугольному виду; получаем их ранги public SLAE(NumericMatrix extended_matrix_of_SLAE) { extended_matrix = extended_matrix_of_SLAE; n_equasions = extended_matrix_of_SLAE.Height(); n_x = extended_matrix_of_SLAE.Width() - 1; matrix = new NumericMatrix(n_equasions, n_x); matrix = extended_matrix.GetArea(0, 0, n_x - 1, n_equasions - 1); extended_rank = NumericMatrix.GetRank(extended_matrix); rank = NumericMatrix.GetRank(matrix); single_solution = new List <double>(); general_solution = new NumericMatrix(n_x, n_x + 1); }
//Метод, осуществляющий сложение данной матрицы с переданной в метод, в случае если размерность матриц совпадает public void Plus(NumericMatrix matrix2) { if (matrix2.width == width && matrix2.height == height) { for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { elements[i, j] += matrix2.GetElement(i, j); } } } else { Console.WriteLine("ERROR using NumericMatrix.Plus(NumericMatrix matrix)"); } }
//Метод, преобразующий матрицу к треугольному виду путем последовательного вычитания строк public static void ToTriangular(NumericMatrix matrix) { int j = 0; int i = 0; int h; double coeff = 0; for (; i < matrix.height - 1; i++) { if (matrix.GetElement(i, j) != 0) { matrix.DevideRow(i, matrix.GetElement(i, j)); } for (int k = i + 1; k < matrix.height; k++) { if (matrix.GetElement(i, j) == 0) { h = j; while (matrix.GetElement(i, h) == 0 && h < matrix.width) { h++; } if (h != matrix.width) { coeff = -(matrix.GetElement(k, j) / matrix.GetElement(i, h)); } } else { coeff = -(matrix.GetElement(k, j) / matrix.GetElement(i, j)); } matrix.SumRows(k, i, coeff); //Console.WriteLine(matrix.ToString()); } j++; } if (matrix.GetElement(i, j) != 0) { matrix.DevideRow(i, matrix.GetElement(i, j)); } //CheckRowsEquality(matrix); matrix.SetType(Type.TRIANGULAR); }
private static void TestMatrix() { NumericMatrix matrix = new NumericMatrix(2, 4); matrix.Fill(9); Console.WriteLine(matrix.ToString()); NumericMatrix matrix2 = new NumericMatrix(3); matrix2.ConsoleInput(); Console.WriteLine("Определитель:" + NumericMatrix.GetDeterminant(matrix2)); Console.WriteLine("Обратная матрица:"); Console.WriteLine(NumericMatrix.GetInverseMatrix(matrix2).ToString()); Console.ReadLine(); }
//Получение матрицы инцидентности по матрице смежности //Обеспечивает более полное описание графа и дает больше гибкости при работе с данным классом private void GetIncTable() { rel_num = 0; for (int i = 0; i < nodes_num; i++) { for (int j = 0; j < nodes_num; j++) { if (adj_table.GetElement(i, j) == 1) { rel_num++; } } } inc_table = new NumericMatrix(nodes_num, rel_num); int rel_counter = 0; for (int i = 0; i < nodes_num; i++) { for (int j = 0; j < nodes_num; j++) { if (adj_table.GetElement(i, j) == 1) { if (i == j) { inc_table.SetElement(i, rel_counter, 2); rel_counter++; } else { inc_table.SetElement(i, rel_counter, -1); inc_table.SetElement(j, rel_counter, 1); rel_counter++; } } if (rel_counter > rel_num) { Console.WriteLine("Warning"); } } } }
//Инициализация СЛАУ с клавиатуры //Расширенная матрица и матрица коэффициентов сразу же приводятся к треугольному виду; получаем их ранги public void ConsoleInput() { Console.WriteLine("Введите количество неизвестных:"); n_x = Convert.ToInt32(Console.ReadLine()); Console.WriteLine("Введите количество уравнений:"); n_equasions = Convert.ToInt32(Console.ReadLine()); Console.WriteLine("Заполните расширенную матрицу:"); extended_matrix = new NumericMatrix(n_equasions, n_x + 1); extended_matrix.ConsoleInput(); Console.WriteLine(extended_matrix.ToString()); matrix = new NumericMatrix(n_equasions, n_x); matrix = extended_matrix.GetArea(0, 0, n_x - 1, n_equasions - 1); extended_rank = NumericMatrix.GetRank(extended_matrix); rank = NumericMatrix.GetRank(matrix); single_solution = new List <double>(); general_solution = new NumericMatrix(n_x, n_x + 1); }
public NumericMatrix ConcatHorizontally(NumericMatrix first, List <double> second) { int newWidth = first.width + 1; NumericMatrix concatenatedMatrix = new NumericMatrix(first.height, newWidth); for (int i = 0; i < first.height; i++) { for (int j = 0; j < newWidth; j++) { if (j < first.width) { concatenatedMatrix.SetElement(i, j, first.GetElement(i, j)); } else { concatenatedMatrix.SetElement(i, j, second[i]); } } } return(concatenatedMatrix); }
//Метод, возвращающий определитель переданной матрицы public static double GetDeterminant(NumericMatrix matrix) { int size = matrix.size; if (size == 1) { return(matrix.GetElement(0, 0)); } else if (size == 2) { return(matrix.GetElement(0, 0) * matrix.GetElement(1, 1) - matrix.GetElement(0, 1) * matrix.GetElement(1, 0)); } else { double det = 0; for (int j = 0; j < size; j++) { det += Math.Pow(-1, 0 + j) * matrix.GetElement(0, j) * GetDeterminant(GetMinorMatrixOfElement(matrix, 0, j)); } return(det); } }
//Решение поставленной краевой задачи методом конечных разностей public NumericMatrix FiniteDifferencesMethod() { solutionsField = new NumericMatrix(stepsT, stepsX); solutionsField.Fill(0); NumericMatrix slaeCoeffs = new NumericMatrix(stepsT * stepsX, stepsT * stepsX + 1); int currentEquasion = 0; //Получить известные u (заданные начальными и граничными условиями) //и заполнить их коэффициенты un : 0,0,...,1([n]),0...=sigma(n*h) в итоговой //СЛАУ //Начальное условие u=phi1(x) - левая вертикаль сетки for (int k = 1; k < stepsT; k++) { solutionsField.SetElement(k, 0, phi1Fun((double)k * tau)); currentEquasion = k * stepsX; slaeCoeffs.SetElement(currentEquasion, currentEquasion, 1); slaeCoeffs.SetElement(currentEquasion + stepsX - 1, stepsT * stepsX, solutionsField.GetElement(k, 0)); } //Начальное условие u=phi2(x) - правая вертикаль сетки for (int k = 1; k < stepsT; k++) { solutionsField.SetElement(k, stepsT - 1, phi2Fun((double)k * h)); currentEquasion = k * stepsX; slaeCoeffs.SetElement(currentEquasion + stepsX - 1, currentEquasion + stepsX - 1, 1); slaeCoeffs.SetElement(currentEquasion + stepsX - 1, stepsT * stepsX, solutionsField.GetElement(k, stepsT - 1)); } //Начальное условие u=sigma1(x) - нижняя горизонталь сетки for (int k = 0; k < stepsX; k++) { solutionsField.SetElement(0, k, sigma1Fun((double)k * h)); currentEquasion = k % stepsX; slaeCoeffs.SetElement(currentEquasion, currentEquasion, 1); slaeCoeffs.SetElement(currentEquasion, stepsT * stepsX, solutionsField.GetElement(0, k)); } //Console.WriteLine(solutionsField.ToString()); //Явная схема - преобразована в линейное уравнение с известными коэффициентами //(2a^2/h^2-2/tau^2) * u[k,j]+ //+ (1/tau^2) * u[k-1,j]+ //+ (1/tau^2) * u[k+1,j]- //- (a^2/h^2) * u[k,j+1]- //- (a^2/h^2) * u[k,j-1]=0 // 0 + 0 // + + + // 0 + 0 //Заполнить коэффициенты для внутренней сетки (t = tDistance не трогаем) по явной схеме for (int k = 1; k < stepsT - 1; k++) { for (int j = 1; j < stepsX - 1; j++) { currentEquasion = k * stepsX + j; slaeCoeffs.SetElement(currentEquasion, stepsX * (k) + j, 2 * Math.Pow(paramA, 2) / Math.Pow(h, 2) - 2 / Math.Pow(tau, 2)); slaeCoeffs.SetElement(currentEquasion, stepsX * (k - 1) + j, 1 / Math.Pow(tau, 2)); slaeCoeffs.SetElement(currentEquasion, stepsX * (k + 1) + j, 1 / Math.Pow(tau, 2)); slaeCoeffs.SetElement(currentEquasion, stepsX * (k) + (j + 1), -1 * Math.Pow(paramA, 2) / Math.Pow(h, 2)); slaeCoeffs.SetElement(currentEquasion, stepsX * (k) + (j - 1), -1 * Math.Pow(paramA, 2) / Math.Pow(h, 2)); } } //Console.WriteLine(solutionsField.ToString()); //Неявная схема - преобразована в линейное уравнение с известными коэффициентами //(1/tau^2 + 2a^2/h^2)*u[k+1,j] - //- (2/tau^2) * u[k,j] + //+ (1/tau^2) * u[k-1,j] - //- (a^2/h^2) * u[k+1, j+1] - //- (a^2/h^2) * u[k+1, j-1] = 0 // + + + // 0 + 0 // 0 + 0 //Заполнить коэффициенты на stepsT*t по неявной схеме int kT = stepsT - 1; for (int j = 1; j < stepsX - 1; j++) { currentEquasion = kT * stepsX + j; slaeCoeffs.SetElement(currentEquasion, stepsX * (kT) + j, 1 / Math.Pow(tau, 2) + 2 * Math.Pow(paramA, 2) / Math.Pow(h, 2)); slaeCoeffs.SetElement(currentEquasion, stepsX * (kT - 1) + j, (-2) / Math.Pow(tau, 2)); slaeCoeffs.SetElement(currentEquasion, stepsX * (kT - 2) + j, 1 / Math.Pow(tau, 2)); slaeCoeffs.SetElement(currentEquasion, stepsX * (kT - 1) + (j + 1), -1 * Math.Pow(paramA, 2) / Math.Pow(h, 2)); slaeCoeffs.SetElement(currentEquasion, stepsX * (kT) + (j - 1), -1 * Math.Pow(paramA, 2) / Math.Pow(h, 2)); } solution = new SLAE(slaeCoeffs); //Console.WriteLine(solution.ToString()); solution.BuildSolution(); if (!solution.isGeneralSolutionExists()) { List <double> tempList = solution.GetSingleSolution(); //Printer.PrintList(tempList, "TEMP_LIST"); int i = 0; foreach (double sol in tempList) { //Console.WriteLine((i / stepsX) + " : " + (i % stepsX)); solutionsField.SetElement(i / stepsX, i % stepsX, sol); i++; } return(solutionsField); } else { return(solutionsField); } }