// 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)); }
// 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)); }
// 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)); }
// 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))); }
// 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); } } }
// 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)); }
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)); }
public static Expression Abs(Constant x) { return(Real.Abs(x)); }