예제 #1
0
def WeightedRipsFiltration(X, F, p, dimension_max=2, filtration_max=np.inf):
    '''
    Compute the weighted Rips filtration of a point cloud, weighted with the 
    values F, and with parameter p. Requires sklearn.metrics.pairwise.euclidean_distances
    to compute pairwise distances between points.
    
    Input:
        X (np.array): size Nxn, representing N points in R^n.
        F (np.array):size 1xN,  representing the values of a function on X.
        p (float): a parameter in [0, +inf) or np.inf.
        dimension_max (int, optional): maximal dimension to expand the complex.
        filtration_max (float, optional): maximal filtration value of the filtration.
    
    Output:
        st (gudhi.SimplexTree): the weighted Rips filtration. 
    '''
    N_tot = X.shape[0]
    distances = euclidean_distances(X)  #compute the pairwise distances
    st = gudhi.SimplexTree()  #create an empty simplex tree
    for i in range(N_tot):  #add vertices to the simplex tree
        value = F[i]
        if value < filtration_max:
            st.insert([i], filtration=F[i])
    for i in range(N_tot):  #add edges to the simplex tree
        for j in range(i):
            value = WeightedRipsFiltrationValue(p, F[i], F[j], distances[i][j])
            if value < filtration_max:
                st.insert([i, j], filtration=value)
    st.expansion(dimension_max)  # expand the simplex tree
    result_str = 'Weighted Rips Complex is of dimension ' + repr(st.dimension()) + ' - ' + \
        repr(st.num_simplices()) + ' simplices - ' + \
        repr(st.num_vertices()) + ' vertices.' +\
        ' Filtration maximal value is ' + str(filtration_max) + '.'
    print(result_str, flush=True)
    return st
예제 #2
0
def main():
	import persistence
	import matplotlib.pyplot as plt
	try:
		import gudhi
	except:
		print('gudhi package not installed')
		return

	# definir la filtration : on a un triangle vide et un triangle plein qui partagent une arete
	st = gudhi.SimplexTree()
	n_pts = 5
	time  = 0.0
	for n in range(n_pts):
		st.insert([n], time)
		time += 1.0
	for n in range(n_pts - 1, 0, -1):
		st.insert([0, n], time)
		time += 1.0
	diag = st.persistence(persistence_dim_max=True)
	gudhi.plot_persistence_diagram(diag)
	plt.show()
	diag2 = clean_diag(diag)
	landscape = persistence.persistence_landscape(diag2)
	persistence.plot_persistence_landscape(landscape)
	plt.show()
예제 #3
0
def RipsComplex(X, filtration_max=np.inf, dimension_max=3):
    '''
    Build the Rips filtration over X, until time filtration_max.
        
    Input: 
        X (np.array): size (N x M), representing a point cloud of R^M.
        filtration_max (float): filtration maximal value.
        dimension_max (int): maximal dimension to expand the complex. 
                             Must be k+1 to read k homology
    
    Output: 
        st (gudhi.SimplexTree): the Rips filtration of X.
        
    '''
    N = X.shape[0]
    distances = euclidean_distances(X)  #pairwise distances
    st = gudhi.SimplexTree()  #create an empty simplex tree
    for i in range(N):  #add vertices to the simplex tree
        st.insert([i], filtration=0)
    distances_threshold = distances < 2 * filtration_max
    indices = zip(*distances_threshold.nonzero())
    for u in indices:  #add edges to the simplex tree
        i = u[0]
        j = u[1]
        if i < j:  #add only edges [i,j] with i<j
            st.insert([i, j], filtration=distances[i, j] / 2)
    st.expansion(dimension_max)  #expand the flag complex
    result_str = 'Rips Complex is of dimension ' + repr(st.dimension()) + ' - ' + \
        repr(st.num_simplices()) + ' simplices - ' + \
        repr(st.num_vertices()) + ' vertices.' +\
        ' Filtration maximal value is ' + repr(filtration_max) + '.'
    print(result_str, flush=True)
    return st
