Periodic and Aperiodic directed graphs - graph

I am a bit confused on how to distinguish a directed graph to be aperiodic or periodic. Wikipedia says this about aperiodic graphs:
'In the mathematical area of graph theory, a directed graph is said to be aperiodic if there is no integer k > 1 that divides the length of every cycle of the graph.'
For example is the graph below aperiodic or periodic. I believe the graph is not periodic but by wikipedia's definition it is periodic since integer k = 2 divides all cycles in the graph (AC and ACDB)
It would be great if someone could provide a method to distinguish if a graph is aperiodic or periodic. Maybe provide some examples of periodic and aperiodic graphs to help explain.
Thank you.

Here's a short python implementation based on Networkx, for finding wether a graph is periodic:
import networkx as nx
from math import gcd
from functools import reduce
G = nx.DiGraph()
G.add_edges_from([('A', 'C'), ('C', 'D'), ('D', 'B'), ('B', 'A'), ('C', 'A')])
cycles = list(nx.algorithms.cycles.simple_cycles(G))
cycles_sizes = [len(c) for c in cycles]
cycles_gcd = reduce(gcd, cycles_sizes)
is_periodic = cycles_gcd > 1
print("is_periodic: {}".format(is_periodic))
The code does the following:
Build the graph from your example (by specifying the edges).
List all cycles (AC and ACDB).
List all cycles sizes [2, 4].
Find greatest common denominator (GCD).
If GCD is 1 it means the graph is aperiodic, otherwise it's periodic by definition.
The graph you have given above in not aperiodic as it has the period of 2. (i.e. every node can return to itself in multiples of 2 steps)
You can play with different examples to get better intuition, and also visualize your graph by adding:
import matplotlib.pyplot as plt
nx.draw_networkx(G, with_labels=True)
plt.show()

Related

How to get the length of lines representing edges in the plot of graph after layout out using networkx

For a graph in networkx, I have made a layout to draw a network graph using code below:
data = pd.read_csv('data\\email-dept3.csv')
edges = [edge for edge in zip(data['source'],data['target'])]
print(len(edges))
G = nx.Graph()
G.add_edges_from(edges)
node_pos = nx.kamada_kawai_layout(G)
#I want to get the edge length as one attributes, but I don't know how to code this function
edge_length = calculate_edge_length()
nx.draw_networkx_nodes(G,node_pos,**options)#draw nodes
[nx.draw_networkx_edges(G,node_pos,edgelist=[key],alpha=np.amin([1,value*100]),width=2) for key,value in cent.items()]
plt.show()
And the result is:
What I want to do is get the every edge's length in this graph. Because after layout, every node has a position in screen, and the edge has its length according to its two nodes' position. But in networkx's API, I can't find the method to get the edge's length. And I also don't know how to calculate this value.
If you need more information, please contact me.
I am trying all kinds of methods to adjust the transparency of edges. The length of line is one of my consideration.
Interesting idea! Seems like a worthwhile experiment; I'll let you decide if it works well or not. :-)
But in networkx's API, I can't find the method to get the edge's length
I think you have to compute them yourself. Fortunately, that's not too hard. Here's an example.
import numpy as np
import pandas as pd
import networkx as nx
import matplotlib.pyplot as plt
plt.rcParams["figure.figsize"] = (10,10)
def example_graph():
"""
Return the classic Karate Club network, but give text labels to the nodes.
"""
labels = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJZKLMNOPQRSTUVWXYZ'
kg = nx.karate_club_graph()
edges = [(labels[i], labels[j]) for i,j in kg.edges()]
G = nx.Graph()
G.add_edges_from(edges)
return G
# Test network
G = example_graph()
# Determine layout node positions
node_pos = nx.kamada_kawai_layout(G)
# Determine edge distances (from the node positions)
node_pos_df = pd.DataFrame(node_pos.values(), columns=['x', 'y'], index=node_pos.keys())
node_pos_df = node_pos_df.rename_axis('label').sort_index()
edges = np.array(G.edges())
u_pos = node_pos_df.loc[edges[:, 0]].values
v_pos = node_pos_df.loc[edges[:, 1]].values
distances = np.linalg.norm(u_pos - v_pos, axis=1)
## Optional: Add the distances as edge attributes
#edge_distances = {(u,v): d for (u,v), d in zip(G.edges(), distances)}
#nx.set_edge_attributes(G, edge_distances, "layout_distance")
# Compute alpha: Set 0.15 as minimum alpha, 1.0 as maximum alpha
d_min, d_max = distances.min(), distances.max()
alphas = 1.0 - 0.85 * (distances - d_min) / (d_max - d_min)
# Draw graph
nx.draw_networkx_nodes(G, node_pos)
nx.draw_networkx_edges(G, node_pos, edgelist=G.edges(), alpha=alphas, width=2)
plt.show()

How to find Global Clustering Coefficient of graph?

