Example #1
0
 def query(self, result_atomspace, query):
     res_set = self.intersect(query)
     # add all possible results to tmp atomspace and run query
     # what is called filter step in graph indexing literature
     tmp = AtomSpace()
     atom_str = self._storage.get_atoms(res_set)
     for item in atom_str:
         tmp.add_atom(scheme_eval_h(tmp, item))
     # pack query in BindLink
     q = tmp.add_link(types.BindLink, [query, query])
     results = execute_atom(tmp, q)
     result_atoms = set()
     for atom in results.out:
         result_atoms.add(result_atomspace.add_atom(atom))
     return result_atoms
Example #2
0
def add_to_atomspace(atoms: set[Atom] | list[Atom],
                     atomspace: AtomSpace) -> None:
    """Add all atoms to the atomspace."""

    for atom in atoms:
        atomspace.add_atom(atom)
Example #3
0
class Index:
    def __init__(self, storage: Storage):
        self.pattern_space = AtomSpace()
        self.semantic_space = AtomSpace()
        # storage maps index to atom
        self._storage = storage
        # index maps subgraph pattern to matching atom ids
        self._index = dict()

    def add_toplevel_pattern(self, atom):
        args = [
            self.pattern_space.add_node(types.VariableNode, '$X' + str(i))
            for i in range(atom.arity)
        ]
        l = self.pattern_space.add_link(atom.type, args)
        bindlink = self.pattern_space.add_link(types.BindLink, [l, l])
        self.add_pattern(bindlink)

    def add_semantic_pattern(self, atom):
        # find all nodes, that inherit from some atom from semantic atomspace
        # replace such atoms by variable nodes
        result = replace(atom, self.semantic_space, self.pattern_space, dict())
        pattern = self.pattern_space.add_link(types.BindLink, [result, result])
        self.add_pattern(pattern)

    def add_data(self, data):
        idx, new = self._storage.add_atom(data)
        if not new:
            return
        assert data.is_link()
        # self.add_toplevel_pattern(data)
        self.add_semantic_pattern(data)

        tmp = create_child_atomspace(self.pattern_space)
        content = tmp.add_atom(data)
        self.update_index(tmp, content, idx)

    def update_index(self, atomspace, data, idx):
        for pat in self._index.keys():
            match = execute_atom(atomspace, pat)
            # patterns can match patterns, so check:
            for m in match.out:
                if m == data:
                    self._index[pat].add(idx)

    def intersect(self, query):
        """
        Extracts relevant patterns to the query and intersects their indices
        returns set of atoms ids
        """
        # put query in tmp atomspace, check if there are relevant patterns
        tmp = create_child_atomspace(self.pattern_space)
        q = tmp.add_atom(rename(tmp, self.pattern_space, query))
        # check query for exact match:
        exact_match = execute_atom(tmp, tmp.add_link(types.BindLink, [q, q]))
        for m in exact_match.out:
            return self._index[self.pattern_space.add_link(
                types.BindLink, [m, m])]
        # no exact match: search among all patterns
        # todo: search subgraphs
        res_set = None
        for pat, idx in self._index.items():
            # pattern is relevant if it matches query
            match = execute_atom(tmp, pat)
            for m in match.out:
                if hash(m) == hash(q):
                    if res_set is None:
                        res_set = idx
                    else:
                        res_set = res_set.intersection(idx)
        return res_set

    def query(self, result_atomspace, query):
        res_set = self.intersect(query)
        # add all possible results to tmp atomspace and run query
        # what is called filter step in graph indexing literature
        tmp = AtomSpace()
        atom_str = self._storage.get_atoms(res_set)
        for item in atom_str:
            tmp.add_atom(scheme_eval_h(tmp, item))
        # pack query in BindLink
        q = tmp.add_link(types.BindLink, [query, query])
        results = execute_atom(tmp, q)
        result_atoms = set()
        for atom in results.out:
            result_atoms.add(result_atomspace.add_atom(atom))
        return result_atoms

    def update_index_dual_link(self, content):
        # doesn't work
        d = tmp.add_link(types.DualLink, [content])
        # result is a set of conditional parts from pattens(GetLinks)
        pattern_set = execute_atom(tmp, d)
        # todo: create a new pattern

        assert len(pattern_set.out)
        for pattern in pattern_set.out:
            get_link = self.pattern_space.add_link(types.GetLink, pattern)
            self._index[get_link].add(data)

    def add_pattern(self, pat):
        assert pat.type == types.BindLink
        atom = self.pattern_space.add_atom(pat)
        if atom not in self._index:
            self._index[atom] = set()