예제 #4
0
 def persistence_diagram(self):
     list_dgm = []
     num_cols = self.clus_colors[list(self.clus_colors.keys())[0]].shape[0]
     for c in range(num_cols):
         col_vals = []
         for key, elem in self.clus_colors.items():
             col_vals.append(elem[c])
         st = gd.SimplexTree()
         list_simplices, list_vertices = self.st_.get_skeleton(
             1), self.st_.get_skeleton(0)
         for simplex in list_simplices:
             st.insert(simplex[0] + [-2], filtration=-3)
         min_val, max_val = min(col_vals), max(col_vals)
         for vertex in list_vertices:
             if st.find(vertex[0]):
                 st.assign_filtration(vertex[0],
                                      filtration=-2 +
                                      (col_vals[vertex[0][0]] - min_val) /
                                      (max_val - min_val))
                 st.assign_filtration(vertex[0] + [-2],
                                      filtration=2 -
                                      (col_vals[vertex[0][0]] - min_val) /
                                      (max_val - min_val))
         st.make_filtration_non_decreasing()
         dgm = st.persistence()
         for point in range(len(dgm)):
             b, d = dgm[point][1][0], dgm[point][1][1]
             b, d = min_val + (2 - abs(b)) * (
                 max_val - min_val), min_val + (2 - abs(d)) * (max_val -
                                                               min_val)
             dgm[point] = tuple([dgm[point][0], tuple([b, d])])
         list_dgm.append(dgm)
     return list_dgm
예제 #5
0
def makePlane(n: int, m: int):
    simp = gd.SimplexTree()

    counter = 0
    for i in range(0, n * m):
        simp.insert([counter], counter)
        counter += 1

    for j in range(0, m - 1):
        for i in range(0, n - 1):
            a = i + j * n
            b = i + 1 + j * n
            c = i + (j + 1) * n
            d = i + 1 + (j + 1) * n
            #print((a,b,c,d))
            simp.insert([a, b], counter)
            counter += 1
            simp.insert([a, c], counter)
            counter += 1
            simp.insert([a, d], counter)
            counter += 1
            simp.insert([b, d], counter)
            counter += 1
            simp.insert([c, d], counter)
            counter += 1
            simp.insert([a, b, d], counter)
            counter += 1
            simp.insert([a, c, d], counter)

    return simp
def build_gudhi_tree(patterns):
    print("building tree...")
    tree = gudhi.SimplexTree()
    for simplex, frequency in patterns.items():
        tree.insert(simplex, 1.0 / frequency)
    print("tree built...")
    return tree
예제 #7
0
def makeTorus(n: int, m: int):
    simp = gd.SimplexTree()

    counter = 0
    for i in range(0, n * m):
        simp.insert([counter], counter)
        counter += 1

    for j in range(0, m):
        for i in range(0, n):
            a = (i + j * n) % (m * n)
            b = ((i + 1 % n) + j * n) % (m * n)
            c = (i + ((j + 1) % m) * n) % (m * n)
            d = ((i + 1 % n) + ((j + 1) % m) * n) % (m * n)
            #print((a,b,c,d))
            simp.insert([a, b], counter)
            counter += 1
            simp.insert([a, c], counter)
            counter += 1
            simp.insert([a, d], counter)
            counter += 1

    for j in range(0, m):
        for i in range(0, n):
            a = (i + j * n) % (m * n)
            b = ((i + 1 % n) + j * n) % (m * n)
            c = (i + ((j + 1) % m) * n) % (m * n)
            d = ((i + 1 % n) + ((j + 1) % m) * n) % (m * n)
            #print((a,b,c,d))
            simp.insert([a, b, d], counter)
            counter += 1
            simp.insert([a, c, d], counter)
            counter += 1

    return simp
예제 #8
0
파일: SWL.py 프로젝트: 2019mohamed/SWL
def Build_Cliques(G):
    cliques = list(nx.algorithms.clique.enumerate_all_cliques(G))
    st = gudhi.SimplexTree()

    for clique in cliques:
        st.insert(clique)

    return st
def test_empty():
    st = gudhi.SimplexTree()
    st.persistence()
    assert st.lower_star_persistence_generators() == ([], [])
    g = st.flag_persistence_generators()
    assert np.array_equal(g[0], np.empty((0, 3)))
    assert g[1] == []
    assert np.array_equal(g[2], [])
    assert g[3] == []
def _get_base_simplex(A):
    num_vertices = A.shape[0]
    st = gd.SimplexTree()
    for i in range(num_vertices):
        st.insert([i], filtration=-1e10)
        for j in range(i + 1, num_vertices):
            if A[i, j] > 0:
                st.insert([i, j], filtration=-1e10)
    return st.get_filtration()
    def init_and_build_simplex_tree(self):
        self.st = gd.SimplexTree()

        for i in range(len(self.X) - 1):
            self.st.insert([i], filtration = self.Y[i])
            self.st.insert([i, i + 1], filtration = max(self.Y[i], self.Y[i + 1]))

        self.st.insert([i + 1], filtration = self.Y[i + 1])
        self.pd = PersistenceDiagram(self.st)
