    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    }