Пример #1
0
        // Find the best pivot in column j.
        private KeyValuePair <int, Real> PartialPivot(int i1, int i2, Expression j)
        {
            int  row = -1;
            Real max = -1;

            for (int i = i1; i < i2; ++i)
            {
                Expression ij = equations[i][j];
                if (!ij.EqualsZero())
                {
                    // If we don't a pivot yet, just grab this one.
                    if (row == -1)
                    {
                        row = i;
                    }

                    // Select the larger pivot if this is a constant.
                    if (ij is Constant && Real.Abs((Real)ij) > max)
                    {
                        row = i;
                        max = Real.Abs((Real)ij);
                    }
                }
            }

            return(new KeyValuePair <int, Real>(row, max));
        }
Пример #2
0
 // Note that this is *not* an arithmetic comparison, it is a canonicalization ordering.
 public override int CompareTo(Expression R)
 {
     if (R is Constant RC)
     {
         return(Real.Abs(RC.Value).CompareTo(Real.Abs(Value)));
     }
     return(base.CompareTo(R));
 }
Пример #3
0
        // Note that this is *not* an arithmetic comparison, it is a canonicalization ordering.
        public override int CompareTo(Expression R)
        {
            Constant RC = R as Constant;

            if (!ReferenceEquals(RC, null))
            {
                return(Real.Abs(RC.Value).CompareTo(Real.Abs(Value)));
            }

            return(base.CompareTo(R));
        }
Пример #4
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)));
        }
Пример #5
0
        // Enumerates x, splitting negative constants into a positive constant and -1.
        private static IEnumerable <Expression> FactorsOf(Expression x)
        {
            foreach (Expression i in Product.TermsOf(x))
            {
                if (i is Constant && (Real)i < 0)
                {
                    yield return(-1);

                    yield return(Real.Abs((Real)i));
                }
                else if (i is Power power)
                {
                    yield return(i);

                    yield return(power.Left);
                }
                else
                {
                    yield return(i);
                }
            }
        }
Пример #6
0
        // Find the best pivot in column j.
        private KeyValuePair <int, Real> PartialPivot(int i1, int i2, Expression j, IEnumerable <Arrow> PivotConditions)
        {
            int  row = -1;
            Real max = -1;

            for (int i = i1; i < i2; ++i)
            {
                Expression ij = equations[i][j];
                if (!ij.EqualsZero())
                {
                    // If we don't a pivot yet, just grab this one.
                    if (row == -1)
                    {
                        row = i;
                    }

                    // Select the larger pivot if this is a constant, using the PivotConditions.
                    Expression ijc;
                    if (ij is Constant || PivotConditions is null)
                    {
                        ijc = ij;
                    }
                    else
                    {
                        ijc = ij.Evaluate(PivotConditions);
                    }
                    if (ijc is Constant && Real.Abs((Real)ijc) > max)
                    {
                        row = i;
                        max = Real.Abs((Real)ijc);
                    }
                }
            }

            return(new KeyValuePair <int, Real>(row, max));
        }
Пример #7
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));
        }
Пример #8
0
 public static Expression Abs(Constant x)
 {
     return(Real.Abs(x));
 }