r65499 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r65498‎ | r65499 | r65500 >
Date:23:07, 23 April 2010
Author:daniel
Status:deferred
Tags:
Comment:
add phrase detection to SlidingCoherenceDisambiguator; QueryConsole is still missing a way to instantiate a PhraseExtractor.
Modified paths:
  • /trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/disambig/CoherenceDisambiguator.java (modified) (history)
  • /trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/disambig/PopularityDisambiguator.java (modified) (history)
  • /trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/disambig/SlidingCoherenceDisambiguator.java (modified) (history)
  • /trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/disambig/Term.java (modified) (history)
  • /trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/model/PhraseOccurance.java (modified) (history)
  • /trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/model/TermMeaning.java (modified) (history)
  • /trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/model/TermReference.java (modified) (history)
  • /trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/query/QueryConsole.java (modified) (history)
  • /trunk/WikiWord/WikiWordBuilder/src/main/java/de/brightbyte/wikiword/analyzer/PlainTextAnalyzer.java (modified) (history)

Diff [purge]

Index: trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/disambig/SlidingCoherenceDisambiguator.java
@@ -7,6 +7,8 @@
88 import java.util.List;
99 import java.util.Map;
1010
 11+import de.brightbyte.data.Functor2;
 12+import de.brightbyte.data.Functors;
