toponetx.PathComplex#

class toponetx.PathComplex(paths: Graph | Iterable[Sequence[Hashable] | Path] | None = None, reserve_sequence_order: bool = False, allowed_paths: Iterable[tuple[Hashable]] | None = None, max_rank: int = 3, **kwargs)[source]#

Bases: Complex

A class representing a path complex based on simple paths as proposed in [1].

The original path complex is defined in [2].

A path complex contains elementary p-paths that span the space of simple paths. Path complexes are a topological structure whose building blocks are paths, which are essentially different from simplicial complexes and cell complexes. If certain conditions are met, path complexes can generalize simplicial complexes.

For example, a triangle with three vertices 1, 2, and 3 can be represented as a simplicial complex (1, 2, 3). Similarly, it can be represented as a path complex (1, 2, 3) whose boundary 1-paths are (1, 2), (2, 3), and (1, 3). Another example is a simple path (1, 2, 3). In this case, we cannot lift the simple path to a 2-dimensional simplicial complex, as triangle does not exist. However, we can still represent the simple path as a path complex (1, 2, 3) whose boundary 1-paths are (1, 2) and (2, 3) (1-path (1,3) does not exist).

Parameters:
pathsnx.Graph or Iterable[Sequence[Hashable]]

The paths in the path complex. If a graph is provided, the path complex will be constructed from the graph, and allowed paths are automatically computed.

reserve_sequence_orderbool, default=False

If True, reserve the order of the sub-sequence of nodes in the elementary p-path. Else, the sub-sequence of nodes in the elementary p-path will be reversed if the first index is larger than the last index.

allowed_pathsIterable[tuple[Hashable]], optional

An iterable of allowed boundaries. If None and the input is a Graph, allowed paths are automatically computed by enumerating all simple paths in the graph whose length is less than or equal to max_rank. If None and the input is not a Graph, allowed paths contain the input paths, their truncated subsequences (sub-sequences where the first or the last index is omitted), and any sub-sequences of the truncated subsequences in a recursive manner.

max_rankint, default=3

The maximal length of a path in the path complex.

**kwargskeyword arguments, optional

Additional attributes to be associated with the path complex.

Attributes:
dim

Dimension.

edges

Edges.

nodes

Nodes.

paths

Set of all elementary p-paths.

shape

Shape of path complex.

Methods

add_node(node, **attr)

Add node to the path complex.

add_path(path, **attr)

Add an elementary path to the path complex.

add_paths_from(paths)

Add elementary paths from an iterable of elementary paths.

adjacency_matrix(rank[, signed, weight, index])

Compute adjacency matrix of the path complex.

clone()

Return a copy of the path complex.

coadjacency_matrix(rank[, signed, weight, index])

Compute coadjacency matrix of the path complex.

compute_allowed_paths(graph[, ...])

Compute allowed paths from a graph.

down_laplacian_matrix(rank[, signed, ...])

Compute down laplacian matrix of the path complex.

get_edge_attributes(name)

Get edge attributes from a path complex.

get_node_attributes(name)

Get node attributes from a path complex.

get_path_attributes(name)

Get path attributes from a path complex.

hodge_laplacian_matrix(rank[, signed, ...])

Compute Hodge Laplacian matrix of the path complex.

incidence_matrix(rank[, signed, weight, index])

Compute incidence matrix of the path complex.

remove_nodes(node_set)

Remove nodes from the path complex.

restrict_to_nodes(node_set)

Return a new path complex restricted to a subset of nodes.

restrict_to_paths(path_set)

Return a new path complex restricted to a subset of paths.

set_edge_attributes(values[, name])

Set edge attributes for a path complex.

set_node_attributes(values[, name])

Set node attributes for a path complex.

set_path_attributes(values[, name])

Set path attributes for a path complex.

skeleton(rank)

Compute skeleton.

up_laplacian_matrix(rank[, signed, weight, ...])

Compute up laplacian matrix of the path complex.

