internal static Entity SimplifyChildren(Entity expr) { return(expr.Replace(Patterns.InvertNegativePowers) .Replace(Patterns.InvertNegativeMultipliers).Replace( Patterns.SortRules(TreeAnalyzer.SortLevel.HIGH_LEVEL) ) .InnerSimplified.Replace(Patterns.CommonRules).InnerSimplified); }
/// <summary>Finds all alternative forms of an expression</summary> internal static IEnumerable <Entity> Alternate(Entity src, int level) { if (src is Number or Variable or Entity.Boolean) { return new[] { src } } ; var stage1 = src.InnerSimplified; if (stage1 is Number or Variable or Entity.Boolean) { return new[] { stage1 } } ; // List of criteria for expr's complexity var history = new SortedDictionary <int, HashSet <Entity> >(); void AddHistory(Entity expr) { void __IterAddHistory(Entity expr) { static int CountExpressionComplexity(Entity expr) => MathS.Settings.ComplexityCriteria.Value(expr); var refexpr = expr.Replace(Patterns.SortRules(TreeAnalyzer.SortLevel.HIGH_LEVEL)).InnerSimplified; var compl1 = CountExpressionComplexity(refexpr); var compl2 = CountExpressionComplexity(expr); var n = compl1 > compl2 ? expr : refexpr; var ncompl = Math.Min(compl2, compl1); if (history.TryGetValue(ncompl, out var ncomplList)) { ncomplList.Add(n); } else { history[ncompl] = new HashSet <Entity> { n } }; } __IterAddHistory(expr); __IterAddHistory(expr.Replace(Patterns.InvertNegativePowers)); } AddHistory(stage1); var res = stage1; for (int i = 0; i < Math.Abs(level); i++) { res = res.Replace(Patterns.SortRules(i switch { 1 => TreeAnalyzer.SortLevel.MIDDLE_LEVEL, 2 => TreeAnalyzer.SortLevel.LOW_LEVEL, _ => TreeAnalyzer.SortLevel.HIGH_LEVEL })).InnerSimplified;
/// <summary>Finds all alternative forms of an expression</summary> internal static IEnumerable <Entity> Alternate(Entity src, int level) { if (src is FiniteSet ss) { return new[] { ss.Apply(ent => ent.Simplify()).InnerSimplified } } ; if (src is Number or Variable or Entity.Boolean) { return new[] { src } } ; var stage1 = src.InnerSimplified; if (stage1 is Number or Variable or Entity.Boolean) { return new[] { stage1 } } ; // List of criteria for expr's complexity var history = new SortedDictionary <double, HashSet <Entity> >(); void AddHistory(Entity expr) { void __IterAddHistory(Entity expr) { var refexpr = expr.Replace(Patterns.SortRules(TreeAnalyzer.SortLevel.HIGH_LEVEL)).InnerSimplified; var compl1 = refexpr.SimplifiedRate; var compl2 = expr.SimplifiedRate; var n = compl1 > compl2 ? expr : refexpr; var ncompl = Math.Min(compl2, compl1); if (history.TryGetValue(ncompl, out var ncomplList)) { ncomplList.Add(n); } else { history[ncompl] = new HashSet <Entity> { n } }; } __IterAddHistory(expr); __IterAddHistory(expr.Replace(Patterns.InvertNegativePowers)); MultithreadingFunctional.ExitIfCancelled(); } AddHistory(stage1); var res = stage1; for (int i = 0; i < Math.Abs(level); i++) { res = res.Replace(Patterns.SortRules(i switch { 1 => TreeAnalyzer.SortLevel.MIDDLE_LEVEL, 2 => TreeAnalyzer.SortLevel.LOW_LEVEL, _ => TreeAnalyzer.SortLevel.HIGH_LEVEL })).InnerSimplified; if (res.Nodes.Any(child => child is Powf)) { AddHistory(res = res.Replace(Patterns.PowerRules).InnerSimplified); } AddHistory(res = SimplifyChildren(res)); AddHistory(res = res.Replace(Patterns.InvertNegativePowers).Replace(Patterns.DivisionPreparingRules).InnerSimplified); AddHistory(res = res.Replace(Patterns.PolynomialLongDivision).InnerSimplified); if (res.Nodes.Any(child => child is TrigonometricFunction)) { var res1 = res.Replace(Patterns.ExpandTrigonometricRules).InnerSimplified; AddHistory(res = res.Replace(Patterns.TrigonometricRules).Replace(Patterns.CommonRules).InnerSimplified); AddHistory(res1); res = PickSimplest(res, res1); AddHistory(res = res.Replace(Patterns.CollapseTrigonometricFunctions).Replace(Patterns.TrigonometricRules)); } if (res.Nodes.Any(child => child is Statement)) { AddHistory(res = res.Replace(Patterns.BooleanRules).InnerSimplified); } if (res.Nodes.Any(child => child is ComparisonSign)) { AddHistory(res = res.Replace(Patterns.InequalityEqualityRules).InnerSimplified); } if (res.Nodes.Any(child => child is Factorialf)) { AddHistory(res = res.Replace(Patterns.ExpandFactorialDivisions).InnerSimplified); AddHistory(res = res.Replace(Patterns.FactorizeFactorialMultiplications).InnerSimplified); } if (res.Nodes.Any(child => child is Powf or Logf)) { AddHistory(res = res.Replace(Patterns.PowerRules).InnerSimplified); } if (res.Nodes.Any(child => child is Set)) { AddHistory(res = res.Replace(Patterns.SetOperatorRules).InnerSimplified); } if (res.Nodes.Any(child => child is Phif)) { AddHistory(res = res.Replace(Patterns.PhiFunctionRules).InnerSimplified); } Entity?possiblePoly = null; foreach (var var in res.Vars) { if (TryPolynomial(res, var, out var resPoly) && (possiblePoly is null || resPoly.Complexity < possiblePoly.Complexity)) { AddHistory(possiblePoly = resPoly); } } if (possiblePoly is { } && possiblePoly.Complexity < res.Complexity)
/// <summary>Finds all alternative forms of an expression</summary> internal static IEnumerable <Entity> Alternate(Entity src, int level) { if (src is FiniteSet ss) { return new[] { ss.Apply(ent => ent.Simplify()).InnerSimplified } } ; if (src is Number or Variable or Entity.Boolean) { return new[] { src } } ; var stage1 = src.InnerSimplified; #if DEBUG if (MathS.Diagnostic.CatchOnSimplify.Value(stage1)) { throw new MathS.Diagnostic.DiagnosticCatchException(); } #endif if (stage1 is Number or Variable or Entity.Boolean) { return new[] { stage1 } } ; // List of criteria for expr's complexity var history = new SortedDictionary <double, HashSet <Entity> >(); void AddHistory(Entity expr) { #if DEBUG if (MathS.Diagnostic.CatchOnSimplify.Value(expr)) { throw new MathS.Diagnostic.DiagnosticCatchException(); } #endif void __IterAddHistory(Entity expr) { var refexpr = expr.Replace(Patterns.SortRules(TreeAnalyzer.SortLevel.HIGH_LEVEL)).InnerSimplified; var compl1 = refexpr.SimplifiedRate; var compl2 = expr.SimplifiedRate; var n = compl1 > compl2 ? expr : refexpr; var ncompl = Math.Min(compl2, compl1); if (history.TryGetValue(ncompl, out var ncomplList)) { ncomplList.Add(n); } else { history[ncompl] = new HashSet <Entity> { n } }; } __IterAddHistory(expr); __IterAddHistory(expr.Replace(Patterns.InvertNegativePowers)); MultithreadingFunctional.ExitIfCancelled(); } AddHistory(stage1); var res = stage1; for (int i = 0; i < Math.Abs(level); i++) { var sortLevel = i switch { 1 => TreeAnalyzer.SortLevel.MIDDLE_LEVEL, 2 => TreeAnalyzer.SortLevel.LOW_LEVEL, _ => TreeAnalyzer.SortLevel.HIGH_LEVEL }; res = res.Replace(Patterns.SortRules(sortLevel)).InnerSimplified; if (res.Nodes.Any(child => child is Powf)) { AddHistory(res = res.Replace(Patterns.PowerRules).InnerSimplified); } AddHistory(res = SimplifyChildren(res)); AddHistory(res = res.Replace(Patterns.InvertNegativePowers).Replace(Patterns.DivisionPreparingRules).InnerSimplified); AddHistory(res = res.Replace(Patterns.PolynomialLongDivision).InnerSimplified); AddHistory(res = res.Replace(Patterns.NormalTrigonometricForm).InnerSimplified); AddHistory(res = res.Replace(Patterns.CollapseMultipleFractions).InnerSimplified); AddHistory(res = res.Replace(e => Patterns.FractionCommonDenominatorRules(e, sortLevel)).InnerSimplified); AddHistory(res = res.Replace(Patterns.InvertNegativePowers).Replace(Patterns.DivisionPreparingRules).InnerSimplified); AddHistory(res = res.Replace(Patterns.PowerRules).InnerSimplified); AddHistory(res = res.Replace(Patterns.TrigonometricRules).InnerSimplified); AddHistory(res = res.Replace(Patterns.CollapseTrigonometricFunctions).InnerSimplified); if (res.Nodes.Any(child => child is TrigonometricFunction)) { var res1 = res.Replace(Patterns.ExpandTrigonometricRules).InnerSimplified; AddHistory(res = res.Replace(Patterns.TrigonometricRules).Replace(Patterns.CommonRules).InnerSimplified); AddHistory(res1); res = PickSimplest(res, res1); AddHistory(res = res.Replace(Patterns.CollapseTrigonometricFunctions).Replace(Patterns.TrigonometricRules)); } if (res.Nodes.Any(child => child is Statement)) { AddHistory(res = res.Replace(Patterns.BooleanRules).InnerSimplified); } if (res.Nodes.Any(child => child is ComparisonSign)) { AddHistory(res = res.Replace(Patterns.InequalityEqualityRules).InnerSimplified); } if (res.Nodes.Any(child => child is Factorialf)) { AddHistory(res = res.Replace(Patterns.ExpandFactorialDivisions).InnerSimplified); AddHistory(res = res.Replace(Patterns.FactorizeFactorialMultiplications).InnerSimplified); } if (res.Nodes.Any(child => child is Powf or Logf)) { AddHistory(res = res.Replace(Patterns.PowerRules).InnerSimplified); } if (res.Nodes.Any(child => child is Set)) { var replaced = res.Replace(Patterns.SetOperatorRules); AddHistory(res = replaced.InnerSimplified); } if (res.Nodes.Any(child => child is Phif)) { AddHistory(res = res.Replace(Patterns.PhiFunctionRules).InnerSimplified); } Entity?possiblePoly = null; foreach (var var in res.Vars) { if (TryPolynomial(res, var, out var resPoly) && (possiblePoly is null || resPoly.Complexity < possiblePoly.Complexity)) { AddHistory(possiblePoly = resPoly); } } if (possiblePoly is { } && possiblePoly.Complexity < res.Complexity) { res = possiblePoly; } AddHistory(res = res.Replace(Patterns.CommonRules)); AddHistory(res = res.Replace(Patterns.NumericNeatRules)); /* * This was intended to simplify expressions as polynomials over nodes, some kind of * greatest common node and simplifying over it. However, the current algorithm does * not solve this issue completely and yet too slow to be accepted. * * AddHistory(res = TreeAnalyzer.Factorize(res)); */ res = history[history.Keys.Min()].First(); } if (level > 0) // if level < 0 we don't check whether expanded version is better { AddHistory(res.Expand().Simplify(-level)); AddHistory(res.Factorize().Simplify(-level)); } return(history.Values.SelectMany(x => x)); }