/// <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 }