def backward(self, oia_graph: OIAGraph, ** kwargs): """ @param oia_graph: @type oia_graph: @param kwargs: @type kwargs: @return: @rtype: """ fixed = False for node in list(oia_graph.nodes()): if not is_conjunction_without_args(node, oia_graph): continue relations = [(n, l.label) for n, l in oia_graph.children(node)] relations = list(filter(lambda x: x[1].startswith("pred.arg."), relations)) if not relations: continue if any(len(list(oia_graph.children(child))) for child, rel in relations): # child nodes also has child, not merge continue merged_words = sum([list(child.words()) for child, rel in relations], []) start = min([x for x in merged_words if isinstance(x, int)]) end = max([x for x in merged_words if isinstance(x, int)]) new_node = oia_graph.add_spans([(start, end)]) fixed = True for child, rel in relations: oia_graph.remove_node(child) oia_graph.replace(node, new_node) logger.debug("Merging {0} to {1}".format("|".join(oia_graph.node_text(child) for child, rel in relations), oia_graph.node_text(new_node))) return fixed
def graph_match_metric(pred_graph: OIAGraph, truth_graph: OIAGraph): """ :param predict: :param truth: :return: """ pred_nodes = [pred_graph.node_text(n) for n in pred_graph.nodes()] true_nodes = [truth_graph.node_text(n) for n in truth_graph.nodes()] node_true_num = len(true_nodes) node_pred_num = len(pred_nodes) node_match_num = sum(node in true_nodes for node in pred_nodes) pred_edges = [(pred_graph.node_text(n1), edge.label.strip("\" "), pred_graph.node_text(n2)) for n1, edge, n2 in pred_graph.edges()] true_edges = [(truth_graph.node_text(n1), edge.label.strip("\" "), truth_graph.node_text(n2)) for n1, edge, n2 in truth_graph.edges()] logger.debug(pred_edges) logger.debug(true_edges) edge_true_num = len(true_edges) edge_pred_num = len(pred_edges) edge_match_num = sum(edge in true_edges for edge in pred_edges) exact_same = node_match_num == node_true_num == node_pred_num and \ edge_match_num == edge_true_num == edge_pred_num return (node_pred_num, node_true_num, node_match_num), \ (edge_pred_num, edge_true_num, edge_match_num), exact_same
def forward(self, oia_graph: OIAGraph, **kwargs): """ split the noun phrase with of in it According to the previous merge operation, if there is any modification to the part after the of, the noun phrase will be not merged. So the noun phrases with of do not have any modification to the second part. @param oia_graph: @type oia_graph: @param kwargs: @type kwargs: @return: @rtype: """ for node in list(oia_graph.nodes()): node_words = oia_graph.node_text(node).split(" ") try: index = node_words.index("of") except Exception as e: continue if len(node_words) == 1: # that is of continue of_split_words = [] current_words = [] for span in node.spans: if isinstance(span, str): current_words.append(span) else: start, end = span for idx in range(start, end + 1): if oia_graph.words[idx] == "of": of_split_words.append(current_words) of_split_words.append(idx) current_words = [] else: current_words.append(idx) if not current_words: # of is the ending, warning, maybe something like "because of " logger.warning("We found a of at the last of the phrase: " + oia_graph.node_text(node)) continue of_split_words.append(current_words) first_part_words = of_split_words[0] first_node = oia_graph.add_words(first_part_words) previous_node = first_node for p, l in list(oia_graph.parents(node)): oia_graph.add_relation(p, first_node, l.label) oia_graph.remove_relation(p, node) children = list(oia_graph.children(node)) if children: logger.warning( "noun of noun has {0} children, be careful!!!".format( len(children))) for c, l in children: logger.warning("Child: {} {}".format( l.label, oia_graph.node_text(c))) oia_graph.add_relation(first_node, c, l.label) oia_graph.remove_relation(node, c) oia_graph.remove_node(node) for of_word, noun_words in more_itertools.chunked( of_split_words[1:], 2): of_node = oia_graph.add_words([of_word]) next_node = oia_graph.add_words(noun_words) oia_graph.add_relation(previous_node, of_node, "as:pred.arg.1") oia_graph.add_relation(of_node, next_node, "pred.arg.2") previous_node = next_node
def forward(self, oia_graph: OIAGraph, dep_graph: DependencyGraph=None, **kwargs): """ note that this only process the situation that @param oia_graph: @type oia_graph: @param kwargs: @type kwargs: @return: @rtype: """ for node in list(oia_graph.nodes()): node_words = oia_graph.node_text(node).split(" ") if not any([x in {"and", "or"} for x in node_words]): continue if any(["{" in x and "}" in x for x in node_words]): continue arguments = [] conjs = [] current_words = [] for span in node.spans: if isinstance(span, str): current_words.append(span) else: start, end = span for idx in range(start, end + 1): if oia_graph.words[idx].lower() in {"and", "or"}: arguments.append(current_words) conjs.append(idx) current_words = [] else: current_words.append(idx) arguments.append(current_words) logger.debug("conj found = {}".format(conjs)) logger.debug("argument found = {}".format(arguments)) if all(not arg or all(oia_graph.words[x] in {",", ";", ".", " "} for x in arg) for arg in arguments): # single words continue if len(conjs) == 1: conj_words = conjs else: # len(conjs) >= 2: logger.warning("We are processing conjs with more than two args") conj_words = ['{1}'] for idx, conj in enumerate(conjs): conj_words.append(conj) conj_words.append("{{{0}}}".format(idx + 2)) conj_node = oia_graph.add_words(conj_words) for idx, arg in enumerate(arguments): arg_node = oia_graph.add_words(arg) oia_graph.add_relation(conj_node, arg_node, "pred.arg.{0}".format(idx + 1)) for p, l in list(oia_graph.parents(node)): oia_graph.add_relation(p, conj_node, l.label) oia_graph.remove_relation(p, node) for c, l in list(oia_graph.children(node)): oia_graph.add_relation(conj_node, c, l.label) oia_graph.remove_relation(node, c) oia_graph.remove_node(node)