/// <summary> /// Adds "le" to "this". Afterwards, "le" should not be used, because it will have been destroyed. /// </summary> /// <param name="le"></param> public void Add(LinearExpr /*!*/ le) /* throws ArithmeticException */ { Contract.Requires(le != null); Contract.Requires(le != this); checked { constant += le.constant; } le.constant = BigNum.FromInt(-70029); // "le" should no longer be used; assign it a strange value so that misuse is perhaps more easily detected // optimization: if (le.terms == null) { return; } else if (terms == null) { terms = le.terms; le.terms = null; return; } // merge the two term lists // Use a nested loop, which is quadratic in time complexity, but we hope the lists will be small Term newTerms = null; while (le.terms != null) { // take off next term from "le" Term t = le.terms; le.terms = t.next; t.next = null; for (Term u = terms; u != null; u = u.next) { if (u.var == t.var) { checked { u.coeff += t.coeff; } goto NextOuter; } } t.next = newTerms; newTerms = t; NextOuter: ; } // finally, include all non-0 terms while (terms != null) { // take off next term from "this" Term t = terms; terms = t.next; if (!t.coeff.IsZero) { t.next = newTerms; newTerms = t; } } terms = newTerms; }
/// <summary> /// Builds a linear expression from "e", if possible; returns null if not possible. /// </summary> /// <param name="e"></param> /// <returns></returns> public static /*maybe null*/ LinearExpr AsExpr(IExpr /*!*/ e) /* throws ArithmeticException */ { Contract.Requires(e != null); if (e is IVariable) { // Note, without a type for the variable, we don't know if the identifier is intended to hold an integer value. // However, it seems that no harm can be caused by here treating the identifier as if it held an // integer value, because other parts of this method will reject the expression as a linear expression // if non-numeric operations other than equality are applied to the identifier. return(new LinearExpr((IVariable)e)); } else if (e is IFunApp) { IFunApp /*!*/ funapp = (IFunApp)e; Contract.Assert(funapp != null); IFunctionSymbol /*!*/ s = funapp.FunctionSymbol; Contract.Assert(s != null); if (s is IntSymbol) { return(new LinearExpr(((IntSymbol)s).Value)); } else if (s.Equals(Int.Negate)) { Contract.Assert(funapp.Arguments.Count == 1); LinearExpr le = AsExpr((IExpr /*!*/)cce.NonNull(funapp.Arguments[0])); if (le != null) { le.Negate(); return(le); } } else if (s.Equals(Int.Add) || s.Equals(Int.Sub) || s.Equals(Int.Mul)) { Contract.Assert(funapp.Arguments.Count == 2); IExpr /*!*/ arg0 = (IExpr /*!*/)cce.NonNull(funapp.Arguments[0]); IExpr /*!*/ arg1 = (IExpr /*!*/)cce.NonNull(funapp.Arguments[1]); LinearExpr le0 = AsExpr(arg0); if (le0 == null) { return(null); } LinearExpr le1 = AsExpr(arg1); if (le1 == null) { return(null); } if (s.Equals(Int.Add)) { le0.Add(le1); return(le0); } else if (s.Equals(Int.Sub)) { le1.Negate(); le0.Add(le1); return(le0); } else if (s.Equals(Int.Mul)) { BigNum x; if (le0.AsConstant(out x)) { le1.Multiply(x); return(le1); } else if (le1.AsConstant(out x)) { le0.Multiply(x); return(le0); } } } } return(null); }
/// <summary> /// Adds "le" to "this". Afterwards, "le" should not be used, because it will have been destroyed. /// </summary> /// <param name="le"></param> public void Add(LinearExpr/*!*/ le) /* throws ArithmeticException */ { Contract.Requires(le != null); Contract.Requires(le != this); checked { constant += le.constant; } le.constant = BigNum.FromInt(-70029); // "le" should no longer be used; assign it a strange value so that misuse is perhaps more easily detected // optimization: if (le.terms == null) { return; } else if (terms == null) { terms = le.terms; le.terms = null; return; } // merge the two term lists // Use a nested loop, which is quadratic in time complexity, but we hope the lists will be small Term newTerms = null; while (le.terms != null) { // take off next term from "le" Term t = le.terms; le.terms = t.next; t.next = null; for (Term u = terms; u != null; u = u.next) { if (u.var == t.var) { checked { u.coeff += t.coeff; } goto NextOuter; } } t.next = newTerms; newTerms = t; NextOuter: ; } // finally, include all non-0 terms while (terms != null) { // take off next term from "this" Term t = terms; terms = t.next; if (!t.coeff.IsZero) { t.next = newTerms; newTerms = t; } } terms = newTerms; }
static /*maybe null*/ LinearCondition GetCond(IExpr e, bool positive) /* throws ArithmeticException */ { IFunApp funapp = e as IFunApp; if (funapp == null) { return(null); } IFunctionSymbol /*!*/ s = funapp.FunctionSymbol; Contract.Assert(s != null); if ((positive && s.Equals(Prop.False)) || (!positive && s.Equals(Prop.True))) { return(new LCBottom()); } else if (s.Equals(Prop.Not)) { Contract.Assert(funapp.Arguments.Count == 1); return(GetCond((IExpr /*!*/)cce.NonNull(funapp.Arguments[0]), !positive)); } else if (funapp.Arguments.Count == 2) { IExpr /*!*/ arg0 = (IExpr /*!*/)cce.NonNull(funapp.Arguments[0]); IExpr /*!*/ arg1 = (IExpr /*!*/)cce.NonNull(funapp.Arguments[1]); LinearExpr le0 = AsExpr(arg0); if (le0 == null) { return(null); } LinearExpr le1 = AsExpr(arg1); if (le1 == null) { return(null); } LinearConstraint constraint = null; bool sense = true; if ((positive && s.Equals(Int.Less)) || (!positive && s.Equals(Int.AtLeast))) { constraint = MakeConstraint(le0, le1, LinearConstraint.ConstraintRelation.LE, BigNum.ONE); } else if ((positive && s.Equals(Int.AtMost)) || (!positive && s.Equals(Int.Greater))) { constraint = MakeConstraint(le0, le1, LinearConstraint.ConstraintRelation.LE, BigNum.ZERO); } else if ((positive && s.Equals(Int.AtLeast)) || (!positive && s.Equals(Int.Less))) { constraint = MakeConstraint(le1, le0, LinearConstraint.ConstraintRelation.LE, BigNum.ZERO); } else if ((positive && s.Equals(Int.Greater)) || (!positive && s.Equals(Int.AtMost))) { constraint = MakeConstraint(le1, le0, LinearConstraint.ConstraintRelation.LE, BigNum.ONE); } else if (s.Equals(Int.Eq)) { constraint = MakeConstraint(le0, le1, LinearConstraint.ConstraintRelation.EQ, BigNum.ZERO); sense = positive; } else if (s.Equals(Int.Neq)) { constraint = MakeConstraint(le0, le1, LinearConstraint.ConstraintRelation.EQ, BigNum.ZERO); sense = !positive; } if (constraint != null) { if (constraint.coefficients.Count != 0) { return(new LinearConditionLiteral(sense, constraint)); } else if (constraint.IsConstantSatisfiable()) { return(null); } else { return(new LCBottom()); } } } return(null); }
public static LinearConstraint MakeConstraint(LinearExpr/*!*/ le0, LinearExpr/*!*/ le1, LinearConstraint.ConstraintRelation rel, BigNum constantOffset) /* throws ArithmeticException */ { Contract.Requires(le0 != null); Contract.Requires(le1 != null); le1.Negate(); le0.Add(le1); le0.AddConstant(constantOffset); return le0.ToConstraint(rel); }