Example #1
0
        /// <summary>
        /// - runs the state machine pointed to by CurrIndex, in place, and
        ///   returns the successor wrapped into a curr
        /// - assigns to argument a clone (!) of the old curr, and advances
        ///   its choice vector and currIndex, as appropriate
        /// So curr points to new memory after calling Execute. The returned
        /// successor is stored in old memory.
        /// </summary>
        /// <param name="curr"></param>
        /// <returns></returns>
        static BacktrackingState Execute(BacktrackingState curr)
        {
            /// create a copy of curr
            var origState = (StateImpl)curr.State.Clone();

            /// --PL Q: set as 0 every time is called?
            int choiceIndex = 0;

            /// curr.State.UserBooleanChoice is a pointer to a function with
            /// signature f: {} -> Bool.
            /// The following assigns the code under 'delegate' to this function pointer.
            /// curr and choiceIndex are global variables. -- PL: Q: global variables?
            curr.State.UserBooleanChoice = delegate()
            {
                if (choiceIndex < curr.ChoiceVector.Count)
                {
                    return(curr.ChoiceVector[choiceIndex++]);
                }

                choiceIndex++;
                curr.ChoiceVector.Add(false);
                return(false);
            };
            /// --PL: Execute the machine with index = CurrIndex
            curr.State.EnabledMachines[curr.CurrIndex].PrtRunStateMachine();

            Debug.Assert(choiceIndex == curr.ChoiceVector.Count);

            /// flip last choice -- PL Q: What does this mean??

            /// remove all 1's from the right
            while (curr.ChoiceVector.Count > 0 && curr.ChoiceVector[curr.ChoiceVector.Count - 1])
            {
                curr.ChoiceVector.RemoveAt(curr.ChoiceVector.Count - 1);
            }

            if (curr.ChoiceVector.Count > 0)
            {
                curr.ChoiceVector[curr.ChoiceVector.Count - 1] = true;
            }

            /// --PL: create the successor
            var succ = new BacktrackingState(curr.State)
            {
                depth = curr.depth + 1
            };

            curr.State = origState; // a clone of curr.State
            if (curr.ChoiceVector.Count == 0)
            {
                curr.CurrIndex++; // first iterate through all choices. When exhausted, step to the next enabled machine
            }

            return(succ);
        }
