Beispiel #1
0
        protected override Expression VisitIndex(Index I)
        {
            I = (Index)base.VisitIndex(I);

            // We can only evaluate index expressions with constant integer indices.
            if (!I.Indices.All(i => i.IsInteger()))
            {
                return(I);
            }

            // Index a matrix.
            Matrix M = I.Target as Matrix;

            if (!ReferenceEquals(M, null))
            {
                switch (I.Indices.Count())
                {
                case 1: return(M[(int)I.Indices.ElementAt(0)]);

                case 2: return(M[(int)I.Indices.ElementAt(0), (int)I.Indices.ElementAt(1)]);
                }
            }

            // Index an array.
            Array A = I.Target as Array;

            if (!ReferenceEquals(A, null))
            {
                return(Constant.New(A.Value.GetValue(I.Indices.Select(i => (int)i).ToArray())));
            }

            return(I);
        }
Beispiel #2
0
 public static LazyExpression operator !=(Expression L, Expression R)
 {
     if ((L is null) || (R is null))
     {
         return(new LazyExpression(Constant.New(!ReferenceEquals(L, R))));
     }
     return(new LazyExpression(Binary.NotEqual(L, R)));
 }
Beispiel #3
0
 public static LazyExpression operator ==(Expression L, Expression R)
 {
     if (ReferenceEquals(L, null) || ReferenceEquals(R, null))
     {
         return(new LazyExpression(Constant.New(ReferenceEquals(L, R))));
     }
     return(new LazyExpression(Binary.Equal(L, R)));
 }
 public static LazyExpression operator !=(LazyExpression L, LazyExpression R)
 {
     if (ReferenceEquals(L.value, null) || ReferenceEquals(R.value, null))
     {
         return(new LazyExpression(Constant.New(!ReferenceEquals(L.value, R.value))));
     }
     return(new LazyExpression(Binary.NotEqual(L.value, R.value)));
 }
Beispiel #5
0
        protected override Expression VisitPower(Power P)
        {
            Expression L = Visit(P.Left);
            Expression R = Visit(P.Right);

            if (R.IsInteger())
            {
                // Transform (x*y)^z => x^z*y^z if z is an integer.
                Product M = L as Product;
                if (!ReferenceEquals(M, null))
                {
                    return(Visit(Product.New(M.Terms.Select(i => Power.New(i, R)))));
                }
            }

            // Transform (x^y)^z => x^(y*z) if z is an integer.
            Power LP = L as Power;

            if (!ReferenceEquals(LP, null))
            {
                L = LP.Left;
                R = Visit(Product.New(P.Right, LP.Right));
            }

            // Handle identities.
            Real?LR = AsReal(L);

            if (EqualsZero(LR))
            {
                return(0);
            }
            if (EqualsOne(LR))
            {
                return(1);
            }

            Real?RR = AsReal(R);

            if (EqualsZero(RR))
            {
                return(1);
            }
            if (EqualsOne(RR))
            {
                return(L);
            }

            // Evaluate result.
            if (LR != null && RR != null)
            {
                return(Constant.New(LR.Value ^ RR.Value));
            }
            else
            {
                return(Power.New(L, R));
            }
        }
Beispiel #6
0
        // Combine like terms and multiply constants.
        protected override Expression VisitProduct(Product M)
        {
            // Map terms to exponents.
            DefaultDictionary <Expression, Real> terms = new DefaultDictionary <Expression, Real>(0);

            // Accumulate constants and sum exponent of each term.
            Real C = 1;

            foreach (Expression i in M.Terms.SelectMany(i => Product.TermsOf(Visit(i))))
            {
                if (i is Constant)
                {
                    Real Ci = (Real)i;
                    // Early exit if 0.
                    if (Ci.EqualsZero())
                    {
                        return(0);
                    }
                    C *= Ci;
                }
                else
                {
                    Power Pi = i as Power;
                    if (!ReferenceEquals(Pi, null) && Pi.Right is Constant)
                    {
                        terms[Pi.Left] += (Real)Pi.Right;
                    }
                    else
                    {
                        terms[i] += 1;
                    }
                }
            }

            // Build a new expression with the accumulated terms.
            if (!C.EqualsOne())
            {
                // Find a sum term that has a constant term to distribute into.
                KeyValuePair <Expression, Real> A = terms.FirstOrDefault(i => Real.Abs(i.Value).EqualsOne() && i.Key is Sum);
                if (!ReferenceEquals(A.Key, null))
                {
                    terms.Remove(A.Key);
                    terms[ExpandExtension.Distribute(C ^ A.Value, A.Key)] += A.Value;
                }
                else
                {
                    terms.Add(C, 1);
                }
            }
            return(Product.New(terms
                               .Where(i => !i.Value.EqualsZero())
                               .Select(i => !i.Value.EqualsOne() ? Power.New(i.Key, Constant.New(i.Value)) : i.Key)));
        }
