/*********************************************************************** 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/ **********************************************************************/ package keel.Algorithms.RE_SL_Methods.SEFC; /** * <p> * @author Written by Francisco Jos� Berlanga (University of Ja�n) 01/01/2007 * @version 1.0 * @since JDK 1.6 * </p> */ import java.io.IOException; import java.util.*; import org.core.*; public class Algorithm { /** * <p> * It contains the implementation of the algorithm * </p> */ myDataset train, val, test; String outputTr, outputTst, outputBC; double classProb[]; double attrProb[][][]; //atribute value, atribute position, class int entradas; ArrayList<Individual> Poblacion; ArrayList<Individual> Poblacion2; ArrayList<Individual> Hijos; ArrayList<Individual> SistemaDifuso; ArrayList<Individual> BestSistemaDifuso; long semilla; int tamPoblacion, Nf, Nr, Gen, GenSincambio, numGeneraciones, K, numGenMigration; double probMut, Bestperformance; int [] vectorNr; //We may declare here the algorithm's parameters private boolean somethingWrong = false; //to check if everything is correct. /** * <p> * Default constructor * </p> */ public Algorithm() { } /** * <p> * It reads the data from the input files (training, validation and test) and parse all the parameters * from the parameters array. * </p> * @param parameters parseParameters It contains the input files, output files and parameters */ public Algorithm(parseParameters parameters) { train = new myDataset(); val = new myDataset(); test = new myDataset(); try { System.out.println("\nReading the training set: " + parameters.getTrainingInputFile()); train.readRegressionSet(parameters.getTrainingInputFile(), true); System.out.println("\nReading the validation set: " + parameters.getValidationInputFile()); val.readRegressionSet(parameters.getValidationInputFile(), false); System.out.println("\nReading the test set: " + parameters.getTestInputFile()); test.readRegressionSet(parameters.getTestInputFile(), false); } catch (IOException e) { System.err.println( "There was a problem while reading the input data-sets: " + e); somethingWrong = true; } //We may check if there are some numerical attributes, because our algorithm may not handle them: //somethingWrong = somethingWrong || train.hasNumericalAttributes(); //somethingWrong = somethingWrong || train.hasMissingAttributes(); outputTr = parameters.getTrainingOutputFile(); outputTst = parameters.getTestOutputFile(); outputBC = parameters.getOutputFile(0); //Now we parse the parameters, for example: semilla = Long.parseLong(parameters.getParameter(0)); //... tamPoblacion = Integer.parseInt(parameters.getParameter(1)); numGeneraciones = Integer.parseInt(parameters.getParameter(2)); numGenMigration = Integer.parseInt(parameters.getParameter(3)); Nr = Integer.parseInt(parameters.getParameter(4)); Nf = Integer.parseInt(parameters.getParameter(5)); K = Integer.parseInt(parameters.getParameter(6)); probMut = Double.parseDouble(parameters.getParameter(7)); entradas = train.getnInputs(); Poblacion = new ArrayList<Individual>(tamPoblacion); for (int i = 0; i < tamPoblacion; i++) { Individual indi = new Individual(entradas); Poblacion.add(indi); } Poblacion2 = new ArrayList<Individual>(tamPoblacion); Hijos = new ArrayList<Individual>(tamPoblacion / 2); SistemaDifuso = new ArrayList<Individual>(Nr); BestSistemaDifuso = new ArrayList<Individual>(Nr); vectorNr = new int[Nr]; } /** * <p> * It launches the algorithm * </p> */ public void execute() { int i, j, num; double fitness, fitness2; if (somethingWrong) { //We do not execute the program System.err.println("An error was found, either the data-set have numerical values or missing values."); System.err.println("Aborting the program"); //We should not use the statement: System.exit(-1); } else { //We do here the algorithm's operations Randomize.setSeed(semilla); /* Generation of the initial population */ System.out.println("Creating the initial population."); initializePopulation(); Gen = 0; GenSincambio = 0; Bestperformance = -1.0; /* Main of the genetic algorithm */ System.out.println("Starting the evolutionary process."); do { /* First, all rules' fitness is set to 0 */ for(i = 0; i < tamPoblacion; i++){ Poblacion.get(i).fitness = 0.0; Poblacion.get(i).n_SistemasDifusos = 0; } /* Then Nf fuzzy system are created */ for(i = 0; i < Nf; i++){ /* A fuzzy system containing Nr rules from the population is created */ Create_fuzzy_system(); /* The fitness asociated to this fuzzy system is calculated */ fitness = Evaluate_fuzzy_system(); /* The fitness value is accumulated among the rules in the fuzzy system */ Accumulate_fitness_fuzzy_system(fitness); /* If the fitness of the current fuzzy system outperforms the best evolved one, we update this last one */ if(fitness > Bestperformance){ Bestperformance = fitness; GenSincambio = -1; BestSistemaDifuso.clear(); for(j = 0; j < Nr; j++){ Individual indi = new Individual(Poblacion.get(vectorNr[j])); BestSistemaDifuso.add(indi); } } } /* The accumulated fitness value of each individual in the population is divided by the number of times it has been selected */ for (i = 0; i < tamPoblacion; i++) { if (Poblacion.get(i).n_SistemasDifusos != 0) { Poblacion.get(i).fitness /= Poblacion.get(i).n_SistemasDifusos; } else { Poblacion.get(i).fitness = 0.0; } /* Now we count the number of parameter used in the consequent, in order to give a better fitness to those rules with a lower number of parameters */ num = 0; for(j = 0; j < entradas; j++){ if(Poblacion.get(i).consecuente[j] != 0.0){ num++; } } if(Poblacion.get(i).consecuente[entradas] != 0.0){ num++; } Poblacion.get(i).fitness /= (K + num); } /* we increment the counter of the number of generations */ Gen++; GenSincambio++; if(GenSincambio == numGenMigration){ /* Migration stage: half of the population (the worst one) is radomly generated again to increase the searching ability of the genetic process */ System.out.println("Migrating half of the population in order to restart the evolutionary process."); Migration(); GenSincambio = 0; } else{ /* Reproduction stage (includes crossover) */ Reproduction(); /* Mutation */ Mutation(); } System.out.println("Iteration: " + Gen + ". Best fitness: " + (1.0 / Bestperformance)); } while (Gen <= numGeneraciones); String salida = new String(""); salida += Print_Population(); SistemaDifuso.clear(); for(i = 0; i < Nr; i++){ Individual indi = new Individual(BestSistemaDifuso.get(i)); SistemaDifuso.add(indi); } salida += "MSE Training:\t" + (1.0 / Bestperformance) + "%\n"; salida += "MSE Test:\t\t" + Evaluate_best_fuzzy_system_in_test() + "%\n\n"; Files.writeFile(outputBC, salida); doOutput(this.val, this.outputTr); doOutput(this.test, this.outputTst); System.out.println("Algorithm Finished."); } } /** * <p> * It initializes each individual in the population * </p> */ void initializePopulation() { int i, j, num; double u; for (j = 0; j < tamPoblacion; j++) { /* First, the antecedent */ for (i = 0; i < entradas; i++) { Poblacion.get(j).antecedente[i].m = Randomize.RanddoubleClosed(train.getMin(i), train.getMax(i)); Poblacion.get(j).antecedente[i].sigma = Randomize.RandintClosed(1, 4); } /* Secondly, the consequent */ do{ num = 0; for (i = 0; i < entradas; i++) { u = Randomize.RandClosed(); /* The term is used in the consequent */ if (u < 0.5) { Poblacion.get(j).consecuente[i] = Randomize.RanddoubleClosed(-1.0, 1.0); // Poblacion.get(j).consecuente[i] = Randomize.RanddoubleClosed(train.getMin(i) - 45.0, train.getMax(i) + 45.0); // Poblacion.get(j).consecuente[i] = Randomize.RanddoubleClosed(-45.0, 45.0); if(Poblacion.get(j).consecuente[i] != 0.0){ num++; } } /* The term is NOT used in the consequent */ else { Poblacion.get(j).consecuente[i] = 0.0; } } u = Randomize.RandClosed(); /* The term is used in the consequent */ if (u < 0.5) { // Poblacion.get(j).consecuente[entradas] = Randomize.RanddoubleClosed( - 45.0, 45.0); Poblacion.get(j).consecuente[entradas] = Randomize.RanddoubleClosed(-1.0 * ((train.getMax(entradas) - train.getMin(entradas)) / 2.0), ((train.getMax(entradas) - train.getMin(entradas)) / 2.0)); if(Poblacion.get(j).consecuente[entradas] != 0.0){ num++; } } /* The term is NOT used in the consequent */ else { Poblacion.get(j).consecuente[entradas] = 0.0; } } while (num == 0); } } /** * <p> * It creates a fuzzy system containing Nr rules from the population * </p> */ void Create_fuzzy_system(){ int i, pos, tam; int [] vector = new int[tamPoblacion]; for (i = 0; i < tamPoblacion; i++){ vector[i] = i; } tam = tamPoblacion; SistemaDifuso.clear(); for (i = 0; i < Nr; i++){ pos = Randomize.RandintClosed(0, tam-1); Poblacion.get(vector[pos]).n_SistemasDifusos++; Individual indi = new Individual(Poblacion.get(vector[pos])); SistemaDifuso.add(indi); vectorNr[i] = vector[pos]; vector[pos] = vector[tam-1]; tam--; } } /** * <p> * It Evaluates the performance of the fuzzy system. The Mean Square Error (MSE) by training is used * </p> */ public double Evaluate_fuzzy_system(){ int i; double result, suma, fuerza; suma = 0.0; for (i = 0; i < train.getnData(); i++){ fuerza = Output_fuzzy_system(train.getExample(i)); suma += Math.pow(train.getOutputAsReal(i) - fuerza, 2.0); } result = suma / train.getnData(); /* We want to have a maximization problem so, we invert the error */ if(result != 0.0){ result = 1.0 / result; } return(result); } /** * <p> * It accumulates de fitness value (obtained by the evaluation function) among all the rules forming the fuzzy system * </p> * @param valor double The fitness value obtained by the evaluation function */ void Accumulate_fitness_fuzzy_system(double valor){ int i; for(i = 0; i < Nr; i++){ Poblacion.get(vectorNr[i]).fitness += (valor / Nr); } } /** * <p> * It applies the migration stage * </p> */ void Migration() { int i, j, num; double u; /* First, the individual in the population are ordered according to their fitness */ Collections.sort(Poblacion); /* The second half (the worst one) is radomly initialized again */ for (j = (tamPoblacion / 2); j < tamPoblacion; j++) { /* First, the antecedent */ for (i = 0; i < entradas; i++) { Poblacion.get(j).antecedente[i].m = Randomize.RanddoubleClosed(train.getMin(i), train.getMax(i)); Poblacion.get(j).antecedente[i].sigma = Randomize.RandintClosed(1, 4); } /* Secondly, the consequent */ do{ num = 0; for (i = 0; i < entradas; i++) { u = Randomize.RandClosed(); /* The term is used in the consequent */ if(u < 0.5){ Poblacion.get(j).consecuente[i] = Randomize.RanddoubleClosed(-1.0, 1.0); // Poblacion.get(j).consecuente[entradas] = Randomize.RanddoubleClosed(-45.0, 45.0); if(Poblacion.get(j).consecuente[i] != 0.0){ num++; } } /* The term is NOT used in the consequent */ else{ Poblacion.get(j).consecuente[i] = 0.0; } } u = Randomize.RandClosed(); /* The term is used in the consequent */ if(u < 0.5){ Poblacion.get(j).consecuente[entradas] = Randomize.RanddoubleClosed(-1.0 * ((train.getMax(entradas) - train.getMin(entradas)) / 2.0), ((train.getMax(entradas) - train.getMin(entradas)) / 2.0)); // Poblacion.get(j).consecuente[entradas] = Randomize.RanddoubleClosed(-45.0, 45.0); // Poblacion.get(j).consecuente[entradas] = Randomize.RanddoubleClosed(train.getMin(entradas), train.getMax(entradas)); if(Poblacion.get(j).consecuente[entradas] != 0.0){ num++; } } /* The term is NOT used in the consequent */ else{ Poblacion.get(j).consecuente[entradas] = 0.0; } } while(num == 0); } } /** * <p> * It applies the reproduction stage * </p> */ void Reproduction(){ int i, madre, padre; /* First, the individual in the population are ordered according to their fitness */ Collections.sort(Poblacion); /* Create the new population */ Poblacion2.clear(); Hijos.clear(); /* Top-half best-performing individuals will advance to the next generation */ for(i = 0; i < (tamPoblacion / 2); i++){ Individual indi = new Individual(Poblacion.get(i)); Poblacion2.add(indi); } /* The remaining half is generated by performing crossover operations on individuals in the top half */ while(Poblacion.size() != (Poblacion2.size() + Hijos.size())){ /* 2 parents are selected */ madre = Selection(); do{ padre = Selection(); } while (madre == padre); /* 2 children are created by crossover operator */ Crossover(madre, padre); } /* Create the population for the next generation */ Poblacion.clear(); for(i = 0; i < Poblacion2.size(); i++){ Individual indi = new Individual(Poblacion2.get(i)); Poblacion.add(indi); } for(i = 0; i < Hijos.size(); i++){ Individual indi = new Individual(Hijos.get(i)); Poblacion.add(indi); } } /** * <p> * It selects one parent to participate in the evolutionary process (by binary tournament selection). * </p> * @param int The position in the population for the selected parent */ int Selection() { int result; int[] indiv = new int[2]; indiv[0] = Randomize.RandintClosed(0, ((tamPoblacion / 2)-2)); do{ indiv[1] = Randomize.RandintClosed(0, ((tamPoblacion / 2) - 2)); } while (indiv[0] == indiv[1]); if(Poblacion2.get(indiv[0]).fitness > Poblacion2.get(indiv[1]).fitness){ result = indiv[0]; } else{ result = indiv[1]; } return(result); } /** * <p> * It applies a One-point Crossover genetic operator between individual in position "madre" and "padre" in the population. * The new generated children (2 descendants) are added in a population of descendants * </p> * @param madre int Parent number 1 is in position "madre" in the population * @param padre int Parent number 2 is in position "padre" in the population */ void Crossover(int madre, int padre) { int i, xpoint, num1, num2; Individual Hijo1 = new Individual(entradas); Individual Hijo2 = new Individual(entradas); boolean salir; do{ salir = true; /* We choose the crossover site */ xpoint = Randomize.RandintClosed(1, ((2 * entradas) + entradas -1)); /* The crossover point is in the antededent part */ if(xpoint < (2 * entradas)){ /* The crossover point does not part a fuzzy set */ if((xpoint % 2) == 0){ for(i = 0; i < (xpoint / 2); i++){ Hijo1.antecedente[i].m = Poblacion2.get(madre).antecedente[i].m; Hijo1.antecedente[i].sigma = Poblacion2.get(madre).antecedente[i].sigma; Hijo2.antecedente[i].m = Poblacion2.get(padre).antecedente[i].m; Hijo2.antecedente[i].sigma = Poblacion2.get(padre).antecedente[i].sigma; } for(i = (xpoint / 2); i < entradas; i++){ Hijo1.antecedente[i].m = Poblacion2.get(padre).antecedente[i].m; Hijo1.antecedente[i].sigma = Poblacion2.get(padre).antecedente[i].sigma; Hijo2.antecedente[i].m = Poblacion2.get(madre).antecedente[i].m; Hijo2.antecedente[i].sigma = Poblacion2.get(madre).antecedente[i].sigma; } } /* The crossover point part a fuzzy set */ else{ for(i = 0; i < ((xpoint - 1) / 2); i++){ Hijo1.antecedente[i].m = Poblacion2.get(madre).antecedente[i].m; Hijo1.antecedente[i].sigma = Poblacion2.get(madre).antecedente[i].sigma; Hijo2.antecedente[i].m = Poblacion2.get(padre).antecedente[i].m; Hijo2.antecedente[i].sigma = Poblacion2.get(padre).antecedente[i].sigma; } Hijo1.antecedente[((xpoint - 1) / 2)].m = Poblacion2.get(madre).antecedente[((xpoint - 1) / 2)].m; Hijo1.antecedente[((xpoint - 1) / 2)].sigma = Poblacion2.get(padre).antecedente[((xpoint - 1) / 2)].sigma; Hijo2.antecedente[((xpoint - 1) / 2)].m = Poblacion2.get(padre).antecedente[((xpoint - 1) / 2)].m; Hijo2.antecedente[((xpoint - 1) / 2)].sigma = Poblacion2.get(madre).antecedente[((xpoint - 1) / 2)].sigma; for(i = ((xpoint + 1) / 2); i < entradas; i++){ Hijo1.antecedente[i].m = Poblacion2.get(padre).antecedente[i].m; Hijo1.antecedente[i].sigma = Poblacion2.get(padre).antecedente[i].sigma; Hijo2.antecedente[i].m = Poblacion2.get(madre).antecedente[i].m; Hijo2.antecedente[i].sigma = Poblacion2.get(madre).antecedente[i].sigma; } } for(i = 0; i < (entradas + 1); i++){ Hijo1.consecuente[i] = Poblacion2.get(padre).consecuente[i]; Hijo2.consecuente[i] = Poblacion2.get(madre).consecuente[i]; } } /* The crossover point is in the consequent part */ else{ for(i = 0; i < entradas; i++){ Hijo1.antecedente[i].m = Poblacion2.get(madre).antecedente[i].m; Hijo1.antecedente[i].sigma = Poblacion2.get(madre).antecedente[i].sigma; Hijo2.antecedente[i].m = Poblacion2.get(padre).antecedente[i].m; Hijo2.antecedente[i].sigma = Poblacion2.get(padre).antecedente[i].sigma; } xpoint -= (2 * entradas); for(i = 0; i < xpoint; i++){ Hijo1.consecuente[i] = Poblacion2.get(madre).consecuente[i]; Hijo2.consecuente[i] = Poblacion2.get(padre).consecuente[i]; } for(i = xpoint; i < entradas; i++){ Hijo1.consecuente[i] = Poblacion2.get(padre).consecuente[i]; Hijo2.consecuente[i] = Poblacion2.get(madre).consecuente[i]; } } num1 = num2 = 0; for(i = 0; i <= entradas; i++){ if(Hijo1.consecuente[i] != 0){ num1++; } if(Hijo2.consecuente[i] != 0){ num2++; } } if((num1 == 0) || (num2 == 0)){ salir = false; } } while(salir == false); /* Add the new 2 children to the offspring population */ Hijos.add(Hijo1); Hijos.add(Hijo2); } /** * <p> * It applies mutation genetic operator * </p> */ void Mutation() { int i, j, aux1, num; double u, u2; for (j = 0; j < tamPoblacion; j++){ /* First, the antecedent */ for (i = 0; i < entradas; i++){ u = Randomize.RandClosed(); if (u < probMut){ Poblacion.get(j).antecedente[i].m = Randomize.RanddoubleClosed(train.getMin(i), train.getMax(i)); } u = Randomize.RandClosed(); if (u < probMut){ aux1 = Poblacion.get(j).antecedente[i].sigma; do{ Poblacion.get(j).antecedente[i].sigma = Randomize.RandintClosed(1, 4); } while (aux1 == Poblacion.get(j).antecedente[i].sigma); } } /* Secondly, the consequent */ num = 0; for (i = 0; i <= entradas; i++){ if(Poblacion.get(j).consecuente[i] != 0.0){ num++; } } for (i = 0; i < entradas; i++){ u = Randomize.RandClosed(); if (u < probMut){ u2 = Randomize.RandClosed(); if (u2 < 0.5){ Poblacion.get(j).consecuente[i] = Randomize.RanddoubleClosed(-1.0, 1.0); } /* The term is NOT used in the consequent */ else { if (num != 1){ Poblacion.get(j).consecuente[i] = 0.0; num--; } } } } u = Randomize.RandClosed(); if (u < probMut){ u2 = Randomize.RandClosed(); if (u2 < 0.5){ Poblacion.get(j).consecuente[entradas] = Randomize.RanddoubleClosed(-1.0 * ((train.getMax(entradas) - train.getMin(entradas)) / 2.0), ((train.getMax(entradas) - train.getMin(entradas)) / 2.0)); // Poblacion.get(j).consecuente[entradas] = Randomize.RanddoubleClosed(-45.0, 45.0); } /* The term is NOT used in the consequent */ else { if (num != 1){ Poblacion.get(j).consecuente[entradas] = 0.0; num--; } } } } } /** * <p> * It calculate the matching degree between the antecedent of the rule and a given example * </p> * @param indiv Individual The individual representing a fuzzy rule * @param ejemplo double [] A given example * @return double The matching degree between the example and the antecedent of the rule */ double Matching_degree(Individual indiv, double[] ejemplo) { int i, sig; double result, suma, numerador, denominador, sigma, ancho_intervalo; suma = 0.0; for (i = 0; i < entradas; i++){ ancho_intervalo = train.getMax(i) - train.getMin(i); sigma = -1.0; sig = indiv.antecedente[i].sigma; switch(sig){ case 1: sigma = 0.3; break; case 2: sigma = 0.4; break; case 3: sigma = 0.5; break; case 4: sigma = 0.6; break; } sigma *= ancho_intervalo; numerador = Math.pow((ejemplo[i] - indiv.antecedente[i].m), 2.0); denominador = Math.pow(sigma, 2.0); suma += (numerador / denominador); } suma *= -1.0; result = Math.exp(suma); return (result); } /** * <p> * Returns the output value for the individual according to the example * </p> * @param indiv Individual The individual enconding a fuzzy rule * @param ejemplo double [] A given example * @return double The output value for the rule */ double Output_value(Individual indiv, double[] ejemplo){ int i; double suma; suma = 0.0; for(i = 0; i < entradas; i++){ suma += (indiv.consecuente[i] * ejemplo[i]); } suma += indiv.consecuente[entradas]; // w0 return (suma); } /** * <p> * It calculate the output of the fuzzy system for a given example * </p> * @param ejemplo double [] A given example * @return double The output value obtained as output of the fuzzy system for a given example */ double Output_fuzzy_system(double[] ejemplo){ int i; double result, suma1, suma2, omega, y; suma1 = suma2 = 0.0; for(i = 0; i < Nr; i++){ omega = Matching_degree(SistemaDifuso.get(i), ejemplo); y = Output_value(SistemaDifuso.get(i), ejemplo); suma1 += (omega * y); suma2 += omega; } if(suma2 != 0.0){ result = suma1 / suma2; } else{ // result = 0.0; result = ((train.getMax(entradas) - train.getMin(entradas)) / 2.0); } return (result); } /** * <p> * It Evaluates the performance of the best evolved fuzzy system on test data. The Mean Square Error (MSE) is used * </p> * @return double The MSE error in test data */ public double Evaluate_best_fuzzy_system_in_test(){ int i; double result, suma, fuerza; SistemaDifuso.clear(); for(i = 0; i < Nr; i++){ Individual indi = new Individual(BestSistemaDifuso.get(i)); SistemaDifuso.add(indi); } suma = 0.0; for (i = 0; i < test.getnData(); i++){ fuerza = Output_fuzzy_system(test.getExample(i)); suma += Math.pow(test.getOutputAsReal(i) - fuerza, 2.0); } result = suma / test.getnData(); return(result); } /** * <p> * It prints the current population as a String * </p> * @return String The current population as a String */ public String Print_Population(){ int i, j, sig; double sigma, ancho_intervalo; boolean anterior_nulo; String output = new String(""); output += "Rule Base with " + Nr + " rules\n\n"; for(i = 0; i < Nr; i++){ output += "Rule " + (i+1) + ": IF "; for(j = 0; j < entradas; j++){ ancho_intervalo = train.getMax(j) - train.getMin(j); sigma = -1.0; sig = BestSistemaDifuso.get(i).antecedente[j].sigma; switch(sig){ case 1: sigma = 0.3; break; case 2: sigma = 0.4; break; case 3: sigma = 0.5; break; case 4: sigma = 0.6; break; } sigma *= ancho_intervalo; output += "X(" + (j+1) + ") is Gaussian(" + BestSistemaDifuso.get(i).antecedente[j].m + ", " + sigma + ")"; if(j != (entradas - 1)){ output += " and "; } } output += " THEN Y = "; anterior_nulo = true; if(BestSistemaDifuso.get(i).consecuente[entradas] != 0.0){ anterior_nulo = false; output += "(" + BestSistemaDifuso.get(i).consecuente[entradas] + ")"; } for(j = 0; j < entradas; j++){ if(BestSistemaDifuso.get(i).consecuente[j] != 0.0){ if(anterior_nulo == false){ output += " + "; } anterior_nulo = false; output += "(" + BestSistemaDifuso.get(i).consecuente[j] + " * X(" + (j+1) + "))"; } } output += "\n\n"; } return(output); } /** * <p> * It generates the output file from a given dataset and stores it in a file * </p> * @param dataset myDataset input dataset * @param filename String the name of the file */ private void doOutput(myDataset dataset, String filename) { int i; double fuerza; String output = new String(""); output = dataset.copyHeader(); //we insert the header in the output file for (i = 0; i < dataset.getnData(); i++){ fuerza = Output_fuzzy_system(dataset.getExample(i)); output += (dataset.getOutputAsReal(i) + " " + fuerza + " " + "\n"); } Files.writeFile(filename, output); } }