Beispiel #1
0
 def __init__(self, session, config):
     self.session = session
     self.config = config
     self.activations = []
     self.root = self.session.query(RootNode).one()
     self.lexicon = Lexicon(session, config)
     self.present = FactSet('present', self.lexicon, config)
     self.past = FactSet('past', self.lexicon, config)
     self.pipe = None
Beispiel #2
0
class Network(object):

    def __init__(self, session, config):
        self.session = session
        self.config = config
        self.activations = []
        self.root = self.session.query(RootNode).one()
        self.lexicon = Lexicon(session, config)
        self.present = FactSet('present', self.lexicon, config)
        self.past = FactSet('past', self.lexicon, config)
        self.pipe = None

    @classmethod
    def initialize(self, session):
        try:
            session.query(RootNode).one()
        except NoResultFound:
            root = RootNode()
            session.add(root)
            Lexicon.initialize(session)

    def passtime(self):
        past = eval(self.now, {}, {})
        now = 0
        if self.config['time'] == 'normal':
            now = past + 1
        elif self.config['time'] == 'real':
            now = int(time.time())

        q = self.lexicon.make_var('Occur1')
        topast = self.present.query_facts(q, {})
        for f in topast:
            logger.info('To past: ' + str(f.pred))
            try:
                new_pred = f.pred.copy()
            except Exception as e:
                logger.error('Exception passing {!r}: {!r}'.format(f.pred, e))
                self.session.delete(f)
            else:
                self.session.delete(f)
                new_pred.add_object('at_', self.lexicon.now_term)
                self.past.add_fact(new_pred)
                self.session.flush()
        self.now = now

    def _get_now(self):
        return str(self.lexicon.time.now)

    def _set_now(self, val):
        self.lexicon.time.now = eval(str(val), {}, {})
        now = str(0 + self.lexicon.time.now)
        self.lexicon.now_term = self.lexicon.make_term(now, self.lexicon.number)

    now = property(_get_now, _set_now)

    def get_paths(self, pred):
        '''
        build a path for each testable feature in term.
        Each path is a tuple of strings,
        and corresponds to a node in the primary network.
        '''
        paths = []
        verb_ = pred.term_type
        self._recurse_paths(verb_, pred, paths, (), first=True)
        return paths

    def _recurse_paths(self, verb_, pred, paths, path, first=False):
        paths.append(path + ('_verb',))
        if not isa(pred, self.lexicon.verb):  # not a verb var
            paths.append(path + ('_neg',))
        for obt in sorted(verb_.object_types, key=lambda x: x.label):
            if obt.label in ('till_', 'at_'):
                continue
            t = obt.obj_type
            if isa(t, self.lexicon.verb):
                if obt.label in pred.objects:
                    pred = pred.get_object(obt.label)
                    verb_ = pred.term_type
                    self._recurse_paths(verb_, pred, paths, path + (obt.label,))
                else:
                    paths.append(path + (obt.label, '_verb'))
            else:
                paths.append(path + (obt.label, '_term'))

    def _get_nclass(self, ntype):
        mapper = Node.__mapper__
        return mapper.base_mapper.polymorphic_map[ntype].class_

    def add_fact(self, pred):
        factset = self.present
        if isa(pred, self.lexicon.exclusive_endure):
            old_pred = Predicate(pred.true, pred.term_type)
            old_pred.add_object('subj', pred.get_object('subj'))
            for label in pred.objects:
                if label.startswith('u-'):
                    old_pred.add_object(label, pred.get_object(label))
            self.finish(old_pred)
        elif isa(pred, self.lexicon.finish):
            tofinish = pred.get_object('what')
            self.finish(tofinish)
        #neg = pred.copy()
        #neg.true = not neg.true
        #contradiction = factset.query(neg)
        #if contradiction:
        #    raise exceptions.Contradiction('we already have ' + str(neg))

        facts = factset.query_facts(pred, {})
        if facts.count() == 0:
            if isa(pred, self.lexicon.endure):
                pred.add_object('since_', self.lexicon.now_term)
            fact = factset.add_fact(pred)
            if isa(pred, self.lexicon.happen):
                if self.pipe is not None:
                    self.pipe.send_bytes(str(pred).encode('utf8'))
            if self.root.child_path:
                m = Match(pred)
                m.paths = self.get_paths(pred)
                m.fact = fact
                Node.dispatch(self.root, m, self)
            n = 0
            while self.activations:
                n += 1
                cmc = int(self.config['commit_many_consecuences'])
                if cmc and n % cmc == 0:
                    self.session.commit()
                match = self.activations.pop(0)
                Node.dispatch(self.root, match, self)
            return fact
        else:
            return facts.first()

    def finish(self, predicate):
        fs = self.present.query_facts(predicate, {})
        for f in fs:
            if isa(f.pred, self.lexicon.endure):
                logger.info('Finish: ' + str(f.pred))
                new_pred = f.pred.copy()
                self.session.delete(f)
                new_pred.add_object('at_', self.lexicon.now_term)
                self.past.add_fact(new_pred)
                self.session.flush()

    def del_fact(self, pred):
        fact = self.present.query_facts(pred, {}).one()
        self.session.delete(fact)

    def add_rule(self, prems, conds, condcode, cons):
        rule = Rule()
        for n, pred in enumerate(prems):
            vars = {}
            paths = self.get_paths(pred)
            old_node = self.root
            for path in paths:
                old_node = self.get_or_create_node(old_node, pred, path, vars, rule)
            if old_node.terminal:
                pnode = old_node.terminal
            else:
                pnode = PremNode(old_node)
                old_node.terminal = pnode
            premise = Premise(pnode, n, pred)
            rule.prems.append(premise)
            for n, varname in vars.values():
                rule.pvars.append(PVarname(premise, n, varname))
        rule.conditions = conds
        rule.condcode = condcode
        for con in cons:
            if isinstance(con, Predicate):
                rule.consecuences.append(con)
            else:
                rule.vconsecuences.append(con)
        for prem in rule.prems:
            matches = self.present.query(prem.pred)
            for match in matches:
                try:
                    prem.node.matches.filter(PMatch.fact==match.fact).one()
                except NoResultFound:
                    m = PMatch(prem.node, match.fact)
                    for var, val in match.items():
                        numvar = prem.name_to_num(var)
                        m.pairs.append(MPair.make_pair(numvar, val))
                prem.dispatch(match, self)
        return rule


    def query(self, *q):
        submatches = []
        for pred in q:
            factset = self.present
            if set(pred.objects).intersection({'at_', 'till_'}):
                factset = self.past
            smatches = factset.query(pred)
            submatches.append(smatches)
        matches = merge_submatches(submatches)
        unique = []
        for m in matches:
            for m2 in unique:
                if m2 == m:
                    break
            else:
                unique.append(m)
        return unique

    def get_or_create_node(self, parent, term, path, vars, rule):
        ntype_name = path[-1]
        cls = self._get_nclass(ntype_name)
        value = cls.resolve(term, path)
        redundant_var = getattr(value, 'redundant_var', False)
        is_var = getattr(value, 'var', False)
        if redundant_var and not is_var:
            value = value.term_type
            is_var = getattr(value, 'var', False)
        name = getattr(value, 'name', '')
        pnum = 0
        if is_var:
            if name not in vars:
                pnum = len(vars) + 1
                vars[name] = (pnum, Varname(value, rule))
            else:
                pnum = vars[name][0]
        rnum = 0
        if redundant_var:
            rname = redundant_var.name
            if rname not in vars:
                rnum = len(vars) + 1
                vars[rname] = (rnum, Varname(redundant_var, rule))
            else:
                rnum = vars[rname][0]
        try:
            nodes = self.session.query(cls).filter(cls.parent_id==parent.id, cls.var==pnum)
            if redundant_var:
                nodes = nodes.filter(cls.redundant_var==rnum)
            node = nodes.filter(cls.value==value).one()
        except NoResultFound:
            #  build the node and append it
            node = cls(value)
            node.var = pnum
            if redundant_var:
                node.redundant_var = rnum
            parent.children.append(node)
            if not parent.child_path:
                parent.child_path = path
        return node