Beispiel #1
0
        /// <summary>
        /// Checks whether two temporal network instances are the same (including the labeling of time steps and the labeling of nodes)
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public override bool Equals(object obj)
        {
            if (obj.GetType() != this.GetType())
            {
                return(false);
            }

            TemporalNetwork other = obj as TemporalNetwork;

            foreach (int t in this.Keys)
            {
                if (!other.ContainsKey(t))
                {
                    return(false);
                }
                else
                {
                    foreach (var edge in this[t])
                    {
                        if (!other[t].Contains(edge))
                        {
                            return(false);
                        }
                    }
                }
            }
            return(true);
        }
        /// <summary>
        /// Creates an instance of a random walk process
        /// </summary>
        /// <param name="network"></param>
        /// <param name="walkmode"></param>
        public RandomWalk(TemporalNetwork network, RandomWalkMode walkmode)
        {
            RandomWalkMode       = walkmode;
            _network             = network;
            rand                 = new Random();
            _current_visitations = new Dictionary <string, int>();
            _last_visits         = new Dictionary <string, int>();

            // Set visitations to 0
            foreach (string v in network.AggregateNetwork.Vertices)
            {
                _current_visitations[v] = 0;
            }

            foreach (string v in network.AggregateNetwork.Vertices)
            {
                _last_visits[v] = -1000;
            }

            // Reduce first and second-order aggregate network to strongly connected component
            _network.AggregateNetwork.ReduceToLargestStronglyConnectedComponent();
            _network.SecondOrderAggregateNetwork.ReduceToLargestStronglyConnectedComponent();

            // Initialize random walk
            CurrentEdge = StringToTuple(_network.SecondOrderAggregateNetwork.RandomNode);
            CurrentNode = CurrentEdge.Item2;
            _current_visitations[CurrentNode] = 1;
            Time = 1;

            // Compute stationary distribution
            _stationary_dist = ComputeStationaryDist();

            InitializeCumulatives();
        }
        /// <summary>
        /// Computes the baseline betweenness preference matrix of a node under the assumption
        /// that the temporal network does not contain a betweenness preference correlation. This corresponds to
        /// equation (5) in the paper.
        /// </summary>
        /// <param name="temp_net">The temporal network for which to compute the matrix</param>
        /// <param name="x">The node to compute the baseline betweenness preference for</param>
        /// <param name="ego_net">The weighted, aggregate ego network of node x</param>
        /// <param name="index_pred">Indices of predecessor nodes in the betweenness preference matrix</param>
        /// <param name="index_succ">Indices of successor nodes in the betweenness preference matric</param>
        /// <param name="normalize">Whether or not to normalize the betweenness preference matrix (i.e. whether B or P shall be returned)</param>
        /// <returns>Depending on the normalization, a betweenness preference matrix B or the normalized version P will be returned</returns>
        public static double[,] GetUncorrelatedBetweennessPrefMatrix(TemporalNetwork temp_net, string x, out Dictionary <string, int> index_pred, out Dictionary <string, int> index_succ)
        {
            // Use a mapping of indices to node labels
            index_pred = new Dictionary <string, int>();
            index_succ = new Dictionary <string, int>();

            // Compute the matrix from the weighted ego network
            return(GetUncorrelatedBetweennessPrefMatrix(temp_net.AggregateNetwork, x, out index_pred, out index_succ));
        }
