private static bool IsFinite(PairNonNull <Rational, Rational> point) { return(!point.One.IsInfinity && !point.Two.IsInfinity); }
[ContractVerification(false)] // The analysis of this method takes forever. Should consider refactoring internal Set <Polynomial <Variable, Expression> > ConvexHullHelper( IntervalEnvironment <Variable, Expression> other, Variable slack, SubPolyhedra.JoinConstraintInference inference) { Contract.Requires(other != null); var result = new Set <Polynomial <Variable, Expression> >(); var commonVariables = this.VariablesNonSlack.SetIntersection(other.VariablesNonSlack); var oct = false; if (commonVariables.Count <= SubPolyhedra.MaxVariablesInOctagonsConstraintInference) { oct = true; } else if (inference == SubPolyhedra.JoinConstraintInference.Standard) { return(result); } bool CH = inference == SubPolyhedra.JoinConstraintInference.CHOct || inference == SubPolyhedra.JoinConstraintInference.ConvexHull2D; oct = oct || inference == SubPolyhedra.JoinConstraintInference.CHOct || inference == SubPolyhedra.JoinConstraintInference.Octagons; int i = 0, j = 0; var this_Bounds = new Dictionary <Variable, Interval>(); var other_Bounds = new Dictionary <Variable, Interval>(); foreach (var e1 in commonVariables) { i++; Interval e1Left, e1Right; if ( !TryEvalWithCache(this, e1, this_Bounds, out e1Left) || !TryEvalWithCache(other, e1, other_Bounds, out e1Right)) { continue; } j = 0; foreach (var e2 in commonVariables) { j++; // either e1 == e2 or we already have relations between e1 and e2 if (e1.Equals(e2) || j <= i) { continue; } Interval e2Left, e2Right; if ( !TryEvalWithCache(this, e2, this_Bounds, out e2Left) || !TryEvalWithCache(other, e2, other_Bounds, out e2Right)) { continue; } if (oct) { #region Adding octogonal constraints to get at least as much precision as octagons var monomials = new Monomial <Variable>[] { new Monomial <Variable>(e1), new Monomial <Variable>(-1, e2), new Monomial <Variable>(slack) }; Polynomial <Variable, Expression> pol; if (!Polynomial <Variable, Expression> .TryToPolynomialForm(true, monomials, out pol)) { throw new AbstractInterpretationException("Impossible case"); } result.Add(pol); #endregion } if (CH) { #region Convex Hull // adaptation of the Monotone Chain algorithm var vertices = new PairNonNull <Rational, Rational>[8] { new PairNonNull <Rational, Rational>(e1Left.LowerBound, e2Left.LowerBound), new PairNonNull <Rational, Rational>(e1Left.LowerBound, e2Left.UpperBound), new PairNonNull <Rational, Rational>(e1Left.UpperBound, e2Left.LowerBound), new PairNonNull <Rational, Rational>(e1Left.UpperBound, e2Left.UpperBound), new PairNonNull <Rational, Rational>(e1Right.LowerBound, e2Right.LowerBound), new PairNonNull <Rational, Rational>(e1Right.LowerBound, e2Right.UpperBound), new PairNonNull <Rational, Rational>(e1Right.UpperBound, e2Right.LowerBound), new PairNonNull <Rational, Rational>(e1Right.UpperBound, e2Right.UpperBound) }; try { Array.Sort(vertices, delegate(PairNonNull <Rational, Rational> x, PairNonNull <Rational, Rational> y) { if ((x.One - y.One).Sign == 0) { return((x.Two - y.Two).Sign); } else { return((x.One - y.One).Sign); } }); } catch (InvalidOperationException) { return(result); } var IsInHull = new bool[8]; try { Polynomial <Variable, Expression> pol; #region Computation of the Lower Hull IsInHull[0] = IsFinite(vertices[0]); IsInHull[2] = IsFinite(vertices[2]); IsInHull[4] = IsFinite(vertices[4]); if (IsInHull[0] && IsInHull[2] && IsInHull[4] && (vertices[2].One - vertices[0].One) * (vertices[4].Two - vertices[0].Two) <= (vertices[4].One - vertices[0].One) * (vertices[2].Two - vertices[0].Two)) { IsInHull[2] = false; } IsInHull[6] = IsFinite(vertices[6]); if (IsInHull[2] && IsInHull[4] && IsInHull[6] && (vertices[4].One - vertices[2].One) * (vertices[6].Two - vertices[2].Two) <= (vertices[6].One - vertices[2].One) * (vertices[4].Two - vertices[2].Two)) { IsInHull[4] = false; } if (IsInHull[0] && IsInHull[4] && IsInHull[6] && (vertices[4].One - vertices[0].One) * (vertices[6].Two - vertices[0].Two) <= (vertices[6].One - vertices[0].One) * (vertices[4].Two - vertices[0].Two)) { IsInHull[4] = false; } if (IsInHull[0] && IsInHull[2] && IsInHull[6] && (vertices[2].One - vertices[0].One) * (vertices[6].Two - vertices[0].Two) <= (vertices[6].One - vertices[0].One) * (vertices[2].Two - vertices[0].Two)) { IsInHull[2] = false; } #endregion #region Computation of the Upper Hull IsInHull[1] = IsFinite(vertices[1]); IsInHull[3] = IsFinite(vertices[3]); IsInHull[5] = IsFinite(vertices[5]); if (IsInHull[1] && IsInHull[3] && IsInHull[5] && (vertices[3].One - vertices[1].One) * (vertices[5].Two - vertices[1].Two) >= (vertices[5].One - vertices[1].One) * (vertices[3].Two - vertices[1].Two)) { IsInHull[3] = false; } IsInHull[7] = IsFinite(vertices[7]); if (IsInHull[3] && IsInHull[5] && IsInHull[7] && (vertices[5].One - vertices[3].One) * (vertices[7].Two - vertices[3].Two) >= (vertices[7].One - vertices[3].One) * (vertices[5].Two - vertices[3].Two)) { IsInHull[5] = false; } if (IsInHull[1] && IsInHull[5] && IsInHull[7] && (vertices[5].One - vertices[1].One) * (vertices[7].Two - vertices[1].Two) >= (vertices[7].One - vertices[1].One) * (vertices[5].Two - vertices[1].Two)) { IsInHull[5] = false; } if (IsInHull[1] && IsInHull[3] && IsInHull[7] && (vertices[3].One - vertices[1].One) * (vertices[7].Two - vertices[1].Two) >= (vertices[7].One - vertices[1].One) * (vertices[3].Two - vertices[1].Two)) { IsInHull[3] = false; } #endregion #region Removing points that are in the hull of the subset of finite points but not in the hull due to infinite extreme points int index = 0; var value = Rational.For(0); if (vertices[0].One.IsInfinity) { index = 2; value = vertices[2].Two; for (int n = 4; n < 8; n += 2) { if (vertices[n].Two <= value) { for (int m = index; m < n; m += 2) { IsInHull[m] = false; } index = n; value = vertices[n].Two; } } } if (vertices[6].One.IsInfinity) { index = 4; value = vertices[4].Two; for (int n = 2; n >= 0; n -= 2) { if (vertices[n].Two <= value) { for (int m = index; m > n; m -= 2) { IsInHull[m] = false; } index = n; value = vertices[n].Two; } } } if (vertices[1].One.IsInfinity) { index = 3; value = vertices[3].Two; for (int n = 5; n < 8; n += 2) { if (vertices[n].Two >= value) { for (int m = index; m < n; m += 2) { IsInHull[m] = false; } index = n; value = vertices[n].Two; } } } if (vertices[7].One.IsInfinity) { index = 5; value = vertices[5].Two; for (int n = 3; n >= 0; n -= 2) { if (vertices[n].Two >= value) { for (int m = index; m > n; m -= 2) { IsInHull[m] = false; } index = n; value = vertices[n].Two; } } } #endregion #region Adding to the result the Polynomials for the edges that are in the hull and neither horizontal nor vertical var point = new PairNonNull <Rational, Rational>(); Rational c; int numberOfPointsInHull = 0; for (int k = 0; k < 8; k += 2) { if (IsInHull[k]) { if (numberOfPointsInHull > 0 && point.One != vertices[k].One && point.Two != vertices[k].Two) { try { c = (vertices[k].One - point.One) / (point.Two - vertices[k].Two); } catch (ArithmeticExceptionRational) { continue; } var list = new Monomial <Variable>[] { new Monomial <Variable>(e1), new Monomial <Variable>(c, e2), new Monomial <Variable>(slack) }; if (!Polynomial <Variable, Expression> .TryToPolynomialForm(true, list, out pol)) { throw new AbstractInterpretationException("Impossible case"); } result.Add(pol); } point = vertices[k]; numberOfPointsInHull++; } } for (int k = 1; k < 8; k += 2) { if (IsInHull[k]) { if (numberOfPointsInHull > 0 && point.One != vertices[k].One && point.Two != vertices[k].Two) { try { c = (vertices[k].One - point.One) / (point.Two - vertices[k].Two); } catch (ArithmeticExceptionRational) { continue; } var list = new Monomial <Variable>[] { new Monomial <Variable>(e1), new Monomial <Variable>(c, e2), new Monomial <Variable>(slack) }; if (!Polynomial <Variable, Expression> .TryToPolynomialForm(true, list, out pol)) { throw new AbstractInterpretationException("Impossible case"); } result.Add(pol); } point = vertices[k]; numberOfPointsInHull++; } } #endregion } catch (ArithmeticExceptionRational) { // Ignore the constraint } #endregion } } } return(result); }