Beispiel #1
0
 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);
 }
Beispiel #2
0
        /// <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;
Beispiel #3
0
        /// <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)
Beispiel #4
0
        /// <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));
        }