/*********************************************************************** 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.Associative_Classification.ClassifierFuzzyFARCHD; /** * <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 * @version 1.0 * @since JDK1.6 */ import org.core.Randomize; import java.lang.*; public class Individual implements Comparable{ double[] gene; int[] geneR; double fitness, accuracy, w1; int n_e, nGenes; RuleBase ruleBase; 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) { this.ruleBase = ruleBase; this.w1 = w1; this.fitness = Double.NEGATIVE_INFINITY; this.accuracy = 0.0; this.n_e = 0; this.nGenes = dataBase.getnLabelsReal(); if (this.nGenes > 0) this.gene = new double[this.nGenes]; 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; if (this.nGenes > 0) { ind.gene = new double[this.nGenes]; for (int j = 0; j < this.nGenes; j++) ind.gene[j] = this.gene[j]; } 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() { if (this.nGenes > 0) { for (int i = 0; i < this.nGenes; i++) this.gene[i] = 0.5; } for (int i = 0; i < this.geneR.length; i++) this.geneR[i] = 1; } public void randomValues () { if (this.nGenes > 0) { for (int i = 0; i < this.nGenes; i++) this.gene[i] = Randomize.Rand(); } 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 = 0.0; C1 = gene[i] + I; if (C1 > 1.0) C1 = 1.0; gene[i] = A1 + Randomize.Rand() * (C1 - A1); A1 = indiv.gene[i] - I; if (A1 < 0.0) A1 = 0.0; C1 = indiv.gene[i] + I; if (C1 > 1.0) C1 = 1.0; 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); 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.accuracy = this.ruleBase.getAccuracy(); this.fitness = this.accuracy - (this.w1 / (this.ruleBase.size() - this.getnSelected() + 1.0)) - (5.0 * this.ruleBase.getUncover()) - (5.0 * this.ruleBase.hasClassUncovered(this.geneR)); } public int compareTo(Object a) { if ( ( (Individual) a).fitness < this.fitness) { return -1; } if ( ( (Individual) a).fitness > this.fitness) { return 1; } return 0; } }