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