Skip to content

tda

This module contains for topological data analysis (TDA) of loss landscapes.

bottleneck_distance(p1, p2)

Calculates the bottleneck distance between two persistence diagrams.

Parameters:

Name Type Description Default
p1 ArrayLike

The first persistence diagram, represented as a 1D array of persistence values.

required
p2 ArrayLike

The second persistence diagram, represented as a 1D array of persistence values.

required

Returns:

Type Description
float

A float representing the bottleneck distance between the two diagrams.

Source code in src/landscaper/tda.py
def bottleneck_distance(p1: npt.ArrayLike, p2: npt.ArrayLike) -> float:
    """Calculates the bottleneck distance between two persistence diagrams.

    Args:
        p1 (npt.ArrayLike): The first persistence diagram, represented as a 1D array of persistence values.
        p2 (npt.ArrayLike): The second persistence diagram, represented as a 1D array of persistence values.

    Returns:
            A float representing the bottleneck distance between the two diagrams.
    """
    ppd1 = [(0, val) for val in p1]
    ppd2 = [(0, val) for val in p2]
    return gd.bottleneck_distance(ppd1, ppd2)

digraph_mt(mt)

Converts a merge tree to a directed graph representation that makes it easy to navigate the hierarchy.

The root is the maximum which points down the tree towards saddles and minima. The 'partition' edge attributes list the members of the integral line from node a->b, while 'counts' contains the number of members along that line.

Parameters:

Name Type Description Default
mt MergeTree

The merge tree to convert.

required

Returns:

Type Description
DiGraph

A networkx DiGraph representation of the merge tree hierarchy.

Source code in src/landscaper/tda.py
def digraph_mt(mt: tp.MergeTree) -> nx.DiGraph:
    """Converts a merge tree to a directed graph representation that makes it easy to navigate the hierarchy.

    The root is the maximum which points down the tree towards saddles and minima.
    The 'partition' edge attributes list the members of the integral line from node a->b,
    while 'counts' contains the number of members along that line.

    Args:
        mt (tp.MergeTree): The merge tree to convert.

    Returns:
        A networkx DiGraph representation of the merge tree hierarchy.
    """
    g = nx.DiGraph()
    for n, v in mt.nodes.items():
        g.add_node(n, value=v)

    g.add_edges_from([(e[1], e[0]) for e in list(mt.edges)])
    e_info = {(e[1], e[0]): [e[0]] for e in list(mt.edges)}
    aug_info = {(e[1], e[0]): [e[0], *v] for e, v in mt.augmentedEdges.items()}
    e_info.update(aug_info)

    nx.set_edge_attributes(g, e_info, "partitions")
    len_part_dict = {e: len(v) for e, v in e_info.items()}
    nx.set_edge_attributes(g, len_part_dict, "counts")

    return g

get_persistence_dict(msc)

Returns the persistence of the given Morse-Smale complex as a dictionary.

Parameters:

Name Type Description Default
msc MorseSmaleComplex

A Morse-Smale complex from Topopy.

required

Returns:

Type Description

The values of the Morse-Smale Complex as a dictionary of nodes to persistence values.

Source code in src/landscaper/tda.py
def get_persistence_dict(msc: tp.MorseSmaleComplex):
    """Returns the persistence of the given Morse-Smale complex as a dictionary.

    Args:
        msc (tp.MorseSmaleComplex): A Morse-Smale complex from [Topopy](https://github.com/maljovec/topopy).

    Returns:
        The values of the Morse-Smale Complex as a dictionary of nodes to persistence values.
    """
    """"""
    return {key: msc.get_merge_sequence()[key][0] for key in msc.get_merge_sequence()}

merge_tree(loss, coords, graph, direction=1)

Helper function used to generate a merge tree for a loss landscape.

Parameters:

Name Type Description Default
loss ArrayLike

Function values for each point in the space.

required
coords ArrayLike

N-dimensional array of ranges for each dimension in the space.

required
graph nglGraph

nglpy graph of the space (usually filled out by topopy).

required
direction Literal[-1, 1]

The direction to generate a merge tree for. -1 generates a merge tree for maxima, while the default value (1) is for minima.

1

Returns:

Type Description
MergeTree

Merge tree for the space.

Source code in src/landscaper/tda.py
def merge_tree(
    loss: npt.ArrayLike,
    coords: npt.ArrayLike,
    graph: ngl.EmptyRegionGraph,
    direction: Literal[-1, 1] = 1,
) -> tp.MergeTree:
    """Helper function used to generate a merge tree for a loss landscape.

    Args:
        loss (np.ArrayLike): Function values for each point in the space.
        coords (np.ArrayLike): N-dimensional array of ranges for each dimension in the space.
        graph (ngl.nglGraph): nglpy graph of the space (usually filled out by topopy).
        direction (Literal[-1,1]): The direction to generate a merge tree for.
            -1 generates a merge tree for maxima, while the default value (1) is for minima.

    Returns:
        Merge tree for the space.
    """
    loss_flat = loss.flatten()
    t = tp.MergeTree(graph=graph)
    t.build(np.array(coords), direction * loss_flat)
    return t

merge_tree_to_nx(mt)

Converts a Topopy MergeTree to a networkx representation.

Parameters:

Name Type Description Default
mt MergeTree

The merge tree to convert.

required

Returns:

Type Description
Graph

A networkx Graph representation of the merge tree. Can be used for visualization and analysis.

Source code in src/landscaper/tda.py
def merge_tree_to_nx(mt: tp.MergeTree) -> nx.Graph:
    """Converts a Topopy MergeTree to a networkx representation.

    Args:
        mt (tp.MergeTree): The merge tree to convert.

    Returns:
       A networkx Graph representation of the merge tree. Can be used for visualization and analysis.
    """
    g = nx.Graph()
    for n, v in mt.nodes.items():
        g.add_node(n, value=v)
    g.add_edges_from(list(mt.edges))
    return g

topological_index(msc, idx)

Gets the topological index of a given point.

Parameters:

Name Type Description Default
msc MorseSmaleComplex

The Morse-Smale complex that represents the space being analyzed.

required
idx int

The index of the point to get a topological index for.

required

Returns:

Type Description
Literal[0, 1, 2]

Either 0, 1, or 2. This indicates that the point is either a minima (0), saddle point (1) or a maxima (2).

Source code in src/landscaper/tda.py
def topological_index(msc: tp.MorseSmaleComplex, idx: int) -> Literal[0, 1, 2]:
    """Gets the topological index of a given point.

    Args:
        msc (tp.MorseSmaleComplex): The Morse-Smale complex that represents the space being analyzed.
        idx (int): The index of the point to get a topological index for.

    Returns:
        Either 0, 1, or 2. This indicates that the point is either a minima (0), saddle point (1) or a maxima (2).
    """
    c = msc.get_classification(idx)
    if c == "minimum":
        return 0
    elif c == "regular":
        return 1
    else:
        return 2