def __call__(self, node, **params): # ====================================================================== # Initialization # ====================================================================== logger.debug('inference on {}'.format(self.name)) if self.prac.verbose > 0: print prac_heading('Resolving Coreferences') preds = list( node.rdfs( goaltest=lambda n: isinstance(n, FrameNode) and not n.children, all=True))[:2] dbs = node.outdbs infstep = PRACInferenceStep(node, self) projectpath = os.path.join(pracloc.pracmodules, self.name) ac = None pngs = {} # if not preds: return [] # ====================================================================== # Preprocessing # ====================================================================== # merge output dbs from senses_and_roles step, containing # roles inferred from multiple sentences. if not preds: # no coreferencing required - forward dbs and settings # from previous module infstep.indbs = [db.copy() for db in dbs] infstep.outdbs = [db.copy() for db in infstep.indbs] logger.debug( '%s has no predecessors. Nothing to do here. Passing db...' % node) return [node] # retrieve all words from the dbs to calculate distances. # Do not use pracinference.instructions as they are not # annotated by the Stanford parser. sentences = [db.words() for pred in preds for db in pred.indbs] infstep.indbs = [db.copy() for db in dbs] # infstep.outdbs = [db.copy() for db in infstep.indbs] # query action core to load corresponding project actioncore = node.frame.actioncore # clear corefdb and unify current db with the two preceding ones corefdb = PRACDatabase(self.prac) corefdb = corefdb.union(dbs, self.prac.mln) # for s in range(max(0, i - 2), i+1): # corefdb = corefdb.union(dbs[s], self.prac.mln) for pred in preds: logger.debug('unifying with %s' % pred) for db in pred.indbs: corefdb = corefdb.union(db, self.prac.mln) # remove all senses from the databases' domain that are not # assigned to any word. for q in corefdb.query('!(EXIST ?w (has_sense(?w,?sense)))'): corefdb.rmval('sense', q['?sense']) try: # preprocessing: adding distance information for each # word in the instructions # s = words[max(0, i - 2):i+1] # snts = list(enumerate(s)) # idx = len(snts) - 1 # idx of current sentence # for s in snts[:-1]: # idx2 = s[0] # for w in s[1]: # corefdb << 'distance({},DIST{})'.format(w, idx - idx2) for sidx, s in enumerate(sentences): for w in s: cont = True for q in corefdb.query('distance({}, ?w)'.format(w)): cont = False break if not cont: continue corefdb << 'distance({},DIST{})'.format(w, sidx) # print 'distance({},DIST{})'.format(w, sidx) logger.debug('loading Project: {}'.format( colorize(actioncore, (None, 'cyan', True), True))) project = MLNProject.open( os.path.join(projectpath, '{}.pracmln'.format(actioncore))) mlntext = project.mlns.get(project.queryconf['mln'], None) mln = parse_mln(mlntext, searchpaths=[self.module_path], projectpath=projectpath, logic=project.queryconf.get('logic', 'FuzzyLogic'), grammar=project.queryconf.get( 'grammar', 'PRACGrammar')) except MLNParsingError: logger.warning( 'Could not use MLN in project {} for coreference resolution'. format(colorize(actioncore, (None, 'cyan', True), True))) infstep.outdbs = [db.copy(self.prac.mln) for db in dbs] infstep.png = node.parent.laststep.png infstep.applied_settings = node.parent.laststep.applied_settings return [node] except Exception: infstep.outdbs = [db.copy(self.prac.mln) for db in dbs] infstep.png = node.parent.laststep.png infstep.applied_settings = node.parent.laststep.applied_settings logger.warning( 'Could not load project "{}". Passing dbs to next module...'. format(ac)) return [node] # adding similarities wnmod = self.prac.module('wn_senses') newdatabase = wnmod.add_sims(corefdb, mln) # update queries depending on missing roles acroles = filter(lambda role: role != 'action_verb', self.prac.actioncores[actioncore].roles) missingroles = [ ar for ar in acroles if len(list(newdatabase.query('{}(?w,{})'.format(ar, actioncore)))) == 0 ] conf = project.queryconf conf.update({'queries': ','.join(missingroles)}) print colorize('querying for missing roles {}'.format(conf['queries']), (None, 'green', True), True) # asserting impossible role-ac combinations, leaving previously # inferred roles untouched fulldom = mergedom(mln.domains, newdatabase.domains) ac_domains = [dom for dom in fulldom if '_ac' in dom] acs = list(set([v for a in ac_domains for v in fulldom[a]])) acs = filter(lambda ac_: ac_ != actioncore, acs) for ac1 in acs: for r in missingroles: for w in newdatabase.domains['word']: # words with no sense are asserted false if list( corefdb.query( '!(EXIST ?sense (has_sense({},?sense)))'. format(w))): newdatabase << '!{}({},{})'.format(r, w, actioncore) # leave previously inferred information roles # untouched if list(newdatabase.query('{}({},{})'.format(r, w, ac1))): continue else: newdatabase << '!{}({},{})'.format(r, w, ac1) try: # ========================================================== # Inference # ========================================================== infer = self.mlnquery(config=conf, verbose=self.prac.verbose > 2, db=newdatabase, mln=mln) if self.prac.verbose == 2: print print prac_heading('INFERENCE RESULTS') infer.write() # ========================================================== # Postprocessing # ========================================================== # merge initial db with results for db in infstep.indbs: resultdb = db.copy() for res in infer.results.keys(): if infer.results[res] != 1.0: continue resultdb << str(res) _, _, args = self.prac.mln.logic.parse_literal(res) w = args[0] for q in newdatabase.query( 'has_sense({0},?s) ^ has_pos({0},?pos)'.format(w)): resultdb << 'has_sense({},{})'.format(w, q['?s']) resultdb << 'is_a({0},{0})'.format(q['?s']) resultdb << 'has_pos({},{})'.format(w, q['?pos']) resultdb = wnmod.add_sims(resultdb, mln) # enhance the frame data for mrole in missingroles: for q in resultdb.query( '{role}(?w, {actioncore}) ^ has_sense(?w, ?s)'. format(role=mrole, actioncore=actioncore)): for p in preds: if p.frame.object(q['?w']) is not None: node.frame.actionroles[mrole] = p.frame.object( q['?w']) break infstep.outdbs.append(resultdb) pprint(node.frame.tojson()) except NoConstraintsError: logger.debug('No coreferences found. Passing db...') infstep.outdbs.append(db) except Exception: logger.error('Something went wrong') traceback.print_exc() pngs['Coref - ' + str(node)] = get_cond_prob_png(project.queryconf.get( 'queries', ''), dbs, filename=self.name) infstep.png = pngs infstep.applied_settings = project.queryconf.config return [node]
def __call__(self, node, **params): # ====================================================================== # Initialization # ====================================================================== logger.debug('inference on {}'.format(self.name)) if self.prac.verbose > 0: print(prac_heading('Refining Actioncores')) dbs = node.outdbs infstep = PRACInferenceStep(node, self) # if node.previous_module == 'achieved_by': # raise ActionKnowledgeError('I don\'t know how to %s' % node.frame.sentence) # ====================================================================== # Preprocessing # ====================================================================== for olddb in dbs: infstep.indbs.append(olddb.copy()) #To handle multiple acs in one task, we have to check if the single # dbs contain achieved_bys which representing already plans pngs = {} actioncore = node.frame.actioncore mod = self.prac.module('complex_achieved_by') newnodes = list(mod(node)) n = None parentframes = [ p.frame for p in node.parentspath() if isinstance(p, FrameNode) ] if any(n.frame in parentframes for n in newnodes): logger.error( 'aborting reasoning because of infinite loop. (%s)' % node.frame) node.children = [] else: for n in newnodes: yield n if n is not None: return if n is None: # This list is used to avoid an infinite loop during the # achieved by inference. # To avoid this infinite loop, the list contains the pracmlns # which were inferenced during the process. # Every pracmln should be used only once during the process # because the evidence for the inference will always remain # the same. # So if the pracmln hadnt inferenced a plan in the first time, # it will never do it. # Need to remove possible achieved_by predicates from # previous achieved_by inferences db_ = PRACDatabase(self.prac) for atom, truth in sorted(olddb.evidence.items()): if 'achieved_by' in atom: continue db_ << (atom, truth) if params.get('project', None) is None: logger.debug('Loading Project: {}.pracmln'.format( colorize(actioncore, (None, 'cyan', True), True))) projectpath = os.path.join(pracloc.pracmodules, self.name, '{}.pracmln'.format(actioncore)) if os.path.exists(projectpath): project = MLNProject.open(projectpath) else: infstep.outdbs.append(olddb) logger.error(actioncore + ".pracmln does not exist.") return else: logger.debug( colorize('Loading Project from params', (None, 'cyan', True), True)) projectpath = os.path.join( params.get('projectpath', None) or os.path.join(pracloc.pracmodules, self.name), params.get('project').name) project = params.get('project') mlntext = project.mlns.get(project.queryconf['mln'], None) mln = parse_mln( mlntext, searchpaths=[self.module_path], projectpath=projectpath, logic=project.queryconf.get('logic', 'FirstOrderLogic'), grammar=project.queryconf.get('grammar', 'PRACGrammar')) known_concepts = mln.domains.get('concept', []) wnmod = self.prac.module('wn_senses') #Merge domains of db and given mln to avoid errors due to role inference and the resulting missing fuzzy perdicates known_concepts = list( set(known_concepts).union( set(db_.domains.get('concept', [])))) db = wnmod.get_senses_and_similarities(db_, known_concepts) unified_db = db_.union(db) dbnew = wnmod.add_sims(unified_db, unified_db) # Inference achieved_by predicate db_ = self.extendDBWithAchievedByEvidence( dbnew, mln, actioncore) # ============================================================== # Inference # ============================================================== # db_.write() try: infer = self.mlnquery(config=project.queryconf, verbose=self.prac.verbose > 2, db=db_, mln=mln) except NoConstraintsError: logger.error( 'achieved_by inference failed due to NoConstraintsError: %s' % node.frame) return result_db = infer.resultdb if self.prac.verbose == 2: print() print(prac_heading('INFERENCE RESULTS')) infer.write() # ============================================================== # Postprocessing # ============================================================== # unified_db = result_db.union(kb.query_mln, db_) # only add inferred achieved_by atoms, leave out # 0-evidence atoms for qa in result_db.query('achieved_by(?ac1,?ac2)'): if qa['?ac2'] == 'Complex': continue unified_db << 'achieved_by({},{})'.format( qa['?ac1'], qa['?ac2']) pngs[qa['?ac2']] = get_cond_prob_png(project.queryconf.get( 'queries', ''), dbs, filename=self.name) newframe = Frame(self.prac, node.frame.sidx, '', words=[], syntax=[], actioncore=qa['?ac2'], actionroles={}) # out('->', newframe) infstep.outdbs.append(unified_db) yield FrameNode(node.pracinfer, newframe, node, pred=None, indbs=[unified_db], prevmod=self.name) return infstep.outdbs.append(unified_db) # raise ActionKnowledgeError('I don\'t know how to %s' % node.frame.sentence)