You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@uima.apache.org by jo...@apache.org on 2011/08/01 16:21:35 UTC
svn commit: r1152792 [2/10] - in /uima/sandbox/trunk/TextMarker:
org.apache.uima.tm.textruler.lp2/ org.apache.uima.tm.textruler.lp2/META-INF/
org.apache.uima.tm.textruler.lp2/bin/ org.apache.uima.tm.textruler.lp2/src/
org.apache.uima.tm.textruler.lp2/s...
Added: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/NaiveLP2.java
URL: http://svn.apache.org/viewvc/uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/NaiveLP2.java?rev=1152792&view=auto
==============================================================================
--- uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/NaiveLP2.java (added)
+++ uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/NaiveLP2.java Mon Aug 1 14:21:12 2011
@@ -0,0 +1,337 @@
+package org.apache.uima.tm.textruler.lp2;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.uima.cas.CAS;
+import org.apache.uima.cas.Type;
+import org.apache.uima.cas.TypeSystem;
+import org.apache.uima.cas.text.AnnotationFS;
+import org.apache.uima.tm.textruler.core.TextRulerAnnotation;
+import org.apache.uima.tm.textruler.core.TextRulerExample;
+import org.apache.uima.tm.textruler.core.TextRulerRule;
+import org.apache.uima.tm.textruler.core.TextRulerRuleItem;
+import org.apache.uima.tm.textruler.core.TextRulerRulePattern;
+import org.apache.uima.tm.textruler.core.TextRulerTarget;
+import org.apache.uima.tm.textruler.core.TextRulerToolkit;
+import org.apache.uima.tm.textruler.core.TextRulerTarget.MLTargetType;
+import org.apache.uima.tm.textruler.extension.TextRulerLearnerDelegate;
+import org.apache.uima.tm.textruler.lp2.LP2RuleItem.MLLP2ContextConstraint;
+import org.apache.uima.tm.textruler.lp2.LP2RuleItem.MLLP2OtherConstraint;
+import org.apache.uima.util.FileUtils;
+
+public class NaiveLP2 extends BasicLP2 {
+
+ public NaiveLP2(String inputDir, String prePropTMFile, String tmpDir, String[] slotNames,
+ Set<String> filterSet, TextRulerLearnerDelegate delegate) {
+ super(inputDir, prePropTMFile, tmpDir, slotNames, filterSet, delegate);
+ }
+
+ public static final boolean SAVE_DEBUG_INFO_IN_TEMPFOLDER = false;
+
+ @Override
+ protected void induceRulesFromExample(TextRulerExample e, int roundNumber) {
+ LP2Rule baseRule = createInitialRuleForPositiveExample(e);
+ List<LP2Rule> genRules = generalizeRule(baseRule);
+
+ if (shouldAbort())
+ return;
+
+ List<LP2Rule> test = new ArrayList<LP2Rule>();
+
+ // int i=1;
+ // for (LP2Rule newRule : genRules)
+ // {
+ // if (shouldAbort())
+ // return;
+ // sendStatusUpdateToDelegate("Round "+roundNumber+" - Testing proposed generalization "+i+"/"+(genRules.size())+
+ // " - uncovered examples: "+
+ // (examples.size()-coveredExamples.size() + " / "+examples.size()),
+ // TextRulerLearnerState.ML_RUNNING, false);
+ // i++;
+ // testRuleOnDocumentSet(newRule, exampleDocuments);
+ //
+ // checkAndHandleNewRule(newRule);
+ //
+ // if (TextRulerToolkit.DEBUG)
+ // test.add(newRule);
+ // }
+ // new cache and testCAS optimized rule testing:
+
+ sendStatusUpdateToDelegate("Round " + roundNumber + " - Testing " + (genRules.size())
+ + "generalizations... - uncovered examples: "
+ + (examples.size() - coveredExamples.size() + " / " + examples.size()),
+ TextRulerLearnerState.ML_RUNNING, false);
+ testRulesOnDocumentSet(new ArrayList<TextRulerRule>(genRules), exampleDocuments);
+
+ for (LP2Rule newRule : genRules) {
+ checkAndHandleNewRule(newRule);
+ if (TextRulerToolkit.DEBUG)
+ test.add(newRule);
+ }
+
+ if (TextRulerToolkit.DEBUG && SAVE_DEBUG_INFO_IN_TEMPFOLDER) {
+ Collections.sort(test, new Comparator<LP2Rule>() {
+
+ public int compare(LP2Rule o1, LP2Rule o2) {
+ return o1.getRuleString().compareTo(o2.getRuleString());
+ }
+
+ });
+
+ String startend = e.getTarget().type == MLTargetType.SINGLE_LEFT_BOUNDARY ? "left_"
+ : "right_";
+ File file = new File(tempDirectory() + startend + "generalizations" + roundNumber + ".tm");
+ StringBuffer str = new StringBuffer();
+ for (TextRulerRule rule : test) {
+ str.append(rule.getCoveringStatistics() + "\t\t" + rule.getRuleString() + "\n");
+ }
+ try {
+ FileUtils.saveString2File(str.toString(), file);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ }
+
+ protected void checkAndHandleNewRule(LP2Rule rule) {
+ boolean tooFewPositives = rule.getCoveringStatistics().getCoveredPositivesCount() < minCoveredPositives;
+ boolean tooManyErrors = rule.getErrorRate() > maxErrorThreshold;
+
+ boolean isBestRule = !(tooFewPositives || tooManyErrors);
+
+ if (TextRulerToolkit.DEBUG && SAVE_DEBUG_INFO_IN_TEMPFOLDER)
+ TextRulerToolkit.appendStringToFile(tempDirectory() + "bestcandidates.tm", rule
+ .getRuleString()
+ + "\n");
+
+ if (isBestRule) {
+ currentBestRules.add(rule);
+ currentBestRules.removeSubsumedRules();
+ currentBestRules.cutToMaxSize();
+ } else if (!tooFewPositives) {
+
+ // test in context
+ // in our TM representation, we simply can add a NEAR condition in
+ // the MARKing rule item and retest it on the
+ // corpus. we should do that for all kinds of tags we have, but
+ // currently we only do it for the corresponding opening/closing
+ // tag, since we do not have any information about other slots yet!
+ // // TODO use all other slot tags! (see optimized version as well)
+
+ if (true) {
+ rule = rule.copy();
+ LP2RuleItem item = rule.getMarkingRuleItem();
+ // TextRulerToolkit.log("CONTEXTUAL RULE CANDIDATE: "+rule.getRuleString()+" ; "+rule.getCoveringStatistics());
+ item.setContextConstraint(new MLLP2ContextConstraint(slotMaximumTokenCount, rule));
+ rule.setIsContextualRule(true);
+
+ rule.setNeedsCompile(true);
+
+ if (TextRulerToolkit.DEBUG && SAVE_DEBUG_INFO_IN_TEMPFOLDER)
+ TextRulerToolkit.appendStringToFile(tempDirectory() + "ctxcandidates.tm", rule
+ .getRuleString());
+
+ testRuleOnDocumentSet(rule, exampleDocuments); // not very
+ // fast... but
+ // works!
+ boolean ctxTooFewPositives = rule.getCoveringStatistics().getCoveredPositivesCount() < minCoveredPositives;
+ boolean ctxTooManyErrors = rule.getErrorRate() > maxErrorThreshold;
+ boolean isGoodContextRule = !(ctxTooFewPositives || ctxTooManyErrors);
+ if (isGoodContextRule) {
+ currentContextualRules.add(rule);
+ currentContextualRules.removeSubsumedRules();
+ currentContextualRules.cutToMaxSize();
+ }
+ }
+
+ }
+ }
+
+ protected List<LP2Rule> generalizeRule(LP2Rule baseRule) {
+ List<LP2Rule> result = new ArrayList<LP2Rule>();
+ TextRulerRulePattern rulePattern = new TextRulerRulePattern();
+ TextRulerRulePattern prePattern = baseRule.getPreFillerPattern();
+
+ for (int i = prePattern.size() - 1; i >= 0; i--) // we have to reverse
+ // the order again!
+ {
+ rulePattern.add(prePattern.get(i));
+ }
+ rulePattern.addAll(baseRule.getPostFillerPattern());
+
+ recursiveGeneralizeRule(baseRule, rulePattern, new TextRulerRulePattern(), result);
+ TextRulerToolkit.log("GENERALIZATIONS: " + result.size());
+
+ for (LP2Rule r : result)
+ removeOutermostWildCardItemsFromRule(r);
+
+ // for (LP2Rule r : result)
+ // {
+ // TextRulerToolkit.log("NEWRULE = "+r.getRuleString());
+ // }
+
+ return result;
+ }
+
+ protected LP2Rule createInitialRuleForPositiveExample(TextRulerExample example) {
+ TextRulerTarget target = example.getTarget();
+ LP2Rule rule = new LP2Rule(this, example.getTarget());
+ CAS docCas = example.getDocumentCAS();
+ TextRulerAnnotation exampleAnnotation = example.getAnnotation();
+ TypeSystem ts = docCas.getTypeSystem();
+ Type tokensRootType = ts.getType(TextRulerToolkit.TM_ANY_TYPE_NAME);
+ int thePosition = target.type == MLTargetType.SINGLE_LEFT_BOUNDARY ? exampleAnnotation
+ .getBegin() : exampleAnnotation.getEnd();
+
+ List<AnnotationFS> leftContext = TextRulerToolkit.getAnnotationsBeforePosition(docCas,
+ thePosition, windowSize, TextRulerToolkit.getFilterSetWithSlotNames(slotNames,
+ filterSet), tokensRootType);
+ List<AnnotationFS> rightContext = TextRulerToolkit.getAnnotationsAfterPosition(docCas,
+ thePosition, windowSize, TextRulerToolkit.getFilterSetWithSlotNames(slotNames,
+ filterSet), tokensRootType);
+
+ // the left context has to be reversed since we get the arrayList from
+ // the slot's point of view!
+ for (int i = leftContext.size() - 1; i >= 0; i--) {
+ TextRulerAnnotation annot = new TextRulerAnnotation(leftContext.get(i), example.getDocument());
+ LP2RuleItem item = new LP2RuleItem();
+ item.setWordConstraint(annot);
+ if (item.getWordConstraint().isRegExpConstraint())
+ item.addOtherConstraint(new MLLP2OtherConstraint(annot, annot));
+ rule.addPreFillerItem(item);
+ }
+
+ for (AnnotationFS afs : rightContext) {
+ TextRulerAnnotation annot = new TextRulerAnnotation(afs, example.getDocument());
+ LP2RuleItem item = new LP2RuleItem();
+ item.setWordConstraint(annot);
+ if (item.getWordConstraint().isRegExpConstraint())
+ item.addOtherConstraint(new MLLP2OtherConstraint(annot, annot));
+
+ rule.addPostFillerItem(item);
+ }
+ TextRulerToolkit.log("INITIAL RULE: " + rule.getRuleString());
+ return rule;
+ }
+
+ protected void recursiveGeneralizeRule(LP2Rule baseRule, TextRulerRulePattern allItems,
+ TextRulerRulePattern currentPattern, List<LP2Rule> resultList) {
+ if (currentPattern.size() == allItems.size()) {
+ // create new Rule
+ LP2Rule newRule = new LP2Rule(this, baseRule.getTarget());
+ int preCount = baseRule.getPreFillerPattern().size();
+ for (int i = 0; i < currentPattern.size(); i++) {
+ if (i < preCount)
+ newRule.addPreFillerItem(currentPattern.get(i));
+ else
+ newRule.addPostFillerItem(currentPattern.get(i));
+ }
+ // TextRulerToolkit.log("GEN: "+newRule.getRuleString());
+ if (newRule.totalInnerConstraintCount() > 0) // skip the ANY ANY ANY
+ // ANY... rule ! this
+ // makes no sense in no
+ // application!!
+ resultList.add(newRule);
+ } else {
+ int index = currentPattern.size();
+ TextRulerRuleItem baseItem = allItems.get(index);
+ List<TextRulerRuleItem> itemGeneralizations = generalizeRuleItem((LP2RuleItem) baseItem);
+ for (TextRulerRuleItem newItem : itemGeneralizations) {
+ currentPattern.add(newItem);
+ recursiveGeneralizeRule(baseRule, allItems, currentPattern, resultList);
+ currentPattern.remove(currentPattern.size() - 1);
+ }
+ }
+ }
+
+ protected void recursiveGeneralizeRuleItem(LP2RuleItem baseItem,
+ List<MLLP2OtherConstraint> otherConstraints, int currentConstraintIndex,
+ List<MLLP2OtherConstraint> currentConstraintTuple, List<TextRulerRuleItem> result) {
+ if (currentConstraintIndex > otherConstraints.size() - 1) {
+ LP2RuleItem newItem;
+ newItem = new LP2RuleItem();
+ for (MLLP2OtherConstraint c : currentConstraintTuple)
+ newItem.addOtherConstraint(c.copy());
+ result.add(newItem);
+ } else {
+ MLLP2OtherConstraint currentConstraint = otherConstraints.get(currentConstraintIndex);
+ // recurse WITH and WITHOUT this key:
+ recursiveGeneralizeRuleItem(baseItem, otherConstraints, currentConstraintIndex + 1,
+ currentConstraintTuple, result);
+ currentConstraintTuple.add(currentConstraint);
+ recursiveGeneralizeRuleItem(baseItem, otherConstraints, currentConstraintIndex + 1,
+ currentConstraintTuple, result);
+ currentConstraintTuple.remove(currentConstraintTuple.size() - 1);
+ }
+ }
+
+ protected List<TextRulerRuleItem> generalizeRuleItem(LP2RuleItem baseItem) {
+ List<TextRulerRuleItem> result = new ArrayList<TextRulerRuleItem>();
+
+ // one with word constraint
+ if (baseItem.getWordConstraint() != null) {
+ LP2RuleItem newItem = new LP2RuleItem();
+ newItem.setWordConstraint(baseItem.getWordConstraint().copy());
+ result.add(newItem);
+ }
+
+ // all other combinations without word constraint
+ // List<String> keys = new
+ // ArrayList<String>(baseItem.getOtherConstraints().keySet());
+ List<MLLP2OtherConstraint> constraints = baseItem.getOtherConstraints();
+ recursiveGeneralizeRuleItem(baseItem, constraints, 0, new ArrayList<MLLP2OtherConstraint>(),
+ result);
+ return result;
+ }
+
+ protected void removeOutermostWildCardItemsFromRule(LP2Rule rule) {
+ while (true) {
+ LP2RuleItem item = (LP2RuleItem) rule.getOutermostPreFillerItem();
+ if (item == null) // no more items left
+ break;
+
+ // if this rule is a RIGHT BOUNDARY rule, we must not remove the
+ // last remaining pre filler item,
+ // since this is used for marking the SLOT END BOUNDARY (= RIGHT
+ // BOUNDARY)
+ if ((rule.getTarget().type == MLTargetType.SINGLE_RIGHT_BOUNDARY)
+ && (rule.getPreFillerPattern().size() == 1))
+ break;
+
+ if (item.totalConstraintCount() == 0)
+ rule.removeOutermostPreFillerItem();
+ else
+ break;
+ }
+ while (true) {
+ LP2RuleItem item = (LP2RuleItem) rule.getOutermostPostFillerItem();
+ if (item == null) // no more items left
+ break;
+
+ // if this rule is a LEFT BOUNDARY rule, we must not remove the last
+ // remaining post filler item,
+ // since this is used for marking the SLOT START BOUNDARY (= LEFT
+ // BOUNDARY)
+ if ((rule.getTarget().type == MLTargetType.SINGLE_LEFT_BOUNDARY)
+ && (rule.getPostFillerPattern().size() == 1))
+ break;
+
+ if (item.totalConstraintCount() == 0)
+ rule.removeOutermostPostFillerItem();
+ else
+ break;
+ }
+ }
+
+ @Override
+ public boolean collectNegativeCoveredInstancesWhenTesting() {
+ return false;
+ }
+
+}
Propchange: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/NaiveLP2.java
------------------------------------------------------------------------------
svn:executable = *
Propchange: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/NaiveLP2.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/NaiveLP2Factory.java
URL: http://svn.apache.org/viewvc/uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/NaiveLP2Factory.java?rev=1152792&view=auto
==============================================================================
--- uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/NaiveLP2Factory.java (added)
+++ uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/NaiveLP2Factory.java Mon Aug 1 14:21:12 2011
@@ -0,0 +1,53 @@
+package org.apache.uima.tm.textruler.lp2;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.uima.tm.textruler.extension.TextRulerLearner;
+import org.apache.uima.tm.textruler.extension.TextRulerLearnerDelegate;
+import org.apache.uima.tm.textruler.extension.TextRulerLearnerFactory;
+import org.apache.uima.tm.textruler.extension.TextRulerLearnerParameter;
+import org.apache.uima.tm.textruler.extension.TextRulerLearnerParameter.MLAlgorithmParamType;
+
+public class NaiveLP2Factory implements TextRulerLearnerFactory {
+
+ public TextRulerLearner createAlgorithm(String inputFolderPath, String additionalFolderPath,
+ String prePropTMFile, String tempFolderPath, String[] fullSlotTypeNames,
+ Set<String> filterSet, TextRulerLearnerDelegate delegate) {
+ return new NaiveLP2(inputFolderPath, prePropTMFile, tempFolderPath, fullSlotTypeNames,
+ filterSet, delegate);
+ }
+
+ public TextRulerLearnerParameter[] getAlgorithmParameters() {
+ TextRulerLearnerParameter[] result = new TextRulerLearnerParameter[5];
+
+ result[0] = new TextRulerLearnerParameter(BasicLP2.WINDOW_SIZE_KEY,
+ "Context Window Size (to the left and right)", MLAlgorithmParamType.ML_INT_PARAM);
+ result[1] = new TextRulerLearnerParameter(BasicLP2.CURRENT_BEST_RULES_SIZE_KEY,
+ "Best Rules List Size", MLAlgorithmParamType.ML_INT_PARAM);
+ result[2] = new TextRulerLearnerParameter(BasicLP2.MIN_COVERED_POSITIVES_PER_RULE_KEY,
+ "Minimum Covered Positives per Rule", MLAlgorithmParamType.ML_INT_PARAM);
+ result[3] = new TextRulerLearnerParameter(BasicLP2.MAX_ERROR_THRESHOLD_KEY,
+ "Maximum Error Threshold", MLAlgorithmParamType.ML_FLOAT_PARAM);
+ result[4] = new TextRulerLearnerParameter(BasicLP2.CURRENT_CONTEXTUAL_RULES_SIZE_KEY,
+ "Contextual Rules List Size", MLAlgorithmParamType.ML_INT_PARAM);
+
+ return result;
+ }
+
+ public Map<String, Object> getAlgorithmParameterStandardValues() {
+ Map<String, Object> result = new HashMap<String, Object>();
+ result.put(BasicLP2.WINDOW_SIZE_KEY, BasicLP2.STANDARD_WINDOW_SIZE);
+ result
+ .put(BasicLP2.CURRENT_BEST_RULES_SIZE_KEY,
+ BasicLP2.STANDARD_MAX_CURRENT_BEST_RULES_COUNT);
+ result.put(BasicLP2.MIN_COVERED_POSITIVES_PER_RULE_KEY,
+ BasicLP2.STANDARD_MIN_COVERED_POSITIVES_PER_RULE);
+ result.put(BasicLP2.MAX_ERROR_THRESHOLD_KEY, BasicLP2.STANDARD_MAX_ERROR_THRESHOLD);
+ result.put(BasicLP2.CURRENT_CONTEXTUAL_RULES_SIZE_KEY,
+ BasicLP2.STANDARD_MAX_CONTEXTUAL_RULES_COUNT);
+ return result;
+ }
+
+}
Propchange: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/NaiveLP2Factory.java
------------------------------------------------------------------------------
svn:executable = *
Propchange: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/NaiveLP2Factory.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/NaiveLP2PreferencePage.java
URL: http://svn.apache.org/viewvc/uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/NaiveLP2PreferencePage.java?rev=1152792&view=auto
==============================================================================
--- uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/NaiveLP2PreferencePage.java (added)
+++ uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/NaiveLP2PreferencePage.java Mon Aug 1 14:21:12 2011
@@ -0,0 +1,104 @@
+package org.apache.uima.tm.textruler.lp2;
+
+import java.util.ArrayList;
+import java.util.Map;
+
+import org.apache.uima.tm.textruler.TextRulerPlugin;
+import org.apache.uima.tm.textruler.extension.TextRulerController;
+import org.apache.uima.tm.textruler.extension.TextRulerLearnerController;
+import org.apache.uima.tm.textruler.extension.TextRulerLearnerFactory;
+import org.apache.uima.tm.textruler.extension.TextRulerLearnerParameter;
+import org.eclipse.jface.preference.BooleanFieldEditor;
+import org.eclipse.jface.preference.FieldEditor;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferencePage;
+import org.eclipse.jface.preference.StringFieldEditor;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+
+
+public class NaiveLP2PreferencePage extends PreferencePage implements IWorkbenchPreferencePage {
+
+ public static String ID = "org.apache.uima.tm.textruler.algorithmPages";
+
+ private TextRulerLearnerController algorithmController;
+
+ private IPreferenceStore store;
+
+ private ArrayList<FieldEditor> fields = new ArrayList<FieldEditor>();
+
+ public NaiveLP2PreferencePage() {
+ TextRulerLearnerController ctrl = TextRulerController.getControllerForID("org.apache.uima.tm.textruler.lp2naive");
+ this.algorithmController = ctrl;
+ store = TextRulerPlugin.getDefault().getPreferenceStore();
+ setPreferenceStore(store);
+ }
+
+ @Override
+ protected Control createContents(Composite parent) {
+ Composite top = new Composite(parent, SWT.LEFT);
+ top.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ top.setLayout(new GridLayout());
+
+ TextRulerLearnerFactory f = algorithmController.getFactory();
+ TextRulerLearnerParameter[] params = f.getAlgorithmParameters();
+ Map<String, Object> values = f.getAlgorithmParameterStandardValues();
+ if (params != null) {
+ for (int i = 0; i < params.length; i++) {
+ TextRulerLearnerParameter p = params[i];
+ String id = algorithmController.getID() + "." + p.id;
+ FieldEditor l = null;
+ switch (p.type) {
+ case ML_BOOL_PARAM: {
+ l = new BooleanFieldEditor(id, p.name, top);
+ fields.add(l);
+ store.setDefault(id, (Boolean) values.get(p.id));
+ l.setPreferenceStore(store);
+ l.load();
+ break;
+ }
+
+ case ML_FLOAT_PARAM:
+ case ML_INT_PARAM:
+ case ML_STRING_PARAM: {
+ l = new StringFieldEditor(id, p.name, top);
+ fields.add(l);
+ store.setDefault(id, values.get(p.id).toString());
+ l.setPreferenceStore(store);
+ l.load();
+ break;
+ }
+ case ML_SELECT_PARAM:
+ break;
+ }
+ }
+ }
+ return top;
+ }
+
+ @Override
+ public void init(IWorkbench workbench) {
+ }
+
+ @Override
+ protected void performDefaults() {
+ for (FieldEditor f : fields)
+ f.loadDefault();
+ // super.performDefaults();
+ }
+
+ @Override
+ public boolean performOk() {
+ for (FieldEditor f : fields)
+ f.store();
+ // return super.performOk();
+ return true;
+ }
+
+
+}
Propchange: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/NaiveLP2PreferencePage.java
------------------------------------------------------------------------------
svn:executable = *
Propchange: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/NaiveLP2PreferencePage.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/OptimizedLP2.java
URL: http://svn.apache.org/viewvc/uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/OptimizedLP2.java?rev=1152792&view=auto
==============================================================================
--- uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/OptimizedLP2.java (added)
+++ uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/OptimizedLP2.java Mon Aug 1 14:21:12 2011
@@ -0,0 +1,572 @@
+package org.apache.uima.tm.textruler.lp2;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.uima.cas.CAS;
+import org.apache.uima.cas.Type;
+import org.apache.uima.cas.TypeSystem;
+import org.apache.uima.cas.text.AnnotationFS;
+import org.apache.uima.tm.textruler.core.TextRulerAnnotation;
+import org.apache.uima.tm.textruler.core.TextRulerExample;
+import org.apache.uima.tm.textruler.core.TextRulerRule;
+import org.apache.uima.tm.textruler.core.TextRulerRuleList;
+import org.apache.uima.tm.textruler.core.TextRulerStatisticsCollector;
+import org.apache.uima.tm.textruler.core.TextRulerTarget;
+import org.apache.uima.tm.textruler.core.TextRulerToolkit;
+import org.apache.uima.tm.textruler.core.TextRulerTarget.MLTargetType;
+import org.apache.uima.tm.textruler.extension.TextRulerLearnerDelegate;
+import org.apache.uima.tm.textruler.lp2.LP2RuleItem.MLLP2ContextConstraint;
+import org.apache.uima.tm.textruler.lp2.LP2RuleItem.MLLP2OtherConstraint;
+import org.apache.uima.util.FileUtils;
+
+
+public class OptimizedLP2 extends BasicLP2 {
+
+ public static final boolean SAVE_DEBUG_INFO_IN_TEMPFOLDER = false;
+
+ private Map<String, TextRulerStatisticsCollector> cachedTestedStartRuleStatistics = new HashMap<String, TextRulerStatisticsCollector>();
+
+ private long cachedTestedStartRuleStatisticsHitCounter = 0;
+
+ public OptimizedLP2(String inputDir, String prePropTMFile, String tmpDir, String[] slotNames,
+ Set<String> filterSet, TextRulerLearnerDelegate delegate) {
+ super(inputDir, prePropTMFile, tmpDir, slotNames, filterSet, delegate);
+ }
+
+ @Override
+ protected TextRulerRuleList learnTaggingRules(TextRulerTarget target,
+ TextRulerRuleList contextualRules) {
+ cachedTestedStartRuleStatisticsHitCounter = 0;
+ cachedTestedStartRuleStatistics.clear();
+ TextRulerRuleList result = super.learnTaggingRules(target, contextualRules);
+ TextRulerToolkit
+ .log("[OptimizedLP2.learnTaggingRules] saved rule testings due to start rule results cache: "
+ + cachedTestedStartRuleStatisticsHitCounter);
+ TextRulerToolkit.log("[OptimizedLP2.learnTaggingRules] cacheSize at end of induction: "
+ + cachedTestedStartRuleStatistics.size());
+ cachedTestedStartRuleStatistics.clear();
+ return result;
+ }
+
+ @Override
+ protected void induceRulesFromExample(final TextRulerExample e, final int roundNumber) {
+ // in order to get cache optimized contextual start rules testing, we
+ // simply create
+ // and add the ctxStartRules HERE (not when we want to create a
+ // contextual rule!) to
+ // all startRules, test those startRules + ctxStartRules cacheOptimized
+ // on the trainings-Set
+ // and then have their results in our covering-statistics-cache for
+ // later ctx rules creation!
+ List<LP2Rule> startRules = createStartRulesForExample(e);
+ if (startRules.size() < 1)
+ return;
+ List<LP2Rule> ctxStartRules = new ArrayList<LP2Rule>();
+ // TODO set isCorrectionRuleMode = true ?!
+ if (!(e.getTarget().isLeftCorrection() || e.getTarget().isRightCorrection()))
+ ctxStartRules = createContextStartRulesForStartRule(startRules.get(0));
+ List<LP2Rule> rulesToTest = new ArrayList<LP2Rule>(ctxStartRules.size() + startRules.size());
+ rulesToTest.addAll(startRules);
+ rulesToTest.addAll(ctxStartRules);
+
+ sendStatusUpdateToDelegate("Round " + roundNumber + " - Testing " + rulesToTest.size()
+ + " start rules... " + " - uncovered examples: "
+ + (examples.size() - coveredExamples.size() + " / " + examples.size()) + " cs: "
+ + cachedTestedStartRuleStatistics.size(), TextRulerLearnerState.ML_RUNNING, false);
+ testStartRulesIfNotCached(rulesToTest);
+ if (shouldAbort())
+ return;
+ // int i=0;
+ // for (LP2Rule r : startRules)
+ // {
+ // i++;
+ // sendStatusUpdateToDelegate("Round "+roundNumber+" - Testing start rule "+i+"/"+startRules.size()+
+ // " - uncovered examples: "+
+ // (examples.size()-coveredExamples.size() + " / "+examples.size())+
+ // "cs:"+cachedTestedStartRuleStatistics.size(),
+ // TextRulerLearnerState.ML_RUNNING, false);
+ // testStartRuleIfNotCached(r);
+ // if (shouldAbort())
+ // return;
+ // if (TextRulerToolkit.DEBUG)
+ // {
+ // if
+ // (!r.getCoveringStatistics().getCoveredPositiveExamples().contains(e))
+ // {
+ // TextRulerToolkit.log("A START RULE MUST (!) COVER ITs POSITIVE EXAMPLE! OTHEREWISE, THERE IS SOMETHING WRONG!!");
+ // }
+ // }
+ // }
+
+ Comparator<LP2Rule> cmp = new Comparator<LP2Rule>() {
+
+ public int compare(LP2Rule o1, LP2Rule o2) {
+ return o1.getCoveringStatistics().getCoveredPositivesCount()
+ - o2.getCoveringStatistics().getCoveredPositivesCount();
+ }
+
+ };
+ // sort from low to high positive coverage in order to higher the
+ // pruning probability while recursion:
+ Collections.sort(startRules, cmp);
+ Collections.sort(ctxStartRules, cmp);
+
+ while ((startRules.size() > 0)
+ && (startRules.get(0).getCoveringStatistics().getCoveredPositivesCount() < minCoveredPositives))
+ startRules.remove(0);
+
+ while ((ctxStartRules.size() > 0)
+ && (ctxStartRules.get(0).getCoveringStatistics().getCoveredPositivesCount() < minCoveredPositives))
+ ctxStartRules.remove(0);
+
+ sendStatusUpdateToDelegate("Round " + roundNumber + " - Creating all generalizations..."
+ + " - uncovered examples: "
+ + (examples.size() - coveredExamples.size() + " / " + examples.size()),
+ TextRulerLearnerState.ML_RUNNING, false);
+
+ // only for debugging purposes: List<LP2Rule> resultRules = new
+ // ArrayList<LP2Rule>();
+
+ ArrayList<LP2Rule> debugRuleCollector = null;
+
+ if (TextRulerToolkit.DEBUG && SAVE_DEBUG_INFO_IN_TEMPFOLDER) {
+ debugRuleCollector = new ArrayList<LP2Rule>();
+ }
+
+ if (!recursiveCreateAllRuleCombinations(startRules, ctxStartRules, 0, new ArrayList<LP2Rule>(),
+ null, debugRuleCollector))
+ return; // aborted!
+
+ if (TextRulerToolkit.DEBUG && debugRuleCollector != null && SAVE_DEBUG_INFO_IN_TEMPFOLDER) {
+ // TextRulerToolkit.log("all combinations: "+debugRuleCollector.size());
+
+ Collections.sort(debugRuleCollector, new Comparator<LP2Rule>() {
+
+ public int compare(LP2Rule o1, LP2Rule o2) {
+ return o1.getRuleString().compareTo(o2.getRuleString());
+ }
+
+ });
+ String startend = e.getTarget().type == MLTargetType.SINGLE_LEFT_BOUNDARY ? "left_"
+ : "right_";
+ File file = new File(tempDirectory() + startend + "generalizations" + roundNumber + ".tm");
+ StringBuffer str = new StringBuffer();
+ for (TextRulerRule rule : debugRuleCollector) {
+ str.append(rule.getCoveringStatistics() + "\t\t" + rule.getRuleString() + "\n");
+ }
+ try {
+ FileUtils.saveString2File(str.toString(), file);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ // TextRulerToolkit.log("----");
+ }
+ }
+
+ protected void testStartRulesIfNotCached(List<LP2Rule> startRules) {
+ List<TextRulerRule> rulesToTest = new ArrayList<TextRulerRule>();
+
+ for (LP2Rule r : startRules) {
+ String key = r.getRuleString();
+ if (cachedTestedStartRuleStatistics.containsKey(key)) {
+ r.setCoveringStatistics(cachedTestedStartRuleStatistics.get(key).copy());
+ cachedTestedStartRuleStatisticsHitCounter++;
+ } else
+ rulesToTest.add(r);
+ }
+
+ if (rulesToTest.size() > 0) {
+ testRulesOnDocumentSet(rulesToTest, exampleDocuments);
+ if (shouldAbort())
+ return;
+ for (TextRulerRule r : rulesToTest) {
+ String key = r.getRuleString();
+ cachedTestedStartRuleStatistics.put(key, r.getCoveringStatistics().copy());
+ }
+ }
+ }
+
+ protected LP2Rule combineRulesToOneRule(List<LP2Rule> ruleList,
+ TextRulerStatisticsCollector covering) {
+ // TextRulerToolkit.log("----------------------------------------------");
+ // for (LP2Rule r : ruleList)
+ // TextRulerToolkit.log(r+" ; "+r.getCoveringStatistics());
+
+ LP2Rule rule = new LP2Rule(this, ruleList.get(0).getTarget());
+
+ int maxPreCount = 0;
+ int maxPostCount = 0;
+ for (LP2Rule r : ruleList) {
+ if (r.getPreFillerPattern().size() > maxPreCount)
+ maxPreCount = r.getPreFillerPattern().size();
+ if (r.getPostFillerPattern().size() > maxPostCount)
+ maxPostCount = r.getPostFillerPattern().size();
+ }
+
+ for (int i = 0; i < maxPreCount; i++) {
+ LP2RuleItem newItem = new LP2RuleItem();
+ for (LP2Rule r : ruleList)
+ if (i < r.getPreFillerPattern().size()) {
+ LP2RuleItem rItem = (LP2RuleItem) r.getPreFillerPattern().get(
+ r.getPreFillerPattern().size() - i - 1);
+ if (rItem.getWordConstraint() != null)
+ newItem.setWordConstraint(rItem.getWordConstraint().copy());
+ if (rItem.getContextConstraint() != null)
+ newItem.setContextConstraint(rItem.getContextConstraint().copy());
+ // for (String key : rItem.getOtherConstraints().keySet())
+ // newItem.setOtherConstraint(key,
+ // rItem.getOtherConstraints().get(key).copy());
+ for (MLLP2OtherConstraint c : rItem.getOtherConstraints())
+ newItem.addOtherConstraint(c.copy());
+
+ }
+ rule.addPreFillerItem(newItem);
+ }
+
+ for (int i = 0; i < maxPostCount; i++) {
+ LP2RuleItem newItem = new LP2RuleItem();
+ for (LP2Rule r : ruleList)
+ if (i < r.getPostFillerPattern().size()) {
+ LP2RuleItem rItem = (LP2RuleItem) r.getPostFillerPattern().get(i);
+ if (rItem.getWordConstraint() != null)
+ newItem.setWordConstraint(rItem.getWordConstraint().copy());
+ if (rItem.getContextConstraint() != null)
+ newItem.setContextConstraint(rItem.getContextConstraint().copy());
+ // for (String key : rItem.getOtherConstraints().keySet())
+ // newItem.setOtherConstraint(key,
+ // rItem.getOtherConstraints().get(key).copy());
+ for (MLLP2OtherConstraint c : rItem.getOtherConstraints())
+ newItem.addOtherConstraint(c.copy());
+ }
+ rule.addPostFillerItem(newItem);
+ }
+
+ rule.setCoveringStatistics(covering.copy());
+
+ return rule;
+ }
+
+ protected boolean recursiveCreateAllRuleCombinations(final List<LP2Rule> startRules,
+ final List<LP2Rule> ctxStartRules, final int index, final List<LP2Rule> currentRuleTuple,
+ final TextRulerStatisticsCollector currentCovering, final List<LP2Rule> debugRuleCollector) {
+ if (index > startRules.size() - 1) {
+ if (shouldAbort())
+ return false;
+ if (currentRuleTuple.size() > 0) {
+ LP2Rule newRule = createAndCheckRuleFromStartRules(currentRuleTuple, currentCovering,
+ ctxStartRules);
+ if (debugRuleCollector != null)
+ debugRuleCollector.add(newRule);
+ }
+ } else {
+ // recurse WITHOUT and WITH this start rule:
+ if (!recursiveCreateAllRuleCombinations(startRules, ctxStartRules, index + 1,
+ currentRuleTuple, currentCovering, debugRuleCollector))
+ return false;
+
+ // only recurse WITH this rule, if the constraint it adds does
+ // really create a new rule!
+ // if a word constraint of the same item is already present, we do
+ // not need to add any other constraint of that
+ // token, since it does not make sense to add more constraints to
+ // the obviously most specific rule !
+
+ LP2Rule candidateRule = startRules.get(index);
+ boolean isPre = candidateRule.isPreFillerStartRule();
+ boolean containsWordConstraint = false;
+ for (LP2Rule r : currentRuleTuple)
+ if (r.isPreFillerStartRule() == isPre) {
+ if (isPre)
+ containsWordConstraint = r.getPreFillerPattern().size() == candidateRule
+ .getPreFillerPattern().size();
+ else
+ containsWordConstraint = r.getPostFillerPattern().size() == candidateRule
+ .getPostFillerPattern().size();
+ if (containsWordConstraint)
+ break;
+ }
+ if (!containsWordConstraint) {
+ // and calculate intersection of coverings:
+ TextRulerStatisticsCollector newCovering;
+ if (currentCovering != null)
+ newCovering = getCoveringIntersection(currentCovering, candidateRule
+ .getCoveringStatistics());
+ else
+ newCovering = candidateRule.getCoveringStatistics();
+
+ // prune all rules that go below our minCoveredPositives
+ // threshold!
+ if (newCovering.getCoveredPositivesCount() >= minCoveredPositives) {
+ // add rule to configuration tuple
+ currentRuleTuple.add(candidateRule);
+
+ if (!recursiveCreateAllRuleCombinations(startRules, ctxStartRules, index + 1,
+ currentRuleTuple, newCovering, debugRuleCollector))
+ return false;
+ currentRuleTuple.remove(currentRuleTuple.size() - 1);
+ }
+ }
+ }
+ return true;
+ }
+
+ protected TextRulerStatisticsCollector getCoveringIntersection(
+ final TextRulerStatisticsCollector c1, final TextRulerStatisticsCollector c2) {
+ // calculate intersections of coverings:
+ TextRulerStatisticsCollector resultC = new TextRulerStatisticsCollector(c1);
+
+ resultC.getCoveredPositiveExamples().retainAll(c2.getCoveredPositiveExamples());
+ resultC.getCoveredNegativeExamples().retainAll(c2.getCoveredNegativeExamples());
+ resultC.reflectCountsFromCoveredExamples();
+
+ return resultC;
+ }
+
+ protected LP2Rule createAndCheckRuleFromStartRules(final List<LP2Rule> startRules,
+ final TextRulerStatisticsCollector covering, final List<LP2Rule> ctxStartRules) {
+ LP2Rule newRule = combineRulesToOneRule(startRules, covering);
+ // TextRulerToolkit.log("COMBINED RULE: "+newRule.getRuleString()+" ; "+newRule.getCoveringStatistics());
+ boolean tooFewPositives = newRule.getCoveringStatistics().getCoveredPositivesCount() < minCoveredPositives;
+ boolean tooManyErrors = newRule.getErrorRate() > maxErrorThreshold;
+ boolean isBestRule = !(tooFewPositives || tooManyErrors);
+
+ if (TextRulerToolkit.DEBUG && SAVE_DEBUG_INFO_IN_TEMPFOLDER)
+ TextRulerToolkit.appendStringToFile(tempDirectory() + "bestcandidates.tm", newRule
+ .getRuleString()
+ + "\n");
+
+ if (isBestRule) {
+ currentBestRules.add(newRule);
+ currentBestRules.removeSubsumedRules();
+ currentBestRules.cutToMaxSize();
+ } else if (!tooFewPositives && (ctxStartRules.size() > 0)) {
+ // new: use precalculated ctx startrules:
+ for (LP2Rule ctxStartRule : ctxStartRules) {
+
+ MLLP2ContextConstraint ctxConstraint = ctxStartRule.getMarkingRuleItem()
+ .getContextConstraint();
+ LP2Rule newCTXRule = newRule.copy();
+ newCTXRule.setIsContextualRule(true);
+ newCTXRule.getMarkingRuleItem().setContextConstraint(ctxConstraint.copy());
+ newCTXRule.setNeedsCompile(true);
+ newCTXRule.compileRuleString();
+ newCTXRule.setCoveringStatistics(getCoveringIntersection(newRule.getCoveringStatistics(),
+ ctxStartRule.getCoveringStatistics()));
+ // if
+ // (newCTXRule.getCoveringStatistics().getCoveredPositivesCount()
+ // < 1)
+ // {
+ // TextRulerToolkit.log("ERROR!");
+ // }
+
+ boolean ctxTooFewPositives = newCTXRule.getCoveringStatistics().getCoveredPositivesCount() < minCoveredPositives;
+ boolean ctxTooManyErrors = newCTXRule.getErrorRate() > maxErrorThreshold;
+ boolean isGoodCTXRule = !(ctxTooFewPositives || ctxTooManyErrors);
+ // TextRulerToolkit.log("CTXRULE : "+newCTXRule.getRuleString()
+ // + " ; "+newCTXRule.getCoveringStatistics());
+
+ if (TextRulerToolkit.DEBUG && SAVE_DEBUG_INFO_IN_TEMPFOLDER)
+ TextRulerToolkit.appendStringToFile(tempDirectory() + "ctxcandidates.tm", newCTXRule
+ .getRuleString()
+ + "\n");
+
+ if (isGoodCTXRule) {
+ currentContextualRules.add(newCTXRule);
+ currentContextualRules.removeSubsumedRules();
+ currentContextualRules.cutToMaxSize();
+ }
+ }
+ }
+
+ return newRule;
+ }
+
+ protected LP2Rule createStartRuleForConstraint(final TextRulerTarget target,
+ final int contextSize, final boolean isLeftContext, final LP2RuleItem constraintItem) {
+ LP2Rule newRule = new LP2Rule(this, target);
+
+ // add contextSize-1 ANY items
+ for (int j = 0; j < contextSize - 1; j++)
+ if (isLeftContext)
+ newRule.addPreFillerItem(new LP2RuleItem());
+ else
+ newRule.addPostFillerItem(new LP2RuleItem());
+
+ // add 1 constraint item:
+ if (isLeftContext)
+ newRule.addPreFillerItem(constraintItem);
+ else
+ newRule.addPostFillerItem(constraintItem);
+
+ // if we are building the left context start rules for LEFT BOUNDARIES,
+ // we need at least ONE
+ // empty ANY item as the marking item:
+ if (isLeftContext
+ && (target.type == MLTargetType.SINGLE_LEFT_BOUNDARY || target.type == MLTargetType.SINGLE_LEFT_CORRECTION))
+ newRule.addPostFillerItem(new LP2RuleItem());
+ // otherwise, if we build the right context rules for RIGHT BOUNDARY
+ // RULES, we need at least ONE
+ // empty ANY item on the LEFT as the marking item:
+ else if (!isLeftContext
+ && (target.type == MLTargetType.SINGLE_RIGHT_BOUNDARY || target.type == MLTargetType.SINGLE_RIGHT_CORRECTION))
+ newRule.addPreFillerItem(new LP2RuleItem());
+
+ newRule.setIsPreFillerStartRule(isLeftContext);
+ // if (isLeftContext)
+ // newRule.setStartRuleItemIndex(0);
+ // else
+ // newRule.setStartRuleItemIndex(newRule.getPreFillerPattern().size()+newRule.getPostFillerPattern().size()-1);
+ return newRule;
+ }
+
+ protected List<LP2Rule> createContextStartRulesForStartRule(final LP2Rule aStartRule) {
+ List<LP2Rule> result = new ArrayList<LP2Rule>();
+
+ // TODO make all other tags contextual tags here. for now we take only
+ // the counterpart
+ // tag of the current learning process: (opening/closing tags)
+
+ LP2RuleItem ctxItem = new LP2RuleItem();
+ MLLP2ContextConstraint ctxConstraint = new MLLP2ContextConstraint(slotMaximumTokenCount,
+ aStartRule);
+ ctxItem.setContextConstraint(ctxConstraint);
+ LP2Rule ctxStartRule = new LP2Rule(this, aStartRule.getTarget());
+ ctxStartRule.setIsContextualRule(true);
+ if (aStartRule.getTarget().type == MLTargetType.SINGLE_LEFT_BOUNDARY)
+ ctxStartRule.addPostFillerItem(ctxItem);
+ else
+ ctxStartRule.addPreFillerItem(ctxItem);
+ result.add(ctxStartRule);
+ return result;
+ }
+
+ protected List<LP2Rule> createStartRulesForExample(final TextRulerExample example) {
+ TextRulerTarget target = example.getTarget();
+ List<LP2Rule> result = new ArrayList<LP2Rule>();
+ CAS docCas = example.getDocumentCAS();
+ TextRulerAnnotation exampleAnnotation = example.getAnnotation();
+ TypeSystem ts = docCas.getTypeSystem();
+ Type tokensRootType = ts.getType(TextRulerToolkit.TM_ANY_TYPE_NAME);
+
+ boolean isLeftBoundary = (target.type == MLTargetType.SINGLE_LEFT_BOUNDARY || target.type == MLTargetType.SINGLE_LEFT_CORRECTION);
+ int thePosition = isLeftBoundary ? exampleAnnotation.getBegin() : exampleAnnotation.getEnd();
+ List<AnnotationFS> leftContext = TextRulerToolkit.getAnnotationsBeforePosition(docCas,
+ thePosition, windowSize, TextRulerToolkit.getFilterSetWithSlotNames(slotNames,
+ filterSet), tokensRootType);
+
+ List<AnnotationFS> rightContext;
+ if (target.type == MLTargetType.SINGLE_LEFT_CORRECTION
+ || target.type == MLTargetType.SINGLE_RIGHT_CORRECTION) {
+ rightContext = TextRulerToolkit.getAnnotationsAfterPosition(docCas, thePosition,
+ windowSize + 1, TextRulerToolkit.getFilterSetWithSlotNames(slotNames, filterSet),
+ tokensRootType);
+ rightContext.remove(0);
+ } else {
+ rightContext = TextRulerToolkit.getAnnotationsAfterPosition(docCas, thePosition, windowSize,
+ TextRulerToolkit.getFilterSetWithSlotNames(slotNames, filterSet), tokensRootType);
+ }
+
+ int totalCount = leftContext.size() + rightContext.size();
+
+ // LEFT CONTEXT (PRE FILLER PATTERN)
+ // result.add(createStartRuleForConstraint(example, 0, true, null));
+
+ for (int index = 0; index < totalCount; index++) {
+ boolean isPre = index < leftContext.size();
+ int prePostIndex = isPre ? index : index - leftContext.size();
+ AnnotationFS tokenAFS = isPre ? leftContext.get(leftContext.size() - 1 - prePostIndex)
+ : rightContext.get(prePostIndex);
+ TextRulerAnnotation tokenAnnotation = new TextRulerAnnotation(tokenAFS, example.getDocument());
+ LP2RuleItem wordItem = new LP2RuleItem();
+
+ // one rule with only the word constraint:
+ wordItem.setWordConstraint(tokenAnnotation);
+ result.add(createStartRuleForConstraint(example.getTarget(), prePostIndex + 1, isPre,
+ wordItem));
+
+ if (wordItem.getWordConstraint().isRegExpConstraint()) {
+ LP2RuleItem basicItem = new LP2RuleItem();
+ // basicItem.setOtherConstraint("basicTM", new
+ // MLLP2OtherConstraint(tokenAnnotation, tokenAnnotation));
+ basicItem.addOtherConstraint(new MLLP2OtherConstraint(tokenAnnotation, tokenAnnotation));
+ result.add(createStartRuleForConstraint(example.getTarget(), prePostIndex + 1, isPre,
+ basicItem));
+ }
+
+ // // POS-Tags created by our test hmm tagger.
+ // Type posTagsRootType = ts.getType("de.uniwue.ml.ML.postag");
+ // if (posTagsRootType != null)
+ // {
+ // List<AnnotationFS> posTagAnnotations =
+ // TextRulerToolkit.getAnnotationsWithinBounds(example.getDocumentCAS(),
+ // tokenAnnotation.getBegin(), tokenAnnotation.getEnd(), null,
+ // posTagsRootType);
+ // if (posTagAnnotations.size()>0)
+ // {
+ // if (TextRulerToolkit.DEBUG && posTagAnnotations.size()>1)
+ // {
+ // TextRulerToolkit.logIfDebug("HOW CAN ONE TOKEN HAVE MORE THAN ONE POS TAG ?? "+tokenAnnotation.getBegin()+":"+tokenAnnotation.getEnd()+"="+tokenAnnotation.getCoveredText());
+ // for (AnnotationFS afs : posTagAnnotations)
+ // {
+ // System.out.print(afs.getType().getShortName()+":"+afs.getCoveredText()+" "+afs.getBegin()+":"+afs.getEnd()+"\n");
+ // }
+ // TextRulerToolkit.logIfDebug("");
+ // }
+ //
+ // TextRulerAnnotation posTagAnnotation = new
+ // TextRulerAnnotation(posTagAnnotations.get(0),
+ // example.getDocument());
+ // LP2RuleItem basicItem = new LP2RuleItem();
+ // basicItem.setOtherConstraint("postag", new
+ // MLLP2OtherConstraint(posTagAnnotation, posTagAnnotation));
+ // result.add(createStartRuleForConstraint(example.getTarget(),
+ // prePostIndex+1, isPre, basicItem));
+ // }
+ // }
+
+ // new dynamic system: grab everything we get from the annotation
+ // index that lies over this token:
+ // (annotations WITHIN (with smaller bounds than the token itself)
+ // are ignored for now! we could
+ // add using them with the CONTAINS constraint. but our
+ // MLLP2OtherConstraint is not yet capable of this!
+
+ List<AnnotationFS> featureAnnotations = TextRulerToolkit.getNonTMAnnoationsOverToken(docCas,
+ tokenAFS, filterSetWithSlotNames);
+ if (TextRulerToolkit.DEBUG && featureAnnotations.size() > 1) {
+ TextRulerToolkit.log("FOUND MORE THAN ONE EXTRA TOKEN FEATURE ANNOTATION !");
+ for (AnnotationFS featA : featureAnnotations)
+ TextRulerToolkit.log(featA.toString());
+ TextRulerToolkit.log("--------------------------------");
+ }
+ for (AnnotationFS featA : featureAnnotations) {
+ TextRulerAnnotation featureAnnot = new TextRulerAnnotation(featA, example.getDocument());
+ LP2RuleItem basicItem = new LP2RuleItem();
+ basicItem.addOtherConstraint(new MLLP2OtherConstraint(tokenAnnotation, featureAnnot));
+ result.add(createStartRuleForConstraint(example.getTarget(), prePostIndex + 1, isPre,
+ basicItem));
+ }
+
+ }
+
+ // for (TextRulerRule r : result)
+ // {
+ // TextRulerToolkit.log("STARTRULE = "+r.getRuleString());
+ // }
+
+ return result;
+ }
+
+ @Override
+ public boolean collectNegativeCoveredInstancesWhenTesting() {
+ return true;
+ }
+
+}
Propchange: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/OptimizedLP2.java
------------------------------------------------------------------------------
svn:executable = *
Propchange: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/OptimizedLP2.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/OptimizedLP2Factory.java
URL: http://svn.apache.org/viewvc/uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/OptimizedLP2Factory.java?rev=1152792&view=auto
==============================================================================
--- uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/OptimizedLP2Factory.java (added)
+++ uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/OptimizedLP2Factory.java Mon Aug 1 14:21:12 2011
@@ -0,0 +1,52 @@
+package org.apache.uima.tm.textruler.lp2;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.uima.tm.textruler.extension.TextRulerLearner;
+import org.apache.uima.tm.textruler.extension.TextRulerLearnerDelegate;
+import org.apache.uima.tm.textruler.extension.TextRulerLearnerFactory;
+import org.apache.uima.tm.textruler.extension.TextRulerLearnerParameter;
+import org.apache.uima.tm.textruler.extension.TextRulerLearnerParameter.MLAlgorithmParamType;
+
+public class OptimizedLP2Factory implements TextRulerLearnerFactory {
+
+ public TextRulerLearner createAlgorithm(String inputFolderPath, String additionalFolderPath,
+ String prePropTMFile, String tempFolderPath, String[] fullSlotTypeNames,
+ Set<String> filterSet, TextRulerLearnerDelegate delegate) {
+ return new OptimizedLP2(inputFolderPath, prePropTMFile, tempFolderPath, fullSlotTypeNames,
+ filterSet, delegate);
+ }
+
+ public TextRulerLearnerParameter[] getAlgorithmParameters() {
+ TextRulerLearnerParameter[] result = new TextRulerLearnerParameter[5];
+
+ result[0] = new TextRulerLearnerParameter(BasicLP2.WINDOW_SIZE_KEY,
+ "Context Window Size (to the left and right)", MLAlgorithmParamType.ML_INT_PARAM);
+ result[1] = new TextRulerLearnerParameter(BasicLP2.CURRENT_BEST_RULES_SIZE_KEY,
+ "Best Rules List Size", MLAlgorithmParamType.ML_INT_PARAM);
+ result[2] = new TextRulerLearnerParameter(BasicLP2.MIN_COVERED_POSITIVES_PER_RULE_KEY,
+ "Minimum Covered Positives per Rule", MLAlgorithmParamType.ML_INT_PARAM);
+ result[3] = new TextRulerLearnerParameter(BasicLP2.MAX_ERROR_THRESHOLD_KEY,
+ "Maximum Error Threshold", MLAlgorithmParamType.ML_FLOAT_PARAM);
+ result[4] = new TextRulerLearnerParameter(BasicLP2.CURRENT_CONTEXTUAL_RULES_SIZE_KEY,
+ "Contextual Rules List Size", MLAlgorithmParamType.ML_INT_PARAM);
+
+ return result;
+ }
+
+ public Map<String, Object> getAlgorithmParameterStandardValues() {
+ Map<String, Object> result = new HashMap<String, Object>();
+ result.put(BasicLP2.WINDOW_SIZE_KEY, BasicLP2.STANDARD_WINDOW_SIZE);
+ result
+ .put(BasicLP2.CURRENT_BEST_RULES_SIZE_KEY,
+ BasicLP2.STANDARD_MAX_CURRENT_BEST_RULES_COUNT);
+ result.put(BasicLP2.MIN_COVERED_POSITIVES_PER_RULE_KEY,
+ BasicLP2.STANDARD_MIN_COVERED_POSITIVES_PER_RULE);
+ result.put(BasicLP2.MAX_ERROR_THRESHOLD_KEY, BasicLP2.STANDARD_MAX_ERROR_THRESHOLD);
+ result.put(BasicLP2.CURRENT_CONTEXTUAL_RULES_SIZE_KEY,
+ BasicLP2.STANDARD_MAX_CONTEXTUAL_RULES_COUNT);
+ return result;
+ }
+}
Propchange: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/OptimizedLP2Factory.java
------------------------------------------------------------------------------
svn:executable = *
Propchange: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/OptimizedLP2Factory.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/OptimizedLP2PreferencePage.java
URL: http://svn.apache.org/viewvc/uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/OptimizedLP2PreferencePage.java?rev=1152792&view=auto
==============================================================================
--- uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/OptimizedLP2PreferencePage.java (added)
+++ uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/OptimizedLP2PreferencePage.java Mon Aug 1 14:21:12 2011
@@ -0,0 +1,101 @@
+package org.apache.uima.tm.textruler.lp2;
+
+import java.util.ArrayList;
+import java.util.Map;
+
+import org.apache.uima.tm.textruler.TextRulerPlugin;
+import org.apache.uima.tm.textruler.extension.TextRulerController;
+import org.apache.uima.tm.textruler.extension.TextRulerLearnerController;
+import org.apache.uima.tm.textruler.extension.TextRulerLearnerFactory;
+import org.apache.uima.tm.textruler.extension.TextRulerLearnerParameter;
+import org.eclipse.jface.preference.BooleanFieldEditor;
+import org.eclipse.jface.preference.FieldEditor;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferencePage;
+import org.eclipse.jface.preference.StringFieldEditor;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+
+public class OptimizedLP2PreferencePage extends PreferencePage implements IWorkbenchPreferencePage {
+
+ public static String ID = "org.apache.uima.tm.textruler.algorithmPages";
+
+ private TextRulerLearnerController algorithmController;
+
+ private IPreferenceStore store;
+
+ private ArrayList<FieldEditor> fields = new ArrayList<FieldEditor>();
+
+ public OptimizedLP2PreferencePage() {
+ TextRulerLearnerController ctrl = TextRulerController.getControllerForID("org.apache.uima.tm.textruler.lp2opt");
+ this.algorithmController = ctrl;
+ store = TextRulerPlugin.getDefault().getPreferenceStore();
+ setPreferenceStore(store);
+ }
+
+ @Override
+ protected Control createContents(Composite parent) {
+ Composite top = new Composite(parent, SWT.LEFT);
+ top.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ top.setLayout(new GridLayout());
+
+ TextRulerLearnerFactory f = algorithmController.getFactory();
+ TextRulerLearnerParameter[] params = f.getAlgorithmParameters();
+ Map<String, Object> values = f.getAlgorithmParameterStandardValues();
+ if (params != null) {
+ for (int i = 0; i < params.length; i++) {
+ TextRulerLearnerParameter p = params[i];
+ String id = algorithmController.getID() + "." + p.id;
+ FieldEditor l = null;
+ switch (p.type) {
+ case ML_BOOL_PARAM: {
+ l = new BooleanFieldEditor(id, p.name, top);
+ fields.add(l);
+ store.setDefault(id, (Boolean) values.get(p.id));
+ l.setPreferenceStore(store);
+ l.load();
+ break;
+ }
+
+ case ML_FLOAT_PARAM:
+ case ML_INT_PARAM:
+ case ML_STRING_PARAM: {
+ l = new StringFieldEditor(id, p.name, top);
+ fields.add(l);
+ store.setDefault(id, values.get(p.id).toString());
+ l.setPreferenceStore(store);
+ l.load();
+ break;
+ }
+ case ML_SELECT_PARAM:
+ break;
+ }
+ }
+ }
+ return top;
+ }
+
+ @Override
+ public void init(IWorkbench workbench) {
+ }
+
+ @Override
+ protected void performDefaults() {
+ for (FieldEditor f : fields)
+ f.loadDefault();
+ // super.performDefaults();
+ }
+
+ @Override
+ public boolean performOk() {
+ for (FieldEditor f : fields)
+ f.store();
+ // return super.performOk();
+ return true;
+ }
+}
Propchange: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/OptimizedLP2PreferencePage.java
------------------------------------------------------------------------------
svn:executable = *
Propchange: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.lp2/src/main/java/org/apache/uima/tm/textruler/lp2/OptimizedLP2PreferencePage.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Propchange: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Mon Aug 1 14:21:12 2011
@@ -0,0 +1 @@
+.settings
Added: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/.classpath
URL: http://svn.apache.org/viewvc/uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/.classpath?rev=1152792&view=auto
==============================================================================
--- uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/.classpath (added)
+++ uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/.classpath Mon Aug 1 14:21:12 2011
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src/main/java"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
Propchange: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/.classpath
------------------------------------------------------------------------------
svn:executable = *
Propchange: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/.classpath
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/.project
URL: http://svn.apache.org/viewvc/uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/.project?rev=1152792&view=auto
==============================================================================
--- uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/.project (added)
+++ uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/.project Mon Aug 1 14:21:12 2011
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.apache.uima.tm.textruler.rapier</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
Propchange: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/.project
------------------------------------------------------------------------------
svn:executable = *
Propchange: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/.project
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/META-INF/MANIFEST.MF
URL: http://svn.apache.org/viewvc/uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/META-INF/MANIFEST.MF?rev=1152792&view=auto
==============================================================================
--- uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/META-INF/MANIFEST.MF (added)
+++ uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/META-INF/MANIFEST.MF Mon Aug 1 14:21:12 2011
@@ -0,0 +1,13 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: TextRuler Rapier Plugin
+Bundle-SymbolicName: org.apache.uima.tm.textruler.rapier;singleton:=true
+Bundle-Version: 1.0.0.qualifier
+Bundle-Activator: org.apache.uima.tm.textruler.rapier.RapierPlugin
+Bundle-Vendor: University of Würzburg
+Require-Bundle: org.eclipse.core.runtime,
+ org.apache.uima.tm.textruler,
+ org.apache.uima.runtime;bundle-version="2.3.0",
+ org.eclipse.ui
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Bundle-ActivationPolicy: lazy
Propchange: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/META-INF/MANIFEST.MF
------------------------------------------------------------------------------
svn:executable = *
Propchange: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/META-INF/MANIFEST.MF
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/build.properties
URL: http://svn.apache.org/viewvc/uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/build.properties?rev=1152792&view=auto
==============================================================================
--- uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/build.properties (added)
+++ uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/build.properties Mon Aug 1 14:21:12 2011
@@ -0,0 +1,5 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .,\
+ plugin.xml
Propchange: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/build.properties
------------------------------------------------------------------------------
svn:executable = *
Propchange: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/build.properties
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/plugin.xml
URL: http://svn.apache.org/viewvc/uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/plugin.xml?rev=1152792&view=auto
==============================================================================
--- uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/plugin.xml (added)
+++ uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/plugin.xml Mon Aug 1 14:21:12 2011
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<plugin>
+ <extension
+ point="org.apache.uima.tm.textruler.learners">
+ <learner
+ class="org.apache.uima.tm.textruler.rapier.RapierFactory"
+ id="org.apache.uima.tm.textruler.rapier"
+ name="RAPIER">
+ </learner>
+ </extension>
+ <extension
+ point="org.eclipse.ui.preferencePages">
+ <page
+ category="org.apache.uima.tm.textruler"
+ class="org.apache.uima.tm.textruler.rapier.RapierPreferencePage"
+ id="org.apache.uima.tm.textruler.rapier"
+ name="Rapier">
+ </page>
+ </extension>
+
+</plugin>
Propchange: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/plugin.xml
------------------------------------------------------------------------------
svn:executable = *
Propchange: uima/sandbox/trunk/TextMarker/org.apache.uima.tm.textruler.rapier/plugin.xml
------------------------------------------------------------------------------
svn:mime-type = text/plain