/** * Given an iterable set of edges, returns the set of vertices covered by these edges. * * Note: CDM changed the return of this from a List to a Set in 2011. This seemed more * sensible. Hopefully it doesn't break anything.... */ private static Set<IndexedWord> getVerticesFromEdgeSet(Iterable<SemanticGraphEdge> edges) { Set<IndexedWord> retSet = Generics.newHashSet(); for (SemanticGraphEdge edge : edges) { retSet.add(edge.getGovernor()); retSet.add(edge.getDependent()); } return retSet; }
/** * Pretty printers */ public static String printEdges(Iterable<SemanticGraphEdge> edges) { StringWriter buf = new StringWriter(); for (SemanticGraphEdge edge : edges) { buf.append("\t"); buf.append(edge.getRelation().toString()); buf.append("("); buf.append(edge.getGovernor().toString()); buf.append(", "); buf.append(edge.getDependent().toString()); buf.append(")\n"); } return buf.toString(); }
/** The head of the subject of this relation triple. */ @Override public CoreLabel subjectHead() { if (subject.size() == 1) { return subject.get(0); } Span subjectSpan = Span.fromValues(subject.get(0).index(), subject.get(subject.size() - 1).index()); for (int i = subject.size() - 1; i >= 0; --i) { for (SemanticGraphEdge edge : sourceTree.incomingEdgeIterable(new IndexedWord(subject.get(i)))) { if (edge.getGovernor().index() < subjectSpan.start() || edge.getGovernor().index() >= subjectSpan.end()) { return subject.get(i); } } } return subject.get(subject.size() - 1); }
/** The head of the object of this relation triple. */ @Override public CoreLabel objectHead() { if (object.size() == 1) { return object.get(0); } Span objectSpan = Span.fromValues(object.get(0).index(), object.get(object.size() - 1).index()); for (int i = object.size() - 1; i >= 0; --i) { for (SemanticGraphEdge edge : sourceTree.incomingEdgeIterable(new IndexedWord(object.get(i)))) { if (edge.getGovernor().index() < objectSpan.start() || edge.getGovernor().index() >= objectSpan.end()) { return object.get(i); } } } return object.get(object.size() - 1); }
@Override public boolean prerequisitesMet(SemanticGraph originalTree, SemanticGraphEdge edge) { // Only valid if there's a single nontrivial outgoing edge from a node. Otherwise it's a whole can of worms. Iterator<SemanticGraphEdge> iter = originalTree.outgoingEdgeIterable(edge.getGovernor()).iterator(); if (!iter.hasNext()) { return false; // what? } boolean nontrivialEdge = false; while (iter.hasNext()) { SemanticGraphEdge outEdge = iter.next(); switch (outEdge.getRelation().toString()) { case "nn": case "amod": break; default: if (nontrivialEdge) { return false; } nontrivialEdge = true; } } return true; }
/** * Determine if a tree is cyclic. * @param tree The tree to check. * @return True if the tree has at least once cycle in it. */ public static boolean isCyclic(SemanticGraph tree) { for (IndexedWord vertex : tree.vertexSet()) { if (tree.getRoots().contains(vertex)) { continue; } IndexedWord node = tree.incomingEdgeIterator(vertex).next().getGovernor(); Set<IndexedWord> seen = new HashSet<>(); seen.add(vertex); while (node != null) { if (seen.contains(node)) { return true; } seen.add(node); if (tree.incomingEdgeIterator(node).hasNext()) { node = tree.incomingEdgeIterator(node).next().getGovernor(); } else { node = null; } } } return false; }
@Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof SemanticGraphEdge)) return false; final SemanticGraphEdge semanticGraphEdge = (SemanticGraphEdge) o; if (relation != null) { boolean retFlag = relation.equals(semanticGraphEdge.relation); boolean govMatch = getGovernor().equals(semanticGraphEdge.getGovernor()); boolean depMatch = getDependent().equals(semanticGraphEdge.getDependent()); boolean matched = retFlag && govMatch && depMatch; return matched; } // if (relation != null ? !relation.equals(semanticGraphEdge.relation) : semanticGraphEdge.relation != null) return false; return super.equals(o); }
protected static void crawl(IndexedWord vertex, SemanticGraph sg, Set<IndexedWord> seenVerts) { seenVerts.add(vertex); for (SemanticGraphEdge edge : sg.incomingEdgeIterable(vertex)) { IndexedWord gov = edge.getGovernor(); if (!seenVerts.contains(gov)) { crawl(gov, sg, seenVerts); } } for (SemanticGraphEdge edge : sg.outgoingEdgeIterable(vertex)) { IndexedWord dep = edge.getDependent(); if (!seenVerts.contains(dep)) { crawl(dep, sg, seenVerts); } } }
/** The head of the relation of this relation triple. */ @Override public CoreLabel relationHead() { if (relation.size() == 1) { return relation.get(0); } CoreLabel guess = null; CoreLabel newGuess = super.relationHead(); int iters = 0; // make sure we don't infinite loop... while (guess != newGuess && iters < 100) { guess = newGuess; iters += 1; for (SemanticGraphEdge edge : sourceTree.incomingEdgeIterable(new IndexedWord(guess))) { // find a node in the relation list which is a governor of the candidate root Optional<CoreLabel> governor = relation.stream().filter(x -> x.index() == edge.getGovernor().index()).findFirst(); // if we found one, this is the new root. The for loop continues if (governor.isPresent()) { newGuess = governor.get(); } } } // Return if (iters >= 100) { err("Likely cycle in relation tree"); } return guess; }
public SemanticGraphEdge addEdge(SemanticGraphEdge edge) { SemanticGraphEdge newEdge = new SemanticGraphEdge(edge.getGovernor(), edge.getDependent(), edge.getRelation(), edge.getWeight(), edge.isExtra()); graph.add(edge.getGovernor(), edge.getDependent(), newEdge); return newEdge; }
public static List<String> dependencyPathAsList(List<SemanticGraphEdge> edgePath, IndexedWord node, boolean generalize) { if(edgePath == null) return null; List<String> path = new ArrayList<>(); for (SemanticGraphEdge edge : edgePath) { IndexedWord nextNode; GrammaticalRelation relation; if (generalize) { relation = generalizeRelation(edge.getRelation()); } else { relation = edge.getRelation(); } if (node.equals(edge.getDependent())) { String v = (relation + "->").intern(); path.add(v); nextNode = edge.getGovernor(); } else { String v = ("<-" + relation).intern(); path.add(v); nextNode = edge.getDependent(); } node = nextNode; } return path; }
/** A helper method for * {@link NaturalLogicAnnotator#getModifierSubtreeSpan(edu.stanford.nlp.semgraph.SemanticGraph, edu.stanford.nlp.ling.IndexedWord)} and * {@link NaturalLogicAnnotator#getSubtreeSpan(edu.stanford.nlp.semgraph.SemanticGraph, edu.stanford.nlp.ling.IndexedWord)}. */ private static Pair<Integer, Integer> getGeneralizedSubtreeSpan(SemanticGraph tree, IndexedWord root, Set<String> validArcs) { int min = root.index(); int max = root.index(); Queue<IndexedWord> fringe = new LinkedList<>(); for (SemanticGraphEdge edge : tree.outgoingEdgeIterable(root)) { String edgeLabel = edge.getRelation().getShortName(); if ((validArcs == null || validArcs.contains(edgeLabel)) && !"punct".equals(edgeLabel)) { fringe.add(edge.getDependent()); } } while (!fringe.isEmpty()) { IndexedWord node = fringe.poll(); min = Math.min(node.index(), min); max = Math.max(node.index(), max); // ignore punctuation fringe.addAll(tree.getOutEdgesSorted(node).stream().filter(edge -> edge.getGovernor().equals(node) && !(edge.getGovernor().equals(edge.getDependent())) && !"punct".equals(edge.getRelation().getShortName())).map(SemanticGraphEdge::getDependent).collect(Collectors.toList())); } return Pair.makePair(min, max + 1); }
@Override public Optional<State> applyTo(SemanticGraph tree, State source, SemanticGraphEdge outgoingEdge, SemanticGraphEdge subjectOrNull, SemanticGraphEdge objectOrNull) { return Optional.of(new State( outgoingEdge, subjectOrNull == null ? source.subjectOrNull : subjectOrNull, subjectOrNull == null ? (source.distanceFromSubj + 1) : 0, objectOrNull == null ? source.objectOrNull : objectOrNull, source.thunk.andThen(toModify -> { assert Util.isTree(toModify); simpleClause(toModify, outgoingEdge); addSubtree(toModify, outgoingEdge.getDependent(), "nsubjpass", tree, outgoingEdge.getGovernor(), Collections.singleton(outgoingEdge)); // addWord(toModify, outgoingEdge.getDependent(), "auxpass", mockNode(outgoingEdge.getDependent().backingLabel(), "is", "VBZ")); assert Util.isTree(toModify); }), true )); } });
/** * Mostly just an alias, but make sure our featurizer is serializable! */ public interface Featurizer extends Function<Triple<ClauseSplitterSearchProblem.State, ClauseSplitterSearchProblem.Action, ClauseSplitterSearchProblem.State>, Counter<String>>, Serializable { boolean isSimpleSplit(Counter<String> feats); }
public static void copyEmptyNodes(SemanticGraph source, SemanticGraph target) { for (IndexedWord node : source.vertexSet()) { if (isEmptyNode(node)) { target.addVertex(node); System.err.println("added vertex" + node); } } //remove all orphan dependencies for (SemanticGraphEdge edge: target.edgeListSorted()) { if (edge.getRelation().getShortName().equals("orphan")) { target.removeEdge(edge); System.err.println("removed edge" + edge); } } for (SemanticGraphEdge edge : source.edgeIterable()) { if (edge.getRelation().getShortName().equals("orphan") || isEmptyNode(edge.getDependent()) || isEmptyNode(edge.getGovernor())) { target.addEdge(edge.getGovernor(), edge.getDependent(), edge.getRelation(), edge.getWeight(), edge.isExtra()); System.err.println("added edge" + edge); } } }
/** * Copies a the current graph, but also sets the mapping from the old to new * graph. */ public SemanticGraph(SemanticGraph g, Map<IndexedWord, IndexedWord> prevToNewMap) { graph = new DirectedMultiGraph<>(outerMapFactory, innerMapFactory); if (prevToNewMap == null) { prevToNewMap = wordMapFactory.newMap(); } Set<IndexedWord> vertexes = g.vertexSet(); for (IndexedWord vertex : vertexes) { IndexedWord newVertex = new IndexedWord(vertex); newVertex.setCopyCount(vertex.copyCount()); addVertex(newVertex); prevToNewMap.put(vertex, newVertex); } roots = wordMapFactory.newSet(); for (IndexedWord oldRoot : g.getRoots()) { roots.add(prevToNewMap.get(oldRoot)); } for (SemanticGraphEdge edge : g.edgeIterable()) { IndexedWord newGov = prevToNewMap.get(edge.getGovernor()); IndexedWord newDep = prevToNewMap.get(edge.getDependent()); addEdge(newGov, newDep, edge.getRelation(), edge.getWeight(), edge.isExtra()); } }
private static void fixCCAttachment(SemanticGraph sg) { HashMap<SemanticGraphEdge, Integer> newHeads = new HashMap<>(); for (SemanticGraphEdge edge : sg.edgeIterable()) { if (edge.getRelation().equals(UniversalEnglishGrammaticalRelations.COORDINATION)) { // check if "cc" is attached to previous conjunct if (edge.getGovernor().index() < edge.getDependent().index()) { Set<IndexedWord> conjuncts = sg.getChildrenWithReln(edge.getGovernor(), UniversalEnglishGrammaticalRelations.CONJUNCT); int newHead = Integer.MAX_VALUE; for (IndexedWord conjunct : conjuncts) { if (conjunct.index() < newHead && conjunct.index() > edge.getDependent().index()) { newHead = conjunct.index(); } } if (newHead < Integer.MAX_VALUE) { newHeads.put(edge, newHead); } } } } for (SemanticGraphEdge edge : newHeads.keySet()) { IndexedWord newGovernor = sg.getNodeByIndex(newHeads.get(edge)); sg.removeEdge(edge); sg.addEdge(newGovernor, edge.getDependent(), edge.getRelation(), edge.getWeight(), edge.isExtra()); } }
/** * Given a list of graphs, constructs a new graph combined from the * collection of graphs. Original vertices are used, edges are * copied. Graphs are ordered by the sentence index and index of * the original vertices. Intent is to create a "mega graph" * similar to the graphs used in the RTE problem. * <br> * This method only works if the indexed words have different * sentence ids, as otherwise the maps used will confuse several of * the IndexedWords. */ public static SemanticGraph makeFromGraphs(Collection<SemanticGraph> sgList) { SemanticGraph sg = new SemanticGraph(); Collection<IndexedWord> newRoots = Generics.newHashSet(); for (SemanticGraph currSg : sgList) { newRoots.addAll(currSg.getRoots()); for (IndexedWord currVertex : currSg.vertexSet()) sg.addVertex(currVertex); for (SemanticGraphEdge currEdge : currSg.edgeIterable()) sg.addEdge(currEdge.getGovernor(), currEdge.getDependent(), currEdge.getRelation(), currEdge.getWeight(), currEdge.isExtra()); } sg.setRoots(newRoots); return sg; }
/** * This creates a new graph based off the given, but uses the existing nodes objects. */ public static SemanticGraph duplicateKeepNodes(SemanticGraph sg) { SemanticGraph retSg = new SemanticGraph(); for (IndexedWord node : sg.vertexSet()) { retSg.addVertex(node); } retSg.setRoots(sg.getRoots()); for (SemanticGraphEdge edge : sg.edgeIterable()) { retSg.addEdge(edge.getGovernor(), edge.getDependent(), edge.getRelation(), edge.getWeight(), edge.isExtra()); } return retSg; }
/** * Given a graph, ensures all edges are EnglishGrammaticalRelations. * NOTE: this is English specific. * NOTE: currently EnglishGrammaticalRelations does not link collapsed prep string forms * back to their object forms, for its valueOf relation. This may need to be repaired if * generated edges indeed do have collapsed preps as strings. */ private static void enRepairEdges(SemanticGraph sg, boolean verbose) { for (SemanticGraphEdge edge : sg.edgeIterable()) { if (edge.getRelation().isFromString()) { GrammaticalRelation newReln = EnglishGrammaticalRelations.valueOf(edge.getRelation().toString()); if (newReln != null) { IndexedWord gov = edge.getGovernor(); IndexedWord dep = edge.getDependent(); double weight = edge.getWeight(); boolean isExtra = edge.isExtra(); sg.removeEdge(edge); sg.addEdge(gov, dep, newReln, weight, isExtra); } else { if (verbose) log.info("Warning, could not find matching GrammaticalRelation for reln=" + edge.getRelation()); } } } }