Beispiel #4
0
        /// <summary>
        /// Creates a temporal network instance from an ordered sequence of edges
        /// </summary>
        /// <param name="sequence">An ordered sequence of edges</param>
        /// <returns>An instance of a temporal network</returns>
        public static TemporalNetwork FromEdgeSequence(List <Tuple <string, string> > sequence)
        {
            TemporalNetwork net  = new TemporalNetwork();
            int             time = 0;

            foreach (Tuple <string, string> t in sequence)
            {
                net.AddTemporalEdge(time++, t.Item1, t.Item2);
            }
            return(net);
        }
        /// <summary>
        /// Computes the (scalar) betwenness preference of a node
        /// </summary>
        /// <param name="temp_net">The temporal network for which to compute betweenness preference</param>
        /// <param name="x">The node for which to compute betweenness preference</param>
        /// <returns>The betweenness preference, defined as the mutual information of the source and target of two-paths</returns>
        public static double GetBetweennessPref(TemporalNetwork temp_net, string x)
        {
            // This will be used to store the index mappings in the betweenness preference matrix
            Dictionary <string, int> index_pred;
            Dictionary <string, int> index_succ;

            // Compute the normalized betweenness preference matrix of x according to equation (2) and (3)
            double[,] P = GetBetweennessPrefMatrix(temp_net, x, out index_pred, out index_succ);

            return(GetBetweennessPref(temp_net.AggregateNetwork, x, P));
        }
Beispiel #6
0
        /// <summary>
        /// Creates a random temporal network by shuffling the edges present in an original weighted network
        /// </summary>
        /// <param name="net">The weighted network to draw the microstate from</param>
        /// <param name="length">The length of the sequence in terms of the number of time-stamped interactions</param>
        /// <returns></returns>
        public static TemporalNetwork ShuffleEdges(TemporalNetwork 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 network
            length = length > 0 ? length : (int)net.AggregateNetwork.CumulativeWeight;

            int lcm = 1;


            foreach (var twopath in net.TwoPathWeights.Keys)
            {
                int whole, numerator, denominator;
                MathHelper.RoundToMixedFraction(net.TwoPathWeights[twopath], precision, out whole, out numerator, out denominator);
                lcm = MathHelper.LCM(lcm, denominator);
            }

            // Collect edges in two sampling sets for in and outgoing edges of two paths
            List <Tuple <string, string> > in_edges  = new List <Tuple <string, string> >();
            List <Tuple <string, string> > out_edges = new List <Tuple <string, string> >();

            string[] split = null;

            foreach (var twopath in net.TwoPathWeights.Keys)
            {
                for (int k = 0; k < Math.Round(net.TwoPathWeights[twopath] * lcm); k++)
                {
                    split = twopath.Split(',');
                    in_edges.Add(new Tuple <string, string>(split[0], split[1]));
                    out_edges.Add(new Tuple <string, string>(split[1], split[2]));
                }
            }

            TemporalNetwork output = new TemporalNetwork();
            int             l      = 0;

            while (l < length)
            {
                // Draw edges uniformly at random and add them to temporal network
                var edge1 = in_edges.ElementAt(rand.Next(in_edges.Count));
                Tuple <string, string> edge2 = null;
                while (edge2 == null)
                {
                    edge2 = out_edges.ElementAt(rand.Next(out_edges.Count));
                    if (edge1.Item2 != edge2.Item1)
                    {
                        edge2 = null;
                    }
                }

                // Add to the output network
                output.AddTemporalEdge(l++, edge1.Item1, edge1.Item2);
                output.AddTemporalEdge(l++, edge2.Item1, edge2.Item2);
            }
            return(output);
        }
        /// <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);
        }
