예제 #1
0
        private List <EnvironmentState> _stateEnv = new List <EnvironmentState>(); // how to link up the corresponding concrete states for easy access? e.g., given abstract tuple, get the concrete predicates being abstracted

        /**
         *
         */
        public AbstractState(ConcreteLocation rstate, List <EnvironmentState> estates)
            : base("", UInt32.MaxValue, false)
        {
            this._stateRef       = rstate;
            this._stateEnv       = estates;
            this._concretization = null;
        }
예제 #2
0
        public Transition(ConcreteLocation p)
        {
            this.Parent = p;

            // todo next: switch if not int type: , Controller.Instance.IndexType
            Expr hidxinner = Controller.Instance.Z3.MkIntConst("h");

            this.TransitionTermGlobal = (BoolExpr)this.makeTransitionTerm(null, hidxinner, null);        // no local vars
            this.TransitionTerm       = (BoolExpr)this.makeTransitionTerm(this.Parent, hidxinner, null); // with local vars
        }
예제 #3
0
 /**
  *
  */
 private void Dispose(bool disposing)
 {
     // Check to see if Dispose has already been called.
     if (!this._dispose)
     {
         // If disposing equals true, dispose all managed and unmanaged resources.
         if (disposing)
         {
             // Dispose managed resources.
             this._label    = null;
             this._stateRef = null;
             this._stateEnv = null;
         }
     }
     this._dispose = true;
 }
예제 #4
0
 public Transition(ConcreteLocation p, Expr guard, Expr reset, List <AState> nextStates)
     : this(p, nextStates)
 {
     this.Guard  = guard;
     this._reset = reset;
 }
예제 #5
0
 public Transition(ConcreteLocation p, Expr guard, Expr reset) : this(p)
 {
     this.Guard  = guard;
     this._reset = reset;
 }
예제 #6
0
 public Transition(ConcreteLocation p, List <AState> nextStates) : this(p)
 {
     this._nextStates = nextStates;
 }
예제 #7
0
 public Transition(ConcreteLocation p, AState nextState, AbstractTransitionType t)
     : this(p, nextState)
 {
     this._type = t;
 }
