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 }