Source code for toponetx.transform.graph_to_simplicial_complex
"""Methods to lift a graph to a simplicial complex."""
from itertools import combinations, takewhile
import networkx as nx
from typing_extensions import deprecated
from toponetx.classes.simplicial_complex import SimplicialComplex
__all__ = [
"graph_to_clique_complex",
"graph_to_neighbor_complex",
"weighted_graph_to_vietoris_rips_complex",
]
[docs]
def graph_to_neighbor_complex(G: nx.Graph) -> SimplicialComplex:
"""Get the neighbor complex of a graph.
Parameters
----------
G : networkx.Graph
Input graph.
Returns
-------
toponetx.classes.SimplicialComplex
The neighbor complex of the graph.
Notes
-----
This type of simplicial complexes can have very large dimension (max degree of the
graph) and it is a function of the distribution of the valency of the graph.
"""
simplices = [[*list(G.neighbors(node)), node] for node in G]
return SimplicialComplex(simplices)
[docs]
def graph_to_clique_complex(
G: nx.Graph, max_rank: int | None = None
) -> SimplicialComplex:
"""Get the clique complex of a graph.
Parameters
----------
G : networks.Graph
Input graph.
max_rank : int, optional
The maximum rank of the simplices in the output clique complex.
Returns
-------
SimplicialComplex
The clique simplicial complex of rank `max_rank` of the graph G.
"""
cliques = nx.enumerate_all_cliques(G)
# `nx.enumerate_all_cliques` returns cliques in ascending order of size. Abort calling the generator once we reach
# cliques larger than the requested max dimension.
cliques = takewhile(
lambda clique: max_rank is None or len(clique) <= max_rank + 1, cliques
)
SC = SimplicialComplex(cliques)
# copy attributes of the input graph
for node in G.nodes:
SC[[node]].update(G.nodes[node])
# if the resulting complex has dimension 1 or higher, copy the attributes of the edges
if SC.dim >= 1:
for edge in G.edges:
SC[edge].update(G.edges[edge])
SC.complex.update(G.graph)
return SC
@deprecated(
"`graph_2_neighbor_complex` is deprecated and will be removed in a future version, use `graph_to_neighbor_complex` instead."
)
def graph_2_neighbor_complex(G) -> SimplicialComplex:
"""Get the neighbor complex of a graph.
Parameters
----------
G : networkx.Graph
Input graph.
Returns
-------
toponetx.classes.SimplicialComplex
The neighbor complex of the graph.
Notes
-----
This type of simplicial complexes can have very large dimension (max degree of the
graph) and it is a function of the distribution of the valency of the graph.
"""
return graph_to_neighbor_complex(G)
@deprecated(
"`graph_2_clique_complex` is deprecated and will be removed in a future version, use `graph_to_clique_complex` instead."
)
def graph_2_clique_complex(
G: nx.Graph, max_rank: int | None = None
) -> SimplicialComplex:
"""Get the clique complex of a graph.
Parameters
----------
G : networks.Graph
Input graph.
max_rank : int, optional
The maximum rank of the simplices in the output clique complex.
Returns
-------
SimplicialComplex
The clique simplicial complex of rank `max_rank` of the graph `G`.
"""
return graph_to_clique_complex(G, max_rank)
[docs]
def weighted_graph_to_vietoris_rips_complex(
G: nx.Graph, r: float, max_dim: int | None = None
):
r"""Get the Vietoris-Rips complex of radius r of a weighted undirected graph.
The Vietoris-Rips complex of radius `r` is the clique complex given by the cliques
of `G` whose nodes have pairwise distances less or equal than `r`. All vertices are
added to the Vietoris-Rips complex regardless of the radius introduced.
If `G` is a clique weighted by a dissimilarity function d that satisfies
\max_v d(v, v) <= \min d(u,v) for u != v, and r >= d(v, v) for all nodes v,
then the Vietoris-Rips complex of radius `r` is the usual Vietoris-Rips abstract
simplicial complex of radius `r` for point clouds with dissimilarities.
Parameters
----------
G : networkx.Graph
Weighted undirected input graph. The weights of the edges must be in the attribute 'weight'.
r : float
The radius for the Vietoris-Rips simplicial complex computation.
max_dim : int, optional
The max dimension of the cliques in the output clique complex.
Returns
-------
SimplicialComplex
The Vietoris-Rips simplicial complex of dimension max_dim of the graph G.
"""
def is_in_vr_complex(clique): # numpydoc ignore=GL08
edges = combinations(clique, 2)
return all(G[u][v]["weight"] <= r for u, v in edges)
all_cliques = nx.enumerate_all_cliques(G)
possible_cliques = takewhile(
lambda face: max_dim is None or len(face) <= max_dim, all_cliques
)
vr_cliques = filter(is_in_vr_complex, possible_cliques)
return SimplicialComplex(list(vr_cliques))