/***********************************************************************
This file is part of KEEL-software, the Data Mining tool for regression,
classification, clustering, pattern mining and so on.
Copyright (C) 2004-2010
F. Herrera (herrera@decsai.ugr.es)
L. Sánchez (luciano@uniovi.es)
J. Alcalá-Fdez (jalcala@decsai.ugr.es)
S. García (sglopez@ujaen.es)
A. Fernández (alberto.fernandez@ujaen.es)
J. Luengo (julianlm@decsai.ugr.es)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see http://www.gnu.org/licenses/
**********************************************************************/
/**
* File: Multiple.java
*
* This class performs several statistical comparisons between 1xN methods
*
* @author Written by Joaqu�n Derrac (University of Granada) 29/04/2010
* @version 1.1
* @since JDK1.5
*/
package keel.GraphInterKeel.statistical.tests;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.*;
import keel.GraphInterKeel.statistical.Configuration;
import org.core.*;
public class Friedman {
private static boolean Iman, Nemenyi, Bonferroni, Holm, Hoch, Hommel, Scha, Berg, Holland, Rom, Finner, Li; //post-hoc methods to apply
private static boolean Friedman, Alligned, Quade; //Main methods to apply
/**
* Builder
*/
public Friedman(){
}//end-method
/**
* <p>
* In this method, all possible post hoc statistical test between more than three algorithms results
* are executed, according to the configuration file
* </p>
*/
public static void doFriedman(double data[][], String algorithms[]) {
String outputFileName = Configuration.getPath();
//store type of test
Alligned=false;
Friedman=true;
Quade=false;
String outputString = new String("");
outputString = header();
outputString += runMultiple(data, algorithms);
Files.writeFile(outputFileName, outputString);
}//end-method
/**
* <p>
* In this method, all possible post hoc statistical test between more than three algorithms results
* are executed, according to the configuration file
* </p>
*/
public static void doFriedmanAligned(double data[][], String algorithms[]) {
String outputFileName = Configuration.getPath();
//store type of test
Alligned=true;
Friedman=false;
Quade=false;
String outputString = new String("");
outputString = header();
outputString += runMultiple(data, algorithms);
Files.writeFile(outputFileName, outputString);
}//end-method
/**
* <p>
* In this method, all possible post hoc statistical test between more than three algorithms results
* are executed, according to the configuration file
* </p>
*/
public static void doQuade(double data[][], String algorithms[]) {
String outputFileName = Configuration.getPath();
//store type of test
Alligned=false;
Friedman=false;
Quade=true;
String outputString = new String("");
outputString = header();
outputString += runMultiple(data, algorithms);
Files.writeFile(outputFileName, outputString);
}//end-method
/**
* This method runs the multiple comparison tests
*
* @param results Array with the results of the methods
* @param algorithmName Array with the name of the methods employed
*
* @return A string with the contents of the test in LaTeX format
*/
private static String runMultiple(double[][] results,String algorithmName[]) {
String out="";
int i, j, k, m;
int posicion;
int counter;
double mean[][];
double meanAR[][];
Pair orden[][];
Pair rank[][];
Pair ordenAR[];
Pair rankAR[];
Pair bRank[];
Pair bOrden[];
double diffBlocks[];
boolean encontrado;
int ig;
double sum;
boolean visto[];
Vector <Integer> porVisitar;
double Rj[];
double RjAR[];
double Sj[];
double SMj[];
double min, max;
double friedman;
double sumatoria=0;
double temporal;
double termino1, termino2, termino3;
double numerador, denominador;
double iman;
boolean vistos[];
int pos;
double maxVal, minVal;
double diffMax = 0;
double Pm = 0;
double PmAR = 0;
double PmQ = 0;
double rankingRef;
double Pi[];
double PiAR[];
double PiQ[];
double ALPHAiHolm[];
double ALPHAiHolland[];
double ALPHAiRom[];
double ALPHAiFinner[];
double ALPHA2Li = 0;
double adjustedRom[];
String ordenAlgoritmosF[];
String ordenAlgoritmosAF[];
String ordenAlgoritmosQ[];
double adjustedP[][];
double Ci[];
double SE;
boolean parar, otro;
double pFriedman, pIman;
DecimalFormat nf4 = (DecimalFormat) DecimalFormat.getInstance();
nf4.setMaximumFractionDigits(4);
nf4.setMinimumFractionDigits(0);
DecimalFormatSymbols dfs = nf4.getDecimalFormatSymbols();
dfs.setDecimalSeparator('.');
nf4.setDecimalFormatSymbols(dfs);
DecimalFormat nf6 = (DecimalFormat) DecimalFormat.getInstance();
nf6.setMaximumFractionDigits(6);
nf6.setMinimumFractionDigits(0);
nf6.setDecimalFormatSymbols(dfs);
DecimalFormat nf12 = (DecimalFormat) DecimalFormat.getInstance();
nf12.setMaximumFractionDigits(12);
nf12.setMinimumFractionDigits(0);
nf12.setDecimalFormatSymbols(dfs);
int nDatasets = Configuration.getNDatasets();
int nAlgorithms = Configuration.getNAlgorithms();
Iman = Configuration.isIman();
Nemenyi = Configuration.isNemenyi();
Bonferroni = Configuration.isBonferroni();
Holm = Configuration.isHolm();
Hoch = Configuration.isHochberg();
Hommel = Configuration.isHommel();
Scha = Configuration.isShaffer();
Berg = Configuration.isBergman();
Holland = Configuration.isHolland();
Rom = Configuration.isRom();
Finner = Configuration.isFinner();
Li = Configuration.isLi();
mean = new double[nDatasets][algorithmName.length];
//Maximize performance
if(Configuration.getObjective()==1){
/*Compute the average performance per algorithm for each data set*/
for (i=0; i<nDatasets; i++) {
for (j=0; j<algorithmName.length; j++) {
mean[i][j] = results[j][i];
}
}
}
//Minimize performance
else{
double maxValue=Double.MIN_VALUE;
/*Compute the average performance per algorithm for each data set*/
for (i=0; i<nDatasets; i++) {
for (j=0; j<algorithmName.length; j++) {
if(results[j][i]>maxValue){
maxValue=results[j][i];
}
mean[i][j] = (-1.0 * results[j][i]);
}
}
for (i=0; i<nDatasets; i++) {
for (j=0; j<algorithmName.length; j++) {
mean[i][j] += maxValue;
}
}
}
/** FRIEDMAN PROCEDURE ****************************************************************************************/
/*We use the Pair structure to compute and order rankings*/
orden = new Pair[nDatasets][nAlgorithms];
for (i=0; i<nDatasets; i++) {
for (j=0; j<nAlgorithms; j++){
orden[i][j] = new Pair (j,mean[i][j]);
}
Arrays.sort(orden[i]);
}
/*building of the rankings table per algorithms and data sets*/
rank = new Pair[nDatasets][nAlgorithms];
posicion = 0;
for (i=0; i<nDatasets; i++) {
for (j=0; j<nAlgorithms; j++){
encontrado = false;
for (k=0; k<nAlgorithms && !encontrado; k++) {
if (orden[i][k].indice == j) {
encontrado = true;
posicion = k+1;
}
}
rank[i][j] = new Pair(posicion,orden[i][posicion-1].valor);
}
}
/*In the case of having the same performance, the rankings are equal*/
for (i=0; i<nDatasets; i++) {
visto = new boolean[nAlgorithms];
porVisitar= new Vector <Integer> ();
Arrays.fill(visto,false);
for (j=0; j<nAlgorithms; j++) {
porVisitar.removeAllElements();
sum = rank[i][j].indice;
visto[j] = true;
ig = 1;
for (k=j+1;k<nAlgorithms;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][porVisitar.elementAt(k).intValue()].indice = sum;
}
}
}
/*compute the average ranking for each algorithm*/
Rj = new double[nAlgorithms];
for (i=0; i<nAlgorithms; i++){
Rj[i] = 0;
for (j=0; j<nDatasets; j++) {
Rj[i] += rank[j][i].indice / ((double)nDatasets);
}
}
/**FRIEDMAN ALIGNED RANKS PROCEDURE *******************************************************************************/
meanAR = new double[nDatasets][nAlgorithms];
/*Compute the average performance per algorithm for each data set*/
for (i=0; i<nDatasets; i++) {
sum = 0;
for (j=0; j<nAlgorithms; j++) {
sum += mean[i][j];
}
sum /= nAlgorithms;
for (j=0; j<nAlgorithms; j++) {
meanAR[i][j] = mean[i][j] - sum;
}
}
/*We use the Pair structure to compute and order rankings*/
ordenAR = new Pair[nDatasets * nAlgorithms];
for (i=0; i<nDatasets * nAlgorithms; i++) {
ordenAR[i] = new Pair (i,meanAR[i/nAlgorithms][i%nAlgorithms]);
}
Arrays.sort(ordenAR);
/*building of the rankings table per algorithms and data sets*/
rankAR = new Pair[nDatasets * nAlgorithms];
posicion = 0;
for (i=0; i<nDatasets * nAlgorithms; i++) {
encontrado = false;
for (k=0; k<nAlgorithms * nDatasets && !encontrado; k++) {
if (ordenAR[k].indice == i) {
encontrado = true;
posicion = k+1;
}
}
rankAR[i] = new Pair(posicion,ordenAR[posicion-1].valor);
}
/*In the case of having the same performance, the rankings are equal*/
visto = new boolean[nAlgorithms*nDatasets];
porVisitar= new Vector <Integer> ();
Arrays.fill(visto,false);
for (i=0; i<nAlgorithms*nDatasets; i++) {
porVisitar.removeAllElements();
sum = rankAR[i].indice;
visto[i] = true;
ig = 1;
for (j=i+1;j<nAlgorithms*nDatasets;j++) {
if (rankAR[i].valor == rankAR[j].valor && !visto[j]) {
sum += rankAR[j].indice;
ig++;
porVisitar.add(new Integer(j));
visto[j] = true;
}
}
sum /= (double)ig;
rankAR[i].indice = sum;
for (j=0; j<porVisitar.size(); j++) {
rankAR[porVisitar.elementAt(j).intValue()].indice = sum;
}
}
/*compute the average ranking for each algorithm*/
RjAR = new double[nAlgorithms];
for (i=0; i<nAlgorithms; i++){
RjAR[i] = 0;
for (j=0; j<nDatasets; j++) {
RjAR[i] += rankAR[j*nAlgorithms + i].indice / ((double)nDatasets);
}
}
/** QUADE TEST ***************************************************************************************************/
diffBlocks = new double[nDatasets];
for (i=0; i<nDatasets; i++) {
min = mean[i][0];
max = mean[i][0];
for (j=1; j<mean[i].length; j++) {
if (mean[i][j] < min){
min = mean[i][j];
} else if (mean[i][j] > max) {
max = mean[i][j];
}
}
diffBlocks[i] = max - min;
}
/*We use the Pair structure to compute and order rankings*/
bOrden = new Pair[nDatasets];
for (i=0; i<nDatasets; i++) {
bOrden[i] = new Pair (i,diffBlocks[i]);
}
Arrays.sort(bOrden);
/*building of the rankings table per algorithms and data sets*/
bRank = new Pair[nDatasets];
posicion = 0;
for (i=0; i<nDatasets; i++){
encontrado = false;
for (j=0; j<nDatasets && !encontrado; j++) {
if (bOrden[j].indice == i) {
encontrado = true;
posicion = j+1;
}
}
bRank[i] = new Pair(nDatasets+1-posicion,bOrden[posicion-1].valor);
}
/*In the case of having the same performance, the rankings are equal*/
visto = new boolean[nDatasets];
porVisitar= new Vector <Integer> ();
Arrays.fill(visto,false);
for (i=0; i<nDatasets; i++) {
porVisitar.removeAllElements();
sum = bRank[i].indice;
visto[i] = true;
ig = 1;
for (j=i+1;j<nDatasets;j++) {
if (bRank[i].valor == bRank[j].valor && !visto[j]) {
sum += bRank[j].indice;
ig++;
porVisitar.add(new Integer(j));
visto[j] = true;
}
}
sum /= (double)ig;
bRank[i].indice = sum;
for (j=0; j<porVisitar.size(); j++) {
bRank[porVisitar.elementAt(j).intValue()].indice = sum;
}
}
/*compute the average ranking for each algorithm*/
Sj = new double[nAlgorithms];
SMj = new double[nAlgorithms];
for (i=0; i<nAlgorithms; i++){
SMj[i] = 0;
for (j=0; j<nDatasets; j++) {
Sj[i] += ((rank[j][i].indice)-(nAlgorithms+1)/2)* bRank[j].indice;
SMj[i] += (rank[j][i].indice)* bRank[j].indice / (((double)nDatasets*(nDatasets+1))/2.0);
}
}
/** Print the results of multiple comparison tests ****************************************************************/
if(Friedman){
out+="\n\\section{Average rankings of Friedman test}\n\n";
out+="\nAverage ranks obtained by each method in the Friedman test.\n\n";
/*Print the average ranking per algorithm for Friedman*/
out+="\\begin{table}[!htp]\n" +
"\\centering\n" +
"\\begin{tabular}{|c|c|}\\hline\n" +
"Algorithm&Ranking\\\\\\hline\n";
for (i=0; i<nAlgorithms;i++) {
out+=algorithmName[i]+"&"+nf4.format(Rj[i])+"\\\\";
}
out+="\\hline\\end{tabular}\n\\caption{Average Rankings of the algorithms (Friedman)}\n\\end{table}";
/*Compute the Friedman statistic*/
termino1 = (12*(double)nDatasets)/((double)nAlgorithms*((double)nAlgorithms+1));
termino2 = (double)nAlgorithms*((double)nAlgorithms+1)*((double)nAlgorithms+1)/(4.0);
for (i=0; i<nAlgorithms;i++) {
sumatoria += Rj[i]*Rj[i];
}
friedman = (sumatoria - termino2) * termino1;
out+="\n\nFriedman statistic (distributed according to chi-square with "+(nAlgorithms-1)+" degrees of freedom): "+nf6.format(friedman)+". ";
pFriedman = ChiSq(friedman, (nAlgorithms-1));
out+="\\newline P-value computed by Friedman Test: " + nf6.format(pFriedman) +".\\newline\n\n";
if(Iman){
/*Compute the Iman-Davenport statistic*/
iman = ((nDatasets-1)*friedman)/(nDatasets*(nAlgorithms-1) - friedman);
out+="Iman and Davenport statistic (distributed according to F-distribution with "+(nAlgorithms-1)+" and "+ (nAlgorithms-1)*(nDatasets-1) +" degrees of freedom): "+nf6.format(iman)+". ";
pIman = FishF(iman, (nAlgorithms-1),(nAlgorithms-1) * (nDatasets - 1));
out+="\\newline P-value computed by Iman and Daveport Test: " + nf12.format(pIman) +".\\newline\n\n";
}
out+="\n\\newpage\n";
}
termino3 = Math.sqrt((double)nAlgorithms*((double)nAlgorithms+1)/(6.0*(double)nDatasets));
if(Alligned){
out+="\n\\section{Average rankings of Friedman Alligned test}\n\n";
out+="\nAverage ranks obtained by each method in the Friedman Alligned test.\n\n";
/*Print the average ranking per algorithm for Aligned Friedman*/
out+="\\begin{table}[!htp]\n" +
"\\centering\n" +
"\\begin{tabular}{|c|c|}\\hline\n" +
"Algorithm&Ranking\\\\\\hline\n";
for (i=0; i<nAlgorithms;i++) {
out+=(String)algorithmName[i]+"&"+nf4.format(RjAR[i])+"\\\\";
}
out+="\\hline\\end{tabular}\n\\caption{Average Rankings of the algorithms (Aligned Friedman)}\n\\end{table}";
/*Compute the Aligned Friedman statistic*/
termino1 = (double)nAlgorithms-1;
termino2 = (double)nAlgorithms*((double)nDatasets*nDatasets)/4.0;
termino2 *= ((double)nAlgorithms*(double)nDatasets + 1)*((double)nAlgorithms*(double)nDatasets + 1);
sumatoria = 0;
for (i=0; i<nAlgorithms;i++) {
temporal = 0;
for (j=0; j<nDatasets; j++) {
temporal += (double)rankAR[j*nAlgorithms+i].indice;
}
sumatoria += temporal * temporal;
}
sumatoria /= (double)nAlgorithms;
numerador = sumatoria - termino2;
numerador *= termino1;
termino1 = (double)nAlgorithms*(double)nDatasets*((double)nAlgorithms*(double)nDatasets + 1)* ((double)nAlgorithms*(double)nDatasets*2 + 1);
termino1 /= 6;
sumatoria = 0;
for (i=0; i<nDatasets;i++) {
temporal = 0;
for (j=0; j<nAlgorithms; j++) {
temporal += (double)rankAR[i*nAlgorithms+j].indice;
}
sumatoria += temporal * temporal;
}
denominador = termino1 - sumatoria;
friedman = numerador / denominador;
out+="\n\nAligned Friedman statistic (distributed according to chi-square with "+(nAlgorithms-1)+" degrees of freedom): "+nf6.format(friedman)+". ";
pFriedman = ChiSq(friedman, (nAlgorithms-1));
out+="\\newline P-value computed by Aligned Friedman Test: " + nf12.format(pFriedman) +".\\newline\n\n";
out+="\n\\newpage\n";
}
if(Quade){
out+="\n\\section{Average rankings of Quade test}\n\n";
out+="\nAverage ranks obtained by each method in the Quade test.\n\n";
/*Print the average ranking per algorithm for Quade*/
out+="\\begin{table}[!htp]\n" +
"\\centering\n" +
"\\begin{tabular}{|c|c|}\\hline\n" +
"Algorithm&Ranking\\\\\\hline\n";
for (i=0; i<nAlgorithms;i++) {
out+=(String)algorithmName[i]+"&"+nf4.format(SMj[i])+"\\\\";
}
out+="\\hline\\end{tabular}\n\\caption{Average Rankings of the algorithms (Quade)}\n\\end{table}";
/*Compute the Quade statistic*/
sumatoria = 0;
for (i=0; i<nAlgorithms; i++) {
sumatoria += Sj[i]*Sj[i];
}
sumatoria /= nDatasets;
termino1 = (nDatasets*(nDatasets+1)*(2*nDatasets+1)*nAlgorithms*(nAlgorithms+1)*(nAlgorithms-1)) / 72;
iman = ((nDatasets-1)*sumatoria) / (termino1 - sumatoria);
out+="Quade statistic (distributed according to F-distribution with "+(nAlgorithms-1)+" and "+ (nAlgorithms-1)*(nDatasets-1) +" degrees of freedom): "+nf6.format(iman)+". ";
pIman = FishF(iman, (nAlgorithms-1),(nAlgorithms-1) * (nDatasets - 1));
out+="\\newline P-value computed by Quade Test: " + nf12.format(pIman) +".\\newline\n\n";
out+="\n\\newpage\n";
}
/************ COMPARING A CONTROL METHOD *************************************************************************/
/*Compute the unadjusted p_i value for each comparison alpha=0.05*/
Pi = new double[nAlgorithms-1];
PiAR = new double[nAlgorithms-1];
PiQ = new double[nAlgorithms-1];
ALPHAiHolm = new double[nAlgorithms-1];
ALPHAiHolland = new double[nAlgorithms-1];
ALPHAiRom = new double[nAlgorithms-1];
ALPHAiFinner = new double[nAlgorithms-1];
ordenAlgoritmosF = new String[nAlgorithms-1];
ordenAlgoritmosAF = new String[nAlgorithms-1];
ordenAlgoritmosQ = new String[nAlgorithms-1];
adjustedRom = new double[nAlgorithms-1];
calcularROM(0.05,ALPHAiRom, adjustedRom);
/** USING FRIEDMAN TEST ******************************************************************************************/
if(Friedman){
out+="\n\\section{Post hoc comparison (Friedman)}\n\n";
out+="\nP-values obtained in by applying post hoc methods over the results of Friedman procedure.\n\n";
SE = termino3;
vistos = new boolean[nAlgorithms];
rankingRef = 0.0;
Arrays.fill(vistos,false);
for (i=0; i<nAlgorithms;i++) {
for (j=0;vistos[j]==true;j++);
pos = j;
maxVal = Rj[j];
minVal = Rj[j];
for (j=j+1;j<nAlgorithms;j++) {
if (i > 1) {
if (vistos[j] == false && Rj[j] > maxVal) {
pos = j;
maxVal = Rj[j];
}
} else if (i == 1) {
if (vistos[j] == false && Rj[j] > maxVal) {
pos = j;
maxVal = Rj[j];
}
if (vistos[j] == false && Rj[j] < minVal) {
minVal = Rj[j];
}
} else {
if (vistos[j] == false && Rj[j] < maxVal) {
pos = j;
maxVal = Rj[j];
}
}
}
vistos[pos] = true;
if (i==1) {
diffMax = minVal - rankingRef;
Pm = 2*CDF_Normal.normp((-1)*Math.abs((diffMax)/SE));
ALPHA2Li = (1 - Pm) / (1 - 0.05) * 0.05;
}
if (i==0) {
counter=4;
if((Holm)||(Hoch)||(Hommel)){
counter++;
}
if(Holland){
counter++;
}
if(Rom){
counter++;
}
if(Finner){
counter++;
}
if(Li){
counter++;
}
rankingRef = maxVal;
out+="\\begin{table}[!htp]\n\\centering\\footnotesize\n" +
"\\begin{tabular}{"+printC(counter)+"}\n" +
"$i$&algorithm&$z=(R_0 - R_i)/SE$&$p$";
if((Holm)||(Hoch)||(Hommel)){
out+="&";
if(Holm){
out+="Holm ";
}
if(Hoch){
out+="Hochberg ";
}
if(Hommel){
out+="Hommel ";
}
}
if(Holland){
out+="&Holland";
}
if(Rom){
out+="&Rom";
}
if(Finner){
out+="&Finner";
}
if(Li){
out+="&Li";
}
out+="\\\\\n\\hline";
} else {
ALPHAiHolm[i-1] = 0.05/((double)nAlgorithms-(double)i);
ALPHAiHolland[i-1] = 1.0 - Math.pow((1.0 - 0.05),(1.0/((double)nAlgorithms-(double)i)));
ALPHAiFinner[i-1] = 1.0 - Math.pow((1.0 - 0.05),(1.0/(((double)nAlgorithms-1)/(double)i)));
ordenAlgoritmosF[i-1] = new String ((String)algorithmName[pos]);
out+=(nAlgorithms-i) + "&" + algorithmName[pos] + "&" +
nf6.format(Math.abs((rankingRef-maxVal)/SE)) + "&" +
nf6.format(2*CDF_Normal.normp((-1)*Math.abs((rankingRef-maxVal)/SE)));
if((Holm)||(Hoch)||(Hommel)){
out+="&" + nf6.format(ALPHAiHolm[i-1]);
}
if(Holland){
out+="&" + nf6.format(ALPHAiHolland[i-1]);
}
if(Rom){
out+="&" + nf6.format(ALPHAiRom[i-1]);
}
if(Finner){
out+="&" + nf6.format(ALPHAiFinner[i-1]);
}
if(Li){
out+="&" + ((i==(nAlgorithms-1))?(0.05):(nf6.format(ALPHA2Li)));
}
out+="\\\\";
Pi[i-1] = 2*CDF_Normal.normp((-1)*Math.abs((rankingRef-maxVal)/SE));
}
}
out+="\\hline\n" + "\\end{tabular}\n\\caption{Post Hoc comparison Table for $\\alpha=0.05$ (FRIEDMAN)}\n" + "\\end{table}";
/*Compute the rejected hypotheses for each test*/
if(Bonferroni){
out+="Bonferroni-Dunn's procedure rejects those hypotheses that have an unadjusted p-value $\\le"+nf6.format(0.05/(double)(nAlgorithms-1))+"$.\n\n";
}
if(Holm){
parar = false;
for (i=0; i<nAlgorithms-1 && !parar; i++) {
if (Pi[i] > ALPHAiHolm[i]) {
out+="Holm's procedure rejects those hypotheses that have an unadjusted p-value $\\le"+nf6.format(ALPHAiHolm[i])+"$.\n\n";
parar = true;
}
}
}
if(Hoch){
parar = false;
for (i=nAlgorithms-2; i>=0 && !parar; i--) {
if (Pi[i] <= ALPHAiHolm[i]) {
out+="Hochberg's procedure rejects those hypotheses that have an unadjusted p-value $\\le"+nf6.format(ALPHAiHolm[i])+"$.\n\n";
parar = true;
}
}
}
if(Hommel){
otro = true;
for (j=nAlgorithms-1; j>0 && otro; j--) {
otro = false;
for (k=1; k<=j && !otro; k++) {
if (Pi[nAlgorithms-1-j+k-1] <= 0.05*(double)k/(double)j) {
otro = true;
}
}
}
if (otro == true) {
out+="Hommel's procedure rejects all hypotheses.\n\n";
} else {
j++;
out+="Hommel's procedure rejects those hypotheses that have an unadjusted p-value $\\le"+nf6.format(0.05/(double)j)+"$.\n\n";
}
}
if(Holland){
parar = false;
for (i=0; i<nAlgorithms-1 && !parar; i++) {
if (Pi[i] > ALPHAiHolland[i]) {
out+="Holland's procedure rejects those hypotheses that have an unadjusted p-value $\\le"+nf6.format(ALPHAiHolland[i])+"$.\n\n";
parar = true;
}
}
}
if(Rom){
parar = false;
for (i=nAlgorithms-2; i>=0 && !parar; i--) {
if (Pi[i] <= ALPHAiRom[i]) {
out+="Rom's procedure rejects those hypotheses that have an unadjusted p-value $\\le"+nf6.format(ALPHAiRom[i])+"$.\n\n";
parar = true;
}
}
}
if(Finner){
parar = false;
for (i=0; i<nAlgorithms-1 && !parar; i++) {
if (Pi[i] > ALPHAiFinner[i]) {
out+="Finner's procedure rejects those hypotheses that have an unadjusted p-value $\\le"+nf6.format(ALPHAiFinner[i])+"$.\n\n";
parar = true;
}
}
}
if(Li){
if (Pi[nAlgorithms-2] < 0.05) {
out+="Li's procedure rejects those hypotheses that have an unadjusted p-value $\\le"+0.05+"$.\n\n";
} else {
out+="Li's procedure rejects those hypotheses that have an unadjusted p-value $\\le"+nf6.format(ALPHA2Li)+"$.\n\n";
}
}
out+="\n\\newpage\n";
}
/** USING ALIGNED FRIEDMAN TEST *******************************************************************************************/
if(Alligned){
out+="\n\\section{Post hoc comparison (Friedman Alligned)}\n\n";
out+="\nP-values obtained in by applying post hoc methods over the results of Friedman Alligned procedure.\n\n";
SE = Math.sqrt((double)nAlgorithms*((double)nDatasets*(double)nAlgorithms+1)/6.0);
vistos = new boolean[nAlgorithms];
rankingRef = 0.0;
Arrays.fill(vistos,false);
for (i=0; i<nAlgorithms;i++) {
for (j=0;vistos[j]==true;j++);
pos = j;
maxVal = RjAR[j];
minVal = RjAR[j];
for (j=j+1;j<nAlgorithms;j++) {
if (i > 1) {
if (vistos[j] == false && RjAR[j] > maxVal) {
pos = j;
maxVal = RjAR[j];
}
} else if (i == 1) {
if (vistos[j] == false && RjAR[j] > maxVal) {
pos = j;
maxVal = RjAR[j];
}
if (vistos[j] == false && RjAR[j] < minVal) {
minVal = RjAR[j];
}
} else {
if (vistos[j] == false && RjAR[j] < maxVal) {
pos = j;
maxVal = RjAR[j];
}
}
}
vistos[pos] = true;
if (i==1) {
diffMax = minVal - rankingRef;
PmAR = 2*CDF_Normal.normp((-1)*Math.abs((diffMax)/SE));
ALPHA2Li = (1 - PmAR) / (1 - 0.05) * 0.05;
}
if (i==0) {
counter=4;
if((Holm)||(Hoch)||(Hommel)){
counter++;
}
if(Holland){
counter++;
}
if(Rom){
counter++;
}
if(Finner){
counter++;
}
if(Li){
counter++;
}
rankingRef = maxVal;
out+="\\begin{table}[!htp]\n\\centering\\footnotesize\n" +
"\\begin{tabular}{"+printC(counter)+"}\n" +
"$i$&algorithm&$z=(R_0 - R_i)/SE$&$p$";
if((Holm)||(Hoch)||(Hommel)){
out+="&";
if(Holm){
out+="Holm ";
}
if(Hoch){
out+="Hochberg ";
}
if(Hommel){
out+="Hommel ";
}
}
if(Holland){
out+="&Holland";
}
if(Rom){
out+="&Rom";
}
if(Finner){
out+="&Finner";
}
if(Li){
out+="&Li";
}
out+="\\\\\n\\hline";
} else {
ALPHAiHolm[i-1] = 0.05/((double)nAlgorithms-(double)i);
ALPHAiHolland[i-1] = 1.0 - Math.pow((1.0 - 0.05),(1.0/((double)nAlgorithms-(double)i)));
ALPHAiFinner[i-1] = 1.0 - Math.pow((1.0 - 0.05),(1.0/(((double)nAlgorithms-1)/(double)i)));
ordenAlgoritmosAF[i-1] = new String ((String)algorithmName[pos]);
out+=(nAlgorithms-i) + "&" + algorithmName[pos] + "&" +
nf6.format(Math.abs((rankingRef-maxVal)/SE)) + "&" +
nf6.format(2*CDF_Normal.normp((-1)*Math.abs((rankingRef-maxVal)/SE)));
if((Holm)||(Hoch)||(Hommel)){
out+="&" + nf6.format(ALPHAiHolm[i-1]);
}
if(Holland){
out+="&" + nf6.format(ALPHAiHolland[i-1]);
}
if(Rom){
out+="&" + nf6.format(ALPHAiRom[i-1]);
}
if(Finner){
out+="&" + nf6.format(ALPHAiFinner[i-1]);
}
if(Li){
out+="&" + ((i==(nAlgorithms-1))?(0.05):(nf6.format(ALPHA2Li)));
}
out+="\\\\";
PiAR[i-1] = 2*CDF_Normal.normp((-1)*Math.abs((rankingRef-maxVal)/SE));
}
}
out+="\\hline\n" + "\\end{tabular}\n\\caption{Post Hoc comparison Table for $\\alpha=0.05$ (FRIEDMAN ALLIGNED)}\n" + "\\end{table}";
/*Compute the rejected hypotheses for each test*/
if(Bonferroni){
out+="Bonferroni-Dunn's procedure rejects those hypotheses that have an unadjusted p-value $\\le"+nf6.format(0.05/(double)(nAlgorithms-1))+"$.\n\n";
}
if(Holm){
parar = false;
for (i=0; i<nAlgorithms-1 && !parar; i++) {
if (PiAR[i] > ALPHAiHolm[i]) {
out+="Holm's procedure rejects those hypotheses that have an unadjusted p-value $\\le"+nf6.format(ALPHAiHolm[i])+"$.\n\n";
parar = true;
}
}
}
if(Hoch){
parar = false;
for (i=nAlgorithms-2; i>=0 && !parar; i--) {
if (PiAR[i] <= ALPHAiHolm[i]) {
out+="Hochberg's procedure rejects those hypotheses that have an unadjusted p-value $\\le"+nf6.format(ALPHAiHolm[i])+"$.\n\n";
parar = true;
}
}
}
if(Hommel){
otro = true;
for (j=nAlgorithms-1; j>0 && otro; j--) {
otro = false;
for (k=1; k<=j && !otro; k++) {
if (PiAR[nAlgorithms-1-j+k-1] <= 0.05*(double)k/(double)j) {
otro = true;
}
}
}
if (otro == true) {
out+="Hommel's procedure rejects all hypotheses.\n\n";
} else {
j++;
out+="Hommel's procedure rejects those hypotheses that have an unadjusted p-value $\\le"+nf6.format(0.05/(double)j)+"$.\n\n";
}
}
if(Holland){
parar = false;
for (i=0; i<nAlgorithms-1 && !parar; i++) {
if (PiAR[i] > ALPHAiHolland[i]) {
out+="Holland's procedure rejects those hypotheses that have an unadjusted p-value $\\le"+nf6.format(ALPHAiHolland[i])+"$.\n\n";
parar = true;
}
}
}
if(Rom){
parar = false;
for (i=nAlgorithms-2; i>=0 && !parar; i--) {
if (PiAR[i] <= ALPHAiRom[i]) {
out+="Rom's procedure rejects those hypotheses that have an unadjusted p-value $\\le"+nf6.format(ALPHAiRom[i])+"$.\n\n";
parar = true;
}
}
}
if(Finner){
parar = false;
for (i=0; i<nAlgorithms-1 && !parar; i++) {
if (PiAR[i] > ALPHAiFinner[i]) {
out+="Finner's procedure rejects those hypotheses that have an unadjusted p-value $\\le"+nf6.format(ALPHAiFinner[i])+"$.\n\n";
parar = true;
}
}
}
if(Li){
if (PiAR[nAlgorithms-2] < 0.05) {
out+="Li's procedure rejects those hypotheses that have an unadjusted p-value $\\le"+0.05+"$.\n\n";
} else {
out+="Li's procedure rejects those hypotheses that have an unadjusted p-value $\\le"+nf6.format(ALPHA2Li)+"$.\n\n";
}
}
out+="\n\\newpage\n";
}
/** USING QUADE TEST **********************************************************************************************/
if(Quade){
out+="\n\\section{Post hoc comparison (Quade)}\n\n";
out+="\nP-values obtained in by applying post hoc methods over the results of Quade procedure.\n\n";
SE = Math.sqrt(((double)nAlgorithms*((double)nAlgorithms+1)*((double)nAlgorithms-1)*((double)nDatasets*2+1))/(18.0*(double)nDatasets*((double)nDatasets+1)));
vistos = new boolean[nAlgorithms];
rankingRef = 0.0;
Arrays.fill(vistos,false);
for (i=0; i<nAlgorithms;i++) {
for (j=0;vistos[j]==true;j++);
pos = j;
maxVal = SMj[j];
minVal = SMj[j];
for (j=j+1;j<nAlgorithms;j++) {
if (i > 1) {
if (vistos[j] == false && SMj[j] > maxVal) {
pos = j;
maxVal = SMj[j];
}
} else if (i == 1) {
if (vistos[j] == false && SMj[j] > maxVal) {
pos = j;
maxVal = SMj[j];
}
if (vistos[j] == false && SMj[j] < minVal) {
minVal = SMj[j];
}
} else {
if (vistos[j] == false && SMj[j] < maxVal) {
pos = j;
maxVal = SMj[j];
}
}
}
vistos[pos] = true;
if (i==1) {
diffMax = minVal - rankingRef;
PmQ = 2*CDF_Normal.normp((-1)*Math.abs((diffMax)/SE));
ALPHA2Li = (1 - PmQ) / (1 - 0.05) * 0.05;
}
if (i==0) {
counter=4;
if((Holm)||(Hoch)||(Hommel)){
counter++;
}
if(Holland){
counter++;
}
if(Rom){
counter++;
}
if(Finner){
counter++;
}
if(Li){
counter++;
}
rankingRef = maxVal;
out+="\\begin{table}[!htp]\n\\centering\\footnotesize\n" +
"\\begin{tabular}{"+printC(counter)+"}\n" +
"$i$&algorithm&$z=(R_0 - R_i)/SE$&$p$";
if((Holm)||(Hoch)||(Hommel)){
out+="&";
if(Holm){
out+="Holm ";
}
if(Hoch){
out+="Hochberg ";
}
if(Hommel){
out+="Hommel ";
}
}
if(Holland){
out+="&Holland";
}
if(Rom){
out+="&Rom";
}
if(Finner){
out+="&Finner";
}
if(Li){
out+="&Li";
}
out+="\\\\\n\\hline";
} else {
ALPHAiHolm[i-1] = 0.05/((double)nAlgorithms-(double)i);
ALPHAiHolland[i-1] = 1.0 - Math.pow((1.0 - 0.05),(1.0/((double)nAlgorithms-(double)i)));
ALPHAiFinner[i-1] = 1.0 - Math.pow((1.0 - 0.05),(1.0/(((double)nAlgorithms-1)/(double)i)));
ordenAlgoritmosQ[i-1] = new String ((String)algorithmName[pos]);
out+=(nAlgorithms-i) + "&" + algorithmName[pos] + "&" +
nf6.format(Math.abs((rankingRef-maxVal)/SE)) + "&" +
nf6.format(2*CDF_Normal.normp((-1)*Math.abs((rankingRef-maxVal)/SE)));
if((Holm)||(Hoch)||(Hommel)){
out+="&" + nf6.format(ALPHAiHolm[i-1]);
}
if(Holland){
out+="&" + nf6.format(ALPHAiHolland[i-1]);
}
if(Rom){
out+="&" + nf6.format(ALPHAiRom[i-1]);
}
if(Finner){
out+="&" + nf6.format(ALPHAiFinner[i-1]);
}
if(Li){
out+="&" + ((i==(nAlgorithms-1))?(0.05):(nf6.format(ALPHA2Li)));
}
out+="\\\\";
PiQ[i-1] = 2*CDF_Normal.normp((-1)*Math.abs((rankingRef-maxVal)/SE));
}
}
out+="\\hline\n" + "\\end{tabular}\n\\caption{Post Hoc comparison Table for $\\alpha=0.05$ (Quade)}\n" + "\\end{table}";
/*Compute the rejected hypotheses for each test*/
if(Bonferroni){
out+="Bonferroni-Dunn's procedure rejects those hypotheses that have an unadjusted p-value $\\le"+nf6.format(0.05/(double)(nAlgorithms-1))+"$.\n\n";
}
if(Holm){
parar = false;
for (i=0; i<nAlgorithms-1 && !parar; i++) {
if (PiQ[i] > ALPHAiHolm[i]) {
out+="Holm's procedure rejects those hypotheses that have an unadjusted p-value $\\le"+nf6.format(ALPHAiHolm[i])+"$.\n\n";
parar = true;
}
}
}
if(Hoch){
parar = false;
for (i=nAlgorithms-2; i>=0 && !parar; i--) {
if (PiQ[i] <= ALPHAiHolm[i]) {
out+="Hochberg's procedure rejects those hypotheses that have an unadjusted p-value $\\le"+nf6.format(ALPHAiHolm[i])+"$.\n\n";
parar = true;
}
}
}
if(Hommel){
otro = true;
for (j=nAlgorithms-1; j>0 && otro; j--) {
otro = false;
for (k=1; k<=j && !otro; k++) {
if (PiQ[nAlgorithms-1-j+k-1] <= 0.05*(double)k/(double)j) {
otro = true;
}
}
}
if (otro == true) {
out+="Hommel's procedure rejects all hypotheses.\n\n";
} else {
j++;
out+="Hommel's procedure rejects those hypotheses that have an unadjusted p-value $\\le"+nf6.format(0.05/(double)j)+"$.\n\n";
}
}
if(Holland){
parar = false;
for (i=0; i<nAlgorithms-1 && !parar; i++) {
if (PiQ[i] > ALPHAiHolland[i]) {
out+="Holland's procedure rejects those hypotheses that have an unadjusted p-value $\\le"+nf6.format(ALPHAiHolland[i])+"$.\n\n";
parar = true;
}
}
}
if(Rom){
parar = false;
for (i=nAlgorithms-2; i>=0 && !parar; i--) {
if (PiQ[i] <= ALPHAiRom[i]) {
out+="Rom's procedure rejects those hypotheses that have an unadjusted p-value $\\le"+nf6.format(ALPHAiRom[i])+"$.\n\n";
parar = true;
}
}
}
if(Finner){
parar = false;
for (i=0; i<nAlgorithms-1 && !parar; i++) {
if (PiQ[i] > ALPHAiFinner[i]) {
out+="Finner's procedure rejects those hypotheses that have an unadjusted p-value $\\le"+nf6.format(ALPHAiFinner[i])+"$.\n\n";
parar = true;
}
}
}
if(Li){
if (PiQ[nAlgorithms-2] < 0.05) {
out+="Li's procedure rejects those hypotheses that have an unadjusted p-value $\\le"+0.05+"$.\n\n";
} else {
out+="Li's procedure rejects those hypotheses that have an unadjusted p-value $\\le"+nf6.format(ALPHA2Li)+"$.\n\n";
}
}
out+="\n\\newpage\n";
}
/************ ADJUSTED P-VALUES IN 1xN **************************************************************************/
/** FRIEDMAN *****************************************************************************************************/
if(Friedman){
out+="\n\\section{Adjusted P-Values (Friedman)}\n\n";
out+="\nAdjusted P-values obtained through the application of the post hoc methods (Friedman).\n\n";
adjustedP = new double[nAlgorithms-1][8];
for (i=0; i<adjustedP.length; i++) {
adjustedP[i][0] = Pi[i] * (double)(nAlgorithms-1);
adjustedP[i][1] = Pi[i] * (((double)(nAlgorithms-1))-i);
adjustedP[i][2] = Pi[i] * (((double)(nAlgorithms-1))-i);
adjustedP[i][4] = 1.0 - Math.pow((1.0 - Pi[i]),((double)(nAlgorithms-1))-i);
adjustedP[i][5] = Pi[i] * adjustedRom[i];
adjustedP[i][6] = 1.0 - Math.pow((1.0 - Pi[i]),((double)(nAlgorithms-1))/(i+1));
adjustedP[i][7] = Pi[i] / (Pi[i] + 1 - Pm);
}
for (i=1; i<adjustedP.length; i++) {
if (adjustedP[i][1] < adjustedP[i-1][1])
adjustedP[i][1] = adjustedP[i-1][1];
if (adjustedP[i][4] < adjustedP[i-1][4])
adjustedP[i][4] = adjustedP[i-1][4];
if (adjustedP[i][6] < adjustedP[i-1][6])
adjustedP[i][6] = adjustedP[i-1][6];
}
for (i=adjustedP.length-2; i>=0; i--) {
if (adjustedP[i][2] > adjustedP[i+1][2])
adjustedP[i][2] = adjustedP[i+1][2];
if (adjustedP[i][5] > adjustedP[i+1][5])
adjustedP[i][5] = adjustedP[i+1][5];
}
/*Algoritmo que calcula los valores p ajustados para Hommel*/
Ci= new double[adjustedP.length+1];
for (i=0; i<adjustedP.length; i++) {
adjustedP[i][3] = Pi[i];
}
for (m=adjustedP.length; m>1; m--) {
for (i=adjustedP.length; i> (adjustedP.length-m); i--) {
Ci[i] = ((double)m*Pi[i-1])/((double)(m+i-adjustedP.length));
}
min = Double.POSITIVE_INFINITY;
for (i=adjustedP.length; i> (adjustedP.length-m); i--) {
if (Ci[i] < min)
min = Ci[i];
}
for (i=adjustedP.length; i> (adjustedP.length-m); i--) {
if (adjustedP[i-1][3] < min)
adjustedP[i-1][3] = min;
}
for (i=1; i<=(adjustedP.length-m); i++) {
Ci[i] = Math.min(min, (double)m * Pi[i-1]);
}
for (i=1; i<=(adjustedP.length-m); i++) {
if (adjustedP[i-1][3] < Ci[i])
adjustedP[i-1][3] = Ci[i];
}
}
counter=3;
if(Bonferroni){
counter++;
}
if(Holm){
counter++;
}
if(Hoch){
counter++;
}
if(Hommel){
counter++;
}
out+="\\begin{table}[!htp]\n\\centering\\small\n" +
"\\begin{tabular}{"+printC(counter)+"}\n" +
"i&algorithm&unadjusted $p$";
if(Bonferroni){
out+="&$p_{Bonf}$";
}
if(Holm){
out+="&$p_{Holm}$";
}
if(Hoch){
out+="&$p_{Hochberg}$";
}
if(Hommel){
out+="&$p_{Hommel}$";
}
out+="\\\\\n\\hline";
for (i=0; i<Pi.length; i++) {
out+=(i+1) + "&" + ordenAlgoritmosF[i] + "&" + nf6.format(Pi[i]);
if(Bonferroni){
out+="&" + nf6.format(adjustedP[i][0]);
}
if(Holm){
out+="&" + nf6.format(adjustedP[i][1]);
}
if(Hoch){
out+="&" + nf6.format(adjustedP[i][2]);
}
if(Hommel){
out+="&" + nf6.format(adjustedP[i][3]);
}
out+="\\\\";
}
out+="\\hline\n" + "\\end{tabular}\n\\caption{Adjusted $p$-values (FRIEDMAN) (I)}\n" + "\\end{table}\n";
counter=3;
if(Holland){
counter++;
}
if(Rom){
counter++;
}
if(Finner){
counter++;
}
if(Li){
counter++;
}
out+="\\begin{table}[!htp]\n\\centering\\small\n" +
"\\begin{tabular}{"+printC(counter)+"}\n" +
"i&algorithm&unadjusted $p$";
if(Holland){
out+="&$p_{Holland}$";
}
if(Rom){
out+="&$p_{Rom}$";
}
if(Finner){
out+="&$p_{Finner}$";
}
if(Li){
out+="&$p_{Li}$";
}
out+="\\\\\n\\hline";
for (i=0; i<Pi.length; i++) {
out+=(i+1) + "&" + ordenAlgoritmosF[i] + "&" + nf6.format(Pi[i]);
if(Holland){
out+="&" + nf6.format(adjustedP[i][4]);
}
if(Rom){
out+="&" + nf6.format(adjustedP[i][5]);
}
if(Finner){
out+="&" + nf6.format(adjustedP[i][6]);
}
if(Li){
out+="&" + nf6.format(adjustedP[i][7]);
}
out+="\\\\";
}
out+="\\hline\n" + "\\end{tabular}\n\\caption{Adjusted $p$-values (FRIEDMAN) (II)}\n" + "\\end{table}\n";
out+="\n\\newpage\n";
}
/** ALIGNED FRIEDMAN *****************************************************************************************************/
if(Alligned){
out+="\n\\section{Adjusted P-Values (Friedman Alligned)}\n\n";
out+="\nAdjusted P-values obtained through the application of the post hoc methods (Friedman Alligned).\n\n";
adjustedP = new double[nAlgorithms-1][8];
for (i=0; i<adjustedP.length; i++) {
adjustedP[i][0] = PiAR[i] * (double)(nAlgorithms-1);
adjustedP[i][1] = PiAR[i] * (((double)(nAlgorithms-1))-i);
adjustedP[i][2] = PiAR[i] * (((double)(nAlgorithms-1))-i);
adjustedP[i][4] = 1.0 - Math.pow((1.0 - PiAR[i]),((double)(nAlgorithms-1))-i);
adjustedP[i][5] = PiAR[i] * adjustedRom[i];
adjustedP[i][6] = 1.0 - Math.pow((1.0 - PiAR[i]),((double)(nAlgorithms-1))/(i+1));
adjustedP[i][7] = PiAR[i] / (PiAR[i] + 1 - PmAR);
}
for (i=1; i<adjustedP.length; i++) {
if (adjustedP[i][1] < adjustedP[i-1][1])
adjustedP[i][1] = adjustedP[i-1][1];
if (adjustedP[i][4] < adjustedP[i-1][4])
adjustedP[i][4] = adjustedP[i-1][4];
if (adjustedP[i][6] < adjustedP[i-1][6])
adjustedP[i][6] = adjustedP[i-1][6];
}
for (i=adjustedP.length-2; i>=0; i--) {
if (adjustedP[i][2] > adjustedP[i+1][2])
adjustedP[i][2] = adjustedP[i+1][2];
if (adjustedP[i][5] > adjustedP[i+1][5])
adjustedP[i][5] = adjustedP[i+1][5];
}
/*Algoritmo que calcula los valores p ajustados para Hommel*/
Ci= new double[adjustedP.length+1];
for (i=0; i<adjustedP.length; i++) {
adjustedP[i][3] = PiAR[i];
}
for (m=adjustedP.length; m>1; m--) {
for (i=adjustedP.length; i> (adjustedP.length-m); i--) {
Ci[i] = ((double)m*PiAR[i-1])/((double)(m+i-adjustedP.length));
}
min = Double.POSITIVE_INFINITY;
for (i=adjustedP.length; i> (adjustedP.length-m); i--) {
if (Ci[i] < min)
min = Ci[i];
}
for (i=adjustedP.length; i> (adjustedP.length-m); i--) {
if (adjustedP[i-1][3] < min)
adjustedP[i-1][3] = min;
}
for (i=1; i<=(adjustedP.length-m); i++) {
Ci[i] = Math.min(min, (double)m * PiAR[i-1]);
}
for (i=1; i<=(adjustedP.length-m); i++) {
if (adjustedP[i-1][3] < Ci[i])
adjustedP[i-1][3] = Ci[i];
}
}
counter=3;
if(Bonferroni){
counter++;
}
if(Holm){
counter++;
}
if(Hoch){
counter++;
}
if(Hommel){
counter++;
}
out+="\\begin{table}[!htp]\n\\centering\\small\n" +
"\\begin{tabular}{"+printC(counter)+"}\n" +
"i&algorithm&unadjusted $p$";
if(Bonferroni){
out+="&$p_{Bonf}$";
}
if(Holm){
out+="&$p_{Holm}$";
}
if(Hoch){
out+="&$p_{Hochberg}$";
}
if(Hommel){
out+="&$p_{Hommel}$";
}
out+="\\\\\n\\hline";
for (i=0; i<PiAR.length; i++) {
out+=(i+1) + "&" + ordenAlgoritmosAF[i] + "&" + nf6.format(PiAR[i]);
if(Bonferroni){
out+="&" + nf6.format(adjustedP[i][0]);
}
if(Holm){
out+="&" + nf6.format(adjustedP[i][1]);
}
if(Hoch){
out+="&" + nf6.format(adjustedP[i][2]);
}
if(Hommel){
out+="&" + nf6.format(adjustedP[i][3]);
}
out+="\\\\";
}
out+="\\hline\n" + "\\end{tabular}\n\\caption{Adjusted $p$-values (ALIGNED FRIEDMAN) (I)}\n" + "\\end{table}\n";
counter=3;
if(Holland){
counter++;
}
if(Rom){
counter++;
}
if(Finner){
counter++;
}
if(Li){
counter++;
}
out+="\\begin{table}[!htp]\n\\centering\\small\n" +
"\\begin{tabular}{"+printC(counter)+"}\n" +
"i&algorithm&unadjusted $p$";
if(Holland){
out+="&$p_{Holland}$";
}
if(Rom){
out+="&$p_{Rom}$";
}
if(Finner){
out+="&$p_{Finner}$";
}
if(Li){
out+="&$p_{Li}$";
}
out+="\\\\\n\\hline";
for (i=0; i<PiAR.length; i++) {
out+=(i+1) + "&" + ordenAlgoritmosAF[i] + "&" + nf6.format(PiAR[i]);
if(Holland){
out+="&" + nf6.format(adjustedP[i][4]);
}
if(Rom){
out+="&" + nf6.format(adjustedP[i][5]);
}
if(Finner){
out+="&" + nf6.format(adjustedP[i][6]);
}
if(Li){
out+="&" + nf6.format(adjustedP[i][7]);
}
out+="\\\\";
}
out+="\\hline\n" + "\\end{tabular}\n\\caption{Adjusted $p$-values (ALIGNED FRIEDMAN) (II)}\n" + "\\end{table}\n";
out+="\n\\newpage\n";
}
/** QUADE *****************************************************************************************************/
if(Quade){
out+="\n\\section{Adjusted P-Values (Quade)}\n\n";
out+="\nAdjusted P-values obtained through the application of the post hoc methods (Quade).\n\n";
adjustedP = new double[nAlgorithms-1][8];
for (i=0; i<adjustedP.length; i++) {
adjustedP[i][0] = PiQ[i] * (double)(nAlgorithms-1);
adjustedP[i][1] = PiQ[i] * (((double)(nAlgorithms-1))-i);
adjustedP[i][2] = PiQ[i] * (((double)(nAlgorithms-1))-i);
adjustedP[i][4] = 1.0 - Math.pow((1.0 - PiQ[i]),((double)(nAlgorithms-1))-i);
adjustedP[i][5] = PiQ[i] * adjustedRom[i];
adjustedP[i][6] = 1.0 - Math.pow((1.0 - PiQ[i]),((double)(nAlgorithms-1))/(i+1));
adjustedP[i][7] = PiQ[i] / (PiQ[i] + 1 - PmQ);
}
for (i=1; i<adjustedP.length; i++) {
if (adjustedP[i][1] < adjustedP[i-1][1])
adjustedP[i][1] = adjustedP[i-1][1];
if (adjustedP[i][4] < adjustedP[i-1][4])
adjustedP[i][4] = adjustedP[i-1][4];
if (adjustedP[i][6] < adjustedP[i-1][6])
adjustedP[i][6] = adjustedP[i-1][6];
}
for (i=adjustedP.length-2; i>=0; i--) {
if (adjustedP[i][2] > adjustedP[i+1][2])
adjustedP[i][2] = adjustedP[i+1][2];
if (adjustedP[i][5] > adjustedP[i+1][5])
adjustedP[i][5] = adjustedP[i+1][5];
}
/*Algoritmo que calcula los valores p ajustados para Hommel*/
Ci= new double[adjustedP.length+1];
for (i=0; i<adjustedP.length; i++) {
adjustedP[i][3] = PiQ[i];
}
for (m=adjustedP.length; m>1; m--) {
for (i=adjustedP.length; i> (adjustedP.length-m); i--) {
Ci[i] = ((double)m*PiQ[i-1])/((double)(m+i-adjustedP.length));
}
min = Double.POSITIVE_INFINITY;
for (i=adjustedP.length; i> (adjustedP.length-m); i--) {
if (Ci[i] < min)
min = Ci[i];
}
for (i=adjustedP.length; i> (adjustedP.length-m); i--) {
if (adjustedP[i-1][3] < min)
adjustedP[i-1][3] = min;
}
for (i=1; i<=(adjustedP.length-m); i++) {
Ci[i] = Math.min(min, (double)m * PiQ[i-1]);
}
for (i=1; i<=(adjustedP.length-m); i++) {
if (adjustedP[i-1][3] < Ci[i])
adjustedP[i-1][3] = Ci[i];
}
}
counter=3;
if(Bonferroni){
counter++;
}
if(Holm){
counter++;
}
if(Hoch){
counter++;
}
if(Hommel){
counter++;
}
out+="\\begin{table}[!htp]\n\\centering\\small\n" +
"\\begin{tabular}{"+printC(counter)+"}\n" +
"i&algorithm&unadjusted $p$";
if(Bonferroni){
out+="&$p_{Bonf}$";
}
if(Holm){
out+="&$p_{Holm}$";
}
if(Hoch){
out+="&$p_{Hochberg}$";
}
if(Hommel){
out+="&$p_{Hommel}$";
}
out+="\\\\\n\\hline";
for (i=0; i<PiQ.length; i++) {
out+=(i+1) + "&" + ordenAlgoritmosQ[i] + "&" + nf6.format(PiQ[i]);
if(Bonferroni){
out+="&" + nf6.format(adjustedP[i][0]);
}
if(Holm){
out+="&" + nf6.format(adjustedP[i][1]);
}
if(Hoch){
out+="&" + nf6.format(adjustedP[i][2]);
}
if(Hommel){
out+="&" + nf6.format(adjustedP[i][3]);
}
out+="\\\\";
}
out+="\\hline\n" + "\\end{tabular}\n\\caption{Adjusted $p$-values (QUADE) (I)}\n" + "\\end{table}\n";
counter=3;
if(Holland){
counter++;
}
if(Rom){
counter++;
}
if(Finner){
counter++;
}
if(Li){
counter++;
}
out+="\\begin{table}[!htp]\n\\centering\\small\n" +
"\\begin{tabular}{"+printC(counter)+"}\n" +
"i&algorithm&unadjusted $p$";
if(Holland){
out+="&$p_{Holland}$";
}
if(Rom){
out+="&$p_{Rom}$";
}
if(Finner){
out+="&$p_{Finner}$";
}
if(Li){
out+="&$p_{Li}$";
}
out+="\\\\\n\\hline";
for (i=0; i<PiQ.length; i++) {
out+=(i+1) + "&" + ordenAlgoritmosQ[i] + "&" + nf6.format(PiQ[i]);
if(Holland){
out+="&" + nf6.format(adjustedP[i][4]);
}
if(Rom){
out+="&" + nf6.format(adjustedP[i][5]);
}
if(Finner){
out+="&" + nf6.format(adjustedP[i][6]);
}
if(Li){
out+="&" + nf6.format(adjustedP[i][7]);
}
out+="\\\\";
}
out+="\\hline\n" + "\\end{tabular}\n\\caption{Adjusted $p$-values (QUADE) (II)}\n" + "\\end{table}\n";
}
out+="\\end{landscape}\\end{document}";
return out;
}//end-method
/**
* Computes ROM adjusted p-values
*
* @param alpha Alpha value
* @param vector Array with the unadjusted p-values
* @param adjusted Array to store the p-values
*
*/
public static void calcularROM(double alpha, double vector[], double adjusted[]) {
int i, j;
int m;
double suma1, suma2;
m = vector.length;
vector[m-1] = alpha;
vector[m-2] = alpha/2.0;
adjusted[m-1] = 1;
adjusted[m-2] = 2;
for (i=3; i<=m; i++) {
suma1 = suma2 = 0;
for (j=1;j<(i-1);j++) {
suma1 += Math.pow(alpha, (double)j);
}
for (j=1;j<(i-2);j++){
suma2 += combinatoria(j,i)*Math.pow(vector[m-j-1], (double)(i-j));
}
vector[m-i] = (suma1-suma2)/(double)i;
adjusted[m-i] = vector[m-1] / vector[m-i];
}
}//end-method
/**
* Computes the (N/M) combinatory number
*
* @param m N value
* @param n M value
*
* @return The (N/M) combinatory number
*/
public static double combinatoria (int m, int n) {
double result = 1;
int i;
if (n >= m) {
for (i=1; i<=m; i++)
result *= (double)(n-m+i)/(double)i;
} else {
result = 0;
}
return result;
}//end-method
/**
* Computes the Chi Square distribution
*
* @param x X value
* @param n N value
*
* @return The Chi Square value
*/
private static double ChiSq(double x, int n) {
if (n == 1 & x > 1000) {
return 0;
}
if (x > 1000 | n > 1000) {
double q = ChiSq((x - n) * (x - n) / (2 * n), 1) / 2;
if (x > n) {
return q;
}
{
return 1 - q;
}
}
double p = Math.exp( -0.5 * x);
if ((n % 2) == 1) {
p = p * Math.sqrt(2 * x / Math.PI);
}
double k = n;
while (k >= 2) {
p = p * x / k;
k = k - 2;
}
double t = p;
double a = n;
while (t > 0.0000000001 * p) {
a = a + 2;
t = t * x / a;
p = p + t;
}
return 1 - p;
}//end-method
/**
* Computes the Fisher distribution
* @param f F value
* @param n1 N1 value
* @param n2 N2 value
*
* @return The Fisher value
*/
private static double FishF(double f, int n1, int n2) {
double x = n2 / (n1 * f + n2);
if ((n1 % 2) == 0) {
return StatCom(1 - x, n2, n1 + n2 - 4, n2 - 2) * Math.pow(x, n2 / 2.0);
}
if ((n2 % 2) == 0) {
return 1 -
StatCom(x, n1, n1 + n2 - 4, n1 - 2) *
Math.pow(1 - x, n1 / 2.0);
}
double th = Math.atan(Math.sqrt(n1 * f / (1.0*n2)));
double a = th / (Math.PI / 2.0);
double sth = Math.sin(th);
double cth = Math.cos(th);
if (n2 > 1) {
a = a +
sth * cth * StatCom(cth * cth, 2, n2 - 3, -1) / (Math.PI / 2.0);
}
if (n1 == 1) {
return 1 - a;
}
double c = 4 * StatCom(sth * sth, n2 + 1, n1 + n2 - 4, n2 - 2) * sth *
Math.pow(cth, n2) / Math.PI;
if (n2 == 1) {
return 1 - a + c / 2.0;
}
int k = 2;
while (k <= (n2 - 1) / 2.0) {
c = c * k / (k - .5);
k = k + 1;
}
return 1 - a + c;
}//end-method
/**
* Computes the statCom distribution
* @param q Q value
* @param i I value
* @param j J value
* @param b B value
*
* @return The statCom value
*/
private static double StatCom(double q, int i, int j, int b) {
double zz = 1;
double z = zz;
int k = i;
while (k <= j) {
zz = zz * q * k / (k - b);
z = z + zz;
k = k + 2;
}
return z;
}//end-method
/**
* Prints as many "c" as desired
*
* @param n Number of "c" to print
*
* @return A string with all the "c"s
*/
public static String printC(int n){
String out="";
for(int i=0;i<n;i++){
out+="c";
}
return out;
}//end-method
/**
* <p>
* This method decodes composes the header of the LaTeX file where the results are saved
* </p>
* @return A string with the header of the LaTeX file
*/
private static String header() {
String output = new String("");
output += "\\documentclass[a4paper,10pt]{article}\n";
output += "\\usepackage{graphicx}\n";
output += "\\usepackage{lscape}\n";
output += "\\title{Output tables for 1xN statistical comparisons.}\n";
output += "\\author{}\n\\date{\\today}\n\\begin{document}\n";
output += "\\begin{landscape}\n\\pagestyle{empty}\n\\maketitle\n\\thispagestyle{empty}\n";
return output;
}//end-method
}//end-class