Example #1
0
 /// <summary>
 /// Adds to "lines" the lines implied by initial-variable columns not in basis
 /// (see section 3.4.2 of Cousot and Halbwachs), and adds to "constraints" the
 /// constraints to exclude those lines (see step 4.2 of section 3.4.3 of
 /// Cousot and Halbwachs).
 /// </summary>
 /// <param name="lines"></param>
 /// <param name="constraints"></param>
 public void ProduceLines(ArrayList /*FrameElement*//*!*/ lines, ArrayList /*LinearConstraint*//*!*/ constraints)
 {
     Contract.Requires(constraints != null);
     Contract.Requires(lines != null);
     // for every initial variable not in basis
     for (int i0 = 0; i0 < numInitialVars; i0++)
     {
         if (inBasis[i0] == -1)
         {
             FrameElement     fe = new FrameElement();
             LinearConstraint lc = new LinearConstraint(LinearConstraint.ConstraintRelation.EQ);
             for (int i = 0; i < numInitialVars; i++)
             {
                 if (i == i0)
                 {
                     fe.AddCoordinate((IVariable)cce.NonNull(dims[i]), Rational.ONE);
                     lc.SetCoefficient((IVariable)cce.NonNull(dims[i]), Rational.ONE);
                 }
                 else if (inBasis[i] != -1)
                 {
                     // i is a basis column
                     Contract.Assert(m[inBasis[i], i].HasValue(1));
                     Rational val = -m[inBasis[i], i0];
                     fe.AddCoordinate((IVariable)cce.NonNull(dims[i]), val);
                     lc.SetCoefficient((IVariable)cce.NonNull(dims[i]), val);
                 }
             }
             lines.Add(fe);
             constraints.Add(lc);
         }
     }
 }
Example #2
0
        public FrameElement Clone()
        {
            FrameElement z = new FrameElement();

            z.terms = (Hashtable /*IVariable->Rational*/)this.terms.Clone();
            return(z);
        }
Example #3
0
        /// <summary>
        /// Determines whether or not a given vertex or ray saturates the constraint.
        /// </summary>
        /// <param name="fe"></param>
        /// <param name="vertex">true if "fe" is a vertex; false if "fe" is a ray</param>
        /// <returns></returns>
        public bool IsSaturatedBy(FrameElement /*!*/ fe, bool vertex)
        {
            Contract.Requires(fe != null);
            Rational lhs = EvaluateLhs(fe);
            Rational rhs = vertex ? this.rhs : Rational.ZERO;

            return(lhs == rhs);
        }
Example #4
0
        /// <summary>
        /// Returns the left-hand side of the constraint evaluated at the point "v".
        /// Any coordinate not present in "v" is treated as if it were 0.
        /// Stated differently, this routine treats the left-hand side of the constraint
        /// as a row vector and "v" as a column vector, and then returns the dot-product
        /// of the two.
        /// </summary>
        /// <param name="v"></param>
        /// <returns></returns>
        public Rational EvaluateLhs(FrameElement /*!*/ v)
        {
            Contract.Requires(v != null);
            Rational q = Rational.ZERO;

            foreach (DictionaryEntry /*IVariable,Rational*/ term in coefficients)
            {
                IVariable dim = (IVariable /*!*/)cce.NonNull(term.Key);
                Rational  a   = (Rational)(cce.NonNull(term.Value));
                Rational  x   = v[dim];
                q += a * x;
            }
            return(q);
        }
Example #5
0
        public FrameElement Rename(IVariable /*!*/ oldName, IVariable /*!*/ newName)
        {
            Contract.Requires(newName != null);
            Contract.Requires(oldName != null);
            object /*Rational*/ z = terms[oldName];

            if (z == null)
            {
                return(this);
            }
            else
            {
                System.Diagnostics.Debug.Assert(z is Rational);
                Hashtable /*IVariable->Rational*/ newTerms = (Hashtable /*!*/ /*IVariable->Rational*/)cce.NonNull(terms.Clone());
                newTerms.Remove(oldName);
                newTerms.Add(newName, z);

                FrameElement fe = new FrameElement();
                fe.terms = newTerms;
                return(fe);
            }
        }
Example #6
0
 /// <summary>
 /// Determines whether or not a given vertex or ray saturates the constraint.
 /// </summary>
 /// <param name="fe"></param>
 /// <param name="vertex">true if "fe" is a vertex; false if "fe" is a ray</param>
 /// <returns></returns>
 public bool IsSaturatedBy(FrameElement/*!*/ fe, bool vertex) {
   Contract.Requires(fe != null);
   Rational lhs = EvaluateLhs(fe);
   Rational rhs = vertex ? this.rhs : Rational.ZERO;
   return lhs == rhs;
 }
