// Perform the redDFS public bool SwarmNestedDFSDepthFirstSearchRed(LocalPair s, Stack <LocalPair> BlueStack, Dictionary <string, List <string> > OutgoingTransitionTable, Dictionary <string, StateColor> colorData) { //store the expended event step of a node to avoid multiple invocation of the make one move. Dictionary <string, List <LocalPair> > ExpendedNode = new Dictionary <string, List <LocalPair> >(256); Stack <LocalPair> RedStack = new Stack <LocalPair>(5000); RedStack.Push(s); do { if (CancelRequested || StopMutliCoreThreads) { return(false); } LocalPair pair = RedStack.Peek(); string v = pair.GetCompressedState(); ConfigurationBase evt = pair.configuration; string BAState = pair.state; List <string> outgoing = OutgoingTransitionTable[v]; bool redDone = true; if (!ExpendedNode.ContainsKey(v)) { //ConfigurationBase[] list = evt.MakeOneMove().ToArray(); IEnumerable <ConfigurationBase> list = evt.MakeOneMove(); pair.SetEnabled(list, FairnessType); List <LocalPair> product = LocalPair.NextLocal(BA, list, BAState); ExpendedNode.Add(v, product); } List <LocalPair> neighbourList = ExpendedNode[v]; //transverse all neighbour nodes for (int k = neighbourList.Count - 1; k >= 0; k--) { LocalPair step = neighbourList[k]; string tmp = step.GetCompressedState(); StateColor neighbourColor = colorData[tmp]; // if the neighbour node is blue if (neighbourColor.IsBlue()) { //only add the first unvisited node //for the second or more unvisited steps, ignore at the monent if (redDone) { neighbourColor.SetRed(); RedStack.Push(step); redDone = true; neighbourList.RemoveAt(k); } } // if the neighbour is cyan // report cycle else if (neighbourColor.IsCyan()) { SwarmNestedDFSReportRedCycle(s, step, pair, BlueStack, RedStack, colorData, OutgoingTransitionTable); return(true); } else { neighbourList.RemoveAt(k); } } if (redDone) { RedStack.Pop(); } } while (RedStack.Count > 0); return(false); }
/// <summary> /// The function of each worker in swarm NDFS /// </summary> /// <returns></returns> public void SwarmNestedDFSModelCheckingWorker() { Dictionary <string, List <string> > OutgoingTransitionTable = new Dictionary <string, List <string> >(Ultility.Ultility.MC_INITIAL_SIZE); List <LocalPair> initials = LocalPair.GetInitialPairsLocal(BA, InitialStep); if (initials.Count == 0) { VerificationOutput.VerificationResult = VerificationResultType.VALID; return; } Stack <LocalPair> BlueStack = new Stack <LocalPair>(5000); Dictionary <string, StateColor> colorData = new Dictionary <string, StateColor>(5000); int threadId; // Create random variable with different seed for each thread Random rand; // helps different threads access different region of the graph lock (MultiCoreLock) { threadId = MultiCoreSeed; rand = new Random(MultiCoreSeed); MultiCoreSeed++; } // Create the list of initial states // May apply randomness here to increase performance int[] permutation = generatePermutation(initials.Count, rand); for (int z = 0; z < initials.Count; z++) { LocalPair initState = initials[permutation[z]]; BlueStack.Push(initState); string ID = initState.GetCompressedState(); colorData.Add(ID, new StateColor()); OutgoingTransitionTable.Add(ID, new List <string>(8)); } //store the expended event step of a node to avoid multiple invocation of the make one move. Dictionary <string, List <LocalPair> > ExpendedNode = new Dictionary <string, List <LocalPair> >(1024); do { if (CancelRequested || StopMutliCoreThreads) { return; } LocalPair pair = BlueStack.Peek(); ConfigurationBase evt = pair.configuration; string BAState = pair.state; string v = pair.GetCompressedState(); List <string> outgoing = OutgoingTransitionTable[v]; StateColor nodeColor = colorData[v]; if (nodeColor.IsWhite()) { nodeColor.SetCyan(); } bool blueDone = true; // Initialize the node if first time visited if (!ExpendedNode.ContainsKey(v)) { //ConfigurationBase[] configList = evt.MakeOneMove().ToArray(); IEnumerable <ConfigurationBase> configList = evt.MakeOneMove(); pair.SetEnabled(configList, FairnessType); List <LocalPair> product = LocalPair.NextLocal(BA, configList, BAState); ExpendedNode.Add(v, product); for (int k = product.Count - 1; k >= 0; k--) { LocalPair step = product[k]; string tmp = step.GetCompressedState(); //update the incoming and outgoing edges outgoing.Add(tmp); if (!colorData.ContainsKey(tmp)) { colorData.Add(tmp, new StateColor()); OutgoingTransitionTable.Add(tmp, new List <string>(8)); } } } List <LocalPair> list = ExpendedNode[v]; //transverse all neighbour nodes for (int k = list.Count - 1; k >= 0; k--) { int randIndex = rand.Next(list.Count); //int randIndex = list.Count - 1; LocalPair step = list[randIndex]; string tmp = step.GetCompressedState(); StateColor neighbourColor = colorData[tmp]; //if the neighbour node is white if (neighbourColor.IsWhite()) { if (blueDone) { BlueStack.Push(step); blueDone = false; list.RemoveAt(randIndex); break; } } // if the neighbour node is cyan, // and either this node or the neibour node is the accept state // then report cycle else if (neighbourColor.IsCyan()) { if (step.state.EndsWith(Constants.ACCEPT_STATE) || pair.state.EndsWith(Constants.ACCEPT_STATE)) { SwarmNestedDFSReportBlueCycle(step, pair, BlueStack, colorData, OutgoingTransitionTable); return; } else { list.RemoveAt(randIndex); } } // if the neighbour node is either blue or red, // can remove from the list else { list.RemoveAt(randIndex); } } if (blueDone) { BlueStack.Pop(); // If the current node is an accept state, // do the red DFS if (pair.state.EndsWith(Constants.ACCEPT_STATE)) { if (evt.IsDeadLock) { lock (MultiCoreLock) { StopMutliCoreThreads = true; Dictionary <string, LocalPair> LoopPairs = new Dictionary <string, LocalPair>(); LoopPairs.Add(v, pair); MultiCoreLocalTaskStack = BlueStack; MultiCoreResultedLoop = LoopPairs; MultiCoreOutgoingTransitionTable = OutgoingTransitionTable; return; } } bool stop = SwarmNestedDFSDepthFirstSearchRed(pair, BlueStack, OutgoingTransitionTable, colorData); if (stop) { return; } nodeColor.SetRed(); } else { nodeColor.SetBlue(); } } } while (BlueStack.Count > 0); StopMutliCoreThreads = true; VerificationOutput.VerificationResult = VerificationResultType.VALID; VerificationOutput.NoOfStates = colorData.Count; return; }
/// <summary> /// Improved Nested DFS /// A Note on On-The-Fly Verification Algorithms - TACAS 2005 /// Stefan Schwoon and Javier Esparza /// </summary> public void ImprovedNestedDFS() { // data for on-the-fly Nested DFS Dictionary <string, List <string> > outgoingTransitionTable = new Dictionary <string, List <string> >(Ultility.Ultility.MC_INITIAL_SIZE); Stack <LocalPair> blueStack = new Stack <LocalPair>(5000); Dictionary <string, Color> colorData = new Dictionary <string, Color>(5000); Dictionary <string, List <LocalPair> > expendedNodes = new Dictionary <string, List <LocalPair> >(1024); // create initial states List <LocalPair> initialStates = LocalPair.GetInitialPairsLocal(BA, InitialStep); if (initialStates.Count == 0 || !BA.HasAcceptState) { VerificationOutput.VerificationResult = VerificationResultType.VALID; return; } // test //expendedNodesNumber = 0; for (int i = 0; i < initialStates.Count; i++) { LocalPair tmp = initialStates[i]; blueStack.Push(tmp); string ID = tmp.GetCompressedState(); colorData.Add(ID, new Color()); outgoingTransitionTable.Add(ID, new List <string>(8)); } while (blueStack.Count > 0) { // cancel if too long action or couterexample reported if (CancelRequested) { VerificationOutput.NoOfStates = colorData.Count; return; } // get the top of blueStack LocalPair pair = blueStack.Peek(); ConfigurationBase LTSState = pair.configuration; string BAState = pair.state; string v = pair.GetCompressedState(); // local data of the top List <string> outgoing = outgoingTransitionTable[v]; Color vColor = colorData[v]; // if v is not expended then expend successors of v if (!expendedNodes.ContainsKey(v)) { // create next states from v & add to expendedNodes IEnumerable <ConfigurationBase> nextLTSStates = LTSState.MakeOneMove(); pair.SetEnabled(nextLTSStates, FairnessType); List <LocalPair> nextStates = LocalPair.NextLocal(BA, nextLTSStates, BAState); expendedNodes.Add(v, nextStates); // increase number of states expended //expendedNodesNumber++; // update outgoing of v and set initial data for successors // no need to use inverse for statement and use nextStates foreach (LocalPair next in nextStates) { string w = next.GetCompressedState(); outgoing.Add(w); if (!colorData.ContainsKey(w)) { colorData.Add(w, new Color()); outgoingTransitionTable.Add(w, new List <string>(8)); } } } // get successor of v List <LocalPair> successors = expendedNodes[v]; // visit v & early accepting cycle detection if (vColor.isWhite()) { vColor.setCyan(); // early cycle detection // use reverse order to remove visited states for (int i = successors.Count - 1; i >= 0; i--) { LocalPair succ = successors[i]; string w = succ.GetCompressedState(); Color wColor = colorData[w]; // if successor is not white then remove from expendedNodes if (wColor.isCyan()) { if (succ.state.EndsWith(Constants.ACCEPT_STATE) || pair.state.EndsWith(Constants.ACCEPT_STATE)) { blueReportAcceptinCycle(succ, blueStack, colorData, outgoingTransitionTable); return; } else { successors.RemoveAt(i); } } } } // find unvisited successor bool blueDone = true; for (int i = successors.Count - 1; i >= 0; i--) { LocalPair succ = successors[i]; string w = succ.GetCompressedState(); if (colorData[w].isWhite()) { blueStack.Push(succ); successors.RemoveAt(i); blueDone = false; break; } else { successors.RemoveAt(i); } } // if there is no unvisited successor if (blueDone) { // if v is accepting if (pair.state.EndsWith(Constants.ACCEPT_STATE)) { if (LTSState.IsDeadLock) { blueReportAcceptinCycle(pair, blueStack, colorData, outgoingTransitionTable); return; } else // start red DFS { bool stop = redDFSImprovedNestedDFS(pair, blueStack, colorData, outgoingTransitionTable); if (stop) { return; } } // SET PINK FOR ACCEPTING STATE vColor.setPink(); } else // v is not accepting { vColor.setBlue(); } // pop blueStack blueStack.Pop(); } } // report no couterexample VerificationOutput.VerificationResult = VerificationResultType.VALID; VerificationOutput.NoOfStates = colorData.Count; return; }
/// <summary> /// The function of each worker in MultiCore Tarjan Model Checking /// </summary> /// <returns></returns> public void MultiCoreWithSharedMemoryTarjanModelCheckingWorker() { Dictionary <string, List <string> > OutgoingTransitionTable = new Dictionary <string, List <string> >(Ultility.Ultility.MC_INITIAL_SIZE); Stack <LocalPair> TaskStack = new Stack <LocalPair>(5000); List <LocalPair> initials = LocalPair.GetInitialPairsLocal(BA, InitialStep); Dictionary <string, int[]> DFSData = new Dictionary <string, int[]>(5000); if (initials.Count == 0) { VerificationOutput.VerificationResult = VerificationResultType.VALID; return; } int threadId; // Create random variable with different seed for each thread Random rand; // helps different threads access different region of the graph lock (MultiCoreLock) { threadId = MultiCoreSeed; rand = new Random(MultiCoreSeed); MultiCoreSeed++; } // Create the list of initial states // May apply randomness here to increase performance int[] permutation = generatePermutation(initials.Count, rand); for (int z = 0; z < initials.Count; z++) { LocalPair initState = initials[permutation[z]]; TaskStack.Push(initState); string ID = initState.GetCompressedState(); DFSData.Add(ID, new int[] { VISITED_NOPREORDER, 0 }); OutgoingTransitionTable.Add(ID, new List <string>(8)); } Dictionary <string, LocalPair> SCCPairs = new Dictionary <string, LocalPair>(1024); Stack <LocalPair> stepStack = new Stack <LocalPair>(1024); // Preorder counter int i = 0; int numSCCs = 0; //store the expended event step of a node to avoid multiple invocation of the make one move. Dictionary <string, List <LocalPair> > ExpendedNode = new Dictionary <string, List <LocalPair> >(1024); do { if (CancelRequested || StopMutliCoreThreads) { return; } LocalPair pair = TaskStack.Peek(); ConfigurationBase evt = pair.configuration; string BAState = pair.state; string v = pair.GetCompressedState(); List <string> outgoing = OutgoingTransitionTable[v]; int[] nodeData = DFSData[v]; if (nodeData[0] == VISITED_NOPREORDER) { nodeData[0] = i; i++; } bool done = true; // Initialize the states if first time visited if (!ExpendedNode.ContainsKey(v)) { List <LocalPair> product; //lock (MultiCoreLock) //{ ConfigurationBase[] configList = evt.MakeOneMove(); pair.SetEnabled(configList, FairnessType); product = LocalPair.NextLocal(BA, configList, BAState); int[] randomPermutation = generatePermutation(product.Count, rand); List <LocalPair> randomProduct = new List <LocalPair>(); for (int k = 0; k < product.Count; k++) { randomProduct.Add(product[randomPermutation[k]]); } ExpendedNode.Add(v, randomProduct); //} for (int k = product.Count - 1; k >= 0; k--) { LocalPair step = product[k]; string tmp = step.GetCompressedState(); //update the incoming and outgoing edges outgoing.Add(tmp); if (!DFSData.ContainsKey(tmp)) { DFSData.Add(tmp, new int[] { VISITED_NOPREORDER, 0 }); OutgoingTransitionTable.Add(tmp, new List <string>(8)); } } } List <LocalPair> list = ExpendedNode[v]; //transverse all neighbour nodes for (int k = list.Count - 1; k >= 0; k--) { //int randIndex = rand.Next(list.Count); int randIndex = k; LocalPair step = list[randIndex]; string tmp = step.GetCompressedState(); int[] neighbourDFSData = DFSData[tmp]; //if the step is a unvisited step if (neighbourDFSData[0] == VISITED_NOPREORDER && !SharedSCCFoundStatesMultiCoreTarjan.ContainsKey(tmp)) { if (done) { TaskStack.Push(step); done = false; list.RemoveAt(randIndex); break; } } else { list.RemoveAt(randIndex); } } if (done) { TaskStack.Pop(); int lowlinkV = nodeData[0]; int preorderV = lowlinkV; bool selfLoop = false; for (int j = 0; j < outgoing.Count; j++) { string w = outgoing[j]; if (w == v) { selfLoop = true; } int[] wdata = DFSData[w]; if (wdata[0] != SCC_FOUND && !SharedSCCFoundStatesMultiCoreTarjan.ContainsKey(w)) { if (wdata[0] > preorderV) { lowlinkV = Math.Min(lowlinkV, wdata[1]); } else { lowlinkV = Math.Min(lowlinkV, wdata[0]); } } } nodeData[1] = lowlinkV; if (lowlinkV == preorderV) { bool stopCheckSCC = false; SCCPairs.Add(v, pair); nodeData[0] = SCC_FOUND; //if (!SharedSCCFoundStatesMultiCoreTarjan.ContainsKey(v)) //{ lock (MultiCoreLock) { if (!SharedSCCFoundStatesMultiCoreTarjan.ContainsKey(v)) { numSCCs++; SharedSCCFoundStatesMultiCoreTarjan.Add(v, true); } else { stopCheckSCC = true; } } //} //else //{ // stopCheckSCC = true; //} //checking for buchi-fair bool BuchiFair = pair.state.EndsWith(Constants.ACCEPT_STATE); while (stepStack.Count > 0 && DFSData[stepStack.Peek().GetCompressedState()][0] > preorderV) { LocalPair stepStackNode = stepStack.Pop(); string stepStackNodeID = stepStackNode.GetCompressedState(); DFSData[stepStackNodeID][0] = SCC_FOUND; if (!stopCheckSCC) { SCCPairs.Add(stepStackNodeID, stepStackNode); //if (!SharedSCCFoundStatesMultiCoreTarjan.ContainsKey(stepStackNodeID)) //{ lock (MultiCoreLock) { if (!SharedSCCFoundStatesMultiCoreTarjan.ContainsKey(stepStackNodeID)) { SharedSCCFoundStatesMultiCoreTarjan.Add(stepStackNodeID, true); } } //} if (!BuchiFair && stepStackNode.state.EndsWith(Constants.ACCEPT_STATE)) { BuchiFair = true; } } else { ExpendedNode.Remove(stepStackNodeID); OutgoingTransitionTable.Remove(stepStackNodeID); } } int SCCSize = SCCPairs.Count; if (!stopCheckSCC && BuchiFair && (evt.IsDeadLock || SCCSize > 1 || selfLoop)) { Dictionary <string, LocalPair> value = IsFair(SCCPairs, OutgoingTransitionTable); if (value != null) { lock (MultiCoreLock) { StopMutliCoreThreads = true; MultiCoreResultedLoop = value; MultiCoreOutgoingTransitionTable = OutgoingTransitionTable; MultiCoreLocalTaskStack = TaskStack; } return; } } // Avoid access to found SCCs foreach (string componet in SCCPairs.Keys) { ExpendedNode.Remove(componet); OutgoingTransitionTable.Remove(componet); } //StronglyConnectedComponets.Clear(); SCCPairs.Clear(); } else { stepStack.Push(pair); } } } while (TaskStack.Count > 0); //Console.WriteLine("Thread {0} has traversed {1} SCCs", threadId, numSCCs); }
/// <summary> /// Local Tarjan in each thread to find SCC /// </summary> /// <param name="o"></param> public void LocalImprovedFairTarjan(object o) { //order of this thread int order = (int)o; Random rand = new Random(order); //on-the-fly data Stack <LocalPair> localCallStack = new Stack <LocalPair>(5000); Stack <LocalPair> localCurrentStack = new Stack <LocalPair>(1024); Stack <LocalPair> localGoalStack = new Stack <LocalPair>(256); Dictionary <string, int[]> localDFSNumber = new Dictionary <string, int[]>(5000); int localNumber = 0; Dictionary <string, List <LocalPair> > localExpendedNodes = new Dictionary <string, List <LocalPair> >(5000); //initial states List <LocalPair> initialStates = LocalPair.GetInitialPairsLocal(BA, InitialStep); //check valid result if (initialStates.Count == 0 || !BA.HasAcceptState) { return; } //push local initial states to local call stack int[] localPerm = Permutation(initialStates.Count, rand); for (int i = 0; i < initialStates.Count; i++) { LocalPair tmp = initialStates[localPerm[i]]; localCallStack.Push(tmp); } //start loop while (localCallStack.Count > 0) { //cancel if take long time if (CancelRequested || isGlobalStop) { return; } //get top of call stack LocalPair pair = localCallStack.Peek(); ConfigurationBase LTSState = pair.configuration; string BAState = pair.state; string v = pair.GetCompressedState(); //get successors List <LocalPair> successors = null; if (localExpendedNodes.ContainsKey(v)) { successors = localExpendedNodes[v]; } else { IEnumerable <ConfigurationBase> nextLTSStates = LTSState.MakeOneMove(); pair.SetEnabled(nextLTSStates, FairnessType); successors = LocalPair.NextLocal(BA, nextLTSStates, BAState); localExpendedNodes.Add(v, successors); } //if v is not number yet if (!localDFSNumber.ContainsKey(v)) { //number v int[] vData = new int[] { localNumber, localNumber }; localDFSNumber.Add(v, vData); localNumber = localNumber + 1; //push to currentStack localCurrentStack.Push(pair); //check whether v is accepting if (pair.state.EndsWith(Constants.ACCEPT_STATE)) { localGoalStack.Push(pair); } //update lowlink for already numbered successors for (int i = successors.Count - 1; i >= 0; i--) { LocalPair succ = successors[i]; string w = succ.GetCompressedState(); if (localDFSNumber.ContainsKey(w)) { int[] wData = localDFSNumber[w]; //if w is in current stack if (wData[0] >= 0) { vData[1] = Math.Min(vData[1], wData[0]); //check for report accepting cycle if (localGoalStack.Count > 0 && vData[1] <= localDFSNumber[localGoalStack.Peek().GetCompressedState()][0]) { //------------------------------------ //get SCC Dictionary <string, LocalPair> newSCC = new Dictionary <string, LocalPair>(); Dictionary <string, List <string> > newOutgoingTransitionTable = new Dictionary <string, List <string> >(); LocalPair[] callArray = localCallStack.ToArray(); for (int j = 0; j < callArray.Length; j++) { LocalPair state = callArray[i]; string stateID = state.GetCompressedState(); newSCC.Add(stateID, state); List <string> outgoing = new List <string>(8); List <LocalPair> nextStates = localExpendedNodes[stateID]; foreach (LocalPair next in nextStates) { string nextID = next.GetCompressedState(); outgoing.Add(nextID); } newOutgoingTransitionTable.Add(stateID, outgoing); if (stateID.Equals(w)) { break; } } Dictionary <string, LocalPair> fairSCC = IsFair(newSCC, newOutgoingTransitionTable); if (fairSCC != null) { //REPORT COUNTEREXAMPLE GetLocalLoopCounterExample(w, localCallStack); return; } return; } } } } } //------------------------------------------------------------------------ //filter successors List <int> unvisitedIndexs = new List <int>(successors.Count);//not numbered and not global found for (int i = successors.Count - 1; i >= 0; i--) { LocalPair succ = successors[i]; string w = succ.GetCompressedState(); //if w is not cyan and not global red if (!localDFSNumber.ContainsKey(w) && !globalFoundSCCs.ContainsKey(w)) { unvisitedIndexs.Add(i); } } //------------------------------------------------------------------------ //get random unvisited successors if (unvisitedIndexs.Count > 0) { bool isFresh = false; List <int> unFreshIndexs = new List <int>(); while (unvisitedIndexs.Count > 0) { int r = rand.Next(unvisitedIndexs.Count); LocalPair succ = successors[unvisitedIndexs[r]]; string w = succ.GetCompressedState(); //if w is fresh successor if (!allVisitedStates.ContainsKey(w)) { localCallStack.Push(succ); allVisitedStates.GetOrAdd(w, 0); allVisitedStates[w]++; isFresh = true; break; } else { unFreshIndexs.Add(unvisitedIndexs[r]); unvisitedIndexs.RemoveAt(r); } } if (!isFresh) { int r = rand.Next(unFreshIndexs.Count); LocalPair succ = successors[unFreshIndexs[r]]; string w = succ.GetCompressedState(); localCallStack.Push(succ); allVisitedStates.GetOrAdd(w, 0); allVisitedStates[w]++; } } else { //update global globalFoundSCCs.GetOrAdd(v, true); int[] vData = localDFSNumber[v]; //if v is root if (vData[0] == vData[1]) { // check selfLoop bool selfLoop = false; foreach (LocalPair succ in successors) { string w = succ.GetCompressedState(); if (v.Equals(w)) { selfLoop = true; break; } } //remove states from current stack and goal stack //updata global bool isBuchiFair = false; Dictionary <string, LocalPair> newSCC = new Dictionary <string, LocalPair>(1024); List <ConfigurationBase> cycle = new List <ConfigurationBase>(1024); LocalPair tmp = null; string tmpID = null; do { //get states in SCC tmp = localCurrentStack.Pop(); if (!isBuchiFair && tmp.state.EndsWith(Constants.ACCEPT_STATE)) { isBuchiFair = true; } tmpID = tmp.GetCompressedState(); newSCC.Add(tmpID, tmp); cycle.Insert(0, tmp.configuration); //local localDFSNumber[tmpID][0] = SCC_FOUND; } while (tmp != pair); //local check fairness if (isBuchiFair && (selfLoop || newSCC.Count > 1 || LTSState.IsDeadLock)) { //------------------------------------ //get outgoing transition table Dictionary <string, List <string> > outgoingTransitionTable = new Dictionary <string, List <string> >(newSCC.Count); foreach (KeyValuePair <string, LocalPair> kv in newSCC) { string s = kv.Key; List <LocalPair> nextStates = localExpendedNodes[s]; List <string> outgoing = new List <string>(nextStates.Count); foreach (LocalPair next in nextStates) { string n = next.GetCompressedState(); outgoing.Add(n); } outgoingTransitionTable.Add(s, outgoing); } //------------------------------------ Dictionary <string, LocalPair> fairSCC = IsFair(newSCC, outgoingTransitionTable); if (fairSCC != null) { //REPORT COUNTEREXAMPLE GetLocalFairCounterExample(localCallStack, cycle, LTSState.IsDeadLock); return; } } //pop call stack localCallStack.Pop(); } else { //pop call stack and update lowlink of top LocalPair pop = localCallStack.Pop(); LocalPair top = localCallStack.Peek(); string popID = pop.GetCompressedState(); string topID = top.GetCompressedState(); int[] popData = localDFSNumber[popID]; int[] topData = localDFSNumber[topID]; topData[1] = Math.Min(topData[1], popData[1]); } } } }
/// <summary> /// Tarjan algorithm with farness checking /// </summary> public void FairTarjan() { VerificationOutput.CounterExampleTrace = null; //on-the-fly data Stack <LocalPair> callStack = new Stack <LocalPair>(5000); Stack <LocalPair> currentStack = new Stack <LocalPair>(5000); Stack <LocalPair> goalStack = new Stack <LocalPair>(1024); Dictionary <string, int[]> dfsNumber = new Dictionary <string, int[]>(5000); Dictionary <string, List <LocalPair> > expendedNodes = new Dictionary <string, List <LocalPair> >(5000); int number = 0; Random rand = new Random(); //initial states List <LocalPair> initialStates = LocalPair.GetInitialPairsLocal(BA, InitialStep); //check valid result if (initialStates.Count == 0 || !BA.HasAcceptState) { VerificationOutput.VerificationResult = VerificationResultType.VALID; return; } //push initial states to call stack foreach (LocalPair tmp in initialStates) { callStack.Push(tmp); } //start loop while (callStack.Count > 0) { //cancel if take long time if (CancelRequested) { VerificationOutput.NoOfStates = dfsNumber.Count; return; } //get top of call stack LocalPair pair = callStack.Peek(); ConfigurationBase LTSState = pair.configuration; string BAState = pair.state; string v = pair.GetCompressedState(); //get successors List <LocalPair> successors = null; if (expendedNodes.ContainsKey(v)) { successors = expendedNodes[v]; } else { IEnumerable <ConfigurationBase> nextLTSStates = LTSState.MakeOneMove(); pair.SetEnabled(nextLTSStates, FairnessType); successors = LocalPair.NextLocal(BA, nextLTSStates, BAState); expendedNodes.Add(v, successors); } //if v is not number yet if (!dfsNumber.ContainsKey(v)) { //number v int[] vData = new int[] { number, number }; dfsNumber.Add(v, vData); number = number + 1; //push to currentStack currentStack.Push(pair); //update lowlink for already numbered successors for (int i = successors.Count - 1; i >= 0; i--) { LocalPair succ = successors[i]; string w = succ.GetCompressedState(); //if w is already numbered if (dfsNumber.ContainsKey(w)) { int[] wData = dfsNumber[w]; //if w is in current stack if (wData[0] >= 0) { vData[1] = Math.Min(vData[1], wData[0]); } } } } //------------------------------------------------------------------------ //check if there is an unnumbered successor List <int> unvisitedIndexs = new List <int>(successors.Count);//not visited for (int i = successors.Count - 1; i >= 0; i--) { LocalPair succ = successors[i]; string w = succ.GetCompressedState(); //if w is not already numbered if (!dfsNumber.ContainsKey(w)) { unvisitedIndexs.Add(i); } } //------------------------------------------------------------------------ //get random unvisited successors if (unvisitedIndexs.Count > 0) { int r = rand.Next(unvisitedIndexs.Count); LocalPair succ = successors[unvisitedIndexs[r]]; callStack.Push(succ); } else { int[] vData = dfsNumber[v]; //if v is root if (vData[0] == vData[1]) { // check selfLoop bool selfLoop = false; foreach (LocalPair succ in successors) { string w = succ.GetCompressedState(); if (v.Equals(w)) { selfLoop = true; break; } } //remove states from current stack and goal stack Dictionary <string, LocalPair> newSCC = new Dictionary <string, LocalPair>(1024); List <ConfigurationBase> cycle = new List <ConfigurationBase>(1024); bool isBuchiFair = false; LocalPair tmp = null; string tmpID = null; do { //current stack tmp = currentStack.Pop(); if (!isBuchiFair && tmp.state.EndsWith(Constants.ACCEPT_STATE)) { isBuchiFair = true; } tmpID = tmp.GetCompressedState(); newSCC.Add(tmpID, tmp); cycle.Insert(0, tmp.configuration); //mark visited dfsNumber[tmpID][0] = SCC_FOUND; } while (tmp != pair); //check fairness if (isBuchiFair && (selfLoop || newSCC.Count > 1 || LTSState.IsDeadLock)) { //get outgoing transition table Dictionary <string, List <string> > outgoingTransitionTable = new Dictionary <string, List <string> >(newSCC.Count); foreach (KeyValuePair <string, LocalPair> kv in newSCC) { string s = kv.Key; List <LocalPair> nextStates = expendedNodes[s]; List <string> outgoing = new List <string>(nextStates.Count); foreach (LocalPair next in nextStates) { string n = next.GetCompressedState(); outgoing.Add(n); } outgoingTransitionTable.Add(s, outgoing); } Dictionary <string, LocalPair> fairSCC = IsFair(newSCC, outgoingTransitionTable); if (fairSCC != null) { //REPORT COUNTEREXAMPLE GetFairCounterExample(callStack, cycle, dfsNumber, LTSState.IsDeadLock); return; } } //pop call stack callStack.Pop(); } else { //pop call stack and update lowlink of top LocalPair pop = callStack.Pop(); LocalPair top = callStack.Peek(); string popID = pop.GetCompressedState(); string topID = top.GetCompressedState(); int[] popData = dfsNumber[popID]; int[] topData = dfsNumber[topID]; topData[1] = Math.Min(topData[1], popData[1]); } } } //no counter example VerificationOutput.VerificationResult = VerificationResultType.VALID; VerificationOutput.NoOfStates = dfsNumber.Count; return; }
/// <summary> /// Local Improved Tarjan in each thread /// </summary> /// <param name="o"></param> public void LocalImprovedTarjanSwarm(object o) { //order of this thread int order = (int)o; Random rand = new Random(order); //on-the-fly data Stack <LocalPair> localCallStack = new Stack <LocalPair>(5000); Stack <LocalPair> localCurrentStack = new Stack <LocalPair>(1024); Stack <LocalPair> localGoalStack = new Stack <LocalPair>(256); Dictionary <string, int[]> localDFSNumber = new Dictionary <string, int[]>(5000); int localNumber = 0; Dictionary <string, List <LocalPair> > localExpendedNodes = new Dictionary <string, List <LocalPair> >(5000); //initial states List <LocalPair> initialStates = LocalPair.GetInitialPairsLocal(BA, InitialStep); //check valid result if (initialStates.Count == 0 || !BA.HasAcceptState) { return; } //push local initial states to local call stack int[] localPerm = Permutation(initialStates.Count, rand); for (int i = 0; i < initialStates.Count; i++) { LocalPair tmp = initialStates[localPerm[i]]; localCallStack.Push(tmp); } //start loop while (localCallStack.Count > 0) { //cancel if take long time if (CancelRequested || isGlobalStop) { return; } //get top of call stack LocalPair pair = localCallStack.Peek(); ConfigurationBase LTSState = pair.configuration; string BAState = pair.state; string v = pair.GetCompressedState(); //get successors List <LocalPair> successors = null; if (localExpendedNodes.ContainsKey(v)) { successors = localExpendedNodes[v]; } else { IEnumerable <ConfigurationBase> nextLTSStates = LTSState.MakeOneMove(); pair.SetEnabled(nextLTSStates, FairnessType); successors = LocalPair.NextLocal(BA, nextLTSStates, BAState); localExpendedNodes.Add(v, successors); } //if v is not number yet if (!localDFSNumber.ContainsKey(v)) { //number v int[] vData = new int[] { localNumber, localNumber }; localDFSNumber.Add(v, vData); localNumber = localNumber + 1; //push to currentStack localCurrentStack.Push(pair); //check whether v is accepting if (pair.state.EndsWith(Constants.ACCEPT_STATE)) { localGoalStack.Push(pair); } //update lowlink for already numbered successors for (int i = successors.Count - 1; i >= 0; i--) { LocalPair succ = successors[i]; string w = succ.GetCompressedState(); if (localDFSNumber.ContainsKey(w)) { int[] wData = localDFSNumber[w]; //if w is in current stack if (wData[0] >= 0) { vData[1] = Math.Min(vData[1], wData[0]); //check for report accepting cycle if (localGoalStack.Count > 0 && vData[1] <= localDFSNumber[localGoalStack.Peek().GetCompressedState()][0]) { //REPORT COUNTEREXAMPLE GetLocalLoopCounterExample(w, localCallStack); return; } } } } } //------------------------------------------------------------------------ //filter successors List <int> unvisitedIndexs = new List <int>(successors.Count);//not numbered and not global found for (int i = successors.Count - 1; i >= 0; i--) { LocalPair succ = successors[i]; string w = succ.GetCompressedState(); //if w is not cyan and not global red if (!localDFSNumber.ContainsKey(w)) { unvisitedIndexs.Add(i); } } //------------------------------------------------------------------------ //get random unvisited successors if (unvisitedIndexs.Count > 0) { bool isFresh = false; List <int> unFreshIndexs = new List <int>(); while (unvisitedIndexs.Count > 0) { int r = rand.Next(unvisitedIndexs.Count); LocalPair succ = successors[unvisitedIndexs[r]]; string w = succ.GetCompressedState(); //if w is fresh successor if (!allVisitedStates.ContainsKey(w)) { localCallStack.Push(succ); allVisitedStates.GetOrAdd(w, 0); allVisitedStates[w]++; isFresh = true; break; } else { unFreshIndexs.Add(unvisitedIndexs[r]); unvisitedIndexs.RemoveAt(r); } } if (!isFresh) { int r = rand.Next(unFreshIndexs.Count); LocalPair succ = successors[unFreshIndexs[r]]; string w = succ.GetCompressedState(); localCallStack.Push(succ); allVisitedStates.GetOrAdd(w, 0); allVisitedStates[w]++; } } else { //deadlock at accepting state if (LTSState.IsDeadLock && pair.state.EndsWith(Constants.ACCEPT_STATE)) { //REPORT COUNTEREXAMPLE GetLocalDeadlockCounterExample(localCallStack); return; } int[] vData = localDFSNumber[v]; //if v is root if (vData[0] == vData[1]) { //remove states from current stack and goal stack LocalPair tmp = null; string tmpID = null; do { //current stack tmp = localCurrentStack.Pop(); tmpID = tmp.GetCompressedState(); localDFSNumber[tmpID][0] = SCC_FOUND; //goal stack if (localGoalStack.Count > 0 && tmp == localGoalStack.Peek()) { localGoalStack.Pop(); } } while (tmp != pair); //pop call stack localCallStack.Pop(); } else { //pop call stack and update lowlink of top LocalPair pop = localCallStack.Pop(); LocalPair top = localCallStack.Peek(); string popID = pop.GetCompressedState(); string topID = top.GetCompressedState(); int[] popData = localDFSNumber[popID]; int[] topData = localDFSNumber[topID]; topData[1] = Math.Min(topData[1], popData[1]); } } } }
// local function of each thread public void localQueueTarjanFairnessChecking(object o) { // get order int order = (int)o; // local data for on-the-fly and Tarjan algorithm Dictionary <string, List <string> > outgoingTransitionTable = new Dictionary <string, List <string> >(Ultility.Ultility.MC_INITIAL_SIZE); Stack <LocalPair> callStack = new Stack <LocalPair>(5000); Stack <LocalPair> currentStack = new Stack <LocalPair>(1024); Dictionary <string, int[]> dfsData = new Dictionary <string, int[]>(5000); Dictionary <string, List <LocalPair> > expendedNodes = new Dictionary <string, List <LocalPair> >(1024); int counter = 0; //-------------------------- // create initial states List <LocalPair> initialStates = LocalPair.GetInitialPairsLocal(BA, InitialStep); if (initialStates.Count == 0 || !BA.HasAcceptState) { return; } // create random variable for each process Random rand = new Random(order); // push all initial states to callStack in different order & init data int[] initPermutation = generatePermutation(initialStates.Count, rand); for (int i = 0; i < initPermutation.Length; i++) { //get data from initialStates LocalPair tmp = initialStates[initPermutation[i]]; callStack.Push(tmp); string tmpID = tmp.GetCompressedState(); dfsData.Add(tmpID, new int[] { VISITED_NOPREORDER, 0 }); outgoingTransitionTable.Add(tmpID, new List <string>(8)); } // start loop while (callStack.Count > 0) { // cancel if too long action or any counterexample is reported if (CancelRequested || isStop) { return; } // get the top of callStack LocalPair pair = callStack.Peek(); ConfigurationBase LTSState = pair.configuration; string BAState = pair.state; string v = pair.GetCompressedState(); // get local data of the top List <string> outgoing = outgoingTransitionTable[v]; int[] vData = dfsData[v]; // if not expended then expend to next states from v if (!expendedNodes.ContainsKey(v)) { // create next states of v IEnumerable <ConfigurationBase> nextLTSStates = LTSState.MakeOneMove(); pair.SetEnabled(nextLTSStates, FairnessType); List <LocalPair> nextStates = LocalPair.NextLocal(BA, nextLTSStates, BAState); expendedNodes.Add(v, nextStates); // add to visitedTimes in this thread //visitedTimes.GetOrAdd(v, 0); //visitedTimes[v]++; // update outgoing of v and set initial data for successors // no need to use inverse for statement and use nextStates foreach (LocalPair next in nextStates) { string w = next.GetCompressedState(); outgoing.Add(w); if (!dfsData.ContainsKey(w)) { dfsData.Add(w, new int[] { VISITED_NOPREORDER, 0 }); outgoingTransitionTable.Add(w, new List <string>(8)); } } } // get successors of v List <LocalPair> successors = expendedNodes[v]; // process if v is not numbered yet if (vData[0] == VISITED_NOPREORDER) { vData[0] = counter; vData[1] = counter; counter = counter + 1; // push to currentStack currentStack.Push(pair); // update lowlink according to successors in currentStack // remove already visited successors // no need to use random for (int i = successors.Count - 1; i >= 0; i--) { LocalPair succ = successors[i]; string w = succ.GetCompressedState(); int[] wData = dfsData[w]; if (wData[0] >= 0) { // update & remove from expendedNodes(v) vData[1] = Math.Min(vData[1], wData[0]); successors.RemoveAt(i); } } } // check if there is any successor not numbered & not visited by other threads // choose random bool completed = true; for (int i = successors.Count - 1; i >= 0; i--) { int randIndex = rand.Next(successors.Count); LocalPair succ = successors[randIndex]; string w = succ.GetCompressedState(); int[] wData = dfsData[w]; // check states not locally visited & not in global shared found SCC if (wData[0] == VISITED_NOPREORDER && !sharedSCCStates.ContainsKey(w)) { callStack.Push(succ); successors.RemoveAt(randIndex); completed = false; break; } else { successors.RemoveAt(randIndex); } } // if all successors are visited if (completed) { // check root if (vData[0] == vData[1]) { Dictionary <string, LocalPair> newSCC = new Dictionary <string, LocalPair>(1024); // check selfLoop bool selfLoop = false; foreach (string w in outgoing) { if (v.Equals(w)) { selfLoop = true; break; } } // get all states in a SCC & check Buchi fair bool isBuchiFair = false; LocalPair tmp = null; string tmpID = null; // get from current until v do { tmp = currentStack.Pop(); isBuchiFair = isBuchiFair || tmp.state.EndsWith(Constants.ACCEPT_STATE); tmpID = tmp.GetCompressedState(); int[] tmpData = dfsData[tmpID]; tmpData[0] = SCC_FOUND; newSCC.Add(tmpID, tmp); // update global sharedSCCStates.GetOrAdd(tmpID, true); } while (!tmpID.Equals(v)); if (isBuchiFair && (selfLoop || newSCC.Count > 1 || LTSState.IsDeadLock)) { // queue new SCC to check fairness localQueueSCC(order, newSCC, callStack, outgoingTransitionTable); } //pop callStack callStack.Pop(); } else { //pop callStack & update the parent LocalPair pop = callStack.Pop(); LocalPair top = callStack.Peek(); string popID = pop.GetCompressedState(); string topID = top.GetCompressedState(); int[] popData = dfsData[popID]; int[] topData = dfsData[topID]; topData[1] = Math.Min(topData[1], popData[1]); } } } isStop = true; }
/// <summary> /// Run the verification using the Nested DFS algorithm and get the result. /// Based on: /// A Note on On-The-Fly Verification Algorithms /// http://dl.acm.org/citation.cfm?id=2140670 /// Stefan Schwoon and Javier Esparza /// Proceeding TACAS'05 Proceedings of the 11th international conference on /// Tools and Algorithms for the Construction and Analysis of Systems /// Springer-Verlag Berlin, Heidelberg, 2005 /// </summary> /// <returns></returns> public void NestedDFSModelChecking() { Dictionary <string, List <string> > OutgoingTransitionTable = new Dictionary <string, List <string> >(Ultility.Ultility.MC_INITIAL_SIZE); VerificationOutput.CounterExampleTrace = null; List <LocalPair> initials = LocalPair.GetInitialPairsLocal(BA, InitialStep); if (initials.Count == 0) { VerificationOutput.VerificationResult = VerificationResultType.VALID; return; } Stack <LocalPair> BlueStack = new Stack <LocalPair>(5000); StringDictionary <StateColor> colorData = new StringDictionary <StateColor>(5000); for (int z = 0; z < initials.Count; z++) { LocalPair initState = initials[z]; BlueStack.Push(initState); string ID = initState.GetCompressedState(); colorData.Add(ID, new StateColor()); OutgoingTransitionTable.Add(ID, new List <string>(8)); } //store the expended event step of a node to avoid multiple invocation of the make one move. Dictionary <string, List <LocalPair> > ExpendedNode = new Dictionary <string, List <LocalPair> >(1024); do { if (CancelRequested) { VerificationOutput.NoOfStates = colorData.Count; // VisitedWithID.Count; return; } LocalPair pair = BlueStack.Peek(); ConfigurationBase evt = pair.configuration; string BAState = pair.state; string v = pair.GetCompressedState(); List <string> outgoing = OutgoingTransitionTable[v]; StateColor nodeColor = colorData.GetContainsKey(v); if (nodeColor.IsWhite()) { nodeColor.SetCyan(); } bool blueDone = true; if (ExpendedNode.ContainsKey(v)) { List <LocalPair> list = ExpendedNode[v]; if (list.Count > 0) { //transverse all neighbour nodes for (int k = list.Count - 1; k >= 0; k--) { LocalPair step = list[k]; string tmp = step.GetCompressedState(); StateColor neighbourColor = colorData.GetContainsKey(tmp); //if the neighbour node is white if (neighbourColor.IsWhite()) { //only add the first unvisited node //for the second or more unvisited steps, ignore at the monent if (blueDone) { BlueStack.Push(step); blueDone = false; list.RemoveAt(k); } } // if the neighbour node is cyan, // and either this node or the neibour node is the accept state // then report cycle else if (neighbourColor.IsCyan()) { if (step.state.EndsWith(Constants.ACCEPT_STATE) || pair.state.EndsWith(Constants.ACCEPT_STATE)) { // Report cycle ReportBlueCycle(step, pair, BlueStack, colorData, OutgoingTransitionTable); return; } else { list.RemoveAt(k); } } // if the neighbour node is either blue or red, // can remove from the list else { list.RemoveAt(k); } } } } else { //ConfigurationBase[] list = evt.MakeOneMove().ToArray(); IEnumerable <ConfigurationBase> list = evt.MakeOneMove(); pair.SetEnabled(list, FairnessType); List <LocalPair> product = LocalPair.NextLocal(BA, list, BAState); //count the transitions visited VerificationOutput.Transitions += product.Count; for (int k = product.Count - 1; k >= 0; k--) { LocalPair step = product[k]; string tmp = step.GetCompressedState(); StateColor neighbourColor = colorData.GetContainsKey(tmp); if (neighbourColor != null) { //update the incoming and outgoing edges outgoing.Add(tmp); //if this node is still not visited if (neighbourColor.IsWhite()) { //only add the first unvisited node //for the second or more unvisited steps, ignore at the monent if (blueDone) { BlueStack.Push(step); blueDone = false; product.RemoveAt(k); } } // if the neighbour node is cyan, // and either this node or the neibour node is the accept state // then report cycle else if (neighbourColor.IsCyan()) { if (step.state.EndsWith(Constants.ACCEPT_STATE) || pair.state.EndsWith(Constants.ACCEPT_STATE)) { // Report cycle ReportBlueCycle(step, pair, BlueStack, colorData, OutgoingTransitionTable); return; } else { product.RemoveAt(k); } } // if the neighbour node is either blue or red, // can remove from the list else { product.RemoveAt(k); } } // If the node is not initiated else { colorData.Add(tmp, new StateColor()); OutgoingTransitionTable.Add(tmp, new List <string>(8)); outgoing.Add(tmp); if (blueDone) { BlueStack.Push(step); blueDone = false; product.RemoveAt(k); } } } //create the remaining steps as the expending list for v ExpendedNode.Add(v, product); } if (blueDone) { BlueStack.Pop(); // If the current node is an accept state, // do the red DFS if (pair.state.EndsWith(Constants.ACCEPT_STATE)) { if (evt.IsDeadLock) { VerificationOutput.VerificationResult = VerificationResultType.INVALID; VerificationOutput.NoOfStates = colorData.Count; Dictionary <string, LocalPair> LoopPairs = new Dictionary <string, LocalPair>(); LoopPairs.Add(v, pair); LocalTaskStack = BlueStack; LocalGetCounterExample(LoopPairs, OutgoingTransitionTable); return; } bool stop = DepthFirstSearchRed(pair, BlueStack, OutgoingTransitionTable, colorData); if (stop) { return; } nodeColor.SetRed(); } else { nodeColor.SetBlue(); } } } while (BlueStack.Count > 0); VerificationOutput.VerificationResult = VerificationResultType.VALID; VerificationOutput.NoOfStates = colorData.Count; return; }
/// <summary> /// Improve Tarjan-Geldenhuy algorithm /// Iterative version /// </summary> public void ImprovedTarjanGeldenhuysValmari() { VerificationOutput.CounterExampleTrace = null; // data for on-the-fly and Tarjan algorithm Dictionary <string, List <string> > outgoingTransitionTable = new Dictionary <string, List <string> >(Ultility.Ultility.MC_INITIAL_SIZE); Stack <LocalPair> callStack = new Stack <LocalPair>(5000); Stack <LocalPair> currentStack = new Stack <LocalPair>(1024); Stack <LocalPair> goalStack = new Stack <LocalPair>(256); Dictionary <string, int[]> dfsData = new Dictionary <string, int[]>(5000); Dictionary <string, List <LocalPair> > expendedNodes = new Dictionary <string, List <LocalPair> >(1024); int counter = 0; //-------------------------- // create initial states List <LocalPair> initialStates = LocalPair.GetInitialPairsLocal(BA, InitialStep); if (initialStates.Count == 0 || !BA.HasAcceptState) { VerificationOutput.VerificationResult = VerificationResultType.VALID; return; } // test //expendedNodesNumber = 0; // put all initial states to callStack & init data foreach (LocalPair tmp in initialStates) { callStack.Push(tmp); string tmpID = tmp.GetCompressedState(); dfsData.Add(tmpID, new int[] { VISITED_NOPREORDER, 0 }); outgoingTransitionTable.Add(tmpID, new List <string>(8)); } // start loop while (callStack.Count > 0) { // cancel if too long action if (CancelRequested) { VerificationOutput.NoOfStates = dfsData.Count; return; } // get the top of callStack LocalPair pair = callStack.Peek(); ConfigurationBase LTSState = pair.configuration; string BAState = pair.state; string v = pair.GetCompressedState(); // get data of the top List <string> outgoing = outgoingTransitionTable[v]; int[] vData = dfsData[v]; // if not expended then expend to next states from v if (!expendedNodes.ContainsKey(v)) { // create next states of v & add to expendedNodes IEnumerable <ConfigurationBase> nextLTSStates = LTSState.MakeOneMove(); //.ToArray() pair.SetEnabled(nextLTSStates, FairnessType); List <LocalPair> nextStates = LocalPair.NextLocal(BA, nextLTSStates, BAState); expendedNodes.Add(v, nextStates); // increase number of states expended //expendedNodesNumber++; // increase transitions visited VerificationOutput.Transitions += nextStates.Count; // update outgoing of v and set initial data for successors // no need to use inverse for statement foreach (LocalPair next in nextStates) { string w = next.GetCompressedState(); outgoing.Add(w); if (!dfsData.ContainsKey(w)) { dfsData.Add(w, new int[] { VISITED_NOPREORDER, 0 }); outgoingTransitionTable.Add(w, new List <string>(8)); } } } // get successors of v List <LocalPair> successors = expendedNodes[v]; // process if v is not numbered yet if (vData[0] == VISITED_NOPREORDER) { vData[0] = counter; vData[1] = counter; counter = counter + 1; // push to currentStack currentStack.Push(pair); // check whether v is accepting if (pair.state.EndsWith(Constants.ACCEPT_STATE)) { goalStack.Push(pair); } // update lowlink according to successors in currentStack // remove already visited successors for (int i = successors.Count - 1; i >= 0; i--) { LocalPair succ = successors[i]; string w = succ.GetCompressedState(); int[] wData = dfsData[w]; if (wData[0] >= 0) { // update & remove from expendedNodes(v) vData[1] = Math.Min(vData[1], wData[0]); successors.RemoveAt(i); // check for report accepting cycle if (goalStack.Count > 0 && vData[1] <= dfsData[goalStack.Peek().GetCompressedState()][0]) { // REPORT COUNTEREXAMPLE reportAcceptingCycle(succ, callStack, dfsData, outgoingTransitionTable); return; } } } } // check if there is any successor not numbered bool completed = true; for (int i = successors.Count - 1; i >= 0; i--) { LocalPair succ = successors[i]; string w = succ.GetCompressedState(); int[] wData = dfsData[w]; if (wData[0] == VISITED_NOPREORDER) { callStack.Push(succ); successors.RemoveAt(i); completed = false; break; } else { successors.RemoveAt(i); } } // if all successors are visited if (completed) { // check for loop at deadlock & accepting state if (LTSState.IsDeadLock && pair.state.EndsWith(Constants.ACCEPT_STATE)) { // report accepting cycle reportAcceptingCycle(pair, callStack, dfsData, outgoingTransitionTable); return; } if (vData[0] == vData[1]) { LocalPair tmp = null; string tmpID = null; // pop currentStack and update SCC_FOUND until v do { // remove from currentStack tmp = currentStack.Pop(); tmpID = tmp.GetCompressedState(); int[] tmpData = dfsData[tmpID]; tmpData[0] = SCC_FOUND; // remove from goalStack if (goalStack.Count > 0 && tmp == goalStack.Peek()) { goalStack.Pop(); } } while (!tmpID.Equals(v)); // pop callStack callStack.Pop(); } else { // pop callStack & update the parent LocalPair pop = callStack.Pop(); LocalPair top = callStack.Peek(); string popID = pop.GetCompressedState(); string topID = top.GetCompressedState(); int[] popData = dfsData[popID]; int[] topData = dfsData[topID]; topData[1] = Math.Min(topData[1], popData[1]); } } } // end while loop VerificationOutput.VerificationResult = VerificationResultType.VALID; VerificationOutput.NoOfStates = dfsData.Count; return; }
// local function of each thread public void TarjanFairnessChecking() { // local data for on-the-fly and Tarjan algorithm Dictionary <string, List <string> > outgoingTransitionTable = new Dictionary <string, List <string> >(Ultility.Ultility.MC_INITIAL_SIZE); Stack <LocalPair> callStack = new Stack <LocalPair>(5000); Stack <LocalPair> currentStack = new Stack <LocalPair>(1024); Dictionary <string, int[]> dfsData = new Dictionary <string, int[]>(5000); Dictionary <string, List <LocalPair> > expendedNodes = new Dictionary <string, List <LocalPair> >(1024); int counter = 0; //-------------------------- // create initial states List <LocalPair> initialStates = LocalPair.GetInitialPairsLocal(BA, InitialStep); if (initialStates.Count == 0 || !BA.HasAcceptState) { VerificationOutput.VerificationResult = VerificationResultType.VALID; return; } // put all initial states to callStack & init data foreach (LocalPair tmp in initialStates) { callStack.Push(tmp); string tmpID = tmp.GetCompressedState(); dfsData.Add(tmpID, new int[] { VISITED_NOPREORDER, 0 }); outgoingTransitionTable.Add(tmpID, new List <string>(8)); } // start loop while (callStack.Count > 0) { // cancel if too long action or any counterexample is reported if (CancelRequested) { VerificationOutput.NoOfStates = dfsData.Count; return; } // get the top of callStack LocalPair pair = callStack.Peek(); ConfigurationBase LTSState = pair.configuration; string BAState = pair.state; string v = pair.GetCompressedState(); // get local data of the top List <string> outgoing = outgoingTransitionTable[v]; int[] vData = dfsData[v]; // if not expended then expend to next states from v if (!expendedNodes.ContainsKey(v)) { // create next states of v IEnumerable <ConfigurationBase> nextLTSStates = LTSState.MakeOneMove(); pair.SetEnabled(nextLTSStates, FairnessType); List <LocalPair> nextStates = LocalPair.NextLocal(BA, nextLTSStates, BAState); expendedNodes.Add(v, nextStates); // add to visitedTimes in this thread //visitedTimes.GetOrAdd(v, 0); //visitedTimes[v]++; // update outgoing of v and set initial data for successors // no need to use inverse for statement and use nextStates foreach (LocalPair next in nextStates) { string w = next.GetCompressedState(); outgoing.Add(w); if (!dfsData.ContainsKey(w)) { dfsData.Add(w, new int[] { VISITED_NOPREORDER, 0 }); outgoingTransitionTable.Add(w, new List <string>(8)); } } } // get successors of v List <LocalPair> successors = expendedNodes[v]; // process if v is not numbered yet if (vData[0] == VISITED_NOPREORDER) { vData[0] = counter; vData[1] = counter; counter = counter + 1; // push to currentStack currentStack.Push(pair); // update lowlink according to successors in currentStack // remove already visited successors // no need to use random for (int i = successors.Count - 1; i >= 0; i--) { LocalPair succ = successors[i]; string w = succ.GetCompressedState(); int[] wData = dfsData[w]; if (wData[0] >= 0) { // update & remove from expendedNodes(v) vData[1] = Math.Min(vData[1], wData[0]); successors.RemoveAt(i); } } } // check if there is any successor not numbered bool completed = true; for (int i = successors.Count - 1; i >= 0; i--) { LocalPair succ = successors[i]; string w = succ.GetCompressedState(); int[] wData = dfsData[w]; if (wData[0] == VISITED_NOPREORDER) { callStack.Push(succ); successors.RemoveAt(i); completed = false; break; } else { successors.RemoveAt(i); } } // if all successors are visited if (completed) { // check root if (vData[0] == vData[1]) { //pop callStack callStack.Pop(); Dictionary <string, LocalPair> newSCC = new Dictionary <string, LocalPair>(1024); // check selfLoop bool selfLoop = false; foreach (string w in outgoing) { if (v.Equals(w)) { selfLoop = true; break; } } // get all states in a SCC & check Buchi fair bool isBuchiFair = false; LocalPair tmp = null; string tmpID = null; // get from current until v do { tmp = currentStack.Pop(); isBuchiFair = isBuchiFair || tmp.state.EndsWith(Constants.ACCEPT_STATE); tmpID = tmp.GetCompressedState(); int[] tmpData = dfsData[tmpID]; tmpData[0] = SCC_FOUND; newSCC.Add(tmpID, tmp); } while (!tmpID.Equals(v)); if (isBuchiFair && (selfLoop || newSCC.Count > 1 || LTSState.IsDeadLock)) { Dictionary <string, LocalPair> fairSCC = IsFair(newSCC, outgoingTransitionTable); if (fairSCC != null) { // get the path to accepting cycle VerificationOutput.VerificationResult = VerificationResultType.INVALID; VerificationOutput.NoOfStates = dfsData.Count; LocalTaskStack = callStack; LocalGetCounterExample(fairSCC, outgoingTransitionTable); return; } } } else { //pop callStack & update the parent LocalPair pop = callStack.Pop(); LocalPair top = callStack.Peek(); string popID = pop.GetCompressedState(); string topID = top.GetCompressedState(); int[] popData = dfsData[popID]; int[] topData = dfsData[topID]; topData[1] = Math.Min(topData[1], popData[1]); } } } VerificationOutput.VerificationResult = VerificationResultType.VALID; VerificationOutput.NoOfStates = dfsData.Count; }
// Blue DFS public void localBlueDFSCombinationNestedDFS(object o) { // get order int order = (int)o; // local data of each thread for on-the-fly Nested DFS algorithm Dictionary <string, List <string> > outgoingTransitionTable = new Dictionary <string, List <string> >(Ultility.Ultility.MC_INITIAL_SIZE); Stack <LocalPair> blueStack = new Stack <LocalPair>(5000); Dictionary <string, bool> cyanData = new Dictionary <string, bool>(5000); Dictionary <string, List <LocalPair> > expendedNodes = new Dictionary <string, List <LocalPair> >(1024); // create initial states List <LocalPair> initialStates = LocalPair.GetInitialPairsLocal(BA, InitialStep); if (initialStates.Count == 0 || !BA.HasAcceptState) { return; } // create random variable for each process Random rand = new Random(order); // push initial states to blueStack in random order & init data int[] permutation = generatePermutation(initialStates.Count, rand); for (int i = 0; i < initialStates.Count; i++) { LocalPair tmp = initialStates[permutation[i]]; blueStack.Push(tmp); string ID = tmp.GetCompressedState(); cyanData.Add(ID, false); outgoingTransitionTable.Add(ID, new List <string>(8)); } // start loop while (blueStack.Count > 0) { // cancel if too long action or couterexample reported if (CancelRequested || isStop) { return; } // get the top of blueStack LocalPair pair = blueStack.Peek(); ConfigurationBase LTSState = pair.configuration; string BAState = pair.state; string v = pair.GetCompressedState(); // get local data of the top List <string> outgoing = outgoingTransitionTable[v]; bool isVCyan = cyanData[v]; // if v is not expended then expend successors of v if (!expendedNodes.ContainsKey(v)) { // create next states from v & add to expendedNodes IEnumerable <ConfigurationBase> nextLTSStates = LTSState.MakeOneMove(); pair.SetEnabled(nextLTSStates, FairnessType); List <LocalPair> nextStates = LocalPair.NextLocal(BA, nextLTSStates, BAState); expendedNodes.Add(v, nextStates); // add to visitedTimes in this thread //visitedTimes.GetOrAdd(v, 0); //visitedTimes[v]++; // update outgoing of v and set cyan color false // no need to use inverse for statement and use nextStates foreach (LocalPair next in nextStates) { string w = next.GetCompressedState(); outgoing.Add(w); if (!cyanData.ContainsKey(w)) { cyanData.Add(w, false); outgoingTransitionTable.Add(w, new List <string>(8)); } } } // get successor of v List <LocalPair> successors = expendedNodes[v]; // if v is not cyan if (!isVCyan) { cyanData[v] = true; for (int i = successors.Count - 1; i >= 0; i--) { LocalPair succ = successors[i]; string w = succ.GetCompressedState(); bool isWCyan = cyanData[w]; if (isWCyan) { if (succ.state.EndsWith(Constants.ACCEPT_STATE) || pair.state.EndsWith(Constants.ACCEPT_STATE)) { localBlueReportAcceptinCycle(succ, blueStack, outgoingTransitionTable); return; } else { successors.RemoveAt(i); } } } } // traverse all sucessors in a random order to find unvisited state bool blueDone = true; for (int i = successors.Count - 1; i >= 0; i--) { int randIndex = rand.Next(successors.Count); LocalPair succ = successors[randIndex]; string w = succ.GetCompressedState(); bool isWCyan = cyanData[w]; // if w is not cyan & not global blue // if w is in sharedBlueRedStates then w is global Blue // if sharedBlueRedStates[w] is true then w is also global Red if (!isWCyan && !sharedBlueRedStates.ContainsKey(w)) { blueStack.Push(succ); successors.RemoveAt(randIndex); blueDone = false; break; } else // remove already visited states in expendedNodes { successors.RemoveAt(randIndex); } } // if all successors are visited by blue DFS if (blueDone) { // mark v as global blue & false to indicate not globally red yet sharedBlueRedStates.GetOrAdd(v, false); // check loop at an accepting & deadlock state if (pair.state.EndsWith(Constants.ACCEPT_STATE) && LTSState.IsDeadLock) { lock (reportLocker) { isStop = true; Dictionary <string, LocalPair> acceptingCycle = new Dictionary <string, LocalPair>(); acceptingCycle.Add(v, pair); blueStack.Pop(); finalLocalTaskStack = blueStack; finalAcceptingCycle = acceptingCycle; finalOutgoingTransitionTable = outgoingTransitionTable; return; } } // check whether all successors of v are already red // also right for deadlock state bool isAllRed = true; foreach (string w in outgoing) { // not in shareBlueRedStates or in but not yet red if (!sharedBlueRedStates.ContainsKey(w) || !sharedBlueRedStates[w]) { isAllRed = false; break; } } // if all sucessors are red then v also red if (isAllRed) { sharedBlueRedStates[v] = true; } // if v is accepting state else if (pair.state.EndsWith(Constants.ACCEPT_STATE)) { Dictionary <LocalPair, bool> rSet = new Dictionary <LocalPair, bool>(1024); // initialize red DFS at v bool stop = localRedDFSCombinationNestedDFS(rSet, pair, blueStack, cyanData, outgoingTransitionTable, rand); if (stop) { return; } // wait for all accepting states EXCEPT v in rSet become red foreach (KeyValuePair <LocalPair, bool> kv in rSet) { string s = kv.Key.GetCompressedState(); if (kv.Key.state.EndsWith(Constants.ACCEPT_STATE) && !s.Equals(v)) { while (!sharedBlueRedStates[s]) { } ; } } // set all states in rSet to red // states already blue and in shareBlueRedStates blue foreach (KeyValuePair <LocalPair, bool> kv in rSet) { string kvID = kv.Key.GetCompressedState(); sharedBlueRedStates[kvID] = true; } } //pop v out of blueStack blueStack.Pop(); // uncyan v cyanData[v] = false; } } VerificationOutput.VerificationResult = VerificationResultType.VALID; return; }
// Red DFS public bool localRedDFSCombinationNestedDFS(Dictionary <LocalPair, bool> rSet, LocalPair acceptingState, Stack <LocalPair> blueStack, Dictionary <string, bool> cyanData, Dictionary <string, List <string> > outgoingTransitionTable, Random rand) { // local data for red DFS Stack <LocalPair> redStack = new Stack <LocalPair>(5000); Dictionary <string, bool> inRSet = new Dictionary <string, bool>(1024); Dictionary <string, List <LocalPair> > expendedNodes = new Dictionary <string, List <LocalPair> >(256); // push accepting state to redStack redStack.Push(acceptingState); // start loop while (redStack.Count > 0) { // too long action or counterexample reported if (CancelRequested || isStop) { return(false); } // get the top of redStack LocalPair pair = redStack.Peek(); ConfigurationBase LTSState = pair.configuration; string BAState = pair.state; string v = pair.GetCompressedState(); bool isVInRSet = inRSet.ContainsKey(v); // if v is not expended in red DFS if (!expendedNodes.ContainsKey(v)) { // get successors & add to expendedNodes IEnumerable <ConfigurationBase> nextLTSStates = LTSState.MakeOneMove(); pair.SetEnabled(nextLTSStates, FairnessType); List <LocalPair> nextStates = LocalPair.NextLocal(BA, nextLTSStates, BAState); expendedNodes.Add(v, nextStates); } // get successor of v List <LocalPair> successors = expendedNodes[v]; // if v is not pink then add to rSet if (!isVInRSet) { // add v to R rSet.Add(pair, true); inRSet.Add(v, true); // check for accepting cycle for (int i = successors.Count - 1; i >= 0; i--) { LocalPair succ = successors[i]; string w = succ.GetCompressedState(); //bool isWCyan = cyanData[w]; // if w is cyan then report accepting cycle // push to redStack states not in R set & not red, so may push states not in the thread's cyanData if (cyanData.ContainsKey(w) && cyanData[w]) { // report accepting cycle localRedReportAcceptinCycle(succ, blueStack, redStack, outgoingTransitionTable); return(true); } else if (inRSet.ContainsKey(w)) { successors.RemoveAt(i); } } } // traverse all successors in a random order to find successor not in R & not global red bool redDone = true; for (int i = successors.Count - 1; i >= 0; i--) { int randIndex = rand.Next(successors.Count); LocalPair succ = successors[randIndex]; string w = succ.GetCompressedState(); // if w is not in rSet & not global red then add w to redStack if (!inRSet.ContainsKey(w) && !sharedBlueRedStates[w]) { redStack.Push(succ); successors.RemoveAt(randIndex); redDone = false; break; } else { successors.RemoveAt(randIndex); } } // backtrack if (redDone) { //pop red stack redStack.Pop(); } } // return not found counterexample return(false); }
// Red DFS public bool localRedDFSNestedDFSSharedRed(LocalPair acceptingState, Stack <LocalPair> blueStack, Dictionary <string, Color> colorData, Dictionary <string, List <string> > outgoingTransitionTable, Random rand) { // local data for red DFS Stack <LocalPair> redStack = new Stack <LocalPair>(5000); Dictionary <string, List <LocalPair> > expendedNodes = new Dictionary <string, List <LocalPair> >(256); // push accepting state to redStack redStack.Push(acceptingState); // start loop while (redStack.Count > 0) { // too long action or counterexample reported if (CancelRequested || isStop) { return(false); } // get the top of redStack LocalPair pair = redStack.Peek(); ConfigurationBase LTSState = pair.configuration; string BAState = pair.state; string v = pair.GetCompressedState(); // local data of v in red DFS Color vColor = colorData[v]; // expend v in red DFS if (!expendedNodes.ContainsKey(v)) { // get successors & add to expendedNodes IEnumerable <ConfigurationBase> nextLTSStates = LTSState.MakeOneMove(); pair.SetEnabled(nextLTSStates, FairnessType); List <LocalPair> nextStates = LocalPair.NextLocal(BA, nextLTSStates, BAState); expendedNodes.Add(v, nextStates); } // successors of v List <LocalPair> successors = expendedNodes[v]; if (!vColor.isPink()) { vColor.setPink(); // check accepting cycle for (int i = successors.Count - 1; i >= 0; i--) { LocalPair succ = successors[i]; string w = succ.GetCompressedState(); Color wColor = colorData[w]; if (wColor.isCyan()) { // report accepting cycle localRedReportAcceptinCycle(succ, blueStack, redStack, outgoingTransitionTable); return(true); } // remove states visited in red DFS else if (wColor.isPink()) { successors.RemoveAt(i); } } } // traverse all successors in a random order bool redDone = true; for (int i = successors.Count - 1; i >= 0; i--) { int randIndex = rand.Next(successors.Count); LocalPair succ = successors[randIndex]; string w = succ.GetCompressedState(); Color wColor = colorData[w]; // if successor is cyan then report counterexample if (!wColor.isPink() && !sharedRedStates.ContainsKey(w)) { redStack.Push(succ); successors.RemoveAt(randIndex); redDone = false; break; } else { successors.RemoveAt(randIndex); } } // backtrack if (redDone) { // if accepting state then decrease count if (pair.state.EndsWith(Constants.ACCEPT_STATE)) { // decrease count sharedAcceptingCountRedDFS[v]--; // wait for count equal 0 while (sharedAcceptingCountRedDFS[v] != 0) { ; } } // mark v globally red sharedRedStates.GetOrAdd(v, true); // pop red stack redStack.Pop(); } } // return not found counterexample return(false); }
/// <summary> /// Run the verification and get the result. /// </summary> /// <returns></returns> public void ModelCheckingLivenessWithFairness() { Dictionary <string, List <string> > OutgoingTransitionTable = new Dictionary <string, List <string> >(Ultility.Ultility.MC_INITIAL_SIZE); LocalTaskStack = new Stack <LocalPair>(5000); VerificationOutput.CounterExampleTrace = null; List <LocalPair> initials = LocalPair.GetInitialPairsLocal(BA, InitialStep); StringDictionary <int[]> DFSData = new StringDictionary <int[]>(); if (initials.Count == 0) { VerificationOutput.VerificationResult = VerificationResultType.VALID; return; } for (int z = 0; z < initials.Count; z++) { LocalPair initState = initials[z]; LocalTaskStack.Push(initState); string ID = initState.GetCompressedState(FairnessType); DFSData.Add(ID, new int[] { VISITED_NOPREORDER, 0 }); OutgoingTransitionTable.Add(ID, new List <string>(8)); } Dictionary <string, LocalPair> SCCPairs = new Dictionary <string, LocalPair>(1024); Stack <LocalPair> stepStack = new Stack <LocalPair>(1024); int i = 0; //store the expended event step of a node to avoid multiple invocation of the make one move. Dictionary <string, List <LocalPair> > ExpendedNode = new Dictionary <string, List <LocalPair> >(1024); do { if (CancelRequested) { VerificationOutput.NoOfStates = DFSData.Count; // VisitedWithID.Count; return; } LocalPair pair = LocalTaskStack.Peek(); ConfigurationBase evt = pair.configuration; string BAState = pair.state; string v = pair.GetCompressedState(FairnessType); List <string> outgoing = OutgoingTransitionTable[v]; int[] nodeData = DFSData.GetContainsKey(v); if (nodeData[0] == VISITED_NOPREORDER) { nodeData[0] = i; i++; } bool done = true; if (ExpendedNode.ContainsKey(v)) { List <LocalPair> list = ExpendedNode[v]; if (list.Count > 0) { //transverse all steps for (int k = list.Count - 1; k >= 0; k--) { LocalPair step = list[k]; //if the step is a unvisited step string tmp = step.GetCompressedState(FairnessType); if (DFSData.GetContainsKey(tmp)[0] == VISITED_NOPREORDER) //if (!preorder.ContainsKey(step.GetCompressedState())) { //only add the first unvisited step //for the second or more unvisited steps, ignore at the monent if (done) { LocalTaskStack.Push(step); done = false; list.RemoveAt(k); } } else { list.RemoveAt(k); } } } } else { //ConfigurationBase[] list = evt.MakeOneMove().ToArray(); IEnumerable <ConfigurationBase> list = evt.MakeOneMove(); pair.SetEnabled(list, FairnessType); List <LocalPair> product = LocalPair.NextLocal(BA, list, BAState); //count the transitions visited VerificationOutput.Transitions += product.Count; for (int k = product.Count - 1; k >= 0; k--) { LocalPair step = product[k]; string tmp = step.GetCompressedState(FairnessType); //if (VisitedWithID.ContainsKey(tmp)) int[] data = DFSData.GetContainsKey(tmp); if (data != null) { //update the incoming and outgoing edges //int t = VisitedWithID.GetContainsKey(tmp); //DataStore.DataManager.GetID(tmp); outgoing.Add(tmp); //if this node is still not visited if (data[0] == VISITED_NOPREORDER) { //step.ID = t; //only put the first one to the work list stack. //if there are more than one node to be visited, //simply ignore them and keep its event step in the list. if (done) { LocalTaskStack.Push(step); done = false; product.RemoveAt(k); } else { product[k] = step; } } //this node is truly visited. can be removed else { product.RemoveAt(k); } } else { //int stateID = VisitedWithID.Count; //VisitedWithID.Add(tmp,false); DFSData.Add(tmp, new int[] { VISITED_NOPREORDER, 0 }); OutgoingTransitionTable.Add(tmp, new List <string>(8)); //step.ID = stateID; outgoing.Add(tmp); //only put the first one into the stack. if (done) { LocalTaskStack.Push(step); done = false; product.RemoveAt(k); } else { product[k] = step; } } } //create the remaining steps as the expending list for v ExpendedNode.Add(v, product); } if (done) { int lowlinkV = nodeData[0]; // preorder[v]; int preorderV = lowlinkV; bool selfLoop = false; for (int j = 0; j < outgoing.Count; j++) { string w = outgoing[j]; if (w == v) { selfLoop = true; } int[] wdata = DFSData.GetContainsKey(w); if (wdata[0] != SCC_FOUND) { if (wdata[0] > preorderV) { lowlinkV = Math.Min(lowlinkV, wdata[1]); } else { lowlinkV = Math.Min(lowlinkV, wdata[0]); } } } nodeData[1] = lowlinkV; LocalTaskStack.Pop(); if (lowlinkV == preorderV) { SCCPairs.Add(v, pair); nodeData[0] = SCC_FOUND; //checking for buchi-fair bool BuchiFair = pair.state.EndsWith(Constants.ACCEPT_STATE); //while (stepStack.Count > 0 && preorder[stepStack.Peek().GetCompressedState()] > preorderV) while (stepStack.Count > 0 && DFSData.GetContainsKey(stepStack.Peek().GetCompressedState(FairnessType))[0] > preorderV) { LocalPair s = stepStack.Pop(); string k = s.GetCompressedState(FairnessType); DFSData.GetContainsKey(k)[0] = SCC_FOUND; SCCPairs.Add(k, s); if (!BuchiFair && s.state.EndsWith(Constants.ACCEPT_STATE)) { BuchiFair = true; } } int SCCSize = SCCPairs.Count; if (BuchiFair && (evt.IsDeadLock || SCCSize > 1 || selfLoop)) { PrintMessage("A SCC of size " + SCCSize + " is found"); Dictionary <string, LocalPair> value = IsFair(SCCPairs, OutgoingTransitionTable); if (value != null) { PrintMessage("The SCC found is FAIR."); VerificationOutput.VerificationResult = VerificationResultType.INVALID; VerificationOutput.NoOfStates = DFSData.Count; // VisitedWithID.Count; LocalGetCounterExample(value, OutgoingTransitionTable); return; } PrintMessage("The SCC found is NOT fair."); } foreach (string componet in SCCPairs.Keys) { ExpendedNode.Remove(componet); OutgoingTransitionTable.Remove(componet); } //StronglyConnectedComponets.Clear(); SCCPairs.Clear(); } else { stepStack.Push(pair); } } } while (LocalTaskStack.Count > 0); VerificationOutput.VerificationResult = VerificationResultType.VALID; VerificationOutput.NoOfStates = DFSData.Count; // VisitedWithID.Count; }
// Blue DFS public void localBlueDFSNestedDFSSharedRed(object o) { // get order int order = (int)o; // local data for on-the-fly Nested DFS Dictionary <string, List <string> > outgoingTransitionTable = new Dictionary <string, List <string> >(Ultility.Ultility.MC_INITIAL_SIZE); Stack <LocalPair> blueStack = new Stack <LocalPair>(5000); Dictionary <string, Color> colorData = new Dictionary <string, Color>(5000); Dictionary <string, List <LocalPair> > expendedNodes = new Dictionary <string, List <LocalPair> >(1024); // create initial states List <LocalPair> initialStates = LocalPair.GetInitialPairsLocal(BA, InitialStep); if (initialStates.Count == 0 || !BA.HasAcceptState) { return; } // create random variable for each thread Random rand = new Random(order); // push initial states to blueStack in random order & initialize data int[] permutation = generatePermutation(initialStates.Count, rand); for (int i = 0; i < initialStates.Count; i++) { LocalPair tmp = initialStates[permutation[i]]; blueStack.Push(tmp); string ID = tmp.GetCompressedState(); colorData.Add(ID, new Color()); outgoingTransitionTable.Add(ID, new List <string>(8)); } // start loop while (blueStack.Count > 0) { // cancel if too long action or couterexample reported if (CancelRequested || isStop) { return; } // get the top of blueStack LocalPair pair = blueStack.Peek(); ConfigurationBase LTSState = pair.configuration; string BAState = pair.state; string v = pair.GetCompressedState(); // local data of the top List <string> outgoing = outgoingTransitionTable[v]; Color vColor = colorData[v]; // if v is not expended then expend successors of v if (!expendedNodes.ContainsKey(v)) { // create next states from v & add to expendedNodes IEnumerable <ConfigurationBase> nextLTSStates = LTSState.MakeOneMove(); pair.SetEnabled(nextLTSStates, FairnessType); List <LocalPair> nextStates = LocalPair.NextLocal(BA, nextLTSStates, BAState); expendedNodes.Add(v, nextStates); // add to visitedTimes in this thread //visitedTimes.GetOrAdd(v, 0); //visitedTimes[v]++; // update outgoing of v and set initial data for successors // no need to use inverse for statement and use nextStates foreach (LocalPair next in nextStates) { string w = next.GetCompressedState(); outgoing.Add(w); if (!colorData.ContainsKey(w)) { colorData.Add(w, new Color()); outgoingTransitionTable.Add(w, new List <string>(8)); } } } // get successor of v List <LocalPair> successors = expendedNodes[v]; // visit v & early accepting cycle detection if (vColor.isWhite()) { vColor.setCyan(); // early cycle detection // use reverse order to remove visited states for (int i = successors.Count - 1; i >= 0; i--) { LocalPair succ = successors[i]; string w = succ.GetCompressedState(); Color wColor = colorData[w]; // if successor is not white then remove from expendedNodes if (wColor.isCyan()) { if (succ.state.EndsWith(Constants.ACCEPT_STATE) || pair.state.EndsWith(Constants.ACCEPT_STATE)) { localBlueReportAcceptinCycle(succ, blueStack, outgoingTransitionTable); return; } else { successors.RemoveAt(i); } } } } // traverse all sucessors in a random order bool blueDone = true; for (int i = successors.Count - 1; i >= 0; i--) { int randIndex = rand.Next(successors.Count); LocalPair succ = successors[randIndex]; string w = succ.GetCompressedState(); // only visite white & not red globally successors if (colorData[w].isWhite() && !sharedRedStates.ContainsKey(w)) { blueStack.Push(succ); successors.RemoveAt(randIndex); blueDone = false; break; } else // remove already visited states in expendedNodes { successors.RemoveAt(randIndex); } } // if all successors are visited by blue DFS if (blueDone) { // check loop at an accepting & deadlock state if (pair.state.EndsWith(Constants.ACCEPT_STATE) && LTSState.IsDeadLock) { lock (reportLocker) { isStop = true; Dictionary <string, LocalPair> acceptingCycle = new Dictionary <string, LocalPair>(); acceptingCycle.Add(v, pair); blueStack.Pop(); finalLocalTaskStack = blueStack; finalAcceptingCycle = acceptingCycle; finalOutgoingTransitionTable = outgoingTransitionTable; return; } } // check whether all successors of v are already red // also right for deadlock state bool isAllRed = true; foreach (string w in outgoing) { if (!sharedRedStates.ContainsKey(w)) { isAllRed = false; break; } } // if all sucessors are red then v also red if (isAllRed) { sharedRedStates.GetOrAdd(v, true); } // if v is accepting states else if (pair.state.EndsWith(Constants.ACCEPT_STATE)) { // increase count red of v by 1 sharedAcceptingCountRedDFS.GetOrAdd(v, 0); sharedAcceptingCountRedDFS[v]++; // initialize red DFS at v bool stop = localRedDFSNestedDFSSharedRed(pair, blueStack, colorData, outgoingTransitionTable, rand); if (stop) { return; } } // set v to blue colorData[v].setBlue(); //pop v out of blueStack blueStack.Pop(); } } VerificationOutput.VerificationResult = VerificationResultType.VALID; return; }
/// <summary> /// Improved Tarjan Algorithm /// A Note on On-The-Fly Verification Algorithms - TACAS 2005 /// </summary> public void ImprovedTarjan() { VerificationOutput.CounterExampleTrace = null; //on-the-fly data Stack <LocalPair> callStack = new Stack <LocalPair>(5000); Stack <LocalPair> currentStack = new Stack <LocalPair>(5000); Stack <LocalPair> goalStack = new Stack <LocalPair>(1024); Dictionary <string, int[]> dfsNumber = new Dictionary <string, int[]>(5000); Dictionary <string, List <LocalPair> > expendedNodes = new Dictionary <string, List <LocalPair> >(5000); int counter = 0; //initial states List <LocalPair> initialStates = LocalPair.GetInitialPairsLocal(BA, InitialStep); //check valid result if (initialStates.Count == 0 || !BA.HasAcceptState) { VerificationOutput.VerificationResult = VerificationResultType.VALID; return; } //push initial states to call stack foreach (LocalPair tmp in initialStates) { callStack.Push(tmp); } //start loop while (callStack.Count > 0) { //cancel if take long time if (CancelRequested) { VerificationOutput.NoOfStates = dfsNumber.Count; return; } //get top of call stack LocalPair pair = callStack.Peek(); ConfigurationBase LTSState = pair.configuration; string BAState = pair.state; string v = pair.GetCompressedState(); //get successors List <LocalPair> successors = null; if (expendedNodes.ContainsKey(v)) { successors = expendedNodes[v]; } else { IEnumerable <ConfigurationBase> nextLTSStates = LTSState.MakeOneMove(); pair.SetEnabled(nextLTSStates, FairnessType); successors = LocalPair.NextLocal(BA, nextLTSStates, BAState); expendedNodes.Add(v, successors); } //if v is not number yet if (!dfsNumber.ContainsKey(v)) { //number v int[] vData = new int[] { counter, counter }; dfsNumber.Add(v, vData); counter = counter + 1; //push to currentStack currentStack.Push(pair); //check whether v is accepting if (pair.state.EndsWith(Constants.ACCEPT_STATE)) { goalStack.Push(pair); } //update lowlink for already numbered successors for (int i = successors.Count - 1; i >= 0; i--) { LocalPair succ = successors[i]; string w = succ.GetCompressedState(); //if w is already numbered if (dfsNumber.ContainsKey(w)) { int[] wData = dfsNumber[w]; //if w is in current stack if (wData[0] >= 0) { vData[1] = Math.Min(vData[1], wData[0]); //check for report accepting cycle if (goalStack.Count > 0 && vData[1] <= dfsNumber[goalStack.Peek().GetCompressedState()][0]) { //REPORT COUNTEREXAMPLE GetLoopCounterExample(w, callStack, dfsNumber); return; } } } } } //check if there is an unnumbered successor bool isCompleted = true; for (int i = successors.Count - 1; i >= 0; i--) { LocalPair succ = successors[i]; string w = succ.GetCompressedState(); //if w is not already numbered if (!dfsNumber.ContainsKey(w)) { callStack.Push(succ); isCompleted = false; break; } } //if there is no unnumbered successor if (isCompleted) { //deadlock at accepting state if (LTSState.IsDeadLock && pair.state.EndsWith(Constants.ACCEPT_STATE)) { //REPORT COUNTEREXAMPLE GetDeadlockCounterExample(callStack, dfsNumber); return; } int[] vData = dfsNumber[v]; //if v is root if (vData[0] == vData[1]) { //remove states from current stack and goal stack LocalPair tmp = null; string tmpID = null; do { //current stack tmp = currentStack.Pop(); tmpID = tmp.GetCompressedState(); dfsNumber[tmpID][0] = SCC_FOUND; //goal stack if (goalStack.Count > 0 && tmp == goalStack.Peek()) { goalStack.Pop(); } } while (tmp != pair); //pop call stack callStack.Pop(); } else { //pop call stack and update lowlink of top LocalPair pop = callStack.Pop(); LocalPair top = callStack.Peek(); string popID = pop.GetCompressedState(); string topID = top.GetCompressedState(); int[] popData = dfsNumber[popID]; int[] topData = dfsNumber[topID]; topData[1] = Math.Min(topData[1], popData[1]); } } } //no counter example VerificationOutput.VerificationResult = VerificationResultType.VALID; VerificationOutput.NoOfStates = dfsNumber.Count; return; }
/// <summary> /// Improved Nested DFS /// A Note on On-The-Fly Verification Algorithms - TACAS 2005 /// Blue DFS /// </summary> public void BlueDFS() { VerificationOutput.CounterExampleTrace = null; //on-the-fly data Stack <LocalPair> blueStack = new Stack <LocalPair>(5000); Dictionary <string, Color> dfsColor = new Dictionary <string, Color>(5000); Dictionary <string, List <LocalPair> > expendedNodes = new Dictionary <string, List <LocalPair> >(5000); //initial states List <LocalPair> initialStates = LocalPair.GetInitialPairsLocal(BA, InitialStep); //check valid result if (initialStates.Count == 0 || !BA.HasAcceptState) { VerificationOutput.VerificationResult = VerificationResultType.VALID; return; } //push initial states to call stack foreach (LocalPair tmp in initialStates) { blueStack.Push(tmp); } //start loop while (blueStack.Count > 0) { //cancel if take long time if (CancelRequested) { VerificationOutput.NoOfStates = dfsColor.Count; return; } //get top of call stack LocalPair pair = blueStack.Peek(); ConfigurationBase LTSState = pair.configuration; string BAState = pair.state; string v = pair.GetCompressedState(); //get successors List <LocalPair> successors = null; if (expendedNodes.ContainsKey(v)) { successors = expendedNodes[v]; } else { IEnumerable <ConfigurationBase> nextLTSStates = LTSState.MakeOneMove(); pair.SetEnabled(nextLTSStates, FairnessType); successors = LocalPair.NextLocal(BA, nextLTSStates, BAState); expendedNodes.Add(v, successors); } //if v is white if (!dfsColor.ContainsKey(v)) { //set v cyan Color vColor = new Color(); vColor.setCyan(); dfsColor.Add(v, vColor); //early cycle detection for (int i = successors.Count - 1; i >= 0; i--) { LocalPair succ = successors[i]; string w = succ.GetCompressedState(); //if w is cyan and (v or w is accepting) if (dfsColor.ContainsKey(w)) { Color wColor = dfsColor[w]; if (wColor.isCyan() && (succ.state.EndsWith(Constants.ACCEPT_STATE) || pair.state.EndsWith(Constants.ACCEPT_STATE))) { //REPORT COUNTEREXAMPLE GetLoopCounterExample(w, blueStack, dfsColor); return; } } } } //check if there is an unnumbered successor bool isBlueCompleted = true; for (int i = successors.Count - 1; i >= 0; i--) { LocalPair succ = successors[i]; string w = succ.GetCompressedState(); //if w is white if (!dfsColor.ContainsKey(w)) { blueStack.Push(succ); isBlueCompleted = false; break; } } //if there is no unnumbered successor if (isBlueCompleted) { Color vColor = dfsColor[v]; //if v is accepting if (pair.state.EndsWith(Constants.ACCEPT_STATE)) { //if v is deadlock if (LTSState.IsDeadLock) { //REPORT COUNTEREXAMPLE GetDeadlockCounterExample(blueStack, dfsColor); return; } else { bool stop = RedDFS(pair, blueStack, dfsColor, expendedNodes); if (stop) { return; } } //set v pink vColor.setPink(); } else { vColor.setBlue(); } //pop blue stack blueStack.Pop(); } } //no counter example VerificationOutput.VerificationResult = VerificationResultType.VALID; VerificationOutput.NoOfStates = dfsColor.Count; return; }
/// <summary> /// Local red DFS in each thread /// </summary> /// <param name="rSet"></param> /// <param name="acceptingState"></param> /// <param name="localBlueStack"></param> /// <param name="localCyanData"></param> /// <param name="rand"></param> /// <returns></returns> public bool LocalRed2(Dictionary <LocalPair, bool> rSet, LocalPair acceptingState, Stack <LocalPair> localBlueStack, Dictionary <string, bool> localCyanData, Random rand, Dictionary <string, List <LocalPair> > localExpendedNodes) { Stack <LocalPair> localRedStack = new Stack <LocalPair>(5000); Dictionary <string, bool> inRSet = new Dictionary <string, bool>(1024); //push accepting state to red stack localRedStack.Push(acceptingState); //start loop while (localRedStack.Count > 0) { //cancel if take long time if (CancelRequested || isGlobalStop) { return(false); } //get top of red stack LocalPair pair = localRedStack.Peek(); ConfigurationBase LTSState = pair.configuration; string BAState = pair.state; string v = pair.GetCompressedState(); //get successors //v may not in expendedNodes List <LocalPair> successors = null; if (localExpendedNodes.ContainsKey(v)) { successors = localExpendedNodes[v]; } else { IEnumerable <ConfigurationBase> nextLTSStates = LTSState.MakeOneMove(); pair.SetEnabled(nextLTSStates, FairnessType); successors = LocalPair.NextLocal(BA, nextLTSStates, BAState); localExpendedNodes.Add(v, successors); } //if v not in R set if (!inRSet.ContainsKey(v)) { //add v to R rSet.Add(pair, true); inRSet.Add(v, true); //check if there is cyan successor for (int i = successors.Count - 1; i >= 0; i--) { LocalPair succ = successors[i]; string w = succ.GetCompressedState(); if (localCyanData.ContainsKey(w) && localCyanData[w]) { //REPORT COUNTER EXAMPLE GetLocalLoopCounterExample(w, localBlueStack, localRedStack); return(true); } } } //------------------------------------------------------------------------ //filter successors List <int> unvisitedIndexs = new List <int>(successors.Count);//not in and not global red for (int i = successors.Count - 1; i >= 0; i--) { LocalPair succ = successors[i]; string w = succ.GetCompressedState(); //if w is white and not global red if (!inRSet.ContainsKey(w) && !globalBlueRedStates[w]) { unvisitedIndexs.Add(i); } } //------------------------------------------------------------------------ //get random unvisited successors if (unvisitedIndexs.Count > 0) { int r = rand.Next(unvisitedIndexs.Count); LocalPair succ = successors[unvisitedIndexs[r]]; localRedStack.Push(succ); } else { localRedStack.Pop(); } } //cannot report counter example return(false); }
/// <summary> /// The local function of each process running Improved MultiCore Tarjan algorithm /// </summary> /// <returns></returns> public void localImprovedTarjanGeldenhuysValmari() { //local data for on-the-fly and Tarjan algorithm Dictionary <string, List <string> > outgoingTransitionTable = new Dictionary <string, List <string> >(Ultility.Ultility.MC_INITIAL_SIZE); StringDictionary <int[]> dfsData = new StringDictionary <int[]>(5000); Dictionary <string, List <LocalPair> > expendedNodes = new Dictionary <string, List <LocalPair> >(1024); Stack <LocalPair> callStack = new Stack <LocalPair>(5000); Stack <LocalPair> currentStack = new Stack <LocalPair>(1024); int counter = 0; string goal = null; int[] goalData = new int[2] { -2, 0 }; //-------------------------- //create initial states List <LocalPair> initialStates = LocalPair.GetInitialPairsLocal(BA, InitialStep); if (initialStates.Count == 0 || !BA.HasAcceptState) { VerificationOutput.VerificationResult = VerificationResultType.VALID; return; } //create random variable for each process Random rand = null; lock (MultiCoreLock) { rand = new Random(MultiCoreSeed); MultiCoreSeed++; } //put all initial states to callStack in different order & init data int[] initPermutation = generatePermutation(initialStates.Count, rand); for (int i = 0; i < initPermutation.Length; i++) { //get data from initialStates LocalPair tmp = initialStates[initPermutation[i]]; callStack.Push(tmp); string tmpID = tmp.GetCompressedState(); dfsData.Add(tmpID, new int[] { VISITED_NOPREORDER, 0 }); outgoingTransitionTable.Add(tmpID, new List <string>(8)); } //start loop while (callStack.Count > 0) { //cancel if too long action if (CancelRequested || StopMutliCoreThreads) { return; } //get the top of callStack LocalPair pair = callStack.Peek(); ConfigurationBase LTSState = pair.configuration; string BAState = pair.state; string v = pair.GetCompressedState(); //get local data of the top List <string> outgoing = outgoingTransitionTable[v]; int[] vData = dfsData.GetContainsKey(v); //if not expended then expend to next states from v if (!expendedNodes.ContainsKey(v)) { //create next states of v ConfigurationBase[] nextLTSStates = LTSState.MakeOneMove(); pair.SetEnabled(nextLTSStates, FairnessType); List <LocalPair> nextStates = LocalPair.NextLocal(BA, nextLTSStates, BAState); expendedNodes.Add(v, nextStates); //update outgoing of v and set initial data for successors //no need to use inverse for statement and use nextStates foreach (LocalPair next in nextStates) { string w = next.GetCompressedState(); outgoing.Add(w); if (!dfsData.ContainsKey(w)) { dfsData.Add(w, new int[] { VISITED_NOPREORDER, 0 }); outgoingTransitionTable.Add(w, new List <string>(8)); } } } //get successors of v List <LocalPair> successors = expendedNodes[v]; //process if v is not numbered yet if (vData[0] == VISITED_NOPREORDER) { vData[0] = counter; vData[1] = counter; counter = counter + 1; //push to currentStack currentStack.Push(pair); //check whether v is accepting if (pair.state.EndsWith(Constants.ACCEPT_STATE)) { goal = v; goalData = vData; } //update lowlink according to successors in currentStack //remove already visited successors //no need random because consider all successors for (int i = successors.Count - 1; i >= 0; i--) { LocalPair succ = successors[i]; string w = succ.GetCompressedState(); int[] wData = dfsData.GetContainsKey(w); if (wData[0] >= 0 && !foundSCCTarjanGeldenhuysValmari.ContainsKey(w)) { //update & remove from expendedNodes(v) vData[1] = Math.Min(vData[1], wData[0]); successors.RemoveAt(i); //check for report accepting cycle if (vData[1] <= goalData[0]) { //REPORT COUNTEREXAMPLE localReportAcceptingCycle(succ, callStack, dfsData, outgoingTransitionTable); return; } } } } //check if there is any successor not numbered & not visited by other threads //choose random bool completed = true; LocalPair firstUnnumbered = null; for (int i = successors.Count - 1; i >= 0; i--) { int randIndex = rand.Next(successors.Count); LocalPair succ = successors[randIndex]; string w = succ.GetCompressedState(); int[] wData = dfsData.GetContainsKey(w); //only check states not in foundSCCTarjanGeldenhuysValmari if (wData[0] == VISITED_NOPREORDER && !foundSCCTarjanGeldenhuysValmari.ContainsKey(w)) { completed = false; firstUnnumbered = succ; successors.RemoveAt(randIndex); break; } else { successors.RemoveAt(randIndex); } } // if there at least one unnumbered successor if (!completed) { callStack.Push(firstUnnumbered); } else //all successors are numbered { //check for loop at an accepting & deadlock state if (LTSState.IsDeadLock && pair.state.EndsWith(Constants.ACCEPT_STATE)) { //report AcceptingCycle localReportAcceptingCycle(pair, callStack, dfsData, outgoingTransitionTable); return; } if (vData[0] == vData[1]) { //find the root -> mark as local and global for all processes LocalPair tmp = null; string tmpID = null; //pop currentStack and update SCC_FOUND and add to global memory until v do { //local tmp = currentStack.Pop(); tmpID = tmp.GetCompressedState(); int[] tmpData = dfsData.GetContainsKey(tmpID); tmpData[0] = SCC_FOUND; //global foundSCCTarjanGeldenhuysValmari.GetOrAdd(tmpID, true); } while (!tmpID.Equals(v)); //pop callStack callStack.Pop(); } else { //pop callStack & update the parent LocalPair pop = callStack.Pop(); LocalPair top = callStack.Peek(); string popID = pop.GetCompressedState(); string topID = top.GetCompressedState(); int[] popData = dfsData.GetContainsKey(popID); int[] topData = dfsData.GetContainsKey(topID); topData[1] = Math.Min(topData[1], popData[1]); } } } }
/// <summary> /// Local blue DFS in each thread /// </summary> /// <param name="o"></param> public void LocalBlue2(object o) { //order of this thread int order = (int)o; Random rand = new Random(order); //on-the-fly data Stack <LocalPair> localBlueStack = new Stack <LocalPair>(5000); Dictionary <string, bool> localCyanData = new Dictionary <string, bool>(5000); Dictionary <string, List <LocalPair> > localExpendedNodes = new Dictionary <string, List <LocalPair> >(5000); //initial states List <LocalPair> initialStates = LocalPair.GetInitialPairsLocal(BA, InitialStep); //check valid result if (initialStates.Count == 0 || !BA.HasAcceptState) { return; } //push local initial states to local blue stack int[] localPerm = Permutation(initialStates.Count, rand); for (int i = 0; i < initialStates.Count; i++) { LocalPair tmp = initialStates[localPerm[i]]; localBlueStack.Push(tmp); } //start loop while (localBlueStack.Count > 0) { //cancel if take long time if (CancelRequested || isGlobalStop) { return; } //get top of blue stack LocalPair pair = localBlueStack.Peek(); ConfigurationBase LTSState = pair.configuration; string BAState = pair.state; string v = pair.GetCompressedState(); //get successors List <LocalPair> successors = null; if (localExpendedNodes.ContainsKey(v)) { successors = localExpendedNodes[v]; } else { IEnumerable <ConfigurationBase> nextLTSStates = LTSState.MakeOneMove(); pair.SetEnabled(nextLTSStates, FairnessType); successors = LocalPair.NextLocal(BA, nextLTSStates, BAState); localExpendedNodes.Add(v, successors); } //if v is not cyan if (!localCyanData.ContainsKey(v)) { //set v cyan localCyanData.Add(v, true); //early cycle detection for (int i = successors.Count - 1; i >= 0; i--) { LocalPair succ = successors[i]; string w = succ.GetCompressedState(); //if w is cyan and (v or w is accepting) if (localCyanData.ContainsKey(w)) { bool isWcyan = localCyanData[w]; if (isWcyan && (succ.state.EndsWith(Constants.ACCEPT_STATE) || pair.state.EndsWith(Constants.ACCEPT_STATE))) { //REPORT COUNTEREXAMPLE GetLocalLoopCounterExample(w, localBlueStack); return; } } } } //------------------------------------------------------------------------ //filter successors and check if all successors are red bool isAllRed = true; List <int> unvisitedIndexs = new List <int>(successors.Count);//not visited and not global red for (int i = successors.Count - 1; i >= 0; i--) { LocalPair succ = successors[i]; string w = succ.GetCompressedState(); //if w is not cyan and not global blue if (!localCyanData.ContainsKey(w) && !globalBlueRedStates.ContainsKey(w)) { unvisitedIndexs.Add(i); } //set all red variable to false if w not global red if (isAllRed) { if (!globalBlueRedStates.ContainsKey(w) || !globalBlueRedStates[w]) { isAllRed = false; } } } //------------------------------------------------------------------------ //get random unvisited successors if (unvisitedIndexs.Count > 0) { bool isFresh = false; List <int> unFreshIndexs = new List <int>(); while (unvisitedIndexs.Count > 0) { int r = rand.Next(unvisitedIndexs.Count); LocalPair succ = successors[unvisitedIndexs[r]]; string w = succ.GetCompressedState(); //if w is fresh successor if (!allVisitedStates.ContainsKey(w)) { localBlueStack.Push(succ); allVisitedStates.GetOrAdd(w, 0); allVisitedStates[w]++; isFresh = true; break; } else { unFreshIndexs.Add(unvisitedIndexs[r]); unvisitedIndexs.RemoveAt(r); } } if (!isFresh) { int r = rand.Next(unFreshIndexs.Count); LocalPair succ = successors[unFreshIndexs[r]]; string w = succ.GetCompressedState(); localBlueStack.Push(succ); allVisitedStates.GetOrAdd(w, 0); allVisitedStates[w]++; } } else { //mark v global blue globalBlueRedStates.GetOrAdd(v, false); //deadlock at accepting state if (pair.state.EndsWith(Constants.ACCEPT_STATE) && LTSState.IsDeadLock) { //REPORT COUNTEREXAMPLE GetLocalDeadlockCounterExample(localBlueStack); return; } //if all successors are global red if (isAllRed) { globalBlueRedStates[v] = true; } else if (pair.state.EndsWith(Constants.ACCEPT_STATE)) { Dictionary <LocalPair, bool> rSet = new Dictionary <LocalPair, bool>(1024); //start local red DFS bool isStop = LocalRed2(rSet, pair, localBlueStack, localCyanData, rand, localExpendedNodes); if (isStop) { return; } //wait for all accepting states EXCEPT v in rSet become red foreach (KeyValuePair <LocalPair, bool> kv in rSet) { string s = kv.Key.GetCompressedState(); if (kv.Key.state.EndsWith(Constants.ACCEPT_STATE) && !s.Equals(v)) { while (!globalBlueRedStates[s]) { ; } } } //set all states in rSet to red foreach (KeyValuePair <LocalPair, bool> kv in rSet) { string kvID = kv.Key.GetCompressedState(); globalBlueRedStates[kvID] = true; } } //pop blue stack localBlueStack.Pop(); //uncyan v localCyanData[v] = false; } } }
/// <summary> /// Local blue DFS in each thread /// </summary> /// <param name="o"></param> public void LocalBlueSwarm(object o) { //order of this thread int order = (int)o; Random rand = new Random(order); //on-the-fly data Stack <LocalPair> localBlueStack = new Stack <LocalPair>(5000); Dictionary <string, Color> localDFSColor = new Dictionary <string, Color>(5000); Dictionary <string, List <LocalPair> > localExpendedNodes = new Dictionary <string, List <LocalPair> >(5000); //initial states List <LocalPair> initialStates = LocalPair.GetInitialPairsLocal(BA, InitialStep); //check valid result if (initialStates.Count == 0 || !BA.HasAcceptState) { return; } //push local initial states to local blue stack int[] localPerm = Permutation(initialStates.Count, rand); for (int i = 0; i < initialStates.Count; i++) { LocalPair tmp = initialStates[localPerm[i]]; localBlueStack.Push(tmp); } //start loop while (localBlueStack.Count > 0) { //cancel if take long time if (CancelRequested || isGlobalStop) { return; } //get top of blue stack LocalPair pair = localBlueStack.Peek(); ConfigurationBase LTSState = pair.configuration; string BAState = pair.state; string v = pair.GetCompressedState(); //get successors List <LocalPair> successors = null; if (localExpendedNodes.ContainsKey(v)) { successors = localExpendedNodes[v]; } else { IEnumerable <ConfigurationBase> nextLTSStates = LTSState.MakeOneMove(); pair.SetEnabled(nextLTSStates, FairnessType); successors = LocalPair.NextLocal(BA, nextLTSStates, BAState); localExpendedNodes.Add(v, successors); } //if v is white if (!localDFSColor.ContainsKey(v)) { //set v cyan Color vColor = new Color(); vColor.setCyan(); localDFSColor.Add(v, vColor); //early cycle detection for (int i = successors.Count - 1; i >= 0; i--) { LocalPair succ = successors[i]; string w = succ.GetCompressedState(); //if w is cyan and (v or w is accepting) if (localDFSColor.ContainsKey(w)) { Color wColor = localDFSColor[w]; if (wColor.isCyan() && (succ.state.EndsWith(Constants.ACCEPT_STATE) || pair.state.EndsWith(Constants.ACCEPT_STATE))) { //REPORT COUNTEREXAMPLE GetLocalLoopCounterExample(w, localBlueStack); return; } } } } //------------------------------------------------------------------------ //filter successors List <int> unvisitedIndexs = new List <int>(successors.Count); for (int i = successors.Count - 1; i >= 0; i--) { LocalPair succ = successors[i]; string w = succ.GetCompressedState(); //if w is white and not global red if (!localDFSColor.ContainsKey(w)) { unvisitedIndexs.Add(i); } } //------------------------------------------------------------------------ //get random unvisited successors if (unvisitedIndexs.Count > 0) { bool isFresh = false; List <int> unFreshIndexs = new List <int>(); while (unvisitedIndexs.Count > 0) { int r = rand.Next(unvisitedIndexs.Count); LocalPair succ = successors[unvisitedIndexs[r]]; string w = succ.GetCompressedState(); //if w is fresh successor if (!allVisitedStates.ContainsKey(w)) { localBlueStack.Push(succ); allVisitedStates.GetOrAdd(w, 0); allVisitedStates[w]++; isFresh = true; break; } else { unFreshIndexs.Add(unvisitedIndexs[r]); unvisitedIndexs.RemoveAt(r); } } if (!isFresh) { int r = rand.Next(unFreshIndexs.Count); LocalPair succ = successors[unFreshIndexs[r]]; string w = succ.GetCompressedState(); localBlueStack.Push(succ); allVisitedStates.GetOrAdd(w, 0); allVisitedStates[w]++; } } else { Color vColor = localDFSColor[v]; //if v is accepting if (pair.state.EndsWith(Constants.ACCEPT_STATE)) { //if v is deadlock if (LTSState.IsDeadLock) { //REPORT COUNTEREXAMPLE GetLocalDeadlockCounterExample(localBlueStack); return; } else { bool isStop = LocalRedSwarm(pair, localBlueStack, localDFSColor, rand, localExpendedNodes); if (isStop) { return; } } //set v pink vColor.setPink(); } else { vColor.setBlue(); } //pop v out of blueStack localBlueStack.Pop(); } } }
// RED DFS private bool redDFSImprovedNestedDFS(LocalPair acceptingState, Stack <LocalPair> blueStack, Dictionary <string, Color> colorData, Dictionary <string, List <string> > outgoingTransitionTable) { // local data for red DFS Stack <LocalPair> redStack = new Stack <LocalPair>(5000); Dictionary <string, List <LocalPair> > expendedNodes = new Dictionary <string, List <LocalPair> >(256); // push accepting state to redStack redStack.Push(acceptingState); // start loop while (redStack.Count > 0) { // too long action or counterexample reported if (CancelRequested) { VerificationOutput.NoOfStates = colorData.Count; return(false); } // get the top of redStack LocalPair pair = redStack.Peek(); ConfigurationBase LTSState = pair.configuration; string BAState = pair.state; string v = pair.GetCompressedState(); // if v is not in expendedNodes of red DFS if (!expendedNodes.ContainsKey(v)) { // create next states from v & add to expendedNodes IEnumerable <ConfigurationBase> nextLTSStates = LTSState.MakeOneMove(); pair.SetEnabled(nextLTSStates, FairnessType); List <LocalPair> nextStates = LocalPair.NextLocal(BA, nextLTSStates, BAState); expendedNodes.Add(v, nextStates); } // get successors of v List <LocalPair> successors = expendedNodes[v]; // check all successors if there is at least cyan state for (int i = successors.Count - 1; i >= 0; i--) { LocalPair succ = successors[i]; string w = succ.GetCompressedState(); Color wColor = colorData[w]; // if they are cyan if (wColor.isCyan()) { // report accepting cycle redReportAcceptinCycle(succ, blueStack, redStack, colorData, outgoingTransitionTable); return(true); } else if (!wColor.isBlue()) { successors.RemoveAt(i); } } // find invisited state in red DFS bool redDone = true; for (int i = successors.Count - 1; i >= 0; i--) { LocalPair succ = successors[i]; string w = succ.GetCompressedState(); Color wColor = colorData[w]; // if w is blue if (wColor.isBlue()) { // set w pink wColor.setPink(); // add w to redStack redStack.Push(succ); successors.RemoveAt(i); redDone = false; break; } else { successors.RemoveAt(i); } } // if there is no blue successors if (redDone) { redStack.Pop(); } } return(false); }