Notes

  • By the definition established by [2], a path complex P is a non-empty collection of elementary p-paths such that for any sequence of vertices in a finite non-empty set V that belong to P, the truncated sequence of vertices (which is sometimes referred to as obvious boundaries) also belongs to P. The truncated sequences are sub-sequences of the original elementary p-path where the first or the last index is omitted. For instance, if we have an elementary p-path (1, 2, 3), the truncated sequences are (1,2) and (2,3).

  • Path complex in [1] is different from the path complex defined in [2] in the sense that elementary p-paths span the space of simple paths. The path complex originally proposed has elementary p-paths that span the space of boundary-invariant paths.

  • Unlike hypergraphs, combinatorial, simplicial, and cell complexes, path complexes take into account the order of sequences.

References

[1] (1,2)

Truong and Chin. Generalizing Topological Graph Neural Networks with Paths. https://arxiv.org/abs/2308.06838.pdf

[2] (1,2,3)

Grigor’yan, Lin, Muranov, and Yau. Homologies of path complexes and digraphs. https://arxiv.org/pdf/1207.2834.pdf

Examples

>>> PC = tnx.PathComplex([(1, 2, 3)])
>>> PC.paths
PathView([(1,), (2,), (3,), (1, 2), (2, 3), (1, 2, 3)])
>>> PC.add_paths_from([(1, 2, 4), (1, 2, 5), (4, 5)])
>>> PC.paths
PathView([(1,), (2,), (3,), (4,), (5,), (1, 2), (2, 3), (2, 4), (2, 5), (4, 5), (1, 2, 3), (1, 2, 4), (1, 2, 5)])
>>> G = nx.Graph()
>>> G.add_edges_from([(1, 2), (2, 3), (1, 3)])
>>> PC = tnx.PathComplex(G)
>>> PC.paths
PathView([(1,), (2,), (3,), (1, 2), (1, 3), (2, 3), (1, 3, 2), (1, 2, 3), (2, 1, 3)])
__init__(paths: Graph | Iterable[Sequence[Hashable] | Path] | None = None, reserve_sequence_order: bool = False, allowed_paths: Iterable[tuple[Hashable]] | None = None, max_rank: int = 3, **kwargs) None[source]#

Initialize a new instance of the Complex class.

Parameters:
**kwargskeyword arguments, optional

Attributes to add to the complex as key=value pairs.

Methods

__init__([paths, reserve_sequence_order, ...])

Initialize a new instance of the Complex class.

add_node(node, **attr)

Add node to the path complex.

add_path(path, **attr)

Add an elementary path to the path complex.

add_paths_from(paths)

Add elementary paths from an iterable of elementary paths.

adjacency_matrix(rank[, signed, weight, index])

Compute adjacency matrix of the path complex.

clone()

Return a copy of the path complex.

coadjacency_matrix(rank[, signed, weight, index])

Compute coadjacency matrix of the path complex.

compute_allowed_paths(graph[, ...])

Compute allowed paths from a graph.

down_laplacian_matrix(rank[, signed, ...])

Compute down laplacian matrix of the path complex.

get_edge_attributes(name)

Get edge attributes from a path complex.

get_node_attributes(name)

Get node attributes from a path complex.

get_path_attributes(name)

Get path attributes from a path complex.

hodge_laplacian_matrix(rank[, signed, ...])

Compute Hodge Laplacian matrix of the path complex.

incidence_matrix(rank[, signed, weight, index])

Compute incidence matrix of the path complex.

remove_nodes(node_set)

Remove nodes from the path complex.

restrict_to_nodes(node_set)

Return a new path complex restricted to a subset of nodes.

restrict_to_paths(path_set)

Return a new path complex restricted to a subset of paths.

set_edge_attributes(values[, name])

Set edge attributes for a path complex.

set_node_attributes(values[, name])

Set node attributes for a path complex.

set_path_attributes(values[, name])

Set path attributes for a path complex.

skeleton(rank)

Compute skeleton.

up_laplacian_matrix(rank[, signed, weight, ...])

Compute up laplacian matrix of the path complex.

Attributes

dim

Dimension.

edges

Edges.

nodes

Nodes.

paths

Set of all elementary p-paths.

shape

Shape of path complex.

complex

add_node(node: Hashable | Path, **attr) None[source]#

Add node to the path complex.

Parameters:
nodeHashable or Path

A Hashable or singleton Path representing a node in a path complex.

**attrkeyword arguments

Additional attributes to be provided as keyword arguments.

add_path(path: Hashable | Sequence[Hashable] | Path, **attr) None[source]#

Add an elementary path to the path complex.

