示例#1
0
        /// <summary>
        /// Distribute products across sums.
        /// </summary>
        /// <param name="f"></param>
        /// <param name="x"></param>
        /// <returns></returns>
        public static Expression Factor(this Expression f, Expression x)
        {
            // If f is a product, just factor its terms.
            if (f is Product)
            {
                return(Product.New(((Product)f).Terms.Select(i => i.Factor(x))));
            }

            // If if is l^r, factor l and distribute r.
            if (f is Power)
            {
                Expression l = ((Power)f).Left.Factor(x);
                Expression r = ((Power)f).Right;
                return(Product.New(Product.TermsOf(l).Select(i => Power.New(i, r))));
            }

            // If f is a polynomial of x, use polynomial factoring methods.
            if (f is Polynomial && (((Polynomial)f).Variable.Equals(x) || ReferenceEquals(x, null)))
            {
                return(((Polynomial)f).Factor());
            }

            // Try interpreting f as a polynomial of x.
            if (!ReferenceEquals(x, null))
            {
                // If f is a polynomial of x, factor it.
                try
                {
                    return(Polynomial.New(f, x).Factor());
                }
                catch (Exception) { }
            }

            // Just factor out common sub-expressions.
            if (f is Sum)
            {
                Sum s = (Sum)f;

                IEnumerable <Expression> terms = s.Terms.Select(i => i.Factor()).Buffer();

                // All of the distinct factors.
                IEnumerable <Expression> factors = terms.SelectMany(i => FactorsOf(i).Except(1, -1)).Distinct();
                // Choose the most common factor to use.
                Expression factor = factors.ArgMax(i => terms.Count(j => FactorsOf(j).Contains(i)));
                // Find the terms that contain the factor.
                IEnumerable <Expression> contains = terms.Where(i => FactorsOf(i).Contains(factor)).Buffer();
                // If more than one term contains the factor, pull it out and factor the resulting expression (again).
                if (contains.Count() > 1)
                {
                    return(Sum.New(
                               Product.New(factor, Sum.New(contains.Select(i => Binary.Divide(i, factor))).Evaluate()),
                               Sum.New(terms.Except(contains, Expression.RefComparer))).Factor(null));
                }
            }

            return(f);
        }
示例#2
0
 public static Expression operator /(Polynomial N, Polynomial D)
 {
     if (Equals(N.Variable, D.Variable))
     {
         Polynomial R;
         Polynomial Q = Divide(N, D, out R);
         return(Sum.New(Q, Binary.Divide(R, D)));
     }
     else
     {
         return((Expression)N / (Expression)D);
     }
 }
示例#3
0
        public override bool Matches(Expression E, MatchContext Matched)
        {
            Expression matched;

            if (Matched.TryGetValue(Right, out matched))
            {
                if (Left.Matches(E ^ Binary.Divide(1, matched), Matched))
                {
                    return(true);
                }
            }

            // x^0 = 1.
            if (E.EqualsOne() && Right.Matches(0, Matched))
            {
                return(true);
            }
            // 0^x = 0.
            if (E.EqualsZero() && Left.Matches(0, Matched))
            {
                return(true);
            }

            Binary PE = E as Power;

            if (!ReferenceEquals(PE, null) && Matched.TryMatch(() => Left.Matches(PE.Left, Matched) && Right.Matches(PE.Right, Matched)))
            {
                return(true);
            }

            // If the exponent matches 1, E can match left.
            if (Matched.TryMatch(() => Right.Matches(1, Matched) && Left.Matches(E, Matched)))
            {
                return(true);
            }

            if (Right.IsInteger() && Left.Matches(ComputerAlgebra.Power.New(E, Binary.Divide(1, Right)).Evaluate(), Matched))
            {
                return(true);
            }

            return(false);
        }
示例#4
0
        protected override Expression VisitPower(Power P)
        {
            Expression f = P.Left;
            Expression g = P.Right;

            if (g.DependsOn(x))
            {
                // f(x)^g(x)
                return(Product.New(P,
                                   Sum.New(
                                       Product.New(Visit(f), Binary.Divide(g, f)),
                                       Product.New(Visit(g), Call.Ln(f)))).Evaluate());
            }
            else
            {
                // f(x)^g
                return(Product.New(
                           g,
                           Power.New(f, Binary.Subtract(g, 1)),
                           Visit(f)).Evaluate());
            }
        }
示例#5
0
        public override bool Matches(Expression E, MatchContext Matched)
        {
            // if E is zero, any term can match to zero to succeed.
            if (E.EqualsZero())
            {
                return(Terms.Any(i => i.Matches(0, Matched)));
            }

            // Move the constants in this pattern to E.
            IEnumerable <Expression> PTerms    = Terms;
            IEnumerable <Expression> Constants = PTerms.OfType <Constant>();

            if (Constants.Any())
            {
                E      = Binary.Divide(E, New(Constants)).Evaluate();
                PTerms = PTerms.Except(Constants, RefComparer);
            }

            IEnumerable <Expression> ETerms = TermsOf(E);

            // Try starting the match at each term of the pattern.
            foreach (Expression p in PTerms)
            {
                // Remaining terms of the pattern.
                Expression P = New(PTerms.ExceptUnique(p, RefComparer));

                // If p is a variable, we have to handle the possibility that more than one term of E might match this term.
                if (p is Variable)
                {
                    // Check if p has already been matched. If it has, treat it as a constant and match the rest of the terms.
                    Expression matched;
                    if (Matched.TryGetValue(p, out matched))
                    {
                        // p has already been matched. Remove it out of E and match the remainder of the pattern.
                        if (P.Matches(E / matched, Matched))
                        {
                            return(true);
                        }
                    }
                    else
                    {
                        // Try matching p to the various combinations of the terms of E.
                        for (int i = 1; i <= ETerms.Count(); ++i)
                        {
                            foreach (IEnumerable <Expression> e in ETerms.Combinations(i))
                            {
                                if (Matched.TryMatch(() =>
                                                     p.Matches(New(e), Matched) &&
                                                     P.Matches(New(ETerms.ExceptUnique(e, RefComparer)), Matched)))
                                {
                                    return(true);
                                }
                            }
                        }

                        // Try matching p to identity.
                        if (Matched.TryMatch(() => p.Matches(1, Matched) && P.Matches(E, Matched)))
                        {
                            return(true);
                        }
                    }
                }
                else
                {
                    // If p is not a variable, try matching it to any of the terms of E.
                    foreach (Expression e in ETerms)
                    {
                        if (Matched.TryMatch(() =>
                                             p.Matches(e, Matched) &&
                                             P.Matches(New(ETerms.ExceptUnique(e, RefComparer)), Matched)))
                        {
                            return(true);
                        }
                    }
                }
            }

            return(false);
        }