public override void ComputeFreeVariables(Set freeVars) { //Contract.Requires(freeVars != null); foreach (var e in Rhss) { e.ComputeFreeVariables(freeVars); } foreach (var v in Dummies) { Contract.Assert(v != null); Contract.Assert(!freeVars[v]); } foreach (var v in Dummies) { freeVars.AddRange(v.TypedIdent.Type.FreeVariables); } for (var a = Attributes; a != null; a = a.Next) { foreach (var o in a.Params) { var e = o as Expr; if (e != null) { e.ComputeFreeVariables(freeVars); } } } Body.ComputeFreeVariables(freeVars); freeVars.RemoveRange(Dummies); }
/// <summary> /// Add to "freeVars" the free variables in the triggering expressions. /// </summary> public void ComputeFreeVariables(Set /*Variable*/ freeVars) { Contract.Requires(freeVars != null); foreach (Expr /*!*/ e in this.Tr) { Contract.Assert(e != null); e.ComputeFreeVariables(freeVars); } }
public override Expr VisitOldExpr(OldExpr node) { Set freeVars = new Set(); node.Expr.ComputeFreeVariables(freeVars); foreach (var v in freeVars) { // Note, "v" is either a Variable or a TypeVariable if (v is Variable) { FreeOldVars.Add((Variable) v); } } return node; // don't visit subexpressions, since ComputeFreeVariables has already gone through those }
/// <summary> /// Performs lambda lifting (see <see cref="LambdaHelper.ExpandLambdas"/>) by replacing the lambda's /// free variables with bound ones. /// </summary> /// <param name="lambda">A lambda expression /// <code>(lambda x1: T1 ... x_n: T_n :: t)</code> /// where <c>t</c> contains the free variables <c>y1</c>, ..., <c>y_m</c>. /// </param> /// <returns> /// <list type="bullet"> /// <item> /// A function application <c>f(y1, ..., y_m)</c> where <c>f</c>'s body is defined to be the result of /// replacing the free variables <c>y1</c>, ..., <c>y_m</c> in <c>t</c> with bound variables /// <c>b1</c>, ..., <c>b_m</c>. /// </item> /// <item> /// Adds a definition and axiom for <c>f</c> to <see cref="lambdaFunctions"/> and <see cref="lambdaAxioms"/>. /// Memoizes <c>f</c> as the lifted lambda for <para>lambda</para>. /// </item> /// </list> /// </returns> private Expr LiftLambdaFreeVars(LambdaExpr lambda) { // We start by getting rid of any use of "old" inside the lambda. This is done as follows. // For each variable "g" occurring inside lambda as "old(... g ...)", create a new name "og". // Replace each old occurrence of "g" with "og", removing the enclosing "old" wrappers. var oldFinder = new OldFinder(); oldFinder.Visit(lambda); var oldSubst = new Dictionary<Variable, Expr>(); // g -> g0 var callOldMapping = new Dictionary<Variable, Expr>(); // g0 -> old(g) foreach (var v in oldFinder.FreeOldVars) { var g = v as GlobalVariable; if (g != null) { var g0 = new GlobalVariable(g.tok, new TypedIdent(g.tok, g.TypedIdent.Name + "@old", g.TypedIdent.Type)); oldSubst.Add(g, new IdentifierExpr(g0.tok, g0)); callOldMapping.Add(g0, new OldExpr(g0.tok, new IdentifierExpr(g.tok, g))); } } var lambdaBody = Substituter.ApplyReplacingOldExprs( Substituter.SubstitutionFromDictionary(new Dictionary<Variable, Expr>()), Substituter.SubstitutionFromDictionary(oldSubst), lambda.Body); var lambdaAttrs = Substituter.ApplyReplacingOldExprs( Substituter.SubstitutionFromDictionary(new Dictionary<Variable, Expr>()), Substituter.SubstitutionFromDictionary(oldSubst), lambda.Attributes); if (0 < CommandLineOptions.Clo.VerifySnapshots && QKeyValue.FindStringAttribute(lambdaAttrs, "checksum") == null) { // Attach a dummy checksum to avoid issues in the dependency analysis. var checksumAttr = new QKeyValue(lambda.tok, "checksum", new List<object> {"lambda expression"}, null); if (lambdaAttrs == null) { lambdaAttrs = checksumAttr; } else { lambdaAttrs.AddLast(checksumAttr); } } // this is ugly, the output will depend on hashing order var subst = new Dictionary<Variable, Expr>(); var substFnAttrs = new Dictionary<Variable, Expr>(); var formals = new List<Variable>(); var callArgs = new List<Expr>(); var axCallArgs = new List<Expr>(); var dummies = new List<Variable>(lambda.Dummies); var freeTypeVars = new List<TypeVariable>(); var fnTypeVarActuals = new List<Type /*!*/>(); var freshTypeVars = new List<TypeVariable>(); // these are only used in the lambda@n function's definition // compute the free variables of the lambda expression, but with lambdaBody instead of lambda.Body Set freeVars = new Set(); BinderExpr.ComputeBinderFreeVariables(lambda.TypeParameters, lambda.Dummies, lambdaBody, null, lambdaAttrs, freeVars); foreach (object o in freeVars) { // 'o' is either a Variable or a TypeVariable. if (o is Variable) { var v = o as Variable; var ti = new TypedIdent(v.TypedIdent.tok, v.TypedIdent.Name, v.TypedIdent.Type); var f = new Formal(v.tok, ti, true); formals.Add(f); substFnAttrs.Add(v, new IdentifierExpr(f.tok, f)); var b = new BoundVariable(v.tok, ti); dummies.Add(b); if (callOldMapping.ContainsKey(v)) { callArgs.Add(callOldMapping[v]); } else { callArgs.Add(new IdentifierExpr(v.tok, v)); } Expr id = new IdentifierExpr(b.tok, b); subst.Add(v, id); axCallArgs.Add(id); } else { var tv = (TypeVariable) o; freeTypeVars.Add(tv); fnTypeVarActuals.Add(tv); freshTypeVars.Add(new TypeVariable(tv.tok, tv.Name)); } } var sw = new System.IO.StringWriter(); var wr = new TokenTextWriter(sw, true); lambda.Emit(wr); string lam_str = sw.ToString(); FunctionCall fcall; IToken tok = lambda.tok; Formal res = new Formal(tok, new TypedIdent(tok, TypedIdent.NoName, cce.NonNull(lambda.Type)), false); if (liftedLambdas.TryGetValue(lambda, out fcall)) { if (CommandLineOptions.Clo.TraceVerify) { Console.WriteLine("Old lambda: {0}", lam_str); } } else { if (CommandLineOptions.Clo.TraceVerify) { Console.WriteLine("New lambda: {0}", lam_str); } Function fn = new Function(tok, FreshLambdaFunctionName(), freshTypeVars, formals, res, "auto-generated lambda function", Substituter.Apply(Substituter.SubstitutionFromDictionary(substFnAttrs), lambdaAttrs)); fn.OriginalLambdaExprAsString = lam_str; fcall = new FunctionCall(new IdentifierExpr(tok, fn.Name)); fcall.Func = fn; // resolve here liftedLambdas[lambda] = fcall; List<Expr /*!*/> selectArgs = new List<Expr /*!*/>(); foreach (Variable /*!*/ v in lambda.Dummies) { Contract.Assert(v != null); selectArgs.Add(new IdentifierExpr(v.tok, v)); } NAryExpr axcall = new NAryExpr(tok, fcall, axCallArgs); axcall.Type = res.TypedIdent.Type; axcall.TypeParameters = SimpleTypeParamInstantiation.From(freeTypeVars, fnTypeVarActuals); NAryExpr select = Expr.Select(axcall, selectArgs); select.Type = lambdaBody.Type; List<Type /*!*/> selectTypeParamActuals = new List<Type /*!*/>(); List<TypeVariable> forallTypeVariables = new List<TypeVariable>(); foreach (TypeVariable /*!*/ tp in lambda.TypeParameters) { Contract.Assert(tp != null); selectTypeParamActuals.Add(tp); forallTypeVariables.Add(tp); } forallTypeVariables.AddRange(freeTypeVars); select.TypeParameters = SimpleTypeParamInstantiation.From(lambda.TypeParameters, selectTypeParamActuals); Expr bb = Substituter.Apply(Substituter.SubstitutionFromDictionary(subst), lambdaBody); NAryExpr body = Expr.Eq(select, bb); body.Type = Type.Bool; body.TypeParameters = SimpleTypeParamInstantiation.EMPTY; Trigger trig = new Trigger(select.tok, true, new List<Expr> {select}); lambdaFunctions.Add(fn); lambdaAxioms.Add(new ForallExpr(tok, forallTypeVariables, dummies, Substituter.Apply(Substituter.SubstitutionFromDictionary(subst), lambdaAttrs), trig, body)); } NAryExpr call = new NAryExpr(tok, fcall, callArgs); call.Type = res.TypedIdent.Type; call.TypeParameters = SimpleTypeParamInstantiation.From(freeTypeVars, fnTypeVarActuals); return call; }
public static void ComputeBinderFreeVariables(List <TypeVariable> typeParameters, List <Variable> dummies, Expr body, Trigger triggers, QKeyValue attributes, Set freeVars) { Contract.Requires(dummies != null); Contract.Requires(body != null); foreach (var v in dummies) { Contract.Assert(v != null); Contract.Assert(!freeVars[v]); } body.ComputeFreeVariables(freeVars); for (var trig = triggers; trig != null; trig = trig.Next) { foreach (var e in trig.Tr) { e.ComputeFreeVariables(freeVars); } } for (var a = attributes; a != null; a = a.Next) { foreach (var o in a.Params) { var e = o as Expr; if (e != null) { e.ComputeFreeVariables(freeVars); } } } foreach (var v in dummies) { freeVars.AddRange(v.TypedIdent.Type.FreeVariables); } freeVars.RemoveRange(dummies); freeVars.RemoveRange(typeParameters); }
public override void ComputeFreeVariables(Set freeVars) { //Contract.Requires(freeVars != null); ComputeBinderFreeVariables(TypeParameters, Dummies, Body, null, Attributes, freeVars); }
public override IExpr /*?*/ EquivalentExpr(Element /*!*/ e, IQueryable /*!*/ q, IExpr /*!*/ expr, IVariable /*!*/ var, ISet /*<IVariable!>*//*!*/ prohibitedVars) { //Contract.Requires(prohibitedVars != null); //Contract.Requires(var != null); //Contract.Requires(expr != null); //Contract.Requires(q != null); //Contract.Requires(e != null); // BUGBUG: TODO: this method can be implemented in a more precise way return(null); }
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 }
/// <summary> /// Initializes FrameVertices, FrameRays, FrameLines, and FrameDimensions, see /// Cousot and Halbwachs, section 3.4. Any previous values of these fields are /// ignored and overwritten. /// /// If the set of Constraints is unsatisfiable, then "this" is changed into Bottom. /// </summary> void GenerateFrameFromConstraints() { if (Constraints == null) { FrameVertices = null; FrameRays = null; FrameLines = null; FrameDimensions = new HashSet /*IVariable!*/ (); return; } // Step 1 (see Cousot and Halbwachs, section 3.4.3): create a Simplex Tableau. #if DEBUG_PRINT Console.WriteLine("DEBUG: --- GenerateFrameFromConstraint ---"); Console.WriteLine("Constraints:"); foreach (LinearConstraint cc in Constraints) { Console.WriteLine(" {0}", cc); } #endif SimplexTableau tableau = new SimplexTableau(Constraints); #if DEBUG_PRINT Console.WriteLine("Initial tableau:"); tableau.Dump(); #endif FrameDimensions = tableau.GetDimensions(); #if DEBUG_PRINT Console.WriteLine("Dimensions:"); foreach (object dim in FrameDimensions) { Console.Write(" {0}", dim); } Console.WriteLine(); #endif // Step 3 and 2: Put as many initial variables as possible into basis, then check if // we reached a feasible basis tableau.AddInitialVarsToBasis(); #if DEBUG_PRINT Console.WriteLine("Tableau after Step 3:"); tableau.Dump(); #endif if (!tableau.IsFeasibleBasis) { // The polyhedron is empty (according to Cousot and Halbwachs) ChangeIntoBottom(); return; } FrameVertices = new ArrayList /*FrameElement*/ (); FrameRays = new ArrayList /*FrameElement*/ (); FrameLines = new ArrayList /*FrameElement*/ (); if (FrameDimensions.Count == 0) { // top element return; } if (tableau.AllInitialVarsInBasis) { // All initial variables are in basis; there are no lines. #if DEBUG_PRINT Console.WriteLine("Tableau after Steps 2 and 3 (all initial variables in basis):"); tableau.Dump(); #endif } else { // There are lines #if DEBUG_PRINT Console.WriteLine("Tableau after Steps 2 and 3 (NOT all initial variables in basis--there are lines):"); tableau.Dump(); #endif // Step 4.2: Pick out the lines, then produce the tableau for a new polyhedron without those lines. ArrayList /*LinearConstraint*/ moreConstraints = cce.NonNull((ArrayList/*!*/ /*LinearConstraint*/)Constraints.Clone()); tableau.ProduceLines(FrameLines, moreConstraints); tableau = new SimplexTableau(moreConstraints); #if DEBUG_PRINT Console.WriteLine("Lines produced:"); foreach (FrameElement line in FrameLines) { Console.WriteLine(" {0}", line); } Console.WriteLine("The new list of constraints is:"); foreach (LinearConstraint c in moreConstraints) { Console.WriteLine(" {0}", c); } Console.WriteLine("Tableau after producing lines in Step 4.2:"); tableau.Dump(); #endif // Repeat step 3 for the new tableau. // Since the new tableau contains no lines, the following call should cause all initial // variables to be in basis (see step 4.2 in section 3.4.3 of Cousot and Halbwachs). tableau.AddInitialVarsToBasis(); System.Diagnostics.Debug.Assert(tableau.AllInitialVarsInBasis); System.Diagnostics.Debug.Assert(tableau.IsFeasibleBasis); // the new tableau represents a set of feasible constraints, so this basis should be found to be feasible #if DEBUG_PRINT Console.WriteLine("Tableau after all initial variables have been moved into basis:"); tableau.Dump(); #endif } // Step 4.1: One vertex has been found. Find all others, too. tableau.TraverseVertices(FrameVertices, FrameRays); #if DEBUG_PRINT Console.WriteLine("Tableau after vertex traversal:"); tableau.Dump(); #endif }
public LinearConstraintSystem() { FrameDimensions = new HashSet /*IVariable!*/ (); //:base(); CheckInvariant(); }
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(); }
public override IExpr/*?*/ EquivalentExpr(Element/*!*/ e, IQueryable/*!*/ q, IExpr/*!*/ expr, IVariable/*!*/ var, ISet/*<IVariable!>*//*!*/ prohibitedVars) { //Contract.Requires(prohibitedVars != null); //Contract.Requires(var != null); //Contract.Requires(expr != null); //Contract.Requires(q != null); //Contract.Requires(e != null); // BUGBUG: TODO: this method can be implemented in a more precise way return null; }