From a6e239883203627a9a247741e0e38704be45668f Mon Sep 17 00:00:00 2001 From: WhiteBlackGoose Date: Wed, 16 Nov 2022 14:05:46 +0300 Subject: [PATCH 1/4] Working on amcli info --- Program.cs | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) diff --git a/Program.cs b/Program.cs index fad6b77..a284260 100644 --- a/Program.cs +++ b/Program.cs @@ -18,11 +18,13 @@ using AngouriMath.Extensions; using HonkSharp; using HonkSharp.Functional; +using PeterO.Numbers; var cliArgs = System.Environment.GetCommandLineArgs(); var reader = new ArgReader(cliArgs); - +var prec = GetEnv("AMCLI_PRECISION", 100); +MathS.Settings.DecimalPrecisionContext.Set(new EContext(prec, ERounding.HalfUp, -prec, 10 * prec, false)); Entity expr; Entity.Variable v; string res; @@ -170,6 +172,13 @@ is equivalent to Here the result of `echo` is substituted instead of the second argument of `amcli sub`, not the last one. + SETTINGS + + All settings are set using environment variables. + + AMCLI_PRECISION - precision/number of digits in decimal numbers. + Default - 100. + OTHER You can bind amcli to @ using aliases. On Unix-like operating systems, @@ -228,11 +237,82 @@ Here the result of `echo` is substituted instead of the second argument Console.WriteLine(expr.Substitute(v, withWhat)); break; + case "info": + expr = reader.Next(); + var splitter = new string('-', 20); + Console.WriteLine($"expr: {expr}"); + Console.WriteLine(splitter); + Console.WriteLine($"vars: {expr.Vars.ToLList()}"); + Console.WriteLine(splitter); + var vars = expr.Vars.ToArray(); + foreach (var vx in vars) + { + Console.Write($"diff over {vx}: "); + Console.WriteLine(expr.Differentiate(vx).InnerSimplified); + Console.WriteLine(splitter); + } + foreach (var vx in vars) + { + Console.Write($"roots over {vx}: "); + Console.WriteLine(expr.Solve(vx).InnerSimplified); + Console.WriteLine(splitter); + } + + var diffs = new List(); + foreach (var vx in vars) + diffs.add(expr.Differentiate(vx).InnerSimplified); + + var system = MathS.Equations(diff); + var sols = system.Solve(expr.Vars); + if (sols is null) + { + Console.WriteLine("amcli wasn't able to find any extremas"); + break; + } + + var diffMatrix = new Entity.Matrix(dims => + expr + .Differentiate(vars[dims[0]]) + .Differentiate(vars[dims[1]]) + .InnerSimplified, + vars.Length, + vars.Length); + + foreach (var (i, sol) in sols.Enumerate()) + { + var exprToSub = expr; + var diffMatToSub = diffMatrix; + foreach (var (vr, val) in sol.Zip(vars)) + { + exprToSub = exprToSub.Substitute(vr, val); + diffMatToSub = diffMatToSub.Substitute(vr, val); + } + var fValue = exprToSub.Evaled; + var det = diffMatToSub.Evaled.Determinant.EvalNumerical(); + Console.WriteLine($"Extrema #{i}:"); + Console.WriteLine($"Point: {sol}"); + Console.WriteLine($"Value: {fValue}"); + Console.WriteLine($"Hessian det: {det}"); + } + + break; + default: Console.WriteLine($"Unrecognized command `{cmd}`"); break; } +static T GetEnv(string name, T def) +{ + if (Environment.GetEnvironmentVariable(name) is not string value) + return def; + if (typeof(T) == typeof(int)) + return (T)(object)int.Parse(value); + if (typeof(T) == typeof(string)) + return (T)(object)value; + throw new(); +} + public sealed class ArgReader { private readonly string[] args; @@ -252,3 +332,4 @@ public string Next() return Console.ReadLine()!; } } + From 266e2bc23be7ed28b55f1b9aee409f0e4e5433d4 Mon Sep 17 00:00:00 2001 From: WhiteBlackGoose Date: Wed, 16 Nov 2022 21:58:56 +0300 Subject: [PATCH 2/4] extrema analysis --- CLI.csproj | 1 - Program.cs | 124 ++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 90 insertions(+), 35 deletions(-) diff --git a/CLI.csproj b/CLI.csproj index 14e8666..4ea0774 100644 --- a/CLI.csproj +++ b/CLI.csproj @@ -5,7 +5,6 @@ net7.0 enable enable - true true true diff --git a/Program.cs b/Program.cs index a284260..f50bdca 100644 --- a/Program.cs +++ b/Program.cs @@ -16,12 +16,13 @@ using AngouriMath; using AngouriMath.Extensions; -using HonkSharp; using HonkSharp.Functional; +using HonkSharp.Fluency; using PeterO.Numbers; var cliArgs = System.Environment.GetCommandLineArgs(); -var reader = new ArgReader(cliArgs); +IArgReader reader = new ArgReader(cliArgs); +// IArgReader reader = new ArgReader(new [] { "", "info", "x2 + 4y2 + y4 + x + (z - 3)^2 - 1" }); var prec = GetEnv("AMCLI_PRECISION", 100); MathS.Settings.DecimalPrecisionContext.Set(new EContext(prec, ERounding.HalfUp, -prec, 10 * prec, false)); @@ -254,45 +255,96 @@ Here the result of `echo` is substituted instead of the second argument foreach (var vx in vars) { Console.Write($"roots over {vx}: "); - Console.WriteLine(expr.Solve(vx).InnerSimplified); + Console.WriteLine(expr.Equalizes(0).Solve(vx).InnerSimplified); Console.WriteLine(splitter); } - - var diffs = new List(); - foreach (var vx in vars) - diffs.add(expr.Differentiate(vx).InnerSimplified); - - var system = MathS.Equations(diff); - var sols = system.Solve(expr.Vars); - if (sols is null) + if (vars.Length is 1) { - Console.WriteLine("amcli wasn't able to find any extremas"); - break; + var fx = expr.Differentiate(vars[0]); + var crit = fx.Equalizes(0).Solve(vars[0]); + if (crit is not Entity.Set.FiniteSet fins) + goto notOneVar; + var fxx = fx.Differentiate(vars[0]); + foreach (var (i, sol) in fins.Enumerate()) + { + Console.WriteLine($"Extremum #{i}"); + Console.WriteLine($"Point: {sol}"); + Console.WriteLine($"Value: {expr.Substitute(vars[0], sol).Evaled}"); + var fxxValue = fxx.Substitute(vars[0], sol).EvalNumerical(); + Console.WriteLine($"2nd derivative value: {fxxValue}"); + Console.Write("Type of extremum: "); + if (fxxValue is not Entity.Number.Real rVal) + continue; + if (rVal == 0) + Console.WriteLine("Saddle"); + if ((double)rVal > 0.0) + Console.WriteLine("Minimum"); + if ((double)rVal < 0.0) + Console.WriteLine("Maximum"); + Console.WriteLine(); + } } + notOneVar: + if (vars.Length is > 1) + { + var diffs = new List(); + foreach (var vx in vars) + diffs.Add(expr.Differentiate(vx).InnerSimplified); - var diffMatrix = new Entity.Matrix(dims => - expr - .Differentiate(vars[dims[0]]) - .Differentiate(vars[dims[1]]) - .InnerSimplified, - vars.Length, - vars.Length); + var system = MathS.Equations((IEnumerable)diffs); + var sols2 = system.Solve(vars); + if (sols2 is null) + { + Console.WriteLine("amcli wasn't able to find any extremas"); + break; + } - foreach (var (i, sol) in sols.Enumerate()) - { - var exprToSub = expr; - var diffMatToSub = diffMatrix; - foreach (var (vr, val) in sol.Zip(vars)) + var hessian = new Entity.Matrix(dims => + expr + .Differentiate(vars[dims[0]]) + .Differentiate(vars[dims[1]]) + .InnerSimplified, + vars.Length, + vars.Length); + + foreach (var (i, sol) in sols2.Enumerate()) { - exprToSub = exprToSub.Substitute(vr, val); - diffMatToSub = diffMatToSub.Substitute(vr, val); + var exprToSub = expr; + Entity hessianToSub = hessian; + var msol = ((Entity.Matrix)sol).T; + foreach (var (val, vr) in msol.Zip(vars)) + { + exprToSub = exprToSub.Substitute(vr, val); + hessianToSub = hessianToSub.Substitute(vr, val); + } + var fValue = exprToSub.Evaled; + var hessienEvaled = (Entity.Matrix)hessianToSub.Evaled; + var det = hessienEvaled.Determinant!.EvalNumerical(); + Console.WriteLine($"Extrema #{i}:"); + Console.WriteLine($"Point: {msol.T}"); + Console.WriteLine($"Value: {fValue}"); + Console.WriteLine($"Hessien:"); + Console.WriteLine(hessienEvaled.ToString(multilineFormat: true)); + + var uniqueVar = MathS.Var("lambda_quackfrog"); + var eigenMatrix = (Entity.Matrix)(hessianToSub - MathS.IdentityMatrix(hessian.RowCount) * uniqueVar).InnerSimplified; + var eigenDet = eigenMatrix.Determinant!; + var eigenValues = eigenDet.Equalizes(0).Solve(uniqueVar).Evaled; + if (eigenValues is Entity.Set.FiniteSet eigens) + { + Console.WriteLine($"Eigen values of hessian: {eigens}"); + if (eigens.All(val => val.EvalNumerical() is Entity.Number.Real r1 && r1.IsPositive)) + Console.WriteLine("Type of extremum: Minimum"); + else if (eigens.All(val => val.EvalNumerical() is Entity.Number.Real r2 && r2.IsNegative)) + Console.WriteLine("Type of extremum: Negative"); + else if (eigens.All(val => val.EvalNumerical() is Entity.Number.Real r3 && r3.IsNegative || val.EvalNumerical() is Entity.Number.Real r4 && r4.IsPositive)) + Console.WriteLine("Type of extremum: Saddle"); + else + Console.WriteLine("Cannot detect type of extremum"); + } + Console.WriteLine(); + Console.WriteLine(); } - var fValue = exprToSub.Evaled; - var det = diffMatToSub.Evaled.Determinant.EvalNumerical(); - Console.WriteLine($"Extrema #{i}:"); - Console.WriteLine($"Point: {sol}"); - Console.WriteLine($"Value: {fValue}"); - Console.WriteLine($"Hessian det: {det}"); } break; @@ -313,7 +365,7 @@ static T GetEnv(string name, T def) throw new(); } -public sealed class ArgReader +public sealed class ArgReader : IArgReader { private readonly string[] args; private int curr = 1; @@ -333,3 +385,7 @@ public string Next() } } +public interface IArgReader +{ + public string Next(); +} From 557e83efd30517bb1c1ebeb525d493dd6258ed4a Mon Sep 17 00:00:00 2001 From: WhiteBlackGoose Date: Thu, 17 Nov 2022 16:19:08 +0300 Subject: [PATCH 3/4] Improved, WIP --- .gitmodules | 3 +++ AngouriMath | 1 + CLI.csproj | 3 ++- Program.cs | 30 ++++++++++++++++++------------ 4 files changed, 24 insertions(+), 13 deletions(-) create mode 100644 .gitmodules create mode 160000 AngouriMath diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..e9db78e --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "AngouriMath"] + path = AngouriMath + url = git@github.com:asc-community/AngouriMath.git diff --git a/AngouriMath b/AngouriMath new file mode 160000 index 0000000..c58bb0e --- /dev/null +++ b/AngouriMath @@ -0,0 +1 @@ +Subproject commit c58bb0e94feccfdefc5d2db9760ee6797599ce7e diff --git a/CLI.csproj b/CLI.csproj index 4ea0774..0fcae01 100644 --- a/CLI.csproj +++ b/CLI.csproj @@ -16,8 +16,9 @@ - + + diff --git a/Program.cs b/Program.cs index f50bdca..a9c55fa 100644 --- a/Program.cs +++ b/Program.cs @@ -22,9 +22,8 @@ var cliArgs = System.Environment.GetCommandLineArgs(); IArgReader reader = new ArgReader(cliArgs); -// IArgReader reader = new ArgReader(new [] { "", "info", "x2 + 4y2 + y4 + x + (z - 3)^2 - 1" }); - -var prec = GetEnv("AMCLI_PRECISION", 100); +// IArgReader reader = new ArgReader(new [] { "", "info", "-66 x_1 2 - 6 x_1 x_2 + 24 x_1 x_3 - 12 x_1 x_4 + 270 x_1 - 74 x_2 2 - 8 x_2 x_3 + 4 x_2 x_4 - 440 x_2 - 59 x_3 2 - 16 x_3 x_4 - 190 x_3 - 71 x_4 2 + 20 x_4" }); +var prec = GetEnv("AMCLI_PRECISION", 20); MathS.Settings.DecimalPrecisionContext.Set(new EContext(prec, ERounding.HalfUp, -prec, 10 * prec, false)); Entity expr; Entity.Variable v; @@ -292,6 +291,8 @@ Here the result of `echo` is substituted instead of the second argument diffs.Add(expr.Differentiate(vx).InnerSimplified); var system = MathS.Equations((IEnumerable)diffs); + Console.WriteLine("First order condition:"); + Console.WriteLine(system); var sols2 = system.Solve(vars); if (sols2 is null) { @@ -329,18 +330,23 @@ Here the result of `echo` is substituted instead of the second argument var uniqueVar = MathS.Var("lambda_quackfrog"); var eigenMatrix = (Entity.Matrix)(hessianToSub - MathS.IdentityMatrix(hessian.RowCount) * uniqueVar).InnerSimplified; var eigenDet = eigenMatrix.Determinant!; - var eigenValues = eigenDet.Equalizes(0).Solve(uniqueVar).Evaled; + var eigenValues = eigenDet.InnerSimplified.Equalizes(0).Solve(uniqueVar).Evaled; if (eigenValues is Entity.Set.FiniteSet eigens) { - Console.WriteLine($"Eigen values of hessian: {eigens}"); - if (eigens.All(val => val.EvalNumerical() is Entity.Number.Real r1 && r1.IsPositive)) - Console.WriteLine("Type of extremum: Minimum"); - else if (eigens.All(val => val.EvalNumerical() is Entity.Number.Real r2 && r2.IsNegative)) - Console.WriteLine("Type of extremum: Negative"); - else if (eigens.All(val => val.EvalNumerical() is Entity.Number.Real r3 && r3.IsNegative || val.EvalNumerical() is Entity.Number.Real r4 && r4.IsPositive)) - Console.WriteLine("Type of extremum: Saddle"); + if (eigens.Count is 0) + Console.WriteLine("amcli wasn't able to find eigen values and the type of extremum"); else - Console.WriteLine("Cannot detect type of extremum"); + { + Console.WriteLine($"Eigen values of hessian: {eigens}"); + if (eigens.All(val => val.EvalNumerical() is Entity.Number.Real r1 && r1.IsPositive)) + Console.WriteLine("Type of extremum: Minimum"); + else if (eigens.All(val => val.EvalNumerical() is Entity.Number.Real r2 && r2.IsNegative)) + Console.WriteLine("Type of extremum: Negative"); + else if (eigens.All(val => val.EvalNumerical() is Entity.Number.Real r3 && r3.IsNegative || val.EvalNumerical() is Entity.Number.Real r4 && r4.IsPositive)) + Console.WriteLine("Type of extremum: Saddle"); + else + Console.WriteLine("Cannot detect type of extremum"); + } } Console.WriteLine(); Console.WriteLine(); From b63d50583497dd484e918ae8b02ed5334b23c267 Mon Sep 17 00:00:00 2001 From: WhiteBlackGoose Date: Fri, 18 Nov 2022 16:59:57 +0300 Subject: [PATCH 4/4] upd --- AngouriMath | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AngouriMath b/AngouriMath index c58bb0e..18c127d 160000 --- a/AngouriMath +++ b/AngouriMath @@ -1 +1 @@ -Subproject commit c58bb0e94feccfdefc5d2db9760ee6797599ce7e +Subproject commit 18c127d7c576624d063aee7df95a86c1995c1432