/*********************************************************************** 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/ **********************************************************************/ /* * CromosomaEntero.java * * Created on 23 de agosto de 2005, 11:50 * */ package keel.Algorithms.Preprocess.Feature_Selection.evolutionary_algorithms; import org.core.Randomize; /** * * @author Manuel Chica Serrano * class CromosomaEntero that defines a specificationn of Cromosoma, the internal representation will be an integer array */ public class CromosomaEntero extends Cromosoma{ /** numCaracteristicas is the number of the total dataset's features. This number will define the maximum gen value (0,numCaracs-1) */ private int numCaracteristicas; /** Creates a new instance of CromosomaEntero * @param tam is the number of features to be selected @param numCaracs is the total dataset's features */ public CromosomaEntero(int numCaracs, int tam) { super(tam); numCaracteristicas = numCaracs; } /** random initialization of a chromosome. Tbe random values are defined between 0 and total dataset's features -1 */ public void initRand(){ int temp = 0,i,j; for(i=0; i<tamCromosoma; i++){ j = -1; while(j!=i){ temp = Randomize.Randint(0,numCaracteristicas); /** checks if temp value hasn't been selected yet */ for(j=0; j<i && rep[j]!=temp; j++); } rep[i] = temp; } } /** this method is used in CHC method. * initializes a chromosome using a chromosome template and a random initialization * @param crPlantilla is a chromosome template * @param ratio is the ratio of random initialization */ public void initPlantilla(Cromosoma crPlantilla, double ratio){ int temp = 0,i,j; /* firstly, copies the chromosome template into new chromosome */ for(i=0; i<tamCromosoma; i++) if(Randomize.RandClosed() <= ratio) rep[i] = crPlantilla.devolverGen(i); else rep[i] = -1; /* secondly, completes gens containing -1 with randomly numbers */ for(i=0; i<tamCromosoma; i++){ j = -1; while(j!=i){ temp = Randomize.Randint(0, numCaracteristicas); /* vemos si no estaba ya el valor aleatorio en el cromosoma */ for(j=0; j<tamCromosoma && rep[j]!=temp; j++); } /* aqui tenemos ya un valor entero temp no repetido en el cromosoma */ rep[i] = temp; } } /** return the ith gen of chromosome @param i is the ith position @return integer with gen value */ public int devolverGen(int i){ if(i<0 || i>=tamCromosoma) { System.err.println("ERROR: Gen i is out of chromosome bounds"); System.exit(0); } return rep[i]; } /** modifies the ith value of a gene @param nuevoValorGen the new value for the gene @param posGen the position what we want to change (0..tamCromsoma-1) */ public void cambiarGen(int nuevoValorGen, int posGen){ int j; if(posGen<0 || posGen>=rep.length){ System.err.println("ERROR: Gen 'posGen' is out of bounds"); System.exit(0); } if(nuevoValorGen<0){ System.err.println("ERROR: The new value for gen doesn't correct. " + "It must be greater than -1 & less than numFeatures-1"); System.exit(0); } /* checks if nuevoValorGen is in chromosome */ for(j=0; j<rep.length && rep[j]!=nuevoValorGen; j++); if(j==rep.length) rep[posGen] = nuevoValorGen; else { System.err.println("ERROR: New value for chromosome is incorrect. This value already exists"); System.exit(0); } } /** crossover operator. The offsprings must be created before calling method @param padre2 is a parent @param hijo1 is the first offspring @param hijo2 is the second offspring */ public void cruzar(Cromosoma padre2, Cromosoma hijo1, Cromosoma hijo2){ int i, pos, j, temp = 0, puntoCorte1, puntoCorte2; if(padre2==null){ System.err.println("ERROR: padre2 doesn't exist"); System.exit(0); } /* selects two cut points. it's neccesary to crossover operator */ do { puntoCorte1 = Randomize.Randint(0,tamCromosoma); puntoCorte2 = Randomize.Randint(0,tamCromosoma); } while(puntoCorte1 >= puntoCorte2); int vectorAux[] = new int[tamCromosoma]; for(i=0; i<tamCromosoma; i++) vectorAux[i] = -1; /* ------------------------------------------ FIRST OFFSPRING -------------------------------------*/ /* to create this first offspring we need to copy padre1's gens between puntoCorte1 and puntoCorte2 * Then , completes with padre2's genes */ for(i=puntoCorte1; i<puntoCorte2; i++) vectorAux[i] = rep[i]; /* completes with padre2's genes */ pos = puntoCorte2; for(i=puntoCorte2; i<tamCromosoma; i++){ temp = padre2.devolverGen(i); for(j=0; j<i && vectorAux[j]!=temp; j++); if(j==i) vectorAux[pos++] = temp; } for(i=0; i<puntoCorte1; i++){ temp = padre2.devolverGen(i); for(j=i+1; j<tamCromosoma && vectorAux[j]!=temp; j++); if(j==tamCromosoma){ if(pos==tamCromosoma) pos = 0; vectorAux[pos++] = temp; } } /* the chromosome has genes with -1. we have to change them with new integer values that are not in the chromosome */ for(i=0; i<tamCromosoma; i++) if(vectorAux[i] == -1) { /* finds a new valid value */ j = 0; while(j!=tamCromosoma){ temp = Randomize.Randint(0, numCaracteristicas); /** finds the new value in the chromosome. if this value exists, other new value will be created */ for(j=0; j<tamCromosoma && vectorAux[j]!=temp; j++); } vectorAux[i] = temp; } for(i=0; i<tamCromosoma; i++) hijo1.cambiarGen(vectorAux[i], i); /* ------------------------------------------ SECOND OFFSPRING -------------------------------------*/ /* creates the second offspring with inverse previous method */ for(i=0; i<tamCromosoma; i++) vectorAux[i] = -1; for(i=puntoCorte1; i<puntoCorte2; i++) vectorAux[i] = padre2.devolverGen(i); /* completes with padre1 information */ pos = puntoCorte2; for(i=puntoCorte2; i<tamCromosoma; i++){ temp = rep[i]; for(j=0; j<i && vectorAux[j]!=temp; j++); /* checks if temp value has repeated */ if(j==i) vectorAux[pos++] = temp; } for(i=0; i<puntoCorte1; i++){ temp = rep[i]; for(j=i+1; j<tamCromosoma && vectorAux[j]!=temp; j++); /* checks if temp value has repeated */ if(j==tamCromosoma){ if(pos==tamCromosoma) pos = 0; vectorAux[pos++] = temp; } } /* it's possibly that new offspring has -1 values. this values will be changed with other valids integer values */ for(i=0; i<tamCromosoma; i++) if(vectorAux[i] == -1) { /* the new value must to not be in chromosome */ j = 0; while(j!=tamCromosoma){ temp = Randomize.Randint(0, numCaracteristicas); /** checks if this value was in chromosome */ for(j=0; j<tamCromosoma && vectorAux[j]!=temp; j++); } vectorAux[i] = temp; } for(i=0; i<tamCromosoma; i++) hijo2.cambiarGen(vectorAux[i], i); } /** this method can't be applied to integer chromosome. This is a EMPTY METHOD */ public boolean cruzarHUX(Cromosoma padre2, Cromosoma hijo1, Cromosoma hijo2, int umbral){ return false; } /** integer mutation operator in one point */ public void mutar(){ int puntoAleat = Randomize.Randint(0,tamCromosoma); int j, temp=0; /* the random gene has been initialized to -1 */ rep[puntoAleat] = -1; j = -1; while(j!=tamCromosoma){ temp = Randomize.Randint(0,numCaracteristicas); /** finds new value in chromosome */ for(j=0; j<tamCromosoma && rep[j]!=temp; j++); } rep[puntoAleat] = temp; fitness = -1; } /** it prints a chromosome, gene by gene */ public String print(){ String res = new String(); for(int i=0; i<tamCromosoma; i++) res += "Gen " + String.valueOf(i+1) + ": Value " + String.valueOf(rep[i]) + "\n"; return res; } /** returns a boolean array needed for Leaving One Out, Cross Validation and other methods used in * Feature Selection Algorithm @return a boolean array with the selected features */ public boolean[] devolverFeaturesVector(){ boolean featuresVector[]; featuresVector = new boolean[numCaracteristicas]; for(int i=0; i<numCaracteristicas; i++) featuresVector[i] = false; for(int i=0; i<tamCromosoma; i++) featuresVector[rep[i]] = true; return featuresVector; } }