protected int LowestDelay(GraphNode src, GraphNode dst) { ConnectionList cl = src.ConnectionTable.GetConnections(ConnectionType.Structured); Connection fastest_con = cl[0]; int lowest_delay = Int32.MaxValue; int second_half = Int32.MaxValue; foreach(Connection con in cl) { GraphEdge edge = con.Edge as GraphEdge; int delay = edge.Delay; if(delay == 0) { continue; } GraphNode mid = _addr_to_node[fastest_con.Address as AHAddress]; int delay2 = CalculateDelay(mid, dst); if(second_half == 0) { continue; } if(delay < lowest_delay) { fastest_con = con; lowest_delay = delay; second_half = delay2; } } return lowest_delay + second_half; }
///</summary>Creates a new Graph for simulate routing algorithms.</summary> ///<param name="count">The network size not including the clusters.</param> ///<param name="near">The amount of connections on the left or right of a ///node.</param> ///<param name="shortcuts">The amount of far connections had per node.</param> ///<param name="latency">(optional)count x count matrix containing the ///latency between ///two points.</param> ///<param name="cluster_count">A cluster is a 100 node network operating on ///a single point in the network. A cluster cannot communicate directly ///with another cluster.</param> ///<param name="dataset">A square dataset consisting of pairwise latencies.</param> public Graph(int count, int near, int shortcuts, int random_seed, List<List<int>> dataset) { _latency_map = dataset; _rand = new Random(random_seed); GraphNode.SetSeed(_rand.Next()); _addr_to_node = new Dictionary<AHAddress, GraphNode>(count); _addrs = new List<AHAddress>(count); _addr_to_index = new Dictionary<AHAddress, int>(count); // first we create our regular network while(_addrs.Count < count) { AHAddress addr = GenerateAddress(); GraphNode node = new GraphNode(addr); _addr_to_node[addr] = node; _addrs.Add(addr); } FixLists(); for(int i = 0; i < count; i++) { GraphNode cnode = _addr_to_node[_addrs[i]]; ConnectionList cons = cnode.ConnectionTable.GetConnections(ConnectionType.Structured); // We select our left and right neighbors up to near out (so we get 2*near connections) // Then we check to make sure we don't already have this connection, since the other guy // may have added it, if we don't we create one and add it. for(int j = 1; j <= near; j++) { int left = i - j; if(left < 0) { left += count; } GraphNode lnode = _addr_to_node[_addrs[left]]; if(!cons.Contains(lnode.Address)) { int delay = CalculateDelay(cnode, lnode); AddConnection(cnode, lnode, delay); AddConnection(lnode, cnode, delay); } int right = i+j; if(right >= count) { right -= count; } GraphNode rnode = _addr_to_node[_addrs[right]]; // No one has this connection, let's add it to both sides. if(!cons.Contains(rnode.Address)) { int delay = CalculateDelay(cnode, rnode); AddConnection(cnode, rnode, delay); AddConnection(rnode, cnode, delay); } } // Let's add shortcuts so that we have at least the minimum number of shortcuts while(cnode.Shortcuts < shortcuts) { cons = cnode.ConnectionTable.GetConnections(ConnectionType.Structured); AHAddress addr = ComputeShortcutTarget(cnode.Address); addr = FindNodeNearestToAddress(addr); if(cons.Contains(addr) || addr.Equals(cnode.Address)) { continue; } GraphNode snode = _addr_to_node[addr]; cons = snode.ConnectionTable.GetConnections(ConnectionType.Structured); int delay = CalculateDelay(cnode, snode); if(delay == -1) { continue; } AddConnection(cnode, snode, delay); AddConnection(snode, cnode, delay); cnode.Shortcuts++; snode.Shortcuts++; } } foreach(GraphNode gn in _addr_to_node.Values) { gn.UpdateSystem(); } }
///<summary>Calculates the delay between two nodes.</summary> protected virtual int CalculateDelay(GraphNode node1, GraphNode node2) { if(_latency_map != null) { int mod = _latency_map.Count; int x = node1.UniqueID % mod; int y = node2.UniqueID % mod; return (int) (_latency_map[x][y] / 1000.0); } return _rand.Next(10, 240); }
///<summary>Creates an edge and a connection from node2 to node1 including ///the edge. Note: this is unidirectional, this must be called twice, ///swapping node1 with node2 for a connection to be complete.</summary> protected void AddConnection(GraphNode node1, GraphNode node2, int delay) { Edge edge = new GraphEdge(delay); Connection con = new Connection(edge, node2.Address, ConnectionType.Structured.ToString(), null, null); node1.ConnectionTable.Add(con); }
///<summary>Calculates the delay between two nodes.</summary> protected virtual int CalculateDelay(GraphNode node1, GraphNode node2) { if(node1 == node2) { return 0; } if(_latency_map != null) { int mod = _latency_map.Count; int x = node1.UniqueID % mod; int y = node2.UniqueID % mod; if(x == y) { return 0; } else if(_latency_map[x][y] <= 0) { _latency_map[x][y] = 1000 * 1000; } return (int) (_latency_map[x][y] / 1000.0); } return _rand.Next(10, 240); }