An elementary p-path is a sequence of nodes $(n_1, …, n_p)$ where p is the length of the sequence. In a path complex, for every elementary p-path in the path complex, their truncated sequences $(n_2, …, n_p)$ and $(n_1, …, n_{p-1})$ are also in the path complex.

This method automatically initializes any obvious sub-paths (sub-paths where the first or last index is omitted) of the elementary path if not available. In order to add non-obvious sub-paths, manually add the sub-paths.

Parameters:
pathHashable or Sequence[Hashable] or Path

A Hashable or Sequence[Hashable] or Path representing a path in a path complex.

**attrkeyword arguments, optional

Additional keyword arguments to be passed to the method.

Examples

>>> PC = tnx.PathComplex([(1, 2, 3)])
>>> PC.paths
PathView([(1,), (2,), (3,), (1, 2), (2, 3), (1, 2, 3)])
>>> PC.add_path((1, 2, 4))
>>> PC.paths
PathView([(1,), (2,), (3,), (4,), (1, 2), (2, 3), (2, 4), (1, 2, 3), (1, 2, 4)])
add_paths_from(paths: Iterable[Sequence[Hashable] | Path]) None[source]#

Add elementary paths from an iterable of elementary paths.

An elementary p-path is a sequence of nodes $(n_1, …, n_p)$ where $p$ is the length of the sequence. In a path complex, for every elementary p-path in the path complex, their truncated sequences $(n_2, …, n_p)$ and $(n1, …, n_{p-1})$ are also in the path complex.

Parameters:
pathsIterable[Sequence[Hashable] or Path]

An iterable of paths as lists, tuples, or Path objects.

Examples

>>> PC = tnx.PathComplex([(1, 2, 3)])
>>> PC.paths
PathView([(1,), (2,), (3,), (1, 2), (2, 3), (1, 2, 3)])
>>> PC.add_paths_from([(1, 2, 4), (1, 2, 5), (4, 5)])
>>> PC.paths
PathView([(1,), (2,), (3,), (4,), (5,), (1, 2), (2, 3), (2, 4), (2, 5), (4, 5), (1, 2, 3), (1, 2, 4), (1, 2, 5)])
adjacency_matrix(rank: int, signed: bool = False, weight: str | None = None, index: bool = False) tuple[dict, lil_matrix] | lil_matrix[source]#

Compute adjacency matrix of the path complex.

Parameters:
rankint

The dimension of the adjacency matrix.

signedbool, default=False

If True, return signed adjacency matrix. Else, return absolute adjacency matrix.

weightstr, default=None, optional

The weight to be used for the adjacency matrix.

indexbool, default=False

If True, return adjacency matrix with indices. Else, return adjacency matrix without indices.

Returns:
tuple[dict, sp.sparse.lil_matrix] | sp.sparse.lil_matrix

If index is True, return a tuple of (idx_p, adjacency_matrix) else return adjacency_matrix.

clone() Self[source]#

Return a copy of the path complex.

The clone method by default returns an independent shallow copy of the path complex. Use Python’s copy.deepcopy for new containers.

Returns:
PathComplex

Returns a copy of the PathComplex.

coadjacency_matrix(rank: int, signed: bool = False, weight: str | None = None, index: bool = False) tuple[dict, lil_matrix] | lil_matrix[source]#

Compute coadjacency matrix of the path complex.

Parameters:
rankint

The dimension of the coadjacency matrix.

signedbool, default=False

If True, return signed coadjacency matrix. Else, return absolute coadjacency matrix.

weightstr, default=None, optional

The weight to be used for the adjacency matrix.

indexbool, default=False

If True, return coadjacency matrix with indices. Else, return coadjacency matrix without indices.

Returns:
tuple[dict, sp.sparse.lil_matrix] | sp.sparse.lil_matrix

If index is True, return a tuple of (idx_p, coadjacency_matrix) else return coadjacency_matrix.

static compute_allowed_paths(graph: Graph, reserve_sequence_order: bool = False, max_rank: int = 3) set[list | tuple][source]#

Compute allowed paths from a graph.

Allowed paths are automatically computed by enumerating all simple paths in the graph whose length is less than or equal to max_rank. Allowed paths allow us to restrict the boundary of an elementary p-path to only sequences that exist in the graph.

Parameters:
graphnx.Graph

A graph.

reserve_sequence_orderbool, default=False

