/***********************************************************************
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/
**********************************************************************/
/*
IPLDE.java
Isaac Triguero Velazquez.
Created by Isaac Triguero Velazquez 23-7-2009
Copyright (c) 2008 __MyCompanyName__. All rights reserved.
*/
package keel.Algorithms.Instance_Generation.IPLDE;
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.PSO.PSOGenerator;
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 IPLDEGenerator 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 int ParticleSize;
private int MaxIter;
private int iterBasicDE;
private double ScalingFactor;
private double CrossOverRate;
private int Strategy;
private String CrossoverType; // Binomial, Exponential, Arithmetic
private double tau[] = new double[4];
protected int numberOfClass;
protected int numberOfPrototypes; // Particle size is the percentage
/** Parameters of the initial reduction process. */
private String[] paramsOfInitialReducction = null;
private int iterSFGSS;
private int iterSFHC;
/**
* Build a new IPLDEGenerator Algorithm
*/
public IPLDEGenerator(PrototypeSet _trainingDataSet, int neigbors,int poblacion, int perc, int iteraciones, double F, double CR, int strg)
{
super(_trainingDataSet);
algorithmName="IPLDE";
this.k = neigbors;
this.PopulationSize = poblacion;
this.ParticleSize = perc;
this.MaxIter = iteraciones;
this.numberOfPrototypes = getSetSizeFromPercentage(perc);
this.ScalingFactor = F;
this.CrossOverRate = CR;
this.Strategy = strg;
}
/**
* Build a new IPLDEGenerator Algorithm
* @param t Original prototype set to be reduced.
* @param parameters Parameters of the algorithm (only % of reduced set).
*/
public IPLDEGenerator(PrototypeSet t, Parameters parameters)
{
super(t, parameters);
algorithmName="IPLDE";
this.k = parameters.getNextAsInt();
this.iterBasicDE = parameters.getNextAsInt();//*trainingDataSet.get(0).numberOfInputs(); //NC*1000
this.iterSFGSS = parameters.getNextAsInt();
this.iterSFHC = parameters.getNextAsInt();
this.ScalingFactor = parameters.getNextAsDouble();
this.CrossOverRate = parameters.getNextAsDouble();
this.tau[0] = parameters.getNextAsDouble();
this.tau[1] = parameters.getNextAsDouble();
this.numberOfClass = trainingDataSet.getPosibleValuesOfOutput().size();
System.out.print("\nIsaac dice: " + k + " Swar= "+PopulationSize+ " Particle= "+ ParticleSize + " Maxiter= "+ MaxIter+" CR= "+this.CrossOverRate+ " CrossverType = "+ this.CrossoverType+"\n");
//numberOfPrototypes = getSetSizeFromPercentage(parameters.getNextAsDouble());
}
public PrototypeSet mutant(PrototypeSet population, double SFi){
PrototypeSet mutant = new PrototypeSet(population.clone());
Prototype r1,r2,r3,r4,r5, resta,resta2,producto2, producto, nearest;
for(int i=0; i< population.size(); i++){
//PrototypeSet mismaClase= KNN.getNearestNeighborsWithSameClassAs(population.get(i), population, 5);
//PrototypeSet mismaClase= KNN.getNearestNeighborsWithSameClassAs(population.get(i), trainingDataSet, 3);
PrototypeSet mismaClase = trainingDataSet.getFromClass(population.get(i).getOutput(0));
PrototypeSet aux = new PrototypeSet();
if(mismaClase.size() < 5){
for(int j=mismaClase.size(); j < 5; j++){
Prototype Perturbance = new Prototype(population.get(i));
for(int k=0; k< Perturbance.numberOfInputs(); k++){
Perturbance.setInput(k, population.get(i).getInput(k)+RandomGenerator.Randdouble(-0.01*j, 0.01*j));
}
aux.add(Perturbance);
}
mismaClase.add(aux);
}
int lista[] = new int[mismaClase.size()];
inic_vector_sin(lista,i);
desordenar_vector_sin(lista);
r1 = mismaClase.get(lista[0]);
r2 = mismaClase.get(lista[1]);
r3 = mismaClase.get(lista[2]);
r4 = mismaClase.get(lista[3]);
r5 = mismaClase.get(lista[4]);
switch(this.Strategy){
case 1:// ViG = Xr1,G + F(Xr2,G - Xr3,G) De rand 1
resta = r2.sub(r3);
producto = resta.mul(SFi);
mutant.set(i, producto.add(r1));
break;
case 2: //DE rand to nearest 1
resta = r1.sub(r2);
nearest = KNN.getNearestNeighborsWithSameClassAs(population.get(i), trainingDataSet, 1).get(0);
resta2 = nearest.sub(population.get(i));
producto = resta.mul(SFi);
producto2 = resta.mul(SFi);
producto = producto.add(producto2);
mutant.set(i, (population.get(i)).add(producto));
break;
case 3://DE current to rand 1
resta = r2.sub(r3);
resta2= r1.sub(population.get(i));
double aleatorio = RandomGenerator.Randdouble(0, 1);
producto = resta.mul(SFi*aleatorio);
producto2 = resta2.mul(aleatorio);
producto = producto.add(producto2);
mutant.set(i, producto.add(population.get(i)));
break;
case 4:// De rand 2
resta = r2.sub(r3);
resta2= r4.sub(r5);
producto = resta.mul(SFi);
producto2 = resta2.mul(SFi);
producto = producto.add(producto2);
mutant.set(i, producto.add(r1));
break;
}
}
// System.out.println("********Mutant**********");
// mutant.print();
mutant.applyThresholds();
return mutant;
}
/**
* Local Search Fitness Function
*/
public double lsff(double Fi, double CRi, PrototypeSet population){
PrototypeSet resta, producto, mutation;
PrototypeSet crossover;
double FitnessFi = 0;
//Mutation:
mutation = new PrototypeSet(population.size());
mutation = mutant(population, Fi);
//Crossover
crossover =new PrototypeSet(mutation);
/*crossover =new PrototypeSet(population.clone());
for(int i=0; i< mutation.size(); i++){
for(int j=0; j< mutation.get(i).numberOfInputs(); j++){
double randNumber = RandomGenerator.Randdouble(0, 1);
if(randNumber<CRi){
Prototype Aux = mutation.get(i);
crossover.get(i).setInput(j, Aux.getInput(j)); // Overwrite.
}
}
}
*/
// Compute fitness
PrototypeSet nominalPopulation = new PrototypeSet();
nominalPopulation.formatear(crossover);
FitnessFi = accuracy(nominalPopulation,trainingDataSet);
return FitnessFi;
}
/**
* SFGSS local Search.
* @param population
*/
public PrototypeSet SFGSS(PrototypeSet population, double CRi){
double a=0.1, b=1;
double fi1=0, fi2=0, fitnessFi1=0, fitnessFi2=0;
double phi = (1+ Math.sqrt(5))/5;
double scaling;
PrototypeSet crossover, resta, producto, mutation;
for (int i=0; i<this.iterSFGSS; i++){ // Computation budjet
fi1 = b - (b-a)/phi;
fi2 = a + (b-a)/phi;
fitnessFi1 = lsff(fi1, CRi, population);
fitnessFi2 = lsff(fi2, CRi,population);
if(fitnessFi1> fitnessFi2){
b = fi2;
}else{
a = fi1;
}
} // End While
if(fitnessFi1> fitnessFi2){
scaling = fi1;
}else{
scaling = fi2;
}
//Mutation:
mutation = new PrototypeSet(population.size());
mutation = mutant(population, scaling);
//Crossover
crossover =new PrototypeSet(mutation);
/*crossover =new PrototypeSet(population.clone());
for(int i=0; i< mutation.size(); i++){
for(int j=0; j< mutation.get(i).numberOfInputs(); j++){
double randNumber = RandomGenerator.Randdouble(0, 1);
if(randNumber<CRi){
Prototype Aux = mutation.get(i);
crossover.get(i).setInput(j, Aux.getInput(j)); // Overwrite.
}
}
}
*/
return crossover;
}
/**
* SFHC local search
*/
public PrototypeSet SFHC(PrototypeSet population, double SFi, double CRi){
double fitnessFi1, fitnessFi2, fitnessFi3, bestFi;
PrototypeSet crossover, resta, producto, mutation;
double h= 0.5;
for (int i=0; i<this.iterSFHC; i++){ // Computation budjet
fitnessFi1 = lsff(SFi-h, CRi, population);
fitnessFi2 = lsff(SFi, CRi, population);
fitnessFi3 = lsff(SFi+h, CRi, population);
if(fitnessFi1 >= fitnessFi2 && fitnessFi1 >= fitnessFi3){
bestFi = SFi-h;
}else if(fitnessFi2 >= fitnessFi1 && fitnessFi2 >= fitnessFi3){
bestFi = SFi;
h = h/2; // H is halved.
}else{
bestFi = SFi;
}
SFi = bestFi;
}
//Mutation:
mutation = new PrototypeSet(population.size());
mutation = mutant(population, SFi);
//Crossover
crossover =new PrototypeSet(mutation);
/* crossover =new PrototypeSet(population.clone());
for(int i=0; i< mutation.size(); i++){
for(int j=0; j< mutation.get(i).numberOfInputs(); j++){
double randNumber = RandomGenerator.Randdouble(0, 1);
if(randNumber<CRi){
Prototype Aux = mutation.get(i);
crossover.get(i).setInput(j, Aux.getInput(j)); // Overwrite.
}
}
}
*/
return crossover;
}
/**
*
*
*/
public PrototypeSet basicDE(PrototypeSet myTrain){
double fitness;
Prototype r1,r2,r3, resta, producto, resta2, producto2;
Prototype crossover;
PrototypeSet nominalPopulation;
nominalPopulation = new PrototypeSet();
nominalPopulation.formatear(myTrain);
fitness = accuracy(nominalPopulation,trainingDataSet);
// System.out.println("fitness "+ fitness);
double randj[] = new double[5];
// Generate randj for j=1 to 5.
for(int j=0; j<5; j++){
randj[j] = RandomGenerator.Randdouble(0, 1);
}
for(int i=0; i< this.iterBasicDE; i++){
PrototypeSet modificados = new PrototypeSet(myTrain);
if(i%1000==0){
if(randj[4] < tau[0]){
// System.out.println("SFGSS applied");
//SFGSS
modificados = SFGSS(myTrain, this.CrossOverRate);
}else if(tau[0] <= randj[4] && randj[4] < tau[1]){
modificados = SFHC(myTrain, this.ScalingFactor, this.CrossOverRate);
}
}else{
ScalingFactor = 0.1+ 0.9*RandomGenerator.Randdouble(0, 1);
for(int j=0; j< myTrain.size(); j++){
PrototypeSet mismaClase = trainingDataSet.getFromClass(myTrain.get(j).getOutput(0));
PrototypeSet aux = new PrototypeSet();
if(mismaClase.size() < 3){
for(int l=mismaClase.size(); l < 5; l++){
Prototype Perturbance = new Prototype(myTrain.get(j));
for(int k=0; k< Perturbance.numberOfInputs(); k++){
Perturbance.setInput(k, myTrain.get(j).getInput(k)+RandomGenerator.Randdouble(-0.01*l, 0.01*l));
}
aux.add(Perturbance);
}
mismaClase.add(aux);
}
ArrayList<Integer> indexes = RandomGenerator.generateDifferentRandomIntegers(0, mismaClase.size()-1);
r1 = mismaClase.get(indexes.get(0));
r2 = mismaClase.get(indexes.get(1));
r3 = mismaClase.get(indexes.get(2));
//DE current to rand 1
resta = r2.sub(r3);
resta2= r1.sub(myTrain.get(j));
double aleatorio = RandomGenerator.Randdouble(0, 1);
producto = resta.mul(this.ScalingFactor*aleatorio);
producto2 = resta2.mul(aleatorio);
producto = producto.add(producto2);
crossover = producto.add(myTrain.get(j)); // Current
crossover.applyThresholds();
modificados.set(j,crossover);
} // End mutation and crossover
} //end else
nominalPopulation = new PrototypeSet();
nominalPopulation.formatear(modificados);
double trialFitness =accuracy(nominalPopulation,trainingDataSet);
if(trialFitness > fitness){
//System.out.println("Selecting");
fitness = trialFitness;
myTrain = new PrototypeSet(modificados.clone());
}
}
return myTrain;
}
/**
* Generate a reduced prototype set by the IPLDEGenerator method.
* @return Reduced set by IPLDEGenerator's method.
*/
public PrototypeSet reduceSet()
{
System.out.print("\nThe algorithm IPADE is starting...\n Computing...\n");
this.Strategy = 3;
PrototypeSet solucion = new PrototypeSet();
PrototypeSet Clases [] = new PrototypeSet[this.numberOfClass];
double fitnessClass[] = new double[this.numberOfClass];
PrototypeSet nominalPopulation;
for(int i=0; i<this.numberOfClass; i++){
if(trainingDataSet.getFromClass(i).size() >0){
Clases[i] = new PrototypeSet(trainingDataSet.getFromClass(i).clone());
System.out.println("Size ->"+Clases[i].size());
Prototype centroid = Clases[i].avg();
//centroid.print();
solucion.add(centroid); // Centroide
}
}
// solucion.print();
solucion=basicDE(solucion); //Initial Optimization
// solucion.print();
double Fitness= accuracy(solucion,trainingDataSet);
// System.out.println("Initial Global Fitness = "+ Fitness);
boolean claseMarcada[] = new boolean[this.numberOfClass];
boolean fin[] = new boolean[this.numberOfClass];
Arrays.fill(claseMarcada, false);
Arrays.fill(fin, true);
int iterOptimizada[] = new int [this.numberOfClass];
Arrays.fill(iterOptimizada, 1);
int iter=0;
while(!Arrays.equals(claseMarcada, fin)){
// System.out.println("iter "+ iter+ " fitness= "+Fitness);
// System.out.println("iter "+ iter+ " Red= "+((trainingDataSet.size()-solucion.size())*100.)/trainingDataSet.size());
double minFitness= Double.MAX_VALUE;
int objetivo= -1;
for(int j=0; j<this.numberOfClass; j++){
if(trainingDataSet.getFromClass(j).size()>1){
fitnessClass[j]=accuracy(solucion,trainingDataSet.getFromClass(j));
//System.out.println("Fitness class["+j+"]= " +fitnessClass[j]);
if(fitnessClass[j] < minFitness && !claseMarcada[j]){
minFitness = fitnessClass[j];
objetivo = j;
}
if(fitnessClass[j] == 100){
claseMarcada[j] = true;
}
}else{
claseMarcada[j] = true;
}
}
// System.out.println("Objective =" + objetivo);
PrototypeSet tester;
if(!claseMarcada[objetivo]){
PrototypeSet solucion2 = new PrototypeSet(solucion.clone());
// solucion2.add(trainingDataSet.getFromClass(objetivo).getRandom()); // A�ado uno Y pruebo a optimizar.
solucion2.add(trainingDataSet.farthestTo(solucion.getFromClass(objetivo).getRandom()));
tester = basicDE(solucion2).clone();
nominalPopulation = new PrototypeSet();
nominalPopulation.formatear(solucion);
Fitness= accuracy(nominalPopulation,trainingDataSet);
nominalPopulation = new PrototypeSet();
nominalPopulation.formatear(tester);
double trialFitness= accuracy(nominalPopulation,trainingDataSet);
//System.out.println("Trial fitnss= " + trialFitness);
if(trialFitness > Fitness){
iterOptimizada[objetivo]++;
solucion = new PrototypeSet(tester.clone());
Fitness = trialFitness;
}else{
claseMarcada[objetivo] = true;
}
}
//Fitness= accuracy(solucion,trainingDataSet);
//System.out.println("Fitness = "+ Fitness);
iter++;
}
//solucion.print();
nominalPopulation = new PrototypeSet();
nominalPopulation.formatear(solucion);
double trialFitness= accuracy(nominalPopulation,trainingDataSet);
System.out.println("Final Fitness = "+ trialFitness);
System.out.println("Reduction %, result set = "+((trainingDataSet.size()-solucion.size())*100.)/trainingDataSet.size()+ "\n");
return solucion;
}
/**
* General main for all the prototoype generators
* @param args Arguments of the main function.
*/
public static void main(String[] args)
{
Parameters.setUse("IPLDE", "<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);
IPLDEGenerator.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);
//String[] parametersOfInitialReduction = Arrays.copyOfRange(args, 4, args.length);
//System.out.print(" swarm ="+swarm+"\n");
IPLDEGenerator generator = new IPLDEGenerator(training, k,swarm,particle,iter, 0.5,0.5,1);
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);
}
}