/*********************************************************************** 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.Target; /** * <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<Tree> bosque, hijos; double pSplit; int nClasses, nGenerations; int nCross, nMut, nClone, nImmigration, nTrees; myDataset train; double mejor_fitness, prob1_var, prob2_var; /** * Minimizacion * @param a double primer valor * @param b double segundo valor * @return boolean true si el primer valor es menor que el segundo */ public boolean BETTER(double a, double b) { return (a < b); } public Poblacion() { bosque = new ArrayList<Tree> (); hijos = new ArrayList<Tree> (); } public Poblacion(myDataset train, double pSplit, int nGenerations, int nCross, int nMut, int nClone, int nImmigration) { this.train = train; this.pSplit = pSplit; this.nGenerations = nGenerations; this.nCross = nCross; this.nMut = nMut; this.nClone = nClone; this.nImmigration = nImmigration; nTrees = nCross + nMut + nClone + nImmigration; bosque = new ArrayList<Tree> (); hijos = new ArrayList<Tree> (); mejor_fitness = Double.MAX_VALUE; } public void hacerGenetico() { init(); evaluate(bosque, 0); //System.exit(0); for (int i = 1; i <= nGenerations; i++) { //System.err.println("Generation[" + i + "]"); evolution(); evaluate(hijos, i); replace(); } } private void init() { prob1_var = prob2_var = 0.5; if (train.numCuantitativos() == 1){ prob1_var = 1.0; }else if (train.numCuantitativos() == 2){ prob2_var = 1.0; } for (int i = 0; i < nTrees; i++) { Tree t = new Tree(null, train, pSplit, true,prob1_var, prob2_var); bosque.add(t); //System.err.println("Arbol["+i+"]: "+t.printString()); } //System.exit(0); } private void evaluate(ArrayList<Tree> 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).evaluar(); /*if (generation == 0){ System.err.println("Generacion[" + generation + "], Individuo(" + i + ") -> " + fitness); }*/ if (BETTER(fitness, mejor_fitness)) { mejor_fitness = fitness; entrar = true; } } } if (entrar) { System.out.println("Best Fitness obtained in generation[" + generation + "]: " + mejor_fitness); //System.out.println(individuos.get(mejor).printString()); } } private void evolution() { //System.err.println("cruce"); cross(); //System.err.println("mutacion"); mutate(); //System.err.println("clonacion"); clonation(); //System.err.println("inmigracion"); immigration(); } private int seleccion(int posicionNo) { int i = 0; int posicion = 0; double rank_min = 0.75; double rank_max = 2.0 - rank_min; int tamPoblacion = bosque.size(); double[] Ruleta = new double[tamPoblacion]; /* Ordenamos la poblacion de mayor a menor fitness */ Collections.sort(bosque); /* Calculamos la probabilidad de seleccion de cada individuo mediante el ranking lineal en funcion de su posicion en el orden y construimos la ruleta */ for (i = 0; i < tamPoblacion; i++) { if (i != 0) { Ruleta[i] = Ruleta[i - 1] + (rank_max - (rank_max - rank_min) * i / (double) (tamPoblacion - 1)) / (double) tamPoblacion; } else { Ruleta[i] = (rank_max - (rank_max - rank_min) * i / (double) (tamPoblacion - 1)) / (float) tamPoblacion; } } boolean salir = false; while (!salir) { double u = Randomize.Rand(); posicion = 0; for (i = 0; i < tamPoblacion; i++) { for (; Ruleta[posicion] < u; posicion++) { ; } } if (posicion != posicionNo) { salir = true; } } return posicion; } /** * Para todos los posibles arboles a cruzar: * - Selecciono dos padres (la probabilidad de seleccion depende del fitness) * - Aplico el cruce (uno de los dos posibles) */ private void cross() { for (int i = 0; i < this.nCross; i++) { //Selecciono dos padres int uno = seleccion( -1); int dos = seleccion(uno); //System.out.println("Applying Crossover"); cruce(uno, dos); } } /** * Dos tipos: * - Node Swapping * - Subtree Swapping * @param posPadre int posicion del padre en la poblacion * @param posMadre int posicion de la madre en la poblacion */ private void cruce(int posPadre, int posMadre) { Tree padre = bosque.get(posPadre); Tree madre = bosque.get(posMadre); Tree hijo1, hijo2; hijo1 = padre.copia(null); hijo2 = madre.copia(null); hijo1.n_e = true; hijo2.n_e = true; int nodo1, nodo2; nodo1 = padre.elijeNodo(); nodo2 = madre.elijeNodo(); if (Randomize.Rand() < 0.5) { //node swapping hijo1.nodeSwap(nodo1, nodo2, madre); hijo2.nodeSwap(nodo2, nodo1, padre); } else { //tree swapping hijo1.treeSwap(nodo1, nodo2, madre); hijo2.treeSwap(nodo2, nodo1, padre); } //Ahora elijo el mejor entre los dos padres y los dos hijos y lo meto en "hijos" int elegidoH, elegidoP; double fitnessP, fitnessH; double fitness1 = hijo1.evaluar(); double fitness2 = hijo2.evaluar(); if (BETTER(fitness1, fitness2)) { fitnessH = fitness1; elegidoH = 0; } else { fitnessH = fitness2; elegidoH = 1; } fitness1 = padre.fitness; fitness2 = madre.fitness; if (BETTER(fitness1, fitness2)) { fitnessP = fitness1; elegidoP = 0; } else { fitnessP = fitness2; elegidoP = 1; } if (BETTER(fitnessP, fitnessH)) { if (elegidoP == 0) { //padre hijos.add(padre); } else { //madre hijos.add(madre); } } else { if (elegidoH == 0) { //hijo1 hijos.add(hijo1); } else { //hijo2 hijos.add(hijo2); } } } private void mutate() { for (int i = 0; i < this.nMut; i++) { //Selecciono un arbol int tipo = Randomize.RandintClosed(0, 3); Tree hijo = bosque.get(seleccion( -1)).copia(null); hijo.n_e = true; if (tipo == 0) { //Split set mutation int nodo1; nodo1 = hijo.elijeNodo(); hijo.splitSet(nodo1); } else if (tipo == 1) { //Split rule mutation int nodo1; nodo1 = hijo.elijeNodo(); hijo.splitRule(nodo1); } else if (tipo == 2) { //Node swap mutation int nodo1, nodo2; nodo1 = hijo.elijeNodo(); nodo2 = hijo.elijeNodo(); hijo.nodeSwap(nodo1, nodo2, hijo); } else { //Subtree swap mutation int nodo1, nodo2; nodo1 = hijo.elijeNodo(); nodo2 = hijo.elijeNodo(); hijo.treeSwap(nodo1, nodo2, hijo); } hijos.add(hijo); } } private void clonation() { /*for (int i = 0; i < this.nClone; i++) { Tree hijo = bosque.get(seleccion( -1)).copia(null); hijos.add(hijo); }*/ Collections.sort(bosque); for (int i = 0; i < this.nClone; i++) { Tree hijo = bosque.get(i).copia(null); hijos.add(hijo); } } private void immigration() { for (int i = 0; i < this.nImmigration; i++) { Tree hijo = new Tree(null, train, pSplit, true, prob1_var, prob2_var); hijos.add(hijo); } } private void replace() { bosque.clear(); bosque.addAll(hijos); // } public Tree mejorSolucion() { Collections.sort(bosque); return bosque.get(0).copia(null); } }