/*********************************************************************** 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/ **********************************************************************/ /** * <p> * @author Written by Albert Orriols (La Salle, Ram�n Llull University - Barcelona) 28/03/2004 * @author Modified by Xavi Sol� (La Salle, Ram�n Llull University - Barcelona) 03/12/2008 * @version 1.1 * @since JDK1.2 * </p> */ package keel.Algorithms.Genetic_Rule_Learning.XCS; import keel.Algorithms.Genetic_Rule_Learning.XCS.KeelParser.Config; import java.util.*; import java.lang.*; import java.util.*; public class GA { /** * <p> * This is the main class of the genetic algorithm. It has an object of * crossover and selection, that can take different selection and crossover * models. * </p> */ /////////////////////////////////////// // associations /** * <p> * A reference to a crossover object * </p> */ private Crossover cross; /** * <p> * A reference to a selection object * </p> */ private Selection sel; /////////////////////////////////////// // operations /** * <p> * Constructs the GA * </p> */ public GA() { if (Config.typeOfSelection.toUpperCase().equals("RWS")){ sel = new RouletteSelection(); } else{ sel = new TournamentSelection(); } if (Config.typeOfCrossover.toUpperCase().equals("2PT")){ cross = new TwoPointCrossover(); } else{ cross = new UniformCrossover(); } } // end GA /** * <p> * It makes an iteration of the genetic algorithm. It selects two parents, * performs crossover, mutate the children and introduces them to the * population, accordingly with the doGASubsumption parameter. * </p> * @param actionSet is the action set where the GA has to be applied. * @param envState is the environmental state. */ public void runGA(double[] envState, Population actionSet, int tStamp) { //Declaring the two childs Classifier child1, child2; //Initializing the selection method and selecting the parents. sel.init(actionSet); Classifier parent1 = sel.makeSelection(actionSet); Classifier parent2 = sel.makeSelection(actionSet); // Decision of making crossover or not if (Config.rand() < Config.pX){ // It makes the reductions specified in prediction error and fitness, and set the prediction at the // average of the parents //child1 = new Classifier(parent1, (parent1.getPrediction() + parent2.getPrediction())/2.0, Config.predictionErrorReduction * (parent1.getPredError() + parent2.getPredError())/2.0 , Config.fitReduction * (parent1.getFitness()/parent1.getNumerosity() + parent2.getFitness()/parent2.getNumerosity()) /2., tStamp, parent1.getASize(), 0, 1); //child2 = new Classifier(parent2, child1.getPrediction(), child1.getPredError(), child1.getFitness(), tStamp, parent2.getASize(), 0, 1); child1 = new Classifier (parent1, parent2, tStamp); child2 = new Classifier (parent2, parent1, tStamp); //Applies crossover (generates two children). cross.makeCrossover(parent1,parent2,child1,child2); } else{ //Crossover will not be applied child1 = new Classifier(parent1, tStamp); child2 = new Classifier(parent2, tStamp); } // The children are mutated. boolean actionMutated1 = child1.mutate(envState); boolean actionMutated2 = child2.mutate(envState); child1.calculateGenerality(); child2.calculateGenerality(); // The children have to be introduced in the population if (Config.doGASubsumption){ // We want to get a reference to the initial population, and we are in the action set. doGASubsumption(actionSet,parent1,parent2,child1,child2,actionMutated1,actionMutated2,envState); } else{ // We do not do GA subsumption Population parentRef = actionSet.getParentRef().getParentRef(); if ( !actionMutated1 & child1.match(envState) ) //It can be inserted in the action set to parentRef.insertInPopulation(child1,actionSet); //The new classifier is inserted in the action set. else parentRef.insertInPopulation(child1,null); if (!actionMutated2 & child2.match(envState)) parentRef.insertInPopulation(child2,actionSet); //The second child is inserted in the action set. else parentRef.insertInPopulation(child2,null); } } // end runGA /** * <p> * It applies the GA subsumption. It has to see if the parents * subsume the children. If they do not, it has to search * in the population for a subsumer. Otherwise, it has to insert * the new classifier in the population. * </p> * @param actionSet is the action set where the GA subsumption has to be applied. * @param parent1 is the first parent. * @param parent2 is the second parent. * @param child1 is the first child. * @param child2 is the second child. * @param actionMutated2 indicates if the action has been mutated * @param envState is the environmental state. */ public void doGASubsumption(Population actionSet,Classifier parent1, Classifier parent2, Classifier child1, Classifier child2,boolean actionMutated1, boolean actionMutated2, double[] envState){ Population parentRef = actionSet.getParentRef().getParentRef(); //Trying to subsume the first child. if (parent1.doesSubsume(child1)){ parent1.increaseNumerosity(1); parentRef.increaseMicroClSum(1); }else if (parent2.doesSubsume(child1)){ parent2.increaseNumerosity(1); parentRef.increaseMicroClSum(1); }else parentRef.insertInPSubsumingCl(child1,null); //Making the same process for the second child. if (parent1.doesSubsume(child2)){ parent1.increaseNumerosity(1); parentRef.increaseMicroClSum(1); }else if (parent2.doesSubsume(child2)){ parent2.increaseNumerosity(1); parentRef.increaseMicroClSum(1); }else parentRef.insertInPSubsumingCl(child2,null); //Deleting the extra classifiers in the population. while (parentRef.getMicroClSum() > Config.popSize){ parentRef.deleteClFromPopulation(actionSet); } } // end doGASubsumption } // end GA