1113 import de.brightbyte.data.LabeledMatrix;
1214 import de.brightbyte.data.LabeledVector;
1315 import de.brightbyte.data.MapLabeledMatrix;
@@ -23,20 +25,45 @@
2426 public class SlidingCoherenceDisambiguator extends CoherenceDisambiguator {
2527
2628 protected int window ;
27 - protected boolean runningStart = false;
2829
2930 public SlidingCoherenceDisambiguator(MeaningFetcher<LocalConcept> meaningFetcher, FeatureFetcher<LocalConcept, Integer> featureFetcher, boolean featuresAreNormalized) {
30 - this(meaningFetcher, featureFetcher, WikiWordConcept.theCardinality,
 31+ this(meaningFetcher, featureFetcher, WikiWordConcept.theCardinality, Functors.Double.product2,
3132 featuresAreNormalized ? ScalarVectorSimilarity.<Integer>getInstance() : CosineVectorSimilarity.<Integer>getInstance(), //if pre-normalized, use scalar to calc cosin
3233 5);
3334 }
3435
35 - public SlidingCoherenceDisambiguator(MeaningFetcher<LocalConcept> meaningFetcher, FeatureFetcher<LocalConcept, Integer> featureFetcher, Measure<WikiWordConcept> popularityMeasure, Similarity<LabeledVector<Integer>> sim, int window) {
36 - super(meaningFetcher, featureFetcher, popularityMeasure, sim);
 36+ public SlidingCoherenceDisambiguator(MeaningFetcher<LocalConcept> meaningFetcher, FeatureFetcher<LocalConcept, Integer> featureFetcher, Measure<WikiWordConcept> popularityMeasure, Functor2<? extends Number, Number, Number> weightCombiner, Similarity<LabeledVector<Integer>> sim, int window) {
 37+ super(meaningFetcher, featureFetcher, popularityMeasure, weightCombiner, sim);
3738
3839 this.window = window;
3940 }
4041
 42+ public <X extends TermReference>Result<X, LocalConcept> evalStep(List<X> baseSequence, Map<X, LocalConcept> interpretation, PhraseNode<X> node,
 43+ Map<X, List<? extends LocalConcept>> meanings, Collection<LocalConcept> context,
 44+ LabeledMatrix<LocalConcept, LocalConcept> similarities, FeatureFetcher<LocalConcept, Integer> features) throws PersistenceException {
 45+ X term = node.getTermReference();
 46+
 47+ List<X> sequence = new ArrayList<X>(baseSequence);
 48+ sequence.add(term);
 49+
 50+ int to = sequence.size();
 51+ int from = to - window;
 52+ if (from<0) from = 0;
 53+
 54+ List<X> frame = sequence.subList(from, to);
 55+
 56+ Result<X, LocalConcept> r ;
 57+
 58+ if (to-from < 2) {
 59+ r = popularityDisambiguator.disambiguate(node, frame, meanings, context);
 60+ } else {
 61+ List<Map<X, LocalConcept>> interpretations = getInterpretations(from, to, frame, interpretation, meanings);
 62+ r = getBestInterpretation(node, frame, meanings, context, interpretations, similarities, features);
 63+ }
 64+
 65+ return r;
 66+ }
 67+
4168 /* (non-Javadoc)
4269 * @see de.brightbyte.wikiword.disambig.Disambiguator#disambiguate(java.util.List)
4370 */
@@ -60,41 +87,35 @@
6188 }
6289
6390 //CAVEAT: because the map disambig can contain only one meaning per term, the same term can not occur with two meanings within the same term sequence.
64 -
65 - Map<X, LocalConcept> disambig = new HashMap<X, LocalConcept>(meanings.size());
6691
6792 LabeledMatrix<LocalConcept, LocalConcept> similarities = new MapLabeledMatrix<LocalConcept, LocalConcept>(true);
6893 FeatureFetcher<LocalConcept, Integer> features = getFeatureCache(meanings, context);
 94+
 95+ Map<X, LocalConcept> disambig = new HashMap<X, LocalConcept>(meanings.size());
 96+ PhraseNode<X> currentNode = root;
 97+ List<X> sequence = new ArrayList<X>();
6998
70 - int start = runningStart ? 0 : window;
71 -
72 - for (int i= start; ; i++) {
73 - int from = i-window;
74 - int to = i+1;
 99+ while (true) {
 100+ List<? extends PhraseNode<X>> successors = currentNode.getSuccessors();
 101+ if (successors==null || successors.isEmpty()) break;
75102
76 - if (from<0) from = 0;
77 - if (to>terms.size()) to = terms.size();
 103+ Result<X, LocalConcept> best = null;
 104+ PhraseNode<X> bestNode = null;
78105
79 - Result r ;
80 -
81 - if (to-from < 2) {
82 - r = popularityDisambiguator.disambiguate(root..., terms.subList(from, to), meanings, context);
83 - } else {
84 - List<Map<X, LocalConcept>> interpretations = getInterpretations(from, to, terms, disambig, meanings);
85 - r = getBestInterpretation(terms, meanings, context, interpretations, similarities, features);
 106+ for (PhraseNode<X> n: successors) {
 107+ Result<X, LocalConcept> r = evalStep(sequence, disambig, currentNode, meanings, context, similarities, features);
 108+ if (best == null || best.getScore() < r.getScore()) {
 109+ best = r;
 110+ bestNode = n;
 111+ }
86112 }
87 -
88 - for (int j=from; j<to; j++) {
89 - X t = terms.get(j);
90 - if (disambig.containsKey(t)) continue;
91 -
92 - LocalConcept m;
93 -
94 - m = (LocalConcept)r.getMeanings().get(t); //UGLY cast
95 - if (m!=null) disambig.put(t, m);
96 - }
97113
98 - if (to+1>terms.size()) break;
 114+ X term = bestNode.getTermReference();
 115+ currentNode = bestNode;
 116+ sequence.add(term);
 117+
 118+ LocalConcept meaning = best.getMeanings().get(term);
 119+ disambig.put(term, meaning);
99120 }
100121
101122 return getScore(disambig, context, similarities, features); //FIXME: this is unnecessarily expensive, we usually don't need the scores this calculates.
@@ -128,12 +149,4 @@
129150 return getSequenceInterpretations(terms.subList(from, to), mset);
130151 }
131152
132 - public boolean getRunningStart() {
133 - return runningStart;
134 - }
135 -
136 - public void setRunningStart(boolean runningStart) {
137 - this.runningStart = runningStart;
138 - }
139 -
140153 }
Index: trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/disambig/PopularityDisambiguator.java
@@ -6,6 +6,8 @@
77 import java.util.List;
88 import java.util.Map;
99
 10+import de.brightbyte.data.Functor2;
 11+import de.brightbyte.data.Functors;
1012 import de.brightbyte.data.measure.Measure;
1113 import de.brightbyte.data.measure.Measure.Comparator;
1214 import de.brightbyte.wikiword.model.LocalConcept;
@@ -16,16 +18,18 @@
1719 public class PopularityDisambiguator extends AbstractDisambiguator<TermReference, LocalConcept> {
1820
1921 protected Measure<WikiWordConcept> popularityMeasure;
 22+ protected Functor2<? extends Number, Number, Number> weigthCombiner;
2023 protected Comparator<LocalConcept> popularityComparator;
2124
2225 public PopularityDisambiguator(MeaningFetcher<LocalConcept> meaningFetcher) {
23 - this(meaningFetcher, WikiWordConcept.theCardinality);
 26+ this(meaningFetcher, WikiWordConcept.theCardinality, Functors.Double.product2);
2427 }
2528
26 - public PopularityDisambiguator(MeaningFetcher<LocalConcept> meaningFetcher, Measure<WikiWordConcept> popularityMeasure) {
 29+ public PopularityDisambiguator(MeaningFetcher<LocalConcept> meaningFetcher, Measure<WikiWordConcept> popularityMeasure, Functor2<? extends Number, Number, Number> weightCombiner) {
2730 super(meaningFetcher);
2831
2932 this.setPopularityMeasure(popularityMeasure);
 33+ this.setWeightCombiner(weightCombiner);
3034 }
3135
3236 public Measure<WikiWordConcept> getPopularityMeasure() {
@@ -37,11 +41,17 @@
3842 this.popularityComparator = new Measure.Comparator<LocalConcept>(popularityMeasure, true);
3943 }
4044
 45+ public void setWeightCombiner(Functor2<? extends Number, Number, Number> weightCombiner) {
 46+ this.weigthCombiner = weightCombiner;
 47+ }
 48+
4149 public <X extends TermReference>Result<X, LocalConcept> disambiguate(PhraseNode<X> root, Collection<X> terms, Map<X, List<? extends LocalConcept>> meanings, Collection<LocalConcept> context) {
4250 if (terms.isEmpty() || meanings.isEmpty()) return new Disambiguator.Result<X, LocalConcept>(Collections.<X, LocalConcept>emptyMap(), 0.0, "no terms or meanings");
4351
4452 Map<X, LocalConcept> disambig = new HashMap<X, LocalConcept>();
45 - int pop = 0;
 53+ double score = 0;
 54+ int totalPop = 0;
 55+
4656 for (X t: terms) {
4757 List<? extends LocalConcept> m = meanings.get(t);
4858 if (m==null || m.size()==0) continue;
@@ -51,12 +61,16 @@
5262 LocalConcept c = m.get(0);
5363 disambig.put(t, c);
5464
55 - pop += Math.log(c.getCardinality());
 65+ double pop = popularityMeasure.measure(c);
 66+ totalPop += pop;
 67+
 68+ Number sc = weigthCombiner.apply(pop, t.getWeight());
 69+ score += sc.doubleValue();
5670 }
5771
58 - if (disambig.size()>0) pop = pop / disambig.size();
 72+ if (disambig.size()>0) score = score / disambig.size();
5973
60 - Result<X, LocalConcept> r = new Result<X, LocalConcept>(disambig, pop, "pop="+pop);
 74+ Result<X, LocalConcept> r = new Result<X, LocalConcept>(disambig, score, "score="+score+"; pop="+totalPop);
6175 return r;
6276 }
6377
Index: trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/disambig/CoherenceDisambiguator.java
@@ -12,6 +12,7 @@
1313
1414 import de.brightbyte.data.Functor;
1515 import de.brightbyte.data.Functor2;
 16+import de.brightbyte.data.Functors;
1617 import de.brightbyte.data.LabeledMatrix;
1718 import de.brightbyte.data.LabeledVector;
1819 import de.brightbyte.data.MapLabeledMatrix;
@@ -38,6 +39,7 @@
3940
4041 protected Similarity<LabeledVector<Integer>> similarityMeasure;
4142 protected Measure<WikiWordConcept> popularityMeasure;
 43+ protected Functor2<? extends Number, Number, Number> weightCombiner;
4244 protected PopularityDisambiguator popularityDisambiguator;
4345 protected Comparator<LocalConcept> popularityComparator;
4446
@@ -65,11 +67,11 @@
6668 };
6769
6870 public CoherenceDisambiguator(MeaningFetcher<LocalConcept> meaningFetcher, FeatureFetcher<LocalConcept, Integer> featureFetcher, boolean featuresAreNormalized) {
69 - this(meaningFetcher, featureFetcher, WikiWordConcept.theCardinality,
 71+ this(meaningFetcher, featureFetcher, WikiWordConcept.theCardinality, Functors.Double.product2,
7072 featuresAreNormalized ? ScalarVectorSimilarity.<Integer>getInstance() : CosineVectorSimilarity.<Integer>getInstance()); //if pre-normalized, use scalar to calc cosin
7173 }
7274
73 - public CoherenceDisambiguator(MeaningFetcher<LocalConcept> meaningFetcher, FeatureFetcher<LocalConcept, Integer> featureFetcher, Measure<WikiWordConcept> popularityMeasure, Similarity<LabeledVector<Integer>> sim) {
 75+ public CoherenceDisambiguator(MeaningFetcher<LocalConcept> meaningFetcher, FeatureFetcher<LocalConcept, Integer> featureFetcher, Measure<WikiWordConcept> popularityMeasure, Functor2<? extends Number, Number, Number> weightCombiner, Similarity<LabeledVector<Integer>> sim) {
7476 super(meaningFetcher);
7577
7678 if (popularityMeasure==null) throw new NullPointerException();
@@ -77,9 +79,10 @@
7880 if (featureFetcher==null) throw new NullPointerException();
7981
8082 this.featureCacheManager = new FeatureCache.Manager<LocalConcept, Integer>(featureFetcher, 10); //TODO: depth
81 - this.popularityDisambiguator = new PopularityDisambiguator(meaningFetcher, popularityMeasure);
 83+ this.popularityDisambiguator = new PopularityDisambiguator(meaningFetcher, popularityMeasure, weightCombiner);
8284
8385 this.setPopularityMeasure(popularityMeasure);
 86+ this.setWeightCombiner(weightCombiner);
8487 this.setSimilarityMeasure(sim);
8588 }
8689
@@ -101,6 +104,11 @@
102105 this.popularityComparator = new Measure.Comparator<LocalConcept>(popularityMeasure, true);
103106 }
104107
 108+ public void setWeightCombiner(Functor2<? extends Number, Number, Number> weightCombiner) {
 109+ this.weightCombiner = weightCombiner;
 110+ this.popularityDisambiguator.setWeightCombiner(weightCombiner);
 111+ }
 112+
105113 public Functor2.Double getScoreCombiner() {
106114 return scoreCombiner;
107115 }
@@ -306,23 +314,31 @@
307315 }
308316
309317 protected <X extends TermReference>Result<X, LocalConcept> getScore(Map<X, LocalConcept> interp, Collection<LocalConcept> context, LabeledMatrix<LocalConcept, LocalConcept> similarities, FeatureFetcher<LocalConcept, Integer> features) throws PersistenceException {
310 - double sim = 0;
311 - double pop = 0;
312 -
313 - Collection<LocalConcept> concepts;
 318+ Map<? extends TermReference, LocalConcept> concepts;
314319 if (context!=null) {
315 - concepts = new ArrayList<LocalConcept>();
316 - concepts.addAll(interp.values());
317 - concepts.addAll(context);
 320+ concepts = new HashMap<TermReference, LocalConcept>();
 321+
 322+ for (Map.Entry<X, LocalConcept> e: interp.entrySet()) {
 323+ ((HashMap<TermReference, LocalConcept>)concepts).put(e.getKey(), e.getValue());
 324+ }
 325+
 326+ for (LocalConcept c: context) {
 327+ ((HashMap<TermReference, LocalConcept>)concepts).put(new Term("", 1), c);
 328+ }
318329 } else {
319 - concepts = interp.values();
 330+ concepts = interp;
320331 }
321332
 333+ double sim = 0, pop = 0, weight = 0;
322334 int i=0, j=0, n=0, c=0;
323 - for (LocalConcept a: concepts) {
 335+ for (Map.Entry<? extends TermReference, LocalConcept> ea: concepts.entrySet()) {
 336+ LocalConcept a = ea.getValue();
 337+ TermReference term = ea.getKey();
 338+
324339 i++;
325340 j=0;
326 - for (LocalConcept b: concepts) {
 341+ for (Map.Entry<? extends TermReference, LocalConcept> eb: concepts.entrySet()) {
 342+ LocalConcept b = eb.getValue();
327343 j++;
328344 if (i==j) break;
329345
@@ -357,21 +373,27 @@
358374 }
359375
360376 double p = popularityMeasure.measure(a);
 377+ double w = term.getWeight();
361378 if (p<1) p= 1;
362 - pop += p;
 379+ if (w<1) w= 1;
 380+
 381+ pop += weightCombiner.apply(p, w).doubleValue();
 382+
 383+ weight += w;
363384 c ++;
364385 }
365386
366387 //normalize
367388 sim = sim / n; //normalize
368389 pop = pop / c; //normalize
 390+ weight = weight / c; //normalize
369391
370392 double popf = popularityFactor.apply(pop);
371393 double simf = similarityFactor.apply(sim);
372394
373395 double score = scoreCombiner.apply(popf, simf);
374396
375 - return new Result<X, LocalConcept>(interp, score, "simf="+simf+", popf="+popf+", sim="+sim+", pop="+pop);
 397+ return new Result<X, LocalConcept>(interp, score, "simf="+simf+", popf="+popf+", sim="+sim+", pop="+pop+", weight="+weight);
376398 }
377399
378400 }
Index: trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/disambig/Term.java
@@ -9,16 +9,25 @@
1010 public class Term implements TermReference {
1111
1212 private final String term;
13 -
 13+ private final double weight;
 14+
1415 public Term(final String term) {
15 - super();
 16+ this(term, 1);
 17+ }
 18+
 19+ public Term(final String term, final double weight) {
1620 this.term = term;
 21+ this.weight = weight;
1722 }
1823
1924 public String getTerm() {
2025 return term;
2126 }
2227
 28+ public double getWeight() {
 29+ return weight;
 30+ }
 31+
2332 public String toString() {
2433 return getTerm();
2534 }
Index: trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/model/PhraseOccurance.java
@@ -1,7 +1,6 @@
22 package de.brightbyte.wikiword.model;
33
44 import java.io.Serializable;
5 -import java.util.List;
65
76 public class PhraseOccurance implements Serializable, Comparable<PhraseOccurance>, TermReference {
87
@@ -45,7 +44,7 @@
4645 return getPhrase();
4746 }
4847
49 - public int getWeight() {
 48+ public double getWeight() {
5049 return weight;
5150 }
5251
Index: trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/model/TermMeaning.java
@@ -27,6 +27,10 @@
2828 public double getScore() {
2929 return score;
3030 }
 31+
 32+ public double getWeight() {
 33+ return getScore();
 34+ }
3135
3236 public String getTerm() {
3337 return term;
Index: trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/model/TermReference.java
@@ -3,5 +3,5 @@
44 public interface TermReference {
55
66 public String getTerm();
7 -
 7+ public double getWeight();
88 }
\ No newline at end of file
Index: trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/query/QueryConsole.java
@@ -19,16 +19,23 @@
2020 import de.brightbyte.util.PersistenceException;
2121 import de.brightbyte.wikiword.ConsoleApp;
2222 import de.brightbyte.wikiword.Corpus;
 23+import de.brightbyte.wikiword.TweakSet;
2324 import de.brightbyte.wikiword.disambig.Disambiguator;
 25+import de.brightbyte.wikiword.disambig.PhraseExtractor;
2426 import de.brightbyte.wikiword.disambig.SlidingCoherenceDisambiguator;
2527 import de.brightbyte.wikiword.disambig.StoredFeatureFetcher;
2628 import de.brightbyte.wikiword.disambig.StoredMeaningFetcher;
 29+import de.brightbyte.wikiword.disambig.Term;
2730 import de.brightbyte.wikiword.model.AbstractConceptOutput;
2831 import de.brightbyte.wikiword.model.ConceptFeatures;
2932 import de.brightbyte.wikiword.model.ConceptOutput;
3033 import de.brightbyte.wikiword.model.ConceptRelations;
3134 import de.brightbyte.wikiword.model.GlobalConcept;
3235 import de.brightbyte.wikiword.model.LocalConcept;
 36+import de.brightbyte.wikiword.model.PhraseNode;
 37+import de.brightbyte.wikiword.model.PhraseOccuranceSet;
 38+import de.brightbyte.wikiword.model.TermListNode;
 39+import de.brightbyte.wikiword.model.TermReference;
3340 import de.brightbyte.wikiword.model.WikiWordConcept;
3441 import de.brightbyte.wikiword.rdf.RdfOutput;
3542 import de.brightbyte.wikiword.store.DatabaseConceptStores;
@@ -45,6 +52,7 @@
4653 protected ConceptQuerySpec minimalConceptSpec;
4754 protected ConceptQuerySpec resolvedConceptSpec;
4855 protected ConceptQuerySpec detailedConceptSpec;
 56+ private PhraseExtractor phraseExtractor;
4957
5058 public QueryConsole() {
5159 super(true, true);
@@ -80,6 +88,9 @@
8189 throw new PersistenceException(e);
8290 }
8391 }
 92+
 93+ //FIXME: make the line below possible...
 94+ //phraseExtractor = PlaintextAnalyzer.getPlaintextAnalyzer(getCorpus(), getTweaks());
8495 }
8596
8697 public ConceptOutput getOutput() {
@@ -375,12 +386,8 @@
376387 showFeatureVector(id, out);
377388 }
378389 else if (cmd.equals("d") || cmd.equals("dis") || cmd.equals("disambig") || cmd.equals("disambiguate")) {
379 - List<String> terms = new ArrayList<String>(params.size()-1);
380 - for (Object t: params.subList(1,params.size())) {
381 - terms.add(t.toString());
382 - }
383 -
384 - showDisambiguation(terms, out);
 390+ PhraseNode<? extends TermReference> root = getPhrases(params.get(1).toString());
 391+ showDisambiguation(root, out);
385392 }
386393 else if (cmd.equals("ls") || cmd.equals("list")) {
387394 listConcepts(out);
@@ -391,6 +398,21 @@
392399 }
393400 }
394401
 402+ protected PhraseNode<? extends TermReference> getPhrases(String s) {
 403+ if (s.indexOf('|')>0) {
 404+ String[] ss = s.split("\\s\\|\\s");
 405+ List<Term> terms = new ArrayList<Term>(ss.length);
 406+ for (String t: ss) {
 407+ terms.add(new Term(t));
 408+ }
 409+
 410+ return new TermListNode<Term>(terms, 0);
 411+ } else {
 412+ PhraseOccuranceSet occurances = phraseExtractor.extractPhrases(s, 6);
 413+ return occurances.getRootNode();
 414+ }
 415+ }
 416+
395417 public boolean isGlobalThesaurus() {
396418 return !isDatasetLocal();
397419 }
@@ -499,8 +521,8 @@
500522 out.writeFeatureVector(conceptFeatures.getFeatureVector());
501523 }
502524
503 - public void showDisambiguation(List<String> terms, ConsoleOutput out) throws PersistenceException {
504 - Disambiguator.Result r = getDisambiguator().disambiguate(terms, null);
 525+ public void showDisambiguation(PhraseNode<? extends TermReference> root, ConsoleOutput out) throws PersistenceException {
 526+ Disambiguator.Result r = getDisambiguator().disambiguate(root, null);
505527 out.writeInterpretation(r.getMeanings());
506528 }
507529
Index: trunk/WikiWord/WikiWordBuilder/src/main/java/de/brightbyte/wikiword/analyzer/PlainTextAnalyzer.java
@@ -20,10 +20,11 @@
2121 import de.brightbyte.io.ConsoleIO;
2222 import de.brightbyte.wikiword.Corpus;
2323 import de.brightbyte.wikiword.TweakSet;
 24+import de.brightbyte.wikiword.disambig.PhraseExtractor;
2425 import de.brightbyte.wikiword.model.PhraseOccurance;
2526 import de.brightbyte.wikiword.model.PhraseOccuranceSet;
2627
27 -public class PlainTextAnalyzer extends AbstractAnalyzer {
 28+public class PlainTextAnalyzer extends AbstractAnalyzer implements PhraseExtractor {
2829 private LanguageConfiguration config;
2930
3031 private Matcher sentenceMatcher;

Status & tagging log