Example #7
0
 /// <summary>
 /// Returns the left-hand side of the constraint evaluated at the point "v".
 /// Any coordinate not present in "v" is treated as if it were 0.
 /// Stated differently, this routine treats the left-hand side of the constraint
 /// as a row vector and "v" as a column vector, and then returns the dot-product
 /// of the two.
 /// </summary>
 /// <param name="v"></param>
 /// <returns></returns>
 public Rational EvaluateLhs(FrameElement/*!*/ v) {
   Contract.Requires(v != null);
   Rational q = Rational.ZERO;
   foreach (DictionaryEntry /*IVariable,Rational*/ term in coefficients) {
     IVariable dim = (IVariable/*!*/)cce.NonNull(term.Key);
     Rational a = (Rational)(cce.NonNull(term.Value));
     Rational x = v[dim];
     q += a * x;
   }
   return q;
 }
    /// <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
    }
Example #9
0
 /// <summary>
 /// Adds to "lines" the lines implied by initial-variable columns not in basis
 /// (see section 3.4.2 of Cousot and Halbwachs), and adds to "constraints" the
 /// constraints to exclude those lines (see step 4.2 of section 3.4.3 of
 /// Cousot and Halbwachs).
 /// </summary>
 /// <param name="lines"></param>
 /// <param name="constraints"></param>
 public void ProduceLines(ArrayList /*FrameElement*//*!*/ lines, ArrayList /*LinearConstraint*//*!*/ constraints) {
   Contract.Requires(constraints != null);
   Contract.Requires(lines != null);
   // for every initial variable not in basis
   for (int i0 = 0; i0 < numInitialVars; i0++) {
     if (inBasis[i0] == -1) {
       FrameElement fe = new FrameElement();
       LinearConstraint lc = new LinearConstraint(LinearConstraint.ConstraintRelation.EQ);
       for (int i = 0; i < numInitialVars; i++) {
         if (i == i0) {
           fe.AddCoordinate((IVariable)cce.NonNull(dims[i]), Rational.ONE);
           lc.SetCoefficient((IVariable)cce.NonNull(dims[i]), Rational.ONE);
         } else if (inBasis[i] != -1) {
           // i is a basis column
           Contract.Assert(m[inBasis[i], i].HasValue(1));
           Rational val = -m[inBasis[i], i0];
           fe.AddCoordinate((IVariable)cce.NonNull(dims[i]), val);
           lc.SetCoefficient((IVariable)cce.NonNull(dims[i]), val);
         }
       }
       lines.Add(fe);
       constraints.Add(lc);
     }
   }
 }
    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 static void RunValidationC() {
      // Run the example in section 3.4.3 of Cousot and Halbwachs backwards, that is, from
      // from to constraints.
      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 s0 = new FrameElement();
      s0.AddCoordinate(dim1, Rational.ONE);
      s0.AddCoordinate(dim2, Rational.FromInts(1, 2));
      s0.AddCoordinate(dim3, Rational.FromInts(-1, 2));

      FrameElement s1 = new FrameElement();
      s1.AddCoordinate(dim1, Rational.ONE);
      s1.AddCoordinate(dim2, Rational.FromInts(-1, 2));
      s1.AddCoordinate(dim3, Rational.FromInts(1, 2));

      FrameElement s2 = new FrameElement();
      s2.AddCoordinate(dim1, Rational.FromInt(3));
      s2.AddCoordinate(dim2, Rational.FromInts(-3, 2));
      s2.AddCoordinate(dim3, Rational.FromInts(3, 2));

      FrameElement r0 = new FrameElement();
      r0.AddCoordinate(dim1, Rational.ONE);
      r0.AddCoordinate(dim2, Rational.FromInts(1, 2));
      r0.AddCoordinate(dim3, Rational.FromInts(-1, 2));

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

      FrameElement d0 = new FrameElement();
      d0.AddCoordinate(dim1, Rational.ZERO);
      d0.AddCoordinate(dim2, Rational.ONE);
      d0.AddCoordinate(dim3, Rational.ONE);

      LinearConstraintSystem lcs = new LinearConstraintSystem(s0);
      lcs.Dump();

      lcs.AddVertex(s1);
      lcs.Dump();

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

      lcs.AddRay(r0);
      lcs.Dump();

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

      lcs.AddLine(d0);
      lcs.Dump();

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

#if LATER
      lcs.GenerateFrameFromConstraints(); // should give us back the original frame...
#endif
    }
    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();
    }
    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();
    }
    /// <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
    }
