/*********************************************************************** 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/ **********************************************************************/ /* SADE.java Isaac Triguero Velazquez. Created by Isaac Triguero Velazquez 23-7-2009 Copyright (c) 2008 __MyCompanyName__. All rights reserved. */ package keel.Algorithms.Instance_Generation.SADE; import keel.Algorithms.Instance_Generation.Basic.PrototypeSet; import keel.Algorithms.Instance_Generation.Basic.PrototypeGenerator; import keel.Algorithms.Instance_Generation.Basic.Prototype; import keel.Algorithms.Instance_Generation.Basic.PrototypeGenerationAlgorithm; import keel.Algorithms.Instance_Generation.Chen.ChenGenerator; import keel.Algorithms.Instance_Generation.HYB.HYBGenerator; import keel.Algorithms.Instance_Generation.*; import java.util.*; import keel.Algorithms.Instance_Generation.utilities.*; import keel.Algorithms.Instance_Generation.utilities.KNN.*; import org.core.*; import org.core.*; import java.util.StringTokenizer; /** * @param k Number of neighbors * @param Population Size. * @param ParticleSize. * @param Scaling Factor. * @param Crossover rate. * @param Strategy (1-5). * @param MaxIter * @author Isaac Triguero * @version 1.0 */ public class SADEGenerator extends PrototypeGenerator { /*Own parameters of the algorithm*/ // We need the variable K to use with k-NN rule private int k; private int PopulationSize; private double ParticleSize; private int MaxIter; private double ScalingFactor; private double CrossOverRate[]; private int LearningPeriod; private int Strategy; protected int numberOfPrototypes; // Particle size is the percentage protected int numberOfStrategies; // number of strategies in the pool protected int numberOfClass; /** Parameters of the initial reduction process. */ private String[] paramsOfInitialReducction = null; /** * Build a new SADEGenerator Algorithm * */ public SADEGenerator(PrototypeSet _trainingDataSet, int neigbors,int poblacion, int perc, int iteraciones) { super(_trainingDataSet); algorithmName="SADE"; this.k = neigbors; this.PopulationSize = poblacion; this.ParticleSize = perc; this.MaxIter = iteraciones; this.numberOfPrototypes = getSetSizeFromPercentage(perc); } /** * Build a new SADEGenerator Algorithm * @param t Original prototype set to be reduced. * @param parameters Parameters of the algorithm (only % of reduced set). */ public SADEGenerator(PrototypeSet t, Parameters parameters) { super(t, parameters); algorithmName="SADE"; this.k = parameters.getNextAsInt(); this.PopulationSize = parameters.getNextAsInt(); this.ParticleSize = parameters.getNextAsDouble(); this.MaxIter = parameters.getNextAsInt(); this.LearningPeriod = parameters.getNextAsInt(); this.numberOfStrategies = parameters.getNextAsInt(); this.numberOfPrototypes = getSetSizeFromPercentage(ParticleSize); this.numberOfClass = trainingDataSet.getPosibleValuesOfOutput().size(); System.out.print("\nIsaac dice: " + k + " Swar= "+PopulationSize+ " Particle= "+ ParticleSize + " Maxiter= "+ MaxIter+" LP= "+this.LearningPeriod+ "\n"); //numberOfPrototypes = getSetSizeFromPercentage(parameters.getNextAsDouble()); } /** * I modified the order of the list of strategies, i need it because i want to do the Same POOL like the paper. * Original POOL = DE/Rand/1/bin. | DE/rand-to-best/2/bin | De/Rand/2/bin | DE/current-to-rand/1/arithmetic * @param population * @param actual * @param mejor */ public PrototypeSet mutant(PrototypeSet population[], int actual, int mejor){ PrototypeSet mutant = new PrototypeSet(population.length); PrototypeSet r1,r2,r3,r4,r5, resta, producto, resta2, producto2, result, producto3, resta3; //We need three differents solutions of actual int lista[] = new int[population.length]; inic_vector_sin(lista,actual); desordenar_vector_sin(lista); // System.out.println("Lista = "+lista[0]+","+ lista[1]+","+lista[2]); r1 = population[lista[0]]; r2 = population[lista[1]]; r3 = population[lista[2]]; r4 = population[lista[3]]; r5 = population[lista[4]]; switch(this.Strategy){ case 1: // ViG = Xr1,G + F(Xr2,G - Xr3,G) De rand 1 resta = r2.restar(r3); producto = resta.mulEscalar(this.ScalingFactor); mutant = producto.sumar(r1); break; case 2: //DE rand 2 resta = r2.restar(r3); resta2 = r4.restar(r5); producto = resta.mulEscalar(this.ScalingFactor); producto2 = resta2.mulEscalar(this.ScalingFactor); result = r1.sumar(producto); mutant = result.sumar(producto2); break; case 3: //DE rand to best 2 resta = r1.restar(r2); resta2 = r3.restar(r4); resta3 = population[mejor].restar(population[actual]); producto = resta.mulEscalar(this.ScalingFactor); producto2 = resta2.mulEscalar(this.ScalingFactor); producto3 = resta3.mulEscalar(this.ScalingFactor); result = population[actual].sumar(producto); result = result.sumar(producto2); mutant = result.sumar(producto3); break; case 4: //DE current to rand 1 resta = r1.restar(population[actual]); resta2 = r2.restar(r3); producto = resta.mulEscalar(RandomGenerator.Randdouble(0, 1)); producto2 = resta2.mulEscalar(this.ScalingFactor); result = population[actual].sumar(producto); mutant = result.sumar(producto2); break; case 5: // Vig = Xbest,G + F(Xr2,G - Xr3,G) De best 1 resta = r2.restar(r3); producto = resta.mulEscalar(this.ScalingFactor); mutant = population[mejor].sumar(producto); break; case 6: // Vig = ... De rand to best 1 resta = r1.restar(r2); resta2 = population[mejor].restar(population[actual]); producto = resta.mulEscalar(this.ScalingFactor); producto2 = resta2.mulEscalar(this.ScalingFactor); result = population[actual].sumar(producto); mutant = result.sumar(producto2); break; case 7: // DE best 2 resta = r1.restar(r2); resta2 = r3.restar(r4); producto = resta.mulEscalar(this.ScalingFactor); producto2 = resta2.mulEscalar(this.ScalingFactor); result = population[mejor].sumar(producto); mutant = result.sumar(producto2); break; } // System.out.println("********Mutante**********"); // mutant.print(); mutant.applyThresholds(); //System.out.println("********Mutante Reformado**********"); // mutant.print(); return mutant; } public double Skg (int strategy, int successRate[][], int failureRate[][]){ double numerator=0, denominator=0; for(int k=0; k<this.LearningPeriod; k++){ numerator += successRate[k][strategy]; denominator += successRate[k][strategy] + failureRate[k][strategy]; } double SKG = numerator/denominator + 0.01; // Add epsilon 0.01 return SKG; } /* * The probability of use the K strategy is: pk,G = SkG / SUM(Sk,g). */ public double updateProbability(int strategy,int successRate[][],int failureRate[][]){ double numerator=0, denominator =0; numerator =Skg(strategy,successRate, failureRate); for(int i =0; i< this.numberOfStrategies;i++){ denominator+=Skg(i,successRate, failureRate); } return (numerator/denominator); } /** * I use this function to calculate what strategy we must use with the probability strategy we have. * @param ProbabilityStrategy * */ public int selectStrategy(double ProbabilityStrategy[]){ double random=RandomGenerator.Randdouble(0, 1); //System.out.println("Random = "+random); double aux =0; boolean end = false; int selected=1; for(int i=0; i< this.numberOfStrategies && !end; i++){ aux += ProbabilityStrategy[i]; if(random <= aux){ selected = i+1; // because we count 1..to 7 strategy. end =true; } } return selected; } /** * Generate a reduced prototype set by the SADEGenerator method. * @return Reduced set by SADEGenerator's method. */ public PrototypeSet reduceSet() { System.out.print("\nThe algorithm SADE is starting...\n Computing...\n"); System.out.println("Number of prototypes, result set = "+numberOfPrototypes+ "\n"); if(numberOfPrototypes < trainingDataSet.getPosibleValuesOfOutput().size()){ System.out.println("Number of prototypes less than the number of clases"); numberOfPrototypes = trainingDataSet.getPosibleValuesOfOutput().size(); } System.out.println("Reduction %, result set = "+((trainingDataSet.size()-numberOfPrototypes)*100)/trainingDataSet.size()+ "\n"); // trainingDataSet.print(); //Algorithm // First, we create the population, with PopulationSize. // like a prototypeSet's vector. PrototypeSet nominalPopulation; PrototypeSet population [] = new PrototypeSet [PopulationSize]; PrototypeSet mutation[] = new PrototypeSet[PopulationSize]; PrototypeSet crossover[] = new PrototypeSet[PopulationSize]; // Variables necesarias para hacer el algoritmo adaptativo. int kStrategies = this.numberOfStrategies; double ProbabilityStrategy[] = new double[kStrategies]; double CRmk[] = new double[kStrategies]; double CRmemory[][] = new double[this.LearningPeriod][]; double CRm=0.5; int successRate[][] = new int[this.LearningPeriod][]; int failureRate[][] = new int[this.LearningPeriod][]; for(int i=0; i<this.LearningPeriod; i++){ successRate[i] = new int[kStrategies]; failureRate[i] = new int[kStrategies]; CRmemory[i] = new double[kStrategies]; for(int j=0; j<kStrategies; j++){ successRate[i][j] = 1; failureRate[i][j] = 1; CRmemory[i][j] = 0.5; } } /* In SaDE algorithm, the initial probability of use each strategy * is 1/kStrategies. */ for(int i=0; i<ProbabilityStrategy.length; i++){ ProbabilityStrategy[i] = 1./kStrategies; CRmk[i] = 0.5; // Initial 0.5 } //each Strategy has different CR. this.CrossOverRate= new double[this.numberOfStrategies]; double F[] = new double[this.PopulationSize]; double fitness[] = new double[PopulationSize]; double fitness_bestPopulation[] = new double[PopulationSize]; PrototypeSet bestParticle = new PrototypeSet(); //Each particle must have Particle Size % // First Stage, Initialization. Todas las particulas "IGUALES" structura population[0]=selecRandomSet(numberOfPrototypes,true).clone() ; fitness[0] = accuracy(population[0],trainingDataSet); // Aseguro que al menos hay un representante de cada clase. PrototypeSet clases[] = new PrototypeSet [this.numberOfClass]; for(int i=0; i< this.numberOfClass; i++){ clases[i] = new PrototypeSet(trainingDataSet.getFromClass(i)); } for(int i=0; i< population[0].size(); i++){ for(int j=0; j< this.numberOfClass; j++){ if(population[0].getFromClass(j).size() ==0 && clases[j].size()!=0){ population[0].add(clases[j].getRandom()); } } } for(int i=1; i< PopulationSize; i++){ population[i] = new PrototypeSet(); for(int j=0; j< population[0].size(); j++){ population[i].add(trainingDataSet.getFromClass(population[0].get(j).getOutput(0)).getRandom()); } fitness[i] = accuracy(population[i],trainingDataSet); // SADE fitness } //We select the best initial particle double bestFitness=fitness[0]; int bestFitnessIndex=0; for(int i=1; i< PopulationSize;i++){ if(fitness[i]>bestFitness){ bestFitness = fitness[i]; bestFitnessIndex=i; } } for(int j=0;j<PopulationSize;j++){ //Now, I establish the index of each prototype. for(int i=0; i<population[j].size(); ++i) population[j].get(i).setIndex(i); } //Step 3: for(int iter=1; iter<= MaxIter; iter++){ // Main loop //Step 3.1 if(iter%this.LearningPeriod == 0){ // if G > LP for(int k=0; k<kStrategies; k++){ // Update Pk,G -> PjIter ProbabilityStrategy[k]= updateProbability(k, successRate, failureRate); // System.out.println("Prob Strategy j= "+k+ " -> "+ ProbabilityStrategy[k]); // Remove the first element of Success and failure memory. successRate[iter%this.LearningPeriod][k]= 0; failureRate[iter%this.LearningPeriod][k] =0; } // System.out.println("********"); } /* Step 3.2.*/ // Assign trial vector generation strategy: Lo eligo a posteriori antes de cada llamada a mutaci�n. //System.out.println("Aplicamos las estrategia = "+ this.Strategy); // assign control parameter F . N(0.5,0.3) // if Z sigue una distrubuci�n 0,1, X = sigma*Z + mu sigue la dis n(mu,sigma) for(int i=0; i< this.PopulationSize; i++){ F[i]= RandomGenerator.RandGaussian()*0.3 + 0.5; } // System.out.println("Scaling Factor = "+ this.ScalingFactor); // Correcto /* Assign control parameter CR */ if(iter%this.LearningPeriod == 0){ for(int k=0; k< this.numberOfStrategies; k++){ CRmk[k] = 0 ; for(int m=0; m< this.LearningPeriod; m++){ CRmk[k] += CRmemory[m][k]; } CRmk[k] /= this.LearningPeriod; } } for (int k=0; k< this.numberOfStrategies; k++){ this.CrossOverRate[k] = RandomGenerator.RandGaussian()*0.1 + CRmk[k]; while( this.CrossOverRate[k] < 0 || this.CrossOverRate[k]>1){ this.CrossOverRate[k] = RandomGenerator.RandGaussian()*0.1 + CRmk[k]; } } //System.out.println("CR k= " + this.CrossOverRate[this.Strategy-1]); /* Step 3.3*/ for(int i=0; i<PopulationSize; i++){ // Assign trial vector generation strategy this.Strategy = selectStrategy(ProbabilityStrategy); // cada estrategia se elige antes de cada //Second: Mutation Operation. // I want to generate a PrototypeSet Mutation for each item of the population. this.ScalingFactor = F[i]; mutation[i] = new PrototypeSet(population[i].size()); // Pasamos la poblaci�n, y la mejor actual, por si se usa /best/ mutation[i] = mutant(population, i,bestFitnessIndex).clone(); // Third: Crossver Operation. // Now, we decide if the mutation will be the trial vector. crossover[i] = new PrototypeSet(population[i]); if(this.Strategy !=4){ for(int j=0; j< population[i].size(); j++){ // For each part of the solution double randNumber = RandomGenerator.Randdouble(0, 1); if(randNumber<this.CrossOverRate[this.Strategy-1]){ crossover[i] = mutation[i].clone(); // Overwrite. } } }else{ // if we use currento-rand, "there is no crossover, It's ready in mutation operator" crossover[i] = mutation[i].clone(); // Overwrite. } // Fourth: Selection Operation. // Decide if the trial vector is better than initial population. //Crossover has the trialVector, we check its fitness. nominalPopulation = new PrototypeSet(); nominalPopulation.formatear(population[i]); fitness[i] = accuracy(nominalPopulation,trainingDataSet); nominalPopulation = new PrototypeSet(); nominalPopulation.formatear(crossover[i]); double trialVector = accuracy(nominalPopulation,trainingDataSet); //double trialVector = accuracy(crossover[i],trainingDataSet); //fitness[i] = accuracy(population[i],trainingDataSet); //System.out.println("Trial Vector fitness = "+ trialVector); //System.out.println("fitness de la particula = "+ fitness[i]); if(trialVector > fitness[i]){ // System.out.println("Selecting"); // Actualizo el SuccesRate de esta strategia successRate[iter%this.LearningPeriod][this.Strategy-1]++; CRmemory[iter%this.LearningPeriod][this.Strategy-1] = this.CrossOverRate[this.Strategy-1]; population[i] = crossover[i].clone(); fitness[i] = trialVector; }else{ // Actualizo el FailureRate de esta estrategia. failureRate[iter%this.LearningPeriod][this.Strategy-1]++; } //fitness[i] = accuracy(population[i],trainingDataSet); if(fitness[i]>bestFitness){ bestFitness = fitness[i]; bestFitnessIndex=i; System.out.println("Iter="+ iter +" Acc= "+ bestFitness); } } } nominalPopulation = new PrototypeSet(); nominalPopulation.formatear(population[bestFitnessIndex]); System.err.println("\n% de acierto en training Nominal " + KNN.classficationAccuracy(nominalPopulation,trainingDataSet,1)*100./trainingDataSet.size() ); //nominalPopulation.print(); return nominalPopulation; } /** * General main for all the prototoype generators * Arguments: * 0: Filename with the training data set to be condensed. * 1: Filename which contains the test data set. * 3: Seed of the random number generator. Always. * ************************** * 4: .Number of neighbors * 5: Swarm Size * 6: Particle Size * 7: Max Iter * 8: C1 * 9: c2 * 10: vmax * 11: wstart * 12: wend * @param args Arguments of the main function. */ public static void main(String[] args) { Parameters.setUse("SADE", "<seed> <Number of neighbors>\n<Swarm size>\n<Particle Size>\n<MaxIter>\n<DistanceFunction>"); Parameters.assertBasicArgs(args); PrototypeSet training = PrototypeGenerationAlgorithm.readPrototypeSet(args[0]); PrototypeSet test = PrototypeGenerationAlgorithm.readPrototypeSet(args[1]); long seed = Parameters.assertExtendedArgAsInt(args,2,"seed",0,Long.MAX_VALUE); SADEGenerator.setSeed(seed); int k = Parameters.assertExtendedArgAsInt(args,3,"number of neighbors", 1, Integer.MAX_VALUE); int swarm = Parameters.assertExtendedArgAsInt(args,4,"swarm size", 1, Integer.MAX_VALUE); int particle = Parameters.assertExtendedArgAsInt(args,5,"particle size", 1, Integer.MAX_VALUE); int iter = Parameters.assertExtendedArgAsInt(args,6,"max iter", 1, Integer.MAX_VALUE); double c1 = Parameters.assertExtendedArgAsInt(args,7,"c1", 1, Double.MAX_VALUE); double c2 =Parameters.assertExtendedArgAsInt(args,8,"c2", 1, Double.MAX_VALUE); double vmax =Parameters.assertExtendedArgAsInt(args,9,"vmax", 1, Double.MAX_VALUE); double wstart = Parameters.assertExtendedArgAsInt(args,10,"wstart", 1, Double.MAX_VALUE); double wend =Parameters.assertExtendedArgAsInt(args,11,"wend", 1, Double.MAX_VALUE); //String[] parametersOfInitialReduction = Arrays.copyOfRange(args, 4, args.length); //System.out.print(" swarm ="+swarm+"\n"); SADEGenerator generator = new SADEGenerator(training, k,swarm,particle,iter); PrototypeSet resultingSet = generator.execute(); //resultingSet.save(args[1]); //int accuracyKNN = KNN.classficationAccuracy(resultingSet, test, k); int accuracy1NN = KNN.classficationAccuracy(resultingSet, test); generator.showResultsOfAccuracy(Parameters.getFileName(), accuracy1NN, test); } }