This class provides static methods to compute both betweenness preference matrices as well as betweenness preference of nodes in temporal networks
        /// <summary>
        /// Parallely computes the betweenness preference distribution of all nodes in a temporal network
        /// </summary>
        /// <param name="temp_net">The temporal network to analyze</param>
        /// <returns>An IEnumerable containing betweenness preferences of all nodes</returns>
        public static IEnumerable <double> GetBetweennessPrefDist(TemporalNetwork temp_net)
        {
            List <double> dist = new List <double>(temp_net.AggregateNetwork.VertexCount);

            Parallel.ForEach <string>(temp_net.AggregateNetwork.Vertices, v =>
            {
                double betweennessPref = BetweennessPref.GetBetweennessPref(temp_net, v);

                // Synchronized access to the list
                if (temp_net.AggregateNetwork.GetIndeg(v) > 0 && temp_net.AggregateNetwork.GetOutdeg(v) > 0)
                {
                    lock (dist)
                        dist.Add(betweennessPref);
                }
            });
            return(dist);
        }
Пример #2
0
        public static IDictionary <int, double> RunRW_BWP(TemporalNetwork temp_net, int max_steps = 100000, bool null_model = false)
        {
            Random r = new Random();

            var cumulatives = new Dictionary <Tuple <string, string>, Dictionary <double, string> >();
            var sums        = new Dictionary <Tuple <string, string>, double>();

            // Dictionary<string, Dictionary<double, string>> cumulatives =
            // Dictionary<string, double> sums = new Dictionary<string, double>();

            Dictionary <string, Dictionary <string, int> > indices_pred = new Dictionary <string, Dictionary <string, int> >();
            Dictionary <string, Dictionary <string, int> > indices_succ = new Dictionary <string, Dictionary <string, int> >();
            Dictionary <string, double[, ]> matrices = new Dictionary <string, double[, ]>();

            Dictionary <string, int>    visitations = new Dictionary <string, int>();
            Dictionary <string, double> stationary  = new Dictionary <string, double>();

            Dictionary <Tuple <string, string>, int>    edge_visitations = new Dictionary <Tuple <string, string>, int>();
            Dictionary <Tuple <string, string>, double> edge_stationary  = new Dictionary <Tuple <string, string>, double>();

            Dictionary <int, double> tvd = new Dictionary <int, double>();

            // Aggregate network
            WeightedNetwork network = temp_net.AggregateNetwork;

            // Read analytical stationary distribution (i.e. flow-corrected edge weights) from disk
            string[] lines = System.IO.File.ReadAllLines("stationary_dist_RM.dat");
            foreach (string x in lines)
            {
                string[] split = x.Split(' ');
                string[] nodes = split[0].Split('.');
                var      edge  = new Tuple <string, string>(nodes[0], nodes[1]);

                // Extract stationary dist, set visitations to zero and adjust edge weights ...
                edge_stationary[edge]  = double.Parse(split[1], System.Globalization.CultureInfo.GetCultureInfo("en-US").NumberFormat);
                edge_visitations[edge] = 0;
                network[edge]          = edge_stationary[edge];
            }

            // Compute stationary dist of vertices ...
            double total = 0d;

            foreach (string x in network.Vertices)
            {
                stationary[x] = 0d;
                foreach (string s in network.GetPredecessors(x))
                {
                    stationary[x] += edge_stationary[new Tuple <string, string>(s, x)];
                }
                total += stationary[x];
            }
            foreach (string x in network.Vertices)
            {
                stationary[x] = stationary[x] / total;
            }


            // Compute betweenness preference matrices
            if (!null_model)
            {
                Console.Write("Computing betweenness preference in temporal network ...");
            }
            else
            {
                Console.Write("Calculating null model betweenness preference ...");
            }
            foreach (string x in network.Vertices)
            {
                var ind_p = new Dictionary <string, int>();
                var ind_s = new Dictionary <string, int>();
                if (!null_model)
                {
                    matrices[x] = BetweennessPref.GetBetweennessPrefMatrix(temp_net, x, out ind_p, out ind_s, false);
                }
                else
                {
                    matrices[x] = BetweennessPref.GetUncorrelatedBetweennessPrefMatrix(temp_net, x, out ind_p, out ind_s);
                }

                indices_pred[x] = ind_p;
                indices_succ[x] = ind_s;
            }
            Console.WriteLine("done.");

            // Initialize visitations, stationary distribution and cumulatives ...
            foreach (string x in network.Vertices)
            {
                visitations[x] = 0;
                stationary[x]  = 0d;

                foreach (string s in indices_pred[x].Keys)
                {
                    Tuple <string, string> key = new Tuple <string, string>(s, x);

                    stationary[x] += network.GetWeight(s, x);

                    // Compute the transition probability for a edge (x,t) given that we are in (s,x)
                    cumulatives[key] = new Dictionary <double, string>();
                    double sum = 0d;

                    foreach (string t in indices_succ[x].Keys)
                    {
                        double transition_prob = 0d;

                        string two_path = s + "," + x + "," + t;
                        transition_prob = matrices[x][indices_pred[x][s], indices_succ[x][t]];

                        if (transition_prob > 0)
                        {
                            sum += transition_prob;
                            cumulatives[key][sum] = t;
                        }
                    }
                    sums[key] = sum;
                }
            }

            // Draw two initial nodes ...
            string pred    = network.RandomNode;
            string current = network.GetRandomSuccessor(pred);

            visitations[pred]    = 1;
            visitations[current] = 1;
            edge_visitations[new Tuple <string, string>(pred, current)] = 1;

            // Run the random walk (over edges)
            for (int t = 0; t < max_steps; t++)
            {
                // The edge via which we arrived at the current node
                Tuple <string, string> current_edge = new Tuple <string, string>(pred, current);

                // If this happens, we are stuck in a sink, i.e. there is no out edge
                System.Diagnostics.Debug.Assert(sums[current_edge] > 0, string.Format("Network not strongly connected! RW stuck after passing through edge {0}", current_edge));

                // Draw a sample uniformly from [0,1] and multiply it with the cumulative sum for the current edge ...
                double sample = rand.NextDouble() * sums[current_edge];

                // Determine the next transition ...
                string next_node = null;
                for (int i = 0; i < cumulatives[current_edge].Count; i++)
                {
                    if (cumulatives[current_edge].Keys.ElementAt(i) > sample)
                    {
                        next_node = cumulatives[current_edge].Values.ElementAt(i);
                        break;
                    }
                }
                pred    = current;
                current = next_node;

                visitations[current] = visitations[current] + 1;
                edge_visitations[new Tuple <string, string>(pred, current)] = edge_visitations[new Tuple <string, string>(pred, current)] + 1;

                tvd[t] = TVD(visitations, stationary);
            }
            return(tvd);
        }