예제 #12
0
    def __init__(self, graph):
        simplex_tree = gudhi.SimplexTree()

        for node in graph:
            simplex_tree.insert([node], filtration=node)
            for el in (graph[node]):
                simplex_tree.insert([node, el], filtration=node + el)

        self.simplex_tree = simplex_tree
def build_cochains(simplex_tree, signals_top, function=np.sum):
    """Build the k-cochains using the weights on X (form the X-Y bipartite graph)
     and a chosen aggregating function. Features are aggregated by the provided functions.
     The function takes as input a list of values  and must return a single number.

    Parameters
    ----------
    simplex_tree :
        Gudhi simplex tree
    signals_top : ndarray
        Features for every maximal dimensional simplex = weights on the nodes of X (from bipartite graph X-Y)
    function : callable
        Functions that will aggregate the features to build the k-coachains, default=np.sum

    Returns
    -------
    signals : list of dictionaries
        List of dictionaries, one per dimension k.
        The dictionary's keys are the k-simplices. The
        dictionary's values are the k-cochains
    signals_top:
        Features for every maximal dimensional simplex
    """
    signal = [dict() for _ in range(simplex_tree.dimension() + 1)]
    for d in range(len(signals_top) - 1, -1, -1):
        for simplex, values in signals_top[d].items():
            st = gudhi.SimplexTree()
            st.insert(simplex)
            for face, _ in st.get_skeleton(st.dimension()):
                face = frozenset(face)
                signal[len(face) - 1].setdefault(face, []).extend(
                    signals_top[d][simplex])

    for d in range(len(signals_top) - 1, -1, -1):
        for simplex, values in signals_top[d].items():
            st = gudhi.SimplexTree()
            st.insert(simplex)
            for face, _ in st.get_skeleton(st.dimension()):
                face = frozenset(face)
                value = np.array(signal[len(face) - 1][face])
                signal[len(face) - 1][face] = int(
                    function(value))  ##Choose propagation function
            # signal[len(face)-1][face]=np.mean(value[value>0])
    return signal, signals_top
예제 #14
0
def MappingCylinderFiltration(st_X, st_Y, g):
    '''
    Creates a filtration of the mapping cylinder of g: st_X --> st_Y.
        
    Input:
        st_X (gudhi.SimplexTree): simplex tree, domain of g.
        st_Y (gudhi.SimplexTree): simplex tree, codomain of g.
        g (dict int:int): a simplicial map { (vertices of st_X):(vertices of st_Y)}.
    
    Output: 
        st_cyl (gudhi.SimplexTree): the mapping cylinder of g. 
    
    Example:
        st_X = gudhi.SimplexTree()
        st_X.insert([0,1,2], 0)
        st_X.remove_maximal_simplex([0,1,2])   #st is sphere
        g = {0:0,1:1,2:2}
        st_cyl = velour.MappingCylinderFiltration(st_X, st_X, g)   #st_cyl is a cylinder
        st_cyl.persistence(persistence_dim_max=True, homology_coeff_field = 2)
        ---> [(1, (0.0, inf)), (0, (0.0, inf))] 
    '''
    NewVerticesList = [tuple([v, 0]) for v in GetVerticesSimplexTree(st_X)] + [
        tuple([v, 1]) for v in GetVerticesSimplexTree(st_Y)
    ]
    NewVertices = {NewVerticesList[i]: i for i in range(len(NewVerticesList))}

    st_cyl = gudhi.SimplexTree()

    #insert st_X
    for filtr in st_X.get_filtration():
        simplex = filtr[0]
        simplex_cyl = [NewVertices[tuple([v, 0])] for v in simplex]
        st_cyl.insert(simplex_cyl, filtr[1])

    #insert st_Y
    for filtr in st_Y.get_filtration():
        simplex = filtr[0]
        simplex_cyl = [NewVertices[tuple([v, 1])] for v in simplex]
        st_cyl.insert(simplex_cyl, filtr[1])

    #connect st_X to st_Y
    for filtr in st_X.get_filtration():
        simplex_X = filtr[0]
        simplex_Y = [g[v] for v in simplex_X]
        simplex_X_cyl = [NewVertices[tuple([v, 0])] for v in simplex_X]
        simplex_Y_cyl = [NewVertices[tuple([v, 1])] for v in simplex_Y]
        simplex_cyl = simplex_X_cyl + simplex_Y_cyl  #union of the simplices
        simplex_cyl = list(set(simplex_cyl))  #unique
        st_cyl.insert(simplex_cyl, filtr[1])

    result_str = 'Mapping Cylinder Complex is of dimension ' + repr(st_cyl.dimension()) + ' - ' + \
                 repr(st_cyl.num_simplices()) + ' simplices - ' + \
                 repr(st_cyl.num_vertices()) + ' vertices.'
    print(result_str, flush=True)

    return st_cyl
