package gannuWSD.graphs;
import gannuNLP.data.AmbiguousWord;
import gannuNLP.data.Relation;
import gannuNLP.data.Sense;
import gannuNLP.dictionaries.Dictionary;
import gannuUtil.Util;
import java.io.Serializable;
import java.util.ArrayList;
/**
* Class for storing and accessing a semantic network.
* @author Francisco Viveros-Jiménez
*
*/
public class Graph implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
/**
* The nodes of this graph. The first node is always the root node.
*/
ArrayList<GraphNode> nodes;
/**
* The relations with which a node was connected to this graph.
*/
ArrayList<String> labels;
/**
* Path for storing the graph into the cache.
*/
String path;
/**
* SenseId of the root node.
*/
String root;
/**
* Name of the source dictionary.
*/
String source;
/**
* @return this.nodes
*/
public ArrayList<GraphNode> getNodes() {
return nodes;
}
/**
*
* @return this.path
*/
public String getPath() {
return path;
}
/**
*
* @return this.root
*/
public String getSense() {
return root;
}
/**
*
* @return this.source
*/
public String getSource()
{
return source;
}
/**
*
* @return All the valid labels in this.labels.
*/
public ArrayList<String> getLabels()
{
return Util.removeDuplicates(labels);
}
/**
* Extracts a graph for an specific sense with a deep of 4 an store it in a file in the "data/graphs/" folder.
* @param sense Target sense.
* @param dict Source dictionary.
* @throws Exception
*/
public Graph(Sense sense,Dictionary dict)throws Exception
{
this.labels=new ArrayList<String>();
this.nodes=new ArrayList<GraphNode>();
this.labels.add("root");
ArrayList<Sense> senses=new ArrayList<Sense>();
senses.add(sense);
this.nodes.add(new GraphNode(sense,1));
this.root=sense.getSid();
this.source=dict.getName();
int index=0;
while(index<this.nodes.size())
{
//System.out.print(String.valueOf(index)+"/"+String.valueOf(this.nodes.size()));
//expand the graph until deep=5
GraphNode g=this.nodes.get(index);
Sense s=senses.get(index);
if(g.getDeep()<4)
{
for(Relation r:s.getPlainRelations("all"))
{
Sense ns=dict.getSense(r.getSid());
int idx=this.nodes.indexOf(new GraphNode(ns,0));
if(idx<0)
{
GraphNode ng=g.addNode(ns,r.getType());
this.nodes.add(ng);
senses.add(ns);
this.labels.add(r.getType());
}
else
{
g.addNode(this.nodes.get(idx),r.getType());
}
}
}
index++;
}
this.labels.trimToSize();
this.nodes.trimToSize();
senses=null;
System.gc();
}
/**
* Returns the desired GraphNode if any.
* @param sense Target sense.
* @param maxDepth Maximum depth for the search.
* @param relation Relation with which the desired sense was added into the graph.
* Use "all" for including all the possible nodes.
* @return The desired GraphNode or null when a node for the target sense is unavailable.
*/
public GraphNode get(Sense sense,int maxDepth,String relation)
{
for(int i=0;i<this.nodes.size();i++)
{
if(relation.equals("all")||this.labels.get(i).equals(relation))
{
GraphNode g=this.nodes.get(i);
if(g.getDeep()<=maxDepth&&g.getSense().equals(sense.getSid()))
return g;
}
}
return null;
}
/**
* Returns the desired GraphNode if any.
* @param sense Target sense.
* @param maxDepth Maximum depth for the search.
* @return The desired GraphNode or null when a node for the target sense is unavailable.
*/
public GraphNode get(Sense sense,int maxDepth)
{
for(int i=0;i<this.nodes.size();i++)
{
GraphNode g=this.nodes.get(i);
if(g.getDeep()<=maxDepth&&g.getSense().equals(sense.getSid()))
return g;
}
return null;
}
/**
* Returns the first GraphNode for a corresponding SenseId in the target list.
* @param senses List of target SenseIds.
* @param maxDepth Maximum depth for the search.
* @return The first GraphNode for a corresponding SenseId in the target list or
* null when a node was not found.
*/
public GraphNode get(ArrayList<String> senses,int maxDepth)
{
for(int i=0;i<this.nodes.size();i++)
{
GraphNode g=this.nodes.get(i);
if(g.getDeep()<=maxDepth&&senses.contains(g.getSense()))
return g;
}
return null;
}
/**
* Removes the nodes from the graph that have relations which are not included
* in the target list.
* @param relations List of valid relations.
* @param maxDepth Maximum depth for the search.
*/
public void prune(ArrayList<String> relations,int maxDepth)
{
for(int i=1;i<this.nodes.size();i++)
{
GraphNode g=this.nodes.get(i);
if(g.getDeep()>maxDepth||(!relations.contains("all")&&!relations.contains(labels.get(i))))
{
this.nodes.remove(i);
this.labels.remove(i);
int c=1;
for(GraphNode n:g.vertices)
{
int index=this.nodes.indexOf(n);
if(index>1)
{
this.nodes.remove(index);
this.labels.remove(index);
c++;
}
}
i-=c;
if(i<1)
i=1;
}
}
}
/**
* Returns the corresponding GraphNode having a parent relation included in the
* target relation list.
* @param senses List of target SenseIds.
* @param maxDepth Maximum depth for the search.
* @param relations List of valid relation list. Add an "all" for using all the possible relations.
* @return The corresponding GraphNode or
* null when a node was not found.
*/
public GraphNode get(Sense sense,int maxDeep,ArrayList<String> relations)
{
boolean ban=relations.contains("all");
for(int i=0;i<this.nodes.size();i++)
{
if(ban||relations.contains(this.labels.get(i)))
{
GraphNode g=this.nodes.get(i);
if(g.getDeep()<=maxDeep&&g.getSense().equals(sense.getSid()))
return g;
}
}
return null;
}
/**
* Returns the degree of the root node.
* The graph is pruned by excluding the vertices that do not lead to a sense of the window.
* Also, the nodes not having a valid relation listed on the relation lists.
* @param window List of words which senses indicate the valid paths for calculating the degree.
* @param maxDepth Maximum depth for the search.
* @param relations List of valid relation list. Add an "all" for using all the possible relations.
* @return The degree of the root node.
* @throws Exception
*/
public double getRootDegree(ArrayList<AmbiguousWord> window, int maxDepth, ArrayList<String> relations) throws Exception {
ArrayList<GraphNode> backwards=new ArrayList<GraphNode>();
for(AmbiguousWord word:window)
for(Sense sense:word.getSenses())
{
GraphNode g=this.get(sense, maxDepth);
if(g!=null)
backwards.add(g);
}
ArrayList<GraphNode> good=new ArrayList<GraphNode>();
for(GraphNode g:backwards)
{
ArrayList<GraphNode> visited=new ArrayList<GraphNode>();
ArrayList<GraphNode> cache=new ArrayList<GraphNode>();
cache.add(g);
while(cache.size()>0)
{
visited.add(cache.get(0));
for(GraphNode nw:cache.get(0).getVertices(relations))
{
if(nw.equals(this.nodes.get(0)))
{
if(!good.contains(cache.get(0)))
{
good.add(cache.get(0));
}
}
else
{
if(!visited.contains(nw)&&nw.getDeep()<=maxDepth&&nw.getDeep()<cache.get(0).getDeep())
{
cache.add(nw);
}
}
}
cache.remove(0);
}
}
return ((double)good.size());
}
}