Пример #3
0
        /// <summary>
        /// This method creates a random sequence of two paths, where the betweenness preferences as well as edge weights match those of a given temporal network.
        /// The model implemented here can be viewd in two different ways:
        /// 1.) It can be seen as a reshuffling of two paths realized in a given temporal network, while destroying other correlations like bursty activity patterns
        /// 2.) Alternatively, it can be seen as a random sampling based on the betweenness preference matrices of nodes as computed from an empirical network
        /// </summary>
        /// <param name="temp_net">The temporal network based on which a randomized sequence of two paths will be created</param>
        /// <param name="length">The length of the sequence in terms of the number of time-stamped interactions</param>
        /// <param name="precision">The numerical precision that will be used when sampling from the distribution. This
        /// at the same time affects the memory requirements of the procedure, which is at most precision*two_paths in the input network</param>
        /// <returns>A temporal network that preserves betweenness preferences as well as the aggregated network of the input</returns>
        public static TemporalNetwork ShuffleTwoPaths(TemporalNetwork temp_net, int length = 0, int precision = 1000)
        {
            // If no length is specified (i.e. length has the default value of 0), use the length of the original sequence
            length = length > 0 ? length : temp_net.Length;

            // This will take the betweenness pref. matrices of all nodes ...
            Dictionary <string, double[, ]> betweenness_matrices = new Dictionary <string, double[, ]>();

            Dictionary <string, Dictionary <string, int> > pred_indices = new Dictionary <string, Dictionary <string, int> >();
            Dictionary <string, Dictionary <string, int> > succ_indices = new Dictionary <string, Dictionary <string, int> >();

            int lcm = 1;

            // Compute unnormalized betweenness preference matrices of all nodes in the aggregate network
            foreach (string x in temp_net.AggregateNetwork.Vertices)
            {
                Dictionary <string, int> preds = new Dictionary <string, int>();
                Dictionary <string, int> succs = new Dictionary <string, int>();
                betweenness_matrices[x] = BetweennessPref.GetBetweennessPrefMatrix(temp_net, x, out preds, out succs, normalized: false);
                pred_indices[x]         = preds;
                succ_indices[x]         = succs;

                // Compute the least common multiple of the denominators of all entries ...
                // Eventually we will multiply ALL entries of the matrices of ALL nodes with the LCM in order to
                // ensure that all two paths are represented with the correct relative frequencies
                foreach (string s in temp_net.AggregateNetwork.GetPredecessors(x))
                {
                    foreach (string d in temp_net.AggregateNetwork.GetSuccessors(x))
                    {
                        int whole, numerator, denominator;
                        MathHelper.RoundToMixedFraction(betweenness_matrices[x][pred_indices[x][s], succ_indices[x][d]], precision, out whole, out numerator, out denominator);
                        lcm = MathHelper.LCM(lcm, denominator);
                    }
                }
            }

            List <string> sampling_set = new List <string>();

            // Create a list of two_paths whose relative frequencies match the betweenness preference matrix...
            foreach (string v in betweenness_matrices.Keys)
            {
                // Add source and target of two paths to list according to their relative frequencies in the matrices
                foreach (string s in temp_net.AggregateNetwork.GetPredecessors(v))
                {
                    foreach (string d in temp_net.AggregateNetwork.GetSuccessors(v))
                    {
                        for (int k = 0; k < Math.Round(betweenness_matrices[v][pred_indices[v][s], succ_indices[v][d]] * lcm); k++)
                        {
                            sampling_set.Add(s + "," + v + "," + d);
                        }
                    }
                }
            }

            // Create an empty temporal network
            TemporalNetwork microstate = new TemporalNetwork();

            int time = 0;

            // Draw two-paths at random from the sampling set, this is equivalent to reshuffling existing two paths of the original sequence
            // However, it additionally correctly accounts for continued two paths (in which case an edge overlaps) and for multiple edges in
            // a single step (such two paths will be counted fractionally)
            for (int l = 0; l < length / 2; l++)
            {
                // Draw a random two path
                int      r     = rand.Next(sampling_set.Count);
                string   tp    = sampling_set[r];
                string[] nodes = tp.Split(',');

                // Add two temporal edges
                microstate.AddTemporalEdge(time++, nodes[0], nodes[1]);
                microstate.AddTemporalEdge(time++, nodes[1], nodes[2]);
            }
            return(microstate);
        }