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