Example #2
0
        /// <summary>
        /// --PL: Queue-unbounded exploration, in DFS mode
        /// </summary>
        /// <param name="queueAbstraction">Abstracting queue or not, default is not (set param as false)</param>
        public static void Dfs(bool queueAbstraction = false)
        {
            /// currently, we only implemented the exploration based on state hashing
            if (!useStateHashing)
            {
                throw new NotImplementedException();
            }

            Console.WriteLine("Using "
                              + (PrtEventBuffer.k == 0 ? "unbounded queue" : "queue bound of " + PrtEventBuffer.k.ToString()));
            /// Throw away states obtained from last rounds as all of them are static variables
            concretesInHash.Clear();
            abstractsInHash.Clear();
            abstractSuccsInHash.Clear();

#if DEBUG
            int max_queue_size = 0;
            int max_stack_size = 0;
#endif
            /// --PL: dump states & transitions to files
            StreamWriter concretesFile     = null;
            StreamWriter abstractsFile     = null;
            StreamWriter abstractSuccsFile = null;
            StreamWriter transitionsFile   = null;
            if (fileDump)
            {
                /// add "0" for name formating
                var suffix = (PrtEventBuffer.k < 10 ? "0" : "") + PrtEventBuffer.k.ToString();
                concretesFile = new StreamWriter(Constants.dumpFileConcretePrefix
                                                 + suffix
                                                 + Constants.dumpFileExtension);
                abstractsFile = new StreamWriter(Constants.dumpFileAbstractPrefix
                                                 + suffix
                                                 + Constants.dumpFileExtension);
                abstractSuccsFile = new StreamWriter(Constants.dumpFileAbstractSuccPrefix
                                                     + suffix
                                                     + Constants.dumpFileExtension);
                transitionsFile = new StreamWriter(Constants.dumpFileTransitionPrefix
                                                   + suffix
                                                   + Constants.dumpFileExtension);
            }

            Debug.Assert(start != null);
            var startClone = (StateImpl)start.Clone(); // we need a fresh clone in each iteration (k) of Dfs

            /// worklist, implemented using stack
            var worklist = new Stack <BacktrackingState>();
            // TODO: the following piece of code is duplicate. Need to refine it.
            worklist.Push(new BacktrackingState(startClone));
            var startHash = startClone.GetHashCode();
            concretesInHash.Add(startHash);
            if (fileDump)
            {
                concretesFile.Write(startClone.ToPrettyString());
                concretesFile.WriteLine(Constants.consoleSeparator);
                transitionsFile.WriteLine(startHash);
            }

            if (queueAbstraction)
            {
                var startAbstract = (StateImpl)start.Clone();
                startAbstract.AbstractMe(); // abstract queue

                abstractsInHash.Add(startAbstract.GetHashCode());
                /// compute abstract succs right way
                startAbstract.CollectAbstractSuccessors(abstractSuccsInHash, abstractSuccsFile);
                if (fileDump)
                {
                    abstractsFile.Write(startAbstract.ToPrettyString());
                    abstractsFile.WriteLine(Constants.consoleSeparator);
                }
            }

            /// the main loop of DFS
            while (worklist.Count != 0) /// if worklist is not empty
            {
#if false                               // code for investigating memory usage
                if (worklist.Count == 5000)
                {
                    Console.WriteLine("Stack depth of 5000 reached");

                    GC.Collect();
                    var mem1 = GC.GetTotalMemory(true) / (1024.0 * 1024.0);
                    Console.WriteLine("Current memory usage = {0} MB", mem1.ToString("F2"));

                    // lets clone
                    var stackarr = worklist.ToArray();
                    var newStack = new List <StateImpl>();
                    for (int i = 0; i < stackarr.Length; i++)
                    {
                        newStack.Add((StateImpl)stackarr[i].State.Clone());
                    }

                    GC.Collect();
                    var mem2 = GC.GetTotalMemory(true) / (1024.0 * 1024.0);

                    Console.WriteLine("Memory usage after cloning the stack = {0} MB", mem2.ToString("F2"));
                    Console.WriteLine("Average usage per state = {0} MB", (mem2 - mem1) / 5000.0);

                    Environment.Exit(0);
                }
#endif
                /// -PL: pop a state from worklist, and operate on it
                var curr = worklist.Pop();
                if (curr.CurrIndex >= curr.State.EnabledMachines.Count) // if "done" with curr
                {
                    continue;
                }

                /// Get a successor by executing the enabled machine pointed to by currIndex.
                /// Also, advance currIndex and/or choiceIndex and push curr state back to worklist
                /// TODO: try BFS
                BacktrackingState succ = Execute(curr);
                worklist.Push(curr); // CurrIndex of curr has been updated

                // if we are in competitor finding mode
                if (StateImpl.mode == StateImpl.ExploreMode.Competitor)
                {
                    CheckPredHash(curr.State, succ.State);
                }

                /// check for failure before adding new state: may fail due
                /// to failed assume, in which case we don't want to add
                if (!succ.State.CheckFailure(succ.depth))
                {
                    // update concrete state hashset
                    var succHash = succ.State.GetHashCode();
                    if (!concretesInHash.Add(succHash)) // -- PL: if successor has been explored
                    {
                        continue;
                    }
                    if (!succ.State.CheckConcreteStateInvariant())
                    {
                        throw new QuTLException("QuTL formula fails in concete model checking!");
                    }
                    worklist.Push(succ);
#if DEBUG
                    max_stack_size = Math.Max(max_stack_size, worklist.Count);
#endif

                    if (fileDump)
                    {
                        concretesFile.Write(succ.State.ToPrettyString()); // + " = " + succHash.ToPrettyString());
                        concretesFile.WriteLine(Constants.consoleSeparator);
                        transitionsFile.WriteLine("{0} -> {1}", curr.State.GetHashCode(), succHash);
                    }

                    if (queueAbstraction)
                    {
                        var succAbs = (StateImpl)succ.State.Clone();
                        succAbs.AbstractMe();
                        var succAbsHash = succAbs.GetHashCode();

                        #if false
                        #region dirty code, debugging============================
                        var currAbs = (StateImpl)curr.State.Clone();
                        currAbs.AbstractMe();
                        if (currAbs.GetHashCode() == -105414283)
                        {
                            Console.WriteLine("%%%%%%%%%%%%%%%%%%% = beginning ========");
                            Console.WriteLine(curr.State.ToPrettyString());
                            Console.WriteLine();
                            Console.WriteLine(currAbs.ToPrettyString());
                            Console.WriteLine(succ.State.ToPrettyString());
                            Console.WriteLine("%%%%%%%%%%%%%%%%%%% = " + succAbsHash);
                            Console.WriteLine(succAbs.ToPrettyString());
                            Console.WriteLine("Abstract Successors............");
                        }
                        #endregion
#endif
                        if (abstractsInHash.Add(succAbsHash)) /// --PL: if the abstract of current state has NOT been explored
                        {
                            succAbs.CollectAbstractSuccessors(abstractSuccsInHash, abstractSuccsFile);
                            if (fileDump)
                            {
                                abstractsFile.Write(succAbs.ToPrettyString());
                                abstractsFile.WriteLine(Constants.consoleSeparator);
                            }
                        }

#if false
                        if (currAbs.GetHashCode() == -417525807)
                        {
                            Environment.Exit(0);
                        }
#endif
                    }
#if DEBUG
                    // status and diagnostics
                    if (concretesInHash.Count % 1000 == 0)
                    {
                        Console.WriteLine("-------------- Number of concrete states visited so far   = {0}", concretesInHash.Count);
                        if (queueAbstraction)
                        {
                            Console.WriteLine("-------------- Number of abstract states found so far     = {0}", abstractsInHash.Count);
                            Console.WriteLine("-------------- Number of abstract successors found so far = {0}{1}", abstractSuccsInHash.Count, StateImpl.invariant ? " (only those satisfying all static invariants)" : "");
                        }
                        Console.WriteLine("-------------- Maximum queue size encountered so far      = {0}", max_queue_size);
                        Console.WriteLine("-------------- Maximum stack size encountered so far      = {0}", max_stack_size);
                        Console.WriteLine();
                    }

                    // update maximum encountered queue size
                    foreach (PrtImplMachine m in succ.State.ImplMachines)
                    {
                        max_queue_size = Math.Max(max_queue_size, m.eventQueue.Size());
                    }
#endif
                }
            } // end of while loop

            Console.WriteLine("");
            Console.WriteLine("Number of concrete states visited     = {0}", concretesInHash.Count);
            if (queueAbstraction)
            {
                Console.WriteLine("Number of abstract states encountered = {0}", abstractsInHash.Count);
                Console.WriteLine("Number of abstract successors found   = {0}{1}", abstractSuccsInHash.Count, StateImpl.invariant ? " (only those satisfying all static invariants)" : "");
            }

#if DEBUG
            Console.WriteLine("Maximum queue size  encountered       = {0}", max_queue_size);
            Console.WriteLine("Maximum stack size  encountered       = {0}", max_stack_size);
#endif
            Console.WriteLine();

            if (fileDump)
            {
                /// flush streams before close them
                concretesFile.Flush();
                abstractsFile.Flush();
                abstractSuccsFile.Flush();
                transitionsFile.Flush();
                /// close streams
                concretesFile.Close();
                abstractsFile.Close();
                abstractSuccsFile.Close();
                transitionsFile.Close();
            }
        }