I start learning network analysis & its metrics calculation from last week. Don't have enough knowledge. Can anyone check this ?
The formula of finding the global clustering co-efficient is,
C = (3 * Number of Triangles) / (Number of connected triples of vertices)
I calculate the global clustering co-efficient as,
Number of Triangles = 2
(as there are 2 directly connected triangles in the graph i-e Node4->Node5->Node6 and Node1->Node3->Node4)
Number of connected triples of vertices = 4
(as Node1, Node2, Node3 & Node6 have three vertices connected)
C = (3 * 2) / 4 = 1.5
I don't know I do it correctly or not. Can anyone check this ? or correct me If I am wrong
The denominator must count all triples with 2 or 3 edges.
So, the the given graph we have the following triples:
5-4-6
6-5-4, 6-4-2, 6-5-2
4-6-1, 4-5-1, 4-6-3, 4-5-3, 4-1-3, 4-6-5
1-4-3, 1-3-2, 1-4-2
3-4-1, 3-1-7, 3-4-7
7-3-2
2-7-1, 2-1-6, 2-7-6
This gives a total of 20 triples, so the gcc is 2*3/20 = 0.3.
This algorithm is implemented in python's networkx package. The code for this example is:
import networkx as nx
g = nx.Graph()
g.add_edges_from([(5,6), (5,4), (4,6), (4,1), (4,3), (3,1), (3,7), (7,2), (1,2), (6,2)])
print(nx.transitivity(g))

Generating a complete graph in metric space

Please help with the simplest way to generate a complete random weighted undirected graph given size N, so that weights form a metric space (obey triangle inequality). I know there is networkx library but not sure how to do this.
Although #SvenMarnach is correct, I thought I would mention that it is pretty easy to initialize a graph from a distance matrix in networkx:
import numpy as np
import networkx as nx
V = 100 # number of nodes
D = 2 # dimensionality
positions = np.random.rand(V, D)
differences = positions[:, None, :] - positions[None, :, :]
distances = np.sqrt(np.sum(differences**2, axis=-1)) # euclidean
# create a weighted, directed graph in networkx
graph = nx.from_numpy_matrix(distances, create_using=nx.DiGraph())

Computing a pagerank on a weighted graph with absolute weights

I am facing the same issue as expressed in this link (Networkx PageRank - Equal Ranks with Different Weights).
Essentially, I am using networkx to compute the pagerank on a graph. Since, pagerank computation first converts the graph to a right stochastic matrix (all out-going edges are normalised to one).
What I need is a way to not normalise the edge weights. So, If one node as only one outgoing edge with weight 0.1 and another one has only one outgoing edge with weight 0.05, I want this information to be used in the computation of pagerank (rather than being normalized to 1 each).
Does anyone know what could be the right way of modifying pagerank to achieve this.
thanks in advance,
Amit
Maybe you are thinking of what Larry and Sergey called "Personalized PageRank"? You can adjust the weighting of the nodes in the random jump part of the algorithm to create a bias. E.g.
In [1]: import networkx as nx
In [2]: G = nx.DiGraph()
In [3]: G.add_path([1,2,3,4])
In [4]: nx.pagerank_numpy(G)
Out[4]:
{1: 0.11615582303660349,
2: 0.2148882726177166,
3: 0.29881085476166286,
4: 0.370145049584017}
In [5]: nx.pagerank_numpy(G,personalization={1:1,2:10,3:1,4:1})
Out[5]:
{1: 0.031484535189871404,
2: 0.341607206810105,
3: 0.3218506609784609,
4: 0.3050575970215628}
See, for example, the discussion here http://ilpubs.stanford.edu:8090/422/1/1999-66.pdf
I have a graph which is not right stochastic (i.e. edge weights are absolute and consistent across nodes). I changed pagerank implementation of networkx to avoid converting initial matrix to a right stochastic matrix thus giving me the right answer. However, this implies that pagerank doesn't converge as sometimes total sum of edges > 1, but usually rankings are fairly consistent after 30-40 iterations.
In essence, removing this line from the networkx code (algorithms/link_analysis/pagerank_alg.py) did the job:-
W = x.stochastic_graph(D, weight=weight)

Network Modularity Calculations in R

The equation for Network Modularity is given on its wikipedia page (and in reputable books). I want to see it working in some code. I have found this is possible using the modularity library for igraph used with R (The R Foundation for Statistical Computing).
I want to see the example below (or a similar one) used in the code to calculate the modularity. The library gives on example but it isn't really what I want.
Let us have a set of vertices V = {1, 2, 3, 4, 5} and edges E = {(1,5), (2,3), (2,4), (2,5) (3,5)} that form an undirected graph.
Divide these vertices into two communities: c1 = {2,3} and c2 = {1,4,5}. It is the modularity of these two communities that is to be computed.
library(igraph)
g <- graph(c(1,5,2,3,2,4,2,5,3,5))
membership <- c(1,2,2,1,1)
modularity(g, membership)
Some explanation here:
The vector I use when creating the graph is the edge list of the graph. (In igraph versions older than 0.6, we had to subtract 1 from the numbers because igraph uses zero-based vertex indices at that time, but not any more).
The i-th element of the membership vector membership gives the index of the community to which vertex i belongs.

Resources