package FOM;
import java.util.Iterator;
import java.lang.Math;
import java.util.ArrayList;
public class Taxonomy<E> implements Iterable<E>{
private double[][] relations;
private ArrayList<E> concepts;
public Taxonomy(int size){
relations = new double[size][size];
concepts = new ArrayList<E>();
}
public Taxonomy(ArrayList<E> concepts){
this.concepts = concepts;
int size = concepts.size();
relations = new double[size][size];
}
public void setSpecificity(E subConcept, E concept, double specificity){
int i,j;
i = concepts.indexOf(subConcept);
j = concepts.indexOf(concept);
relations[i][j] = specificity;
}
public double getSpecificity(E subConcept, E concept){
int i,j;
i = concepts.indexOf(subConcept);
j = concepts.indexOf(concept);
return relations[i][j];
}
public void taxonomyPruning(){
double distance[][];
int bigNum = 10000;
int i,j,k;
double sumDist;
int numConcepts = concepts.size();
distance = new double[numConcepts][numConcepts];
/* conservo solo le relazioni più forti:
* ovvero la relazione più alta fra rel(i,j) e rel(j,i)
*/
for(i = 0; i < numConcepts; i++){
for(j = i; j < numConcepts; j++){
if( relations[i][j] != relations[j][i])
if( relations[i][j] > relations[j][i])
relations[j][i] = 0;
else
relations[i][j] = 0;
}
}
//inizializzazione
for(i = 0; i < numConcepts; i++)
for(j = 0; j < numConcepts; j++){
// la distanza da un arco a se stesso è 0
if(i == j){
distance[i][j] = 0;
continue;
}
// distance[i][j] è bigNum solo se relations[i][j] <= 0
distance[i][j] = (relations[i][j] > 0) ? relations[i][j]:bigNum;
}
/*
* Ciò che segue è una leggera modifica dell'algoritmo di
* Floyd Warshall per all-pairs shortest path.
*/
for(k = 0; k < numConcepts; k++){
for(i = 0; i < numConcepts; i++){
for (j = 0; j < numConcepts; j++) {
/*
* Questo controllo viene aggiunto per fare in modo che non
* vengano considerati gli archi diretti fra i e j e neanche
* gli archi il cui peso è minore dell'arco diretto quando
* si cerca lo shortest path che li collega: così facendo
* saremo in grado di sapere se esiste un path che non
* comprende archi il cui peso è minore di quello diretto
* e quindi decidere se esso va eliminato o meno.
*/
if(relations[i][k] > relations[i][j] && relations[k][j] > relations[i][j]){
sumDist = distance[i][k] + distance[k][j];
if( sumDist < distance[i][j])
distance[i][j] = sumDist;
}
}
}
}
for(i = 0; i < numConcepts; i++)
for(j = 0; j < numConcepts; j++){
if((distance[i][j] > relations[i][j]) && relations[i][j] > 0){
System.out.println(concepts.get(i) + " - " + concepts.get(j) + " distance: " + distance[i][j] + " relation: " + relations[i][j]);
relations[i][j] = 0;
}
}
/*for(i = 0; i < numConcepts; i++)
for(j = 0; j < numConcepts; j++)
if((distance[i][j] != relations[i][j]) && relations[i][j] > 0)
System.out.println(concepts.get(i) + " - " + concepts.get(j) + " distance: " + distance[i][j] + " relation: " + relations[i][j]);
*/
}
@Override
public Iterator<E> iterator() {
return concepts.iterator();
}
public ArrayList<E> getConcepts(){
return concepts;
}
}