private static void printDiamond(UInt32 pointASN, UInt32 stub, List <UInt32> competitors, SecureSimulator.NetworkGraph g, StreamWriter output) { SecureSimulator.AsNode pointASNode = g.GetNode(pointASN); SecureSimulator.AsNode stubASNode = g.GetNode(stub); foreach (UInt32 c in competitors) { SecureSimulator.AsNode cASNode = g.GetNode(c); output.WriteLine("{0} {1} {2} {3} {4}", pointASN, relationshipToString(cASNode.GetRelationshipTypeOfNeighbor(pointASNode)), c, relationshipToString(stubASNode.GetRelationshipTypeOfNeighbor(cASNode)), stub); } }
/// <summary> /// Extension method on the NetworkGraph class that performs a [modified] BFS on the /// specified graph from the specified source ndoe. The allowedRelationships specifies /// which edges may be traversed during the BFS. /// This algorithm breaks ties by picking the node with the lower node number. /// This algorithm allows you to execute multiple BFS iterations on a single graph, with the /// constraint that any previous BFS trees created in a prior BFS run will not be modified (only /// added to). /// If limitedDiscovery is true, the BFS will only find new nodes that are 1 edge away from any existing /// BFS tree. /// If includeSibling is true, then ties are broken by first taking non-siblings over siblings. /// /// Modified by PGill Oct. 2010 to take in references to the Best, BucketTable and ChosenPaths sets. The function /// was also modified to populate these for our new sims. /// </summary> public static void ExecuteBfs(NetworkGraph graph, List <UInt32> srcNodeNums, bool limitedDiscovery, bool includeSibling, RelationshipType allowedRelationships, ref List <UInt32>[] Best, ref List <UInt32>[] BestNew, ref List <UInt32>[][] BucketTable, ref List <UInt32>[] ChosenPath, ref UInt32[] ChosenParent, ref byte[] L, ref byte[] BestRelation) { Destination utility = new Destination(); // Initialize some stuff... Queue <AsNode> nodeQueue = new Queue <AsNode>(graph.NodeCount); graph.BfsTreeNodeCount = 0; // "Visit" the source nodes foreach (UInt32 srcNodeNum in srcNodeNums) { AsNode currentNode = graph.GetNode(srcNodeNum); currentNode.InProcessBfsStatus = NodeInProcessBfsStatus.SeenInCurrentRun; currentNode.BfsDepth = 0; nodeQueue.Enqueue(currentNode); graph.BfsTreeNodeCount++; //init the destination's path to itself ChosenPath[srcNodeNum] = new List <UInt32>(); ChosenPath[srcNodeNum].Add(srcNodeNum); Best[srcNodeNum] = new List <UInt32>(); Best[srcNodeNum].Add(srcNodeNum); //if (allowedRelationships.HasFlag(RelationshipType.CustomerOf)) if ((allowedRelationships & RelationshipType.CustomerOf) == RelationshipType.CustomerOf || allowedRelationships == RelationshipType.NullRelationship) { BucketTable[0][Destination._CUSTOMERCOLUMN] = new List <UInt32>(); BucketTable[0][Destination._CUSTOMERCOLUMN].Add(srcNodeNum); } } // While there's still nodes to be examined... while (nodeQueue.Count > 0) { // Dequeue a node to examine. Iterate through all of its neighbors of the specified type (plus // existing BFS children) and visit them. AsNode currentNode = nodeQueue.Dequeue(); foreach (AsNode oppositeNode in currentNode.GetNeighborsByType(allowedRelationships | RelationshipType.BfsParentOf).Distinct()) { bool addedtoBest = false; // If this is the first time we've see this node, mark it and possibly enqueue it for later examination if (oppositeNode.InProcessBfsStatus == NodeInProcessBfsStatus.UnseenInCurrentRun) { // Case 1: oppositeNode is a newly discovered node, also unseen in any previous BFS runs if (oppositeNode.PriorBfsStatus == NodePriorBfsStatus.NotDiscoveredInPriorBfs) { oppositeNode.InProcessBfsStatus = NodeInProcessBfsStatus.SeenInCurrentRun; oppositeNode.BfsDepth = currentNode.BfsDepth + 1; oppositeNode.BfsParentNode = currentNode; currentNode.AddBfsChild(oppositeNode); graph.BfsTreeDepth = Math.Max(graph.BfsTreeDepth, oppositeNode.BfsDepth); graph.BfsTreeNodeCount++; if (!oppositeNode.isStub() || !OnlyNonStubs) { L[oppositeNode.NodeNum] = (byte)oppositeNode.BfsDepth; /*** add this node to the buckettable and update its chosen path, parent and BFS depth***/ //if (allowedRelationships.HasFlag(RelationshipType.CustomerOf)) -- this is .NET 4, downgraded to make comptabilte with .NET 3.5 if ((allowedRelationships & RelationshipType.CustomerOf) == RelationshipType.CustomerOf || allowedRelationships == RelationshipType.NullRelationship) { //init this spot in the bucket table (if needed) if (BucketTable[oppositeNode.BfsDepth][Destination._CUSTOMERCOLUMN] == null) { BucketTable[oppositeNode.BfsDepth][Destination._CUSTOMERCOLUMN] = new List <UInt32>(); } BestRelation[oppositeNode.NodeNum] = Destination._CUSTOMERCOLUMN; BucketTable[oppositeNode.BfsDepth][Destination._CUSTOMERCOLUMN].Add(oppositeNode.NodeNum); utility.updatePath(oppositeNode.NodeNum, ChosenPath[currentNode.NodeNum], Destination._CUSTOMERCOLUMN, ref ChosenPath); } //else if (allowedRelationships.HasFlag(RelationshipType.ProviderTo)) -- this is .NET 4, downgraded to make comptabilte with .NET 3.5 else if ((allowedRelationships & RelationshipType.ProviderTo) == RelationshipType.ProviderTo) { //init this spot in the bucket table (if needed) if (BucketTable[oppositeNode.BfsDepth][Destination._PROVIDERCOLUMN] == null) { BucketTable[oppositeNode.BfsDepth][Destination._PROVIDERCOLUMN] = new List <UInt32>(); } BestRelation[oppositeNode.NodeNum] = Destination._PROVIDERCOLUMN; BucketTable[oppositeNode.BfsDepth][Destination._PROVIDERCOLUMN].Add(oppositeNode.NodeNum); utility.updatePath(oppositeNode.NodeNum, ChosenPath[currentNode.NodeNum], Destination._PROVIDERCOLUMN, ref ChosenPath); } //else if (allowedRelationships.HasFlag(RelationshipType.PeerOf)) -- this is .NET 4, downgraded to make comptabilte with .NET 3.5 else if ((allowedRelationships & RelationshipType.PeerOf) == RelationshipType.PeerOf) { //init this spot in the bucket table (if needed) if (BucketTable[oppositeNode.BfsDepth][Destination._PEERCOLUMN] == null) { BucketTable[oppositeNode.BfsDepth][Destination._PEERCOLUMN] = new List <UInt32>(); } BestRelation[oppositeNode.NodeNum] = Destination._PEERCOLUMN; BucketTable[oppositeNode.BfsDepth][Destination._PEERCOLUMN].Add(oppositeNode.NodeNum); utility.updatePath(oppositeNode.NodeNum, ChosenPath[currentNode.NodeNum], Destination._PEERCOLUMN, ref ChosenPath); } /*** update this node's Best set ***/ if (Best[oppositeNode.NodeNum] == null) { Best[oppositeNode.NodeNum] = new List <UInt32>(); } Best[oppositeNode.NodeNum].Add(currentNode.NodeNum); ChosenParent[oppositeNode.NodeNum] = currentNode.NodeNum; if (BestNew[oppositeNode.NodeNum] == null) { BestNew[oppositeNode.NodeNum] = new List <UInt32>(); } UInt32 encoded = 0; UInt32 NodeNumx = currentNode.NodeNum; if ((allowedRelationships & currentNode.GetRelationshipTypeOfNeighbor(oppositeNode)) == RelationshipType.ProviderTo) { encoded = (UInt32)((NodeNumx << 3) + Destination._PROVIDERCOLUMN); } else if ((allowedRelationships & currentNode.GetRelationshipTypeOfNeighbor(oppositeNode)) == RelationshipType.CustomerOf || allowedRelationships == RelationshipType.NullRelationship) { encoded = (UInt32)((NodeNumx << 3) + Destination._CUSTOMERCOLUMN); } else if ((allowedRelationships & currentNode.GetRelationshipTypeOfNeighbor(oppositeNode)) == RelationshipType.PeerOf) { encoded = (UInt32)((NodeNumx << 3) + Destination._PEERCOLUMN); } BestNew[oppositeNode.NodeNum].Add(encoded); } // If we want to continue discovering past this newly found node, enqueue it if (!limitedDiscovery) { nodeQueue.Enqueue(oppositeNode); } } // Case 2: oppositeNode was found in a prior BFS run, and the path to oppositeNode went through currentNode else if (oppositeNode.BfsParentNode == currentNode) { // Don't need to do any marking of the opposite node because it's already in the BFS tree. // Just enqueue it so we can continue our BFS from that node at some later time. oppositeNode.InProcessBfsStatus = NodeInProcessBfsStatus.SeenInCurrentRun; nodeQueue.Enqueue(oppositeNode); graph.BfsTreeDepth = Math.Max(graph.BfsTreeDepth, oppositeNode.BfsDepth); graph.BfsTreeNodeCount++; // Sanity check... the depth should be the same, right? if (oppositeNode.BfsDepth != currentNode.BfsDepth + 1) { throw new Exception("Unexpected BFS depth during BFS re-run"); } } // Case 3: oppositeNode was found in a prior BFS run, and the path to oppositeNode did NOT go through currentNode // No action necessary. We can't process oppositeNode now because we aren't allow to follow this edge. // Eventually we will hit the already-existing edge that's part of a prior BFS run, and we'll enter Case 2 above. } // We've seen this node before... else { // Did we find an alternate route to the opposite node? // We cannot change the route if this node was found in a prior BFS run. // This is where tie-breaking happens... if ((oppositeNode.InProcessBfsStatus == NodeInProcessBfsStatus.SeenInCurrentRun) && (oppositeNode.BfsDepth == (currentNode.BfsDepth + 1)) && (oppositeNode.PriorBfsStatus != NodePriorBfsStatus.DiscoveredInPriorBfs)) { // This is an alternate route... break the tie //note that current node is a potential parent of opposite node here. //equivalent to current node being one of the nodes in the tiebreak set //Console.WriteLine("Ties Breaker"); //UPDATED CONDITION TO DEAL WITH HASH FLAG if ((Hash && NewRouteWinsTieBreak(currentNode, oppositeNode, includeSibling)) || (!Hash && NewRouteWinsTieBreakOriginal(currentNode, oppositeNode, includeSibling))) { // Tie-break algorithm says we have a new, better route to this node. // We need to switch the route through the current node instead. oppositeNode.BfsParentNode.RemoveBfsChild(oppositeNode); oppositeNode.BfsParentNode = currentNode; currentNode.AddBfsChild(oppositeNode); if (!oppositeNode.isStub() || !OnlyNonStubs) { /*** update chosen parent***/ ChosenParent[oppositeNode.NodeNum] = currentNode.NodeNum; /*** update its chosen path ***/ //if (allowedRelationships.HasFlag(RelationshipType.CustomerOf)) if ((allowedRelationships & RelationshipType.CustomerOf) == RelationshipType.CustomerOf || allowedRelationships == RelationshipType.NullRelationship) { utility.updatePath(oppositeNode.NodeNum, ChosenPath[currentNode.NodeNum], Destination._CUSTOMERCOLUMN, ref ChosenPath); } //else if (allowedRelationships.HasFlag(RelationshipType.ProviderTo)) else if ((allowedRelationships & RelationshipType.ProviderTo) == RelationshipType.ProviderTo) { utility.updatePath(oppositeNode.NodeNum, ChosenPath[currentNode.NodeNum], Destination._PROVIDERCOLUMN, ref ChosenPath); } //else if (allowedRelationships.HasFlag(RelationshipType.PeerOf)) else if ((allowedRelationships & RelationshipType.PeerOf) == RelationshipType.PeerOf) { utility.updatePath(oppositeNode.NodeNum, ChosenPath[currentNode.NodeNum], Destination._PEERCOLUMN, ref ChosenPath); } } } /*** NEED TO UPDATE BEST SET WHETHER OR NOT THIS WINS THE TIE BREAK!! **/ if (!oppositeNode.isStub() || !OnlyNonStubs) { Best[oppositeNode.NodeNum].Add(currentNode.NodeNum); addedtoBest = true; } } } if ((Best[oppositeNode.NodeNum] != null))// && addedtoBest)// && //(oppositeNode.PriorBfsStatus != NodePriorBfsStatus.DiscoveredInPriorBfs)) { if (BestNew[oppositeNode.NodeNum] == null) { BestNew[oppositeNode.NodeNum] = new List <UInt32>(); } UInt32 encoded = 0; UInt32 NodeNumx = currentNode.NodeNum; if ((allowedRelationships & currentNode.GetRelationshipTypeOfNeighbor(oppositeNode)) == RelationshipType.ProviderTo) { encoded = (UInt32)((NodeNumx << 3) + Destination._PROVIDERCOLUMN); } else if ((allowedRelationships & currentNode.GetRelationshipTypeOfNeighbor(oppositeNode)) == RelationshipType.CustomerOf || allowedRelationships == RelationshipType.NullRelationship) { encoded = (UInt32)((NodeNumx << 3) + Destination._CUSTOMERCOLUMN); } else if ((allowedRelationships & currentNode.GetRelationshipTypeOfNeighbor(oppositeNode)) == RelationshipType.PeerOf) { encoded = (UInt32)((NodeNumx << 3) + Destination._PEERCOLUMN); } UInt32 encoded0 = (UInt32)((NodeNumx << 3) + Destination._PROVIDERCOLUMN); UInt32 encoded1 = (UInt32)((NodeNumx << 3) + Destination._CUSTOMERCOLUMN); UInt32 encoded2 = (UInt32)((NodeNumx << 3) + Destination._PEERCOLUMN); if (!((BestNew[oppositeNode.NodeNum].Exists(element => element == encoded0)) || (BestNew[oppositeNode.NodeNum].Exists(element => element == encoded1)) || (BestNew[oppositeNode.NodeNum].Exists(element => element == encoded2)))) { //Console.WriteLine(oppositeNode.NodeNum + "--> Entered for: " + ((UInt32)(((uint)encoded) >> 3) + " relation: " + (int)(encoded & 7))); //Console.WriteLine("encoded = " + encoded); if (encoded != 0) { //Console.WriteLine(oppositeNode.NodeNum + "--> Entered for: " + ((UInt32)(((uint)encoded) >> 3) + " relation: " + (int)(encoded & 7))); //if ((((allowedRelationships & RelationshipType.ProviderTo) == RelationshipType.ProviderTo) && oppositeNode.InProcessBfsStatus == NodeInProcessBfsStatus.ProcessedInCurrentRun)) //{ // Console.Write("Rel: " + allowedRelationships + " & Node status: " + oppositeNode.InProcessBfsStatus + "\n"); //} //else { BestNew[oppositeNode.NodeNum].Add(encoded); } } } } } // Update the in-process BFS status currentNode.InProcessBfsStatus = NodeInProcessBfsStatus.ProcessedInCurrentRun; } // Finished the BFS... lock the discovered nodes into the BFS tree foreach (AsNode node in graph.GetAllNodes()) { // FYI In limitedDiscovery mode, some nodes may have been left in the SeenInCurrentRun state // (instead of ProcessedInCurrentRun). if (node.InProcessBfsStatus != NodeInProcessBfsStatus.UnseenInCurrentRun) { node.PriorBfsStatus = NodePriorBfsStatus.DiscoveredInPriorBfs; } node.InProcessBfsStatus = NodeInProcessBfsStatus.UnseenInCurrentRun; } }