def remove_nodes(self, nodes, verbose=False): ''' Remove nodes from the jusha output. @param nodes: list of nodes. @type nodes: list of integers ''' nodes = list(nodes) if verbose: print("Cleanup: Remove the nodes {0}.".format(nodes)) if len(nodes) == 0: return # update the level sets for ls in dict_values(self.levelsets): ls.nodes.difference_update(nodes) # make a map from old node indices to new indices nodes.sort() offset = 0 c = nodes[offset] node_map = [None] * self.num_nodes for i in range(self.num_nodes): if i == c: offset += 1 c = nodes[offset] if len(nodes) > offset else None else: node_map[i] = i - offset nm = lambda x: node_map[x] # update the simplicial complex D = dict() for s, v in dict_items(self.simplices.as_dict()): if node_map[s[0]] is not None: D[tuple(map(nm, s))] = v self.simplices = simpl_complex(D) # update the list of nodes self.nodes = [self.nodes[i] for i in range(self.num_nodes) \ if i not in nodes ]
def clear_nodes(self): self.nodes = [] self.simplices = simpl_complex() for ls in dict_values(self.levelsets): ls.nodes = set()
def generate_complex(self, cover=None, verbose=False, min_sizes=(), max_dim=-1): ''' Generate the simplicial complex from the intersections of the point sets for each node. The weight of each simplex is the number of data points in the intersection. This is a generic algorithm which works in every case but might not be fast. E.g. it tests every pair of nodes for intersecting point sets, wheres it is often known from the patch arrangement in the cover that many patches do not intersect. Feel free to use a different scheme when speed is an issue. @param verbose: print progress messages? @type verbose: bool ''' ''' The data scheme for the dictionary S: For v1<v2<...<vn, S[(v1,v2,...,v(n-1)][vn] stores the data points in the intersection of the patches U_v1, ..., U_vn if it is nonempty. This is exactly the condition that (v1,...,vn) form simplex. We iteratively generate this data, starting from S[()][i] = (data points for the node i). ''' self.simplices = simpl_complex() dim = 0 if verbose: print("There are {0} nodes.".format(self.num_nodes)) min_nodesize = 1 if len(min_sizes) < 1 else min_sizes[0] S0 = dict() for i, n in enumerate(self.nodes): if n.points.size >= min_nodesize: S0[i] = n.points self.add_simplex((i, ), len(n.points)) S = {(): S0} #S = {() : dict([(i, n.points) for i, n in enumerate(self.nodes) \ # if n.points.size>=min_nodesize])} if verbose: print("Generate the simplicial complex.") while S: # while S is not empty #@xl add a loop stopper for not computing on higher dimensions if dim > 2: break dim += 1 if max_dim >= 0 and dim > max_dim: break min_simplexsize = 1 if len(min_sizes) <= dim else min_sizes[dim] if verbose: print("Collect simplices of dimension {0}:".format(dim)) T = defaultdict(dict) for i1, Si1 in dict_items(S): for i2, i3 in combinations(Si1, 2): intersection = intersect1d(Si1[i2], Si1[i3], assume_unique=True) if intersection.size >= min_simplexsize: if i2 > i3: # ensure i2<i3 i2, i3 = i3, i2 self.add_simplex(i1 + (i2, i3), weight=intersection.size) T[i1 + (i2, )][i3] = intersection S = T if verbose: print("There are {0} simplices of dimension {1}.".\ format(sum(map(len,dict_values(S))), dim) )