Example #15
0
    public FrameElement Rename(IVariable/*!*/ oldName, IVariable/*!*/ newName) {
      Contract.Requires(newName != null);
      Contract.Requires(oldName != null);
      object /*Rational*/ z = terms[oldName];
      if (z == null) {
        return this;
      } else {
        System.Diagnostics.Debug.Assert(z is Rational);
        Hashtable /*IVariable->Rational*/ newTerms = (Hashtable/*!*/ /*IVariable->Rational*/)cce.NonNull(terms.Clone());
        newTerms.Remove(oldName);
        newTerms.Add(newName, z);

        FrameElement fe = new FrameElement();
        fe.terms = newTerms;
        return fe;
      }
    }
Example #16
0
 public FrameElement Clone() {
   FrameElement z = new FrameElement();
   z.terms = (Hashtable /*IVariable->Rational*/)this.terms.Clone();
   return z;
 }
Example #17
0
        /// <summary>
        /// Worker method of TraverseVertices.
        /// This method has no net effect on the tableau.
        /// </summary>
        /// <param name="basesSeenSoFar"></param>
        /// <param name="vertices"></param>
        /// <param name="rays"></param>
        void TraverseBases(ArrayList /*bool[]*//*!*/ basesSeenSoFar, ArrayList /*FrameElement*//*!*/ vertices, ArrayList /*FrameElement*//*!*/ rays)
        {
            Contract.Requires(rays != null);
            Contract.Requires(vertices != null);
            Contract.Requires(basesSeenSoFar != null);
            CheckInvariant();

            bool[] thisBasis = new bool[numSlackVars];
            for (int i = numInitialVars; i < rhsColumn; i++)
            {
                if (inBasis[i] != -1)
                {
                    thisBasis[i - numInitialVars] = true;
                }
            }
            foreach (bool[] /*!*/ basis in basesSeenSoFar)
            {
                Contract.Assert(basis != null);
                Contract.Assert(basis.Length == numSlackVars);
                for (int i = 0; i < numSlackVars; i++)
                {
                    if (basis[i] != thisBasis[i])
                    {
                        goto COMPARE_WITH_NEXT_BASIS;
                    }
                }
                // thisBasis and basis are the same--that is, basisColumns has been visited before--so
                // we don't traverse anything from here
                return;

                COMPARE_WITH_NEXT_BASIS : {
                }
            }
            // basisColumns has not been seen before; record thisBasis and continue with the traversal here
            basesSeenSoFar.Add(thisBasis);

#if DEBUG_PRINT
            Console.Write("TraverseBases, new basis:  ");
            foreach (bool t in thisBasis)
            {
                Console.Write("{0}", t ? "*" : ".");
            }
            Console.WriteLine();
            Dump();
#endif
            // Add vertex
            FrameElement v = new FrameElement();
            for (int i = 0; i < rows; i++)
            {
                int j = basisColumns[i];
                if (j < numInitialVars)
                {
                    v.AddCoordinate((IVariable)cce.NonNull(dims[j]), m[i, rhsColumn]);
                }
            }
#if DEBUG_PRINT
            Console.WriteLine("  Adding vertex: {0}", v);
#endif
            vertices.Add(v);

            // Add rays.  Traverse all columns corresponding to slack variables that
            // are not in basis (see second bullet of section 3.4.2 of Cousot and Halbwachs).
            for (int i0 = numInitialVars; i0 < rhsColumn; i0++)
            {
                if (inBasis[i0] != -1)
                {
                    // skip those slack-variable columns that are in basis
                    continue;
                }
                // check if slack-variable, non-basis column i corresponds to an extreme ray
                for (int row = 0; row < rows; row++)
                {
                    if (m[row, i0].IsPositive)
                    {
                        for (int k = numInitialVars; k < rhsColumn; k++)
                        {
                            if (inBasis[k] != -1 && m[row, k].IsNonZero)
                            {
                                // does not correspond to an extreme ray
                                goto CHECK_NEXT_SLACK_VAR;
                            }
                        }
                    }
                }
                // corresponds to an extreme ray
                FrameElement ray = new FrameElement();
                for (int i = 0; i < numInitialVars; i++)
                {
                    int      j0  = inBasis[i];
                    Rational val = -m[j0, i0];
                    ray.AddCoordinate((IVariable)cce.NonNull(dims[i]), val);
                }
#if DEBUG_PRINT
                Console.WriteLine("  Adding ray: {0}", ray);
#endif
                rays.Add(ray);
                CHECK_NEXT_SLACK_VAR : {
                }
            }

            // Continue traversal
            for (int i = numInitialVars; i < rhsColumn; i++)
            {
                int j = inBasis[i];
                if (j != -1)
                {
                    // try moving i out of basis and some other slack-variable column into basis
                    for (int k = numInitialVars; k < rhsColumn; k++)
                    {
                        if (inBasis[k] == -1 && m[j, k].IsPositive)
                        {
                            Rational[] undo = Pivot(j, k);
                            // check if the new basis is feasible
                            for (int p = 0; p < rows; p++)
                            {
                                int c = basisColumns[p];
                                if (numInitialVars <= c && c < rhsColumn && m[p, rhsColumn].IsNegative)
                                {
                                    // not feasible
                                    goto AFTER_TRAVERSE;
                                }
                            }
                            TraverseBases(basesSeenSoFar, vertices, rays);
AFTER_TRAVERSE:
                            UnPivot(j, k, undo);
                        }
                    }
                }
            }
        }