Beispiel #8
0
        /// <summary>
        /// Saves a temporal network to a file
        /// </summary>
        /// <param name="path">The path to which the file shall be saved. Any existing file will be overwritten silently.</param>
        /// <param name="net">The temporal network to save.</param>
        public static void SaveToFile(string path, TemporalNetwork net)
        {
            StringBuilder sb = new StringBuilder();

            sb.AppendLine("time node1 node2");

            foreach (int t in net.Keys)
            {
                foreach (var edge in net[t])
                {
                    sb.AppendLine(t + " " + edge.Item1 + " " + edge.Item2);
                }
            }

            System.IO.File.WriteAllText(path, sb.ToString());
        }
        /// <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);
        }
        /// <summary>
        /// Computes the betweenness preference matrix of a node based on the set of two-paths of a node.
        /// By this we essentially implement equations (1) and (2).
        /// If additionally the normalization parameter is set, equation (3) will be computed.
        /// </summary>
        /// <param name="temp_net">The temporal network to compute betweeness preference for</param>
        /// <param name="x">The node for which to compute the betweenness preference matrix</param>
        /// <param name="ego_net">The weighted, aggregate ego network</param>
        /// <param name="index_pred">A mapping of nodes to columns in the betweenness preference matrix</param>
        /// <param name="index_succ">A mapping of nodes to rows in the betweenness preference matrix</param>
        /// <param name="normalize">Whether or not to normalize the matrix, i.e. whether B (eq. 2) or P (eq. 3) shall be returned</param>
        /// <returns>Depending on the normalization, a betweenness preference matrix B or the normalized version P will be returned</returns>
        public static double[,] GetBetweennessPrefMatrix(TemporalNetwork temp_net,
                                                         string x,
                                                         out Dictionary <string, int> index_pred,
                                                         out Dictionary <string, int> index_succ,
                                                         bool normalized = true)
        {
            // Use a mapping of indices to node labels
            index_pred = new Dictionary <string, int>();
            index_succ = new Dictionary <string, int>();

            // Create an empty matrix
            double[,] B = new double[temp_net.AggregateNetwork.GetIndeg(x), temp_net.AggregateNetwork.GetOutdeg(x)];

            // Create the index-to-node mapping
            int i = 0;

            foreach (string u in temp_net.AggregateNetwork.GetPredecessors(x))
            {
                index_pred[u] = i++;
            }

            i = 0;
            foreach (string w in temp_net.AggregateNetwork.GetSuccessors(x))
            {
                index_succ[w] = i++;
            }

            // Here we implement equation (1) and (2), i.e. we normalize PER TIME STEP
            foreach (var t in temp_net.TwoPathsByNode[x].Keys)
            {
                foreach (var two_path in temp_net.TwoPathsByNode[x][t])
                {
                    B[index_pred[two_path.Item1], index_succ[two_path.Item2]] += 1d / (double)temp_net.TwoPathsByNode[x][t].Count;
                }
            }

            // This is equation 3, i.e. we normalize ACROSS THE MATRIX
            if (normalized)
            {
                return(NormalizeMatrix(x, temp_net.AggregateNetwork, B));
            }
            else
            {
                return(B);
            }
        }
Beispiel #11
0
        /// <summary>
        /// Reads a temporal network from a file containing lines with trigrams a,b,c
        /// </summary>
        /// <param name="path">The path to the data file</param>
        /// <returns>A temporal network instance</returns>
        public static TemporalNetwork FromTrigramsFile(string path)
        {
            TemporalNetwork temp_net = new TemporalNetwork();

            string[] lines = System.IO.File.ReadAllLines(path);

            // if empty
            if (lines.Length == 0)
            {
                return(temp_net);
            }

            char[] split_chars = new char[] { ' ', '\t', ';', ',' };
            char   split_char  = ' ';

            // detect split character
            string[] line = null;
            foreach (char c in split_chars)
            {
                line = lines[0].Split(c);
                if (line.Length == 3)
                {
                    split_char = c;
                    break;
                }
            }

            // Read trigrams and generate temporal network representation
            int time = 0;

            for (int i = 0; i < lines.Length; i++)
            {
                string[] components = lines[i].Split(split_char);
                temp_net.AddTemporalEdge(time, components[0], components[1]);
                temp_net.AddTemporalEdge(time + 1, components[1], components[2]);
                time = time + 3;
            }

            return(temp_net);
        }
