Esempio n. 1
0
        // Do for each layer random walk for every pair of nodes on the layer.
        // Average the value over all possible starting layers for the actor.

        /// <summary>
        /// Returns dictionary, where actors are keys and random walk betweenness centrality is their value.
        /// </summary>
        /// <param name="mnet">Multilayer network.</param>
        /// <param name="jump">Jump probability for random walker, default value is 0.2.</param>
        /// <param name="transitions">Matrix of transition probabilities between layers. Default is uniform for each pair of layers.</param>
        /// <returns>Dictionary, where actors are keys and random walk betweenness centrality is their value.</returns>
        public ConcurrentDictionary <Actor, int> RandomWalkBetweenness(MultilayerNetwork mnet, double jump = 0.2, double[][] transitions = null)
        {
            // If not set transitions, use uniform probability for every layer.
            transitions = new double[mnet.Layers.Count][];

            for (int i = 0; i < mnet.Layers.Count; i++)
            {
                transitions[i] = new double[mnet.Layers.Count];
                for (int j = 0; j < transitions[i].Length; j++)
                {
                    transitions[i][j] = 1.0 / transitions[i].Length;
                }
            }

            var rw = new Walker(mnet, jump, transitions);

            // Number of random walks passing through given actor.
            var actorRandomWalkCount = new ConcurrentDictionary <Actor, int>();

            //foreach (var a in mnet.GetActors())
            Parallel.ForEach(mnet.GetActors(), (a) =>
            {
                actorRandomWalkCount.TryAdd(a, 0);
            });

            // Do random walk between every pair of nodes.
            // Average it over the layers.
            var nodes = mnet.GetNodes().ToArray();

            for (int i = 0; i < nodes.Length - 1; i++)
            {
                //for (int j = i + 1; j < nodes.Length; j++)
                Parallel.For(i + 1, nodes.Length, j =>
                {
                    RandomWalkActors(rw, nodes[i], nodes[j], ref actorRandomWalkCount);
                });
            }


            var temp = new ConcurrentDictionary <Actor, int>(actorRandomWalkCount);

            // Average it - divide by number of nodes with the corresponding actor.
            //foreach (var a in temp.Keys)
            Parallel.ForEach(temp.Keys, (a) =>
            {
                if (mnet.NodesByActor.ContainsKey(a.Id))
                {
                    var nodesCount          = mnet.NodesByActor[a.Id].Count;
                    actorRandomWalkCount[a] = temp[a] / nodesCount;
                }
            });

            return(actorRandomWalkCount);
        }
        /// <summary>
        /// Utility method, for creating new layer in the multilayer network.
        /// </summary>
        /// <param name="mnet">Multilayer network.</param>
        /// <param name="newLayerName">Name of the new layer.</param>
        /// <param name="layers">Layers of the network.</param>
        /// <param name="forceDirected">True if new edges should be directed, false if not.</param>
        /// <param name="forceActors">True if all actors should be on the new layer, false if not.</param>
        /// <returns>Newly created layer.</returns>
        private Layer createLayer(MultilayerNetwork mnet, string newLayerName, HashSet <Layer> layers,
                                  bool forceDirected, bool forceActors)
        {
            var directed = forceDirected;

            // Check if there are any directed layers, if YES, then new layer will be directed as well.
            if (!directed)
            {
                foreach (var layer1 in layers)
                {
                    foreach (var layer2 in layers)
                    {
                        if (mnet.IsDirected(layer1, layer2))
                        {
                            directed = true;
                            break;
                        }
                    }

                    if (directed)
                    {
                        break;
                    }
                }
            }

            var dir      = directed ? EdgeDirectionality.Directed : EdgeDirectionality.Undirected;
            var newLayer = mnet.AddLayer(newLayerName, dir);

            if (newLayer == null)
            {
                throw new ArgumentException("Layer " + newLayerName + " already exists.");
            }

            if (forceActors)
            {
                foreach (var actor in mnet.GetActors())
                {
                    mnet.AddNode(actor, newLayer);
                }
            }
            else
            {
                foreach (var layer in layers)
                {
                    foreach (var node in mnet.GetNodes(layer))
                    {
                        mnet.AddNode(node.Actor, newLayer);
                    }
                }
            }

            return(newLayer);
        }
Esempio n. 3
0
        /// <summary>
        /// Returns dictionary, where actors are keys and their random walk closeness centrality is value.
        /// </summary>
        /// <param name="mnet">Multilayer network.</param>
        /// <param name="jump">Jump probability, default value is 0.2.</param>
        /// <param name="transitions">Matrix of transition probabilities between layers. Default is uniform for each pair of layers.</param>
        /// <returns>Dictionary, where actors are keys and their random walk closeness centrality is value.</returns>
        public ConcurrentDictionary <Actor, double> RandomWalkCloseness(MultilayerNetwork mnet, double jump = 0.2, double[][] transitions = null)
        {
            // If not set transitions, use uniform probability for every layer.
            transitions = new double[mnet.Layers.Count][];

            for (int i = 0; i < mnet.Layers.Count; i++)
            {
                transitions[i] = new double[mnet.Layers.Count];
                for (int j = 0; j < transitions[i].Length; j++)
                {
                    transitions[i][j] = 1.0 / transitions[i].Length;
                }
            }

            var rw = new Walker(mnet, jump, transitions);

            // Create adjacency matrix for actors.
            // Every actor has its Id.
            // First Id starts at 0.
            // Last Id is actors count - 1.
            var adjActors = new int[mnet.GetActors().Count][];

            for (int i = 0; i < mnet.Actors.Count; i++)
            {
                adjActors[i] = new int[mnet.Actors.Count];
            }

            // Traverse the matrix for every pair of nodes.
            var nodes = mnet.GetNodes().ToArray();

            for (int i = 0; i < nodes.Length - 1; i++)
            {
                //for (int j = i + 1; j < nodes.Length; j++)
                Parallel.For(i + 1, nodes.Length, (j) =>
                {
                    //Console.WriteLine(i + ":" + j);
                    // Do random walk from i to j.
                    // And save only the first walk length.
                    var walkLen = RandomWalkSteps(rw, nodes[i], nodes[j]);

                    // Use only first walk.
                    if (adjActors[nodes[i].Actor.Id][nodes[j].Actor.Id] == 0)
                    {
                        adjActors[nodes[i].Actor.Id][nodes[j].Actor.Id] = walkLen;
                        adjActors[nodes[j].Actor.Id][nodes[i].Actor.Id] = walkLen;
                    }
                });
            }

            var actorById = new ConcurrentDictionary <int, Actor>();

            //foreach (var actor in mnet.GetActors())
            Parallel.ForEach(mnet.GetActors(), (a) =>
            {
                actorById.TryAdd(a.Id, a);
            });

            // Actual Clonesess centrality.
            // Harmonic mean distance.
            var closenessByActor = new ConcurrentDictionary <Actor, double>();

            for (int i = 0; i < adjActors[0].Length; i++)
            {
                double sum = 0;
                //for (int j = 0; j < adjActors[0].Length; j++)
                Parallel.For(0, adjActors[0].Length, (j) =>
                {
                    if (i == j)
                    {
                        adjActors[i][j] = 0;
                    }
                    else
                    {
                        if (adjActors[i][j] != 0)
                        {
                            sum += 1.0 / adjActors[i][j];
                        }
                    }
                });

                double closeness = (1.0 / (adjActors[0].Length - 1)) * sum;
                closenessByActor[actorById[i]] = closeness;
            }

            return(closenessByActor);
        }