diff --git a/Sources/AngouriMath/AngouriMath/Core/Multithreading/MultithreadingFunctional.cs b/Sources/AngouriMath/AngouriMath/Core/Multithreading/MultithreadingFunctional.cs index 5afe5e0d3..e8081b93f 100644 --- a/Sources/AngouriMath/AngouriMath/Core/Multithreading/MultithreadingFunctional.cs +++ b/Sources/AngouriMath/AngouriMath/Core/Multithreading/MultithreadingFunctional.cs @@ -23,7 +23,13 @@ internal static void ExitIfCancelled() { var token = globalCancellationToken.Value; if (token is { } tok) - tok.ThrowIfCancellationRequested(); + { + if (tok.IsCancellationRequested) + { + globalCancellationToken.Value = null; + throw new System.OperationCanceledException(); + } + } } } } diff --git a/Sources/AngouriMath/AngouriMath/Functions/Continuous/Solvers/EquationSolver.cs b/Sources/AngouriMath/AngouriMath/Functions/Continuous/Solvers/EquationSolver.cs index f05e33d41..13faffd7c 100644 --- a/Sources/AngouriMath/AngouriMath/Functions/Continuous/Solvers/EquationSolver.cs +++ b/Sources/AngouriMath/AngouriMath/Functions/Continuous/Solvers/EquationSolver.cs @@ -82,7 +82,12 @@ internal static List> InSolveSystem(List equations, ReadOnl : new(); var result = new List>(); var replacements = new Dictionary(); + equations = + equations + .Select(eq => eq.SimplifyTimeConstrained(msLimit: 500) ?? eq.InnerSimplified) + .ToList(); for (int i = 0; i < equations.Count; i++) + { if (equations[i].ContainsNode(var)) { var solutionsOverVar = equations[i].SolveEquation(var).InnerSimplified; @@ -101,6 +106,7 @@ internal static List> InSolveSystem(List equations, ReadOnl } break; } + } return result; } } diff --git a/Sources/AngouriMath/AngouriMath/Functions/Evaluation/Evaluation.Definition.cs b/Sources/AngouriMath/AngouriMath/Functions/Evaluation/Evaluation.Definition.cs index e3fcabcea..9c6197aa9 100644 --- a/Sources/AngouriMath/AngouriMath/Functions/Evaluation/Evaluation.Definition.cs +++ b/Sources/AngouriMath/AngouriMath/Functions/Evaluation/Evaluation.Definition.cs @@ -212,6 +212,63 @@ public Entity Factorize(int level = 2) => level <= 1 /// public Entity Simplify(int level = 2) => Simplificator.Simplify(this, level); + /// + /// Simplifies an equation ( e.g. (x - y) * (x + y) -> x^2 - y^2, but 3 * x + y * x = (3 + y) * x ) + /// with a time constraint. + /// + /// + /// Increase this argument if you think the equation should be simplified better + /// + /// + /// Specifies the budget time. If simplication takes longer, it will automatically + /// stop and return null. + /// + /// + /// + /// using System; + /// using static AngouriMath.MathS; + /// + /// var (x, y, a) = Var("x", "y", "a"); + /// var expr = Sin(x) + y + a; + /// Console.WriteLine(expr); + /// Console.WriteLine(expr.Simplify()); + /// Console.WriteLine("---------------------"); + /// var expr1 = Sin(x - 3) / Tan(x - 3) + Sec(Sqrt(y)) * Cosec(Sqrt(y)); + /// Console.WriteLine(expr1); + /// Console.WriteLine(expr1.Simplify()); + /// Console.WriteLine("---------------------"); + /// var expr2 = Sin(pi / 3) * 2; + /// Console.WriteLine(expr2); + /// Console.WriteLine(expr2.Simplify()); + /// Console.WriteLine("---------------------"); + /// var expr3 = (Pow(x, 3) + 3 * Sqr(x) * y + 3 * x * Sqr(y) + Pow(y, 3)) / (x + y); + /// Console.WriteLine(expr3); + /// Console.WriteLine(expr3.Simplify()); + /// Console.WriteLine("---------------------"); + /// var expr4 = Derivative(Sin(Sqr(x * y) + y * x), x); + /// Console.WriteLine(expr4); + /// Console.WriteLine(expr4.Simplify()); + /// + /// Prints + /// + /// sin(x) + y + a + /// sin(x) + a + y + /// --------------------- + /// sin(x - 3) / tan(x - 3) + sec(sqrt(y)) * csc(sqrt(y)) + /// 2 * csc(2 * sqrt(y)) + cos(x - 3) + /// --------------------- + /// sin(pi / 3) * 2 + /// sqrt(3) + /// --------------------- + /// (x ^ 3 + 3 * x ^ 2 * y + 3 * x * y ^ 2 + y ^ 3) / (x + y) + /// x ^ 2 + 2 * x * y + y ^ 2 + /// --------------------- + /// derivative(sin((x * y) ^ 2 + y * x), x) + /// cos((x * y) ^ 2 + x * y) * (2 * x * y ^ 2 + y) + /// + /// + public Entity? SimplifyTimeConstrained(int msLimit = 1000, int level = 2) => Simplificator.SimplifyTimeConstrained(this, level, msLimit); + /// Finds all alternative forms of an expression sorted by their complexity /// /// diff --git a/Sources/AngouriMath/AngouriMath/Functions/Simplification/Simplificator.cs b/Sources/AngouriMath/AngouriMath/Functions/Simplification/Simplificator.cs index 6ac1100cb..b0d9b4854 100644 --- a/Sources/AngouriMath/AngouriMath/Functions/Simplification/Simplificator.cs +++ b/Sources/AngouriMath/AngouriMath/Functions/Simplification/Simplificator.cs @@ -8,6 +8,7 @@ using System; using AngouriMath.Core.Multithreading; using PeterO.Numbers; +using System.Threading; namespace AngouriMath.Functions { @@ -22,6 +23,24 @@ internal static Entity PickSimplest(Entity one, Entity another) /// See more details in internal static Entity Simplify(Entity expr, int level) => Alternate(expr, level).First().InnerSimplified; + internal static Entity? SimplifyTimeConstrained(Entity expr, int level, int msCount) + { + var cancellationTokenSource = new CancellationTokenSource(); + cancellationTokenSource.CancelAfter(msCount); + MathS.Multithreading.SetLocalCancellationToken( + cancellationTokenSource.Token); + try + { + var res = Simplify(expr, level); + MathS.Multithreading.SetLocalCancellationToken(CancellationToken.None); + return res; + } + catch (OperationCanceledException) + { + return null; + } + } + internal static Entity SimplifyChildren(Entity expr) { return expr.Replace(Patterns.InvertNegativePowers) diff --git a/Sources/Samples/Samples/Playground.csproj b/Sources/Samples/Samples/Playground.csproj index 9f0b5c30c..866024255 100644 --- a/Sources/Samples/Samples/Playground.csproj +++ b/Sources/Samples/Samples/Playground.csproj @@ -2,7 +2,7 @@ Exe - net6.0 + net7.0 preview enable diff --git a/Sources/Samples/Samples/Program.cs b/Sources/Samples/Samples/Program.cs index 96e79f685..faa4433b0 100644 --- a/Sources/Samples/Samples/Program.cs +++ b/Sources/Samples/Samples/Program.cs @@ -8,13 +8,12 @@ using System; using AngouriMath.Core; using static AngouriMath.MathS; +using AngouriMath; -var expr = Sqrt(-1); -Console.WriteLine(expr); -Console.WriteLine(expr.Codomain); -Console.WriteLine(expr.Evaled); -Console.WriteLine("------------------------------------"); -var newExpr = expr.WithCodomain(Domain.Real); -Console.WriteLine(newExpr); -Console.WriteLine(newExpr.Codomain); -Console.WriteLine(newExpr.Evaled); \ No newline at end of file +var system = MathS.Equations( + "2 * x_1 * (-66) - 6 * x_2 + 24 * x_3 - 12 * x_4 + 270", + "-6 * x_1 - 2 * x_2 * 74 - 8 * x_3 + 4 * x_4 - 440", + "24 * x_1 - 8 * x_2 - 2 * x_3 * 59 - 16 * x_4 - 190", + "-12 * x_1 + 4 * x_2 - 16 * x_3 - 2 * x_4 * 71 + 20" + ); +Console.WriteLine(system.Solve("x_1", "x_2", "x_3", "x_4")); \ No newline at end of file diff --git a/Sources/Tests/UnitTests/Algebra/SolveTest/SolveSystem.cs b/Sources/Tests/UnitTests/Algebra/SolveTest/SolveSystem.cs index cee23809f..9c6e562b7 100644 --- a/Sources/Tests/UnitTests/Algebra/SolveTest/SolveSystem.cs +++ b/Sources/Tests/UnitTests/Algebra/SolveTest/SolveSystem.cs @@ -102,5 +102,13 @@ public void EquationWithDivisionIsSolved() => AssertSystemSolvable(new Entity[] "x2 + y", "y - x - 3" }, new Entity.Variable[] { "x", "y" }, 2); + + [Fact] + public void EquationLinear() => AssertSystemSolvable(new Entity [] { + "2 * x_1 * (-66) - 6 * x_2 + 24 * x_3 - 12 * x_4 + 270", + "-6 * x_1 - 2 * x_2 * 74 - 8 * x_3 + 4 * x_4 - 440", + "24 * x_1 - 8 * x_2 - 2 * x_3 * 59 - 16 * x_4 - 190", + "-12 * x_1 + 4 * x_2 - 16 * x_3 - 2 * x_4 * 71 + 20" + }, new Entity.Variable[] { "x", "y" }, 1); } } diff --git a/Sources/Tests/UnitTests/UnitTests.csproj b/Sources/Tests/UnitTests/UnitTests.csproj index 9b4e43dc3..17fcaf399 100644 --- a/Sources/Tests/UnitTests/UnitTests.csproj +++ b/Sources/Tests/UnitTests/UnitTests.csproj @@ -1,7 +1,7 @@  - net6.0 + net7.0 false AnyCPU;x64