def simplex_tree_constructor_ord(G):
    '''
    G a graph, list of edges [v,w]
    output gudhi simplex tree object
    '''

    st = gudhi.SimplexTree()

    for e in G:
        st.insert(e, 0.0)
    return st
예제 #16
0
def StructureW(X, F, distances, edge_max, dimension_max = 2):
    '''
    Compute the Rips-W filtration of a point cloud, weighted with the DTM
    values
        st = StructureW(X, F, distances, dimension_max = 2)
    Input:
    + X: a nxd numpy array representing n points in R^d
    + F: the values of a function over the set X
    + dim: the dimension of the skeleton of the Rips (dim_max = 1 or 2)
    Output:
    + st: a gd.SimplexTree with the constructed filtration (require Gudhi)
    '''
    nPts = X.shape[0]

    alpha_complex = gd.AlphaComplex(points=X)
    st = alpha_complex.create_simplex_tree()
    stDTM = gd.SimplexTree()
    for simplex in st.get_filtration():
        if len(simplex[0])==1:
            i = simplex[0][0]
            stDTM.insert([i], filtration  = F[i])
        if len(simplex[0])==2:
            i = simplex[0][0]
            j = simplex[0][1]
            if (j < i):
                filtr = (distances[i][j] + F[i] + F[j])/2
            else:
                filtr = (distances[j][i] + F[i] + F[j])/2

            stDTM.insert([i,j], filtration  = filtr)
    stDTM.expansion(dimension_max)
    st = stDTM

    """
    st = gd.SimplexTree()
    for i in range(nPts):
        st.insert([i], filtration = F[i])

    for i in range(nPts):
        for j in range(i):
            if distances[i][j]<edge_max:
                val = (distances[i][j] + F[i] + F[j])/2
                filtr = max([F[i], F[j], val])
                st.insert([i,j], filtration  = filtr)

    st.expansion(dimension_max)
    """

    result_str = 'Complex W is of dimension ' + repr(st.dimension()) + ' - ' + \
        repr(st.num_simplices()) + ' simplices - ' + \
        repr(st.num_vertices()) + ' vertices.'

    return st
def compute_extended_persistence_diagrams(graph, attribute):
    """
    Compute the 4 extended persistence diagrams for a graph, using Gudhi.
    """
    st = gd.SimplexTree()
    for u in graph.vs:
        st.insert([u.index], filtration=u[attribute])
    for e in graph.es:
        st.insert([e.source, e.target], filtration=e[attribute])
    st.extend_filtration()
    dgs = st.extended_persistence()
    return [[t[1] for t in dg] for dg in dgs]
예제 #18
0
    def compute_persistence_diagrams(self):
        """
        Compute the extended persistence diagrams of the Mapper simplicial complex associated to each color function.

        Returns:
            list_dgm (list of gudhi persistence diagrams): output extended persistence diagrams. There is one per color function.
        """
        num_cols, list_dgm = self.colors.shape[1], []

        # Compute an extended persistence diagram for each color
        for c in range(num_cols):

            # Retrieve all color values
            col_vals = {
                node_name: self.node_info_[node_name]["colors"][c]
                for node_name in self.node_info_.keys()
            }

            # Create a new simplicial complex by coning the Mapper with an extra point with name -2
            st = gd.SimplexTree()
            list_simplices, list_vertices = self.mapper_.get_skeleton(
                1), self.mapper_.get_skeleton(0)
            for (simplex, f) in list_simplices:
                st.insert(simplex + [-2], filtration=-3)

            # Assign ascending filtration values on the original simplices and descending filtration values on the coned simplices
            min_val, max_val = min(col_vals), max(col_vals)
            for (vertex, f) in list_vertices:
                if st.find(vertex):
                    st.assign_filtration(vertex,
                                         filtration=-2 +
                                         (col_vals[vertex[0]] - min_val) /
                                         (max_val - min_val))
                    st.assign_filtration(vertex + [-2],
                                         filtration=2 -
                                         (col_vals[vertex[0]] - min_val) /
                                         (max_val - min_val))

            # Compute persistence
            st.make_filtration_non_decreasing()
            dgm = st.persistence()

            # Output extended persistence diagrams
            for point in range(len(dgm)):
                b, d = dgm[point][1][0], dgm[point][1][1]
                b, d = min_val + (2 - abs(b)) * (
                    max_val - min_val), min_val + (2 - abs(d)) * (max_val -
                                                                  min_val)
                dgm[point] = tuple([dgm[point][0], tuple([b, d])])
            list_dgm.append(dgm)

        return list_dgm
