Exemplo n.º 1
0
def test_morse_reduce_two_triangles():
    """ Refactored version is like [MN13] """
    from dmt.dmt import morse_reduce
    from dmt.morse_reduce_nanda import morse_reduce_nanda
    from dmt.morse_complex import MorseComplex
    # Disc from two triangles      a  b  c  d  ab bc ac bd cd bdc abc
    morse_complex = MorseComplex([[0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0],  # a
                                  [0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0],  # b
                                  [0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0],  # c
                                  [0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0],  # d
                                  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],  # ab
                                  [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1],  # bc
                                  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],  # ac
                                  [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0],  # bd
                                  [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0],  # cd
                                  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],  # bdc
                                  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],  # abc
                                 cell_dimensions=[0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2])
    reduced_cplx, matching = morse_reduce_nanda(morse_complex, return_matching=True)
    assert np.all(reduced_cplx.boundary_matrix == np.array([[0]]))
    assert np.all(reduced_cplx.cell_dimensions == [0])
    # Testing whether our custom reduction gets the same result as [MN13]
    reduced_cplx2, matching2 = morse_reduce(morse_complex, return_matching=True)
    assert matching.matches == matching2.matches
    assert np.all(reduced_cplx.boundary_matrix == reduced_cplx2.boundary_matrix)
    assert np.all(reduced_cplx.cell_dimensions == reduced_cplx2.cell_dimensions)
Exemplo n.º 2
0
class Matching(object):
    """ A matching is a discrete vector field on a cell complex """
    def __init__(self, morse_complex=None, matches=None):
        self.morse_complex = MorseComplex(
        ) if morse_complex is None else morse_complex
        self.matches = matches or []

    def __iter__(self):
        return iter(self.matches)

    def append(self, match):
        self.matches.append(match)

    def induce_filtered_matching(self, filtration):
        """ Filter matches by a filtration

        Only matches that appear at the same filtration value survive.

        :param filtration: Filtration to be used for filtering the matches.
        """
        matches = [(q, k) for (q, k) in self.matches
                   if filtration[q] == filtration[k]]
        return Matching(self.morse_complex.copy(filtration=filtration),
                        matches=matches)

    @property
    def unmatched_ixs(self):
        """ Find which cells are unmatched """
        return np.setdiff1d(range(self.morse_complex.size),
                            sum(zip(*self), ()))
Exemplo n.º 3
0
def test_get_ace_ixs():
    from dmt.morse_complex import MorseComplex
    from dmt.matching import Matching
    qk = np.random.choice(range(100), 10, replace=False)
    morse_complex = MorseComplex(boundary_matrix=np.empty((100, 100)),
                                 cell_dimensions=np.empty(100))
    matching = Matching(morse_complex=morse_complex,
                        matches=list(
                            zip(qk[range(0, 10, 2)], qk[range(1, 10, 2)])))
    assert len(matching.matches) == 5
    assert len(matching.unmatched_ixs) == 90
Exemplo n.º 4
0
def test_real_life_morse_reduce():
    from dmt import MorseComplex
    from dmt.data import load_complex
    from dmt.dmt import morse_reduce
    from dmt.binning import get_binning
    from dmt.morse_reduce_nanda import morse_reduce_nanda
    # This once broke
    delta = 0.05
    cplx = load_complex("normal_dist_2D_100pts_1.csv")
    binned_filtration = get_binning(cplx.filtration, delta)
    cplx_discrete = MorseComplex(cplx.boundary_matrix_csr, cplx.cell_dimensions,
                                 filtration=binned_filtration, points=cplx.points)
    cplx_nanda, matching_nanda = morse_reduce_nanda(cplx_discrete, return_matching=True)
    cplx_we, matching_we = morse_reduce(cplx_discrete, return_matching=True)
    assert cplx_nanda.valid_boundary()
    assert cplx_we.valid_boundary()
Exemplo n.º 5
0
def test_morse_reduce_circle():
    """ Refactored version is like [MN13] """
    from dmt.dmt import morse_reduce
    from dmt.morse_reduce_nanda import morse_reduce_nanda
    from dmt.morse_complex import MorseComplex
    # Circle
    morse_complex = MorseComplex([[0, 0, 0, 1, 0, 1],
                                  [0, 0, 0, 1, 1, 0],
                                  [0, 0, 0, 0, 1, 1],
                                  [0, 0, 0, 0, 0, 0],
                                  [0, 0, 0, 0, 0, 0],
                                  [0, 0, 0, 0, 0, 0]],
                                 cell_dimensions=[0, 0, 0, 1, 1, 1])
    reduced_cplx, matching = morse_reduce_nanda(morse_complex, return_matching=True)
    assert np.all(reduced_cplx.boundary_matrix == np.array([[0, 0],
                                                            [0, 0]]))
    assert np.all(reduced_cplx.cell_dimensions == [0, 1])
    # Testing whether our custom reduction gets the same result as [MN13]
    reduced_cplx2, matching2 = morse_reduce(morse_complex, return_matching=True)
    assert matching.matches == matching2.matches
    assert np.all(reduced_cplx.boundary_matrix == reduced_cplx2.boundary_matrix)
    assert np.all(reduced_cplx.cell_dimensions == reduced_cplx2.cell_dimensions)
Exemplo n.º 6
0
def test_point_order(boundary, cell_dimensions, filtration, expected_order,
                     sort_by):
    import numpy as np
    from dmt.morse_complex import MorseComplex
    point_count = len([d for d in cell_dimensions if d == 0])
    points = (np.full((point_count, 2), 1).T * np.arange(point_count)).T
    # Constructor sorts by filtration
    cplx = MorseComplex(boundary,
                        cell_dimensions,
                        filtration=filtration,
                        points=points)
    if sort_by == "dimension":
        cplx.sort_by_dimension()
    elif sort_by == "filtration":
        cplx = cplx.sort_by_filtration()
    assert np.all(
        cplx.get_point(
            [i for i in range(cplx.size)
             if cplx.cell_dimensions[i] == 0]) == points[expected_order])