Beispiel #7
0
        protected override Expression VisitUnary(Unary U)
        {
            Expression O = Visit(U.Operand);
            Real?      C = AsReal(O);

            switch (U.Operator)
            {
            case Operator.Not:
                if (IsTrue(C))
                {
                    return(Constant.New(false));
                }
                else if (IsFalse(C))
                {
                    return(Constant.New(true));
                }
                break;
            }

            return(Unary.New(U.Operator, O));
        }
Beispiel #8
0
        public static Expression EvaluateSum(IEnumerable <Expression> Terms)
        {
            // Map terms to their coefficients.
            DefaultDictionary <Expression, Real> terms = new DefaultDictionary <Expression, Real>(0);

            // Accumulate constants and sum coefficient of each term.
            Real C = 0;

            foreach (Expression i in Terms)
            {
                if (i is Constant)
                {
                    C += (Real)i;
                }
                else
                {
                    // Find constant term.
                    Constant coeff = Product.TermsOf(i).OfType <Constant>().FirstOrDefault();
                    if (!ReferenceEquals(coeff, null))
                    {
                        terms[Product.New(Product.TermsOf(i).ExceptUnique(coeff, Expression.RefComparer))] += (Real)coeff;
                    }
                    else
                    {
                        terms[i] += 1;
                    }
                }
            }

            // Build a new expression with the accumulated terms.
            if (!C.EqualsZero())
            {
                terms.Add(Constant.New(C), (Real)1);
            }
            return(Sum.New(terms
                           .Where(i => !i.Value.EqualsZero())
                           .Select(i => !i.Value.EqualsOne() ? Product.New(i.Key, Constant.New(i.Value)) : i.Key)));
        }
        public override Expression Call(IEnumerable <Expression> Args)
        {
            if (!Args.Zip(Method.GetParameters(), (a, p) => p.ParameterType.IsAssignableFrom(a.GetType())).All())
            {
                return(null);
            }

            try
            {
                object ret = Method.Invoke(_this, Args.ToArray <object>());
                if (ret is Expression)
                {
                    return(ret as Expression);
                }
                else
                {
                    return(Constant.New(ret));
                }
            }
            catch (TargetInvocationException Ex)
            {
                throw Ex.InnerException;
            }
        }
