Example #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);
        }
Example #2
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 product)
            {
                return(Product.New(product.Terms.Select(i => i.Factor(x))));
            }

            // If if is l^r, factor l and distribute r.
            if (f is Power power)
            {
                Expression l = power.Left.Factor(x);
                Expression r = power.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 p && (p.Variable.Equals(x) || (x is null)))
            {
                return(p.Factor());
            }

            // Try interpreting f as a polynomial of x.
            if (!(x is 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 s)
            {
                // Make a list of each terms' products.
                List <List <Expression> > terms = s.Terms.Select(i => FactorsOf(i).ToList()).ToList();

                // All of the distinct factors.
                IEnumerable <Expression> factors = terms.SelectMany(i => i.Except(1, -1)).Distinct();
                // Choose the most common factor to factor.
                Expression factor = factors.ArgMax(i => terms.Count(j => j.Contains(i)));
                // Find the terms that contain the factor.
                List <List <Expression> > contains = terms.Where(i => i.Contains(factor)).ToList();
                // If more than one term contains the factor, pull it out and factor the resulting expressions (again).
                if (contains.Count() > 1)
                {
                    Expression factored     = Sum.New(contains.Select(i => Product.New(i.Except(factor))));
                    Expression not_factored = Sum.New(terms.Except(contains).Select(i => Product.New(i)));
                    return(Sum.New(Product.New(factor, factored), not_factored).Factor(null));
                }
            }
            return(f);
        }
Example #3
0
        // Expand N(x)/D(x) using partial fractions.
        private static Expression ExpandPartialFractions(Expression N, Expression D, Expression x)
        {
            List <Expression> terms    = new List <Expression>();
            List <Variable>   unknowns = new List <Variable>();
            List <Expression> basis    = new List <Expression>();

            foreach (Expression i in Product.TermsOf(D))
            {
                // Get the multiplicity of this basis term.
                Expression e = i;
                int        n = Power.IntegralExponentOf(e);
                if (n != 1)
                {
                    e = ((Power)i).Left;
                }

                // Convert to a polynomial.
                Polynomial Pi = Polynomial.New(e, x);

                // Add new terms for each multiplicity n.
                for (int j = 1; j <= n; ++j)
                {
                    // Expression for the unknown numerator of this term.
                    Expression unknown = 0;
                    for (int k = 0; k < Pi.Degree; ++k)
                    {
                        Variable Ai = Variable.New("_A" + unknowns.Count.ToString());
                        unknown += Ai * (x ^ k);
                        unknowns.Add(Ai);
                    }

                    terms.Add(Product.New(unknown, Power.New(e, -j)));
                }
                basis.Add(i);
            }

            // Equate the original expression with the decomposed expressions.
            D = Sum.New(terms.Select(j => (Expression)(D * j))).Expand();
            Polynomial l = Polynomial.New(N, x);
            Polynomial r = Polynomial.New(D, x);

            // Equate terms of equal degree and solve for the unknowns.
            int          degree = Math.Max(l.Degree, r.Degree);
            List <Equal> eqs    = new List <Equal>(degree + 1);

            for (int i = 0; i <= degree; ++i)
            {
                eqs.Add(Equal.New(l[i], r[i]));
            }
            List <Arrow> A = eqs.Solve(unknowns);

            // Substitute the now knowns.
            return(Sum.New(terms.Select(i => i.Evaluate(A))));
        }