Exemplo n.º 7
0
def test_valid_filtration(filtration, valid):
    from dmt.morse_complex import MorseComplex
    boundary = [[0, 0, 1], [0, 0, 1], [0, 0, 0]]
    dims = [0, 0, 1]
    assert (MorseComplex(boundary, dims,
                         filtration).valid_filtration() == valid)
Exemplo n.º 8
0
def test_parse_cechmate():
    import numpy as np
    from dmt.cechmate_wrap import parse_cechmate
    from dmt.morse_complex import MorseComplex
    cechmate = [
        ([0], 0),  # 0
        ([1], 0),  # 1
        ([2], 0),  # 2
        ([3], 0),  # 3
        ((0, 1, 3), 3.5347319838680913),  # 12
        ((1, 3), 3.5347319838680913),  # 11
        ((0, 1, 2), 1.760962625882297),  # 10
        ((1, 2), 1.760962625882297),  # 9
        ((0, 2, 3), 1.0504164256818944),  # 8
        ((0, 3), 1.0504164256818944),  # 7
        ((0, 1), 0.2489387964292784),  # 4
        ((0, 2), 0.30122587679897417),  # 5
        ((2, 3), 0.6116032053615759)
    ]  #  6
    cplx = parse_cechmate(cechmate)

    # Hacky way to compute the bitwise_xor matrix multiplication
    bdry = cplx["boundary_matrix"]
    assert np.mod(bdry.astype(int).dot(bdry.astype(int)).todense(),
                  2).sum() == 0

    # Result is not yet sorted
    assert np.all(
        cplx["cell_dimensions"] == [0, 0, 0, 0, 2, 1, 2, 1, 2, 1, 1, 1, 1])
    assert np.all(cplx["filtration"] == [
        0, 0, 0, 0, 3.5347319838680913, 3.5347319838680913, 1.760962625882297,
        1.760962625882297, 1.0504164256818944, 1.0504164256818944,
        0.2489387964292784, 0.30122587679897417, 0.6116032053615759
    ])
    assert np.all(cplx["boundary_matrix"].todense().astype(int) ==
                  [[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0],
                   [0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0],
                   [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1],
                   [0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1],
                   [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                   [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
                   [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                   [0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0],
                   [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                   [0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0],
                   [0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0],
                   [0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0],
                   [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0]])

    morsecplx = MorseComplex(**cplx)
    assert np.all(
        morsecplx.boundary_matrix == [[0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0],
                                      [0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0],
                                      [0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0],
                                      [0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0],
                                      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1],
                                      [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0],
                                      [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0],
                                      [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1],
                                      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                                      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0],
                                      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                                      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
                                      [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])
Exemplo n.º 9
0
def test_reduce_by_acyclic_matching_gradient_path_multiplicity(reduction_algo):
    """ Minimal example where there is a gradient path multiplicity of two

    Four triangles like this that are collapsed from left to right, with only the leftmost cell remaining
      ______
     / | >  \
    .  >  |––|
     \_|_>__/
    """
    from dmt import MorseComplex
    from dmt.matching import Matching
    from dmt.dmt import reduce_by_acyclic_matching, reduce_by_acyclic_matching_dense
    from dmt.pers_hom import filter_zero_persistence_classes
    algo_map = {"sparse": reduce_by_acyclic_matching,
                "dense": reduce_by_acyclic_matching_dense}
    edges = np.array([[1, 1, 0, 1, 0, 0, 1, 0],
                      [1, 0, 1, 0, 0, 1, 0, 1],
                      [0, 1, 1, 0, 1, 0, 0, 0],
                      [0, 0, 0, 1, 1, 1, 0, 0],
                      [0, 0, 0, 0, 0, 0, 1, 1]])
    triangles = np.array([[1, 1, 0, 0],
                          [0, 1, 1, 0],
                          [0, 1, 0, 1],
                          [0, 0, 1, 0],
                          [0, 0, 1, 1],
                          [0, 0, 0, 1],
                          [1, 0, 0, 0],
                          [1, 0, 0, 0]])
    boundary = np.block([
        [np.zeros((edges.shape[0], edges.shape[0])), edges, np.zeros((edges.shape[0], triangles.shape[1]))],
        [np.zeros((triangles.shape[0], edges.shape[0])), np.zeros((triangles.shape[0], edges.shape[1])), triangles],
        [np.zeros((triangles.shape[1], 17))]])
    cell_dimensions = [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2]
    filtration =      [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1]
    cplx = MorseComplex(boundary.astype(bool), cell_dimensions, filtration=filtration, sort_by_filtration=False)
    matching = Matching(cplx, matches=[(5, 14), (6, 15), (7, 16)])
    """
matrix([[0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])

    """
    assert cplx.valid_boundary()

    reduced_cplx = algo_map[reduction_algo](matching)
    assert reduced_cplx.size < cplx.size
    assert reduced_cplx.valid_boundary()
    dgm = filter_zero_persistence_classes(cplx.persistence_diagram())
    reduced_dgm = filter_zero_persistence_classes(reduced_cplx.persistence_diagram())
    for i in [0, 1]:
        assert np.all(dgm[i] == reduced_dgm[i])
Exemplo n.º 10
0
 def __init__(self, morse_complex=None, matches=None):
     self.morse_complex = MorseComplex(
     ) if morse_complex is None else morse_complex
     self.matches = matches or []