def __init__(self, head, body): self.__head = head self.__body = body # relations between variables like < <= = != # also for relations between variables and constants # self.__var_rels = {} # a list (body_index1,pos1,body_index2,pos2,comparison operator) self.__var_constraints = [] # explicitly add all equality constraints between variables for bi1, b1 in enumerate(self.__body): positions1 = PositionIndex.get_all_positions(b1) for p1 in positions1: v1 = p1.fetch(b1) if isinstance(v1, Variable): # can't use enumerate here, have to preserve correct indexing # for bi2 for bi2, b2 in zip(range(bi1, len(self.__body)), self.__body[bi1:]): positions2 = PositionIndex.get_all_positions(b2) for p2 in positions2: v2 = p2.fetch(b2) if isinstance(v2, Variable): if (p1 != p2 or bi1 != bi2) and v1 == v2: self.__var_constraints.append((bi1, p1, bi2, p2, Comparison('=='))) # a mapping head_pos -> [(body_index, body_pos)] self.__headvar_bindings = {} hpositions = PositionIndex.get_all_positions(head) for hp in hpositions: hv = hp.fetch(head) if not isinstance(hv, Variable): continue bound = False for bi, b in enumerate(self.__body): bpositions = PositionIndex.get_all_positions(b) for bp in bpositions: bv = bp.fetch(b) if isinstance(bv, Variable): if (hv == bv): self.__headvar_bindings.setdefault(hp, []).append((bi, bp)) bound = True #assert bound, "Head variable %s not bound to any body variables" % hv if not bound: print >> sys.stderr, "Head variable %s not bound to any body variables" % hv # equality constraints on head self.__headvar_constraints = [] for i, p1 in enumerate(hpositions): t1 = p1.fetch(head) if isinstance(t1, Variable): for p2 in hpositions[i+1:]: t2 = p2.fetch(head) if t1 == t2: self.__headvar_constraints.append((p1, p2)) CacheHash.__init__(self)
def add_condition(self, cond): self.__body.append(cond) nbi = len(self.__body) - 1 # add variable equality comparisons for bi1, b1 in enumerate(self.__body): positions1 = PositionIndex.get_all_positions(b1) for p1 in positions1: v1 = p1.fetch(b1) if isinstance(v1, Variable): positions2 = PositionIndex.get_all_positions(cond) for p2 in positions2: v2 = p2.fetch(cond) if isinstance(v2, Variable): if (p1 != p2 or bi1 != nbi) and v1 == v2: self.__var_constraints.append( (bi1, p1, nbi, p2, Comparison('=='))) # add head bindings hpositions = PositionIndex.get_all_positions(self.__head) for hp in hpositions: hv = hp.fetch(self.__head) if not isinstance(hv, Variable): continue bpositions = PositionIndex.get_all_positions(cond) for bp in bpositions: bv = bp.fetch(cond) if isinstance(bv, Variable): if (hv == bv): self.__headvar_bindings.setdefault(hp, []).append( (nbi, bp)) self.recalc_hash()
def add_condition(self, cond): self.__body.append(cond) nbi = len(self.__body) - 1 # add variable equality comparisons for bi1, b1 in enumerate(self.__body): positions1 = PositionIndex.get_all_positions(b1) for p1 in positions1: v1 = p1.fetch(b1) if isinstance(v1, Variable): positions2 = PositionIndex.get_all_positions(cond) for p2 in positions2: v2 = p2.fetch(cond) if isinstance(v2, Variable): if (p1 != p2 or bi1 != nbi) and v1 == v2: self.__var_constraints.append((bi1, p1, nbi, p2, Comparison('=='))) # add head bindings hpositions = PositionIndex.get_all_positions(self.__head) for hp in hpositions: hv = hp.fetch(self.__head) if not isinstance(hv, Variable): continue bpositions = PositionIndex.get_all_positions(cond) for bp in bpositions: bv = bp.fetch(cond) if isinstance(bv, Variable): if (hv == bv): self.__headvar_bindings.setdefault(hp, []).append((nbi, bp)) self.recalc_hash()
def __init__(self, head, body): self.__head = head self.__body = body # relations between variables like < <= = != # also for relations between variables and constants # self.__var_rels = {} # a list (body_index1,pos1,body_index2,pos2,comparison operator) self.__var_constraints = [] # explicitly add all equality constraints between variables for bi1, b1 in enumerate(self.__body): positions1 = PositionIndex.get_all_positions(b1) for p1 in positions1: v1 = p1.fetch(b1) if isinstance(v1, Variable): # can't use enumerate here, have to preserve correct indexing # for bi2 for bi2, b2 in zip(range(bi1, len(self.__body)), self.__body[bi1:]): positions2 = PositionIndex.get_all_positions(b2) for p2 in positions2: v2 = p2.fetch(b2) if isinstance(v2, Variable): if (p1 != p2 or bi1 != bi2) and v1 == v2: self.__var_constraints.append( (bi1, p1, bi2, p2, Comparison('==')))
def __init__(self, head, body): self.__head = head self.__body = body # relations between variables like < <= = != # also for relations between variables and constants # self.__var_rels = {} # a list (body_index1,pos1,body_index2,pos2,comparison operator) self.__var_constraints = [] # explicitly add all equality constraints between variables for bi1, b1 in enumerate(self.__body): positions1 = PositionIndex.get_all_positions(b1) for p1 in positions1: v1 = p1.fetch(b1) if isinstance(v1, Variable): # can't use enumerate here, have to preserve correct indexing # for bi2 for bi2, b2 in zip(range(bi1, len(self.__body)), self.__body[bi1:]): positions2 = PositionIndex.get_all_positions(b2) for p2 in positions2: v2 = p2.fetch(b2) if isinstance(v2, Variable): if (p1 != p2 or bi1 != bi2) and v1 == v2: self.__var_constraints.append((bi1, p1, bi2, p2, Comparison('==')))
def add_var_constraint(self, v1, v2, comparison): for bi1, b1 in enumerate(self.__body): pos1 = PositionIndex.get_positions(b1, v1) if len(pos1) > 0: for bi2, b2 in enumerate(self.__body): pos2 = PositionIndex.get_positions(b2, v2) for p1 in pos1: for p2 in pos2: if p1 != p2 or bi1 != bi2: self.__var_constraints.append((bi1, p1, bi2, p2, comparison))
def add_var_constraint(self, v1, v2, comparison): for bi1, b1 in enumerate(self.__body): pos1 = PositionIndex.get_positions(b1, v1) if len(pos1) > 0: for bi2, b2 in enumerate(self.__body): pos2 = PositionIndex.get_positions(b2, v2) for p1 in pos1: for p2 in pos2: if p1 != p2 or bi1 != bi2: self.__var_constraints.append( (bi1, p1, bi2, p2, comparison))
def rbclicked(self): if self.bg1.checkedId() == 1: self.searchEngine = BooleanIndex VectorSpaceIndex.releaseSpace() PositionIndex.releasespace() bm25.releasespace() WildCardIndex.releasespace() elif self.bg1.checkedId() == 2: self.searchEngine = VectorSpaceIndex BooleanIndex.releaseSpace() PositionIndex.releasespace() bm25.releasespace() WildCardIndex.releasespace() elif self.bg1.checkedId() == 3: self.searchEngine = bm25 VectorSpaceIndex.releaseSpace() BooleanIndex.releaseSpace() PositionIndex.releasespace() WildCardIndex.releasespace() elif self.bg1.checkedId() == 4: self.searchEngine = PositionIndex VectorSpaceIndex.releaseSpace() BooleanIndex.releaseSpace() bm25.releasespace() WildCardIndex.releasespace() elif self.bg1.checkedId() == 5: self.searchEngine = WildCardIndex PositionIndex.releasespace() VectorSpaceIndex.releaseSpace() BooleanIndex.releaseSpace() bm25.releasespace()
def get_all_constants(grounds): consts = set() for g in grounds: poses = PositionIndex.get_all_positions(g) for p in poses: consts.add(p.fetch(g)) return consts
def get_var_terms(self): result = [] positions = PositionIndex.get_all_positions(self) for p in positions: term = p.fetch(self) if isinstance(term, Variable): result.append(p, term) return result
def build_constant_relations(int_rep, map = {}): consts2rels = {} # const -> [(pos, rel)] for s in int_rep.get_statics(): rel = s.get_relation() for p in PositionIndex.get_all_positions(s): term = p.fetch(s) if isinstance(term, Constant) and isinstance(term.get_name(), str) and term.get_name() not in exclude: if rel in map: rel = map[rel] consts2rels.setdefault(term.get_name(), []).append((p, rel)) return consts2rels
def build_constant_relations(int_rep, map={}): consts2rels = {} # const -> [(pos, rel)] for s in int_rep.get_statics(): rel = s.get_relation() for p in PositionIndex.get_all_positions(s): term = p.fetch(s) if isinstance(term, Constant) and isinstance( term.get_name(), str) and term.get_name() not in exclude: if rel in map: rel = map[rel] consts2rels.setdefault(term.get_name(), []).append((p, rel)) return consts2rels
def build_c2p(int_rep, map = {}): """ returns a map of constants to the predicates that they appear in """ c2p = {} # const -> [(pos, pred)] for g in int_rep.get_statics() + int_rep.get_inits(): pred = g.get_predicate() for p in PositionIndex.get_all_positions(g): term = p.fetch(g) if isinstance(term, Constant) and \ isinstance(term.get_name(), str) and \ term.get_name() not in exclude: c2p.setdefault(term.get_name(), []).append((p, pred)) return c2p
def build_c2p(int_rep, map={}): """ returns a map of constants to the predicates that they appear in """ c2p = {} # const -> [(pos, pred)] for g in int_rep.get_statics() + int_rep.get_inits(): pred = g.get_predicate() for p in PositionIndex.get_all_positions(g): term = p.fetch(g) if isinstance(term, Constant) and \ isinstance(term.get_name(), str) and \ term.get_name() not in exclude: c2p.setdefault(term.get_name(), []).append((p, pred)) return c2p
def check_min_max(r, ec, score): "Find indications that a number is to be minimized, maximized" place_types = {} for b in r.get_body(): pos = PositionIndex.get_all_positions(b) for p in pos: term = p.fetch(b) if isinstance(term, Constant) and term.get_name() == 0: c = ec.get_or_make_class((b.get_predicate(), p)) if score == 100 ^ b.is_negated(): ec.set_class_type(c, placetype.NUM_MIN) else: ec.set_class_type(c, placetype.NUM_MAX) return place_types
def expand(self, r, bi): expanded = [] b = r.get_body()[bi] pred = b.get_predicate() assert pred in self.__g_elabs for elab in self.__g_elabs[pred]: ehead = elab.get_head() conflict = False for p in PositionIndex.get_all_positions(b): t1 = p.fetch(b) t2 = p.fetch(ehead) if isinstance(t1, Constant) and isinstance(t2, Constant) and t1 != t2: # this elab rule is incompatible conflict = True break if conflict: continue r_copy = r.copy() elab_copy = elab.copy() expanded.extend(self.expand_with_rule(r_copy, bi, elab_copy)) return expanded
def expand(self, r, bi): expanded = [] b = r.get_body()[bi] pred = b.get_predicate() assert pred in self.__g_elabs for elab in self.__g_elabs[pred]: ehead = elab.get_head() conflict = False for p in PositionIndex.get_all_positions(b): t1 = p.fetch(b) t2 = p.fetch(ehead) if isinstance(t1, Constant) and isinstance( t2, Constant) and t1 != t2: # this elab rule is incompatible conflict = True break if conflict: continue r_copy = r.copy() elab_copy = elab.copy() expanded.extend(self.expand_with_rule(r_copy, bi, elab_copy)) return expanded
from PositionIndex import PositionIndex comp_rels = ['<', '>', '>=', 'lessThan', 'greaterThan', 'succ'] math_op_rels = ['+', '-', '*', '/', 'min', 'minus', 'plus'] obj_loc_place = set([('location', PositionIndex([0, 0]))]) coord_places = set([('location', PositionIndex([0, p])) for p in [1, 2]]) # an equivalence class that has one of these places as a member must # be a number num_places = set([(c, PositionIndex([0])) for c in comp_rels] + \ [(c, PositionIndex([1])) for c in comp_rels] + \ [(o, PositionIndex([0])) for o in math_op_rels] + \ [(o, PositionIndex([1])) for o in math_op_rels] + \ [(o, PositionIndex([2])) for o in math_op_rels] + \ [('int', PositionIndex([0]))]) # these are the place types AGENT, OBJECT, COORD, NUM_MAX, NUM_MIN, NUM, UNKNOWN = range(7) # for string output type_names = { AGENT: 'agent', OBJECT: 'object', COORD: 'coord', NUM_MAX: 'num_max', NUM_MIN: 'num_min', NUM: 'num', UNKNOWN: 'unknown' } # specificity ordering relations
for src_p in pred_order: tgt_p = pred_map[src_p] print src_p, tgt_p if src_p not in src_gnds or tgt_p not in tgt_gnds: print >> sys.stderr, "PROBABLY A BAD MATCH BETWEEN %s AND %s" % (src_p, tgt_p) continue matches = cross_product(src_gnds[src_p], tgt_gnds[tgt_p]) # get the position mapping this is fake right now, but we should get this # from a different script in the future right now just assume all the # constant positions are preserved tmp_src_g, tmp_tgt_g = matches[0] src_p = PositionIndex.get_all_positions(tmp_src_g) tgt_p = PositionIndex.get_all_positions(tmp_tgt_g) pmap = dict([(p, p) for p in src_p if p in tgt_p]) # here we're going to match up all the grounds for this predicate # the order of the matching is random and can affect the quality of the # match, but I don't have any good idea about how to do it right now matches = filter_matches(matches, cmap, pmap) while len(matches) > 0: src_g, tgt_g = matches.pop() commit_ground_match(src_g, tgt_g, cmap, pmap) matches = filter_matches(matches, cmap, pmap) for sp, tp in pred_map.items(): print 'map predicate %s %s' % (sp, tp)
tgt_p = pred_map[src_p] print src_p, tgt_p if src_p not in src_gnds or tgt_p not in tgt_gnds: print >> sys.stderr, "PROBABLY A BAD MATCH BETWEEN %s AND %s" % ( src_p, tgt_p) continue matches = cross_product(src_gnds[src_p], tgt_gnds[tgt_p]) # get the position mapping this is fake right now, but we should get this # from a different script in the future right now just assume all the # constant positions are preserved tmp_src_g, tmp_tgt_g = matches[0] src_p = PositionIndex.get_all_positions(tmp_src_g) tgt_p = PositionIndex.get_all_positions(tmp_tgt_g) pmap = dict([(p, p) for p in src_p if p in tgt_p]) # here we're going to match up all the grounds for this predicate # the order of the matching is random and can affect the quality of the # match, but I don't have any good idea about how to do it right now matches = filter_matches(matches, cmap, pmap) while len(matches) > 0: src_g, tgt_g = matches.pop() commit_ground_match(src_g, tgt_g, cmap, pmap) matches = filter_matches(matches, cmap, pmap) for sp, tp in pred_map.items(): print 'map predicate %s %s' % (sp, tp)
def get_predicates(rules, roles): """Extract predicate information from the rules""" preds = set() pred_names = set() predTypes = {} # maps places to the equivalence class they're in ec = TypedEquivalenceClass() for r in rules: goal_place_types = {} if r.get_head().get_relation() == 'goal': score = r.get_head().get_term(1).get_name() if score == 0 or score == 100: # we can't really say anything about the middle cases goal_place_types = check_min_max(r, ec, score) score = r.get_head().get_term(1) sentences = r.get_body() elif r.get_head().get_relation() == 'terminal': sentences = r.get_body() else: sentences = [r.get_head()] + r.get_body() for i,s1 in enumerate(sentences): s1pred = s1.get_predicate() assert s1pred != None if s1pred in placetype.preset_types: # the first place is supposed to get acted upon, not act upon the # second place. The preset places are not to be acted upon continue predTypes[s1pred] = s1.get_type() s1pos = PositionIndex.get_all_positions(s1) for p1 in s1pos: ec.get_or_make_class((s1pred, p1)) if len(s1pos) == 0: preds.add(Predicate(s1pred, s1.get_type(), ())) pred_names.add(s1pred) continue added = False for s2 in sentences[i+1:]: s2pred = s2.get_predicate() s2pos = PositionIndex.get_all_positions(s2) assert s1pred != None and s2pred != None for p1 in s1pos: place1 = (s1pred, p1) t1 = p1.fetch(s1) c1 = ec.get_or_make_class(place1) if place1 in placetype.preset_types: ec.set_class_type(c1, placetype.preset_types[place1]) for p2 in s2pos: place2 = (s2pred, p2) t2 = p2.fetch(s2) if isinstance(t1, Variable) and isinstance(t2, Variable) and \ t1 == t2: if place2 in goal_place_types: ec.set_class_type(c1, goal_place_types[place2]) elif place2 in placetype.preset_types: ec.set_class_type(c1, placetype.preset_types[place2]) else: # put these two places in the same equivalence class place1 = (s1pred, p1) place2 = (s2pred, p2) ec.make_equivalent(place1, place2) # run through the rules again. If a role constant appears somewhere, and # no non-role constants appear in that place, then that place is an agent possible_agent_places = set() impossible_agent_places = set() for r in rules: if r.get_head().get_predicate() != None: sentences = [r.get_head()] + r.get_body() else: sentences = r.get_body() for s in sentences: for p in PositionIndex.get_all_positions(s): place = (s.get_predicate(), p) t = p.fetch(s) if t in roles: if place not in impossible_agent_places: possible_agent_places.add(place) else: if isinstance(t, Constant): impossible_agent_places.add(place) possible_agent_places.discard(place) collected = {} for place in ec.get_all_members(): if place in possible_agent_places: type = placetype.AGENT else: type = ec.get_member_type(place) collected.setdefault(place[0],[]).append((place, type)) for p, types in collected.items(): types.sort(lambda x,y: cmp(x[0],y[0])) types_no_place = [t[1] for t in types] preds.add(Predicate(p, predTypes[p], types_no_place)) pred_names.add(p) # go over one more time and see if we missed anything for r in rules: sentences = [r.get_head()] + r.get_body() for s in sentences: p = s.get_predicate() if p == None: continue if p not in pred_names: pos = PositionIndex.get_all_positions(s) preds.add(Predicate(p, s.get_type(), tuple([placetype.UNKNOWN] * len(pos)))) return preds
def expand_with_rule(self, r, bi, elab): expanded = [] b = r.get_body()[bi] elab_head = elab.get_head() positions = PositionIndex.get_all_positions(b) assert positions == PositionIndex.get_all_positions(elab_head) # this is so there won't be name collisions elab.mangle_vars("__cr_") # first we have to add the equality constraints constraints from the head # of the elab rule to the condition which is being substituted. for p1, p2 in elab.get_headvar_constraints(): r.add_pos_constraint(bi, p1, bi, p2, Comparison('==')) # propagate the constraints throughout the rule r.enforce_equality() # make the head of the elab rule and the condition being expanded look # exactly the same preserve_vars = [] terms = [p.fetch(b) for p in positions] for p, t in zip(positions, terms): elab_term = p.fetch(elab_head) if t == elab_term: continue if isinstance(elab_term, Constant) and isinstance(t, Variable): p.set(b, elab_term.copy()) elif isinstance(elab_term, Variable) and isinstance(t, Constant): p.set(elab_head, t.copy()) elif isinstance(elab_term, Variable) and isinstance(t, Variable): # should change the variables in the elab rule to match the # expanded rule. Since the equality constraints on the head # variables are already applied to the substituted condition, # we should have that if two variables in the elab head are # equal, those variables in the condition are equal too p.set(elab_head, t.copy()) preserve_vars.append(t.get_name()) else: assert t == elab_term r.enforce_equality(preserve_vars) elab.enforce_equality(preserve_vars) offset = r.num_conditions() gr_head = elab.get_head() # for each constraint that applied to the condition # being expanded, we have to insert duplicates of # those that apply to the inserted conditions # we're going to append all the new rules to the end of # the body first, and then add and modify the approriate # constraints. After everything is done, remove the body # condition that was substituted # no variable equalities should be drawn here for grb in elab.get_body(): r.add_condition(grb) # add the variable constraints for p in positions: if isinstance(p.fetch(gr_head), Constant): continue b2b_cons = r.get_constraints_on(bi, p) # body-to-body constraints hv_bindings = elab.get_headvar_binding(p) for old_i, old_p, comp, order in b2b_cons: for bound_i, bound_p in hv_bindings: if order == 0: # head var first r.add_pos_constraint(offset + bound_i, bound_p, old_i, old_p, comp) else: r.add_pos_constraint(old_i, old_p, offset + bound_i, bound_p, comp) if comp.relation() == '==': # have to rename the variables in original condition to # equal new condition new_cond = r.get_cond(bound_i + offset) new_name = bound_p.fetch(new_cond) old_p.set(r.get_cond(old_i), new_name) # finally remove the replaced condition r.remove_condition(bi) expanded.append(r) return expanded
def __init__(self, head, body): self.__head = head self.__body = body # relations between variables like < <= = != # also for relations between variables and constants # self.__var_rels = {} # a list (body_index1,pos1,body_index2,pos2,comparison operator) self.__var_constraints = [] # explicitly add all equality constraints between variables for bi1, b1 in enumerate(self.__body): positions1 = PositionIndex.get_all_positions(b1) for p1 in positions1: v1 = p1.fetch(b1) if isinstance(v1, Variable): # can't use enumerate here, have to preserve correct indexing # for bi2 for bi2, b2 in zip(range(bi1, len(self.__body)), self.__body[bi1:]): positions2 = PositionIndex.get_all_positions(b2) for p2 in positions2: v2 = p2.fetch(b2) if isinstance(v2, Variable): if (p1 != p2 or bi1 != bi2) and v1 == v2: self.__var_constraints.append( (bi1, p1, bi2, p2, Comparison('=='))) # a mapping head_pos -> [(body_index, body_pos)] self.__headvar_bindings = {} hpositions = PositionIndex.get_all_positions(head) for hp in hpositions: hv = hp.fetch(head) if not isinstance(hv, Variable): continue bound = False for bi, b in enumerate(self.__body): bpositions = PositionIndex.get_all_positions(b) for bp in bpositions: bv = bp.fetch(b) if isinstance(bv, Variable): if (hv == bv): self.__headvar_bindings.setdefault(hp, []).append( (bi, bp)) bound = True #assert bound, "Head variable %s not bound to any body variables" % hv if not bound: print >> sys.stderr, "Head variable %s not bound to any body variables" % hv # equality constraints on head self.__headvar_constraints = [] for i, p1 in enumerate(hpositions): t1 = p1.fetch(head) if isinstance(t1, Variable): for p2 in hpositions[i + 1:]: t2 = p2.fetch(head) if t1 == t2: self.__headvar_constraints.append((p1, p2)) CacheHash.__init__(self)
def expand_with_rule(self, r, bi, elab): expanded = [] b = r.get_body()[bi] elab_head = elab.get_head() positions = PositionIndex.get_all_positions(b) assert positions == PositionIndex.get_all_positions(elab_head) # this is so there won't be name collisions elab.mangle_vars("__cr_") # first we have to add the equality constraints constraints from the head # of the elab rule to the condition which is being substituted. for p1,p2 in elab.get_headvar_constraints(): r.add_pos_constraint(bi, p1, bi, p2, Comparison('==')) # propagate the constraints throughout the rule r.enforce_equality() # make the head of the elab rule and the condition being expanded look # exactly the same preserve_vars = [] terms = [p.fetch(b) for p in positions] for p, t in zip(positions, terms): elab_term = p.fetch(elab_head) if t == elab_term: continue if isinstance(elab_term, Constant) and isinstance(t, Variable): p.set(b, elab_term.copy()) elif isinstance(elab_term, Variable) and isinstance(t, Constant): p.set(elab_head, t.copy()) elif isinstance(elab_term, Variable) and isinstance(t, Variable): # should change the variables in the elab rule to match the # expanded rule. Since the equality constraints on the head # variables are already applied to the substituted condition, # we should have that if two variables in the elab head are # equal, those variables in the condition are equal too p.set(elab_head, t.copy()) preserve_vars.append(t.get_name()) else: assert t == elab_term r.enforce_equality(preserve_vars) elab.enforce_equality(preserve_vars) offset = r.num_conditions() gr_head = elab.get_head() # for each constraint that applied to the condition # being expanded, we have to insert duplicates of # those that apply to the inserted conditions # we're going to append all the new rules to the end of # the body first, and then add and modify the approriate # constraints. After everything is done, remove the body # condition that was substituted # no variable equalities should be drawn here for grb in elab.get_body(): r.add_condition(grb) # add the variable constraints for p in positions: if isinstance(p.fetch(gr_head), Constant): continue b2b_cons = r.get_constraints_on(bi, p) # body-to-body constraints hv_bindings = elab.get_headvar_binding(p) for old_i, old_p, comp, order in b2b_cons: for bound_i, bound_p in hv_bindings: if order == 0: # head var first r.add_pos_constraint(offset + bound_i, bound_p, old_i, old_p, comp) else: r.add_pos_constraint(old_i, old_p, offset + bound_i, bound_p, comp) if comp.relation() == '==': # have to rename the variables in original condition to # equal new condition new_cond = r.get_cond(bound_i + offset) new_name = bound_p.fetch(new_cond) old_p.set(r.get_cond(old_i), new_name) # finally remove the replaced condition r.remove_condition(bi) expanded.append(r) return expanded
def get_predicates(rules, roles): """Extract predicate information from the rules""" preds = set() pred_names = set() predTypes = {} # maps places to the equivalence class they're in ec = TypedEquivalenceClass() for r in rules: goal_place_types = {} if r.get_head().get_relation() == 'goal': score = r.get_head().get_term(1).get_name() if score == 0 or score == 100: # we can't really say anything about the middle cases goal_place_types = check_min_max(r, ec, score) score = r.get_head().get_term(1) sentences = r.get_body() elif r.get_head().get_relation() == 'terminal': sentences = r.get_body() else: sentences = [r.get_head()] + r.get_body() for i, s1 in enumerate(sentences): s1pred = s1.get_predicate() assert s1pred != None if s1pred in placetype.preset_types: # the first place is supposed to get acted upon, not act upon the # second place. The preset places are not to be acted upon continue predTypes[s1pred] = s1.get_type() s1pos = PositionIndex.get_all_positions(s1) for p1 in s1pos: ec.get_or_make_class((s1pred, p1)) if len(s1pos) == 0: preds.add(Predicate(s1pred, s1.get_type(), ())) pred_names.add(s1pred) continue added = False for s2 in sentences[i + 1:]: s2pred = s2.get_predicate() s2pos = PositionIndex.get_all_positions(s2) assert s1pred != None and s2pred != None for p1 in s1pos: place1 = (s1pred, p1) t1 = p1.fetch(s1) c1 = ec.get_or_make_class(place1) if place1 in placetype.preset_types: ec.set_class_type(c1, placetype.preset_types[place1]) for p2 in s2pos: place2 = (s2pred, p2) t2 = p2.fetch(s2) if isinstance(t1, Variable) and isinstance(t2, Variable) and \ t1 == t2: if place2 in goal_place_types: ec.set_class_type(c1, goal_place_types[place2]) elif place2 in placetype.preset_types: ec.set_class_type( c1, placetype.preset_types[place2]) else: # put these two places in the same equivalence class place1 = (s1pred, p1) place2 = (s2pred, p2) ec.make_equivalent(place1, place2) # run through the rules again. If a role constant appears somewhere, and # no non-role constants appear in that place, then that place is an agent possible_agent_places = set() impossible_agent_places = set() for r in rules: if r.get_head().get_predicate() != None: sentences = [r.get_head()] + r.get_body() else: sentences = r.get_body() for s in sentences: for p in PositionIndex.get_all_positions(s): place = (s.get_predicate(), p) t = p.fetch(s) if t in roles: if place not in impossible_agent_places: possible_agent_places.add(place) else: if isinstance(t, Constant): impossible_agent_places.add(place) possible_agent_places.discard(place) collected = {} for place in ec.get_all_members(): if place in possible_agent_places: type = placetype.AGENT else: type = ec.get_member_type(place) collected.setdefault(place[0], []).append((place, type)) for p, types in collected.items(): types.sort(lambda x, y: cmp(x[0], y[0])) types_no_place = [t[1] for t in types] preds.add(Predicate(p, predTypes[p], types_no_place)) pred_names.add(p) # go over one more time and see if we missed anything for r in rules: sentences = [r.get_head()] + r.get_body() for s in sentences: p = s.get_predicate() if p == None: continue if p not in pred_names: pos = PositionIndex.get_all_positions(s) preds.add( Predicate(p, s.get_type(), tuple([placetype.UNKNOWN] * len(pos)))) return preds