/// <summary> /// Точка входа в программу. /// </summary> /// <param name="args">Аргументы командной строки.</param> public static void Main(string[] args) { if (args.Length == 0) { Console.WriteLine("Run application with --help"); Environment.Exit(-1); } var parser = new Parser(with => with.HelpWriter = null); var parserResult = parser.ParseArguments <CommandLineOptions>(args); parserResult .WithParsed(options => commandLineOptions = options) .WithNotParsed(errs => DisplayHelp(parserResult)); if (args.Any(a => a.Contains("help") || a.Contains("--version"))) { Environment.Exit(-1); } Console.WriteLine("#### Program started ####\n"); var matrix = SquareMatrixHelper.SquareMatrix(commandLineOptions.SquareMatrixEntries.ToArray()); var x0 = new ColumnVector(commandLineOptions.InitVector.ToArray()); var t0 = commandLineOptions.InitTime.ToList()[0]; var t1 = commandLineOptions.InitTime.ToList()[1]; var n = commandLineOptions.N; var frames = commandLineOptions.Frames; var dt = (t1 - t0) / frames; PlotByNMath(frames, matrix, x0, n, t0, dt); // PlotByPython(frames, matrix, x0, n, t0, dt); Console.WriteLine("#### Program finished ####"); }
/// <summary> /// Вычислить значения опорной функции для множества достижимости. /// </summary> /// <param name="matrix">Исходная матрица</param> /// <param name="x0">Начальное положение.</param> /// <param name="n">Количество точек для расчёта.</param> /// <param name="t0">Начальный момент времени.</param> /// <param name="t">Конечный момент времени.</param> /// <param name="psiFunc">Фунция для вычисления значений векторов направлений.</param> /// <param name="psi">Массив векторов.</param> /// <param name="supportingFunctionValues">Массив значений опорной функции множества достижимости.</param> private static void CalculateSupportingFunctionOfReachableSet(SquareMatrix matrix, ColumnVector x0, int n, double t0, double t, Func <double, ColumnVector> psiFunc, out ColumnVector[] psi, out double[] supportingFunctionValues) { supportingFunctionValues = new double[n]; var dx = 2 * PI / n; psi = new ColumnVector[n]; for (var i = 0; i < n; i++) { psi[i] = psiFunc(i * dx); } var expMFunc = SquareMatrixHelper.ExpM(matrix); for (var i = 0; i < n; i++) { supportingFunctionValues[i] = VectorHelper.Prod(expMFunc(t - t0) * x0, psi[i]) + Integrate(expMFunc, psi[i], t0, t, n); } }
/// <summary> /// Получить собственные (и присоединённые) векторы матрицы. /// </summary> /// <param name="originMatrix">Входная матрица.</param> /// <returns>Матрица, состоящая из комплексных чисел.</returns> public static SquareMatrix GetEigenvectors(this SquareMatrix originMatrix) { var eigenvalues = originMatrix.Eigenvalues(); if (eigenvalues.Any(v => v.Im != 0)) { throw new ComplexEigenvaluesException("Комплексные собственные значения не поддерживаются."); } const double max = 1.0; const double min = 0.0; var eigenvectors = new SquareMatrix(originMatrix.Dimension); var identityMatrix = SquareMatrixHelper.GetIdentityMatrix(originMatrix.Dimension); // Два различных собственных значения. if (!(eigenvalues[0] - eigenvalues[1]).Re.IsZero()) { var eigenSol1 = originMatrix - eigenvalues[0].Re * identityMatrix; var eigenSol2 = originMatrix - eigenvalues[1].Re * identityMatrix; if (!eigenSol1.Row(0).IsZero()) { eigenvectors = new SquareMatrix(new [, ] { { eigenSol1[0, 1], eigenSol2[0, 1] }, { -eigenSol1[0, 0], -eigenSol2[0, 0] } }); } else { eigenvectors = new SquareMatrix(new [, ] { { eigenSol1[1, 1], eigenSol2[0, 1] }, { -eigenSol1[1, 0], -eigenSol2[0, 0] } }); } } else if ((eigenvalues[0] - eigenvalues[1]).Re.IsZero()) { while (true) { if ((originMatrix - eigenvalues[1].Re * identityMatrix).GetRank() != 0) { var possibleAttachedVectorEntries = GetRandomColumnVector(max, min); var possibleAttachedVector = new ColumnVector(possibleAttachedVectorEntries); var possibleEigenvector = (originMatrix - eigenvalues[1].Re * identityMatrix) * possibleAttachedVector; if (originMatrix * possibleAttachedVector == eigenvalues[1].Re * possibleAttachedVector) { continue; } if (possibleEigenvector.OneNorm().IsZero()) { continue; } if (((originMatrix - eigenvalues[0].Re * identityMatrix) * possibleEigenvector).OneNorm().IsZero()) { eigenvectors = new SquareMatrix(new [, ] { { possibleEigenvector[0], possibleAttachedVector[0] }, { possibleEigenvector[1], possibleAttachedVector[1] } }); break; } } eigenvectors = new SquareMatrix(new [, ] { { 1.0, 0.0 }, { 0.0, 1.0 } }); break; } } return(eigenvectors); }
/// <summary> /// Получить геометрическую кратность собственного значения матрицы. /// </summary> /// <param name="originMatrix">Исходная матрица.</param> /// <param name="eigenvalue">Собственное значение.</param> /// <returns></returns> public static int GetGeometricMultiplicity(this SquareMatrix originMatrix, double eigenvalue) { var identityMatrix = SquareMatrixHelper.GetIdentityMatrix(originMatrix.Dimension); return(originMatrix.Dimension - (originMatrix - eigenvalue * identityMatrix).GetRank()); }