/// <summary>
    /// Adds a ray to the frame of "this" and updates Constraints accordingly, see
    /// Cousot and Halbwachs, section 3.3.1.1.  However, this method does not simplify
    /// Constraints after the operation; that remains the caller's responsibility (which
    /// gives the caller the opportunity to make multiple calls to AddVertex, AddRay,
    /// and AddLine before calling SimplifyConstraints).
    /// Assumes Constraints (and the frame fields) to be non-null.
    /// </summary>
    /// <param name="ray"></param>
    void AddRay(FrameElement/*!*/ ray) {
      Contract.Requires(ray != null);
      Contract.Requires(this.FrameRays != null);
#if DEBUG_PRINT
      Console.WriteLine("DEBUG: AddRay called on {0}", ray);
      Console.WriteLine("  Initial constraints:");
      foreach (LinearConstraint cc in Constraints) {
        Console.WriteLine("    {0}", cc);
      }
#endif

      FrameRays.Add(ray.Clone());
#if FIXED_DESERIALIZER      
      Contract.Assert(Contract.ForAll(ray.GetDefinedDimensions() , var=> FrameDimensions.Contains(var)));
#endif

      // We use a new temporary dimension.
      IVariable/*!*/ lambda = new LambdaDimension();

      // We change the constraints A*X <= B into
      //     A*X - (A*ray)*lambda <= B.
      // That means that each row k in A (which corresponds to one LinearConstraint
      // in Constraints) is changed by subtracting
      //     (A*ray)[k] * lambda
      // from row k.
      // Note:
      //     (A*ray)[k]
      //  =      { A*ray is a row vector whose every row i is the dot-product of
      //           row i of A with the column vector "ray" }
      //     A[k]*ray
      foreach (LinearConstraint/*!*/ cc in cce.NonNull(Constraints)) {
        Contract.Assert(cc != null);
        Rational d = cc.EvaluateLhs(ray);
        cc.SetCoefficient(lambda, -d);
      }

      // We also add the constraints that lambda is at least 0.
      LinearConstraint la = new LinearConstraint(LinearConstraint.ConstraintRelation.LE);
      la.SetCoefficient(lambda, Rational.MINUS_ONE);
      la.rhs = Rational.ZERO;
      Constraints.Add(la);
#if DEBUG_PRINT
      Console.WriteLine("  Constraints after addition:");
      foreach (LinearConstraint cc in Constraints) {
        Console.WriteLine("    {0}", cc);
      }
#endif

      // Finally, project out the dummy dimension.
      Constraints = Project(lambda, Constraints);

#if DEBUG_PRINT
      Console.WriteLine("  Resulting constraints:");
      foreach (LinearConstraint cc in Constraints) {
        Console.WriteLine("    {0}", cc);
      }
#endif
    }
    /// <summary>
    /// Adds a line to the frame of "this" and updates Constraints accordingly, see
    /// Cousot and Halbwachs, section 3.3.1.1.  However, this method does not simplify
    /// Constraints after the operation; that remains the caller's responsibility (which
    /// gives the caller the opportunity to make multiple calls to AddVertex, AddRay,
    /// and AddLine before calling SimplifyConstraints).
    /// Assumes Constraints (and the frame fields) to be non-null.
    /// </summary>
    /// <param name="line"></param>
    void AddLine(FrameElement/*!*/ line) {
      Contract.Requires(line != null);
      Contract.Requires(this.FrameLines != null);
      // Note:  The code for AddLine is identical to that of AddRay, except the AddLine
      // does not introduce the constraint 0 <= lambda.  (One could imagine sharing the
      // code between AddRay and AddLine.)
#if DEBUG_PRINT
      Console.WriteLine("DEBUG: AddLine called on {0}", line);
      Console.WriteLine("  Initial constraints:");
      foreach (LinearConstraint cc in Constraints) {
        Console.WriteLine("    {0}", cc);
      }
#endif

      FrameLines.Add(line.Clone());
#if FIXED_DESERIALIZER      
      Contract.Assert(Contract.ForAll(line.GetDefinedDimensions() , var=> FrameDimensions.Contains(var)));
#endif

      // We use a new temporary dimension.
      IVariable/*!*/ lambda = new LambdaDimension();

      // We change the constraints A*X <= B into
      //     A*X - (A*line)*lambda <= B.
      // That means that each row k in A (which corresponds to one LinearConstraint
      // in Constraints) is changed by subtracting
      //     (A*line)[k] * lambda
      // from row k.
      // Note:
      //     (A*line)[k]
      //  =      { A*line is a row vector whose every row i is the dot-product of
      //           row i of A with the column vector "line" }
      //     A[k]*line
      foreach (LinearConstraint/*!*/ cc in cce.NonNull(Constraints)) {
        Contract.Assert(cc != null);
        Rational d = cc.EvaluateLhs(line);
        cc.SetCoefficient(lambda, -d);
      }

#if DEBUG_PRINT
      Console.WriteLine("  Constraints after addition:");
      foreach (LinearConstraint cc in Constraints) {
        Console.WriteLine("    {0}", cc);
      }
#endif

      // Finally, project out the dummy dimension.
      Constraints = Project(lambda, Constraints);

#if DEBUG_PRINT
      Console.WriteLine("  Resulting constraints:");
      foreach (LinearConstraint cc in Constraints) {
        Console.WriteLine("    {0}", cc);
      }
#endif
    }
    /// <summary>
    /// Adds a vertex to the frame of "this" and updates Constraints accordingly, see
    /// Cousot and Halbwachs, section 3.3.1.1.  However, this method does not simplify
    /// Constraints after the operation; that remains the caller's responsibility (which
    /// gives the caller the opportunity to make multiple calls to AddVertex, AddRay,
    /// and AddLine before calling SimplifyConstraints).
    /// Assumes Constraints (and the frame fields) to be non-null.
    /// </summary>
    /// <param name="vertex"></param>
    void AddVertex(FrameElement/*!*/ vertex) {
      Contract.Requires(vertex != null);
      Contract.Requires(this.FrameVertices != null);
#if DEBUG_PRINT
      Console.WriteLine("DEBUG: AddVertex called on {0}", vertex);
      Console.WriteLine("  Initial constraints:");
      foreach (LinearConstraint cc in Constraints) {
        Console.WriteLine("    {0}", cc);
      }
#endif

      FrameVertices.Add(vertex.Clone());
#if FIXED_DESERIALIZER      
      Contract.Assert(Contract.ForAll(vertex.GetDefinedDimensions() , var=> FrameDimensions.Contains(var)));
#endif

      // We use a new temporary dimension.
      IVariable/*!*/ lambda = new LambdaDimension();

      // We change the constraints A*X <= B into
      //     A*X + (A*vector - B)*lambda <= A*vector.
      // That means that each row k in A (which corresponds to one LinearConstraint
      // in Constraints) is changed by adding
      //     (A*vector - B)[k] * lambda
      // to row k and changing the right-hand side of row k to
      //     (A*vector)[k]
      // Note:
      //     (A*vector - B)[k]
      //  =      { vector subtraction is pointwise }
      //     (A*vector)[k] - B[k]
      //  =      { A*vector is a row vector whose every row i is the dot-product of
      //           row i of A with the column vector "vector" }
      //     A[k]*vector - B[k]
      foreach (LinearConstraint/*!*/ cc in cce.NonNull(Constraints)) {
        Contract.Assert(cc != null);
        Rational d = cc.EvaluateLhs(vertex);
        cc.SetCoefficient(lambda, d - cc.rhs);
        cc.rhs = d;
      }

      // We also add the constraints that lambda lies between 0 ...
      LinearConstraint la = new LinearConstraint(LinearConstraint.ConstraintRelation.LE);
      la.SetCoefficient(lambda, Rational.MINUS_ONE);
      la.rhs = Rational.ZERO;
      Constraints.Add(la);
      // ... and 1.
      la = new LinearConstraint(LinearConstraint.ConstraintRelation.LE);
      la.SetCoefficient(lambda, Rational.ONE);
      la.rhs = Rational.ONE;
      Constraints.Add(la);
#if DEBUG_PRINT
      Console.WriteLine("  Constraints after addition:");
      foreach (LinearConstraint cc in Constraints) {
        Console.WriteLine("    {0}", cc);
      }
#endif

      // Finally, project out the dummy dimension.
      Constraints = Project(lambda, Constraints);

#if DEBUG_PRINT
      Console.WriteLine("  Resulting constraints:");
      foreach (LinearConstraint cc in Constraints) {
        Console.WriteLine("    {0}", cc);
      }
#endif
    }