/*********************************************************************** 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.Decision_Trees.DT_GA; /** * <p>Title: </p> * * <p>Description: </p> * * <p>Copyright: Copyright (c) 2007</p> * * <p>Company: </p> * * @author not attributable * @version 1.0 */ import java.util.ArrayList; import java.util.Collections; import org.core.*; public class Poblacion { ArrayList<Individuo> cromosomas; ArrayList<Individuo> hijos; ArrayList<Regla> reglas; myDataset train; int nGenerations, popSize, nEjemplos; double crossProb, mutProb, mejor_fitness; int ejemplos[], selectos[]; double infoG; double [] norm_acc; public boolean BETTER(double a, double b) { if (a > b) { return true; } return false; } public Poblacion() { cromosomas = new ArrayList<Individuo> (); mejor_fitness = 0; } public Poblacion(int codigoRegla, Regla r, int nGenerations, int popSize, double crossProb, double mutProb, myDataset train, String clase) { cromosomas = new ArrayList<Individuo> (); hijos = new ArrayList<Individuo> (); reglas = new ArrayList<Regla> (); this.train = train; boolean[] atributos = new boolean[train.getnInputs()]; for (int i = 0; i < atributos.length; i++) { atributos[i] = true; } for (int i = 0; i < r.size(); i++) { atributos[r.antecedente.get(i).getAtributo()] = false; } this.nGenerations = nGenerations; this.popSize = popSize; this.crossProb = crossProb; this.mutProb = mutProb; this.nEjemplos = r.cubiertos(); this.ejemplos = r.ejemplosCubiertos.clone(); //el conjunto de train corresponde solo a los cubiertos mejor_fitness = 0; this.selectos = new int[popSize]; inicializaPoblacion(atributos, clase, codigoRegla); calculaInfoG(); } public Poblacion(boolean[] ejemplosTr, int nGenerations, int popSize, double crossProb, double mutProb, myDataset train, double [] norm_acc) { cromosomas = new ArrayList<Individuo> (); hijos = new ArrayList<Individuo> (); reglas = new ArrayList<Regla> (); this.train = train; //Tengo que formar los ejemplos de entrenamiento escogerEjemplos(ejemplosTr); this.nGenerations = nGenerations; this.popSize = popSize; this.crossProb = crossProb; this.mutProb = mutProb; mejor_fitness = 0; this.selectos = new int[popSize]; this.norm_acc = norm_acc.clone(); //inicializaPoblacion(); //calculaInfoG(); } /** * Inicializa la poblacion para el caso de GA_Small * @param atributos boolean[] los atributos que se pueden (true) y no se pueden (false) colocar en el cromosoma * @param clase String es la clase consecuente para todos los cromosomas * @param codigoRegla int es el codigo de la regla de la que se generan los individuos */ private void inicializaPoblacion(boolean[] atributos, String clase, int codigoRegla) { for (int i = 0; i < popSize; i++) { //se generan aleatorios, en funcion del tipo de cada atributo Individuo ind = new Individuo(atributos, clase, train, codigoRegla); cromosomas.add(ind); } //System.err.println("Poblacion: \n" + this.printString()); } /** * Inicializa la poblacion para el caso de GA_Large */ private void inicializaPoblacion() { for (int i = 0; i < popSize; i++) { //se generan aleatorios, en funcion del tipo de cada atributo int semilla = ejemplos[Randomize.RandintClosed(0,nEjemplos-1)]; Individuo ind = new Individuo(train, semilla); cromosomas.add(ind); } //System.err.println("Poblacion: \n" + this.printString()); } public String printString() { String cadena = new String(""); for (int i = 0; i < popSize; i++) { cadena += "Chromosome[" + (i + 1) + "]: " + cromosomas.get(i).printString(); } return cadena; } public void GA_Small() { clasifica(cromosomas, 0); for (int i = 0; i < nGenerations; i++) { selection(); crossover(); mutation(); rule_pruning(); clasifica(hijos, i); //calcula la BR de cada cromosoma y obtiene su fitness elitist(); } Collections.sort(cromosomas); reglas.add(cromosomas.get(0).convertir()); } private void clasifica(ArrayList<Individuo> individuos, int generation) { boolean entrar = false; for (int i = 0; i < individuos.size(); i++) { if (individuos.get(i).n_e) { double fitness = individuos.get(i).clasifica(ejemplos, nEjemplos); //System.err.println("Generacion["+generation+"], Individuo("+i+") -> "+fitness); if (fitness > mejor_fitness) { mejor_fitness = fitness; entrar = true; } } } if (entrar) { System.out.println("Best Fitness obtained in generation[" + generation + "]: " + mejor_fitness); } } /** @brief Torneo binario entre cromosomas @param indice Indice del hijo @param cromosoma1 Es el indice del individuo1 dentro de la poblacion @param cromosoma2 Es el indice del individuo2 dentro de la poblacion Comparo las fitness de los dos individuos, el que tenga mayor valor pasa a formar parte del nuevo conjunto de seleccion. */ void torneo(int indice, int cromosoma1, int cromosoma2) { if (BETTER(cromosomas.get(cromosoma1).fitness, cromosomas.get(cromosoma2).fitness)) { selectos[indice] = cromosoma1; } else { selectos[indice] = cromosoma2; } ; } private void selection() { hijos.clear(); int aleatorio1, aleatorio2, i, inicio; inicio = 0; for (i = inicio; i < cromosomas.size(); i++) { //Generamos la otra mitad por los operadores geneticos, Cojo numIndividuos nuevos individuos... aleatorio1 = Randomize.RandintClosed(0, cromosomas.size()-1); //Elijo uno aleatoriamente do { aleatorio2 = Randomize.RandintClosed(0, cromosomas.size()-1); //Elijo otro aleatoriamente } while (aleatorio1 == aleatorio2); //pero que no coincida con el anterior torneo(i, aleatorio1, aleatorio2); //Inserto en la posicion 'i' el mejor de los 2 } } private void elitist() { Collections.sort(cromosomas); Individuo mejor = cromosomas.get(0).clone(); cromosomas.clear(); cromosomas.add(mejor); int posicion = Randomize.RandintClosed(0, hijos.size()-1); hijos.remove(posicion); for (int i = 0; i < hijos.size(); i++) { Individuo nuevo = hijos.get(i).clone(); cromosomas.add(nuevo); } } /** * Standard one-point crossover */ private void crossover() { for (int i = 0; i < selectos.length / 2; i++) { Individuo padre = cromosomas.get(selectos[i]); Individuo madre = cromosomas.get(selectos[i + 1]); if (Randomize.Rand() < crossProb) { int puntoCorte = Randomize.RandintClosed(1, padre.size() - 2); Individuo hijo1 = new Individuo(padre, madre, puntoCorte); Individuo hijo2 = new Individuo(madre, padre, puntoCorte); hijos.add(hijo1); hijos.add(hijo2); } else { hijos.add(padre.clone()); hijos.add(madre.clone()); } } } /** * Random mutation of each chromosome */ private void mutation() { for (int i = 0; i < hijos.size(); i++) { if (hijos.get(i).n_e) { //es un hijo generado nuevo hijos.get(i).mutar(mutProb); } } } /** * Obtiene el numero de ejemplos para la clase i-esima * @param clase int codigo de clase * @return int numero de ejemplos pertenencientes a dicha clase */ public int numEjemplos(int clase){ int n_ejemplos = 0; for (int i = 0; i < nEjemplos; i++){ if (clase == train.getOutputAsInteger(ejemplos[i])) n_ejemplos++; } return n_ejemplos; } /** * Info(G) = - sum_{j=1}^c {|Gj|/|T|*log_2{|Gj|/|T|}} * c = numero de clases * |Gj| = numero de ejemplos de la clase G * |T| = numero total de ejemplos */ private void calculaInfoG(){ int c = train.getnClasses(); double sum = 0.0; for (int i = 0; i < c; i++){ double aux = 1.0*this.numEjemplos(i)/nEjemplos; sum += (aux)*(Math.log(aux)/Math.log(2)); } infoG = -sum; } private void rule_pruning(){ for (int i = 0; i < hijos.size(); i++){ hijos.get(i).pruning(infoG,nEjemplos,ejemplos); } } public void escogerEjemplos(boolean [] ejemplos){ nEjemplos = 0; this.ejemplos = new int [ejemplos.length]; for (int i = 0; i < ejemplos.length; i++){ if (ejemplos[i]){ this.ejemplos[nEjemplos] = i; nEjemplos++; } } } public void GA_Large() { System.out.println("#Examples Remaining in Training-Set-2 -> "+nEjemplos); while (nEjemplos > 5){ mejor_fitness = 0; cromosomas.clear(); hijos.clear(); inicializaPoblacion(); clasificaLarge(cromosomas, 0); for (int i = 0; i < nGenerations; i++) { selection(); crossover(); mutation(); rule_pruning_large(); clasificaLarge(hijos, i); //calcula la BR de cada cromosoma y obtiene su fitness elitist(); } Collections.sort(cromosomas); reglas.add(cromosomas.get(0).convertir()); niching(); //eliminar del conjunto de entrenamiento los ejemplos cubiertos //System.out.println("#Examples Remaining in Training-Set-2 -> "+nEjemplos); } } private void clasificaLarge(ArrayList<Individuo> individuos, int generation) { boolean entrar = false; for (int i = 0; i < individuos.size(); i++) { if (individuos.get(i).n_e) { double fitness = individuos.get(i).clasificaLarge(ejemplos, nEjemplos); //elijo dinamicamente la clase //System.err.println("Generacion["+generation+"], Individuo("+i+") -> "+fitness); if (fitness > mejor_fitness) { mejor_fitness = fitness; entrar = true; } } } /*if (entrar) { System.out.println("Best Fitness obtained in generation[" + generation + "]: " + mejor_fitness); }*/ } private void rule_pruning_large(){ for (int i = 0; i < hijos.size(); i++){ hijos.get(i).pruning(norm_acc); } } private void niching(){ Regla r = reglas.get(reglas.size()-1); //cojo la ultima generada //System.err.print("Regla -> "+r.printString()); r.cubrirEjemplos(); int [] ejsCubiertosOK = new int[train.size()]; ejsCubiertosOK = r.ejemplosBienCubiertos.clone(); int ejemplosOK = r.cubiertosOK(); for (int i = 0; i < nEjemplos; i++){ boolean salir = false; for (int j = 0; j < ejemplosOK && (!salir); j++){ salir = (ejsCubiertosOK[j] == ejemplos[i]); } if (salir){ ejemplos[i] = ejemplos[nEjemplos-1]; //sustituyo por el �ltimo nEjemplos--; //me cargo uno i--; //para que no me afecte al contador } } } public ArrayList<Regla> dameReglas() { return reglas; } }