If True, reserve the order of the sub-sequence of nodes in the elmentary p-path. Else, the sub-sequence of nodes in the elementary p-path will be reversed if the first index is larger than the last index.

max_rankint, default=3

The maximal length of a path in the path complex.

Returns:
set[list | tuple]

A set of allowed paths.

Examples

>>> G = nx.Graph()
>>> G.add_edges_from([(1, 2), (2, 3), (1, 3), (0, 1)])
>>> allowed_paths = tnx.PathComplex.compute_allowed_paths(G, max_rank=2)
>>> allowed_paths
{(0, 1), (1, 3), (1, 2), (2,), (1, 3, 2), (0, 1, 2), (0, 1, 3), (1, 2, 3), (2, 1, 3), (2, 3), (1,), (0,), (3,)}
property dim: int#

Dimension.

Returns:
int

This is the highest dimension of any elementary p-path in the complex.

down_laplacian_matrix(rank: int, signed: bool = True, weight: str | None = None, index: bool = False) tuple[dict, lil_matrix] | lil_matrix[source]#

Compute down laplacian matrix of the path complex.

Parameters:
rankint

The dimension of the down laplacian matrix.

signedbool, default=True

If True, return signed down laplacian matrix. Else, return absolute down laplacian matrix.

weightstr, optional

If not given, all nonzero entries are 1.

indexbool, default=False

If True, return down laplacian matrix with indices. Else, return down laplacian matrix without indices.

Returns:
tuple[dict, sp.sparse.lil_matrix] | sp.sparse.lil_matrix

If index is True, return a tuple of (idx_p, down_laplacian_matrix) otherwise if index is False, return down_laplacian_matrix.

property edges: EdgeView#

Edges.

Returns:
EdgeView

A view of all edges in the path complex.

get_edge_attributes(name: str) dict[tuple[Hashable], Any][source]#

Get edge attributes from a path complex.

Parameters:
namestr

The name of the edge attribute.

Returns:
dict[tuple[Hashable], Any]

A dictionary of edge and its associated value for the given attribute name.

Examples

>>> PC = tnx.PathComplex()
>>> PC.add_paths_from([[0, 1], [1, 2, 3], [1, 3, 2], [2, 1, 3]])
>>> PC.add_path([0, 1], weight=32)
>>> PC.add_path([1, 2], weight=98)
>>> PC.add_path([1, 3], color="red")
>>> PC.add_path([2, 3], color="blue")
>>> PC.get_edge_attributes("weight")
{(0, 1): 32, (1, 2): 98}
>>> PC.get_edge_attributes("color")
{(1, 3): 'red', (2, 3): 'blue'}
get_node_attributes(name: str) dict[tuple[Hashable], Any][source]#

Get node attributes from a path complex.

Parameters:
namestr

The name of the node attribute.

Returns:
dict[tuple[Hashable], Any]

A dictionary of node and its associated value for the given attribute name.

Examples

>>> PC = tnx.PathComplex()
>>> PC.add_node(0)
>>> PC.add_node(1, heat=55)
>>> PC.add_node(2, heat=66)
>>> PC.add_node(3, color="red")
>>> PC.add_node(2, color="blue")
>>> PC.add_paths_from([[0, 1], [1, 2, 3], [1, 3, 2], [2, 1, 3]])
>>> PC.get_node_attributes("heat")
{(1,): 55, (2,): 66}
>>> PC.get_node_attributes("color")
{(2,): 'blue', (3,): 'red'}
get_path_attributes(name: str) dict[tuple[Hashable], Any][source]#

Get path attributes from a path complex.

Parameters:
namestr

The name of the path attribute.

Returns:
dict[tuple[Hashable], Any]

A dictionary of path and its associated value for the given attribute name.

Examples

>>> PC = tnx.PathComplex()
>>> PC.add_paths_from([[0, 1]])
>>> PC.add_path([0, 1, 2], weight=43)
>>> PC.add_path([0, 1, 3], weight=98)
>>> PC.add_path([1, 2, 3], color="red")
>>> PC.add_path([1, 3, 2], color="blue")
>>> PC.add_path([2, 1, 3], color="green")
>>> PC.get_path_attributes("weight")
{(0, 1, 2): 43, (0, 1, 3): 98}
>>> PC.get_path_attributes("color")
{(1, 2, 3): 'red', (1, 3, 2): 'blue', (2, 1, 3): 'green'}
hodge_laplacian_matrix(rank: int, signed: bool = True, weight: str | None = None, index: bool = False) tuple[dict, lil_matrix] | lil_matrix[source]#

