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    }