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 }