Skip to content

Commit 7ad1d9c

Browse files
committed
Update the prune operation to only reset the roots if a root is deleted
Include a test of the basic operation using a semgrex which searches for unattached nodes Also check the operation of resetting the roots when a root is pruned
1 parent b606bec commit 7ad1d9c

File tree

2 files changed

+124
-4
lines changed

2 files changed

+124
-4
lines changed

src/edu/stanford/nlp/semgraph/semgrex/ssurgeon/DeleteGraphFromNode.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,18 @@ public boolean evaluate(SemanticGraph sg, SemgrexMatcher sm) {
7070
return false;
7171
}
7272

73+
boolean deletedRoot = false;
7374
Set<IndexedWord> nodesToDestroy = crawl(seedNode, sg);
7475
for (IndexedWord node : nodesToDestroy) {
76+
if (sg.isRoot(node)) {
77+
deletedRoot = true;
78+
}
7579
sg.removeVertex(node);
7680
}
77-
// After destroy nodes, need to reset the roots, since it's possible a root node
78-
// was destroyed.
79-
// TODO: better is to check first
80-
sg.resetRoots();
81+
// After destroy nodes, need to reset the roots if any roots were destroyed
82+
if (deletedRoot) {
83+
sg.resetRoots();
84+
}
8185
return true;
8286
}
8387

test/src/edu/stanford/nlp/semgraph/semgrex/ssurgeon/SsurgeonTest.java

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,122 @@ public void readXMLRemoveEdgeIterate() {
117117
assertEquals(newSg, expected);
118118
}
119119

