/// <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); }
// 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> /// Moves the walker /// </summary> /// <returns>Node where walker moved onto.</returns> public Node Next() { if (mathUtils.Test(jump)) { current = Utils.Extensions.GetAtRandom(mnet.GetNodes()); justJumped = true; noAction = false; } else { Layer flattened = mnet.GetLayer("flattenedNetwork"); var layerId = layerIds[current.Layer.Id]; var layerIdTest = mathUtils.Test(transitions, layerId); var newLayer = mnet.GetLayers().Except(new HashSet <Layer>() { flattened }).ElementAt(layerIdTest); if (current.Layer == newLayer) { // Inside same layer. var neigh = mnet.Neighbors(current, EdgeMode.Out); if (neigh.Count == 0) { // Cant move. // No action. noAction = true; return(current); } var rand = mathUtils.GetRandomInt(neigh.Count); current = neigh.ElementAt(rand); justJumped = false; noAction = false; } else { // Changing to another node with this actor. var nextNode = mnet.GetNode(current.Actor, newLayer); if (nextNode == null) { // No other nodes with this actor. noAction = true; return(current); } current = nextNode; justJumped = false; noAction = false; } } return(current); }
/// <summary> /// Returns degree on provided layer. /// </summary> /// <param name="mnet">Multlayer network model.</param> /// <param name="actor">Actor.</param> /// <param name="layer">Single Layer.</param> /// <param name="edgeMode">In / Out / All, mode of edge.</param> /// <returns>Degree of the Actor.</returns> public int Degree(MultilayerNetwork mnet, Actor actor, Layer layer, EdgeMode edgeMode) { var degree = 0; // All nodes with this ACTOR. foreach (var node in mnet.GetNodes(actor)) { // All neighbors of this NODE, with the correct edgeMode (In / Out / Or both). foreach (var neighbor in mnet.Neighbors(node, edgeMode)) { // We go through all his neighbors, and if the neighbor is on the provided layer // we increase his degree by 1. if (neighbor.Layer == layer) { degree += 1; } } } return(degree); }
private MathUtils mathUtils = MathUtils.Instance; //new MathUtils(); #region Degree /// <summary> /// Returns degree of the actor on provided layers. /// </summary> /// <param name="mnet">Multilayer network model.</param> /// <param name="actor">Actor.</param> /// <param name="layers">HashSet of layers.</param> /// <param name="edgeMode">In / Out / All, mode of edge.</param> /// <returns>Degree of the Actor.</returns> public int Degree(MultilayerNetwork mnet, Actor actor, HashSet <Layer> layers, EdgeMode edgeMode) { var degree = 0; // All nodes with this ACTOR. foreach (var node in mnet.GetNodes(actor)) { // All neighbors of this NODE, with the correct edgeMode (In / Out / Or both). foreach (var neighbor in mnet.Neighbors(node, edgeMode)) { // If there is a layer with this neighbor it means, that this NODE has this neighbor // on this layer, so we increase his degree by 1. if (layers.Contains(neighbor.Layer)) { degree += 1; } } } return(degree); }
/// <summary> /// Returns neighbors of given actor on given layer with specific edgemode. /// </summary> /// <param name="mnet">Multilayer network model.</param> /// <param name="actor">Actor to get neighbors of.</param> /// <param name="layer">Layer to get neighbors on.</param> /// <param name="edgeMode">In/Out/InOut edges.</param> /// <returns>Neighbors of given actor on given layer with specific edgemode.</returns> private HashSet <Actor> Neighbors(MultilayerNetwork mnet, Actor actor, Layer layer, EdgeMode edgeMode = EdgeMode.InOut) { // Empty hashset to add checked actors. var neighbors = new HashSet <Actor>(); // All nodes with this ACTOR. foreach (var node in mnet.GetNodes(actor)) { // All neighbors of this NODE, with the correct edgeMode (In / Out / Or both). foreach (var neighbor in mnet.Neighbors(node, edgeMode)) { // If there is a layer with this neighbor it means, that this NODE has this neighbor // on this layer, so we increase his degree by 1 IF actor on this node is still available. if (layer == neighbor.Layer) { neighbors.Add(neighbor.Actor); } } } return(neighbors); }
/// <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); }
/// <summary> /// Returns dictionary, where actors are keys and their occupation centrality is 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> /// <param name="numSteps">Maximum number of steps, if not specified it is number of edges times 100.</param> /// <param name="initialNode">Starting node for the random walker.</param> /// <returns>Dictionary, where actors are keys and their occupation centrality is value.</returns> public Dictionary <Actor, int> Occupation(MultilayerNetwork mnet, double jump = 0.2, double[][] transitions = null, int numSteps = 0, Node initialNode = null) { // If not set number of steps, set default number of steps to 100 times number of edges. // This was used in the R library. if (numSteps == 0) { numSteps = mnet.Edges.Count * 100; } // 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); if (initialNode == null) { rw.SetInitialNode(mnet.GetNodes().FirstOrDefault()); } else { rw.SetInitialNode(initialNode); } var occupation = new Dictionary <Actor, int>(); var node = rw.Now(); var flag = true; while (numSteps-- > 0) { if (flag) { // Initial node. flag = false; } else { node = rw.Next(); } if (!rw.Action()) { continue; } if (rw.Jumped()) { // Jumped to a new node - not counting. } else { // If actor is not present yet. if (!occupation.ContainsKey(node.Actor)) { occupation.Add(node.Actor, 0); } // Then increase his occupancy. occupation[node.Actor]++; } } return(occupation); }
private IO io = IO.Instance; //new IO(); public void TransformationTest() { var transform = new Transformation.Transformation(); Console.WriteLine("Transformation test begin..."); Console.WriteLine("Creating the network..."); var mnet = new MultilayerNetwork("Transformation Test"); var a1 = mnet.AddActor("a1"); var a2 = mnet.AddActor("a2"); var a3 = mnet.AddActor("a3"); var a4 = mnet.AddActor("a4"); var a5 = mnet.AddActor("a5"); var a6 = mnet.AddActor("a6"); var i1 = mnet.AddActor("I1"); var i2 = mnet.AddActor("I2"); var i3 = mnet.AddActor("I3"); var L1 = mnet.AddLayer("People 1", EdgeDirectionality.Undirected); var L2 = mnet.AddLayer("People 2", EdgeDirectionality.Undirected); var people = new HashSet <Layer> { L1, L2 }; var L3 = mnet.AddLayer("Institutions", EdgeDirectionality.Undirected); var a1l1 = mnet.AddNode(a1, L1); var a2l1 = mnet.AddNode(a2, L1); var a3l1 = mnet.AddNode(a3, L1); var a4l1 = mnet.AddNode(a4, L1); var a5l1 = mnet.AddNode(a5, L1); var a1l2 = mnet.AddNode(a1, L2); var a2l2 = mnet.AddNode(a2, L2); var a3l2 = mnet.AddNode(a3, L2); var a4l2 = mnet.AddNode(a4, L2); var a5l2 = mnet.AddNode(a5, L2); var i1l3 = mnet.AddNode(i1, L3); var i2l3 = mnet.AddNode(i2, L3); var i3l3 = mnet.AddNode(i3, L3); mnet.AddEdge(a1l1, a2l1); mnet.AddEdge(a1l1, a3l1); mnet.AddEdge(a1l2, a2l2); mnet.AddEdge(a3l2, a4l2); mnet.AddEdge(a1l2, i1l3); mnet.AddEdge(a2l2, i1l3); mnet.AddEdge(a2l2, i2l3); mnet.AddEdge(a3l2, i2l3); mnet.AddEdge(a4l2, i2l3); mnet.AddEdge(a5l2, i3l3); Console.WriteLine("Creating network end."); Console.WriteLine("Flattening L1 and L2 (unweighted, only existing actors)..."); var f1 = transform.FlattenUnweighted(mnet, "flattened1", people, false, false); if (mnet.IsDirected(f1, f1)) { Console.WriteLine("Layer should be undirected"); } if (mnet.GetNodes(f1).Count != 5) { Console.WriteLine("Wrong number of nodes"); } if (mnet.GetEdges(f1, f1).Count != 3) { Console.WriteLine("Wrong number of edges"); } Console.WriteLine("Done! " + mnet.ToString()); Console.WriteLine(); Console.WriteLine("Flattening L1 and L2 (unweighted, all actors)..."); var f2 = transform.FlattenUnweighted(mnet, "flattened2", people, false, true); if (mnet.IsDirected(f2, f2)) { Console.WriteLine("Layer should be undirected"); } if (mnet.GetNodes(f2).Count != 9) { Console.WriteLine("Wrong number of nodes, {0}\t != {1}", mnet.GetNodes(f2).Count, 9); } if (mnet.GetEdges(f2, f2).Count != 3) { Console.WriteLine("Wrong number of edges"); } Console.WriteLine("Done! " + mnet.ToString()); Console.WriteLine(); Console.WriteLine("Transformation test end."); Console.ReadLine(); }