Exemplo n.º 1
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);
        }
Exemplo n.º 2
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);
        }