/// <summary> /// Uses the frame to simplify Constraints. See section 3.3.1.2 of Cousot and Halbwachs. /// /// Note: This code does not necessarily eliminate all irrelevant equalities; Cousot and /// Halbwachs only claim that the technique eliminates all irrelevant inequalities. /// </summary> void SimplifyConstraints() { if (Constraints == null) { return; } Contract.Assume(this.FrameVertices != null); Contract.Assume(this.FrameRays != null); SimplificationStatus[] status = new SimplificationStatus[Constraints.Count]; /*readonly*/ int feCount = FrameVertices.Count + FrameRays.Count; // Create a table that keeps track of which constraints are satisfied by which vertices and rays bool[,] sat = new bool[Constraints.Count, FrameVertices.Count + FrameRays.Count]; for (int i = 0; i < Constraints.Count; i++) { status[i] = SimplificationStatus.Relevant; LinearConstraint lc = (LinearConstraint/*!*/)cce.NonNull(Constraints[i]); int cnt = 0; // number of vertices and rays that saturate lc for (int j = 0; j < FrameVertices.Count; j++) { FrameElement vertex = (FrameElement/*!*/)cce.NonNull(FrameVertices[j]); if (lc.IsSaturatedBy(vertex, true)) { sat[i, j] = true; cnt++; } } if (cnt == 0) { // no vertex saturates the constraint, so the constraint is irrelevant status[i] = SimplificationStatus.Irrelevant; continue; } for (int j = 0; j < FrameRays.Count; j++) { FrameElement ray = (FrameElement/*!*/)cce.NonNull(FrameRays[j]); if (lc.IsSaturatedBy(ray, false)) { sat[i, FrameVertices.Count + j] = true; cnt++; } } if (cnt == feCount) { status[i] = SimplificationStatus.More; } else { // Cousot and Halbwachs says that all equalities are found in the way we just tested. // If I understand that right, then we should not get here if the constraint is an // equality constraint. The following assertion tests my understanding. --KRML System.Diagnostics.Debug.Assert(lc.Relation == LinearConstraint.ConstraintRelation.LE); } } CheckPairSimplifications(sat, status); // Finally, make the changes to the list of constraints for (int i = Constraints.Count - 1; 0 <= i; i--) { switch (status[i]) { case SimplificationStatus.Relevant: break; case SimplificationStatus.Irrelevant: #if DEBUG_PRINT Console.WriteLine("Removing irrelevant constraint: {0}", Constraints[i]); #endif Constraints.RemoveAt(i); break; case SimplificationStatus.More: LinearConstraint lc = (LinearConstraint/*!*/)cce.NonNull(Constraints[i]); if (lc.Relation == LinearConstraint.ConstraintRelation.LE) { #if DEBUG_PRINT Console.WriteLine("Converting the following constraint into an equality: {0}", lc); #endif LinearConstraint lcEq = lc.ChangeRelation(LinearConstraint.ConstraintRelation.EQ); Constraints[i] = lcEq; } break; } } foreach (LinearConstraint/*!*/ lc in Constraints) { Contract.Assert(lc != null); lc.Normalize(); } }
/// <summary> /// Requires sat.GetLength(0) == status.Length. /// </summary> /// <param name="sat"></param> /// <param name="status"></param> static void CheckPairSimplifications(bool[,]/*!*/ sat, SimplificationStatus[]/*!*/ status) { Contract.Requires(status != null); Contract.Requires(sat != null); Contract.Requires(sat.GetLength(0) == status.Length); int M = sat.GetLength(0); int N = sat.GetLength(1); for (int i = 0; i < M - 1; i++) { if (status[i] != SimplificationStatus.Relevant) { continue; } for (int j = i + 1; j < M; j++) { if (status[j] != SimplificationStatus.Relevant) { continue; } // check (sat[i,*] <= sat[j,*]) and (sat[i,*] >= sat[j,*]) int cmp = 0; // -1: (sat[i,*] <= sat[j,*]), 0: equal, 1: (sat[i,*] >= sat[j,*]) for (int c = 0; c < N; c++) { if (cmp < 0) { if (sat[i, c] && !sat[j, c]) { // incomparable goto NEXT_PAIR; } } else if (0 < cmp) { if (!sat[i, c] && sat[j, c]) { // incomparable goto NEXT_PAIR; } } else if (sat[i, c] != sat[j, c]) { if (!sat[i, c]) { cmp = -1; } else { cmp = 1; } } } if (cmp <= 0) { // sat[i,*] <= sat[j,*] holds, so mark i as irrelevant status[i] = SimplificationStatus.Irrelevant; goto NEXT_OUTER; } else { // sat[i,*] >= sat[j,*] holds, so mark j as irrelevant status[j] = SimplificationStatus.Irrelevant; } NEXT_PAIR: { } } NEXT_OUTER: { } } }
static void RemoveIrrelevantFrameElements(ArrayList/*!*/ /*FrameElement*/ ff, SimplificationStatus[]/*!*/ status, /*maybe null*/ ArrayList /*FrameElement*/ lines) { Contract.Requires(ff != null); Contract.Requires(status != null); Contract.Requires(ff.Count == status.Length); for (int j = ff.Count - 1; 0 <= j; j--) { switch (status[j]) { case SimplificationStatus.Relevant: break; case SimplificationStatus.Irrelevant: #if DEBUG_PRINT Console.WriteLine("Removing irrelevant {0}: {1}", lines == null ? "vertex" : "ray", ff[j]); #endif ff.RemoveAt(j); break; case SimplificationStatus.More: System.Diagnostics.Debug.Assert(lines != null); FrameElement f = (FrameElement)ff[j]; #if DEBUG_PRINT Console.WriteLine("Changing ray into line: {0}", f); #endif ff.RemoveAt(j); Contract.Assert(lines != null); lines.Add(f); break; } } }
/// <summary> /// For each i, sets status[i] to: /// <ul> /// <li>Irrelevant if ff[i] is irrelevant</li> /// <li>Relevant if ff[i] is irrelevant</li> /// <li>More if vertices is true and ray ff[i] can be replaced by a line ff[i]</li> /// </ul> /// </summary> /// <param name="ff"></param> /// <param name="vertices">true if "ff" contains vertices; false if "ff" contains rays</param> /// <param name="constraints"></param> /// <param name="status"></param> static void SimplifyFrameElements(ArrayList/*!*/ /*FrameElement*/ ff, bool vertices, ArrayList/*!*/ /*LinearConstraint*/ constraints, out SimplificationStatus[]/*!*/ status) { Contract.Requires(ff != null); Contract.Requires(constraints != null); Contract.Ensures(Contract.ValueAtReturn(out status) != null); status = new SimplificationStatus[ff.Count]; bool[,] sat = new bool[ff.Count, constraints.Count]; for (int i = 0; i < ff.Count; i++) { FrameElement f = (FrameElement/*!*/)cce.NonNull(ff[i]); int cnt = 0; for (int c = 0; c < constraints.Count; c++) { LinearConstraint lc = (LinearConstraint/*!*/)cce.NonNull(constraints[c]); bool s = lc.IsSaturatedBy(f, vertices); if (s) { sat[i, c] = true; cnt++; } } if (!vertices && cnt == constraints.Count) { status[i] = SimplificationStatus.More; } else { status[i] = SimplificationStatus.Relevant; } } CheckPairSimplifications(sat, status); }