/// <summary> /// Creates a weighted network representation of a temporal network by aggregating edge occurences /// (and thus discarding information on the temporal ordering of edges) /// </summary> /// <param name="temp_net">he temporal network that shall be aggregated</param> /// <returns>An instance of a weighted aggregate network</returns> public static WeightedNetwork FromTemporalNetwork(TemporalNetwork temp_net) { WeightedNetwork weighted_net = new WeightedNetwork(); foreach (var t in temp_net.Keys) { foreach (Tuple <string, string> edge in temp_net[t]) { weighted_net.AddEdge(edge.Item1, edge.Item2); } } return(weighted_net); }
/// <summary> /// This methods extracts all two paths from the sequence of edges in the temporal network (two-paths according to eq. (1) of the paper). /// It will also extract the correct (statistical) weights for both the two paths and the edges in the aggregate network. /// After this method returns, the weighted TwoPaths list as well as the weighted AggregateNetwork are available. /// If an explicit call to preprocess is ommitted, the preprocessing will be triggered whenever the AggregateNetwork or the TwoPaths dictionary /// is used for the first time. Changing the temporal network (i.e. adding or removing and edge) will invalidate both, so this method has to be called /// again. /// </summary> /// <seealso cref="TwoPathsByNode"/> /// <seealso cref="AggregateNetwork"/> public void ReduceToTwoPaths() { _twoPathsByNode = new Dictionary <string, Dictionary <int, List <Tuple <string, string> > > >(); _twoPathWeights = new Dictionary <string, double>(); _twoPathsByStartTime = new Dictionary <int, List <string> >(); var two_path_edges = new Dictionary <int, List <Tuple <string, string> > >(); int prev_t = -1; var ordered_time = Keys.OrderBy(k => k, new CompareInts()); // Walk through time ... foreach (int t in ordered_time) { if (prev_t == -1) { prev_t = t; // We skip the first time step and just set the prev_t index ... } else { // N.B.: Only two-paths consisting of edges in time steps immediately following each other are found // N.B.: We also account for multiple edges happening at the same time, i.e. multiple two-paths can pass through a node at a given time t! // N.B.: For three consecutive edges (a,b), (b,c), (c,d) , two two-paths (a,b,c) and (b,c,d) will be found foreach (var in_edge in this[prev_t]) { foreach (var out_edge in this[t]) { // In this case, we found the two_path (in_edge) -> (out_edge) = (s,v) -> (v,d) if (in_edge.Item2 == out_edge.Item1) { // Use notation from the paper string s = in_edge.Item1; string v = in_edge.Item2; string d = out_edge.Item2; string two_path = s + "," + v + "," + d; double indeg_v = 0d; double outdeg_v = 0d; indeg_v = (from x in this[prev_t].AsParallel() where x.Item2 == v select x).Count(); //foreach (var edge in this[prev_t]) // if (edge.Item2 == v) // indeg_v++; outdeg_v = (from x in this[t].AsParallel() where x.Item1 == v select x).Count(); //foreach (var edge in this[t]) // if (edge.Item1 == v) // outdeg_v++; if (!_twoPathWeights.ContainsKey(two_path)) { _twoPathWeights[two_path] = 0d; } _twoPathWeights[two_path] += 1d / (indeg_v * outdeg_v); if (!two_path_edges.ContainsKey(prev_t)) { two_path_edges[prev_t] = new List <Tuple <string, string> >(); } if (!two_path_edges.ContainsKey(t)) { two_path_edges[t] = new List <Tuple <string, string> >(); } // Important: In the reduced temporal network, we only use edges belonging to two paths. Each edge is added only once, // even if it belongs to several two paths (this is the case for continued two paths as well as for two paths with multiple edges // in one time step if (!two_path_edges[prev_t].Contains(in_edge)) { two_path_edges[prev_t].Add(in_edge); } if (!two_path_edges[t].Contains(out_edge)) { two_path_edges[t].Add(out_edge); } // Add the identified two paths to the list of two paths passing through v at time t if (!_twoPathsByNode.ContainsKey(v)) { _twoPathsByNode[v] = new Dictionary <int, List <Tuple <string, string> > >(); } if (!_twoPathsByNode[v].ContainsKey(t)) { _twoPathsByNode[v][t] = new List <Tuple <string, string> >(); } if (!_twoPathsByStartTime.ContainsKey(prev_t)) { _twoPathsByStartTime[prev_t] = new List <string>(); } _twoPathsByNode[v][t].Add(new Tuple <string, string>(s, d)); _twoPathsByStartTime[prev_t].Add(s + "," + v + "," + d); } } } prev_t = t; } } // Replace the edges of the temporal network by those contributing to two paths if (_stripEdges) { this.Clear(); foreach (int t in two_path_edges.Keys) { this[t] = two_path_edges[t]; } } // Build the aggregate networks with the correct weights ... _cachedWeightedNetwork = new WeightedNetwork(); _cachedWeightedNetworkSecondOrder = new WeightedNetwork(); foreach (var two_path in _twoPathWeights.Keys) { string[] split = two_path.Split(','); _cachedWeightedNetwork.AddEdge(split[0], split[1], EdgeType.Directed, _twoPathWeights[two_path]); _cachedWeightedNetwork.AddEdge(split[1], split[2], EdgeType.Directed, _twoPathWeights[two_path]); _cachedWeightedNetworkSecondOrder.AddEdge(string.Format("({0};{1})", split[0], split[1]), string.Format("({0};{1})", split[1], split[2]), EdgeType.Directed, _twoPathWeights[two_path]); } foreach (string v in _cachedWeightedNetwork.Vertices) { if (!_twoPathsByNode.ContainsKey(v)) { _twoPathsByNode[v] = new Dictionary <int, List <Tuple <string, string> > >(); } } }