Compute Hodge Laplacian matrix of the path complex.

Parameters:
rankint

The dimension of the Hodge Laplacian matrix.

signedbool, default=False

If True, return signed Hodge Laplacian matrix. Else, return absolute Hodge Laplacian matrix.

weightstr, optional

If not given, all nonzero entries are 1.

indexbool, default=False

If True, return Hodge Laplacian matrix with indices. Else, return Hodge Laplacian matrix without indices.

Returns:
tuple[dict, sp.sparse.lil_matrix] | sp.sparse.lil_matrix

When index is True, return a tuple of (idx_p, Laplacian) else return Laplacian.

incidence_matrix(rank: int, signed: bool = True, weight: str | None = None, index: bool = False) tuple[dict, dict, lil_matrix] | lil_matrix[source]#

Compute incidence matrix of the path complex.

Parameters:
rankint

The dimension of the incidence matrix.

signedbool, default=True

If True, return signed incidence matrix. Else, return absolute incidence matrix.

weightstr, optional

If not given, all nonzero entries are 1.

indexbool, default=False

If True, return incidence matrix with indices. Else, return incidence matrix without indices.

Returns:
tuple[dict, dict, sp.sparse.lil_matrix] | sp.sparse.lil_matrix

If index is True, return a tuple of (idx_p_minus_1, idx_p, incidence_matrix) otherwise if index is False, return incidence_matrix.

property nodes: NodeView#

Nodes.

Returns:
NodeView

A view of all nodes in the path complex.

property paths: PathView#

Set of all elementary p-paths.

Returns:
PathView

A view of all elementary p-paths in the path complex.

remove_nodes(node_set: Iterable[Hashable]) None[source]#

Remove nodes from the path complex.

Parameters:
node_setIterable[Hashable]

An iterable of nodes to be removed.

restrict_to_nodes(node_set: Iterable[Hashable])[source]#

Return a new path complex restricted to a subset of nodes.

Parameters:
node_setIterable[Hashable]

The nodes to be used for the new restricted path complex.

Returns:
PathComplex

The new path complex restricted to the provided subset of nodes.

Examples

>>> PC = tnx.PathComplex(
...     [[0, 1], [1, 2, 3], [1, 3, 2], [2, 1, 3], [0, 1, 2], [0, 1, 3]]
... )
>>> PC = PC.restrict_to_nodes([0, 1, 3])
>>> PC.paths
PathView([(0,), (1,), (3,), (0, 1), (1, 3), (0, 1, 3)])
restrict_to_paths(path_set: Iterable[Sequence[Hashable]])[source]#

Return a new path complex restricted to a subset of paths.

Parameters:
path_setIterable[Sequence[Hashable]]

The paths to be used for the new restricted path complex.

Returns:
PathComplex

The new path complex restricted to the provided subset of paths.

Examples

>>> PC = tnx.PathComplex(
...     [[0, 1], [1, 2, 3], [1, 3, 2], [2, 1, 3], [0, 1, 2], [0, 1, 3]]
... )
>>> PC = PC.restrict_to_paths([[1, 2, 3]])
>>> PC.paths
PathView([(1,), (2,), (3,), (1, 2), (2, 3), (1, 2, 3)])
set_edge_attributes(values: dict[Sequence[Hashable], Hashable | dict[Hashable, Any]], name: str | None = None) None[source]#

Set edge attributes for a path complex.

Parameters:
valuesdict[Sequence[Hashable], Hashable | dict[Hashable, Any]]

A dictionary of edge and its associated attribute values.

namestr

The name of the edge attribute.

Examples