예제 #19
0
def compute_betti(facetlist, highest_dim):
    """
    This function computes the betti numbers of the j-skeleton of the simplicial complex given in the shape of a facet
    list.
    Parameters
    ----------
    facetlist (list of list) : Sublists are facets with the index of the nodes in the facet.
    highest_dim (int) : Highest dimension allowed for the facets. If a facet is of higher dimension in the facet list,
                        the algorithm breaks it down into it's N choose k faces. The resulting simplicial complexe is
                        called the j-skeleton, where j = highest_dim.
    Returns
    -------
    The (highest_dim - 1) Betti numbers of the simplicial complexe.
    """

    st = gudhi.SimplexTree()
    for facet in facetlist:

        # This condition and the loop it contains break a facet in all its n choose k faces. This is more
        # memory efficient than inserting a big facet because of the way GUDHI's SimplexTree works. The
        # dimension of the faces has to be at least one unit bigger than the skeleton we use.
        if len(facet) > highest_dim + 1:
            for face in itertools.combinations(facet, highest_dim + 1):
                st.insert(face)
        else:
            st.insert(facet)

    # We need to add a facet that has a size equivalent to the Betti we want to compute + 2 because GUDHI cannot compute
    # Betti N if there are no facets of size N + 2. As an example, if we take the 1-skeleton, there are, of course, no
    # facet of size higher than 2 and does not compute Betti 1. As a result, highest_dim needs to be 1 unit higher than
    # the maximum Betti number we want to compute. Moreover, we need to manually add a facet of size N + 2 (highest_dim + 1)
    # for the case where there are no such facets in the original complex. As an example, if we have two empty triangles,
    # GUDHI kinda assumes it's a 1-skeleton, and just compute Betti 0, although we would like to know that Betti 1 = 2.
    # The only way, it seems, to do so it to add a facet of size N + 2 (highest_dim + 1)
    # It also need to be disconnected from our simplicial complex because we don't want it to create unintentional holes.
    # This has the effect to add a componant in the network, hence why we substract 1 from Betti 0 (see last line of the function)

    # We add + 1 + 2 for the following reasons. First, we need a new facet of size highest_dim + 1 because of the reason
    # above. The last number in arange is not considered (ex : np.arange(0, 3) = [0, 1, 2], so we need to add 1 again.
    # Moreover, we cannot start at index 0 (because 0 is in the complex) nor -1 because GUDHI returns an error code 139.
    # If we could start at -1, it would be ok only with highest_dim + 3, but since we start at -2, we need to go one
    # index further, hence + 1.
    disconnected_facet = [
        label for label in np.arange(-2, -(highest_dim + 1 + 2), -1)
    ]
    st.insert(disconnected_facet)

    # This function has to be launched in order to compute the Betti numbers
    st.persistence()
    bettis = st.betti_numbers()
    bettis[0] = bettis[0] - 1
    return bettis
예제 #20
0
def get_persistence_from_audio(audio_wave,
                               sample=22050,
                               length=5,
                               graph=False):
    simplex_up = gd.SimplexTree()  # for the upper level persistence data
    simplex_dw = gd.SimplexTree()  # for the lower level persistence data
    for i in np.arange(len(audio_wave)):
        simplex_up.insert([i, i + 1], filtration=audio_wave[i])
        simplex_dw.insert([i, i + 1], filtration=-audio_wave[i])
    for i in np.arange(len(audio_wave) - 1):
        simplex_up.insert([i, i + 1], filtration=audio_wave[i])
        simplex_dw.insert([i, i + 1], filtration=-audio_wave[i])
    simplex_up.initialize_filtration()
    simplex_dw.initialize_filtration()
    dig_up = simplex_up.persistence()
    dig_dw = simplex_dw.persistence()
    if graph:
        plt.figure()
        lr_disp.waveplot(audio_wave, sr=sample)
        plt.title("Audio Wave")
        plt.show()
        plt.figure()
        gd.plot_persistence_barcode(dig_up)
        plt.title("Upper Level Persistence Barcode")
        plt.show()
        plt.figure()
        gd.plot_persistence_barcode(dig_dw)
        plt.title("Sub Levels Persistence Barcode")
        plt.show()
        plt.figure()
        gd.plot_persistence_diagram(dig_up)
        plt.title("Upper Level Persistence Diagram")
        plt.show()
        plt.figure()
        gd.plot_persistence_diagram(dig_dw)
        plt.title("Sub Levels Persistence Diagram")
        plt.show()
    return dig_up, dig_dw  # NOTE: this does not filter out infinite values
예제 #21
0
def build_simplex_tree(facetlist, highest_dim):
    st = gudhi.SimplexTree()
    for facet in facetlist:

        # This condition and the loop it contains break a facet in all its n choose k faces. This is more
        # memory efficient than inserting a big facet because of the way GUDHI's SimplexTree works. The
        # dimension of the faces has to be at least one unit bigger than the skeleton we use.
        if len(facet) > highest_dim + 1:
            for face in itertools.combinations(facet, highest_dim + 1):
                st.insert(face)
        else:
            st.insert(facet)

    return st
예제 #22
0
def SimplexTree(stbase, fct, dim, card):
    # Parameters: stbase (array containing the name of the file where the simplex tree is located)
    #             fct (function values on the vertices of stbase),
    #             dim (homological dimension),
    #             card (number of persistence diagram points, sorted by distance-to-diagonal)

    # Copy stbase in another simplex tree st
    st = gd.SimplexTree()
    f = open(stbase[0], "r")
    for line in f:
        ints = line.split(" ")
        s = [int(v) for v in ints[:-1]]
        st.insert(s, -1e10)
    f.close()

    # Assign new filtration values
    for i in range(st.num_vertices()):
        st.assign_filtration([i], fct[i])
    st.make_filtration_non_decreasing()

    # Compute persistence diagram
    dgm = st.persistence()

    # Get vertex pairs for optimization. First, get all simplex pairs
    pairs = st.persistence_pairs()

    # Then, loop over all simplex pairs
    indices, pers = [], []
    for s1, s2 in pairs:
        # Select pairs with good homological dimension and finite lifetime
        if len(s1) == dim + 1 and len(s2) > 0:
            # Get IDs of the vertices corresponding to the filtration values of the simplices
            l1, l2 = np.array(s1), np.array(s2)
            i1 = l1[np.argmax(fct[l1])]
            i2 = l2[np.argmax(fct[l2])]
            indices.append(i1)
            indices.append(i2)
            # Compute lifetime
            pers.append(st.filtration(s2) - st.filtration(s1))

    # Sort vertex pairs wrt lifetime
    perm = np.argsort(pers)
    indices = list(np.reshape(indices, [-1, 2])[perm][::-1, :].flatten())

    # Pad vertex pairs
    indices = indices[:2 * card] + [
        0 for _ in range(0, max(0, 2 * card - len(indices)))
    ]
    return list(np.array(indices, dtype=np.int32))
예제 #23
0
def init_freudenthal_2d(width, height):
    """
	Freudenthal triangulation of 2d grid
	"""
    # row-major format
    # 0-cells
    # global st
    st = gudhi.SimplexTree()
    count = 0
    for i in range(height):
        for j in range(width):
            ind = i * width + j

            st.insert([ind], max_value([ind]))
            count += 1
    # 1-cells
    # pdb.set_trace()
    for i in range(height):
        for j in range(width - 1):
            ind = i * width + j
            st.insert([ind, ind + 1], max_value([ind, ind + 1]))
            count += 1
    # pdb.set_trace()
    for i in range(height - 1):
        for j in range(width):
            ind = i * width + j
            st.insert([ind, ind + width], max_value([ind, ind + width]))
            count += 1
    # pdb.set_trace()
    # 2-cells + diagonal 1-cells
    for i in range(height - 1):
        for j in range(width - 1):
            ind = i * width + j
            # diagonal
            st.insert([ind, ind + width + 1], max_value([ind,
                                                         ind + width + 1]))
            count += 1
            # 2-cells
            st.insert([ind, ind + 1, ind + width + 1],
                      max_value([ind, ind + 1, ind + width + 1]))
            count += 1
            st.insert([ind, ind + width, ind + width + 1],
                      max_value([ind, ind + width, ind + width + 1]))
            count += 1
        # pdb.set_trace()
    print(count, "counts")
    return st
예제 #24
0
def AlphaWeightedRipsFiltration(X,
                                F,
                                p,
                                dimension_max=2,
                                filtration_max=np.inf):
    '''
    /!\ this is a heuristic method, to speed-up the computation
    It computes the weighted Rips filtration as a subset of the alpha complex

    Input:
    X: a nxd numpy array representing n points in R^d
    F: an array of length n,  representing the values of a function on X
    p: a parameter in [0, +inf) or np.inf
    filtration_max: maximal filtration value of simplices when building the complex
    dimension_max: maximal dimension to expand the complex

    Output:
    st: a gudhi.SimplexTree
    '''
    N_tot = X.shape[0]
    distances = euclidean_distances(X)  # compute the pairwise distances

    st_alpha = gudhi.AlphaComplex(points=X).create_simplex_tree()
    st = gudhi.SimplexTree()  # create an empty simplex tree

    for simplex in st_alpha.get_skeleton(
            2):  # add vertices with corresponding filtration value
        if len(simplex[0]) == 1:
            i = simplex[0][0]
            st.insert([i], filtration=F[i])
        if len(simplex[0]
               ) == 2:  # add edges with corresponding filtration value
            i = simplex[0][0]
            j = simplex[0][1]
            value = Filtration_value(p, F[i], F[j], distances[i][j])
            st.insert([i, j], filtration=value)

    st.expansion(dimension_max)  # expand the complex

    result_str = 'Alpha Weighted Rips Complex is of dimension '+repr(st.dimension())+' - '+ \
                 repr(st.num_simplices())+' simplices - '+ \
                 repr(st.num_vertices())+' vertices.'+ \
                 ' Filtration maximal value is '+str(filtration_max)+'.'
    print(result_str)

    return st
def test_lower_star_generators():
    st = gudhi.SimplexTree()
    st.insert([0, 1, 2], -10)
    st.insert([0, 3], -10)
    st.insert([1, 3], -10)
    st.assign_filtration([2], -1)
    st.assign_filtration([3], 0)
    st.assign_filtration([0], 1)
    st.assign_filtration([1], 2)
    st.make_filtration_non_decreasing()
    st.persistence(min_persistence=-1)
    g = st.lower_star_persistence_generators()
    assert len(g[0]) == 2
    assert np.array_equal(g[0][0], [[0, 0], [3, 0], [1, 1]])
    assert np.array_equal(g[0][1], [[1, 1]])
    assert len(g[1]) == 2
    assert np.array_equal(g[1][0], [2])
    assert np.array_equal(g[1][1], [1])
예제 #26
0
def AlphaDTMFiltration(X, m, p, dimension_max=2, filtration_max=np.inf):
    '''
    /!\ this is a heuristic method, that speeds-up the computation.
    It computes the DTM-filtration seen as a subset of the Delaunay filtration.
    
    Input:
        X (np.array): size Nxn, representing N points in R^n.
        m (float): parameter of the DTM, in [0,1). 
        p (float): parameter of the DTM-filtration, in [0, +inf) or np.inf.
        dimension_max (int, optional): maximal dimension to expand the complex.
        filtration_max (float, optional): maximal filtration value of the filtration.
    
    Output:
        st (gudhi.SimplexTree): the alpha-DTM filtration.
    '''
    N_tot = X.shape[0]
    alpha_complex = gudhi.AlphaComplex(points=X)
    st_alpha = alpha_complex.create_simplex_tree()
    Y = np.array([alpha_complex.get_point(i) for i in range(N_tot)])
    distances = euclidean_distances(Y)  #computes the pairwise distances
    DTM_values = DTM(
        X, Y, m
    )  #/!\ in 3D, gudhi.AlphaComplex may change the ordering of the points

    st = gudhi.SimplexTree()  #creates an empty simplex tree
    for simplex in st_alpha.get_skeleton(
            2):  #adds vertices with corresponding filtration value
        if len(simplex[0]) == 1:
            i = simplex[0][0]
            st.insert([i], filtration=DTM_values[i])
        if len(simplex[0]
               ) == 2:  #adds edges with corresponding filtration value
            i = simplex[0][0]
            j = simplex[0][1]
            value = WeightedRipsFiltrationValue(p, DTM_values[i],
                                                DTM_values[j], distances[i][j])
            st.insert([i, j], filtration=value)
    st.expansion(dimension_max)  #expands the complex
    result_str = 'Alpha Weighted Rips Complex is of dimension ' + repr(st.dimension()) + ' - ' + \
        repr(st.num_simplices()) + ' simplices - ' + \
        repr(st.num_vertices()) + ' vertices.' +\
        ' Filtration maximal value is ' + str(filtration_max) + '.'
    print(result_str)
    return st
예제 #27
0
def apply_graph_extended_persistence(A, filtration_val):
    num_vertices = A.shape[0]
    (xs, ys) = np.where(np.triu(A))
    st = gd.SimplexTree()
    for i in range(num_vertices):
        st.insert([i], filtration=-1e10)
    for idx, x in enumerate(xs):        
        st.insert([x, ys[idx]], filtration=-1e10)
    for i in range(num_vertices):
        st.assign_filtration([i], filtration_val[i])
    st.make_filtration_non_decreasing()
    st.extend_filtration()
    LD = st.extended_persistence()
    dgmOrd0, dgmRel1, dgmExt0, dgmExt1 = LD[0], LD[1], LD[2], LD[3]
    dgmOrd0 = np.vstack([np.array([[ min(p[1][0],p[1][1]), max(p[1][0],p[1][1]) ]]) for p in dgmOrd0 if p[0] == 0]) if len(dgmOrd0) else np.empty([0,2])
    dgmRel1 = np.vstack([np.array([[ min(p[1][0],p[1][1]), max(p[1][0],p[1][1]) ]]) for p in dgmRel1 if p[0] == 1]) if len(dgmRel1) else np.empty([0,2])
    dgmExt0 = np.vstack([np.array([[ min(p[1][0],p[1][1]), max(p[1][0],p[1][1]) ]]) for p in dgmExt0 if p[0] == 0]) if len(dgmExt0) else np.empty([0,2])
    dgmExt1 = np.vstack([np.array([[ min(p[1][0],p[1][1]), max(p[1][0],p[1][1]) ]]) for p in dgmExt1 if p[0] == 1]) if len(dgmExt1) else np.empty([0,2])
    return dgmOrd0, dgmExt0, dgmRel1, dgmExt1
예제 #28
0
def build_series(G, functions, start, time_step, time_count):
    """
    Args:
        G : networkX.Graph(), a graph
        functions : list of functions (one function for each node of G)
        T : list of time slices (for which we sample the functions)
        
    Returns:
        This function returns a sequence of node labelings on K, where K is 
        the clique complex built on the graph G (there is a node labeling 
        for each time slice in T), put in the form of an array np.ndarray() 
        of size |G| x |T|.
    """
    T = []
    for i in range(int(time_count)):
        T.append(start)
        start += time_step

    n = G.number_of_nodes()
    time_count = len(T)

    assert n == len(functions), "There has to be a function for each node."

    K = gd.SimplexTree()
    for e in G.edges:
        K.insert(e)
    for n in G.nodes:
        K.insert([n])
    K.expansion(3)

    complex_series = []
    complex_series += time_count * [K]

    for j in range(time_count):

        nodes = list(complex_series[j].get_skeleton(0))

        for i in range(n):

            complex_series[j].assign_filtration(nodes[i][0],
                                                functions[i](T[j]))

    return complex_series
예제 #29
0
def CopySimplexTree(st):
    '''
    Hard copy of a simplex tree.
    
    Input:
        st (gudhi.SimplexTree): the simplex tree to be copied.
    
    Output:
        st1 (gudhi.SimplexTree): a copy of the simplex tree.
        
    Example:
        st = gudhi.SimplexTree()
        print(st)
        ---> <gudhi.SimplexTree object at 0x7fded6968e30> 
        velour.CopySimplexTree(st)
        ---> <gudhi.SimplexTree at 0x7fded6968d90>
    '''
    st2 = gudhi.SimplexTree()
    for filtr in st.get_filtration():
        st2.insert(filtr[0], filtr[1])
    return st2
예제 #30
0
def WeightedRipsFiltration(X, F, p, dimension_max=2, filtration_max=np.inf):
    '''
    Compute the weighted Rips filtration of a point cloud, weighted with the 
    values F, and with parameter p
    
    Input:
    X: a nxd numpy array representing n points in R^d
    F: an array of length n,  representing the values of a function on X
    p: a parameter in [0, +inf) or np.inf
    filtration_max: maximal filtration value of simplices when building the complex
    dimension_max: maximal dimension to expand the complex
    
    Output:
    st: a gudhi.SimplexTree 
    '''
    N_tot = X.shape[0]
    distances = euclidean_distances(X)  # compute the pairwise distances
    st = gudhi.SimplexTree()  # create an empty simplex tree

    for i in range(N_tot):  # add vertices to the simplex tree
        value = F[i]
        if value < filtration_max:
            st.insert([i], filtration=F[i])
    for i in range(N_tot):  # add edges to the simplex tree
        for j in range(i):
            value = WeightedRipsFiltrationValue(p, F[i], F[j], distances[i][j])
            if value < filtration_max:
                st.insert([i, j], filtration=value)

    st.expansion(dimension_max)  # expand the simplex tree

    result_str = 'Weighted Rips Complex is of dimension ' + repr(st.dimension()) + ' - ' + \
        repr(st.num_simplices()) + ' simplices - ' + \
        repr(st.num_vertices()) + ' vertices.' +\
        ' Filtration maximal value is ' + str(filtration_max) + '.'
    print(result_str)

    return st