Example #18
0
    /// <summary>
    /// Worker method of TraverseVertices.
    /// This method has no net effect on the tableau.
    /// </summary>
    /// <param name="basesSeenSoFar"></param>
    /// <param name="vertices"></param>
    /// <param name="rays"></param>
    void TraverseBases(ArrayList /*bool[]*//*!*/ basesSeenSoFar, ArrayList /*FrameElement*//*!*/ vertices, ArrayList /*FrameElement*//*!*/ rays) {
      Contract.Requires(rays != null);
      Contract.Requires(vertices != null);
      Contract.Requires(basesSeenSoFar != null);
      CheckInvariant();

      bool[] thisBasis = new bool[numSlackVars];
      for (int i = numInitialVars; i < rhsColumn; i++) {
        if (inBasis[i] != -1) {
          thisBasis[i - numInitialVars] = true;
        }
      }
      foreach (bool[]/*!*/ basis in basesSeenSoFar) {
        Contract.Assert(basis != null);
        Contract.Assert(basis.Length == numSlackVars);
        for (int i = 0; i < numSlackVars; i++) {
          if (basis[i] != thisBasis[i]) {
            goto COMPARE_WITH_NEXT_BASIS;
          }
        }
        // thisBasis and basis are the same--that is, basisColumns has been visited before--so
        // we don't traverse anything from here
        return;
      COMPARE_WITH_NEXT_BASIS: {
        }
      }
      // basisColumns has not been seen before; record thisBasis and continue with the traversal here
      basesSeenSoFar.Add(thisBasis);

#if DEBUG_PRINT
      Console.Write("TraverseBases, new basis:  ");
      foreach (bool t in thisBasis) {
        Console.Write("{0}", t ? "*" : ".");
      }
      Console.WriteLine();
      Dump();
#endif
      // Add vertex
      FrameElement v = new FrameElement();
      for (int i = 0; i < rows; i++) {
        int j = basisColumns[i];
        if (j < numInitialVars) {
          v.AddCoordinate((IVariable)cce.NonNull(dims[j]), m[i, rhsColumn]);
        }
      }
#if DEBUG_PRINT
      Console.WriteLine("  Adding vertex: {0}", v);
#endif
      vertices.Add(v);

      // Add rays.  Traverse all columns corresponding to slack variables that
      // are not in basis (see second bullet of section 3.4.2 of Cousot and Halbwachs).
      for (int i0 = numInitialVars; i0 < rhsColumn; i0++) {
        if (inBasis[i0] != -1) {
          // skip those slack-variable columns that are in basis
          continue;
        }
        // check if slack-variable, non-basis column i corresponds to an extreme ray
        for (int row = 0; row < rows; row++) {
          if (m[row, i0].IsPositive) {
            for (int k = numInitialVars; k < rhsColumn; k++) {
              if (inBasis[k] != -1 && m[row, k].IsNonZero) {
                // does not correspond to an extreme ray
                goto CHECK_NEXT_SLACK_VAR;
              }
            }
          }
        }
        // corresponds to an extreme ray
        FrameElement ray = new FrameElement();
        for (int i = 0; i < numInitialVars; i++) {
          int j0 = inBasis[i];
          Rational val = -m[j0, i0];
          ray.AddCoordinate((IVariable)cce.NonNull(dims[i]), val);
        }
#if DEBUG_PRINT
        Console.WriteLine("  Adding ray: {0}", ray);
#endif
        rays.Add(ray);
      CHECK_NEXT_SLACK_VAR: {
        }
      }

      // Continue traversal
      for (int i = numInitialVars; i < rhsColumn; i++) {
        int j = inBasis[i];
        if (j != -1) {
          // try moving i out of basis and some other slack-variable column into basis
          for (int k = numInitialVars; k < rhsColumn; k++) {
            if (inBasis[k] == -1 && m[j, k].IsPositive) {
              Rational[] undo = Pivot(j, k);
              // check if the new basis is feasible
              for (int p = 0; p < rows; p++) {
                int c = basisColumns[p];
                if (numInitialVars <= c && c < rhsColumn && m[p, rhsColumn].IsNegative) {
                  // not feasible
                  goto AFTER_TRAVERSE;
                }
              }
              TraverseBases(basesSeenSoFar, vertices, rays);
            AFTER_TRAVERSE:
              UnPivot(j, k, undo);
            }
          }
        }
      }
    }
    /// <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
    }