Skip to content

Commit 2ad41a6

Browse files
committed
Add a boolean which returns whether or not something was changed by a SsurgeonEdit evaluation. Add a bunch of notes to the operations, including some notes on whether or not they are used in RTE
1 parent 867ae59 commit 2ad41a6

File tree

11 files changed

+121
-45
lines changed

11 files changed

+121
-45
lines changed

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,11 @@ public String toEditString() {
8080
* TODO: figure out how to specify where in the sentence this node goes.
8181
* TODO: determine if we should be copying an IndexedWord, or working just with a FeatureLabel.
8282
* TODO: bombproof if this gov, dep, and reln already exist.
83+
* TODO: This is not used anywhere, even in the old RTE code, so we can redo it however we want.
84+
* Perhaps it could reorder the indices of the new nodes, for example
8385
*/
8486
@Override
85-
public void evaluate(SemanticGraph sg, SemgrexMatcher sm) {
87+
public boolean evaluate(SemanticGraph sg, SemgrexMatcher sm) {
8688
IndexedWord govNode = sm.getNode(govNodeName);
8789
IndexedWord newNode = new IndexedWord(newNodePrototype);
8890
int newIndex = SemanticGraphUtils.leftMostChildVertice(govNode, sg).index(); // cheap En-specific hack for placing copula (beginning of governing phrase)
@@ -91,6 +93,7 @@ public void evaluate(SemanticGraph sg, SemgrexMatcher sm) {
9193
newNode.setSentIndex(govNode.sentIndex());
9294
sg.addVertex(newNode);
9395
sg.addEdge(govNode, newNode, relation, weight,false);
96+
return true;
9497
}
9598

9699
public static final String WORD_KEY = "word";

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

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,21 +65,26 @@ public static AddEdge createEngAddEdge(String govName, String depName, String en
6565
return new AddEdge(govName, depName, reln, weight);
6666
}
6767

68-
68+
69+
/**
70+
* If the edge already exists in the graph,
71+
* a new edge is not added.
72+
*/
6973
@Override
70-
public void evaluate(SemanticGraph sg, SemgrexMatcher sm) {
74+
public boolean evaluate(SemanticGraph sg, SemgrexMatcher sm) {
7175
IndexedWord govNode = getNamedNode(govName, sm);
7276
IndexedWord depNode = getNamedNode(depName, sm);
7377
SemanticGraphEdge existingEdge = sg.getEdge(govNode, depNode, relation);
7478
if (existingEdge == null) {
7579
// When adding the edge, check to see if the gov/dep nodes are presently in the graph.
76-
//
7780
if (!sg.containsVertex(govNode))
7881
sg.addVertex(govNode);
7982
if (!sg.containsVertex(depNode))
8083
sg.addVertex(depNode);
8184
sg.addEdge(govNode, depNode, relation, weight,false );
85+
return true;
8286
}
87+
return false;
8388
}
8489

8590
}

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

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,23 @@ public static AddNode createAddNode(String nodeString, String nodeName) {
2020
return new AddNode(nodeString, nodeName);
2121
}
2222

23-
public static AddNode createAddNode(IndexedWord node, String nodeName) {
24-
String nodeString = AddDep.cheapWordToString(node);
25-
return new AddNode(nodeString, nodeName);
26-
}
23+
public static AddNode createAddNode(IndexedWord node, String nodeName) {
24+
String nodeString = AddDep.cheapWordToString(node);
25+
return new AddNode(nodeString, nodeName);
26+
}
2727

28+
// TODO: can this be bombproofed if the node is already added?
29+
// otherwise, we can insist the user make sure the
30+
// node doesn't already exist, similar to Tsurgeon
31+
// Alternatively we could just not export this one and
32+
// make AddDep a bit more configurable.
33+
// This one is actually used in its current form in RTE
2834
@Override
29-
public void evaluate(SemanticGraph sg, SemgrexMatcher sm) {
35+
public boolean evaluate(SemanticGraph sg, SemgrexMatcher sm) {
3036
IndexedWord newNode = AddDep.fromCheapString(nodeString);
3137
sg.addVertex(newNode);
3238
addNamedNode(newNode, nodeName);
39+
return true;
3340
}
3441

3542

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

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,18 @@ public CollapseSubtree(String rootNodeName) {
3838

3939
@SuppressWarnings({ "unchecked", "rawtypes" })
4040
@Override
41-
public void evaluate(SemanticGraph sg, SemgrexMatcher sm) {
42-
41+
public boolean evaluate(SemanticGraph sg, SemgrexMatcher sm) {
4342
IndexedWord rootNode = this.getNamedNode(rootName, sm);
4443
Set<IndexedWord> subgraphNodeSet = sg.getSubgraphVertices(rootNode);
44+
if (subgraphNodeSet.size() == 1) {
45+
// our work here is done
46+
return false;
47+
}
4548

46-
49+
// TODO: this doesn't do a full search for cycles. Is that relevant?
50+
// Why does this even matter? Perhaps the only thing we care about
51+
// is that the root of the whole graph isn't collapsed
52+
// unless it stays the root
4753
if ( ! sg.isDag(rootNode)) {
4854
/* Check if there is a cycle going back to the root. */
4955
for (IndexedWord child : sg.getChildren(rootNode)) {
@@ -80,6 +86,7 @@ public void evaluate(SemanticGraph sg, SemgrexMatcher sm) {
8086
sg.removeVertex(node);
8187
}
8288

89+
return true;
8390
}
8491

8592
@Override

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

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -64,18 +64,21 @@ protected static Set<IndexedWord> crawl(IndexedWord vertex, SemanticGraph sg) {
6464

6565

6666
@Override
67-
public void evaluate(SemanticGraph sg, SemgrexMatcher sm) {
67+
public boolean evaluate(SemanticGraph sg, SemgrexMatcher sm) {
6868
IndexedWord seedNode = getNamedNode(destroyNodeName, sm);
69-
// TODO: do not execute if seedNode if not in graph (or just error?)
70-
if (sg.containsVertex(seedNode)) {
71-
Set<IndexedWord> nodesToDestroy = crawl(seedNode, sg);
72-
for (IndexedWord node : nodesToDestroy) {
73-
sg.removeVertex(node);
74-
}
75-
// After destroy nodes, need to reset the roots, since it's possible a root node
76-
// was destroyed.
77-
sg.resetRoots();
69+
if (seedNode == null || !sg.containsVertex(seedNode)) {
70+
return false;
71+
}
72+
73+
Set<IndexedWord> nodesToDestroy = crawl(seedNode, sg);
74+
for (IndexedWord node : nodesToDestroy) {
75+
sg.removeVertex(node);
7876
}
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+
return true;
7982
}
8083

8184
}

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

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,21 @@ public KillAllIncomingEdges(String nodeName) {
2020
this.nodeName = nodeName;
2121
}
2222

23+
/**
24+
* If executed twice on the same node, the second time there
25+
* will be no further updates
26+
*/
2327
@Override
24-
public void evaluate(SemanticGraph sg, SemgrexMatcher sm) {
25-
IndexedWord tgtNode = getNamedNode(nodeName, sm);
26-
for (SemanticGraphEdge edge : sg.incomingEdgeIterable(tgtNode)) {
27-
sg.removeEdge(edge);
28-
}
28+
public boolean evaluate(SemanticGraph sg, SemgrexMatcher sm) {
29+
IndexedWord tgtNode = getNamedNode(nodeName, sm);
30+
if (tgtNode == null) {
31+
return false;
32+
}
33+
boolean success = false;
34+
for (SemanticGraphEdge edge : sg.incomingEdgeIterable(tgtNode)) {
35+
success = success || sg.removeEdge(edge);
36+
}
37+
return success;
2938
}
3039

3140
@Override

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

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,22 @@
1616
*/
1717
public class KillNonRootedNodes extends SsurgeonEdit {
1818
public static final String LABEL = "killNonRooted";
19-
19+
20+
/**
21+
* If executed twice on the same graph, the second time there
22+
* will be no further updates
23+
*/
2024
@Override
21-
public void evaluate(SemanticGraph sg, SemgrexMatcher sm) {
25+
public boolean evaluate(SemanticGraph sg, SemgrexMatcher sm) {
26+
boolean changed = false;
2227
List<IndexedWord> nodes = new ArrayList<>(sg.vertexSet());
2328
for (IndexedWord node : nodes) {
2429
List<IndexedWord> rootPath = sg.getPathToRoot(node);
2530
if (rootPath == null) {
26-
sg.removeVertex(node);
31+
changed = changed || sg.removeVertex(node);
2732
}
2833
}
34+
return changed;
2935
}
3036

3137
@Override

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

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,34 +42,51 @@ public String toEditString() {
4242

4343
public static final String WILDCARD_NODE = "**WILDNODE**";
4444

45+
/**
46+
* Remove all edges from gov to dep that match the relation name.
47+
*<br>
48+
* Either gov or dep can be **WILDNODE**, representing that all
49+
* edges to or from the other node of that type should be removed.
50+
*<br>
51+
* You cannot set both gov and dep to **WILDNODE**, though.
52+
*<br>
53+
* This will not update anything the second time executed on the
54+
* same graph.
55+
*/
4556
@Override
46-
public void evaluate(SemanticGraph sg, SemgrexMatcher sm) {
57+
public boolean evaluate(SemanticGraph sg, SemgrexMatcher sm) {
4758
boolean govWild = govName.equals(WILDCARD_NODE);
4859
boolean depWild = depName.equals(WILDCARD_NODE);
4960
IndexedWord govNode = getNamedNode(govName, sm);
50-
IndexedWord depNode =getNamedNode(depName, sm);
61+
IndexedWord depNode = getNamedNode(depName, sm);
62+
boolean success = false;
5163

5264
if (govNode != null && depNode != null) {
5365
SemanticGraphEdge edge = sg.getEdge(govNode, depNode, relation);
54-
if (edge != null) {
55-
@SuppressWarnings("unused")
56-
boolean successFlag = sg.removeEdge(edge);
66+
while (edge != null) {
67+
if (!sg.removeEdge(edge)) {
68+
throw new IllegalStateException("Found an edge and tried to delete it, but somehow this didn't work! " + edge);
69+
}
70+
edge = sg.getEdge(govNode, depNode, relation);
71+
success = true;
5772
}
5873
} else if (depNode != null && govWild) {
5974
// dep known, wildcard gov
6075
for (SemanticGraphEdge edge : sg.incomingEdgeIterable(depNode)) {
6176
if (edge.getRelation().equals(relation) && sg.containsEdge(edge) ) {
62-
sg.removeEdge(edge);
77+
success = success || sg.removeEdge(edge);
6378
}
6479
}
6580
} else if (govNode != null && depWild) {
6681
// gov known, wildcard dep
6782
for (SemanticGraphEdge edge : sg.outgoingEdgeIterable(govNode)) {
6883
if (edge.getRelation().equals(relation) && sg.containsEdge(edge) ) {
69-
sg.removeEdge(edge);
84+
success = success || sg.removeEdge(edge);
7085
}
7186
}
7287
}
88+
// will be true if at least one edge was removed
89+
return success;
7390
}
7491

7592

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

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,17 +45,27 @@ public String toEditString() {
4545
buf.write(depName);
4646
return buf.toString();
4747
}
48-
48+
49+
/**
50+
* Removes the named edge from the graph, if it exists.
51+
*<br>
52+
* TODO: it should not be necessary to have node names for this to work.
53+
* Any edge that gets matched by the edge matcher should just work
54+
* This operation is not used anywhere, even in RTE, so we should be
55+
* able to change its semantics to not include the node names
56+
*/
4957
@Override
50-
public void evaluate(SemanticGraph sg, SemgrexMatcher sm) {
58+
public boolean evaluate(SemanticGraph sg, SemgrexMatcher sm) {
5159
String relation = sm.getRelnString(edgeName);
5260
IndexedWord govNode = getNamedNode(govName, sm);
5361
IndexedWord depNode = getNamedNode(depName, sm);
5462
SemanticGraphEdge edge = sg.getEdge(govNode, depNode, GrammaticalRelation.valueOf(relation));
55-
63+
5664
if (edge != null) {
5765
sg.removeEdge(edge);
66+
return true;
5867
}
68+
return false;
5969
}
6070

6171
public String getDepName() {

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

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,20 @@ public class SetRoots extends SsurgeonEdit {
1818
public SetRoots(List<String> newRootNames) {
1919
this.newRootNames = newRootNames;
2020
}
21-
21+
22+
/**
23+
* If executed twice on the same graph, the second time there
24+
* will be no further updates
25+
*/
2226
@Override
23-
public void evaluate(SemanticGraph sg, SemgrexMatcher sm) {
24-
List<IndexedWord> newRoots = new ArrayList<>();
27+
public boolean evaluate(SemanticGraph sg, SemgrexMatcher sm) {
28+
Set<IndexedWord> newRoots = new LinkedHashSet<>();
2529
for (String name : newRootNames)
2630
newRoots.add(getNamedNode(name, sm));
27-
sg.setRoots(newRoots);
31+
if (newRoots.equals(sg.getRoots()))
32+
return false;
33+
sg.setRoots(newRoots);
34+
return true;
2835
}
2936

3037
@Override

0 commit comments

Comments
 (0)