def build_complex(self, simplex_array): """Compute faces and boundary operators for all dimensions""" N,K = simplex_array.shape s = simplex_array.copy() parity = simplex_array_parity(s) s.sort() simplices = [s] chain_complex = [] parities = [parity] while s.shape[1] > 1: s,boundary = simplex_array_boundary(s,parity) parity = zeros(s.shape[0],dtype=s.dtype) simplices.append( s ) chain_complex.append( boundary ) parities.append( parity ) B0 = sparse.csr_matrix( (1,len(s)), dtype='uint8') chain_complex.append( B0 ) simplices = simplices[::-1] chain_complex = chain_complex[::-1] parities = parities[::-1] 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) ] for n in range(K): data = self.data_cache() data.d = cochain_complex[n] data.boundary = chain_complex[n] data.complex = self data.dim = n data.simplices = simplices[n] data.num_simplices = len(data.simplices) data.simplex_parity = parities[n] self.append(data)
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