def unidecode_edge(edge): if edge.is_atom(): atom = edge label = unidecode(atom.root().replace('_', '')) if label == atom.root() or len(label) == 0 or not label[0].isalpha(): return edge else: parts = (label, ) + tuple(atom.parts()[1:]) return hedge('/'.join(parts)) else: return hedge(tuple(unidecode_edge(item) for item in edge))
def search(self, pattern): """Returns generator for all the edges that match a pattern. Patterns are themselves edges. They can match families of edges by employing special atoms: -> '*' represents a general wildcard (matches any edge) -> '@' represents an atomic wildcard (matches any atom) -> '&' represents a non-atomic wildcard (matches any non-atom) -> '...' at the end indicates an open-ended pattern. The pattern can be a string, that must represent an edge. Examples: '(is/Pd graphbrain/C @)' '(says/pd * ...)' Atomic patterns can also be used to match all edges in the hypergraph (*), all atoms (@), and all non-atoms (&). """ pattern = hedge(pattern) if pattern.is_atom() and len(pattern.parts()) == 1: if pattern[0][0] == '*': return self.all() elif pattern[0][0] == '@': return self.all_atoms() elif pattern[0][0] == '&': return self.all_non_atoms() return self._search(pattern)
def add(self, edge, primary=True, count=False): """Adds an edge if it does not exist yet, returns same edge. All children are recursively added as non-primary edge, for indexing purposes. Edges can be passed in both Hyperedge or string format. Keyword arguments: primary -- edge is primary, meaning, for example, that it counts towards degrees. Non-primary edges are used for indexing purposes, for example to make it easy to find the subedges contained in primary edges when performing queries. count -- an integer counter attribute is added to the edge. If the edge already exists, the counter is incremented. """ if isinstance(edge, Hyperedge): if edge.is_atom(): return edge else: # recursively add all sub-edges as non-primary edges. for child in edge: self.add(child, primary=False) # add entity itself self._add(edge, primary=primary) # increment counter if requested if count: self.inc_attribute(edge, 'count') return edge elif edge: return self.add(hedge(edge), primary=primary, count=count) return None
def clean_edge(edge): if not edge.is_atom(): return hedge([clean_edge(subedge) for subedge in edge]) root = edge.label() root = unidecode(root) root = root.replace('_', '').replace('.', '') return build_atom(root, *edge.parts()[1:])
def search(self, pattern, strict=True): """Returns generator for all the edges that match a pattern. Patterns are themselves edges. They can match families of edges by employing special atoms: -> '*' represents a general wildcard (matches any edge) -> '.' represents an atomic wildcard (matches any atom) -> '(*)' represents a non-atomic wildcard (matches any non-atom) -> '...' at the end indicates an open-ended pattern. The pattern can be a string, that must represent an edge. Examples: '(is/Pd graphbrain/C .)' '(says/pd * ...)' Atomic patterns can also be used to match all edges in the hypergraph: *, all atoms: ., and all non-atoms: (*). Keyword argument: strict -- strictly match the search pattern, or allow for more general atoms to match target atome (e.g. plays/P matches plays/Pd.so in non-strict mode, but only exactl plays/Pd.so matches it in strict mode) Non-strict mode is slower. (default True) """ pattern = hedge(pattern) if pattern.is_atom() and len(pattern.parts()) == 1: if pattern.parens: return self.all_non_atoms() elif pattern[0][0] == '*': return self.all() elif pattern[0][0] == '.': return self.all_atoms() return self._search(pattern, strict=strict)
def get_int_attribute(self, edge, attribute, or_else=None): """Returns attribute as integer value. or_else -- value to return if the entity does not have the give attribute. (default None) """ return self._get_int_attribute(hedge(edge), attribute, or_else=or_else)
def remove(self, edge, deep=False): """Removes an edge. Keyword argument: deep -- recursively remove all subedges (default False) """ self._remove(hedge(edge), deep=deep)
def star(self, center, limit=None): """Returns generator of the edges that contain the center. Keyword argument: limit -- maximum number of results to return, infinite if None """ return self._star(hedge(center), limit=limit)
def get_str_attribute(self, edge, attribute, or_else=None): """Returns attribute as string. Keyword argument: or_else -- value to return if the entity does not have the given attribute. (default None) """ return self._get_str_attribute(hedge(edge), attribute, or_else=or_else)
def count(self, pattern, strict=True): """Number of edges that match a pattern. See search() method for an explanation of patterns. """ pattern = hedge(pattern) n = 0 for _ in self._search(pattern, strict=strict): n += 1 return n
def infer_concepts(edge): concepts = set() if edge.type()[0] == 'C': concepts.add(edge) if not edge.is_atom(): mc = main_concepts(edge) if len(mc) == 1: concepts.add(mc[0]) concept_sets = [infer_concepts(subedge) for subedge in edge[1:]] for product in itertools.product(*concept_sets): concepts.add(hedge((edge[0], ) + product)) return concepts
def add_to_sequence(self, name, edge, primary=True): """Adds 'edge' to sequence 'name'.""" seq_atom = str2atom(name) seq_attrs_edge = hedge((const.sequence_attrs_pred, seq_atom)) pos = self.get_int_attribute(seq_attrs_edge, 'size') if pos is None: pos = 0 result = self.add((const.sequence_pred, seq_atom, str(pos), edge)) self.set_attribute(seq_attrs_edge, 'size', pos + 1) if primary: self.set_primary(edge, True) return result
def count(self, pattern): """Number of edges that match a pattern. See search() method for an explanation of patterns. """ pattern = hedge(pattern) if pattern.is_atom() and len(pattern.parts()) == 1: if pattern[0][0] == '*': return self.edge_count() elif pattern[0][0] == '@': return self.atom_count() elif pattern[0][0] == '&': return self.edge_count() - self.atom_count() n = 0 for _ in self._search(pattern): n += 1 return n
def exists(self, edge): """Checks if the given edge exists.""" return self._exists(hedge(edge))
def set_attribute(self, edge, attribute, value): """Sets the value of an attribute.""" return self._set_attribute(hedge(edge), attribute, value)
def deep_degree(self, edge): """Returns the deep degree of an entity.""" return self._deep_degree(hedge(edge))
def is_primary(self, edge): """Check if an edge is primary.""" return self._is_primary(hedge(edge))
def set_primary(self, edge, value): """Make edge primary if value is True, make it non-primary otherwise. """ self._set_primary(hedge(edge), value)
def match(self, pattern, strict=True, curvars={}): pattern = hedge(pattern) return self._match(pattern, strict=strict, curvars=curvars)
def dec_attribute(self, edge, attribute): """Increments an attribute of an entity.""" return self._dec_attribute(hedge(edge), attribute)
def inc_attribute(self, edge, attribute): """Increments an attribute of an entity, sets initial value to 1 if attribute does not exist. """ return self._inc_attribute(hedge(edge), attribute)
def match(self, pattern, curvars={}): pattern = hedge(pattern) return self._match(pattern, curvars=curvars)