/** * Make terms corresponding to pre and post-state for a transition (can be local or global transition) */ public Expr makeTransitionTerm(ConcreteLocation l, Expr idx, params uint[] paramList) { uint N = 0; uint quant = 0; uint k = 0; if (paramList != null && paramList.Length > 0) { N = paramList[0]; if (paramList.Length > 1) { k = paramList[1]; } if (paramList.Length > 2) { quant = paramList[2]; } } List <BoolExpr> locInvariant = new List <BoolExpr>(); if (l != null) { locInvariant.Add((BoolExpr)l.StatePredicate); // discrete location prestate (e.g., loc[i] = 1) } if (this.NextStates.Count > 0) { locInvariant.Add((BoolExpr)this.ToTerm()); // discrete location post-state (e.g., loc'[i] = 2) } // add guard, if one exists if (this.Guard != null) { locInvariant.Add((BoolExpr)this.Guard); } if (l != null) { // add invariant, if one exists if (l.Invariant != null) { locInvariant.Add((BoolExpr)l.Invariant); } // add stopping condition, if one exists if (l.Stop != null) { locInvariant.Add((BoolExpr)l.Stop); } } List <String> globalVariableResets = new List <String>(); // global variables not reset List <String> indexVariableResets = new List <String>(); // indexed variables of process moving that are not reset List <String> universalIndexVariableResets = new List <String>(); // universally quantified indexed variables that are reset if (this.Reset != null) { locInvariant.Add((BoolExpr)this.Reset); globalVariableResets = Controller.Instance.Z3.findGlobalVariableResets(this.Reset); indexVariableResets = Controller.Instance.Z3.findIndexedVariableResets(this.Reset); } else { // global variable was not mentioned since reset is null: add it to the identity global variables (g' = g) globalVariableResets = Controller.Instance.Z3.findGlobalVariableResets(null); indexVariableResets = Controller.Instance.Z3.findIndexedVariableResets(null); } if (this.UGuard != null) { universalIndexVariableResets = Controller.Instance.Z3.findIndexedVariableResetsNeg(this.UGuard); } Expr locInvariantAnd = null; // create conjunction of pre-state and post-state conditions if (locInvariant.Count > 0) { locInvariantAnd = Controller.Instance.Z3.MkAnd(locInvariant.ToArray()); } Expr identity; if (l == null) { // TODO NEXT: GLOBAL INDEXED VARIABLE COULD CAUSE RESETS / "be the process moving" int i = 0; Expr gidx = null; foreach (var v in Controller.Instance.GlobalVariables) { if (Controller.Instance.Sys.Variables.Find( delegate(Variable gv) { return(gv.Name == v.Key); }).Type == Variable.VarType.index && Controller.Instance.Z3.findTerm(this.Reset, v.Value, true)) { gidx = v.Value; i++; } // TODO: need to refactor forall identity to allow multiple processes moving, for now throw exception if it happens if (i > 1) { throw new Exception("Error: too many global index variables used."); } } identity = Controller.Instance.Sys.forallIdentity(gidx, globalVariableResets, indexVariableResets, universalIndexVariableResets, this.UGuard, N); // no process moves if no location } else { identity = Controller.Instance.Sys.forallIdentity(idx, globalVariableResets, indexVariableResets, universalIndexVariableResets, this.UGuard, N); } if (locInvariantAnd == null && N == 0) { locInvariantAnd = identity; } else if (N == 0) { locInvariantAnd = Controller.Instance.Z3.MkAnd((BoolExpr)locInvariantAnd, (BoolExpr)identity); } if (l != null && N == 0) { locInvariantAnd = locInvariantAnd.Substitute(Controller.Instance.Indices["i"], idx); // replace i by h BoolExpr idxConstraint = Controller.Instance.Z3.MkAnd(Controller.Instance.Z3.MkGe((ArithExpr)idx, (ArithExpr)Controller.Instance.IntOne), Controller.Instance.Z3.MkLe((ArithExpr)idx, (ArithExpr)Controller.Instance.IndexN)); // add quantifiers based on pre-state and post-state, using implies vs. and options and indexing options switch (Controller.Instance.IndexOption) { case Controller.IndexOptionType.naturalOneToN: switch (Controller.Instance.ExistsOption) { case Controller.ExistsOptionType.and: locInvariantAnd = Controller.Instance.Z3.MkAnd(idxConstraint, (BoolExpr)locInvariantAnd); // 1 <= h <= N, enforce identity for all other processes not moving break; case Controller.ExistsOptionType.implies: default: locInvariantAnd = Controller.Instance.Z3.MkImplies(idxConstraint, (BoolExpr)locInvariantAnd); // 1 <= h <= N, enforce identity for all other processes not moving break; } break; case Controller.IndexOptionType.enumeration: case Controller.IndexOptionType.integer: default: //locInvariantAnd = locInvariantAnd & z3.forallIdentity(hidx, globalVariableResets, indexVariableResets); break; } } if (N == 0) { // todo: add quantifier: check if correct } else { List <BoolExpr> transAll = new List <BoolExpr>(); // expand quantifier manually for (uint i = 1; i <= N; i++) { Expr numidx = Controller.Instance.Z3.MkInt(i); //Expr trans = locInvariantAnd.Substitute(idx, numidx); // instantiate i //transAll.Add(z3.MkAnd(z3.MkEq(idx, numidx), (BoolExpr)locInvariantAnd)); // simply set symbol idx = value idx BoolExpr copy = (BoolExpr)Controller.Instance.Z3.copyExpr(locInvariantAnd); foreach (var v in Controller.Instance.Sys.Variables) { copy = (BoolExpr)copy.Substitute(Controller.Instance.GlobalVariables[v.Name], Controller.Instance.Sys.GlobalReachValues[new Tuple <string, uint>(v.Name, k)]); // substitute to constant (needed for doing q.e.) copy = (BoolExpr)copy.Substitute(Controller.Instance.GlobalVariablesPrimed[v.Name], Controller.Instance.Sys.GlobalReachValues[new Tuple <string, uint>(v.Name, k + 1)]); // substitute to constant (needed for doing q.e.) } foreach (var v in Controller.Instance.Sys.HybridAutomata[0].Variables) // TODO: generalize { //copy.Substitute(z3.MkApp(v.Value, idx), z3.MkApp(v.Value, numidx)); // substitute to function idx = Controller.Instance.Z3.MkIntConst("i"); copy = (BoolExpr)copy.Substitute(Controller.Instance.Z3.MkApp(v.Value, idx), Controller.Instance.Sys.ReachValues[new Tuple <string, uint, uint>(v.Name, k, i)]); // substitute to constant (needed for doing q.e.) copy = (BoolExpr)copy.Substitute(Controller.Instance.Z3.MkApp(v.ValuePrimed, idx), Controller.Instance.Sys.ReachValues[new Tuple <string, uint, uint>(v.Name, k + 1, i)]); // substitute to constant (needed for doing q.e.) } copy = (BoolExpr)copy.Substitute(idx, numidx); // must be outside variable loop copy = Controller.Instance.Z3.MkAnd(copy, (BoolExpr)Controller.Instance.Sys.forallIdentity(Controller.Instance.Z3.MkInt(i), globalVariableResets, indexVariableResets, universalIndexVariableResets, this.UGuard, N)); for (uint j = 1; j <= N; j++) { if (j == i) { continue; } foreach (var v in Controller.Instance.Sys.HybridAutomata[0].Variables) // TODO: generalize { copy = (BoolExpr)copy.Substitute(Controller.Instance.Z3.MkApp(v.Value, Controller.Instance.Z3.MkInt(j)), Controller.Instance.Sys.ReachValues[new Tuple <string, uint, uint>(v.Name, k, j)]); // substitute to constant (needed for doing q.e.) copy = (BoolExpr)copy.Substitute(Controller.Instance.Z3.MkApp(v.ValuePrimed, Controller.Instance.Z3.MkInt(j)), Controller.Instance.Sys.ReachValues[new Tuple <string, uint, uint>(v.Name, k + 1, j)]); // substitute to constant (needed for doing q.e.) } } transAll.Add(copy); } locInvariantAnd = Controller.Instance.Z3.MkOr(transAll.ToArray()); } return(locInvariantAnd); }
public Expr MakeReset(Expr idx, uint N, uint k) { ConcreteLocation l = this.Parent; List <BoolExpr> resets = new List <BoolExpr>(); if (this.NextStates.Count > 0) { resets.Add((BoolExpr)this.ToTerm()); // discrete location post-state (e.g., loc'[i] = 2) } List <String> globalVariableResets = new List <String>(); // global variables not reset List <String> indexVariableResets = new List <String>(); // indexed variables of process moving that are not reset List <String> universalIndexVariableResets = new List <String>(); // universally quantified indexed variables that are reset if (this.Reset != null) { resets.Add((BoolExpr)this.Reset); globalVariableResets = Controller.Instance.Z3.findGlobalVariableResets(this.Reset); indexVariableResets = Controller.Instance.Z3.findIndexedVariableResets(this.Reset); } else { // global variable was not mentioned since reset is null: add it to the identity global variables (g' = g) globalVariableResets = Controller.Instance.Z3.findGlobalVariableResets(null); indexVariableResets = Controller.Instance.Z3.findIndexedVariableResets(null); } if (this.UGuard != null) { universalIndexVariableResets = Controller.Instance.Z3.findIndexedVariableResetsNeg(this.UGuard); } Expr resetAnd = null; // create conjunction of pre-state and post-state conditions if (resets.Count > 0) { resetAnd = Controller.Instance.Z3.MkAnd(resets.ToArray()); } Expr identity; if (l == null) { // TODO NEXT: GLOBAL INDEXED VARIABLE COULD CAUSE RESETS / "be the process moving" int i = 0; Expr gidx = null; foreach (var v in Controller.Instance.GlobalVariables) { if (Controller.Instance.Sys.Variables.Find( delegate(Variable gv) { return(gv.Name == v.Key); }).Type == Variable.VarType.index && Controller.Instance.Z3.findTerm(this.Reset, v.Value, true)) { gidx = v.Value; i++; } // TODO: need to refactor forall identity to allow multiple processes moving, for now throw exception if it happens if (i > 1) { throw new Exception("Error: too many global index variables used."); } } identity = Controller.Instance.Sys.forallIdentity(gidx, globalVariableResets, indexVariableResets, universalIndexVariableResets, this.UGuard, N); // no process moves if no location } else { identity = Controller.Instance.Sys.forallIdentity(idx, globalVariableResets, indexVariableResets, universalIndexVariableResets, this.UGuard, N); } if (resetAnd == null && N == 0) { resetAnd = identity; } else if (N == 0) { resetAnd = Controller.Instance.Z3.MkAnd((BoolExpr)resetAnd, (BoolExpr)identity); } List <BoolExpr> transAll = new List <BoolExpr>(); // expand quantifier manually for (uint i = 1; i <= N; i++) { Expr numidx = Controller.Instance.Z3.MkInt(i); //Expr trans = locInvariantAnd.Substitute(idx, numidx); // instantiate i //transAll.Add(z3.MkAnd(z3.MkEq(idx, numidx), (BoolExpr)locInvariantAnd)); // simply set symbol idx = value idx BoolExpr copy = (BoolExpr)Controller.Instance.Z3.copyExpr(resetAnd); idx = Controller.Instance.Z3.MkIntConst("i"); foreach (var v in Controller.Instance.Sys.HybridAutomata[0].Variables) // TODO: generalize { //copy.Substitute(z3.MkApp(v.Value, idx), z3.MkApp(v.Value, numidx)); // substitute to function copy = (BoolExpr)copy.Substitute(Controller.Instance.IndexedVariables[new KeyValuePair <string, string>(v.Name, idx.ToString())], Controller.Instance.Sys.ReachValues[new Tuple <string, uint, uint>(v.Name, k, i)]); // substitute to constant (needed for doing q.e.) copy = (BoolExpr)copy.Substitute(Controller.Instance.IndexedVariablesPrimed[new KeyValuePair <string, string>(v.Name + Controller.PRIME_SUFFIX, idx.ToString())], Controller.Instance.Sys.ReachValues[new Tuple <string, uint, uint>(v.Name, k + 1, i)]); // substitute to constant (needed for doing q.e.) } copy = (BoolExpr)copy.Substitute(idx, numidx); // must be outside loop copy = Controller.Instance.Z3.MkAnd(copy, (BoolExpr)Controller.Instance.Sys.forallIdentity(Controller.Instance.Z3.MkInt(i), globalVariableResets, indexVariableResets, universalIndexVariableResets, this.UGuard, N)); foreach (var v in Controller.Instance.Sys.HybridAutomata[0].Variables) // TODO: generalize { //copy.Substitute(z3.MkApp(v.Value, idx), z3.MkApp(v.Value, numidx)); // substitute to function copy = (BoolExpr)copy.Substitute(Controller.Instance.Z3.MkApp(v.Value, Controller.Instance.Z3.MkInt(i)), Controller.Instance.Sys.ReachValues[new Tuple <string, uint, uint>(v.Name, k, i)]); // substitute to constant (needed for doing q.e.) copy = (BoolExpr)copy.Substitute(Controller.Instance.Z3.MkApp(v.ValuePrimed, Controller.Instance.Z3.MkInt(i)), Controller.Instance.Sys.ReachValues[new Tuple <string, uint, uint>(v.Name, k + 1, i)]); // substitute to constant (needed for doing q.e.) } // todo: check order of operations foreach (var v in Controller.Instance.Sys.Variables) { copy = (BoolExpr)copy.Substitute(Controller.Instance.GlobalVariables[v.Name], Controller.Instance.Sys.GlobalReachValues[new Tuple <string, uint>(v.Name, k)]); // substitute to constant (needed for doing q.e.) copy = (BoolExpr)copy.Substitute(Controller.Instance.GlobalVariablesPrimed[v.Name], Controller.Instance.Sys.GlobalReachValues[new Tuple <string, uint>(v.Name, k + 1)]); // substitute to constant (needed for doing q.e.) } for (uint j = 1; j <= N; j++) { if (j == i) { continue; } foreach (var v in Controller.Instance.Sys.HybridAutomata[0].Variables) // TODO: generalize { copy = (BoolExpr)copy.Substitute(Controller.Instance.Z3.MkApp(v.Value, Controller.Instance.Z3.MkInt(j)), Controller.Instance.Sys.ReachValues[new Tuple <string, uint, uint>(v.Name, k, j)]); // substitute to constant (needed for doing q.e.) copy = (BoolExpr)copy.Substitute(Controller.Instance.Z3.MkApp(v.ValuePrimed, Controller.Instance.Z3.MkInt(j)), Controller.Instance.Sys.ReachValues[new Tuple <string, uint, uint>(v.Name, k + 1, j)]); // substitute to constant (needed for doing q.e.) } } transAll.Add(copy); } resetAnd = Controller.Instance.Z3.MkOr(transAll.ToArray()); return(resetAnd); }