/*********************************************************************** 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/ **********************************************************************/ /** * * File: Cromosoma.java * * Auxiliriary class to represent chromosomes for Instance selection methods * * @author Written by Salvador Garc�a (University of Granada) 20/07/2004 * @version 0.1 * @since JDK1.5 * */ package keel.Algorithms.Preprocess.Instance_Selection.GGA; import keel.Algorithms.Preprocess.Basic.*; import org.core.*; public class Cromosoma implements Comparable { /*Cromosome data structure*/ boolean cuerpo[]; /*Useless data for cromosomes*/ double calidad; boolean cruzado; boolean valido; double errorRate; /** * Builder. Construct a random chromosome of specified size * * @param size Size of the chromosome */ public Cromosoma (int size) { double u; int i; cuerpo = new boolean[size]; for (i=0; i<size; i++) { u = Randomize.Rand(); if (u < 0.5) { cuerpo[i] = false; } else { cuerpo[i] = true; } } cruzado = true; valido = true; }//end-method /** * Builder. Copies a chromosome of specified size * * @param size Size of the chromosome * @param a Chromosome to copy */ public Cromosoma (int size, Cromosoma a) { int i; cuerpo = new boolean[size]; for (i=0; i<cuerpo.length; i++) cuerpo[i] = a.getGen(i); calidad = a.getCalidad(); cruzado = false; valido = true; }//end-method /** * Builder. Construct a chromosome from a binary array * * @param datos Initial data of the chromosome */ public Cromosoma (boolean datos[]) { int i; cuerpo = new boolean[datos.length]; for (i=0; i<datos.length; i++) cuerpo[i] = datos[i]; cruzado = true; valido = true; }//end-method /** * Get the value of a gene * * @param indice Index of the gene * * @return Value of the especified gene */ public boolean getGen (int indice) { return cuerpo[indice]; }//end-method /** * Get the quality of a chromosome * * @return Quality of the chromosome */ public double getCalidad () { return calidad; }//end-method /** * Set the value of a gene * * @param indice Index of the gene * @param valor Value to set */ public void setGen (int indice, boolean valor) { cuerpo[indice] = valor; }//end-method /** * Evaluates a chromosome * * @param datos Reference to the training set * @param real Reference to the training set (real valued) * @param nominal Reference to the training set (nominal valued) * @param nulos Reference to the training set (null values) * @param clases Output attribute of each instance * @param alfa Alpha value of the fitness function * @param kNeigh Number of neighbors for the KNN algorithm * @param nClases Number of classes of the problem * @param distanceEu True= Euclidean distance; False= HVDM */ public void evalua (double datos[][], double real[][], int nominal[][], boolean nulos[][], int clases[], double alfa, int kNeigh, int nClases, boolean distanceEu) { int i, j, l, m; int aciertos = 0; double M, s; double conjS[][]; double conjR[][]; int conjN[][]; boolean conjM[][]; int clasesS[]; int vecinos[]; int claseObt; int vecinoCercano; double dist, minDist; M = (double)datos.length; s = (double)genesActivos(); if (kNeigh > 1) { vecinos = new int[kNeigh]; conjS = new double[(int)s][datos[0].length]; conjR = new double[(int)s][datos[0].length]; conjN = new int[(int)s][datos[0].length]; conjM = new boolean[(int)s][datos[0].length]; clasesS = new int[(int)s]; for (j=0, l=0; j<datos.length; j++) { if (cuerpo[j]) { //the instance must be copied to the solution for (m=0; m<datos[j].length; m++) { conjS[l][m] = datos[j][m]; conjR[l][m] = real[j][m]; conjN[l][m] = nominal[j][m]; conjM[l][m] = nulos[j][m]; } clasesS[l] = clases[j]; l++; } } for (i=0; i<datos.length; i++) { claseObt = KNN.evaluacionKNN2(kNeigh, conjS, conjR, conjN, conjM, clasesS, datos[i], real[i], nominal[i], nulos[i], nClases, distanceEu, vecinos); if (claseObt >= 0) if (clases[i] == claseObt) aciertos++; } } else { for (i=0; i<datos.length; i++) { vecinoCercano = -1; minDist = Double.POSITIVE_INFINITY; for (j=0; j<datos.length; j++) { if (cuerpo[j]) { //It is in S dist = KNN.distancia (datos[i], real[i], nominal[i], nulos[i], datos[j], real[j], nominal[j], nulos[j], distanceEu); if (dist < minDist && dist != 0) { minDist = dist; vecinoCercano = j; } } } if (vecinoCercano >= 0) if (clases[i] == clases[vecinoCercano]) aciertos++; } } calidad = ((double)(aciertos)/M)*alfa*100.0; calidad += ((1.0 - alfa) * 100.0 * (M - s) / M); cruzado = false; }//end-method /** * Mutation operator * * @param pMutacion1to0 Probability of change 1 to 0 * @param pMutacion0to1 Probability of change 0 to 1 */ public void mutacion (double pMutacion1to0, double pMutacion0to1) { int i; for (i=0; i<cuerpo.length; i++) { if (cuerpo[i]) { if (Randomize.Rand() < pMutacion1to0) { cuerpo[i] = false; cruzado = true; } } else { if (Randomize.Rand() < pMutacion0to1) { cuerpo[i] = true; cruzado = true; } } } }//end-method /** * Reinitializes the chromosome by using CHC diverge procedure * * @param r R factor of diverge * @param mejor Best chromosome found so far * @param prob Probability of setting a gen to 1 */ public void divergeCHC (double r, Cromosoma mejor, double prob) { int i; for (i=0; i<cuerpo.length; i++) { if (Randomize.Rand() < r) { if (Randomize.Rand() < prob) { cuerpo[i] = true; } else { cuerpo[i] = false; } } else { cuerpo[i] = mejor.getGen(i); } } cruzado = true; }//end-method /** * Tests if the chromosome is already evaluated * * @return True if the chromosome is already evaluated. False, if not. */ public boolean estaEvaluado () { return !cruzado; }//end-method /** * Count the number of genes set to 1 * * @return Number of genes set to 1 in the chromosome */ public int genesActivos () { int i, suma = 0; for (i=0; i<cuerpo.length; i++) { if (cuerpo[i]) suma++; } return suma; }//end-method /** * Tests if the chromosome is valid * * @return True if the chromosome is valid. False, if not. */ public boolean esValido () { return valido; }//end-method /** * Marks a chromosome for deletion */ public void borrar () { valido = false; }//end-method /** * Compare to Method * * @param o1 Chromosome to compare * * @return Relative order between the chromosomes */ public int compareTo (Object o1) { if (this.calidad > ((Cromosoma)o1).calidad) return -1; else if (this.calidad < ((Cromosoma)o1).calidad) return 1; else return 0; }//end-method /** * Test if two chromosome differ in only one gene * * @param a Chromosome to compare * * @return Position of the difference, if only one is found. Otherwise, -1 */ public int differenceAtOne (Cromosoma a) { int i; int cont = 0, pos = -1; for (i=0; i<cuerpo.length && cont < 2; i++) if (cuerpo[i] != a.getGen(i)) { pos = i; cont++; } if (cont >= 2) return -1; else return pos; }//end-method /** * To String Method * * @return String representation of the chromosome */ public String toString() { int i; String temp = "["; for (i=0; i<cuerpo.length; i++) if (cuerpo[i]) temp += "1"; else temp += "0"; temp += ", " + String.valueOf(calidad) + "," + String.valueOf(errorRate) + ", " + String.valueOf(genesActivos()) + "]"; return temp; }//end-method }//end-class