120+
/**
121+
* Check that cutting a graph with two nodes into two pieces, then
122+
* pruning any disjoint pieces, results in a graph with just the root
123+
*/
124+
@Test
125+
public void readXMLPruneNodesIterate() {
126+
Ssurgeon inst = Ssurgeon.inst();
127+
128+
String cut = String.join(newline,
129+
"<ssurgeon-pattern-list>",
130+
" <ssurgeon-pattern>",
131+
" <uid>38</uid>",
132+
" <notes>Remove dep edges</notes>",
133+
" <semgrex>" + XMLUtils.escapeXML("{}=a1 > {}=a2") + "</semgrex>",
134+
" <edit-list>removeEdge -gov a1 -dep a2 -reln dep</edit-list>",
135+
" </ssurgeon-pattern>",
136+
"</ssurgeon-pattern-list>");
137+
List<SsurgeonPattern> patterns = inst.readFromString(cut);
138+
assertEquals(patterns.size(), 1);
139+
SsurgeonPattern ssurgeonCut = patterns.get(0);
140+
141+
String prune = String.join(newline,
142+
"<ssurgeon-pattern-list>",
143+
" <ssurgeon-pattern>",
144+
" <uid>38</uid>",
145+
" <notes>This semgrex detects disjoint nodes</notes>",
146+
" <semgrex>" + XMLUtils.escapeXML("{}=disjoint !== {$} !<< {$}") + "</semgrex>",
147+
" <edit-list>delete -node disjoint</edit-list>",
148+
" </ssurgeon-pattern>",
149+
"</ssurgeon-pattern-list>");
150+
patterns = inst.readFromString(prune);
151+
assertEquals(patterns.size(), 1);
152+
SsurgeonPattern ssurgeonPrune = patterns.get(0);
153+
154+
// Test a two node only version
155+
SemanticGraph sg = SemanticGraph.valueOf("[A dep> B]");
156+
SemanticGraph cutSG = ssurgeonCut.iterate(sg);
157+
assertEquals(cutSG.vertexSet().size(), 2);
158+
SemanticGraph pruneSG = ssurgeonPrune.iterate(cutSG);
159+
SemanticGraph expected = SemanticGraph.valueOf("[A]");
160+
assertEquals(pruneSG, expected);
161+
162+
// Test a chain cut at the start
163+
sg = SemanticGraph.valueOf("[A dep> [B obj> C]]");
164+
cutSG = ssurgeonCut.iterate(sg);
165+
assertEquals(cutSG.vertexSet().size(), 3);
166+
pruneSG = ssurgeonPrune.iterate(cutSG);
167+
assertEquals(pruneSG, expected);
168+
169+
// Test the chain cut at the bottom
170+
sg = SemanticGraph.valueOf("[A obj> [B dep> C]]");
171+
cutSG = ssurgeonCut.iterate(sg);
172+
assertEquals(cutSG.vertexSet().size(), 3);
173+
pruneSG = ssurgeonPrune.iterate(cutSG);
174+
assertEquals(pruneSG, SemanticGraph.valueOf("[A obj> B]"));
175+
176+
// Test a chain cut at the start
177+
// Only the root will be left at the end
178+
sg = SemanticGraph.valueOf("[A dep> B dep> C]");
179+
cutSG = ssurgeonCut.iterate(sg);
180+
assertEquals(cutSG.vertexSet().size(), 3);
181+
pruneSG = ssurgeonPrune.iterate(cutSG);
182+
assertEquals(pruneSG, expected);
183+
}
184+
185+
/**
186+
* Test that if the root is removed by a prune operation,
187+
* the roots on the graph are reset
188+
*/
189+
@Test
190+
public void readXMLPruneNodesResetRoots() {
191+
Ssurgeon inst = Ssurgeon.inst();
192+
193+
String cut = String.join(newline,
194+
"<ssurgeon-pattern-list>",
195+
" <ssurgeon-pattern>",
196+
" <uid>38</uid>",
197+
" <notes>Remove any dep edges from the graph</notes>",
198+
" <semgrex>" + XMLUtils.escapeXML("{}=a1 > {}=a2") + "</semgrex>",
199+
" <edit-list>removeEdge -gov a1 -dep a2 -reln dep</edit-list>",
200+
" </ssurgeon-pattern>",
201+
"</ssurgeon-pattern-list>");
202+
List<SsurgeonPattern> patterns = inst.readFromString(cut);
203+
assertEquals(patterns.size(), 1);
204+
SsurgeonPattern ssurgeonCut = patterns.get(0);
205+
206+
String prune = String.join(newline,
207+
"<ssurgeon-pattern-list>",
208+
" <ssurgeon-pattern>",
209+
" <uid>38</uid>",
210+
" <notes>This semgrex detects disjoint roots</notes>",
211+
" <semgrex>" + XMLUtils.escapeXML("{$}=root : {} !== {}=root !>> {}=root") + "</semgrex>",
212+
" <edit-list>delete -node root</edit-list>",
213+
" </ssurgeon-pattern>",
214+
"</ssurgeon-pattern-list>");
215+
patterns = inst.readFromString(prune);
216+
assertEquals(patterns.size(), 1);
217+
SsurgeonPattern ssurgeonPrune = patterns.get(0);
218+
219+
// Test a two node only version
220+
SemanticGraph sg = SemanticGraph.valueOf("[A dep> B]");
221+
SemanticGraph cutSG = ssurgeonCut.iterate(sg);
222+
assertEquals(2, cutSG.vertexSet().size());
223+
SemanticGraph pruneSG = ssurgeonPrune.iterate(cutSG);
224+
// note that for now, the prune operation doesn't renumber nodes in any way
225+
SemanticGraph expected = SemanticGraph.valueOf("[B-1]");
226+
assertEquals(expected, pruneSG);
227+
228+
// Test the chain cut at the bottom
229+
sg = SemanticGraph.valueOf("[A obj> [B dep> C]]");
230+
cutSG = ssurgeonCut.iterate(sg);
231+
assertEquals(cutSG.vertexSet().size(), 3);
232+
pruneSG = ssurgeonPrune.iterate(cutSG);
233+
assertEquals(SemanticGraph.valueOf("[C-2]"), pruneSG);
234+
}
235+
120236
/**
121237
* Simple test of an Ssurgeon edit script. This instances a simple semantic graph,
122238
* a semgrex pattern, and then the resulting actions over the named nodes in the

0 commit comments

Comments
 (0)