def add_implicit_iclass(g, each_type_separate=True): """ Adds an implicit graph otherwise a copy of the original graph is returned. :param g: a graph with a non-empty 'entities' list :return: a list of suggested graphs >>> add_implicit_iclass({'edgeSet': [], 'entities': []}) ==\ [{'entities': [], 'edgeSet': [{'type': 'iclass', 'kbID': "P106v"}]}, {'entities': [], 'edgeSet': [{'type': 'iclass', 'kbID': "P31v"}]}] True >>> add_implicit_iclass({'edgeSet': [], 'entities': [{'linkings':[("Q37876", "Natalie Portman")], 'tokens':["Portman"], 'type':'NNP'}]})[0] ==\ {'entities': [{'tokens': ['Portman'], 'linkings': [('Q37876', 'Natalie Portman')], 'type': 'NNP'}], 'edgeSet': [{'type': 'iclass', 'kbID': 'P106v'}]} True >>> add_implicit_iclass({'edgeSet': [], 'entities': [{'linkings':[("Q37876", "city")], 'tokens':["city"], 'type':'NN'}]})[0] ==\ {'entities': [{'tokens': ['city'], 'linkings': [('Q37876', 'city')], 'type': 'NN'}], 'edgeSet': [{'type': 'iclass', 'kbID': "P106v"}]} True >>> add_implicit_iclass({'edgeSet': [], 'entities': [{'linkings':[("Q37876", "city")], 'tokens':["city"], 'type':'NN'}]}, each_type_separate=False)[0] ==\ {'entities': [{'tokens': ['city'], 'linkings': [('Q37876', 'city')], 'type': 'NN'}], 'edgeSet': [{'type': 'iclass'}]} True """ if any(edge.get("type") == 'iclass' for edge in g.get('edgeSet', [])): return [g] if each_type_separate: new_graphs = [] for rel in CLASS_RELATIONS: new_g = graph.copy_graph(g, with_iclass=True) new_g['edgeSet'].append({'type': "iclass", 'kbID': rel}) new_graphs.append(new_g) return new_graphs else: new_g = graph.copy_graph(g, with_iclass=True) new_g['edgeSet'].append({'type': "iclass"}) return [new_g]
def find_groundings(g): """ Retrieve possible groundings for a given graph. :param g: the graph to ground :return: a list of graph groundings. >>> len(find_groundings({'edgeSet': [{'right': ['Percy', 'Jackson'], 'rightkbID': 'Q3899725', 'kbID': 'P674v', 'type': 'direct'}, {'rightkbID': 'Q571', 'right': ['book']}]})) 1 >>> len(find_groundings({'edgeSet': [{'right': ['Percy', 'Jackson'], 'rightkbID': 'Q3899725'}, {'rightkbID': 'Q571', 'right': ['book']}]})) 1 >>> find_groundings({'edgeSet': [{'canonical_right': 'country', 'right': ['country'], 'type': 'class', 'rightkbID':'Q6256'}]}) [{'r0c': 'P31v'}] >>> find_groundings({'edgeSet': [{'canonical_right': 'country', 'right': ['country'], 'type': 'class', 'rightkbID':'Q6256'}, {'right': ['grand', 'bahama', 'island'], 'rightkbID': 'Q866345', 'canonical_right': 'Grand Bahama'}]}) ==\ [{'r0c': 'P31v', 'r1r': 'P17v'}] True >>> find_groundings({'edgeSet': [{'rightkbID': 'Q5620660'}], "tokens": ['Who', 'played', 'Gus', 'Fring', 'in', 'Breaking', 'Bad', '?']}) ==\ [{'r0d': 'P674v'}, {'r0r': 'P106v'}, {'r0r': 'P1441v'}, {'r0r': 'P170v'}, {'r0r': 'P21v'}, {'r0r': 'P31v'}, {'r0v': 'P161v'}, {'r0v': 'P453q'}] True >>> find_groundings({'edgeSet': [{'canonical_right': 'human', 'kbID': 'P31v', 'rightkbID': 'Q5', 'type': 'class'}, \ {'rightkbID': 'Q5620660'}], 'tokens': ['Who', 'played', 'Gus', 'Fring', 'in', 'Breaking', 'Bad', '?']}) ==\ [{'r1r': 'P170v'}, {'r1v': 'P161v'}, {'r1v': 'P453q'}] True >>> find_groundings({'edgeSet': [{'type': 'v-structure', 'right': ['Gus', 'Fring'], 'rightkbID': 'Q5620660', 'propertyName': 'cast member', 'canonical_right': 'Gus Fring', 'kbID': 'P161v'}, {'right': ['Breaking', 'Bad'], 'rightkbID': 'Q1079', 'canonical_right': 'Breaking Bad'}]}) [{'r1r': 'P161v'}] """ query_results = [] num_edges_to_ground = sum( 1 for e in g.get('edgeSet', []) if 'type' not in e or (e.get("type") != "class" and 'kbID' not in e)) num_class_edges_to_ground = sum( 1 for e in g.get('edgeSet', []) if e.get("type") == "class" and 'kbID' not in e) if num_edges_to_ground == 0 and num_class_edges_to_ground == 0: return [{}] if num_edges_to_ground <= 1 and not any( 'hopUp' in e or 'hopDown' in e for e in g.get('edgeSet', []) if not ('type' in e and 'kbID' in e)): query_results += wdaccess.query_graph_groundings(g) else: edges_without_type = sum(1 for e in g.get('edgeSet', []) if 'type' not in e) edge_type_combinations = list( itertools.product(*[['direct', 'reverse']] * edges_without_type)) for type_combination in edge_type_combinations: t = graph.copy_graph(g) for i, edge in enumerate( [e for e in t.get('edgeSet', []) if 'type' not in e]): edge['type'] = type_combination[i] query_results += wdaccess.query_graph_groundings(t) if generation_p['v.structure'] and num_edges_to_ground == 1 and any( w in set(g.get('tokens', [])) for w in v_structure_markers): t = graph.copy_graph(g) edge = [ e for e in t.get('edgeSet', []) if not ('type' in e and 'kbID' in e) ][0] edge['type'] = 'v-structure' query_results += wdaccess.query_graph_groundings(t) return query_results
def add_temporal_relation(g): """ Adds a temporal argmax relation in the graph, that is only the latest/earliest entity is returned as the answer. :param g: a graph with a non-empty edgeSet :return: a list of suggested graphs >>> add_temporal_relation({'edgeSet': [{'right':[2]}, {'right':[8]}], 'entities': [], 'tokens':['who', 'president']}) == \ [{'edgeSet': [{'right':[2]}, {'right':[8]}, {'type':'time', 'argmax':'time'}], 'entities': [], 'tokens':['who', 'president']}] True >>> add_temporal_relation({'edgeSet': [{'right':[2]}, {'right':[8], 'argmin':'time'}], 'entities': []}) [] >>> add_temporal_relation({'edgeSet': [{'right':[2]}, {'type':'time'}], 'entities': []}) [] >>> add_temporal_relation({'edgeSet': [{'kbID': 'P161v','type': 'direct'}],'tokens': ['where','was','<e>','assassinated','?']}) [] """ if len(g.get('edgeSet', [])) == 0 or graph.graph_has_temporal(g): return [] new_graphs = [] consider_types = set() if any(t in argmax_time_markers for t in g.get('tokens', [])): consider_types.add('argmax') if any(t in argmin_time_markers for t in g.get('tokens', [])): consider_types.add('argmin') for t in consider_types.intersection(ARG_TYPES): new_g = graph.copy_graph(g) new_edge = {'type': 'time', t: 'time', 'kbID': "P585v"} new_g['edgeSet'].append(new_edge) new_graphs.append(new_g) return new_graphs
def add_entity_and_relation(g): """ Takes a graph with a non-empty list of free entities and adds a new relations with the one of the free named entities, thus removing it from the list. :param g: a graph with a non-empty 'entities' list :return: a list of suggested graphs >>> add_entity_and_relation({'edgeSet': [], 'entities': []}) [] >>> add_entity_and_relation({'edgeSet': [], 'entities': [{'linkings':[("Q37876", "Natalie Portman"), ("Q872356", "Portman")], 'tokens':["Portman"], 'type':'PERSON'}]}) ==\ [{'edgeSet': [{'right': ['Portman'], 'rightkbID': 'Q37876', 'canonical_right': 'Natalie Portman'}], 'entities': []}, {'edgeSet': [{'right': ['Portman'], 'rightkbID': 'Q872356', 'canonical_right': 'Portman'}], 'entities': []}] True >>> add_entity_and_relation({'edgeSet': [], 'entities': [{'linkings':[("Q37876", "city")], 'tokens':["city"], 'type':'NN'}, {'linkings':[("Q37876", "Natalie Portman")], 'tokens':["Portman"], 'type':'PERSON'}]}) == \ [{'entities': [{'linkings':[("Q37876", "city")], 'tokens':["city"], 'type':'NN'}], 'edgeSet': [{'rightkbID': 'Q37876', 'canonical_right': 'Natalie Portman', 'right': ['Portman']}]}] True >>> add_entity_and_relation({'edgeSet': [], 'entities': [{"linkings": [(None, ["2012"])] ,"tokens": ['2012'], "type": 'CD'}, {'linkings':[("Q37876", "Natalie Portman")], 'tokens':["Portman"], 'type':'PERSON'}]}) == \ [{'entities': [{'linkings': [(None, ['2012'])], 'type': 'CD', 'tokens': ['2012']}], 'edgeSet': [{'rightkbID': 'Q37876', 'canonical_right': 'Natalie Portman', 'right': ['Portman']}]}] True >>> add_entity_and_relation({'edgeSet': [], 'entities': [{"linkings": [(None, ["2012"])] ,"tokens": ['2012'], "type": 'CD'}]}) [] >>> add_entity_and_relation({'edgeSet': [], 'entities': [{'linkings':[("Q37876", "city")], 'tokens':["city"], 'type':'NN'}]}) ==\ [{'entities': [], 'edgeSet': [{'right': ['city'], 'rightkbID': 'Q37876', 'canonical_right': 'city'}]}] True >>> add_entity_and_relation({'edgeSet': [{'rightkbID': 'Q37876', 'canonical_right': 'Natalie Portman', 'right': ['Portman']}], 'entities': [{'linkings':[("Q37876", "city")], 'tokens':["city"], 'type':'NN'}]}) [] >>> add_entity_and_relation({"tokens": ["Who", "played", "Gus", "Fring", "on", "Breaking", "Bad", "?"], "entities": [{"tokens": ["Breaking", "Bad"], "type": "NNP", "linkings": [["Q1079", "Breaking Bad"]]}], "edgeSet": [{"type": "v-structure", "rightkbID": "Q5620660", "right": ["Gus", "Fring"], "propertyName": "cast member", "canonical_right": "Gus Fring", "kbID": "P161v"}]}) """ if len(g.get('entities', [])) == 0: return [] entities = copy.copy(g.get('entities', [])) new_graphs = [] # Consider only named entities entities_to_consider = [ e for e in entities if e.get("type") not in {'CD', 'NN'} ] # If there are no named entities, add one relation with common entity if len(entities_to_consider) == 0 and len(g.get('edgeSet', [])) == 0: entities_to_consider = [e for e in entities if e.get("type") in {'NN'}] skipped = [e for e in entities if e.get("type") in {'CD'}] else: skipped = [e for e in entities if e.get("type") in {'CD', 'NN'}] while entities_to_consider: entity = entities_to_consider.pop(0) if len(entity.get("linkings", [])) > 0: linkings = entity['linkings'] for kbID, label in linkings: new_g = graph.copy_graph(g) new_g['entities'] = skipped[:] + entities_to_consider[:] new_g['edgeSet'].append({ 'right': entity.get("tokens", []), 'rightkbID': kbID, 'canonical_right': label }) new_graphs.append(new_g) return new_graphs
def encode_graphs(self, instance): _, graph_set = instance graphs_encoded = deque() for g in graph_set: g = graph.graph_format_update(g) if not self._p.get("encode.iclass", False): g = graph.copy_graph(g, with_iclass=False) edges_encoded = [] for edge in g.get('edgeSet', []): property_label_tokens = self._get_edge_str_representation(edge).split() edge_encoded = self._encode_tokens(property_label_tokens) edges_encoded.append(edge_encoded) graphs_encoded.append(edges_encoded) return graphs_encoded
def apply_topics(g, topics): """ Apply topics to the implicit edges or create new if needed. :param g: input graph :param topics: topics dictionary :return: graphs with implicit class edges >>> apply_topics({'edgeSet': [{'kbID': 'P1066v', 'rightkbID': 'Q37571', 'type': 'reverse'}]}, {'P31v': ['human'], 'P106v': ['lawyer', 'politician', 'political writer']}) ==\ {'edgeSet': [{'kbID': 'P1066v', 'rightkbID': 'Q37571', 'type': 'reverse'}, {'kbID': 'P31v', 'type': 'iclass', 'canonical_right': ['human']}, {'kbID': 'P106v', 'type': 'iclass', 'canonical_right': ['lawyer', 'politician', 'political writer']}], 'entities': []} True """ grounded = graph.copy_graph(g) for kbID, values in topics.items(): new_edge = {'type': 'iclass'} new_edge['kbID'] = kbID new_edge['canonical_right'] = values grounded['edgeSet'].append(new_edge) return grounded
def apply_grounding(g, grounding): """ Given a grounding obtained from WikiData apply it to the graph. Note: that the variable names returned by WikiData are important as they encode some grounding features. :param g: a single ungrounded graph :param grounding: a dictionary representing the grounding of relations and variables :return: a grounded graph >>> apply_grounding({'edgeSet':[{}]}, {'r0d':'P31v'}) == {'edgeSet': [{'type': 'direct', 'kbID': 'P31v', }], 'entities': []} True >>> apply_grounding({'edgeSet':[{}]}, {'r0v':'P31v'}) == {'edgeSet': [{'type': 'v-structure', 'kbID': 'P31v'}], 'entities': []} True >>> apply_grounding({'edgeSet':[{"hopUp":None}]}, {'r0v':'P31v', 'hop0v':'P131v'}) == {'edgeSet': [{'type': 'v-structure', 'kbID': 'P31v', 'hopUp':'P131v'}], 'entities': []} True >>> apply_grounding({'edgeSet': [{'type': 'v-structure', 'kbID': 'P31v', 'hopUp':'P131v'}], 'tokens': []}, {}) == {'edgeSet': [{'type': 'v-structure', 'kbID': 'P31v', 'hopUp':'P131v'}], 'entities': [], 'tokens': []} True >>> apply_grounding({'edgeSet':[{}, {}]}, {'r1d':'P39v', 'r0v':'P31v', 'e20': 'Q18'}) == {'edgeSet': [{'type': 'v-structure', 'kbID': 'P31v', 'rightkbID': 'Q18'}, {'type': 'direct', 'kbID': 'P39v'}], 'entities': []} True >>> apply_grounding({'edgeSet':[]}, {}) == {'entities': [], 'edgeSet': []} True """ grounded = graph.copy_graph(g) for i, edge in enumerate(grounded.get('edgeSet', [])): if "e2" + str(i) in grounding: edge['rightkbID'] = grounding["e2" + str(i)] if "hop{}v".format(i) in grounding: if 'hopUp' in edge: edge['hopUp'] = grounding["hop{}v".format(i)] else: edge['hopDown'] = grounding["hop{}v".format(i)] if "r{}d".format(i) in grounding: edge['kbID'] = grounding["r{}d".format(i)] edge['type'] = 'direct' elif "r{}r".format(i) in grounding: edge['kbID'] = grounding["r{}r".format(i)] edge['type'] = 'reverse' elif "r{}v".format(i) in grounding: edge['kbID'] = grounding["r{}v".format(i)] edge['type'] = 'v-structure' elif "r{}c".format(i) in grounding: edge['kbID'] = grounding["r{}c".format(i)] edge['type'] = 'class' return grounded
def manual_groundings(g): """ :param g: :return: >>> manual_groundings({'edgeSet': [{'canonical_right': 'Thailand','rightkbID': 'Q869'}], 'tokens': ['what', 'religion', 'in', 'thailand', '?']}) ==\ [{'tokens': ['what', 'religion', 'in', 'thailand', '?'], 'edgeSet': [{'rightkbID': 'Q869', 'type': 'reverse', 'kbID': 'P140v', 'hopUp': 'P27v', 'canonical_right': 'Thailand'}], 'entities': []}] True """ grounded_graphs = [] if any(w in set(g.get('tokens', [])) for w in religion_markers): t = graph.copy_graph(g) edge = [ e for e in t.get('edgeSet', []) if 'type' not in e or ( e.get("type") != "class" and 'kbID' not in e) ] if len(edge) == 1: edge = edge[0] edge['type'] = 'reverse' edge['hopUp'] = 'P27v' edge['kbID'] = 'P140v' grounded_graphs.append(t) return grounded_graphs
def last_relation_numeric(g): """ Adds a numeric restriction to the last relation in the graph. :param g: a graph with a non-empty edgeSet :return: a list of suggested graphs >>> last_relation_numeric({'edgeSet': [{'right':[2], 'type':'direct'}, {'right':[8], 'type':'direct'}], 'entities': [{'linkings':[("Q37876", "Natalie Portman")], 'tokens':["Portman"], 'type':'PERSON'}, {'linkings': [(None, ['2012'])], 'type': 'CD', 'tokens': ['2012']}]}) == \ [{'edgeSet': [{'right':[2], 'type':'direct'}, {'right':[8], 'type':'direct', 'num': ['2012']}], 'entities': [{'linkings':[("Q37876", "Natalie Portman")], 'tokens':["Portman"], 'type':'PERSON'}]}] True >>> last_relation_numeric({'edgeSet': [{'right':[2]}, {'right':[8], 'argmin':'time'}], 'entities': [{'linkings': [(None, ['2012'])], 'type': 'CD', 'tokens': ['2012']}]}) [] >>> last_relation_numeric({'edgeSet': [{'right':[2]}, {'right':[8], 'num':'2009'}], 'entities': [{'linkings': [(None, ['2012'])], 'type': 'CD', 'tokens': ['2012']}]}) [] >>> last_relation_numeric({'edgeSet': [{'right':[2]}], 'entities': []}) [] >>> last_relation_numeric({'edgeSet': [{'right':[2]}], 'entities': [{'linkings':[("Q37876", "Natalie Portman")], 'tokens':["Portman"], 'type':'PERSON'}]}) [] """ if len(g.get('edgeSet', [])) == 0 or graph.graph_has_temporal(g): return [] if len(g.get('entities', [])) == 0 or not any( e.get("type") == 'CD' for e in g['entities'] if len(e) > 1): return [] entities = copy.copy(g.get('entities', [])) cd_entities = [e.get("tokens") for e in entities if e.get("type") == 'CD'] if len(cd_entities) == 0: return [] cd_entity = cd_entities[0] entities = [e for e in entities if e.get("tokens") != cd_entity] new_g = graph.copy_graph(g) new_g['entities'] = entities edge_to_modify = graph.get_graph_last_edge( new_g, filter_out_types={'iclass', 'v-structure', 'class'}) if len(edge_to_modify) > 0: edge_to_modify['num'] = cd_entity return [new_g] return []
def last_relation_hop(g): """ Takes a graph with an existing relation and an intermediate variable by performing a hop-up for the second entity. :param g: a graph with an non-empty edgeSet :return: a list of suggested graphs >>> last_relation_hop({'edgeSet': [], 'entities': [[4, 5, 6]]}) [] >>> last_relation_hop({'edgeSet': [{'right':[4,5,6]}], 'entities': []}) ==\ [{'edgeSet': [{'right':[4,5,6], 'hopUp': None}], 'entities': []}, {'edgeSet': [{'right':[4,5,6], 'hopDown': None}], 'entities': []}] True >>> last_relation_hop({'edgeSet': [{'right':[4,5,6], 'hopUp': None}], 'entities': []}) [] >>> last_relation_hop({'edgeSet': [{'right':[4,5,6], 'kbID': "P31v", "type": "direct"}], 'entities': []}) [] >>> last_relation_hop({'edgeSet': [{'right':["Bahama"], "rightkbID":"Q6754", 'type':'direct'}], 'entities': []}) ==\ [{'edgeSet': [{'right':["Bahama"], "rightkbID":"Q6754", 'hopUp': None, 'type':'direct'}], 'entities': []}, {'edgeSet': [{'right':["Bahama"], "rightkbID":"Q6754", 'hopDown': None, 'type':'direct'}], 'entities': []}] True >>> last_relation_hop({'edgeSet': [{'right':[4,5,6], 'argmax':'time'}], 'entities': []}) [] >>> last_relation_hop({'edgeSet': [{'right':[4,5,6], 'num':['2012']}], 'entities': []}) [] """ if len(g.get('edgeSet', [])) == 0 or any( hop in g['edgeSet'][-1] for hop in {'hopUp', 'hopDown'}) or graph.graph_has_temporal(g): return [] new_graphs = [] for hop in HOP_TYPES: new_g = graph.copy_graph(g) edge_to_modify = graph.get_graph_last_edge( new_g, filter_out_types={'iclass', 'class', 'v-structure', 'time'}) if len(edge_to_modify) > 0 and 'kbID' not in edge_to_modify: edge_to_modify[hop] = None new_graphs.append(new_g) return new_graphs
def add_class(g, keep_skipped=False): """ Takes a graph with a non-empty list of free entities and adds a new class relation with the one of the free entities, thus removing it from the list. :param g: a graph with a non-empty 'entities' list :return: a list of suggested graphs >>> add_class({'edgeSet': [], 'entities': []}) [] >>> add_class({'edgeSet': [], 'entities': [], "tokens": "where is London ?".split()}) ==\ [{'edgeSet': [{'type': 'class', 'rightkbID': 'Q618123', 'kbID': "P31v", 'canonical_right': 'geographical object'}], 'entities': [], 'tokens': ['where', 'is', 'London', '?']}] True >>> add_class({'edgeSet': [], 'entities': [{'linkings':[("Q37876", "Natalie Portman")], 'tokens':["Portman"], 'type':'NNP'}]}) [] >>> add_class({'edgeSet': [], 'entities': [{'linkings':[("Q37876", "album")], 'tokens':["album"], 'type':'NN'}, {'linkings':[("Q37876", "Natalie Portman")], 'tokens':["Portman"], 'type':'NNP'}]}) == \ [{'entities': [{'linkings':[("Q37876", "Natalie Portman")], 'tokens':["Portman"], 'type':'NNP'}], 'edgeSet': [{'canonical_right': 'album', 'type': 'class', 'rightkbID': 'Q37876', 'right': ['album']}]}] True >>> add_class({'edgeSet': [], 'entities': [{"linkings": [(None, ["2012"])] ,"tokens": ['2012'], "type": 'CD'}, {'linkings':[("Q37876", "Natalie Portman")], 'tokens':["Portman"], 'type':'PERSON'}, {'linkings':[("Q37876", "city")], 'tokens':["city"], 'type':'NN'}]}, keep_skipped=True) == \ [{'entities': [{'type': 'CD', 'tokens': ['2012'], 'linkings': [(None, ['2012'])]}, {'type': 'PERSON', 'tokens': ['Portman'], 'linkings': [('Q37876', 'Natalie Portman')]}], 'edgeSet': [{'canonical_right': 'city', 'type': 'class', 'rightkbID': 'Q37876', 'right': ['city']}]}] True >>> add_class({'edgeSet': [], 'entities': [{'linkings':[("Q37876", "city")], 'tokens':["city"], 'type':'NN'}]}) [] >>> len(add_class({'edgeSet': [], 'entities': [{'linkings':[("Q37876", "album"), ("Q390076", "album")], 'tokens':["album"], 'type':'NN'}, {'linkings':[("Q37876", "Natalie Portman")], 'tokens':["Portman"], 'type':'NNP'}]})) 1 >>> add_class({'edgeSet': [], 'entities': [{'linkings': [('Q866345', 'Grand Bahama')], 'type': 'NNP', 'tokens': ['grand', 'bahama', 'island']}, {'linkings': [('Q23442', 'island')], 'type': 'NNP', 'tokens': ['grand', 'bahama', 'island']}, {'linkings': [('Q6256', 'country')], 'type': 'NN', 'tokens': ['country']}], 'tokens': ['what', 'country', 'is', 'the', 'grand', 'bahama', 'island', 'in', '?']}, keep_skipped=True) ==\ [{'edgeSet': [{'right': ['country'], 'rightkbID': 'Q6256', 'canonical_right': 'country', 'type': 'class'}], 'entities': [{'linkings': [('Q866345', 'Grand Bahama')], 'type': 'NNP', 'tokens': ['grand', 'bahama', 'island']}, {'linkings': [('Q23442', 'island')], 'type': 'NNP', 'tokens': ['grand', 'bahama', 'island']}], 'tokens': ['what', 'country', 'is', 'the', 'grand', 'bahama', 'island', 'in', '?']}] True """ # If there is already another class defined, don't add anything if any(edge.get("type") == 'class' for edge in g.get('edgeSet', [])): return [] # If the type is temporal, don't add classes if graph.get_question_type(g) == "temporal": return [] if graph.get_question_type(g) == "person": new_g = graph.copy_graph(g) new_g['edgeSet'].append({ 'rightkbID': "Q5", 'kbID': "P31v", 'canonical_right': "human", 'type': "class" }) return [new_g] if graph.get_question_type(g) == "location": new_g = graph.copy_graph(g) new_g['edgeSet'].append({ 'rightkbID': "Q618123", 'kbID': "P31v", 'canonical_right': "geographical object", 'type': "class" }) return [new_g] # If there are no common entities, don't add anything if len(g.get('entities', [])) == 0 or not any( e.get("type") == 'NN' for e in g['entities'] if len(e) > 1): return [] # If there is only one entity left and it is a common entity and there are no other edges, don't add anything if len(g.get('entities', [])) == 1 and all( e.get("type") == 'NN' for e in g.get('entities', [])) and len(g.get('edgeSet', [])) == 0: return [] entities = copy.copy(g.get('entities', [])) skipped = [] new_graphs = [] while entities: entity = entities.pop(0) if entity.get("type") == 'NN': if len(entity.get("linkings", [])) > 0: linkings = entity['linkings'] if len(linkings) > 0: kbID, label = linkings[0] new_g = graph.copy_graph(g) new_g['entities'] = (skipped[:] if keep_skipped else []) + entities[:] new_g['edgeSet'].append({ 'right': entity.get("tokens", []), 'rightkbID': kbID, 'canonical_right': label, 'type': "class" }) new_graphs.append(new_g) else: skipped.append(entity) return new_graphs