Beispiel #10
0
        //P is
        //    if next is a unary operator
        //         const op := unary(next)
        //         consume
        //         q := prec( op )
        //         const t := Exp( q )
        //         return mkNode( op, t )
        //    else if next = "("
        //         consume
        //         const t := Exp( 0 )
        //         expect ")"
        //         return t
        //    else if next is a v
        //         const t := mkLeaf( next )
        //         consume
        //         return t
        //    else
        //         error
        private Expression P()
        {
            Operator op = new Operator();

            if (tokens.Tok == "+")
            {
                // Skip unary +.
                tokens.Consume();
                return(P());
            }
            else if (IsUnaryPreOperator(tokens.Tok, ref op))
            {
                // Unary operator.
                tokens.Consume();
                Expression t = Exp(Precedence(op));
                return(Unary.New(op, t));
            }
            else if (tokens.Tok == "(")
            {
                // Group.
                tokens.Consume();
                Expression t = Exp(0);
                tokens.Expect(")");
                return(t);
            }
            else if (tokens.Tok == "{")
            {
                // Set.
                tokens.Consume();
                return(Set.New(L(",", "}")));
            }
            else if (tokens.Tok == "[")
            {
                // Matrix.
                tokens.Consume();
                List <List <Expression> > entries = new List <List <Expression> >();
                while (tokens.Tok == "[")
                {
                    tokens.Consume();
                    entries.Add(L(",", "]"));
                }
                tokens.Expect("]");

                return(Matrix.New(entries));
            }
            else
            {
                string tok = tokens.Consume();

                decimal dec = 0;
                double  dbl = 0.0;
                if (decimal.TryParse(tok, NumberStyles.Float, culture, out dec))
                {
                    return(Constant.New(dec));
                }
                if (double.TryParse(tok, NumberStyles.Float, culture, out dbl))
                {
                    return(Constant.New(dbl));
                }
                else if (tok == "True")
                {
                    return(Constant.New(true));
                }
                else if (tok == "False")
                {
                    return(Constant.New(false));
                }
                else if (tok == "\u221E" || tok == "oo")
                {
                    return(Constant.New(Real.Infinity));
                }
                else if (tokens.Tok == "[")
                {
                    // Bracket function call.
                    tokens.Consume();
                    List <Expression> args = L(",", "]");
                    return(Call.New(Resolve(tok, args), args));
                }
                else if (tokens.Tok == "(")
                {
                    // Paren function call.
                    tokens.Consume();
                    List <Expression> args = L(",", ")");
                    return(Call.New(Resolve(tok, args), args));
                }
                else
                {
                    return(Resolve(tok));
                }
            }
        }
Beispiel #11
0
        protected override Expression VisitBinary(Binary B)
        {
            Expression L = Visit(B.Left);
            Expression R = Visit(B.Right);

            // Evaluate substitution operators.
            if (B is Substitute)
            {
                return(Visit(L.Substitute(Set.MembersOf(R).Cast <Arrow>())));
            }

            Real?LR = AsReal(L);
            Real?RR = AsReal(R);

            // Evaluate relational operators on constants.
            if (LR != null && RR != null)
            {
                switch (B.Operator)
                {
                case Operator.Equal: return(Constant.New(LR.Value == RR.Value));

                case Operator.NotEqual: return(Constant.New(LR.Value != RR.Value));

                case Operator.Less: return(Constant.New(LR.Value < RR.Value));

                case Operator.Greater: return(Constant.New(LR.Value <= RR.Value));

                case Operator.LessEqual: return(Constant.New(LR.Value > RR.Value));

                case Operator.GreaterEqual: return(Constant.New(LR.Value >= RR.Value));

                case Operator.ApproxEqual: return(Constant.New(
                                                      LR.Value == RR.Value ||
                                                      Real.Abs(LR.Value - RR.Value) < 1e-12 * Real.Max(Real.Abs(LR.Value), Real.Abs(RR.Value))));
                }
            }

            // Evaluate boolean operators if possible.
            switch (B.Operator)
            {
            case Operator.And:
                if (IsFalse(LR) || IsFalse(RR))
                {
                    return(Constant.New(false));
                }
                else if (IsTrue(LR) && IsTrue(RR))
                {
                    return(Constant.New(true));
                }
                break;

            case Operator.Or:
                if (IsTrue(LR) || IsTrue(RR))
                {
                    return(Constant.New(true));
                }
                else if (IsFalse(LR) && IsFalse(RR))
                {
                    return(Constant.New(false));
                }
                break;

            case Operator.Equal:
            case Operator.ApproxEqual:
                if (L.Equals(R))
                {
                    return(Constant.New(true));
                }
                break;

            case Operator.NotEqual:
                if (L.Equals(R))
                {
                    return(Constant.New(false));
                }
                break;
            }

            return(Binary.New(B.Operator, L, R));
        }
Beispiel #12
0
 public static Expression DependsOn(Expression f, Expression x)
 {
     return(Constant.New(f.DependsOn(x)));
 }
Beispiel #13
0
 public static Expression IsNatural(Constant x)
 {
     return(Constant.New(x.IsInteger() && (Real)x > 0));
 }
Beispiel #14
0
 public static Expression IsInteger(Constant x)
 {
     return(Constant.New(x.IsInteger()));
 }
Beispiel #15
0
 public static Expression IsConstant(Constant x)
 {
     return(Constant.New(true));
 }