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
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