/// <summary> /// Begins the Depth-First Search reachability checking. /// </summary> /// <param name="touched">Dictionary indicating if each module has been checked during this cycle.</param> /// <param name="origStart">Module where the depth-first search will begin. If null, the Start tag is used.</param> private void CheckReachabilityDFS(Dictionary <string, bool> touched, ModuleVertex origStart = null) { if (origStart == null) { origStart = Modules.Find(v => v.IsStart); } var randStart = Modules.Find(v => v.WarpCode == RandomLookup[origStart.WarpCode]); // Search through all modules connected to the start. For now, treat start as not reachable // since we may have no opportunity to return here. foreach (var edge in randStart.LeadsTo) { // If this is a once edge, determine how to handle it. if (IsOnceEdge(edge)) { // Ignore once edges if setting is enabled. if (!IgnoreOnceEdges) { // If allowed, enqueue the once edge for checking at the end of this cycle. if (!Reachable[RandomLookup[edge.WarpCode]] && !OnceQueue.Contains(edge)) { OnceQueue.Enqueue(edge); ReachableUpdated = true; } } continue; } // If this is a locked edge, determine if it is still locked. if (EnforceEdgeTagLocked && IsLockedEdge(edge)) { continue; } DepthFirstSearch(touched, Modules.Find(m => m.WarpCode == RandomLookup[edge.WarpCode])); } // Check edges marked as Once for reachability. for (int i = 0; i < OnceQueue.Count; i++) { var once = OnceQueue.Dequeue(); // Remove if already reachable. if (Reachable[RandomLookup[once.WarpCode]]) { continue; } // Send to back if still locked. if (EnforceEdgeTagLocked && IsLockedEdge(once)) { OnceQueue.Enqueue(once); //ReachableUpdated = true; continue; } // Otherwise, visit. DepthFirstSearch(touched, Modules.Find(m => m.WarpCode == RandomLookup[once.WarpCode])); } }
/// <summary> /// Recursive method to perform Depth-First Search reachability checking. /// </summary> /// <param name="touched">Dictionary indicating if each module has been checked during this cycle.</param> /// <param name="v">The current module to check.</param> private void DepthFirstSearch(Dictionary <string, bool> touched, ModuleVertex v) { // This module has been reached, so assume reachable. touched[v.WarpCode] = true; if (touched[v.WarpCode] != Reachable[v.WarpCode]) { ReachableUpdated = true; Reachable[v.WarpCode] = true; } // Any tags associated with this vertex are also reachable. foreach (var t in v.Tags) { if (!Reachable.ContainsKey(t)) { Reachable.Add(t, true); } else { Reachable[t] = true; } } // Check to see if the locked tag is reachable too. if (!string.IsNullOrWhiteSpace(v.LockedTag)) { var isUnlocked = true; // If ALL tags are reachable, this tag is also reachable. foreach (var ul in v.Unlock) { if (Reachable.ContainsKey(ul) && Reachable[ul]) { isUnlocked = true; } else { isUnlocked = false; break; } } if (!Reachable.ContainsKey(v.LockedTag)) { Reachable.Add(v.LockedTag, isUnlocked); } else { Reachable[v.LockedTag] = isUnlocked; } } // Check each edge that hasn't been reached already. foreach (var edge in v.LeadsTo) { // If this is a once edge, determine how to handle it. if (IsOnceEdge(edge)) { // Ignore once edges if setting is enabled. if (!IgnoreOnceEdges) { // If allowed, enqueue the once edge for checking at the end of this cycle. if (!Reachable[RandomLookup[edge.WarpCode]] && !OnceQueue.Contains(edge)) { OnceQueue.Enqueue(edge); ReachableUpdated = true; } } continue; } // If this is a locked edge, determine if it is still locked. if (EnforceEdgeTagLocked && IsLockedEdge(edge)) { continue; } if (!touched[RandomLookup[edge.WarpCode]]) { DepthFirstSearch(touched, Modules.Find(m => m.WarpCode == RandomLookup[edge.WarpCode])); } } }