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

Support non-simplicial complexes #26

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions cechmate/filtrations/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def __init__(self, maxdim=None, verbose=True):
self.simplices_ = None
self.diagrams_ = None

def diagrams(self, simplices=None, show_inf=False):
def diagrams(self, simplices=None, show_inf=False, verbose=True, simplicial=False):
"""Compute persistence diagrams for the simplices.

Parameters
Expand All @@ -46,6 +46,6 @@ def diagrams(self, simplices=None, show_inf=False):

"""
simplices = simplices or self.simplices_
self.diagrams_ = phat_diagrams(simplices, show_inf)
self.diagrams_ = phat_diagrams(simplices, show_inf, verbose, simplicial)

return self.diagrams_
8 changes: 8 additions & 0 deletions cechmate/filtrations/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,11 @@ def build(self, simplices):
"""

self.simplices_ = simplices

def diagrams(self, simplices=None, show_inf=False, verbose=True, simplicial=True):
"""
Redefine the Custom version of diagrams so that simplicial defaults to True, rather
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you help me understand why this one should default to true while the others default to false?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My thought was that in all of the others, the simplicial complex is being generated in a way that we know it will be a simplicial complex. I thought it would be faster to pass False because we don't need to check it. My thought was not that the other ones are nonsimplicial, it's just that we don't need to assert that they are. For this one, we are generating the complex in a way that may not be simplicial. I assumed that most users would want the default behavior to be a simplicial complex, and they could choose to make something more subtle by passing simplicial=False

than false.
"""

return super().diagrams(simplices,show_inf,verbose,simplicial)
41 changes: 40 additions & 1 deletion cechmate/solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import phat


def phat_diagrams(simplices, show_inf=False, verbose=True):
def phat_diagrams(simplices, show_inf=False, verbose=True, simplicial=False):
"""
Compute the persistence diagram for :code:`simplices` using Phat.

Expand All @@ -19,12 +19,21 @@ def phat_diagrams(simplices, show_inf=False, verbose=True):
show_inf: Boolean
Determines whether or not to return points that never die.

simplicial: Boolean
Asserts that the filtration is a simplicial complex at every "dist,"
not some other kind of topological complex. Defaults to not checking
to ensure speed of existing filtrations.

Returns
--------
dgms: list of diagrams
the persistence diagram for Hk
"""

## Check that the filtration is a simplicial complex at every time step
if simplicial:
simplices = _assert_simplicial(simplices)

## Convert simplices representation to sparse pivot column
# -- sort by birth time, if tie, use order of simplex
ordered_simplices = sorted(simplices, key=lambda x: (x[1], len(x[0])))
Expand Down Expand Up @@ -59,6 +68,36 @@ def phat_diagrams(simplices, show_inf=False, verbose=True):

return dgms

def _assert_simplicial(simplices):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please run black code formatter over these changes.


# Initialize a set to keep track of simplices
existing_simplices = set()

# Initialize a list which is the (sub)filtration
# where the filtration is properly a simplicial
# complex at each point
simplicial_filtration = list()

# Sort the filtration by the time at which each simplex is
for s,t in sorted(simplices, key = lambda x: (x[1],x[0])):

# Sort to ensure a uniform representation
sorted_simplex = tuple(sorted(s))

if sorted_simplex in existing_simplices:
continue

else:
existing_simplices.add(sorted_simplex)

# Don't sort in the final filtration because the
# user might care about the order in which the
# 0-faces are listed

simplicial_filtration.append((s,t))

return simplicial_filtration


def _simplices_to_sparse_pivot_column(ordered_simplices, verbose=False):
"""
Expand Down
Loading