def buildframes(self, db, sidx, sentence): for _, actioncore in db.actioncores(): roles = defaultdict(list) for role, word in db.rolesw(actioncore): sense = db.sense(word) props = db.properties(word) obj = Object(self.prac, id_=word, type_=sense, props=props, syntax=self.buildword(db, word)) roles[role].append(obj) frames = splitd(roles) for frame in frames: yield Frame(self.prac, sidx, sentence, syntax=list(db.syntax()), words=self.buildwords(db), actioncore=actioncore, actionroles=frame)
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)
def determine_missing_roles(self, node, db): ''' Checks if the given database contains all required actionroles to execute the representing actioncore successfully. If this is not the case this module look for frames which contain the missing action roles. :param db: :return: ''' howtodb = self.prac.mongodb.prac.howtos db_ = db.copy() # Assuming there is only one action core for word, actioncore in db.actioncores(): # ================================================================== # Preprocessing & Lookup # ================================================================== missingroles = node.frame.missingroles( ) #set(allroles).difference(givenroles) # Build query: Query should return only frames which have the same actioncore as the instruction # and all required action roles if missingroles: and_conditions = [{ '$eq': [ "$$plan.{}".format(constants.JSON_FRAME_ACTIONCORE), actioncore ] }] # and_conditions.extend([{"$ifNull" : ["$$plan.{}.{}".format(constants.JSON_FRAME_ACTIONCORE_ROLES, r), False]} for r in givenroles]) # and_conditions.extend([{"$eq" : ["$$plan.{}.{}.type".format(constants.JSON_FRAME_ACTIONCORE_ROLES, r), t]} for r, t in givenroles.items()]) roles_query = {"$and": and_conditions} stage_1 = { '$project': { constants.JSON_HOWTO_STEPS: { '$filter': { 'input': "${}".format(constants.JSON_HOWTO_STEPS), 'as': "plan", 'cond': roles_query } }, '_id': 0 } } stage_2 = {"$unwind": "${}".format(constants.JSON_HOWTO_STEPS)} if self.prac.verbose > 2: print("Sending query to MONGO DB ...") cursor_agg = howtodb.aggregate([stage_1, stage_2]) # After once iterating through the query result #it is not possible to iterate again through the result. #Therefore we keep the retrieved results in a separate list. cursor = [] for document in cursor_agg: cursor.append(document[constants.JSON_HOWTO_STEPS]) frames = [Frame.fromjson(self.prac, d) for d in cursor] c = howtodb.find( {constants.JSON_HOWTO_ACTIONCORE: str(actioncore)}) frames.extend([Frame.fromjson(self.prac, d) for d in c]) frames.sort(key=lambda f: f.specifity(), reverse=True) frames.sort(key=lambda f: node.frame.sim(f), reverse=True) if self.prac.verbose >= 2 or logger.level == logs.DEBUG: print('found similar frames in the db:') for f in frames: print('%.2f: %s' % (node.frame.sim(f), f)) if frames: frame = frames[0] if node.frame.sim(frame) >= 0.7: i = 0 for role in [ m for m in missingroles if m in frame.actionroles ]: newword = "{}-{}-skolem-{}".format( frame.actioncore, role, str(i)) if self.prac.verbose: print("Found {} as {}".format( frame.actionroles[role], role)) obj = frame.actionroles[role] newobj = Object(self.prac, newword, obj.type, props=obj.props, syntax=obj.syntax) node.frame.actionroles[role] = newobj atom_role = "{}({}, {})".format( role, newword, actioncore) atom_sense = "has_sense({}, {})".format( newword, obj.type) atom_has_pos = "has_pos({}, {})".format( newword, obj.syntax.pos) db_ << (atom_role, 1.0) db_ << (atom_sense, 1.0) db_ << (atom_has_pos, 1.0) # Need to define that the retrieve role cannot be # asserted to other roles no_roles_set = set( self.prac.actioncores[actioncore].roles) no_roles_set.remove(role) for no_role in no_roles_set: atom_role = "{}({},{})".format( no_role, newword, actioncore) db_ << (atom_role, 0) i += 1 else: if self.prac.verbose > 0: print("Confidence is too low.") else: if self.prac.verbose > 0: print("No suitable frames are available.") else: if self.prac.verbose > 0: print("No suitable frames are available.") # frame_result_list = transform_documents_to_actionrole_dict(cursor) # if len(frame_result_list) > 0: # logger.info("Found suitable frames") # score_frame_matrix = numpy.array(map(lambda x: frame_similarity(roles_senses_dict, x), # frame_result_list)) # confidence_level = 0.7 # # argmax_index = score_frame_matrix.argmax() # current_max_score = score_frame_matrix[argmax_index] # # if current_max_score >= confidence_level: # frame = frame_result_list[argmax_index] # document = cursor[argmax_index] # i = 0 # for role in missingroles: # word = "{}mongo{}".format(str(document[constants.JSON_FRAME_ACTIONCORE_ROLES] # [missing_role] # [constants.JSON_SENSE_WORD]), str(i)) # print "Found {} as {}".format(frame[missing_role], missing_role) # atom_role = "{}({}, {})".format(missing_role, word, actioncore) # atom_sense = "{}({}, {})".format('has_sense', word, frame[missing_role]) # atom_has_pos = "{}({}, {})".format('has_pos', word, str(document[constants.JSON_FRAME_ACTIONCORE_ROLES] # [missing_role] # [constants.JSON_SENSE_PENN_TREEBANK_POS])) # db_ << (atom_role, 1.0) # db_ << (atom_sense, 1.0) # db_ << (atom_has_pos, 1.0) # # # Need to define that the retrieve role cannot be # # asserted to other roles # no_roles_set = set(self.prac.actioncores[actioncore].roles) # no_roles_set.remove(missing_role) # for no_role in no_roles_set: # atom_role = "{}({},{})".format(no_role, word, actioncore) # db_ << (atom_role, 0) # i += 1 return db_, missingroles
def __call__(self, node, **params): # ====================================================================== # Initialization # ====================================================================== logger.debug('inference on {}'.format(self.name)) if self.prac.verbose > 0: print prac_heading('Recognizing {} Roles'.format({ True: 'MISSING', False: 'GIVEN' }[params.get('missing', False)])) dbs = node.outdbs infstep = PRACInferenceStep(node, self) queries = '' wnmod = self.prac.module('wn_senses') actionroles = defaultdict(list) pngs = {} for n, olddb in enumerate(dbs): db_copy = olddb.copy(mln=self.prac.mln) actioncore = node.frame.actioncore logger.debug(actioncore) 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)) project = MLNProject.open(projectpath) 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') queries = project.queryconf.get('queries', '') 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')) known_concepts = mln.domains.get('concept', []) # ============================================================== # Preprocessing # ============================================================== # adding senses and similarities. might be obsolete as it has # already been performed in ac recognition logger.debug('adding senses. concepts={}'.format(known_concepts)) db = wnmod.get_senses_and_similarities(db_copy, known_concepts) # we need senses and similarities as well as original evidence tmp_union_db = db.union(db_copy, mln=self.prac.mln) # ignore roles of false ac's new_tmp_union_db = tmp_union_db.copy(mln=self.prac.mln) roles = self.prac.actioncores[actioncore].roles for ac in tmp_union_db.domains['actioncore']: if ac == actioncore: continue for r in roles: for w in new_tmp_union_db.words(): new_tmp_union_db << ('{}({},{})'.format(r, w, ac), 0) infstep.indbs.append(new_tmp_union_db) # ============================================================== # Inference # ============================================================== infer = self.mlnquery(config=project.queryconf, verbose=self.prac.verbose > 2, db=new_tmp_union_db, mln=mln) resultdb = infer.resultdb if self.prac.verbose == 2: print print prac_heading('INFERENCE RESULTS') infer.write() # ============================================================== # Postprocessing # ============================================================== # get query roles for given actioncore and add inference results # for them to final output db. ignore 0-truth results. unified_db = new_tmp_union_db.union(resultdb, mln=self.prac.mln) # node.frame.actionroles = defaultdict(list) for role, word in unified_db.rolesw(actioncore): sense = unified_db.sense(word) props = dict(unified_db.properties(word)) obj = Object(self.prac, id_=word, type_=sense, props=props, syntax=node.pracinfer.buildword(unified_db, word)) actionroles[role].append(obj) # argdoms = kb.query_mln.predicate(role).argdoms roles = self.prac.actioncores[actioncore].roles new_result = PRACDatabase(self.prac) for atom, truth in unified_db.evidence.iteritems(): if any(r in atom for r in roles): (_, predname, args) = self.prac.mln.logic.parse_literal(atom) if not args[-1] == actioncore: continue new_result << (atom, truth) for q in unified_db.query('has_sense(?w, ?s)'): # TODO Add additional formulas to avoid the using of null values if self.prac.verbose > 1: print colorize(' WORD:', (None, 'white', True), True), q['?w'] print colorize(' SENSE:', (None, 'white', True), True), q['?s'] wnmod.printWordSenses( wnmod.get_possible_meanings_of_word( unified_db, q['?w']), q['?s']) print infstep.outdbs.append(new_result) pngs['Recognizing {} roles - {}'.format( 'given', str(n))] = get_cond_prob_png(queries, infstep.indbs, filename=self.name) infstep.png = pngs if 'project' not in locals(): raise Exception('no actioncore in database: %s' % olddb) infstep.applied_settings = project.queryconf.config # pprint(actionroles) newframes = splitd(actionroles) pred = None for newframe in newframes: # pprint(newframe) f = Frame(self.prac, node.frame.sidx, node.frame.sentence, syntax=list(olddb.syntax()), words=node.frame.words, actioncore=node.frame.actioncore, actionroles=newframe) logger.debug('created new frame %s' % f) # for db in infstep.outdbs: # out(db.syntax()) pred = FrameNode(node.pracinfer, f, node, pred, indbs=infstep.outdbs, prevmod=self.name) yield pred