/** It applies the reproduction stage */ 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); } }
/** * It reads the data from the input files (training, validation and test) and parse all the * parameters from the parameters array. * * @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]; }
/** * It Evaluates the performance of the best evolved fuzzy system on test data. The Mean Square * Error (MSE) is used * * @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); }
/** It creates a fuzzy system containing Nr rules from the population */ 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--; } }
/** * 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 * * @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); }
/** It launches the algorithm */ 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."); } }