/***********************************************************************
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