>>> PC = tnx.PathComplex()
>>> PC.add_paths_from([[0, 1], [1, 2, 3], [1, 3, 2], [2, 1, 3]])
>>> PC.add_path([0, 1], weight=32)
>>> PC.add_path([1, 2], weight=98)
>>> PC.add_path([1, 3], color="red")
>>> PC.add_path([2, 3], color="blue")
>>> PC.get_edge_attributes("weight")
{(0, 1): 32, (1, 2): 98}
>>> PC.set_edge_attributes({(0, 1): 33}, name="weight")
>>> PC.get_edge_attributes("weight")
{(0, 1): 33, (1, 2): 98}
>>> PC.set_edge_attributes(
...     {
...         (1, 3): {"weight": 55, "color": "yellow"},
...         (2, 3): {"weight": 66, "color": "blue"},
...     }
... )
>>> PC[1, 3]
{'color': 'yellow', 'weight': 55}
>>> PC[2, 3]
{'color': 'blue', 'weight': 66}
set_node_attributes(values: dict[Sequence[Hashable], Hashable | dict[Hashable, Any]], name: str | None = None) None[source]#

Set node attributes for a path complex.

Parameters:
valuesdict[Sequence[Hashable], Hashable | dict[Hashable, Any]]

A dictionary of node and its associated attribute values.

namestr

The name of the node attribute.

Examples

>>> PC = tnx.PathComplex()
>>> PC.add_paths_from([[0, 1], [1, 2, 3], [1, 3, 2], [2, 1, 3]])
>>> PC.set_node_attributes(
...     {
...         (1,): {"heat": 55, "color": "red"},
...         (2,): {"heat": 66, "color": "blue"},
...     }
... )
>>> PC[1]
{'heat': 55, 'color': 'red'}
>>> PC[2]
{'heat': 66, 'color': 'blue'}
>>> PC.set_node_attributes({(1,): 58, (2,): 60}, name="heat")
>>> PC[1]
{'heat': 58, 'color': 'red'}
>>> PC[2]
{'heat': 60, 'color': 'blue'}
set_path_attributes(values: dict[Sequence[Hashable], Hashable | dict[Hashable, Any]], name: str | None = None) None[source]#

Set path attributes for a path complex.

Parameters:
valuesdict[Sequence[Hashable], Hashable | dict[Hashable, Any]]

A dictionary of path and its associated attribute values.

namestr

The name of the path attribute.

Examples

>>> PC = tnx.PathComplex(
...     [[0, 1], [0, 1, 2], [0, 1, 3], [1, 2, 3], [1, 3, 2], [2, 1, 3]]
... )
>>> PC.set_path_attributes(
...     {
...         (0, 1, 2): {"weight": 43, "color": "red"},
...         (0, 1, 3): {"weight": 98, "color": "blue"},
...     }
... )
>>> PC.get_path_attributes("weight")
{(0, 1, 2): 43, (0, 1, 3): 98}
>>> PC.get_path_attributes("color")
{(0, 1, 2): 'red', (0, 1, 3): 'blue'}
>>> PC.set_path_attributes({0: 55}, "weight")
>>> PC.get_path_attributes("weight")
{(0,): 55, (0, 1, 2): 43, (0, 1, 3): 98}
>>> PC.set_path_attributes({(0, 1): "red"}, "color")
>>> PC.get_path_attributes("color")
{(0, 1): 'red', (0, 1, 2): 'red', (0, 1, 3): 'blue'}
property shape: tuple[int, ...]#

Shape of path complex.

(number of elementary p-paths for each dimension d, for d in range(0,dim(Pc)))

Returns:
tuple[int, …]

Returns a tuple representing the shape of the path complex.

skeleton(rank: int) list[tuple[Hashable]][source]#

Compute skeleton.

Parameters:
rankint

The rank to be used to generate the skeleton of elementary p-paths.

Returns:
set[tuple[Hashable]]

Set of elementary p-paths of dimension specified by rank.

up_laplacian_matrix(rank: int, signed: bool = True, weight: str | None = None, index: bool = False) tuple[dict, lil_matrix] | lil_matrix[source]#

Compute up laplacian matrix of the path complex.

Parameters:
rankint

The dimension of the up laplacian matrix.

signedbool, default=True

If True, return signed up laplacian matrix. Else, return absolute up laplacian matrix.

weightstr, optional

If not given, all nonzero entries are 1.

indexbool, default=False

If True, return up laplacian matrix with indices. Else, return up laplacian matrix without indices.

Returns:
tuple[dict, sp.sparse.lil_matrix] | sp.sparse.lil_matrix

If index is True, return a tuple of (idx_p, up_laplacian_matrix) otherwise if index is False, return up_laplacian_matrix.