package jmetal.experiments.util;
import jmetal.experiments.Experiment;
import java.io.*;
import java.util.Arrays;
import java.util.StringTokenizer;
import java.util.Vector;
public class Friedman {
private Experiment exp_;
public Friedman(Experiment exp){
exp_ = exp;
}
public void executeTest(String indic){
Vector algoritmos;
Vector datasets;
Vector datos;
String cadena = "";
StringTokenizer lineas;
String linea;
int i, j, k;
int posicion;
double mean[][];
Pareja orden[][];
Pareja rank[][];
boolean encontrado;
int ig;
double sum;
boolean visto[];
Vector porVisitar;
double Rj[];
double friedman;
double sumatoria=0;
double termino1, termino2;
String indicator_ = indic;
/*Read the result file*/
String outDir = exp_.experimentBaseDirectory_ + "/latex";
String outFile = outDir +"/FriedmanTest"+indicator_+".tex";
String Output = "";
Output = Output + ("\\documentclass{article}\n" +
"\\usepackage{graphicx}\n" +
"\\title{Results}\n" +
"\\author{}\n" +
"\\date{\\today}\n" +
"\\begin{document}\n" +
"\\oddsidemargin 0in \\topmargin 0in" +
"\\maketitle\n" +
"\\section{Tables of Friedman Tests}");
algoritmos = new Vector();
datasets = new Vector();
datos = new Vector();
for(int alg = 0; alg<exp_.algorithmNameList_.length; alg++){
algoritmos.add(new String(exp_.algorithmNameList_[alg]));
datos.add(new Vector());
String rutaAlg = exp_.experimentBaseDirectory_ + "/data/"
+ exp_.algorithmNameList_[alg] + "/";
for(int prob = 0; prob<exp_.problemList_.length; prob++){
if(alg == 0){
datasets.add(exp_.problemList_[prob]);
}
String ruta = rutaAlg + exp_.problemList_[prob] + "/" + indicator_;
//Leemos el fichero
cadena = "";
try {
FileInputStream fis = new FileInputStream(ruta);
byte[] leido = new byte[4096];
int bytesLeidos = 0;
while (bytesLeidos != -1) {
bytesLeidos = fis.read(leido);
if (bytesLeidos != -1) {
cadena += new String(leido, 0, bytesLeidos);
}
}
fis.close();
}
catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
lineas = new StringTokenizer (cadena,"\n\r");
double valor = 0.0;
int n = 0;
while (lineas.hasMoreTokens()) {
linea = lineas.nextToken();
valor = valor + Double.parseDouble(linea);
n++;
}
if(n!=0){
((Vector)datos.elementAt(alg)).add(new Double(valor/n));
}else{
((Vector)datos.elementAt(alg)).add(new Double(valor));
}
} // for
} // for
/*Compute the average performance per algorithm for each data set*/
mean = new double[datasets.size()][algoritmos.size()];
for (j=0; j<algoritmos.size(); j++) {
for (i=0; i<datasets.size(); i++) {
mean[i][j] = ((Double)((Vector)datos.elementAt(j)).elementAt(i)).doubleValue();
}
}
/*We use the pareja structure to compute and order rankings*/
orden = new Pareja[datasets.size()][algoritmos.size()];
for (i=0; i<datasets.size(); i++) {
for (j=0; j<algoritmos.size(); j++){
orden[i][j] = new Pareja (j,mean[i][j]);
}
Arrays.sort(orden[i]);
}
/*building of the rankings table per algorithms and data sets*/
rank = new Pareja[datasets.size()][algoritmos.size()];
posicion = 0;
for (i=0; i<datasets.size(); i++) {
for (j=0; j<algoritmos.size(); j++){
encontrado = false;
for (k=0; k<algoritmos.size() && !encontrado; k++) {
if (orden[i][k].indice == j) {
encontrado = true;
posicion = k+1;
}
}
rank[i][j] = new Pareja(posicion,orden[i][posicion-1].valor);
}
}
/*In the case of having the same performance, the rankings are equal*/
for (i=0; i<datasets.size(); i++) {
visto = new boolean[algoritmos.size()];
porVisitar= new Vector();
Arrays.fill(visto,false);
for (j=0; j<algoritmos.size(); j++) {
porVisitar.removeAllElements();
sum = rank[i][j].indice;
visto[j] = true;
ig = 1;
for (k=j+1;k<algoritmos.size();k++) {
if (rank[i][j].valor == rank[i][k].valor && !visto[k]) {
sum += rank[i][k].indice;
ig++;
porVisitar.add(new Integer(k));
visto[k] = true;
}
}
sum /= (double)ig;
rank[i][j].indice = sum;
for (k=0; k<porVisitar.size(); k++) {
rank[i][((Integer)porVisitar.elementAt(k)).intValue()].indice = sum;
}
}
}
/*compute the average ranking for each algorithm*/
Rj = new double[algoritmos.size()];
for (i=0; i<algoritmos.size(); i++){
Rj[i] = 0;
for (j=0; j<datasets.size(); j++) {
Rj[i] += rank[j][i].indice / ((double)datasets.size());
}
}
/*Print the average ranking per algorithm*/
Output = Output + "\n"+("\\begin{table}[!htp]\n" +
"\\centering\n" +
"\\caption{Average Rankings of the algorithms\n}"+// for "+ exp_.problemList_[prob] +" problem\n}" +
"\\begin{tabular}{c|c}\n" +
"Algorithm&Ranking\\\\\n\\hline");
for (i=0; i<algoritmos.size();i++) {
Output = Output + "\n" + (String)algoritmos.elementAt(i)+"&"+Rj[i]+"\\\\";
}
Output = Output + "\n" +
"\\end{tabular}\n" +
"\\end{table}";
/*Compute the Friedman statistic*/
termino1 = (12*(double)datasets.size())/((double)algoritmos.size()*((double)algoritmos.size()+1));
termino2 = (double)algoritmos.size()*((double)algoritmos.size()+1)*((double)algoritmos.size()+1)/(4.0);
for (i=0; i<algoritmos.size();i++) {
sumatoria += Rj[i]*Rj[i];
}
friedman = (sumatoria - termino2) * termino1;
Output = Output + "\n" + "\n\nFriedman statistic considering reduction performance (distributed according to chi-square with "+(algoritmos.size()-1)+" degrees of freedom: "+friedman+").\n\n";
Output = Output + "\n" + "\\end{document}";
try {
File latexOutput;
latexOutput = new File(outDir);
if(!latexOutput.exists()){
latexOutput.mkdirs();
}
FileOutputStream f = new FileOutputStream(outFile);
DataOutputStream fis = new DataOutputStream((OutputStream) f);
fis.writeBytes(Output);
fis.close();
f.close();
}
catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
}
}