// --------------------------------------------------------------------------------------------------------
    // ------------------ support routines --------------------------------------------------------------------
    // --------------------------------------------------------------------------------------------------------

    /// <summary>
    /// Returns a set of constraints that is the given set of constraints with dimension "dim"
    /// projected out.  See Cousot and Halbwachs, section 3.3.1.1.
    /// </summary>
    /// <param name="dim"></param>
    /// <param name="constraints"></param>
    /// <returns></returns>
    static ArrayList /*LinearConstraint!*//*!*/ Project(IVariable/*!*/ dim, ArrayList /*LinearConstraint!*//*!*/ constraints) {
      Contract.Requires(constraints != null);
      Contract.Requires(dim != null);
      Contract.Ensures(Contract.Result<ArrayList>() != null);
      // Sort the inequality constaints into ones where dimension "dim" is 0, negative, and
      // positive, respectively.  Put equality constraints with a non-0 "dim" into "eq".
      ArrayList /*LinearConstraint!*//*!*/ final = new ArrayList /*LinearConstraint!*/ ();
      ArrayList /*LinearConstraint!*//*!*/ negative = new ArrayList /*LinearConstraint!*/ ();
      ArrayList /*LinearConstraint!*//*!*/ positive = new ArrayList /*LinearConstraint!*/ ();
      ArrayList /*LinearConstraint!*//*!*/ eq = new ArrayList /*LinearConstraint!*/ ();
      foreach (LinearConstraint/*!*/ cc in constraints) {
        Contract.Assert(cc != null);
        Rational coeff = cc[dim];
        if (coeff.IsZero) {
          LinearConstraint lc = cce.NonNull(cc.Clone());
          if (!lc.IsConstant()) {
            lc.RemoveDimension(dim);
            final.Add(lc);
          }
        } else if (cc.Relation == LinearConstraint.ConstraintRelation.EQ) {
          eq.Add(cc);
        } else if (coeff.IsNegative) {
          negative.Add(cc);
        } else {
          System.Diagnostics.Debug.Assert(coeff.IsPositive);
          positive.Add(cc);
        }
      }

      if (eq.Count != 0) {
        LinearConstraint eqConstraint = (LinearConstraint/*!*/)cce.NonNull(eq[eq.Count - 1]);
        eq.RemoveAt(eq.Count - 1);
        Rational eqC = -eqConstraint[dim];

        foreach (ArrayList /*LinearConstraint!*/ list in new ArrayList[] { eq, negative, positive }) {
          Contract.Assert(list != null);
          foreach (LinearConstraint/*!*/ lcX in list) {
            Contract.Assert(lcX != null);
            LinearConstraint lc = cce.NonNull(lcX.Clone());
            lc.AddMultiple(lc[dim] / eqC, eqConstraint);
            System.Diagnostics.Debug.Assert(lc[dim].IsZero);
            if (!lc.IsConstant()) {
              lc.RemoveDimension(dim);
              final.Add(lc);
            } else {
              System.Diagnostics.Debug.Assert(lc.IsConstantSatisfiable());
            }
          }
        }
      } else {
        // Consider all pairs of constraints with (negative,positive) coefficients of "dim".
        foreach (LinearConstraint/*!*/ cn in negative) {
          Contract.Assert(cn != null);
          Rational dn = -cn[dim];
          System.Diagnostics.Debug.Assert(dn.IsNonNegative);
          foreach (LinearConstraint/*!*/ cp in positive) {
            Contract.Assert(cp != null);
            Rational dp = cp[dim];

            LinearConstraint lc = new LinearConstraint(LinearConstraint.ConstraintRelation.LE);
            lc.AddMultiple(dn, cp);
            lc.AddMultiple(dp, cn);
            System.Diagnostics.Debug.Assert(lc[dim].IsZero);
            if (!lc.IsConstant()) {
              lc.RemoveDimension(dim);
              final.Add(lc);
            } else {
              System.Diagnostics.Debug.Assert(lc.IsConstantSatisfiable());
            }
          }
        }
      }

      return final;
    }
    public LinearConstraintSystem(ArrayList /*LinearConstraint!*//*!*/ cs) {
      Contract.Requires(cs != null);
#if BUG_159_HAS_BEEN_FIXED
      Contract.Requires(Contract.ForAll(cs) , cc=> cc.coefficients.Count != 0);
#endif

      ArrayList constraints = new ArrayList /*LinearConstraint!*/ (cs.Count);
      foreach (LinearConstraint/*!*/ cc in cs) {
        Contract.Assert(cc != null);
        constraints.Add(cc);
      }
      Constraints = constraints;
      FrameDimensions = new HashSet /*IVariable!*/ ();  // to please compiler; this value will be overridden in the call to GenerateFrameConstraints below
      //:base();

      GenerateFrameFromConstraints();
      SimplifyConstraints();
      CheckInvariant();
#if DEBUG_PRINT
      Console.WriteLine("LinearConstraintSystem: constructor produced:");
      Dump();
#endif
    }
    LinearConstraintSystem(FrameElement/*!*/ v) {
      Contract.Requires(v != null);
      IMutableSet/*!*/ frameDims = v.GetDefinedDimensions();
      Contract.Assert(frameDims != null);
      ArrayList /*LinearConstraint!*/ constraints = new ArrayList /*LinearConstraint!*/ ();
      foreach (IVariable/*!*/ dim in frameDims) {
        Contract.Assert(dim != null);
        LinearConstraint lc = new LinearConstraint(LinearConstraint.ConstraintRelation.EQ);
        lc.SetCoefficient(dim, Rational.ONE);
        lc.rhs = v[dim];
        constraints.Add(lc);
      }
      FrameDimensions = frameDims;
      Constraints = constraints;

      ArrayList /*FrameElement*/ frameVertices = new ArrayList /*FrameElement*/ ();
      frameVertices.Add(v);
      FrameVertices = frameVertices;

      FrameRays = new ArrayList /*FrameElement*/ ();
      FrameLines = new ArrayList /*FrameElement*/ ();

      //:base();
      CheckInvariant();
    }