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;
    }
    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;
      }
    }
Пример #4
0
 public override Answer CheckVariableDisequality(Element/*!*/ e, IVariable/*!*/ var1, IVariable/*!*/ var2) {
   //Contract.Requires(var2 != null);
   //Contract.Requires(var1 != null);
   //Contract.Requires(e != null);
   PolyhedraLatticeElement/*!*/ ple = (PolyhedraLatticeElement)cce.NonNull(e);
   Contract.Assume(ple.lcs.Constraints != null);
   ArrayList /*LinearConstraint!*//*!*/ clist = (ArrayList /*LinearConstraint!*/)cce.NonNull(ple.lcs.Constraints.Clone());
   LinearConstraint/*!*/ lc = new LinearConstraint(LinearConstraint.ConstraintRelation.EQ);
   Contract.Assert(lc != null);
   lc.SetCoefficient(var1, Rational.ONE);
   lc.SetCoefficient(var2, Rational.MINUS_ONE);
   clist.Add(lc);
   LinearConstraintSystem newLcs = new LinearConstraintSystem(clist);
   if (newLcs.IsBottom()) {
     return Answer.Yes;
   } else {
     return Answer.Maybe;
   }
 }