/*********************************************************************** 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.Fuzzy_Rule_Learning.Genetic.IVTURS; import org.core.Randomize; import java.lang.*; /** * <p>Title: Individual</p> * * <p>Description: This class contains the representation of the individuals of the population (CHC Algorithm)</p> * * <p>Copyright: Copyright KEEL (c) 2007</p> * * <p>Company: KEEL </p> * * @author Written by Jesus Alcal� (University of Granada) 09/02/2011 * @author Modified by Jose Antonio Sanz (University of Navarra) 19/12/2011 * @author Modified by Alberto Fernandez (University of Jaen) 24/10/2013 * @version 1.2 * @since JDK1.6 */ public class Individual implements Comparable{ double[] gene; int[] geneR; double fitness, accuracy, w1; int n_e, nGenes, nSim, nAmp, nLat, ajuste; RuleBase ruleBase; double[][] gInt;//min and max values for the genes public Individual() { } /** * <p> * Builder * </p> * @param ruleBase Rule set * @param dataBase Database * @param w1 Weight for the fitness function * @return Return a individual */ public Individual(RuleBase ruleBase, DataBase dataBase, double w1, int tipoAjuste) { this.ajuste = tipoAjuste; this.ruleBase = ruleBase; this.w1 = w1; this.fitness = Double.NEGATIVE_INFINITY; this.accuracy = 0.0; this.n_e = 0; if (this.ajuste == 1){ this.nSim = 2*dataBase.numVariables(); this.nAmp = 0; //amplitude tuning is not carried out this.nLat = 0; //lateral tuning is not carried out } else if (this.ajuste == 2){ //amplitude tuning this.nAmp = dataBase.getnLabelsReal(); this.nSim = 0; //similarity tuning is not carried out this.nLat = 0; //lateral tuning is not carried out } else if (this.ajuste == 3){ //similarity + amplitude tuning this.nSim = 2*dataBase.numVariables(); this.nAmp = dataBase.getnLabelsReal(); this.nLat = 0; //lateral tuning is not carried out } else if (this.ajuste == 4){ //all tuning processes carried out this.nSim = 2*dataBase.numVariables(); this.nAmp = dataBase.getnLabelsReal(); this.nLat = dataBase.getnLabelsReal(); } else if (this.ajuste == 5){ //similarity + lateral tuning this.nSim = 2*dataBase.numVariables(); this.nAmp = 0; this.nLat = dataBase.getnLabelsReal(); } this.nGenes = this.nSim + this.nAmp + this.nLat; //number of genes needed if (this.nGenes > 0){ this.gene = new double[this.nGenes]; this.gInt = new double[this.nGenes][]; for (int i = 0; i < this.nSim; i++){ this.gInt[i] = new double[2]; //similarity this.gInt[i][0] = 0.01; this.gInt[i][1] = 1.99; } for (int i = this.nSim; i < (this.nSim+this.nAmp); i++){ //genes for carrying out the amplitude tuning this.gInt[i] = new double[2]; //amplitude this.gInt[i][0] = 0.0; this.gInt[i][1] = 1.0; } for (int i = (this.nSim+this.nAmp); i < this.nGenes; i++){ //nGenes for reaching the end of the chromosome this.gInt[i] = new double[2]; //lateral this.gInt[i][0] = 0.0; this.gInt[i][1] = 1.0; } } //rule selection this.geneR = new int[this.ruleBase.size()]; } /** * <p> * Clone * </p> * @return A copy of the individual */ public Individual clone(){ Individual ind = new Individual(); ind.ruleBase = this.ruleBase; ind.w1 = this.w1; ind.fitness = this.fitness; ind.accuracy = this.accuracy; ind.n_e = this.n_e; ind.nGenes = this.nGenes; ind.nSim = this.nSim; ind.nAmp = this.nAmp; ind.nLat = this.nLat; ind.ajuste = this.ajuste; if (this.nGenes > 0) { ind.gene = new double[this.nGenes]; ind.gInt = new double[this.nGenes][]; for (int j = 0; j < this.nGenes; j++){ ind.gene[j] = this.gene[j]; ind.gInt[j] = new double[2]; ind.gInt[j][0] = this.gInt[j][0]; ind.gInt[j][1] = this.gInt[j][1]; } } //rule selection ind.geneR = new int[this.geneR.length]; for (int j = 0; j < this.geneR.length; j++) ind.geneR[j] = this.geneR[j]; return ind; } public void reset() { //automorphisms tuning if (this.ajuste == 1){ if (this.nGenes > 0) { for (int i = 0; i < this.nGenes; i++) this.gene[i] = 1.0; } } //rule selection //initialize with values '1' for taking into account all rules for (int i = 0; i < this.geneR.length; i++) this.geneR[i] = 1; } public void resetAmp(int numInd) { if(this.ajuste == 2) { //amplitude tuning if (numInd == 0) if (this.nGenes > 0) { for (int i = this.nSim; i < this.nGenes; i++) this.gene[i] = 0.5; } else if (numInd == 1) if (this.nGenes > 0) { for (int i = this.nSim; i < this.nGenes; i++) this.gene[i] = 0.0; } else if (numInd == 2) if (this.nGenes > 0) { for (int i = this.nSim; i < this.nGenes; i++) this.gene[i] = 1.0; } //rule selection //initialize with values '1' for taking into account all rules for (int i = 0; i < this.geneR.length; i++) this.geneR[i] = 1; } else if(this.ajuste == 3) { //amplitude + similarity tuning if (numInd == 0) if (this.nGenes > 0) { for (int i = 0; i < this.nSim; i++) this.gene[i] = 1.0; for (int i = this.nSim; i < this.nGenes; i++) this.gene[i] = 0.5; } else if (numInd == 1) if (this.nGenes > 0) { for (int i = 0; i < this.nSim; i++) this.gene[i] = 1.0; for (int i = this.nSim; i < this.nGenes; i++) this.gene[i] = 0.0; } else if (numInd == 2) if (this.nGenes > 0) { for (int i = 0; i < this.nSim; i++) this.gene[i] = 1.0; for (int i = this.nSim; i < this.nGenes; i++) this.gene[i] = 1.0; } //rule selection //initialize with values '1' for taking into account all rules for (int i = 0; i < this.geneR.length; i++) this.geneR[i] = 1; } else if(this.ajuste == 4) { //amplitude + similarity + lateral tuning if (numInd == 0) if (this.nGenes > 0) { for (int i = 0; i < this.nSim; i++) this.gene[i] = 1.0; for (int i = this.nSim; i < (this.nSim+this.nAmp); i++) this.gene[i] = 0.5; for (int i = (this.nSim+this.nAmp); i < this.nGenes; i++) this.gene[i] = 0.5; } else if (numInd == 1) if (this.nGenes > 0) { for (int i = 0; i < this.nSim; i++) this.gene[i] = 1.0; for (int i = this.nSim; i < (this.nSim+this.nAmp); i++) this.gene[i] = 0.0; for (int i = (this.nSim+this.nAmp); i < this.nGenes; i++) this.gene[i] = 0.5; } else if (numInd == 2) if (this.nGenes > 0) { for (int i = 0; i < this.nSim; i++) this.gene[i] = 1.0; for (int i = this.nSim; i < (this.nSim+this.nAmp); i++) this.gene[i] = 1.0; for (int i = (this.nSim+this.nAmp); i < this.nGenes; i++) this.gene[i] = 0.5; } //rule selection //initialize with values '1' for taking into account all rules for (int i = 0; i < this.geneR.length; i++) this.geneR[i] = 1; } else if(this.ajuste == 5) { //similarity + lateral tuning if (numInd == 0) if (this.nGenes > 0) { for (int i = 0; i < this.nSim; i++) this.gene[i] = 1.0; for (int i = (this.nSim+this.nAmp); i < this.nGenes; i++) this.gene[i] = 0.5; } //rule selection //initialize with values '1' for taking into account all rules for (int i = 0; i < this.geneR.length; i++) this.geneR[i] = 1; } } public void randomValues () { //automorphisms tuning if (this.nGenes > 0) { for (int i = 0; i < this.nGenes; i++) this.gene[i] = this.gInt[i][0] + (this.gInt[i][1]-this.gInt[i][0])*Randomize.Rand(); } //rule selection: total execution for (int i = 0; i < this.geneR.length; i++){ if (Randomize.Rand() < 0.5) this.geneR[i] = 0; else this.geneR[i] = 1; } } public int size(){ return this.geneR.length; } public int getnSelected() { int i, count; count = 0; for (i=0; i < this.geneR.length; i++) { if (this.geneR[i] > 0) count++; } return (count); } public boolean isNew () { return (this.n_e == 1); } public void onNew () { this.n_e = 1; } public void offNew () { this.n_e = 0; } public void setw1 (double value) { this.w1 = value; } public double getAccuracy() { return this.accuracy; } public double getFitness() { return this.fitness; } /*************************************************************************/ /* Translations between string representation and floating point vectors */ /*************************************************************************/ private int StringRep(Individual indiv, int BITS_GEN) { int i, j, pos, length, count; long n; char last; double INCREMENTO; char[] stringIndiv1; char[] stringIndiv2; char[] stringAux; length = this.nGenes * BITS_GEN; stringIndiv1 = new char[length]; stringIndiv2 = new char[length]; stringAux = new char[length]; INCREMENTO = 1.0 / (Math.pow(2.0, (double) BITS_GEN) - 1.0); pos = 0; for (i=0; i < this.nGenes; i++) { n = (int) (this.gene[i] / INCREMENTO + 0.5); for (j = BITS_GEN - 1; j >=0 ; j--) { stringAux[j] = (char) ('0' + (n & 1)); n >>= 1; } last = '0'; for (j=0; j < BITS_GEN; j++, pos++) { if (stringAux[j] != last) stringIndiv1[pos] = (char) ('0' + 1); else stringIndiv1[pos] = (char) ('0' + 0); last = stringAux[j]; } } pos = 0; for (i=0; i < this.nGenes; i++) { n = (int) (indiv.gene[i] / INCREMENTO + 0.5); for (j = BITS_GEN - 1; j >=0 ; j--) { stringAux[j] = (char) ('0' + (n & 1)); n >>= 1; } last = '0'; for (j=0; j < BITS_GEN; j++, pos++) { if (stringAux[j] != last) stringIndiv2[pos] = (char) ('0' + 1); else stringIndiv2[pos] = (char) ('0' + 0); last = stringAux[j]; } } count = 0; for (i=0; i < length; i++) { if (stringIndiv1[i] != stringIndiv2[i]) count++; } return count; } public int distHamming(Individual ind, int BITS_GEN) { int i, count; count = 0; for (i=0; i < this.geneR.length; i++) { if (this.geneR[i] != ind.geneR[i]) count++; } if (this.nGenes > 0) count += StringRep(ind, BITS_GEN); return (count); } public void Hux(Individual indiv) { int i, dist, random, aux, nPos; int [] position; position = new int[this.geneR.length]; dist = 0; for (i = 0; i < this.geneR.length; i++) { if (this.geneR[i] != indiv.geneR[i]) { position[dist] = i; dist++; } } nPos = dist / 2; for (i = 0; i < nPos; i++) { random = Randomize.Randint(0, dist); aux = this.geneR[position[random]]; this.geneR[position[random]] = indiv.geneR[position[random]]; indiv.geneR[position[random]] = aux; dist--; aux = position[dist]; position[dist] = position[random]; position[random] = aux; } } public void xPC_BLX(Individual indiv, double d) { double I, A1, C1; int i; for (i=0; i < this.nGenes; i++) { I = d * Math.abs(gene[i] - indiv.gene[i]); A1 = gene[i] - I; if (A1 < 0.0) A1 = this.gInt[i][0]; C1 = gene[i] + I; if (C1 > 1.0) C1 = this.gInt[i][1]; gene[i] = A1 + Randomize.Rand() * (C1 - A1); A1 = indiv.gene[i] - I; if (A1 < 0.0) A1 = this.gInt[i][0]; C1 = indiv.gene[i] + I; if (C1 > 1.0) C1 = this.gInt[i][1]; indiv.gene[i] = A1 + Randomize.Rand() * (C1 - A1); } } public RuleBase generateRB() { int i, bestRule; RuleBase ruleBase = this.ruleBase.clone(); ruleBase.evaluate(this.gene, this.geneR, this.ajuste); ruleBase.setDefaultRule(); for (i=geneR.length - 1; i >= 0; i--) { if (geneR[i] < 1) ruleBase.remove(i); } return ruleBase; } /** * <p> * Evaluate this individual (fitness function) * </p> * @return void */ public void evaluate() { this.ruleBase.evaluate(this.gene, this.geneR, this.ajuste); this.accuracy = this.ruleBase.getAccuracy(); this.fitness = this.accuracy; } public int compareTo(Object a) { if ( ( (Individual) a).fitness < this.fitness) { return -1; } if ( ( (Individual) a).fitness > this.fitness) { return 1; } return 0; } }