Source code for GraphRicciCurvature.FormanRicci

"""
A class to compute the Forman-Ricci curvature of a given NetworkX graph.
"""

# Author:
#     Chien-Chun Ni
#     http://www3.cs.stonybrook.edu/~chni/

# Reference:
#     Forman. 2003. “Bochner’s Method for Cell Complexes and Combinatorial Ricci Curvature.”
#         Discrete & Computational Geometry 29 (3). Springer-Verlag: 323–74.
#     Sreejith, R. P., Karthikeyan Mohanraj, Jürgen Jost, Emil Saucan, and Areejit Samal. 2016.
#         “Forman Curvature for Complex Networks.” Journal of Statistical Mechanics: Theory and Experiment 2016 (6).
#         IOP Publishing: 063206.

from .util import logger, set_verbose


[docs]class FormanRicci:
[docs] def __init__(self, G, verbose="ERROR"): """A class to compute Forman-Ricci curvature for all nodes and edges in G. Parameters ---------- G : NetworkX graph A given NetworkX graph, unweighted graph only for now, edge weight will be ignored. verbose: {"INFO","DEBUG","ERROR"} Verbose level. (Default value = "ERROR") - "INFO": show only iteration process log. - "DEBUG": show all output logs. - "ERROR": only show log if error happened. """ self.G = G.copy() set_verbose(verbose)
[docs] def compute_ricci_curvature(self): """Compute Forman-ricci curvature for all nodes and edges in G. Node curvature is defined as the average of all it's adjacency edge. Returns ------- G: NetworkX graph A NetworkX graph with "formanCurvature" on nodes and edges. Examples -------- To compute the Forman-Ricci curvature for karate club graph:: >>> G = nx.karate_club_graph() >>> frc = FormanRicci(G) >>> frc.compute_ricci_curvature() >>> frc.G[0][1] {'formanCurvature': 0} """ # Edge Forman curvature for (v1, v2) in self.G.edges(): if self.G.is_directed(): v1_nbr = set(list(self.G.predecessors(v1)) + list(self.G.successors(v1))) v2_nbr = set(list(self.G.predecessors(v2)) + list(self.G.successors(v2))) else: v1_nbr = set(self.G.neighbors(v1)) v1_nbr.remove(v2) v2_nbr = set(self.G.neighbors(v2)) v2_nbr.remove(v1) face = v1_nbr & v2_nbr # G[v1][v2]["face"]=face prl_nbr = (v1_nbr | v2_nbr) - face # G[v1][v2]["prl_nbr"]=prl_nbr self.G[v1][v2]["formanCurvature"] = len(face) + 2 - len(prl_nbr) logger.debug("Source: %s, target: %d, Forman-Ricci curvature = %f " % ( v1, v2, self.G[v1][v2]["formanCurvature"])) # Node Forman curvature for n in self.G.nodes(): fcsum = 0 # sum of the neighbor Forman curvature if self.G.degree(n) != 0: for nbr in self.G.neighbors(n): if 'formanCurvature' in self.G[n][nbr]: fcsum += self.G[n][nbr]['formanCurvature'] # assign the node Forman curvature to be the average of node's adjacency edges self.G.nodes[n]['formanCurvature'] = fcsum / self.G.degree(n) logger.debug("node %d, Forman Curvature = %f" % (n, self.G.nodes[n]['formanCurvature'])) print("Forman curvature computation done.")