001 package org.maltparser.parser.algorithm.stack;
002
003 import java.util.ArrayList;
004 import java.util.Stack;
005
006 import org.maltparser.core.exception.MaltChainedException;
007 import org.maltparser.core.syntaxgraph.DependencyStructure;
008 import org.maltparser.core.syntaxgraph.node.DependencyNode;
009 import org.maltparser.parser.DependencyParserConfig;
010 import org.maltparser.parser.Oracle;
011 import org.maltparser.parser.ParserConfiguration;
012 import org.maltparser.parser.history.GuideUserHistory;
013 import org.maltparser.parser.history.action.GuideUserAction;
014 /**
015 * @author Johan Hall
016 *
017 */
018 public class SwapLazyOracle extends Oracle {
019 private ArrayList<Integer> swapArray;
020 private boolean swapArrayActive = false;
021
022 public SwapLazyOracle(DependencyParserConfig manager, GuideUserHistory history) throws MaltChainedException {
023 super(manager, history);
024 setGuideName("swaplazy");
025 swapArray = new ArrayList<Integer>();
026 }
027
028 public GuideUserAction predict(DependencyStructure gold, ParserConfiguration configuration) throws MaltChainedException {
029 StackConfig config = (StackConfig)configuration;
030 Stack<DependencyNode> stack = config.getStack();
031
032 if (!swapArrayActive) {
033 createSwapArray(gold);
034 swapArrayActive = true;
035 }
036 if (stack.size() < 2) {
037 return updateActionContainers(NonProjective.SHIFT, null);
038 } else {
039 DependencyNode left = stack.get(stack.size()-2);
040 DependencyNode right = stack.get(stack.size()-1);
041 int leftIndex = left.getIndex();
042 int rightIndex = right.getIndex();
043 if (swapArray.get(leftIndex) > swapArray.get(rightIndex) && necessarySwap(gold, config.getDependencyGraph(), right, config.getInput())) {
044 return updateActionContainers(NonProjective.SWAP, null);
045 } else if (!left.isRoot() && gold.getTokenNode(leftIndex).getHead().getIndex() == rightIndex
046 && nodeComplete(gold, config.getDependencyGraph(), leftIndex)) {
047 return updateActionContainers(NonProjective.LEFTARC, gold.getTokenNode(leftIndex).getHeadEdge().getLabelSet());
048 } else if (gold.getTokenNode(rightIndex).getHead().getIndex() == leftIndex
049 && nodeComplete(gold, config.getDependencyGraph(), rightIndex)) {
050 return updateActionContainers(NonProjective.RIGHTARC, gold.getTokenNode(rightIndex).getHeadEdge().getLabelSet());
051 } else {
052 return updateActionContainers(NonProjective.SHIFT, null);
053 }
054 }
055 }
056
057 private boolean nodeComplete(DependencyStructure gold, DependencyStructure parseDependencyGraph, int nodeIndex) {
058 if (gold.getTokenNode(nodeIndex).hasLeftDependent()) {
059 if (!parseDependencyGraph.getTokenNode(nodeIndex).hasLeftDependent()) {
060 return false;
061 } else if (gold.getTokenNode(nodeIndex).getLeftmostDependent().getIndex() != parseDependencyGraph.getTokenNode(nodeIndex).getLeftmostDependent().getIndex()) {
062 return false;
063 }
064 }
065 if (gold.getTokenNode(nodeIndex).hasRightDependent()) {
066 if (!parseDependencyGraph.getTokenNode(nodeIndex).hasRightDependent()) {
067 return false;
068 } else if (gold.getTokenNode(nodeIndex).getRightmostDependent().getIndex() != parseDependencyGraph.getTokenNode(nodeIndex).getRightmostDependent().getIndex()) {
069 return false;
070 }
071 }
072 return true;
073 }
074
075 private boolean necessarySwap(DependencyStructure gold, DependencyStructure parse, DependencyNode node, Stack<DependencyNode> input) throws MaltChainedException {
076 DependencyNode left = node;
077 int index = input.size() - 1;
078 if (index < 0) {
079 return true;
080 }
081 DependencyNode right = input.peek();
082
083 int rc = -1;
084 while (projectiveInterval(parse, left, right)) {
085 if (rc == right.getIndex()) {
086 return false;
087 }
088 if (gold.getDependencyNode(node.getIndex()).getHead().getIndex() == right.getIndex()) {
089 return !leftComplete(gold, node);
090 }
091 if (gold.getDependencyNode(right.getIndex()).getHead().getIndex() == node.getIndex()) {
092 if (gold.getDependencyNode(right.getIndex()).hasRightDependent()) {
093 rc = gold.getDependencyNode(right.getIndex()).getRightmostProperDescendantIndex();
094 }
095 else {
096 return false;
097 }
098 }
099 if (index > 0) {
100 left = right;
101 right = input.get(--index);
102 } else {
103 break;
104 }
105 }
106
107 return true;
108 }
109
110 private boolean projectiveInterval(DependencyStructure parse, DependencyNode left, DependencyNode right) throws MaltChainedException {
111 int l = swapArray.get(left.getIndex());
112 int r = swapArray.get(right.getIndex());
113 DependencyNode node = null;
114 if (l > r) {
115 return false;
116 } else {
117 for (int i = l + 1; i < r; i++) {
118 for (int j = 0; j < swapArray.size(); j++) {
119 if (swapArray.get(j) == i) {
120 node = parse.getDependencyNode(j);
121 break;
122 }
123 }
124 while (node.hasHead()) {
125 node = node.getHead();
126 }
127 if (!(node == left || node == right)) {
128 return false;
129 }
130 }
131 return true;
132 }
133 }
134
135 private boolean leftComplete(DependencyStructure gold, DependencyNode right) throws MaltChainedException {
136 if (!gold.getDependencyNode(right.getIndex()).hasLeftDependent()) {
137 return true;
138 } else if (!right.hasLeftDependent()) {
139 return false;
140 } else if (gold.getDependencyNode(right.getIndex()).getLeftmostDependent().getIndex() == right.getLeftmostDependent().getIndex()) {
141 return true;
142 }
143 return false;
144 }
145
146 public void finalizeSentence(DependencyStructure dependencyGraph) throws MaltChainedException {
147 swapArrayActive = false;
148 }
149
150 public void terminate() throws MaltChainedException {
151
152 }
153
154 private void createSwapArray(DependencyStructure goldDependencyGraph) throws MaltChainedException {
155 swapArray.clear();
156 for (int i = 0; i <= goldDependencyGraph.getHighestDependencyNodeIndex(); i++) {
157 swapArray.add(new Integer(i));
158 }
159 createSwapArray(goldDependencyGraph.getDependencyRoot(), 0);
160 }
161
162 private int createSwapArray(DependencyNode n, int order) {
163 int o = order;
164 if (n != null) {
165 for (int i=0; i < n.getLeftDependentCount(); i++) {
166 o = createSwapArray(n.getLeftDependent(i), o);
167 }
168 swapArray.set(n.getIndex(), o++);
169 for (int i=n.getRightDependentCount(); i >= 0; i--) {
170 o = createSwapArray(n.getRightDependent(i), o);
171 }
172 }
173 return o;
174 }
175 }