Beispiel #12
0
        /// <summary>
        /// Reads an edge sequence from a file containing ordered edges and creates a temporal network instance. The file is
        /// assumed to have one line per edge, each possibly consisting of several colums and separated by a special delimiter character.
        /// The caller can specify which (zero-based) column number indicate the source and the target of an interaction. If no parameters
        /// are specified apart from the path, each line in the file is assumed to contain two strings representing the source and target of an
        /// edge in the first two columns separated by a space. No header line is assumed by default.
        /// </summary>
        /// <param name="path">The path of the file containing the edge sequence.</param>
        /// <param name="source_col">The zero-based column number on the source node of an edge. 0 by default</param>
        /// <param name="target_col">The zero-based column number on the target node of an edge. 1 by default</param>
        /// <param name="header">Whether or not there is a header line that shall be ignored</param>
        /// <param name="split_char">The character used to separate columns in each line</param>
        /// <returns>An instance of a temporal network corresponding to the input sequence</returns>
        public static TemporalNetwork ReadFromFile(string path, bool undirected = false)
        {
            TemporalNetwork temp_net = new TemporalNetwork();

            // Read all data from file
            string[] lines = System.IO.File.ReadAllLines(path);

            // If empty ...
            if (lines.Length == 0)
            {
                return(temp_net);
            }

            // Extract header
            char[] split_chars = new char[] { ' ', '\t', ';', ',' };
            char   split_char  = ' ';

            // Detect the correct separator character in CSV format
            string[] header = null;
            foreach (char c in split_chars)
            {
                header = lines[0].Split(c);
                if (header.Length >= 2 && ((header.Contains("node1") && header.Contains("node2")) || (header.Contains("source") && header.Contains("target"))))
                {
                    split_char = c;
                    break;
                }
            }

            if (header.Length < 2)
            {
                return(temp_net);
            }

            // Extract indices of columns
            int time_ix   = -1;
            int source_ix = -1;
            int target_ix = -1;

            for (int i = 0; i < header.Length; i++)
            {
                if (header[i] == "time")
                {
                    time_ix = i;
                }
                else if (header[i] == "node1" || header[i] == "source")
                {
                    source_ix = i;
                }
                else if (header[i] == "node2" || header[i] == "target")
                {
                    target_ix = i;
                }
            }

            // If there is no source and target column
            if (source_ix < 0 || target_ix < 0)
            {
                return(temp_net);
            }
            for (int i = 1; i < lines.Length; i++)
            {
                string[] components = lines[i].Split(split_char);
                if (components[source_ix] != "" && components[target_ix] != "")
                {
                    // If there is no explicit time, just consider each edge occuring at consecutive time steps
                    int t = time_ix >= 0 ? int.Parse(components[time_ix]) : i;

                    temp_net.AddTemporalEdge(t, components[source_ix], components[target_ix]);
                    if (undirected)
                    {
                        temp_net.AddTemporalEdge(t, components[target_ix], components[source_ix]);
                    }
                }
            }
            return(temp_net);
        }
        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);
        }
        /// <summary>
        /// Runs a simple SI spreading on a given temporal network and returns the dynamics of the infections
        /// </summary>
        /// <param name="temp_net">The temporal network to use</param>
        /// <param name="p">The infection probability (default is 1)</param>
        /// <returns>An enumerable of infection numbers, each entry giving the number of infected individuals at a certain time of the simulation</returns>
        public static string RunSpreading(TemporalNetwork temp_net, out string times, double p = 1d)
        {
            // Which nodes are already infected?
            Dictionary <string, bool> discovered = new Dictionary <string, bool>();
            Dictionary <int, int>     infections = new Dictionary <int, int>(temp_net.Count);

            // Initialize
            foreach (string s in temp_net.AggregateNetwork.Vertices)
            {
                discovered[s] = false;
            }

            // Build the initial matrix of fastestPathLengths
            Dictionary <string, int> indices = new Dictionary <string, int>(temp_net.AggregateNetwork.VertexCount);

            short[,] fastestPathLengths      = new short[temp_net.AggregateNetwork.VertexCount, temp_net.AggregateNetwork.VertexCount];
            short[,] fastestPath_mid_Lengths = new short[temp_net.AggregateNetwork.VertexCount, temp_net.AggregateNetwork.VertexCount];
            uint[,] fastestPathDurations     = new uint[temp_net.AggregateNetwork.VertexCount, temp_net.AggregateNetwork.VertexCount];

            // Build the indices
            int i = 0;

            foreach (string s in temp_net.AggregateNetwork.Vertices)
            {
                indices[s] = i++;
            }

            // Initialize with maximum values ...
            foreach (string s in temp_net.AggregateNetwork.Vertices)
            {
                foreach (string d in temp_net.AggregateNetwork.Vertices)
                {
                    fastestPathLengths[indices[s], indices[d]]      = short.MaxValue;
                    fastestPath_mid_Lengths[indices[s], indices[d]] = short.MaxValue;
                    fastestPathDurations[indices[s], indices[d]]    = uint.MaxValue;
                }
            }

            // Run a spreading process starting at each node in the network ...
            foreach (var start in temp_net.AggregateNetwork.Vertices)
            {
                // Reset the infected state for all
                foreach (string s in temp_net.AggregateNetwork.Vertices)
                {
                    discovered[s] = false;
                }

                // Infect the start node
                int discovered_n = 1;
                discovered[start] = true;
                fastestPathLengths[indices[start], indices[start]]   = 0;
                fastestPathDurations[indices[start], indices[start]] = 0;

                try
                {
                    // Get the first time stamp where the start node was source of two path
                    var start_time = temp_net.TwoPathsByStartTime.Keys.First(z =>
                    {
                        foreach (string twopath in temp_net.TwoPathsByStartTime[z])
                        {
                            if (twopath.StartsWith(start))
                            {
                                return(true);
                            }
                        }
                        return(false);
                    });
                    uint t_ = (uint)start_time;

                    // Create a list of ordered time stamps starting with the first activity of the start node
                    var time_stamps = from x in temp_net.TwoPathsByStartTime.Keys where x >= start_time orderby x ascending select x;

                    // Extract all paths consisting of "two path" building blocks
                    foreach (int t in time_stamps)
                    {
                        // A path continues if the source node of a two-path has already been discovered
                        foreach (var two_path in temp_net.TwoPathsByStartTime[t])
                        {
                            // Get the three components of the two path
                            string[] comps = two_path.Split(',');

                            // Record the geodesic distance between the start and the middle node comps[1]
                            fastestPath_mid_Lengths[indices[start], indices[comps[1]]] = (short)Math.Min(fastestPath_mid_Lengths[indices[start], indices[comps[1]]], fastestPathLengths[indices[start], indices[comps[0]]] + 1);

                            // If the target node of a two path has not been discovered before, we just discovered a new fastest time-respecting path!
                            if (discovered[comps[0]] && !discovered[comps[2]])
                            {
                                // Add to nodes already discovered
                                discovered_n++;
                                discovered[comps[2]] = true;

                                // Record geodesic distance of fastest time-respecting path
                                fastestPathLengths[indices[start], indices[comps[2]]] = (short)(fastestPathLengths[indices[start], indices[comps[0]]] + 2);

                                // Record temporal length of fastest time-respecting path
                                fastestPathDurations[indices[start], indices[comps[2]]] = (uint)(t - start_time);
                            }
                        }
                        // Stop as soon as all nodes have been discovered
                        if (discovered_n == temp_net.AggregateNetwork.VertexCount)
                        {
                            break;
                        }

                        // Advance the time by two
                        t_ += 2;
                    }
                }
                catch (Exception) {
                    // In this case, a start node is never the source of two-path, so we just ignore it ...
                }
            }

            // Aggregate the matrices
            foreach (string s in temp_net.AggregateNetwork.Vertices)
            {
                foreach (string d in temp_net.AggregateNetwork.Vertices)
                {
                    fastestPathLengths[indices[s], indices[d]] = Math.Min(fastestPathLengths[indices[s], indices[d]], fastestPath_mid_Lengths[indices[s], indices[d]]);
                }
            }

            StringBuilder sb   = new StringBuilder();
            StringBuilder sb_t = new StringBuilder();

            var nodes = from n in temp_net.AggregateNetwork.Vertices.AsParallel() orderby n ascending select n;

            foreach (string s in nodes)
            {
                foreach (string d in nodes)
                {
                    sb.Append(fastestPathLengths[indices[s], indices[d]] + "\t");
                    sb_t.Append(fastestPathDurations[indices[s], indices[d]] + "\t");
                }
                sb.Append("\n");
                sb_t.Append("\n");
            }
            times = sb_t.ToString();
            return(sb.ToString());
        }
