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);
    }
    public static void RunValidationA() {
      IVariable/*!*/ dim1 = new TestVariable("X");
      IVariable/*!*/ dim2 = new TestVariable("Y");
      IVariable/*!*/ dim3 = new TestVariable("Z");
      Contract.Assert(dim1 != null);
      Contract.Assert(dim2 != null);
      Contract.Assert(dim3 != null);

      FrameElement s1 = new FrameElement();
      s1.AddCoordinate(dim1, Rational.ONE);
      s1.AddCoordinate(dim2, Rational.MINUS_ONE);
      s1.AddCoordinate(dim3, Rational.ZERO);
      FrameElement s2 = new FrameElement();
      s2.AddCoordinate(dim1, Rational.MINUS_ONE);
      s2.AddCoordinate(dim2, Rational.ONE);
      s2.AddCoordinate(dim3, Rational.ZERO);
      FrameElement r1 = new FrameElement();
      r1.AddCoordinate(dim1, Rational.ZERO);
      r1.AddCoordinate(dim2, Rational.ZERO);
      r1.AddCoordinate(dim3, Rational.ONE);
      FrameElement d1 = new FrameElement();
      d1.AddCoordinate(dim1, Rational.ONE);
      d1.AddCoordinate(dim2, Rational.ONE);
      d1.AddCoordinate(dim3, Rational.ZERO);

      // create lcs from frame -- cf. Cousot/Halbwachs 1978, section 3.3.1.1
      LinearConstraintSystem lcs = new LinearConstraintSystem(s1);
      lcs.Dump();

      lcs.AddVertex(s2);
      lcs.Dump();

      lcs.AddRay(r1);
      lcs.Dump();

      lcs.AddLine(d1);
      lcs.Dump();

      lcs.SimplifyConstraints();
      lcs.Dump();

#if LATER
      lcs.GenerateFrameFromConstraints(); // should give us back the original frame...
#endif
      Console.WriteLine("IsSubset? {0}", lcs.IsSubset(lcs.Clone()));
      lcs.Dump();
    }