001 package org.maltparser.parser.algorithm.planar;
002
003 import java.util.Stack;
004
005 import org.maltparser.core.exception.MaltChainedException;
006 import org.maltparser.core.symbol.SymbolTable;
007 import org.maltparser.core.symbol.SymbolTableHandler;
008 import org.maltparser.core.syntaxgraph.DependencyGraph;
009 import org.maltparser.core.syntaxgraph.DependencyStructure;
010 import org.maltparser.core.syntaxgraph.edge.Edge;
011 import org.maltparser.core.syntaxgraph.node.DependencyNode;
012 import org.maltparser.parser.ParserConfiguration;
013 import org.maltparser.parser.ParsingException;
014 /**
015 * @author Carlos Gomez Rodriguez
016 *
017 */
018 public class PlanarConfig extends ParserConfiguration {
019 // Root Handling
020 /*
021 public static final int STRICT = 1; //root tokens unattached, Reduce not permissible
022 public static final int RELAXED = 2; //root tokens unattached, Reduce permissible
023 public static final int NORMAL = 3; //root tokens attached to Root with RightArc
024 */
025
026 //Connectedness enforcing
027 public static final int NO_CONNECTEDNESS = 1;
028 public static final int REDUCE_ONLY = 2; //connectedness enforced on reduce only
029 public static final int FULL_CONNECTEDNESS = 3; //connectedness enforced on shift and reduce
030
031 //Constraints
032 public final boolean SINGLE_HEAD = true; //single-head constraint
033 public boolean noCoveredRoots = false; //no-covered-roots constraint
034 public boolean acyclicity = true; //acyclicity constraint
035 public int connectedness = NO_CONNECTEDNESS; //connectedness constraint
036
037
038 private Stack<DependencyNode> stack;
039 private Stack<DependencyNode> input;
040 private DependencyStructure dependencyGraph;
041 //private int rootHandling;
042
043
044 public PlanarConfig(SymbolTableHandler symbolTableHandler, String noCoveredRoots , String acyclicity , String connectedness) throws MaltChainedException {
045 super();
046 stack = new Stack<DependencyNode>();
047 input = new Stack<DependencyNode>();
048 dependencyGraph = new DependencyGraph(symbolTableHandler);
049 //setRootHandling(rootHandling);
050 setNoCoveredRoots(Boolean.valueOf(noCoveredRoots));
051 setAcyclicity(Boolean.valueOf(acyclicity));
052 setConnectedness(connectedness);
053 }
054
055 public Stack<DependencyNode> getStack() {
056 return stack;
057 }
058
059 public Stack<DependencyNode> getInput() {
060 return input;
061 }
062
063 public DependencyStructure getDependencyStructure() {
064 return dependencyGraph;
065 }
066
067 public boolean isTerminalState() {
068 return input.isEmpty();
069 }
070
071 public DependencyNode getStackNode(int index) throws MaltChainedException {
072 if (index < 0) {
073 throw new ParsingException("Stack index must be non-negative in feature specification. ");
074 }
075 if (stack.size()-index > 0) {
076 return stack.get(stack.size()-1-index);
077 }
078 return null;
079 }
080
081 public DependencyNode getInputNode(int index) throws MaltChainedException {
082 if (index < 0) {
083 throw new ParsingException("Input index must be non-negative in feature specification. ");
084 }
085 if (input.size()-index > 0) {
086 return input.get(input.size()-1-index);
087 }
088 return null;
089 }
090
091 public void setDependencyGraph(DependencyStructure source) throws MaltChainedException {
092 dependencyGraph.clear();
093 for (int index : source.getTokenIndices()) {
094 DependencyNode gnode = source.getTokenNode(index);
095 DependencyNode pnode = dependencyGraph.addTokenNode(gnode.getIndex());
096 for (SymbolTable table : gnode.getLabelTypes()) {
097 pnode.addLabel(table, gnode.getLabelSymbol(table));
098 }
099
100 if (gnode.hasHead()) {
101 Edge s = gnode.getHeadEdge();
102 Edge t = dependencyGraph.addDependencyEdge(s.getSource().getIndex(), s.getTarget().getIndex());
103
104 for (SymbolTable table : s.getLabelTypes()) {
105 t.addLabel(table, s.getLabelSymbol(table));
106 }
107 }
108 }
109 for (SymbolTable table : source.getDefaultRootEdgeLabels().keySet()) {
110 dependencyGraph.setDefaultRootEdgeLabel(table, source.getDefaultRootEdgeLabelSymbol(table));
111 }
112 }
113
114 public DependencyStructure getDependencyGraph() {
115 return dependencyGraph;
116 }
117
118 public void initialize(ParserConfiguration parserConfiguration) throws MaltChainedException {
119 if (parserConfiguration != null) {
120 PlanarConfig planarConfig = (PlanarConfig)parserConfiguration;
121 Stack<DependencyNode> sourceStack = planarConfig.getStack();
122 Stack<DependencyNode> sourceInput = planarConfig.getInput();
123 setDependencyGraph(planarConfig.getDependencyGraph());
124 for (int i = 0, n = sourceStack.size(); i < n; i++) {
125 stack.add(dependencyGraph.getDependencyNode(sourceStack.get(i).getIndex()));
126 }
127 for (int i = 0, n = sourceInput.size(); i < n; i++) {
128 input.add(dependencyGraph.getDependencyNode(sourceInput.get(i).getIndex()));
129 }
130 } else {
131 stack.push(dependencyGraph.getDependencyRoot());
132 for (int i = dependencyGraph.getHighestTokenIndex(); i > 0; i--) {
133 final DependencyNode node = dependencyGraph.getDependencyNode(i);
134 if (node != null && !node.hasHead()) {
135 input.push(node);
136 }
137 }
138 }
139 }
140
141 /*
142 public int getRootHandling() {
143 return rootHandling;
144 }
145 */
146
147 public boolean requiresSingleHead()
148 {
149 return SINGLE_HEAD;
150 }
151
152 public boolean requiresNoCoveredRoots()
153 {
154 return noCoveredRoots;
155 }
156
157 public boolean requiresAcyclicity()
158 {
159 return acyclicity;
160 }
161
162 public boolean requiresConnectednessCheckOnReduce()
163 {
164 return connectedness != NO_CONNECTEDNESS;
165 }
166
167 public boolean requiresConnectednessCheckOnShift()
168 {
169 return connectedness == FULL_CONNECTEDNESS;
170 }
171
172 public void setNoCoveredRoots ( boolean value ) {noCoveredRoots = value;}
173
174 public void setAcyclicity ( boolean value ) {acyclicity = value;}
175
176 protected void setConnectedness(String conn) throws MaltChainedException {
177 if (conn.equalsIgnoreCase("none")) {
178 connectedness = NO_CONNECTEDNESS;
179 } else if (conn.equalsIgnoreCase("reduceonly")) {
180 connectedness = REDUCE_ONLY;
181 } else if (conn.equalsIgnoreCase("full")) {
182 connectedness = FULL_CONNECTEDNESS;
183 } else {
184 throw new ParsingException("The connectedness constraint option '"+conn+"' is unknown");
185 }
186 }
187
188 /*
189 public void setRootHandling(int rootHandling) {
190 this.rootHandling = rootHandling;
191 }
192
193 protected void setRootHandling(String rh) throws MaltChainedException {
194 if (rh.equalsIgnoreCase("strict")) {
195 rootHandling = STRICT;
196 } else if (rh.equalsIgnoreCase("relaxed")) {
197 rootHandling = RELAXED;
198 } else if (rh.equalsIgnoreCase("normal")) {
199 rootHandling = NORMAL;
200 } else {
201 throw new ParsingException("The root handling '"+rh+"' is unknown");
202 }
203 }
204 */
205
206 public void clear() throws MaltChainedException {
207 dependencyGraph.clear();
208 stack.clear();
209 input.clear();
210 historyNode = null;
211 }
212
213 public boolean equals(Object obj) {
214 if (this == obj)
215 return true;
216 if (obj == null)
217 return false;
218 if (getClass() != obj.getClass())
219 return false;
220 PlanarConfig that = (PlanarConfig)obj;
221
222 if (stack.size() != that.getStack().size())
223 return false;
224 if (input.size() != that.getInput().size())
225 return false;
226 if (dependencyGraph.nEdges() != that.getDependencyGraph().nEdges())
227 return false;
228 for (int i = 0; i < stack.size(); i++) {
229 if (stack.get(i).getIndex() != that.getStack().get(i).getIndex()) {
230 return false;
231 }
232 }
233 for (int i = 0; i < input.size(); i++) {
234 if (input.get(i).getIndex() != that.getInput().get(i).getIndex()) {
235 return false;
236 }
237 }
238 return dependencyGraph.getEdges().equals(that.getDependencyGraph().getEdges());
239 }
240
241 public String toString() {
242 final StringBuilder sb = new StringBuilder();
243 sb.append(stack.size());
244 sb.append(", ");
245 sb.append(input.size());
246 sb.append(", ");
247 sb.append(dependencyGraph.nEdges());
248 return sb.toString();
249 }
250 }