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 }