    001    package org.maltparser.parser.algorithm.stack;
    002
    003    import java.util.ArrayList;
    004    import java.util.Stack;
    005
    006    import org.maltparser.core.exception.MaltChainedException;
    007    import org.maltparser.core.syntaxgraph.DependencyStructure;
    008    import org.maltparser.core.syntaxgraph.node.DependencyNode;
    009    import org.maltparser.parser.DependencyParserConfig;
    010    import org.maltparser.parser.Oracle;
    011    import org.maltparser.parser.ParserConfiguration;
    012    import org.maltparser.parser.history.GuideUserHistory;
    013    import org.maltparser.parser.history.action.GuideUserAction;
    014    /**
    015     * @author Johan Hall
    016     *
    017     */
    018    public class SwapLazyOracle extends Oracle {
    019            private ArrayList<Integer> swapArray;
    020            private boolean swapArrayActive = false;
    021
    022            public SwapLazyOracle(DependencyParserConfig manager, GuideUserHistory history) throws MaltChainedException {
    023                    super(manager, history);
    024                    setGuideName("swaplazy");
    025                    swapArray = new ArrayList<Integer>();
    026            }
    027
    028            public GuideUserAction predict(DependencyStructure gold, ParserConfiguration configuration) throws MaltChainedException {
    029                    StackConfig config = (StackConfig)configuration;
    030                    Stack<DependencyNode> stack = config.getStack();
    031
    032                    if (!swapArrayActive) {
    033                            createSwapArray(gold);
    034                            swapArrayActive = true;
    035                    }
    036                    if (stack.size() < 2) {
    037                            return updateActionContainers(NonProjective.SHIFT, null);
    038                    } else {
    039                            DependencyNode left = stack.get(stack.size()-2);
    040                            DependencyNode right = stack.get(stack.size()-1);
    041                            int leftIndex = left.getIndex();
    042                            int rightIndex = right.getIndex();
    043                            if (swapArray.get(leftIndex) > swapArray.get(rightIndex) && necessarySwap(gold, config.getDependencyGraph(), right, config.getInput())) {
    044                                    return updateActionContainers(NonProjective.SWAP, null);
    045                            } else if (!left.isRoot() && gold.getTokenNode(leftIndex).getHead().getIndex() == rightIndex
    046                                            && nodeComplete(gold, config.getDependencyGraph(), leftIndex)) {
    047                                    return updateActionContainers(NonProjective.LEFTARC, gold.getTokenNode(leftIndex).getHeadEdge().getLabelSet());
    048                            } else if (gold.getTokenNode(rightIndex).getHead().getIndex() == leftIndex
    049                                            && nodeComplete(gold, config.getDependencyGraph(), rightIndex)) {
    050                                    return updateActionContainers(NonProjective.RIGHTARC, gold.getTokenNode(rightIndex).getHeadEdge().getLabelSet());
    051                            } else {
    052                                    return updateActionContainers(NonProjective.SHIFT, null);
    053                            }
    054                    }
    055            }
    056
    057            private boolean nodeComplete(DependencyStructure gold, DependencyStructure parseDependencyGraph, int nodeIndex) {
    058                    if (gold.getTokenNode(nodeIndex).hasLeftDependent()) {
    059                            if (!parseDependencyGraph.getTokenNode(nodeIndex).hasLeftDependent()) {
    060                                    return false;
    061                            } else if (gold.getTokenNode(nodeIndex).getLeftmostDependent().getIndex() != parseDependencyGraph.getTokenNode(nodeIndex).getLeftmostDependent().getIndex()) {
    062                                    return false;
    063                            }
    064                    }
    065                    if (gold.getTokenNode(nodeIndex).hasRightDependent()) {
    066                            if (!parseDependencyGraph.getTokenNode(nodeIndex).hasRightDependent()) {
    067                                    return false;
    068                            } else if (gold.getTokenNode(nodeIndex).getRightmostDependent().getIndex() != parseDependencyGraph.getTokenNode(nodeIndex).getRightmostDependent().getIndex()) {
    069                                    return false;
    070                            }
    071                    }
    072                    return true;
    073            }
    074
    075            private boolean necessarySwap(DependencyStructure gold, DependencyStructure parse, DependencyNode node, Stack<DependencyNode> input) throws MaltChainedException {
    076                    DependencyNode left = node;
    077                    int index = input.size() - 1;
    078                    if (index < 0) {
    079                            return true;
    080                    }
    081                    DependencyNode right = input.peek();
    082
    083                    int rc = -1;
    084                    while (projectiveInterval(parse, left, right)) {
    085                            if (rc == right.getIndex()) {
    086                                    return false;
    087                            }
    088                            if (gold.getDependencyNode(node.getIndex()).getHead().getIndex() == right.getIndex()) {
    089                                    return !leftComplete(gold, node);
    090                            }
    091                            if (gold.getDependencyNode(right.getIndex()).getHead().getIndex() == node.getIndex()) {
    092                                    if (gold.getDependencyNode(right.getIndex()).hasRightDependent()) {
    093                                              rc = gold.getDependencyNode(right.getIndex()).getRightmostProperDescendantIndex();
    094                                    }
    095                                    else {
    096                                      return false;
    097                                    }
    098                            }
    099                            if (index > 0) {
    100                                    left = right;
    101                                    right = input.get(--index);
    102                            } else {
    103                                    break;
    104                            }
    105                    }
    106
    107                    return true;
    108            }
    109
    110            private boolean projectiveInterval(DependencyStructure parse, DependencyNode left, DependencyNode right) throws MaltChainedException {
    111                    int l = swapArray.get(left.getIndex());
    112                    int r = swapArray.get(right.getIndex());
    113                    DependencyNode node = null;
    114                    if (l > r) {
    115                            return false;
    116                    } else {
    117                            for (int i = l + 1; i < r; i++) {
    118                                    for (int j = 0; j < swapArray.size(); j++) {
    119                                            if (swapArray.get(j) == i) {
    120                                                    node = parse.getDependencyNode(j);
    121                                                    break;
    122                                            }
    123                                    }
    124                                    while (node.hasHead()) {
    125                                            node = node.getHead();
    126                                    }
    127                                    if (!(node == left || node == right)) {
    128                                            return false;
    129                                    }
    130                            }
    131                            return true;
    132                    }
    133            }
    134
    135            private boolean leftComplete(DependencyStructure gold, DependencyNode right) throws MaltChainedException {
    136                    if (!gold.getDependencyNode(right.getIndex()).hasLeftDependent()) {
    137                            return true;
    138                    } else if (!right.hasLeftDependent()) {
    139                            return false;
    140                    } else if (gold.getDependencyNode(right.getIndex()).getLeftmostDependent().getIndex() == right.getLeftmostDependent().getIndex()) {
    141                            return true;
    142                    }
    143                    return false;
    144            }
    145
    146            public void finalizeSentence(DependencyStructure dependencyGraph) throws MaltChainedException {
    147                    swapArrayActive = false;
    148            }
    149
    150            public void terminate() throws MaltChainedException {
    151
    152            }
    153
    154            private void createSwapArray(DependencyStructure goldDependencyGraph) throws MaltChainedException {
    155                    swapArray.clear();
    156                    for (int i = 0; i <= goldDependencyGraph.getHighestDependencyNodeIndex(); i++) {
    157                            swapArray.add(new Integer(i));
    158                    }
    159                    createSwapArray(goldDependencyGraph.getDependencyRoot(), 0);
    160            }
    161
    162            private int createSwapArray(DependencyNode n, int order) {
    163                    int o = order;
    164                    if (n != null) {
    165                            for (int i=0; i < n.getLeftDependentCount(); i++) {
    166                                    o = createSwapArray(n.getLeftDependent(i), o);
    167                            }
    168                            swapArray.set(n.getIndex(), o++);
    169                            for (int i=n.getRightDependentCount(); i >= 0; i--) {
    170                                    o = createSwapArray(n.getRightDependent(i), o);
    171                            }
    172                    }
    173                    return o;
    174            }
    175    }