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 }