Beispiel #15
0
        /// <summary>
        /// Creates a TikZ representation of the temporal unfolding of the temporal network
        /// </summary>
        /// <param name="path">The path to which to write the tikz file</param>
        /// <param name="temp_net">The temporal network that shall be exported</param>
        public static void CreateTikzUnfolding(string path, string between_node, TemporalNetwork temp_net)
        {
            WeightedNetwork net = WeightedNetwork.FromTemporalNetwork(temp_net);

            StringBuilder strB = new StringBuilder();

            strB.AppendLine("\\newcounter{a}");

            strB.AppendLine("\\begin{tikzpicture}[->,>=stealth',auto,scale=0.5, every node/.style={scale=0.9}]");
            strB.AppendLine("\\tikzstyle{node} = [fill=lightgray,text=black,circle]");
            strB.AppendLine("\\tikzstyle{v} = [fill=black,text=white,circle]");
            strB.AppendLine("\\tikzstyle{dst} = [fill=lightgray,text=black,circle]");
            strB.AppendLine("\\tikzstyle{lbl} = [fill=white,text=black,circle]");

            string last = "";

            foreach (string v in net.Vertices.OrderBy(s => s))
            {
                if (last == "")
                {
                    strB.AppendLine("\\node[lbl]                     (" + v + "-0)   {$" + v + "$};");
                }
                else
                {
                    strB.AppendLine("\\node[lbl,right=0.5cm of " + last + "-0] (" + v + "-0)   {$" + v + "$};");
                }
                last = v;
            }

            strB.AppendLine("\\setcounter{a}{0}");
            strB.AppendLine("\\foreach \\number in {1,...," + (temp_net.Length + 1) + "}{");
            strB.AppendLine("\\setcounter{a}{\\number}");
            strB.AppendLine("\\addtocounter{a}{-1}");
            strB.AppendLine("\\pgfmathparse{\\thea}");
            foreach (string v in net.Vertices)
            {
                if (v != between_node)
                {
                    strB.AppendLine("\\node[node,below=0.3cm of " + v + "-\\pgfmathresult]   (" + v + "-\\number) {};");
                }
                else
                {
                    strB.AppendLine("\\node[v,below=0.3cm of " + v + "-\\pgfmathresult]     (" + v + "-\\number) {};");
                }
            }
            strB.AppendLine("\\node[lbl,left=0.5cm of " + net.Vertices.OrderBy(s => s).ElementAt(0) + "-\\number]    (col-\\pgfmathresult) {$t=$\\number};");
            strB.AppendLine("}");
            strB.AppendLine("\\path[->,thick]");
            int i = 1;

            foreach (var t in temp_net.Keys)
            {
                foreach (var edge in temp_net[t])
                {
                    strB.AppendLine("(" + edge.Item1 + "-" + (t + 1) + ") edge (" + edge.Item2 + "-" + (t + 2) + ")");
                    i++;
                }
            }
            strB.AppendLine(";");
            strB.AppendLine("\\end{tikzpicture} ");

            System.IO.File.WriteAllText(path, strB.ToString());
        }
Beispiel #16
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);
        }