public virtual void TestTopologicalSort() { SemanticGraph gr = SemanticGraph.ValueOf("[ate subj>Bill dobj>[muffins compound>blueberry]]"); VerifyTopologicalSort(gr); IList <IndexedWord> vertices = gr.VertexListSorted(); gr.AddEdge(vertices[1], vertices[2], UniversalEnglishGrammaticalRelations.DirectObject, 1.0, false); VerifyTopologicalSort(gr); gr = SemanticGraph.ValueOf("[ate subj>Bill dobj>[muffins compound>blueberry]]"); vertices = gr.VertexListSorted(); gr.AddEdge(vertices[2], vertices[1], UniversalEnglishGrammaticalRelations.DirectObject, 1.0, false); VerifyTopologicalSort(gr); gr = SemanticGraph.ValueOf("[ate subj>Bill dobj>[muffins compound>blueberry]]"); vertices = gr.VertexListSorted(); gr.AddEdge(vertices[1], vertices[3], UniversalEnglishGrammaticalRelations.DirectObject, 1.0, false); VerifyTopologicalSort(gr); // now create a graph with a directed loop, which we should not // be able to topologically sort gr = SemanticGraph.ValueOf("[ate subj>Bill dobj>[muffins compound>blueberry]]"); vertices = gr.VertexListSorted(); gr.AddEdge(vertices[3], vertices[0], UniversalEnglishGrammaticalRelations.DirectObject, 1.0, false); try { VerifyTopologicalSort(gr); throw new Exception("Expected to fail"); } catch (InvalidOperationException) { } }
/// <summary>Parse a JSON formatted tree into a SemanticGraph.</summary> /// <param name="jsonString"> /// The JSON string tree to parse, e.g: /// "[{\"\"dependent\"\": 7, \"\"dep\"\": \"\"root\"\", \"\"governorgloss\"\": \"\"root\"\", \"\"governor\"\": 0, \"\"dependentgloss\"\": \"\"sport\"\"}, {\"\"dependent\"\": 1, \"\"dep\"\": \"\"nsubj\"\", \"\"governorgloss\"\": \"\"sport\"\", \"\"governor\"\": 7, \"\"dependentgloss\"\": \"\"chess\"\"}, {\"\"dependent\"\": 2, \"\"dep\"\": \"\"cop\"\", \"\"governorgloss\"\": \"\"sport\"\", \"\"governor\"\": 7, \"\"dependentgloss\"\": \"\"is\"\"}, {\"\"dependent\"\": 3, \"\"dep\"\": \"\"neg\"\", \"\"governorgloss\"\": \"\"sport\"\", \"\"governor\"\": 7, \"\"dependentgloss\"\": \"\"not\"\"}, {\"\"dependent\"\": 4, \"\"dep\"\": \"\"det\"\", \"\"governorgloss\"\": \"\"sport\"\", \"\"governor\"\": 7, \"\"dependentgloss\"\": \"\"a\"\"}, {\"\"dependent\"\": 5, \"\"dep\"\": \"\"advmod\"\", \"\"governorgloss\"\": \"\"physical\"\", \"\"governor\"\": 6, \"\"dependentgloss\"\": \"\"predominantly\"\"}, {\"\"dependent\"\": 6, \"\"dep\"\": \"\"amod\"\", \"\"governorgloss\"\": \"\"sport\"\", \"\"governor\"\": 7, \"\"dependentgloss\"\": \"\"physical\"\"}, {\"\"dependent\"\": 9, \"\"dep\"\": \"\"advmod\"\", \"\"governorgloss\"\": \"\"sport\"\", \"\"governor\"\": 7, \"\"dependentgloss\"\": \"\"yet\"\"}, {\"\"dependent\"\": 10, \"\"dep\"\": \"\"nsubj\"\", \"\"governorgloss\"\": \"\"shooting\"\", \"\"governor\"\": 12, \"\"dependentgloss\"\": \"\"neither\"\"}, {\"\"dependent\"\": 11, \"\"dep\"\": \"\"cop\"\", \"\"governorgloss\"\": \"\"shooting\"\", \"\"governor\"\": 12, \"\"dependentgloss\"\": \"\"are\"\"}, {\"\"dependent\"\": 12, \"\"dep\"\": \"\"parataxis\"\", \"\"governorgloss\"\": \"\"sport\"\", \"\"governor\"\": 7, \"\"dependentgloss\"\": \"\"shooting\"\"}, {\"\"dependent\"\": 13, \"\"dep\"\": \"\"cc\"\", \"\"governorgloss\"\": \"\"shooting\"\", \"\"governor\"\": 12, \"\"dependentgloss\"\": \"\"and\"\"}, {\"\"dependent\"\": 14, \"\"dep\"\": \"\"parataxis\"\", \"\"governorgloss\"\": \"\"sport\"\", \"\"governor\"\": 7, \"\"dependentgloss\"\": \"\"curling\"\"}, {\"\"dependent\"\": 14, \"\"dep\"\": \"\"conj:and\"\", \"\"governorgloss\"\": \"\"shooting\"\", \"\"governor\"\": 12, \"\"dependentgloss\"\": \"\"curling\"\"}, {\"\"dependent\"\": 16, \"\"dep\"\": \"\"nsubjpass\"\", \"\"governorgloss\"\": \"\"nicknamed\"\", \"\"governor\"\": 23, \"\"dependentgloss\"\": \"\"which\"\"}, {\"\"dependent\"\": 18, \"\"dep\"\": \"\"case\"\", \"\"governorgloss\"\": \"\"fact\"\", \"\"governor\"\": 19, \"\"dependentgloss\"\": \"\"in\"\"}, {\"\"dependent\"\": 19, \"\"dep\"\": \"\"nmod:in\"\", \"\"governorgloss\"\": \"\"nicknamed\"\", \"\"governor\"\": 23, \"\"dependentgloss\"\": \"\"fact\"\"}, {\"\"dependent\"\": 21, \"\"dep\"\": \"\"aux\"\", \"\"governorgloss\"\": \"\"nicknamed\"\", \"\"governor\"\": 23, \"\"dependentgloss\"\": \"\"has\"\"}, {\"\"dependent\"\": 22, \"\"dep\"\": \"\"auxpass\"\", \"\"governorgloss\"\": \"\"nicknamed\"\", \"\"governor\"\": 23, \"\"dependentgloss\"\": \"\"been\"\"}, {\"\"dependent\"\": 23, \"\"dep\"\": \"\"dep\"\", \"\"governorgloss\"\": \"\"shooting\"\", \"\"governor\"\": 12, \"\"dependentgloss\"\": \"\"nicknamed\"\"}, {\"\"dependent\"\": 25, \"\"dep\"\": \"\"dobj\"\", \"\"governorgloss\"\": \"\"nicknamed\"\", \"\"governor\"\": 23, \"\"dependentgloss\"\": \"\"chess\"\"}, {\"\"dependent\"\": 26, \"\"dep\"\": \"\"case\"\", \"\"governorgloss\"\": \"\"ice\"\", \"\"governor\"\": 27, \"\"dependentgloss\"\": \"\"on\"\"}, {\"\"dependent\"\": 27, \"\"dep\"\": \"\"nmod:on\"\", \"\"governorgloss\"\": \"\"chess\"\", \"\"governor\"\": 25, \"\"dependentgloss\"\": \"\"ice\"\"}, {\"\"dependent\"\": 29, \"\"dep\"\": \"\"amod\"\", \"\"governorgloss\"\": \"\"chess\"\", \"\"governor\"\": 25, \"\"dependentgloss\"\": \"\"5\"\"}]"); /// </param> /// <param name="tokens">The tokens of the sentence, to form the backing labels of the tree.</param> /// <returns>A semantic graph of the sentence, according to the given tree.</returns> public static SemanticGraph ParseJsonTree(string jsonString, IList <CoreLabel> tokens) { // Escape quoted string parts IJsonReader json = Javax.Json.Json.CreateReader(new StringReader(jsonString)); SemanticGraph tree = new SemanticGraph(); IJsonArray array = json.ReadArray(); if (array == null || array.IsEmpty()) { return(tree); } IndexedWord[] vertices = new IndexedWord[tokens.Count + 2]; // Add edges for (int i = 0; i < array.Count; i++) { IJsonObject entry = array.GetJsonObject(i); // Parse row int dependentIndex = entry.GetInt("dependent"); if (vertices[dependentIndex] == null) { if (dependentIndex > tokens.Count) { // Bizarre mismatch in sizes; the malt parser seems to do this often return(new SemanticGraph()); } vertices[dependentIndex] = new IndexedWord(tokens[dependentIndex - 1]); } IndexedWord dependent = vertices[dependentIndex]; int governorIndex = entry.GetInt("governor"); if (governorIndex > tokens.Count) { // Bizarre mismatch in sizes; the malt parser seems to do this often return(new SemanticGraph()); } if (vertices[governorIndex] == null && governorIndex > 0) { vertices[governorIndex] = new IndexedWord(tokens[governorIndex - 1]); } IndexedWord governor = vertices[governorIndex]; string relation = entry.GetString("dep"); // Process row if (governorIndex == 0) { tree.AddRoot(dependent); } else { tree.AddVertex(dependent); if (!tree.ContainsVertex(governor)) { tree.AddVertex(governor); } if (!"ref".Equals(relation)) { tree.AddEdge(governor, dependent, GrammaticalRelation.ValueOf(Language.English, relation), double.NegativeInfinity, false); } } } return(tree); }
/// <summary>Create a copy of the passed parse tree, canonicalizing pronominal nodes with their canonical mention.</summary> /// <remarks> /// Create a copy of the passed parse tree, canonicalizing pronominal nodes with their canonical mention. /// Canonical mentions are tied together with the <i>compound</i> dependency arc; otherwise, the structure of /// the tree remains unchanged. /// </remarks> /// <param name="parse">The original dependency parse of the sentence.</param> /// <param name="canonicalMentionMap">The map from tokens to their canonical mentions.</param> /// <returns>A <b>copy</b> of the passed parse tree, with pronouns replaces with their canonical mention.</returns> private static SemanticGraph CanonicalizeCoref(SemanticGraph parse, IDictionary <CoreLabel, IList <CoreLabel> > canonicalMentionMap) { parse = new SemanticGraph(parse); foreach (IndexedWord node in new HashSet <IndexedWord>(parse.VertexSet())) { // copy the vertex set to prevent ConcurrentModificationExceptions if (node.Tag() != null && node.Tag().StartsWith("PRP")) { IList <CoreLabel> canonicalMention = canonicalMentionMap[node.BackingLabel()]; if (canonicalMention != null) { // Case: this node is a preposition with a valid antecedent. // 1. Save the attaching edges IList <SemanticGraphEdge> incomingEdges = parse.IncomingEdgeList(node); IList <SemanticGraphEdge> outgoingEdges = parse.OutgoingEdgeList(node); // 2. Remove the node parse.RemoveVertex(node); // 3. Add the new head word IndexedWord headWord = new IndexedWord(canonicalMention[canonicalMention.Count - 1]); headWord.SetPseudoPosition(node.PseudoPosition()); parse.AddVertex(headWord); foreach (SemanticGraphEdge edge in incomingEdges) { parse.AddEdge(edge.GetGovernor(), headWord, edge.GetRelation(), edge.GetWeight(), edge.IsExtra()); } foreach (SemanticGraphEdge edge_1 in outgoingEdges) { parse.AddEdge(headWord, edge_1.GetDependent(), edge_1.GetRelation(), edge_1.GetWeight(), edge_1.IsExtra()); } // 4. Add other words double pseudoPosition = headWord.PseudoPosition() - 1e-3; for (int i = canonicalMention.Count - 2; i >= 0; --i) { // Create the node IndexedWord dependent = new IndexedWord(canonicalMention[i]); // Set its pseudo position appropriately dependent.SetPseudoPosition(pseudoPosition); pseudoPosition -= 1e-3; // Add the node to the graph parse.AddVertex(dependent); parse.AddEdge(headWord, dependent, UniversalEnglishGrammaticalRelations.CompoundModifier, 1.0, false); } } } } return(parse); }
/// <summary>Parse a CoNLL formatted tree into a SemanticGraph.</summary> /// <param name="conll">The CoNLL tree to parse.</param> /// <param name="tokens">The tokens of the sentence, to form the backing labels of the tree.</param> /// <returns>A semantic graph of the sentence, according to the given tree.</returns> public static SemanticGraph ParseTree(string conll, IList <CoreLabel> tokens) { SemanticGraph tree = new SemanticGraph(); if (conll == null || conll.IsEmpty()) { return(tree); } string[] treeLines = newline.Split(conll); IndexedWord[] vertices = new IndexedWord[tokens.Count + 2]; // Add edges foreach (string line in treeLines) { // Parse row string[] fields = tab.Split(line); int dependentIndex = System.Convert.ToInt32(fields[0]); if (vertices[dependentIndex] == null) { if (dependentIndex > tokens.Count) { // Bizarre mismatch in sizes; the malt parser seems to do this often return(new SemanticGraph()); } vertices[dependentIndex] = new IndexedWord(tokens[dependentIndex - 1]); } IndexedWord dependent = vertices[dependentIndex]; int governorIndex = System.Convert.ToInt32(fields[1]); if (governorIndex > tokens.Count) { // Bizarre mismatch in sizes; the malt parser seems to do this often return(new SemanticGraph()); } if (vertices[governorIndex] == null && governorIndex > 0) { vertices[governorIndex] = new IndexedWord(tokens[governorIndex - 1]); } IndexedWord governor = vertices[governorIndex]; string relation = fields[2]; // Process row if (governorIndex == 0) { tree.AddRoot(dependent); } else { tree.AddVertex(dependent); if (!tree.ContainsVertex(governor)) { tree.AddVertex(governor); } if (!"ref".Equals(relation)) { tree.AddEdge(governor, dependent, GrammaticalRelation.ValueOf(Language.English, relation), double.NegativeInfinity, false); } } } return(tree); }
/// <summary>Parse a CoNLL formatted tree into a SemanticGraph object (along with a list of tokens).</summary> /// <param name="conll">The CoNLL formatted tree.</param> /// <returns> /// A pair of a SemanticGraph and a token list, corresponding to the parse of the sentence /// and to tokens in the sentence. /// </returns> protected internal virtual Pair <SemanticGraph, IList <CoreLabel> > MkTree(string conll) { IList <CoreLabel> sentence = new List <CoreLabel>(); SemanticGraph tree = new SemanticGraph(); foreach (string line in conll.Split("\n")) { if (line.Trim().Equals(string.Empty)) { continue; } string[] fields = line.Trim().Split("\\s+"); int index = System.Convert.ToInt32(fields[0]); string word = fields[1]; CoreLabel label = IETestUtils.MkWord(word, index); sentence.Add(label); if (fields[2].Equals("0")) { tree.AddRoot(new IndexedWord(label)); } else { tree.AddVertex(new IndexedWord(label)); } if (fields.Length > 4) { label.SetTag(fields[4]); } if (fields.Length > 5) { label.SetNER(fields[5]); } if (fields.Length > 6) { label.SetLemma(fields[6]); } } int i = 0; foreach (string line_1 in conll.Split("\n")) { if (line_1.Trim().Equals(string.Empty)) { continue; } string[] fields = line_1.Trim().Split("\\s+"); int parent = System.Convert.ToInt32(fields[2]); string reln = fields[3]; if (parent > 0) { tree.AddEdge(new IndexedWord(sentence[parent - 1]), new IndexedWord(sentence[i]), new GrammaticalRelation(Language.UniversalEnglish, reln, null, null), 1.0, false); } i += 1; } return(Pair.MakePair(tree, sentence)); }
/// <summary>TODO: figure out how to specify where in the sentence this node goes.</summary> /// <remarks> /// TODO: figure out how to specify where in the sentence this node goes. /// TODO: determine if we should be copying an IndexedWord, or working just with a FeatureLabel. /// TODO: bombproof if this gov, dep, and reln already exist. /// </remarks> public override void Evaluate(SemanticGraph sg, SemgrexMatcher sm) { IndexedWord govNode = sm.GetNode(govNodeName); IndexedWord newNode = new IndexedWord(newNodePrototype); int newIndex = SemanticGraphUtils.LeftMostChildVertice(govNode, sg).Index(); // cheap En-specific hack for placing copula (beginning of governing phrase) newNode.SetDocID(govNode.DocID()); newNode.SetIndex(newIndex); newNode.SetSentIndex(govNode.SentIndex()); sg.AddVertex(newNode); sg.AddEdge(govNode, newNode, relation, weight, false); }
/// <summary>This creates a new graph based off the given, but uses the existing nodes objects.</summary> public static SemanticGraph DuplicateKeepNodes(SemanticGraph sg) { SemanticGraph retSg = new SemanticGraph(); foreach (IndexedWord node in sg.VertexSet()) { retSg.AddVertex(node); } retSg.SetRoots(sg.GetRoots()); foreach (SemanticGraphEdge edge in sg.EdgeIterable()) { retSg.AddEdge(edge.GetGovernor(), edge.GetDependent(), edge.GetRelation(), edge.GetWeight(), edge.IsExtra()); } return(retSg); }
/// <summary>Given a list of edges, attempts to create and return a rooted SemanticGraph.</summary> /// <remarks> /// Given a list of edges, attempts to create and return a rooted SemanticGraph. /// TODO: throw Exceptions, or flag warnings on conditions for concern (no root, etc) /// </remarks> public static SemanticGraph MakeFromEdges(IEnumerable <SemanticGraphEdge> edges) { // Identify the root(s) of this graph SemanticGraph sg = new SemanticGraph(); ICollection <IndexedWord> vertices = GetVerticesFromEdgeSet(edges); foreach (IndexedWord vertex in vertices) { sg.AddVertex(vertex); } foreach (SemanticGraphEdge edge in edges) { sg.AddEdge(edge.GetSource(), edge.GetTarget(), edge.GetRelation(), edge.GetWeight(), edge.IsExtra()); } sg.ResetRoots(); return(sg); }
/// <summary> /// Given a set of vertices, and the source graph they are drawn from, create a path composed /// of the minimum paths between the vertices. /// </summary> /// <remarks> /// Given a set of vertices, and the source graph they are drawn from, create a path composed /// of the minimum paths between the vertices. i.e. this is a simple brain-dead attempt at getting /// something approximating a minimum spanning graph. /// NOTE: the hope is the vertices will already be contiguous, but facilities are added just in case for /// adding additional nodes. /// </remarks> public static SemanticGraph MakeFromVertices(SemanticGraph sg, ICollection <IndexedWord> nodes) { IList <SemanticGraphEdge> edgesToAdd = new List <SemanticGraphEdge>(); IList <IndexedWord> nodesToAdd = new List <IndexedWord>(nodes); foreach (IndexedWord nodeA in nodes) { foreach (IndexedWord nodeB in nodes) { if (nodeA != nodeB) { IList <SemanticGraphEdge> edges = sg.GetShortestDirectedPathEdges(nodeA, nodeB); if (edges != null) { Sharpen.Collections.AddAll(edgesToAdd, edges); foreach (SemanticGraphEdge edge in edges) { IndexedWord gov = edge.GetGovernor(); IndexedWord dep = edge.GetDependent(); if (gov != null && !nodesToAdd.Contains(gov)) { nodesToAdd.Add(gov); } if (dep != null && !nodesToAdd.Contains(dep)) { nodesToAdd.Add(dep); } } } } } } SemanticGraph retSg = new SemanticGraph(); foreach (IndexedWord node in nodesToAdd) { retSg.AddVertex(node); } foreach (SemanticGraphEdge edge_1 in edgesToAdd) { retSg.AddEdge(edge_1.GetGovernor(), edge_1.GetDependent(), edge_1.GetRelation(), edge_1.GetWeight(), edge_1.IsExtra()); } retSg.ResetRoots(); return(retSg); }
public override void Evaluate(SemanticGraph sg, SemgrexMatcher sm) { IndexedWord rootNode = this.GetNamedNode(rootName, sm); ICollection <IndexedWord> subgraphNodeSet = sg.GetSubgraphVertices(rootNode); if (!sg.IsDag(rootNode)) { /* Check if there is a cycle going back to the root. */ foreach (IndexedWord child in sg.GetChildren(rootNode)) { ICollection <IndexedWord> reachableSet = sg.GetSubgraphVertices(child); if (reachableSet.Contains(rootNode)) { throw new ArgumentException("Subtree cannot contain cycle leading back to root node!"); } } } IList <IndexedWord> sortedSubgraphNodes = Generics.NewArrayList(subgraphNodeSet); sortedSubgraphNodes.Sort(); IndexedWord newNode = new IndexedWord(rootNode.DocID(), rootNode.SentIndex(), rootNode.Index()); /* Copy all attributes from rootNode. */ foreach (Type key in newNode.BackingLabel().KeySet()) { newNode.Set(key, rootNode.Get(key)); } newNode.SetValue(StringUtils.Join(sortedSubgraphNodes.Stream().Map(null), " ")); newNode.SetWord(StringUtils.Join(sortedSubgraphNodes.Stream().Map(null), " ")); newNode.SetLemma(StringUtils.Join(sortedSubgraphNodes.Stream().Map(null), " ")); if (sg.GetRoots().Contains(rootNode)) { sg.GetRoots().Remove(rootNode); sg.AddRoot(rootNode); } foreach (SemanticGraphEdge edge in sg.IncomingEdgeIterable(rootNode)) { sg.AddEdge(edge.GetGovernor(), newNode, edge.GetRelation(), edge.GetWeight(), edge.IsExtra()); } foreach (IndexedWord node in sortedSubgraphNodes) { sg.RemoveVertex(node); } }
/// <summary> /// Given a list of graphs, constructs a new graph combined from the /// collection of graphs. /// </summary> /// <remarks> /// 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. /// </remarks> public static SemanticGraph MakeFromGraphs(ICollection <SemanticGraph> sgList) { SemanticGraph sg = new SemanticGraph(); ICollection <IndexedWord> newRoots = Generics.NewHashSet(); foreach (SemanticGraph currSg in sgList) { Sharpen.Collections.AddAll(newRoots, currSg.GetRoots()); foreach (IndexedWord currVertex in currSg.VertexSet()) { sg.AddVertex(currVertex); } foreach (SemanticGraphEdge currEdge in currSg.EdgeIterable()) { sg.AddEdge(currEdge.GetGovernor(), currEdge.GetDependent(), currEdge.GetRelation(), currEdge.GetWeight(), currEdge.IsExtra()); } } sg.SetRoots(newRoots); return(sg); }
public override void Evaluate(SemanticGraph sg, SemgrexMatcher sm) { IndexedWord govNode = GetNamedNode(govName, sm); IndexedWord depNode = GetNamedNode(depName, sm); SemanticGraphEdge existingEdge = sg.GetEdge(govNode, depNode, relation); if (existingEdge == null) { // When adding the edge, check to see if the gov/dep nodes are presently in the graph. // if (!sg.ContainsVertex(govNode)) { sg.AddVertex(govNode); } if (!sg.ContainsVertex(depNode)) { sg.AddVertex(depNode); } sg.AddEdge(govNode, depNode, relation, weight, false); } }
/// <summary> /// Like makeFromGraphs, but it makes a deep copy of the graphs and /// renumbers the index words. /// </summary> /// <remarks> /// Like makeFromGraphs, but it makes a deep copy of the graphs and /// renumbers the index words. /// <br /> /// <paramref name="lengths"/> /// must be a vector containing the number of /// tokens in each sentence. This is used to reindex the tokens. /// </remarks> public static SemanticGraph DeepCopyFromGraphs(IList <SemanticGraph> graphs, IList <int> lengths) { SemanticGraph newGraph = new SemanticGraph(); IDictionary <int, IndexedWord> newWords = Generics.NewHashMap(); IList <IndexedWord> newRoots = new List <IndexedWord>(); int vertexOffset = 0; for (int i = 0; i < graphs.Count; ++i) { SemanticGraph graph = graphs[i]; foreach (IndexedWord vertex in graph.VertexSet()) { IndexedWord newVertex = new IndexedWord(vertex); newVertex.SetIndex(vertex.Index() + vertexOffset); newGraph.AddVertex(newVertex); newWords[newVertex.Index()] = newVertex; } foreach (SemanticGraphEdge edge in graph.EdgeIterable()) { IndexedWord gov = newWords[edge.GetGovernor().Index() + vertexOffset]; IndexedWord dep = newWords[edge.GetDependent().Index() + vertexOffset]; if (gov == null || dep == null) { throw new AssertionError("Counting problem (or broken edge)"); } newGraph.AddEdge(gov, dep, edge.GetRelation(), edge.GetWeight(), edge.IsExtra()); } foreach (IndexedWord root in graph.GetRoots()) { newRoots.Add(newWords[root.Index() + vertexOffset]); } vertexOffset += lengths[i]; } newGraph.SetRoots(newRoots); return(newGraph); }
// TODO: implement referencing regexes public static SemanticGraph MakeComplicatedGraph() { SemanticGraph graph = new SemanticGraph(); string[] words = new string[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J" }; IndexedWord[] nodes = new IndexedWord[words.Length]; for (int i = 0; i < words.Length; ++i) { IndexedWord word = new IndexedWord("test", 1, i + 1); word.SetWord(words[i]); word.SetValue(words[i]); nodes[i] = word; graph.AddVertex(word); } graph.SetRoot(nodes[0]); // this graph isn't supposed to make sense graph.AddEdge(nodes[0], nodes[1], EnglishGrammaticalRelations.Modifier, 1.0, false); graph.AddEdge(nodes[0], nodes[2], EnglishGrammaticalRelations.DirectObject, 1.0, false); graph.AddEdge(nodes[0], nodes[3], EnglishGrammaticalRelations.IndirectObject, 1.0, false); graph.AddEdge(nodes[1], nodes[4], EnglishGrammaticalRelations.Marker, 1.0, false); graph.AddEdge(nodes[2], nodes[4], EnglishGrammaticalRelations.Expletive, 1.0, false); graph.AddEdge(nodes[3], nodes[4], EnglishGrammaticalRelations.AdjectivalComplement, 1.0, false); graph.AddEdge(nodes[4], nodes[5], EnglishGrammaticalRelations.AdjectivalModifier, 1.0, false); graph.AddEdge(nodes[4], nodes[6], EnglishGrammaticalRelations.AdverbialModifier, 1.0, false); graph.AddEdge(nodes[4], nodes[8], EnglishGrammaticalRelations.Modifier, 1.0, false); graph.AddEdge(nodes[5], nodes[7], EnglishGrammaticalRelations.PossessionModifier, 1.0, false); graph.AddEdge(nodes[6], nodes[7], EnglishGrammaticalRelations.PossessiveModifier, 1.0, false); graph.AddEdge(nodes[7], nodes[8], EnglishGrammaticalRelations.Agent, 1.0, false); graph.AddEdge(nodes[8], nodes[9], EnglishGrammaticalRelations.Determiner, 1.0, false); return(graph); }
protected internal virtual ICollection <string> Clauses(string conll) { IList <CoreLabel> sentence = new List <CoreLabel>(); SemanticGraph tree = new SemanticGraph(); foreach (string line in conll.Split("\n")) { if (line.Trim().Equals(string.Empty)) { continue; } string[] fields = line.Trim().Split("\\s+"); int index = System.Convert.ToInt32(fields[0]); string word = fields[1]; CoreLabel label = MkWord(word, index); sentence.Add(label); if (fields[2].Equals("0")) { tree.AddRoot(new IndexedWord(label)); } else { tree.AddVertex(new IndexedWord(label)); } if (fields.Length > 4) { label.SetTag(fields[4]); } if (fields.Length > 5) { label.SetNER(fields[5]); } if (fields.Length > 6) { label.SetLemma(fields[6]); } } int i = 0; foreach (string line_1 in conll.Split("\n")) { if (line_1.Trim().Equals(string.Empty)) { continue; } string[] fields = line_1.Trim().Split("\\s+"); int parent = System.Convert.ToInt32(fields[2]); string reln = fields[3]; if (parent > 0) { tree.AddEdge(new IndexedWord(sentence[parent - 1]), new IndexedWord(sentence[i]), new GrammaticalRelation(Language.English, reln, null, null), 1.0, false); } i += 1; } // Run extractor ClauseSplitterSearchProblem problem = new ClauseSplitterSearchProblem(tree, true); ICollection <string> clauses = new HashSet <string>(); problem.Search(null, new LinearClassifier <ClauseSplitter.ClauseClassifierLabel, string>(new ClassicCounter <Pair <string, ClauseSplitter.ClauseClassifierLabel> >()), ClauseSplitterSearchProblem.HardSplits, null, 100000); return(clauses); }
/// <summary>The search algorithm, starting with a full sentence and iteratively shortening it to its entailed sentences.</summary> /// <returns>A list of search results, corresponding to shortenings of the sentence.</returns> private IList <ForwardEntailerSearchProblem.SearchResult> SearchImplementation() { // Pre-process the tree SemanticGraph parseTree = new SemanticGraph(this.parseTree); System.Diagnostics.Debug.Assert(Edu.Stanford.Nlp.Naturalli.Util.IsTree(parseTree)); // (remove common determiners) IList <string> determinerRemovals = new List <string>(); parseTree.GetLeafVertices().Stream().Filter(null).ForEach(null); // (cut conj_and nodes) ICollection <SemanticGraphEdge> andsToAdd = new HashSet <SemanticGraphEdge>(); foreach (IndexedWord vertex in parseTree.VertexSet()) { if (parseTree.InDegree(vertex) > 1) { SemanticGraphEdge conjAnd = null; foreach (SemanticGraphEdge edge in parseTree.IncomingEdgeIterable(vertex)) { if ("conj:and".Equals(edge.GetRelation().ToString())) { conjAnd = edge; } } if (conjAnd != null) { parseTree.RemoveEdge(conjAnd); System.Diagnostics.Debug.Assert(Edu.Stanford.Nlp.Naturalli.Util.IsTree(parseTree)); andsToAdd.Add(conjAnd); } } } // Clean the tree Edu.Stanford.Nlp.Naturalli.Util.CleanTree(parseTree); System.Diagnostics.Debug.Assert(Edu.Stanford.Nlp.Naturalli.Util.IsTree(parseTree)); // Find the subject / object split // This takes max O(n^2) time, expected O(n*log(n)) time. // Optimal is O(n), but I'm too lazy to implement it. BitSet isSubject = new BitSet(256); foreach (IndexedWord vertex_1 in parseTree.VertexSet()) { // Search up the tree for a subj node; if found, mark that vertex as a subject. IEnumerator <SemanticGraphEdge> incomingEdges = parseTree.IncomingEdgeIterator(vertex_1); SemanticGraphEdge edge = null; if (incomingEdges.MoveNext()) { edge = incomingEdges.Current; } int numIters = 0; while (edge != null) { if (edge.GetRelation().ToString().EndsWith("subj")) { System.Diagnostics.Debug.Assert(vertex_1.Index() > 0); isSubject.Set(vertex_1.Index() - 1); break; } incomingEdges = parseTree.IncomingEdgeIterator(edge.GetGovernor()); if (incomingEdges.MoveNext()) { edge = incomingEdges.Current; } else { edge = null; } numIters += 1; if (numIters > 100) { // log.error("tree has apparent depth > 100"); return(Java.Util.Collections.EmptyList); } } } // Outputs IList <ForwardEntailerSearchProblem.SearchResult> results = new List <ForwardEntailerSearchProblem.SearchResult>(); if (!determinerRemovals.IsEmpty()) { if (andsToAdd.IsEmpty()) { double score = Math.Pow(weights.DeletionProbability("det"), (double)determinerRemovals.Count); System.Diagnostics.Debug.Assert(!double.IsNaN(score)); System.Diagnostics.Debug.Assert(!double.IsInfinite(score)); results.Add(new ForwardEntailerSearchProblem.SearchResult(parseTree, determinerRemovals, score)); } else { SemanticGraph treeWithAnds = new SemanticGraph(parseTree); System.Diagnostics.Debug.Assert(Edu.Stanford.Nlp.Naturalli.Util.IsTree(treeWithAnds)); foreach (SemanticGraphEdge and in andsToAdd) { treeWithAnds.AddEdge(and.GetGovernor(), and.GetDependent(), and.GetRelation(), double.NegativeInfinity, false); } System.Diagnostics.Debug.Assert(Edu.Stanford.Nlp.Naturalli.Util.IsTree(treeWithAnds)); results.Add(new ForwardEntailerSearchProblem.SearchResult(treeWithAnds, determinerRemovals, Math.Pow(weights.DeletionProbability("det"), (double)determinerRemovals.Count))); } } // Initialize the search System.Diagnostics.Debug.Assert(Edu.Stanford.Nlp.Naturalli.Util.IsTree(parseTree)); IList <IndexedWord> topologicalVertices; try { topologicalVertices = parseTree.TopologicalSort(); } catch (InvalidOperationException) { // log.info("Could not topologically sort the vertices! Using left-to-right traversal."); topologicalVertices = parseTree.VertexListSorted(); } if (topologicalVertices.IsEmpty()) { return(results); } Stack <ForwardEntailerSearchProblem.SearchState> fringe = new Stack <ForwardEntailerSearchProblem.SearchState>(); fringe.Push(new ForwardEntailerSearchProblem.SearchState(new BitSet(256), 0, parseTree, null, null, 1.0)); // Start the search int numTicks = 0; while (!fringe.IsEmpty()) { // Overhead with popping a node. if (numTicks >= maxTicks) { return(results); } numTicks += 1; if (results.Count >= maxResults) { return(results); } ForwardEntailerSearchProblem.SearchState state = fringe.Pop(); System.Diagnostics.Debug.Assert(state.score > 0.0); IndexedWord currentWord = topologicalVertices[state.currentIndex]; // Push the case where we don't delete int nextIndex = state.currentIndex + 1; int numIters = 0; while (nextIndex < topologicalVertices.Count) { IndexedWord nextWord = topologicalVertices[nextIndex]; System.Diagnostics.Debug.Assert(nextWord.Index() > 0); if (!state.deletionMask.Get(nextWord.Index() - 1)) { fringe.Push(new ForwardEntailerSearchProblem.SearchState(state.deletionMask, nextIndex, state.tree, null, state, state.score)); break; } else { nextIndex += 1; } numIters += 1; if (numIters > 10000) { // log.error("logic error (apparent infinite loop); returning"); return(results); } } // Check if we can delete this subtree bool canDelete = !state.tree.GetFirstRoot().Equals(currentWord); foreach (SemanticGraphEdge edge in state.tree.IncomingEdgeIterable(currentWord)) { if ("CD".Equals(edge.GetGovernor().Tag())) { canDelete = false; } else { // Get token information CoreLabel token = edge.GetDependent().BackingLabel(); OperatorSpec @operator; NaturalLogicRelation lexicalRelation; Polarity tokenPolarity = token.Get(typeof(NaturalLogicAnnotations.PolarityAnnotation)); if (tokenPolarity == null) { tokenPolarity = Polarity.Default; } // Get the relation for this deletion if ((@operator = token.Get(typeof(NaturalLogicAnnotations.OperatorAnnotation))) != null) { lexicalRelation = @operator.instance.deleteRelation; } else { System.Diagnostics.Debug.Assert(edge.GetDependent().Index() > 0); lexicalRelation = NaturalLogicRelation.ForDependencyDeletion(edge.GetRelation().ToString(), isSubject.Get(edge.GetDependent().Index() - 1)); } NaturalLogicRelation projectedRelation = tokenPolarity.ProjectLexicalRelation(lexicalRelation); // Make sure this is a valid entailment if (!projectedRelation.ApplyToTruthValue(truthOfPremise).IsTrue()) { canDelete = false; } } } if (canDelete) { // Register the deletion Lazy <Pair <SemanticGraph, BitSet> > treeWithDeletionsAndNewMask = Lazy.Of(null); // Compute the score of the sentence double newScore = state.score; foreach (SemanticGraphEdge edge_1 in state.tree.IncomingEdgeIterable(currentWord)) { double multiplier = weights.DeletionProbability(edge_1, state.tree.OutgoingEdgeIterable(edge_1.GetGovernor())); System.Diagnostics.Debug.Assert(!double.IsNaN(multiplier)); System.Diagnostics.Debug.Assert(!double.IsInfinite(multiplier)); newScore *= multiplier; } // Register the result if (newScore > 0.0) { SemanticGraph resultTree = new SemanticGraph(treeWithDeletionsAndNewMask.Get().first); andsToAdd.Stream().Filter(null).ForEach(null); results.Add(new ForwardEntailerSearchProblem.SearchResult(resultTree, AggregateDeletedEdges(state, state.tree.IncomingEdgeIterable(currentWord), determinerRemovals), newScore)); // Push the state with this subtree deleted nextIndex = state.currentIndex + 1; numIters = 0; while (nextIndex < topologicalVertices.Count) { IndexedWord nextWord = topologicalVertices[nextIndex]; BitSet newMask = treeWithDeletionsAndNewMask.Get().second; SemanticGraph treeWithDeletions = treeWithDeletionsAndNewMask.Get().first; if (!newMask.Get(nextWord.Index() - 1)) { System.Diagnostics.Debug.Assert(treeWithDeletions.ContainsVertex(topologicalVertices[nextIndex])); fringe.Push(new ForwardEntailerSearchProblem.SearchState(newMask, nextIndex, treeWithDeletions, null, state, newScore)); break; } else { nextIndex += 1; } numIters += 1; if (numIters > 10000) { // log.error("logic error (apparent infinite loop); returning"); return(results); } } } } } // Return return(results); }
public virtual SemanticGraph ConvertIntermediateGraph(IList <CoreLabel> sentence) { SemanticGraph graph = new SemanticGraph(); // First construct the actual nodes; keep them indexed by their index and copy count. // Sentences such as "I went over the river and through the woods" have // two copies for "went" in the collapsed dependencies. TwoDimensionalMap <int, int, IndexedWord> nodeMap = TwoDimensionalMap.HashMap(); foreach (AnnotationSerializer.IntermediateNode @in in nodes) { CoreLabel token = sentence[@in.index - 1]; // index starts at 1! IndexedWord word; if (@in.copyAnnotation > 0) { // TODO: if we make a copy wrapper CoreLabel, use it here instead word = new IndexedWord(new CoreLabel(token)); word.SetCopyCount(@in.copyAnnotation); } else { word = new IndexedWord(token); } // for backwards compatibility - new annotations should have // these fields set, but annotations older than August 2014 might not if (word.DocID() == null && @in.docId != null) { word.SetDocID(@in.docId); } if (word.SentIndex() < 0 && @in.sentIndex >= 0) { word.SetSentIndex(@in.sentIndex); } if (word.Index() < 0 && @in.index >= 0) { word.SetIndex(@in.index); } nodeMap.Put(word.Index(), word.CopyCount(), word); graph.AddVertex(word); if (@in.isRoot) { graph.AddRoot(word); } } // add all edges to the actual graph foreach (AnnotationSerializer.IntermediateEdge ie in edges) { IndexedWord source = nodeMap.Get(ie.source, ie.sourceCopy); if (source == null) { throw new RuntimeIOException("Failed to find node " + ie.source + "-" + ie.sourceCopy); } IndexedWord target = nodeMap.Get(ie.target, ie.targetCopy); if (target == null) { throw new RuntimeIOException("Failed to find node " + ie.target + "-" + ie.targetCopy); } // assert(target != null); lock (Lock) { // this is not thread-safe: there are static fields in GrammaticalRelation GrammaticalRelation rel = GrammaticalRelation.ValueOf(ie.dep); graph.AddEdge(source, target, rel, 1.0, ie.isExtra); } } // compute root nodes if they weren't stored in the graph if (!graph.IsEmpty() && graph.GetRoots().Count == 0) { graph.ResetRoots(); } return(graph); }
/// <summary>Fix some bizarre peculiarities with certain trees.</summary> /// <remarks> /// Fix some bizarre peculiarities with certain trees. /// So far, these include: /// <ul> /// <li>Sometimes there's a node from a word to itself. This seems wrong.</li> /// </ul> /// </remarks> /// <param name="tree">The tree to clean (in place!).</param> /// <returns>A list of extra edges, which are valid but were removed.</returns> public static IList <SemanticGraphEdge> CleanTree(SemanticGraph tree) { // assert !isCyclic(tree); // Clean nodes IList <IndexedWord> toDelete = new List <IndexedWord>(); foreach (IndexedWord vertex in tree.VertexSet()) { // Clean punctuation if (vertex.Tag() == null) { continue; } char tag = vertex.BackingLabel().Tag()[0]; if (tag == '.' || tag == ',' || tag == '(' || tag == ')' || tag == ':') { if (!tree.OutgoingEdgeIterator(vertex).MoveNext()) { // This should really never happen, but it does. toDelete.Add(vertex); } } } toDelete.ForEach(null); // Clean edges IEnumerator <SemanticGraphEdge> iter = tree.EdgeIterable().GetEnumerator(); IList <Triple <IndexedWord, IndexedWord, SemanticGraphEdge> > toAdd = new List <Triple <IndexedWord, IndexedWord, SemanticGraphEdge> >(); toDelete.Clear(); while (iter.MoveNext()) { SemanticGraphEdge edge = iter.Current; if (edge.GetDependent().Index() == edge.GetGovernor().Index()) { // Clean up copy-edges if (edge.GetDependent().IsCopy(edge.GetGovernor())) { foreach (SemanticGraphEdge toCopy in tree.OutgoingEdgeIterable(edge.GetDependent())) { toAdd.Add(Triple.MakeTriple(edge.GetGovernor(), toCopy.GetDependent(), toCopy)); } toDelete.Add(edge.GetDependent()); } if (edge.GetGovernor().IsCopy(edge.GetDependent())) { foreach (SemanticGraphEdge toCopy in tree.OutgoingEdgeIterable(edge.GetGovernor())) { toAdd.Add(Triple.MakeTriple(edge.GetDependent(), toCopy.GetDependent(), toCopy)); } toDelete.Add(edge.GetGovernor()); } // Clean self-edges iter.Remove(); } else { if (edge.GetRelation().ToString().Equals("punct")) { // Clean punctuation (again) if (!tree.OutgoingEdgeIterator(edge.GetDependent()).MoveNext()) { // This should really never happen, but it does. iter.Remove(); } } } } // (add edges we wanted to add) toDelete.ForEach(null); foreach (Triple <IndexedWord, IndexedWord, SemanticGraphEdge> edge_1 in toAdd) { tree.AddEdge(edge_1.first, edge_1.second, edge_1.third.GetRelation(), edge_1.third.GetWeight(), edge_1.third.IsExtra()); } // Handle extra edges. // Two cases: // (1) the extra edge is a subj/obj edge and the main edge is a conj:.* // in this case, keep the extra // (2) otherwise, delete the extra IList <SemanticGraphEdge> extraEdges = new List <SemanticGraphEdge>(); foreach (SemanticGraphEdge edge_2 in tree.EdgeIterable()) { if (edge_2.IsExtra()) { IList <SemanticGraphEdge> incomingEdges = tree.IncomingEdgeList(edge_2.GetDependent()); SemanticGraphEdge toKeep = null; foreach (SemanticGraphEdge candidate in incomingEdges) { if (toKeep == null) { toKeep = candidate; } else { if (toKeep.GetRelation().ToString().StartsWith("conj") && candidate.GetRelation().ToString().Matches(".subj.*|.obj.*")) { toKeep = candidate; } else { if (!candidate.IsExtra() && !(candidate.GetRelation().ToString().StartsWith("conj") && toKeep.GetRelation().ToString().Matches(".subj.*|.obj.*"))) { toKeep = candidate; } } } } foreach (SemanticGraphEdge candidate_1 in incomingEdges) { if (candidate_1 != toKeep) { extraEdges.Add(candidate_1); } } } } extraEdges.ForEach(null); // Add apposition edges (simple coref) foreach (SemanticGraphEdge extraEdge in new List <SemanticGraphEdge>(extraEdges)) { // note[gabor] prevent concurrent modification exception foreach (SemanticGraphEdge candidateAppos in tree.IncomingEdgeIterable(extraEdge.GetDependent())) { if (candidateAppos.GetRelation().ToString().Equals("appos")) { extraEdges.Add(new SemanticGraphEdge(extraEdge.GetGovernor(), candidateAppos.GetGovernor(), extraEdge.GetRelation(), extraEdge.GetWeight(), extraEdge.IsExtra())); } } foreach (SemanticGraphEdge candidateAppos_1 in tree.OutgoingEdgeIterable(extraEdge.GetDependent())) { if (candidateAppos_1.GetRelation().ToString().Equals("appos")) { extraEdges.Add(new SemanticGraphEdge(extraEdge.GetGovernor(), candidateAppos_1.GetDependent(), extraEdge.GetRelation(), extraEdge.GetWeight(), extraEdge.IsExtra())); } } } // Brute force ensure tree // Remove incoming edges from roots IList <SemanticGraphEdge> rootIncomingEdges = new List <SemanticGraphEdge>(); foreach (IndexedWord root in tree.GetRoots()) { foreach (SemanticGraphEdge incomingEdge in tree.IncomingEdgeIterable(root)) { rootIncomingEdges.Add(incomingEdge); } } rootIncomingEdges.ForEach(null); // Loop until it becomes a tree. bool changed = true; while (changed) { // I just want trees to be trees; is that so much to ask!? changed = false; IList <IndexedWord> danglingNodes = new List <IndexedWord>(); IList <SemanticGraphEdge> invalidEdges = new List <SemanticGraphEdge>(); foreach (IndexedWord vertex_1 in tree.VertexSet()) { // Collect statistics IEnumerator <SemanticGraphEdge> incomingIter = tree.IncomingEdgeIterator(vertex_1); bool hasIncoming = incomingIter.MoveNext(); bool hasMultipleIncoming = false; if (hasIncoming) { incomingIter.Current; hasMultipleIncoming = incomingIter.MoveNext(); } // Register actions if (!hasIncoming && !tree.GetRoots().Contains(vertex_1)) { danglingNodes.Add(vertex_1); } else { if (hasMultipleIncoming) { foreach (SemanticGraphEdge edge in new IterableIterator <SemanticGraphEdge>(incomingIter)) { invalidEdges.Add(edge_2); } } } } // Perform actions foreach (IndexedWord vertex_2 in danglingNodes) { tree.RemoveVertex(vertex_2); changed = true; } foreach (SemanticGraphEdge edge_3 in invalidEdges) { tree.RemoveEdge(edge_3); changed = true; } } // Edge case: remove duplicate dobj to "that." // This is a common parse error. foreach (IndexedWord vertex_3 in tree.VertexSet()) { SemanticGraphEdge thatEdge = null; int dobjCount = 0; foreach (SemanticGraphEdge edge in tree.OutgoingEdgeIterable(vertex_3)) { if (Sharpen.Runtime.EqualsIgnoreCase("that", edge_2.GetDependent().Word())) { thatEdge = edge_2; } if ("dobj".Equals(edge_2.GetRelation().ToString())) { dobjCount += 1; } } if (dobjCount > 1 && thatEdge != null) { // Case: there are two dobj edges, one of which goes to the word "that" // Action: rewrite the dobj edge to "that" to be a "mark" edge. tree.RemoveEdge(thatEdge); tree.AddEdge(thatEdge.GetGovernor(), thatEdge.GetDependent(), GrammaticalRelation.ValueOf(thatEdge.GetRelation().GetLanguage(), "mark"), thatEdge.GetWeight(), thatEdge.IsExtra()); } } // Return System.Diagnostics.Debug.Assert(IsTree(tree)); return(extraEdges); }
/// <summary>Returns all of the entailed shortened clauses (as per natural logic) from the given clause.</summary> /// <remarks> /// Returns all of the entailed shortened clauses (as per natural logic) from the given clause. /// This runs the forward entailment component of the OpenIE system only. /// It is usually chained together with the clause splitting component: /// <see cref="ClausesInSentence(Edu.Stanford.Nlp.Util.ICoreMap)"/> /// . /// </remarks> /// <param name="clause">The premise clause, as a sentence fragment in itself.</param> /// <returns>A list of entailed clauses.</returns> public virtual IList <SentenceFragment> EntailmentsFromClause(SentenceFragment clause) { if (clause.parseTree.IsEmpty()) { return(Java.Util.Collections.EmptyList()); } else { // Get the forward entailments IList <SentenceFragment> list = new List <SentenceFragment>(); if (entailmentsPerSentence > 0) { Sharpen.Collections.AddAll(list, forwardEntailer.Apply(clause.parseTree, true).Search().Stream().Map(null).Collect(Collectors.ToList())); } list.Add(clause); // A special case for adjective entailments IList <SentenceFragment> adjFragments = new List <SentenceFragment>(); SemgrexMatcher matcher = adjectivePattern.Matcher(clause.parseTree); while (matcher.Find()) { // (get nodes) IndexedWord subj = matcher.GetNode("subj"); IndexedWord be = matcher.GetNode("be"); IndexedWord adj = matcher.GetNode("adj"); IndexedWord obj = matcher.GetNode("obj"); IndexedWord pobj = matcher.GetNode("pobj"); string prep = matcher.GetRelnString("prep"); // (if the adjective, or any earlier adjective, is privative, then all bets are off) foreach (SemanticGraphEdge edge in clause.parseTree.OutgoingEdgeIterable(obj)) { if ("amod".Equals(edge.GetRelation().ToString()) && edge.GetDependent().Index() <= adj.Index() && Edu.Stanford.Nlp.Naturalli.Util.PrivativeAdjectives.Contains(edge.GetDependent().Word().ToLower())) { goto OUTER_continue; } } // (create the core tree) SemanticGraph tree = new SemanticGraph(); tree.AddRoot(adj); tree.AddVertex(subj); tree.AddVertex(be); tree.AddEdge(adj, be, GrammaticalRelation.ValueOf(Language.English, "cop"), double.NegativeInfinity, false); tree.AddEdge(adj, subj, GrammaticalRelation.ValueOf(Language.English, "nsubj"), double.NegativeInfinity, false); // (add pp attachment, if it existed) if (pobj != null) { System.Diagnostics.Debug.Assert(prep != null); tree.AddEdge(adj, pobj, GrammaticalRelation.ValueOf(Language.English, prep), double.NegativeInfinity, false); } // (check for monotonicity) if (adj.Get(typeof(NaturalLogicAnnotations.PolarityAnnotation)).IsUpwards() && be.Get(typeof(NaturalLogicAnnotations.PolarityAnnotation)).IsUpwards()) { // (add tree) adjFragments.Add(new SentenceFragment(tree, clause.assumedTruth, false)); } OUTER_continue :; } OUTER_break :; Sharpen.Collections.AddAll(list, adjFragments); return(list); } }