Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Possible unintended behavior of vector_vector boundary matrix specification #5

Open
apizzimenti opened this issue Jul 24, 2024 · 0 comments

Comments

@apizzimenti
Copy link

apizzimenti commented Jul 24, 2024

I've been using PHAT's Python bindings to detect the births of essential cycles on a cubical 2-torus. I've noticed that changing the order in which the indices of a cell's faces are listed — e.g. (2, [9, 10, 14, 18]) to (2, [10, 14, 9, 18]) — causes different/incorrect persistence pairs to be reported. Here's a MWE:

from random import sample
import phat

vertices = [(0, [])]*9

edges = [
    (1, [0, 1]),
    (1, [0, 3]),
    (1, [0, 2]),
    (1, [0, 6]),
    (1, [1, 2]),
    (1, [1, 4]),
    (1, [1, 7]),
    (1, [2, 5]),
    (1, [2, 8]),
    (1, [3, 4]),
    (1, [3, 6]),
    (1, [3, 5]),
    (1, [4, 5]),
    (1, [4, 7]),
    (1, [5, 8]),
    (1, [6, 7]),
    (1, [6, 8]),
    (1, [7, 8]),
]

squares = [
    (2, [9, 10, 14, 18]),
    (2, [13, 14, 16, 21]),
    (2, [18, 19, 22, 24]),
    (2, [21, 22, 23, 26]),
    (2, [10, 11, 16, 20]),
    (2, [9, 12, 15, 24]),
    (2, [19, 20, 23, 25]),
    (2, [13, 15, 17, 26]),
    (2, [11, 12, 17, 25]),
]


# To compare the resultant persistence pairs, we shuffle the order in which the
# indices of each square's faces are listed. These indices are listed in increasing
# order by default.
for question, shuffler in zip(["original", "shuffled"], [lambda A: A, lambda B: sample(B, len(B))]):
    # Shuffle the ordering of the squares' faces and construct the cubical complex.
    squares = [(d, shuffler(faces)) for d, faces in squares]
    complex = vertices + edges + squares

    # Construct the boundary matrix and compute the persistence pairs.
    boundary = phat.boundary_matrix()
    boundary.columns = complex
    pairs = boundary.compute_persistence_pairs()
    pairs.sort()
    pairs = list(pairs)

    # Determine the births of essential cycles; these should be invariant under
    # re-orderings of the squares' faces in the specification.
    deaths = set([d for b, d in pairs])
    births = set([b for b, d in pairs])
    times = set(range(len(complex)))
    essential = times-(births|deaths)

    print(question)
    print(f"births @ {births}")
    print(f"deaths @ {deaths}")
    print(f"essential @ {essential}")
    print()

which outputs

>>> original
    births @ {1, 2, 3, 4, 5, 6, 7, 8, 18, 20, 21, 22, 23, 24, 25, 26}
    deaths @ {32, 33, 34, 9, 10, 11, 12, 14, 15, 16, 17, 27, 28, 29, 30, 31}
    essential @ {0, 35, 19, 13}

    shuffled
    births @ {1, 2, 3, 4, 5, 6, 7, 8, 12, 13, 17, 18, 19, 20, 22, 24, 26}
    deaths @ {32, 33, 34, 35, 9, 10, 11, 14, 15, 16, 23, 25, 27, 28, 29, 30, 31}
    essential @ {0, 21}

which are correct and incorrect, respectively. Is this behavior intended?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant