def rips_chain_complex(simplices): """Construct the boundary operators for the Rips complex Constructs the boundary operators for the Rips complex for a given a list of simplex arrays. Parameters ---------- simplices : list of arrays List of length D, where simplices[i] is the simplex array representing the i-dimensional simplices. Returns ------- Bs : list of sparse matrices List of length D + 1 where Bs[i] is the boundary operator for the i-dimensional simplices. Examples -------- TODO """ Bs = [] dtype = 'float32' simplices = [asarray(x) for x in simplices] B0 = csc_matrix( (1, len(simplices[0]) ), dtype=dtype ) Bs.append( B0 ) if len(simplices) == 1: B1 = csc_matrix( (len(simplices[0]), 1), dtype=dtype ) Bs.append(B1) return Bs B1 = empty( 2*len(simplices[1]), dtype=dtype ) B1[0::2] = -1 B1[1::2] = 1 B1 = csc_matrix( ( B1, simplices[1].ravel(), arange(0, 2*(len(simplices[1]) + 1), 2)), \ shape=(len(simplices[0]), len(simplices[1])) ) Bs.append( B1 ) for f,s in zip(simplices[1:-1],simplices[2:]): k = f.shape[1] faces = empty(( len(s), (k+1), k),dtype=s.dtype) for i in range(k+1): faces[:,i,:i] = s[:, : i ] faces[:,i,i:] = s[:,i+1: ] indptr = arange(0, (k+1)*(len(s) + 1), k+1) indices = simplex_array_searchsorted(f, faces.reshape(-1,k) ) data = empty( faces.shape[:-1], dtype=dtype ) for i in range(k+1): data[:,i] = (-1)**i data = data.ravel() Bs.append( csc_matrix( (data,indices,indptr), shape=(len(f),len(s)) ) ) return Bs
def __init__(self, simplices): """Construct an abstract simplicial complex Parameters ---------- simplices : list of arrays Maximal simplices of each dimension TODO Examples -------- >>> from pydec.dec import abstract_simplicial_complex >>> from numpy import array >>> simplices = [array([[4]]), array([[0,3]])] >>> asc = abstract_simplicial_complex(simplices) TODO >>> print rc.simplices[0] >>> print rc.simplices[1] Notes ----- TODO explain input handling """ # convert array-like objects to arrays simplices = [atleast_2d(s) for s in simplices] # find top simplex dimension D = max([s.shape[1] for s in simplices]) - 1 # convert simplices list to canonical simplex_array list representation old_simplices = simplices simplices = [None] * (D + 1) for s in old_simplices: simplices[s.shape[1] - 1] = s # top most simplex array s = simplices[-1].copy() parity = simplex_array_parity(s) s.sort() chain_complex = [None] * (D + 1) for d in range(D - 1, -1, -1): s,B = simplex_array_boundary(s,parity) if simplices[d] is not None: old_s = s # sort columns to ensure user-defined faces are in canonical format simplices[d].sort() # merge user-defined faces with boundary faces s = vstack((s,simplices[d])) # sort rows to bring equivalent elements together s = s[lexsort(s.T[::-1])] # find unique simplices mask = -hstack((array([False]),alltrue(s[1:] == s[:-1],axis=1))) s = s[mask] # indices of the boundary faces in the full face array remap = simplex_array_searchsorted(s, old_s) # remap indices of boundary operator B = B.tocoo(copy=False) B = sparse.coo_matrix((B.data, (remap[B.row], B.col)), (s.shape[0], B.shape[1])) B = B.tocsr() # faces are already in canonical format, so parity is even parity = zeros(s.shape[0],dtype=s.dtype) simplices[d] = s chain_complex[d+1] = B # compute 0-simplices and boundary operator simplices[0] = arange(simplices[0].max() + 1).reshape(-1,1) chain_complex[0] = sparse.csr_matrix( (1,len(s)), dtype='uint8') # store the cochain complex Bn = chain_complex[-1] cochain_complex = [ B.T for B in chain_complex[1:] ] cochain_complex += [ sparse.csc_matrix( (1, Bn.shape[1]), dtype=Bn.dtype) ] # store the data members self.simplices = simplices self._chain_complex = chain_complex self._cochain_complex = cochain_complex