public LinearConstraintSystem/*!*/ Join(LinearConstraintSystem/*!*/ lcs) { Contract.Requires(lcs != null); Contract.Ensures(Contract.Result<LinearConstraintSystem>() != null); #endif if (this.IsBottom()) { return cce.NonNull(lcs.Clone()); } else if (lcs.IsBottom()) { return cce.NonNull(this.Clone()); } else if (this.IsTop() || lcs.IsTop()) { return new LinearConstraintSystem(new ArrayList /*LinearConstraint*/ ()); } else { LinearConstraintSystem/*!*/ z; // Start from the "larger" of the two frames (this is just a heuristic measure intended // to save work). Contract.Assume(this.FrameVertices != null); Contract.Assume(this.FrameRays != null); Contract.Assume(this.FrameLines != null); Contract.Assume(lcs.FrameVertices != null); Contract.Assume(lcs.FrameRays != null); Contract.Assume(lcs.FrameLines != null); if (this.FrameVertices.Count + this.FrameRays.Count + this.FrameLines.Count - this.FrameDimensions.Count < lcs.FrameVertices.Count + lcs.FrameRays.Count + lcs.FrameLines.Count - lcs.FrameDimensions.Count) { z = cce.NonNull(lcs.Clone()); lcs = this; } else { z = cce.NonNull(this.Clone()); } #if DEBUG_PRINT Console.WriteLine("DEBUG: LinearConstraintSystem.Join ---------------"); Console.WriteLine("z:"); z.Dump(); Console.WriteLine("lcs:"); lcs.Dump(); #endif // Start by explicating the implicit lines of z for the dimensions dims(lcs)-dims(z). foreach (IVariable/*!*/ dim in lcs.FrameDimensions) { Contract.Assert(dim != null); if (!z.FrameDimensions.Contains(dim)) { z.FrameDimensions.Add(dim); FrameElement line = new FrameElement(); line.AddCoordinate(dim, Rational.ONE); // Note: AddLine is not called (because the line already exists in z--it's just that // it was represented implicitly). Instead, just tack the explicit representation onto // FrameLines. Contract.Assume(z.FrameLines != null); z.FrameLines.Add(line); #if DEBUG_PRINT Console.WriteLine("Join: After explicating line: {0}", line); z.Dump(); #endif } } // Now, the vertices, rays, and lines can be added. foreach (FrameElement/*!*/ v in lcs.FrameVertices) { Contract.Assert(v != null); z.AddVertex(v); #if DEBUG_PRINT Console.WriteLine("Join: After adding vertex: {0}", v); z.Dump(); #endif } foreach (FrameElement/*!*/ r in lcs.FrameRays) { Contract.Assert(r != null); z.AddRay(r); #if DEBUG_PRINT Console.WriteLine("Join: After adding ray: {0}", r); z.Dump(); #endif } foreach (FrameElement/*!*/ l in lcs.FrameLines) { Contract.Assert(l != null); z.AddLine(l); #if DEBUG_PRINT Console.WriteLine("Join: After adding line: {0}", l); z.Dump(); #endif } // also add to z the implicit lines of lcs foreach (IVariable/*!*/ dim in z.FrameDimensions) { Contract.Assert(dim != null); if (!lcs.FrameDimensions.Contains(dim)) { // "dim" is a dimension that's explicit in "z" but implicit in "lcs" FrameElement line = new FrameElement(); line.AddCoordinate(dim, Rational.ONE); z.AddLine(line); #if DEBUG_PRINT Console.WriteLine("Join: After adding lcs's implicit line: {0}", line); z.Dump(); #endif } } z.SimplifyFrame(); z.SimplifyConstraints(); z.CheckInvariant(); #if DEBUG_PRINT Console.WriteLine("Join: Returning z:"); z.Dump(); Console.WriteLine("----------------------------------------"); #endif return z; } }
public LinearConstraintSystem/*!*/ Widen(LinearConstraintSystem/*!*/ lcs) { Contract.Requires(lcs != null); Contract.Ensures(Contract.Result<LinearConstraintSystem>() != null); #endif if (this.IsBottom()) { return cce.NonNull(lcs.Clone()); } else if (lcs.IsBottom()) { return cce.NonNull(this.Clone()); } else if (this.IsTop() || lcs.IsTop()) { return new LinearConstraintSystem(new ArrayList /*LinearConstraint*/ ()); } // create new LCS, we will add only verified constraints to this... ArrayList /*LinearConstraint*/ newConstraints = new ArrayList /*LinearConstraint*/ (); Contract.Assume(this.Constraints != null); foreach (LinearConstraint/*!*/ ccX in this.Constraints) { Contract.Assert(ccX != null); LinearConstraint cc = ccX; #if DEBUG_PRINT Console.WriteLine("Widen checking: Starting to check constraint: {0}", cc); #endif if (cc.IsConstant()) { // (Can this ever occur in the stable state of a LinearConstraintSystem? --KRML) // constraint is unaffected by the frame components #if DEBUG_PRINT Console.WriteLine("Widen checking: --Adding it!"); #endif newConstraints.Add(cc); continue; } // PHASE I: verify constraints against all frame vertices... foreach (FrameElement/*!*/ vertex in cce.NonNull(lcs.FrameVertices)) { Contract.Assert(vertex != null); Rational lhs = cc.EvaluateLhs(vertex); if (lhs > cc.rhs) { // the vertex does not satisfy the inequality <= if (cc.Relation == LinearConstraint.ConstraintRelation.LE) { #if DEBUG_PRINT Console.WriteLine("Widen checking: throwing out because of vertex: {0}", vertex); #endif goto CHECK_NEXT_CONSTRAINT; } else { // ... but it does satisfy the inequality >= #if DEBUG_PRINT Console.WriteLine("Widen checking: throwing out <= because of vertex: {0}", vertex); #endif cc = cc.ChangeRelationToAtLeast(); #if DEBUG_PRINT Console.WriteLine("Widen checking: left with constraint: {0}", cc); #endif } } else if (cc.Relation == LinearConstraint.ConstraintRelation.EQ && lhs < cc.rhs) { // the vertex does not satisfy the inequality >=, and the constraint is an equality constraint #if DEBUG_PRINT Console.WriteLine("Widen checking: throwing out >= because of vertex: {0}", vertex); #endif cc = cc.ChangeRelation(LinearConstraint.ConstraintRelation.LE); #if DEBUG_PRINT Console.WriteLine("Widen checking: left with contraint: {0}", cc); #endif } } // PHASE II: verify constraints against all frame rays... foreach (FrameElement/*!*/ ray in cce.NonNull(lcs.FrameRays)) { Contract.Assert(ray != null); // The following assumes the constraint to have some dimension with a non-zero coefficient Rational lhs = cc.EvaluateLhs(ray); if (lhs.IsPositive) { // the ray does not satisfy the inequality <= if (cc.Relation == LinearConstraint.ConstraintRelation.LE) { #if DEBUG_PRINT Console.WriteLine("Widen checking: throwing out because of ray: {0}", ray); #endif goto CHECK_NEXT_CONSTRAINT; } else { // ... but it does satisfy the inequality >= #if DEBUG_PRINT Console.WriteLine("Widen checking: throwing out <= because of ray: {0}", ray); #endif cc = cc.ChangeRelationToAtLeast(); #if DEBUG_PRINT Console.WriteLine("Widen checking: left with contraint: {0}", cc); #endif } } else if (cc.Relation == LinearConstraint.ConstraintRelation.EQ && lhs.IsNegative) { // the ray does not satisfy the inequality >=, and the constraint is an equality constraint #if DEBUG_PRINT Console.WriteLine("Widen checking: throwing out >= because of ray: {0}", ray); #endif cc = cc.ChangeRelation(LinearConstraint.ConstraintRelation.LE); #if DEBUG_PRINT Console.WriteLine("Widen checking: left with constraint: {0}", cc); #endif } } // PHASE III: verify constraints against all frame lines... foreach (FrameElement/*!*/ line in cce.NonNull(lcs.FrameLines)) { Contract.Assert(line != null); // The following assumes the constraint to have some dimension with a non-zero coefficient Rational lhs = cc.EvaluateLhs(line); if (!lhs.IsZero) { // The line satisfies neither the inequality <= nor the equality == #if DEBUG_PRINT Console.WriteLine("Widen checking: throwing out because of line: {0}", line); #endif goto CHECK_NEXT_CONSTRAINT; } } // constraint has been verified, so add to new constraint system #if DEBUG_PRINT Console.WriteLine("Widen checking: --Adding it!"); #endif newConstraints.Add(cc); CHECK_NEXT_CONSTRAINT: { } #if DEBUG_PRINT Console.WriteLine("Widen checking: done with that constraint"); #endif } return new LinearConstraintSystem(newConstraints); }
/* IsSubset(): determines if 'lcs' is a subset of 'this' * -- See Cousot/Halbwachs 1978, section */ public bool IsSubset(LinearConstraintSystem/*!*/ lcs) { Contract.Requires(lcs != null); if (lcs.IsBottom()) { return true; } else if (this.IsBottom()) { return false; #if DEBUG #else } else if (this.IsTop()) { // optimization -- this case not needed for correctness return true; } else if (lcs.IsTop()) { // optimization -- this case not needed for correctness return false; #endif } else { // phase 0: check if frame dimensions are a superset of the constraint dimensions ISet /*IVariable!*//*!*/ frameDims = lcs.GetDefinedDimensions(); Contract.Assert(frameDims != null); #if DEBUG_PRINT Console.WriteLine("DEBUG: IsSubset:"); Console.WriteLine(" --- this:"); this.Dump(); Console.WriteLine(" --- lcs:"); lcs.Dump(); Console.WriteLine(" ---"); #endif foreach (LinearConstraint/*!*/ cc in cce.NonNull(this.Constraints)) { Contract.Assert(cc != null); #if DEBUG_PRINT Console.WriteLine(" cc: {0}", cc); Console.WriteLine(" cc.GetDefinedDimensions(): {0}", cc.GetDefinedDimensions()); #endif if (!Contract.ForAll(cc.GetDefinedDimensionsGeneric(), var => frameDims.Contains(var))) { #if DEBUG_PRINT Console.WriteLine(" ---> phase 0 subset violated, return false from IsSubset"); #endif return false; } } } // phase 1: check frame vertices against each constraint... foreach (FrameElement/*!*/ v in cce.NonNull(lcs.FrameVertices)) { Contract.Assert(v != null); foreach (LinearConstraint/*!*/ cc in this.Constraints) { Contract.Assert(cc != null); Rational q = cc.EvaluateLhs(v); if (cc.Relation == LinearConstraint.ConstraintRelation.LE) { if (!(q <= cc.rhs)) { #if DEBUG_PRINT Console.WriteLine(" ---> phase 1a subset violated, return false from IsSubset"); #endif return false; } } else { if (!(q == cc.rhs)) { #if DEBUG_PRINT Console.WriteLine(" ---> phase 1b subset violated, return false from IsSubset"); #endif return false; } } } } // phase 2: check frame rays against each constraint... // To check if a ray "r" falls within a constraint "cc", we add the vector "r" to // any point "p" on the side of the half-space or plane described by constraint, and // then check if the resulting point satisfies the constraint. That is, we check (for // an inequality constraint with coefficients a1,a2,...,an and right-hand side // constant C): // a1*(r1+p1) + a2*(r2+p2) + ... + an*(rn+pn) <= C // Equivalently: // a1*r1 + a2*r2 + ... + an*rn + a1*p1 + a2*p2 + ... + an*pn <= C // To find a point "p", we can pick out a coordinate, call it 1, with a non-zero // coefficient in the constraint, and then choose "p" as the point that has the // value C/a1 in coordinate 1 and has 0 in all other coordinates. We then check: // a1*r1 + a2*r2 + ... + an*rn + a1*(C/a1) + a2*0 + ... + an*0 <= C // which simplifies to: // a1*r1 + a2*r2 + ... + an*rn + C <= C // which in turn simplifies to: // a1*r1 + a2*r2 + ... + an*rn <= 0 // If the constraint is an equality constraint, we simply replace "<=" with "==" // above. foreach (FrameElement/*!*/ r in cce.NonNull(lcs.FrameRays)) { Contract.Assert(r != null); System.Diagnostics.Debug.Assert(r != null, "encountered a null ray..."); foreach (LinearConstraint/*!*/ cc in this.Constraints) { Contract.Assert(cc != null); System.Diagnostics.Debug.Assert(cc != null, "encountered an null constraint..."); Rational q = cc.EvaluateLhs(r); if (cc.Relation == LinearConstraint.ConstraintRelation.LE) { if (q.IsPositive) { #if DEBUG_PRINT Console.WriteLine(" ---> phase 2a subset violated, return false from IsSubset"); #endif return false; } } else { if (q.IsNonZero) { #if DEBUG_PRINT Console.WriteLine(" ---> phase 2b subset violated, return false from IsSubset"); #endif return false; } } } } // phase 3: check frame lines against each constraint... // To check if a line "L" falls within a constraint "cc", we check if both the // vector "L" and "-L", interpreted as rays, fall within the constraint. From // the discussion above, this means we check the following two properties: // a1*L1 + a2*L2 + ... + an*Ln <= 0 (*) // a1*(-L1) + a2*(-L2) + ... + an*(-Ln) <= 0 // The second of these lines can be rewritten as: // - a1*L1 - a2*L2 - ... - an*Ln <= 0 // which is equivalent to: // -1 * (a1*L1 + a2*L2 + ... + an*Ln) <= 0 // Multiplying both sides by -1 and flipping the direction of the inequality, // we have: // a1*L1 + a2*L2 + ... + an*Ln >= 0 (**) // Putting (*) and (**) together, we conclude that we need to check: // a1*L1 + a2*L2 + ... + an*Ln == 0 // If the constraint is an equality constraint, we end up with the same equation. foreach (FrameElement/*!*/ line in cce.NonNull(lcs.FrameLines)) { Contract.Assert(line != null); System.Diagnostics.Debug.Assert(line != null, "encountered a null line..."); foreach (LinearConstraint/*!*/ cc in this.Constraints) { Contract.Assert(cc != null); System.Diagnostics.Debug.Assert(cc != null, "encountered an null constraint..."); Rational q = cc.EvaluateLhs(line); if (q.IsNonZero) { #if DEBUG_PRINT Console.WriteLine(" ---> phase 3 subset violated, return false from IsSubset"); #endif return false; } } } #if DEBUG_PRINT Console.WriteLine(" ---> IsSubset returns true"); #endif return true; }