예제 #8
0
        /**
         * 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);
        }
예제 #9
0
 public Transition(ConcreteLocation p, AState nextState) : this(p)
 {
     this._nextStates = new List <AState>();
     this._nextStates.Add(nextState);
 }
예제 #10
0
        /// <summary>
        /// Compute post from pre
        /// </summary>
        /// <param name="pre"></param>
        /// <returns></returns>
        public Expr MakePost(Expr pre)
        {
            KeyValuePair <Transition, Expr> postKey = new KeyValuePair <Transition, Expr>(this, pre);

            if (Transition.CachePost.ContainsKey(postKey))
            {
                return(CachePost[postKey]);
            }

            Expr idx = Controller.Instance.Indices["i"];

            ConcreteLocation l = this.Parent;

            List <BoolExpr> resets = new List <BoolExpr>();

            resets.Add((BoolExpr)pre); // add prestate

            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) // TODO: handle univerasl resets (assume none for now)
            {
                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.forallIdentityPost(gidx, globalVariableResets, indexVariableResets, universalIndexVariableResets, this.UGuard, 0); // no process moves if no location
            }
            else
            {
                identity = Controller.Instance.Sys.forallIdentityPost(idx, globalVariableResets, indexVariableResets, universalIndexVariableResets, this.UGuard, 0);
            }

            resetAnd = Controller.Instance.Z3.MkAnd((BoolExpr)resetAnd, (BoolExpr)identity);
            resetAnd = Controller.Instance.Z3.copyExpr(resetAnd);

            // short circuit

            /*
             * if (this.Reset == null && Controller.Instance.Sys.Variables.Count == 0)
             * {
             *  return resetAnd;
             * }
             */

            // replace all function declarations with constants (e.g., (q i) => (qi), where qi is a constant, instead of a function)

            List <Expr> bound = new List <Expr>();

            // TODO: use this.Parent.Parent.Parent, etc to access hybrid automata, holism, etc (will make generalizing to compositions easier)
            foreach (var v in Controller.Instance.Sys.HybridAutomata[0].Variables)
            {
                Expr varConst     = Controller.Instance.Z3.MkConst(v.Name + "_" + "i", v.TypeSort);
                Expr varConstPost = Controller.Instance.Z3.MkConst(v.NamePrimed + "_" + "i", v.TypeSort);
                resetAnd = resetAnd.Substitute(Controller.Instance.Z3.MkApp(v.Value, idx), varConst);
                resetAnd = resetAnd.Substitute(Controller.Instance.Z3.MkApp(v.ValuePrimed, idx), varConstPost);
                bound.Add(varConst);
            }

            foreach (var v in Controller.Instance.GlobalVariables.Values)
            {
                bound.Add(v);
            }


            //Expr post = Controller.Instance.Z3.MkExists(new Expr[] { idx }, (BoolExpr)resetAnd);
            Expr post = Controller.Instance.Z3.MkExists(bound.ToArray(), (BoolExpr)resetAnd);


            // HACK: replace all location names with their values...
            foreach (var loc in Controller.Instance.Sys.HybridAutomata[0].Locations)
            {
                post = post.Substitute(loc.LabelExpr, loc.BitVectorExpr);
            }
            post = post.Substitute(Controller.Instance.IndexN, Controller.Instance.Z3.MkInt(Controller.Instance.IndexNValue));



            Tactic tqe = Controller.Instance.Z3.Repeat(Controller.Instance.Z3.MkTactic("qe"));
            Goal   g   = Controller.Instance.Z3.MkGoal();



            List <BoolExpr> remAss = Controller.Instance.Z3.Assumptions.FindAll(a => a.IsQuantifier); // todo: add type constraints to constant (q_i) instead of functions (q i)

            Controller.Instance.Z3.Assumptions.RemoveAll(a => a.IsQuantifier);                        // otherwise q.e. will fail
            g.Assert(Controller.Instance.Z3.Assumptions.ToArray());
            Controller.Instance.Z3.Assumptions.AddRange(remAss);                                      // add back
            g.Assert(Controller.Instance.Z3.AssumptionsUniversal.ToArray());



            g.Assert((BoolExpr)post);
            g = g.Simplify();
            ApplyResult ar = tqe.Apply(g);

            List <BoolExpr> postStates = new List <BoolExpr>();

            foreach (var sg in ar.Subgoals)
            {
                postStates.AddRange(sg.Formulas);
            }



            postStates.RemoveAll(fa => Controller.Instance.Z3.Assumptions.Contains(fa));
            postStates.RemoveAll(fa => Controller.Instance.Z3.AssumptionsUniversal.Contains(fa));



            post = Controller.Instance.Z3.MkAnd(postStates.ToArray());


            // HACK: replace all location values with their names...
            foreach (var loc in Controller.Instance.Sys.HybridAutomata[0].Locations)
            {
                post = post.Substitute(loc.BitVectorExpr, loc.LabelExpr);
            }

            // convert constants back to functions
            foreach (var v in Controller.Instance.Sys.HybridAutomata[0].Variables)
            {
                Expr varConst     = Controller.Instance.Z3.MkConst(v.Name + "_" + "i", v.TypeSort);
                Expr varConstPost = Controller.Instance.Z3.MkConst(v.NamePrimed + "_" + "i", v.TypeSort);
                post = post.Substitute(varConst, Controller.Instance.Z3.MkApp(v.Value, idx));
                post = post.Substitute(varConstPost, Controller.Instance.Z3.MkApp(v.ValuePrimed, idx));
            }

            Controller.Instance.Z3.unprimeAllVariables(ref post); // unprime

            System.Console.WriteLine("POST: " + post.ToString());

            // cache result
            CachePost.Add(postKey, post);

            return(post);
        }
예제 #11
0
        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);
        }