    001    package org.maltparser.parser.guide;
    002
    003
    004    import java.io.IOException;
    005    import java.lang.reflect.Constructor;
    006    import java.lang.reflect.InvocationTargetException;
    007
    008    import org.maltparser.core.exception.MaltChainedException;
    009    import org.maltparser.core.feature.FeatureModel;
    010    import org.maltparser.core.feature.FeatureModelManager;
    011    import org.maltparser.core.feature.FeatureVector;
    012    import org.maltparser.core.feature.system.FeatureEngine;
    013    import org.maltparser.core.helper.SystemLogger;
    014    import org.maltparser.core.helper.Util;
    015    import org.maltparser.core.plugin.PluginLoader;
    016    import org.maltparser.core.syntaxgraph.DependencyStructure;
    017    import org.maltparser.parser.DependencyParserConfig;
    018    import org.maltparser.parser.guide.decision.DecisionModel;
    019    import org.maltparser.parser.history.GuideHistory;
    020    import org.maltparser.parser.history.action.GuideDecision;
    021    import org.maltparser.parser.history.action.MultipleDecision;
    022    import org.maltparser.parser.history.action.SingleDecision;
    023    import org.maltparser.parser.history.container.TableContainer.RelationToNextDecision;
    024
    025
    026    /**
    027     * The guide is used by a parsing algorithm to predict the next parser action during parsing and to
    028     * add a instance to the training instance set during learning.
    029
    030    @author Johan Hall
    031    @since 1.0
    032    */
    033    public class SingleGuide implements ClassifierGuide {
    034            private DependencyParserConfig configuration;
    035            private GuideHistory history;
    036            private DecisionModel decisionModel = null;
    037            private GuideMode guideMode;
    038            private FeatureModelManager featureModelManager;
    039            private FeatureModel featureModel;
    040            private String guideName;
    041
    042            public SingleGuide(DependencyParserConfig configuration, GuideHistory history, GuideMode guideMode) throws MaltChainedException {
    043                    setConfiguration(configuration);
    044                    setHistory(history);
    045                    setGuideMode(guideMode);
    046                    initFeatureModelManager();
    047                    initHistory();
    048                    initFeatureModel();
    049                    featureModel.updateCardinality();
    050            }
    051
    052            public void addInstance(GuideDecision decision) throws MaltChainedException {
    053                    if (decisionModel == null) {
    054                            if (decision instanceof SingleDecision) {
    055                                    initDecisionModel((SingleDecision)decision);
    056                            } else if (decision instanceof MultipleDecision && decision.numberOfDecisions() > 0) {
    057                                    initDecisionModel(((MultipleDecision)decision).getSingleDecision(0));
    058                            }
    059                    }
    060                    decisionModel.addInstance(decision);
    061            }
    062
    063            public void finalizeSentence(DependencyStructure dependencyGraph) throws MaltChainedException {
    064                    if (decisionModel != null) {
    065                            decisionModel.finalizeSentence(dependencyGraph);
    066                    }
    067            }
    068
    069            public void noMoreInstances() throws MaltChainedException {
    070                    if (decisionModel != null) {
    071                            decisionModel.noMoreInstances();
    072                    } else {
    073                            configuration.getConfigLogger().debug("The guide cannot create any models because there is no decision model. ");
    074                    }
    075            }
    076
    077            public void terminate() throws MaltChainedException {
    078                    if (decisionModel != null) {
    079                            decisionModel.terminate();
    080                            decisionModel = null;
    081                    }
    082            }
    083
    084            public void predict(GuideDecision decision) throws MaltChainedException {
    085                    if (decisionModel == null) {
    086                            if (decision instanceof SingleDecision) {
    087                                    initDecisionModel((SingleDecision)decision);
    088                            } else if (decision instanceof MultipleDecision && decision.numberOfDecisions() > 0) {
    089                                    initDecisionModel(((MultipleDecision)decision).getSingleDecision(0));
    090                            }
    091                    }
    092                    decisionModel.predict(decision);
    093            }
    094
    095            public FeatureVector predictExtract(GuideDecision decision) throws MaltChainedException {
    096                    if (decisionModel == null) {
    097                            if (decision instanceof SingleDecision) {
    098                                    initDecisionModel((SingleDecision)decision);
    099                            } else if (decision instanceof MultipleDecision && decision.numberOfDecisions() > 0) {
    100                                    initDecisionModel(((MultipleDecision)decision).getSingleDecision(0));
    101                            }
    102                    }
    103                    return decisionModel.predictExtract(decision);
    104            }
    105
    106            public FeatureVector extract() throws MaltChainedException {
    107                    return decisionModel.extract();
    108            }
    109
    110            public boolean predictFromKBestList(GuideDecision decision) throws MaltChainedException {
    111                    if (decisionModel != null) {
    112                            return decisionModel.predictFromKBestList(decision);
    113                    } else {
    114                            throw new GuideException("The decision model cannot be found. ");
    115                    }
    116            }
    117
    118            public DecisionModel getDecisionModel() {
    119                    return decisionModel;
    120            }
    121
    122            public DependencyParserConfig getConfiguration() {
    123                    return configuration;
    124            }
    125
    126            public GuideHistory getHistory() {
    127                    return history;
    128            }
    129
    130            public GuideMode getGuideMode() {
    131                    return guideMode;
    132            }
    133
    134            public FeatureModelManager getFeatureModelManager() {
    135                    return featureModelManager;
    136            }
    137
    138            protected void setConfiguration(DependencyParserConfig configuration) {
    139                    this.configuration = configuration;
    140            }
    141
    142            protected void setHistory(GuideHistory actionHistory) {
    143                    this.history = actionHistory;
    144            }
    145
    146            protected void setGuideMode(GuideMode guideMode) {
    147                    this.guideMode = guideMode;
    148            }
    149
    150            protected void initHistory() throws MaltChainedException {
    151                    Class<?> kBestListClass = null;
    152                    int kBestSize = 1;
    153                    if (guideMode == ClassifierGuide.GuideMode.CLASSIFY) {
    154                            kBestListClass = (Class<?>)getConfiguration().getOptionValue("guide", "kbest_type");
    155                            kBestSize = ((Integer)getConfiguration().getOptionValue("guide", "kbest")).intValue();
    156                    }
    157                    history.setKBestListClass(kBestListClass);
    158                    history.setKBestSize(kBestSize);
    159                    history.setSeparator(getConfiguration().getOptionValue("guide", "classitem_separator").toString());
    160            }
    161
    162            protected void initDecisionModel(SingleDecision decision) throws MaltChainedException {
    163                    Class<?> decisionModelClass = null;
    164                    if (decision.getRelationToNextDecision() == RelationToNextDecision.SEQUANTIAL) {
    165                            decisionModelClass = org.maltparser.parser.guide.decision.SeqDecisionModel.class;
    166                    } else if (decision.getRelationToNextDecision() == RelationToNextDecision.BRANCHED) {
    167                            decisionModelClass = org.maltparser.parser.guide.decision.BranchedDecisionModel.class;
    168                    } else if (decision.getRelationToNextDecision() == RelationToNextDecision.NONE) {
    169                            decisionModelClass = org.maltparser.parser.guide.decision.OneDecisionModel.class;
    170                    }
    171
    172                    if (decisionModelClass == null) {
    173                            throw new GuideException("Could not find an appropriate decision model for the relation to the next decision");
    174                    }
    175
    176                    try {
    177                            Class<?>[] argTypes = { org.maltparser.parser.guide.ClassifierGuide.class, org.maltparser.core.feature.FeatureModel.class };
    178                            Object[] arguments = new Object[2];
    179                            arguments[0] = this;
    180                            arguments[1] = featureModel;
    181                            Constructor<?> constructor = decisionModelClass.getConstructor(argTypes);
    182                            decisionModel = (DecisionModel)constructor.newInstance(arguments);
    183                    } catch (NoSuchMethodException e) {
    184                            throw new GuideException("The decision model class '"+decisionModelClass.getName()+"' cannot be initialized. ", e);
    185                    } catch (InstantiationException e) {
    186                            throw new GuideException("The decision model class '"+decisionModelClass.getName()+"' cannot be initialized. ", e);
    187                    } catch (IllegalAccessException e) {
    188                            throw new GuideException("The decision model class '"+decisionModelClass.getName()+"' cannot be initialized. ", e);
    189                    } catch (InvocationTargetException e) {
    190                            throw new GuideException("The decision model class '"+decisionModelClass.getName()+"' cannot be initialized. ", e);
    191                    }
    192            }
    193
    194            protected void initFeatureModelManager() throws MaltChainedException {
    195                    final FeatureEngine system = new FeatureEngine();
    196                    system.load("/appdata/features/ParserFeatureSystem.xml");
    197                    system.load(PluginLoader.instance());
    198                    featureModelManager = new FeatureModelManager(system, getConfiguration().getConfigurationDir());
    199            }
    200
    201            protected void initFeatureModel() throws MaltChainedException {
    202                    String featureModelFileName = getConfiguration().getOptionValue("guide", "features").toString().trim();
    203
    204                    if (featureModelFileName.endsWith(".par")) {
    205                            String markingStrategy = getConfiguration().getOptionValue("pproj", "marking_strategy").toString().trim();
    206                            String coveredRoot = getConfiguration().getOptionValue("pproj", "covered_root").toString().trim();
    207                            featureModelManager.loadParSpecification(featureModelFileName, markingStrategy, coveredRoot);
    208                    } else {
    209                            featureModelManager.loadSpecification(featureModelFileName);
    210                    }
    211                    if (getConfiguration().getConfigLogger().isInfoEnabled()) {
    212                            getConfiguration().getConfigLogger().info("  Feature model        : " + featureModelFileName+"\n");
    213                            if (getGuideMode() == ClassifierGuide.GuideMode.BATCH) {
    214                                    getConfiguration().getConfigLogger().info("  Learner              : " + getConfiguration().getOptionValueString("guide", "learner").toString()+"\n");
    215                            } else {
    216                                    getConfiguration().getConfigLogger().info("  Classifier           : " + getConfiguration().getOptionValueString("guide", "learner")+"\n");
    217                            }
    218                    }
    219                    featureModel = getFeatureModelManager().getFeatureModel(getConfiguration().getOptionValue("guide", "features").toString(), 0, getConfiguration().getRegistry());
    220                    if (getGuideMode() == ClassifierGuide.GuideMode.BATCH && getConfiguration().getConfigurationDir().getInfoFileWriter() != null) {
    221                            try {
    222                                    getConfiguration().getConfigurationDir().getInfoFileWriter().write("\nFEATURE MODEL\n");
    223                                    getConfiguration().getConfigurationDir().getInfoFileWriter().write(featureModel.toString());
    224                                    getConfiguration().getConfigurationDir().getInfoFileWriter().flush();
    225                            } catch (IOException e) {
    226                                    throw new GuideException("Could not write feature model specification to configuration information file. ", e);
    227                            }
    228                    }
    229            }
    230
    231
    232            public String getGuideName() {
    233                    return guideName;
    234            }
    235
    236            public void setGuideName(String guideName) {
    237                    this.guideName = guideName;
    238            }
    239
    240            public String toString() {
    241                    final StringBuilder sb = new StringBuilder();
    242                    return sb.toString();
    243            }
    244    }