package gannuWSD.algorithms;
import gannuNLP.data.AmbiguousWord;
import gannuNLP.data.Input;
import gannuNLP.data.Sense;
import gannuWSD.graphs.Graph;
import gannuWSD.graphs.GraphHandler;
import gannuWSD.graphs.GraphNode;
import gannuWSD.testing.Decision;
import java.util.ArrayList;
/**
* Conceptual density algorithm as proposed by Agirre and Rigau
* in "Word Sense Disambiguation using Conceptual Density".
* We also used "Map-based vs. knowledge-based toponym disambiguation"
* from Buscaldi and Rosso as additional reference for conceptual density calculation.
* You can specify the following parameters: <br/>
* <ul>
* <li>depth: Maximum depth for the generated semantic netowork.</li>
* <li>allPos: Flag that tells is this algorithms is going to disambiguate all the open-class words and not only nouns.</li>
* <li>relations: Sets of valid relationships used when expanding the tree.
* E.G. "relations:Hypernym|Hyponym" will create a tree by using only these relationships.</li>
* </ul>
* @author Francisco Viveros-Jiménez
*
*/
public class ConceptualDensity extends WSDAlgorithm {
/**
* Object for loading the semantic networks.
*/
GraphHandler graphs;
/**
* List of valid relationships used when generating the semantic network.
*/
ArrayList<String> relations;
/**
* Maximum depth allowed when generating the semantic network.
*/
int depth;
/**
* Flag that tells is this algorithms is going to disambiguate all the open-class words and not only nouns.
*/
boolean allPos;
/**
* List used by the IsUseful method as a cache for semantic networks.
*/
ArrayList<Graph> cache;
/**
* Cache object for the IsUseful method.
* It contains the word from which all the this.cache graph where generated.
*/
AmbiguousWord lastWord;
public ConceptualDensity()
{
super();
this.name="ConceptualDensity";
this.cache=new ArrayList<Graph>();
this.lastWord=null;
this.graphs=null;
}
@Override
public Decision disambiguate(AmbiguousWord target, ArrayList<AmbiguousWord> window) throws Exception
{
ArrayList<Sense> senses=target.getSenses();
System.out.print(".");
Decision decision=new Decision(target,window);
int i;
ArrayList<Sense> relevantSynsets=new ArrayList<Sense>();
for(AmbiguousWord word:window)
{
relevantSynsets.addAll(word.getSenses());
}
for(i=0;i<senses.size()&&(target.getPos().equals("N")||this.allPos);i++)
{
Graph g=this.graphs.loadGraph(senses.get(i), this.dict);
g.prune(relations, depth);
double w=0.0d;
double m=0.0d;
ArrayList<String> dwords=new ArrayList<String>();
for(Sense s:relevantSynsets)
{
GraphNode gn=g.get(s, depth, relations);
if(gn!=null)
{
dwords.add(s.getSynonyms().get(0));
m+=1.0d;
}
}
w=Math.pow(m, 0.1)*Math.pow(m/((double)g.getNodes().size()),Math.log(((double)i)+1.0d));
decision.setSense(i, w, dwords);
}
decision.calculateAnswer();
return decision;
}
@Override
public void init(Input document) throws Exception{
if(document!=null)
System.out.println("\nDisambiguating "+document.toString());
this.graphs=new GraphHandler(this.dict);
this.relations=new ArrayList<String>();
if(this.getValue("relations")==null)
{
this.relations.add("Hypernym");
this.relations.add("Instance Hypernym");
this.relations.add("Hyponym");
this.relations.add("Instance Hyponym");
}
else
{
for(String rel:this.getValue("relations").split("\\|"))
{
this.relations.add(rel);
}
}
if(this.getValue("depth")==null)
{
this.depth=4;
}
else
{
this.depth=Integer.parseInt(this.getValue("depth"));
}
if(this.getValue("allPos")==null)
{
this.allPos=false;
}
else
{
this.allPos=Boolean.parseBoolean(this.getValue("allPos"));
}
if(this.graphs==null)
this.graphs=new GraphHandler(this.dict);
}
@Override
public boolean IsUseful(AmbiguousWord target, AmbiguousWord windowWord)
throws Exception {
if(!target.equals(this.lastWord))
{
this.lastWord=target;
this.cache.clear();
for(Sense sense:target.getSenses())
{
this.cache.add(this.graphs.loadGraph(sense, dict));
this.cache.get(this.cache.size()-1).prune(relations, depth);
}
}
for(Graph g:this.cache)
{
for(Sense s:windowWord.getSenses())
{
GraphNode gn=g.get(s, depth, "all");
if(gn!=null)
{
return true;
}
}
}
return false;
}
}