/***********************************************************************
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.Genetic_Rule_Learning.BioHEL;
import java.util.Vector;
import org.core.Randomize;
public class geneticAlgorithm {
int currentIteration;
int popSize;
classifierFactory cf;
classifier[] population, offspringPopulation;
rank[] populationRank;
int flagResetBest;
int numVersions;
classifier[] best;
int tournamentSize;
double maxFitness;
double minFitness;
public geneticAlgorithm(classifierFactory pCF){
cf = pCF;
tournamentSize = Parameters.tournamentSize;
numVersions = Parameters.is.numVersions();
best = new classifier [numVersions+1];
for(int i=0;i<numVersions;i++) best[i] = null;
initializePopulation();
doFitnessComputations();
createPopulationRank();
checkBestIndividual();
}
//*******************************************************************************************************************************
public void initializePopulation(){
int i;
popSize = Parameters.popSize;
population = new classifier[popSize];
offspringPopulation = new classifier[popSize];
for ( i = 0; i < popSize; i++ )
population[i] = cf.createClassifier();
populationRank = new rank[popSize];
for( i = 0 ; i < popSize ; ++i )
populationRank[i] = new rank();
flagResetBest = 0;
currentIteration = 0;
}
//*******************************************************************************************************************************
public void doIterations(int n){
for (; n > 0; n--) {
selectionAlgorithm();
crossover();
mutation();
replacementAlgorithm();
createPopulationRank();
checkBestIndividual();
currentIteration++;
}
}
//*******************************************************************************************************************************
// --------------------- SELECTION
public void selectionAlgorithm(){
scalingAlgorithm();
switch (Parameters.selectionAlg) {
case Parameters.TOURNAMENT_WOR:
TournamentSelectionWOR();
break;
case Parameters.TOURNAMENT:
default:
TournamentSelection();
break;
}
classifier[] tempPop = new classifier[popSize];
System.arraycopy(population, 0, tempPop, 0, popSize);
System.arraycopy(offspringPopulation, 0, population, 0, popSize);
System.arraycopy(tempPop, 0, offspringPopulation, 0, popSize);
}
public void TournamentSelectionWOR(){
int i, j, winner, candidate;
Sampling samp = new Sampling(popSize);
for (i = 0; i < popSize; i++) {
//There can be only one
winner=samp.getSample();
for (j = 1; j < tournamentSize; j++) {
candidate=samp.getSample();
if(population[candidate].compareToIndividual(population[winner],Parameters.optimizationMethod)>0) {
winner = candidate;
}
}
offspringPopulation[i]=cf.cloneClassifier(population[winner]);
}
}
public void TournamentSelection(){
int i, j, winner, candidate;
for ( i = 0; i < popSize; i++ ){
//There can be only one
winner = Randomize.Randint(0,popSize);
for ( j = 1 ; j < tournamentSize; j++){
candidate = Randomize.Randint(0,popSize);
if(population[candidate].compareToIndividual(population[winner],Parameters.optimizationMethod)>0){
winner = candidate;
}
}
offspringPopulation[i] = cf.cloneClassifier(population[winner]);
}
}
//*******************************************************************************************************************************
// ----------------- SCALING
void scalingAlgorithm(){
int i;
for( i = 0 ; i < popSize ; i++ ){
double value = population[i].getFitness();
value = identityScaling(value);
population[i].setScaledFitness(value);
}
}
double identityScaling(double value){
double res;
if(Parameters.optimizationMethod==Parameters.MAXIMIZE) res=value;
else res=maxFitness+minFitness-value;
if(minFitness<0) res-=minFitness;
return res;
}
//*******************************************************************************************************************************
//--------------------------------- CROSSOVER
public void crossover(){
int j, countCross = 0;
Sampling samp = new Sampling(popSize);
int p1 = -1;
for ( j = 0 ; j < popSize; j++ ){
if( Randomize.Rand() < Parameters.crossoverProbability){
if (p1 == -1){
p1 = samp.getSample();
}
else{
int p2 = samp.getSample();
crossTwoParents(p1, p2, countCross, countCross+1);
countCross += 2;
p1 = -1;
}
}
else{
crossOneParent(samp.getSample(), countCross++);
}
}
if (p1 != -1){
crossOneParent(p1, countCross++);
}
}
public void crossTwoParents(int parent1, int parent2, int son1,int son2){
offspringPopulation[son1] = cf.cloneClassifier(population[parent1]);
offspringPopulation[son2] = cf.cloneClassifier(population[parent2]);
population[parent1].crossover(population[parent2], offspringPopulation[son1], offspringPopulation[son2]);
}
public void crossOneParent(int parent, int son){
offspringPopulation[son] = cf.cloneClassifier(population[parent]);
}
//*******************************************************************************************************************************
// --------------- MUTATION
public void mutation(){
individualMutation();
specialStages();
}
void specialStages(){
int i,j;
int numStages=offspringPopulation[0].numSpecialStages();
for(i=0;i<numStages;i++) {
for(j=0;j<popSize; j++) {
offspringPopulation[j].doSpecialStage(i);
}
}
}
public void individualMutation(){
int i;
for (i = 0; i < popSize; i++) {
if(Randomize.Rand()<Parameters.mutationProbability) {
offspringPopulation[i].mutation();
}
}
}
//*******************************************************************************************************************************
//-------------------- REMPLAZAMENT
public void replacementAlgorithm(){
totalReplacement();
doFitnessComputations();
createPopulationRank();
if(Parameters.elitismEnabled) doElitism();
}
public void doElitism(){
int i,j;
for(i=0;i<numVersions;i++) {
if(best[i]!=null) {
best[i].fitnessComputation();
}
}
int numV=numVersions;
Vector<Integer> priorities = new Vector<Integer>(popSize+numV);
for(i=0;i<popSize;i++) priorities.addElement(populationRank[i].pos);
for(i=0;i<numV;i++) {
if(best[i]!=null) {
int size=priorities.size();
for(j=0;j<size;j++) {
classifier ind;
int pos=priorities.get(j);
if(pos>=popSize) {
ind=best[pos-popSize];
} else {
ind=population[pos];
}
if(best[i].compareToIndividual(ind,Parameters.optimizationMethod)>0) {
priorities.insertElementAt(popSize+i,j);
break;
}
}
if(j==size) {
priorities.addElement(popSize+i);
}
}
}
Vector<Integer> elite = new Vector<Integer>();
for(i=0;i<popSize;i++) {
if(priorities.get(i)>=popSize) {
elite.addElement(priorities.get(i)-popSize);
}
}
int index=0;
int size=priorities.size();
for(i=popSize;i<size;i++) {
if(priorities.get(i)<popSize) {
int pos=priorities.get(i);
population[pos]= cf.cloneClassifier(best[elite.get(index++)]);
}
}
flagResetBest=0;
}
public void totalReplacement(){
classifier[] tempPop = new classifier[popSize];
System.arraycopy(population, 0, tempPop, 0, popSize);
System.arraycopy(offspringPopulation, 0, population, 0, popSize);
System.arraycopy(tempPop, 0, offspringPopulation, 0, popSize);
}
//*******************************************************************************************************************************
classifier[] getPopulation() { return population; }
classifier getBest() { return best[Parameters.is.getCurrentVersion()]; }
classifier getWorst() {return population[populationRank[popSize - 1].pos];}
rank[] getPopulationRank() { return populationRank; }
//*******************************************************************************************************************************
public void createPopulationRank(){
int i;
double[] vectorQS = new double[popSize];
for( i = 0 ; i < popSize ; ++i )
vectorQS[i] = population[i].fitness;
int optionQS = (Parameters.optimizationMethod == Parameters.MINIMIZE) ? Quicksort.LOWEST_FIRST: Quicksort.HIGHEST_FIRST;
int[] posQS = Quicksort.sort(vectorQS, popSize, optionQS);
for( i = 0; i < popSize; i++ ){
populationRank[i].pos = posQS[i];
populationRank[i].ind = cf.cloneClassifier(population[posQS[i]]);
}
}
//*******************************************************************************************************************************
public void doFitnessComputations(){
int i;
for(i=0;i<popSize;i++) {
population[i].fitnessComputation();
}
maxFitness=minFitness=population[0].getFitness();
for(i=1;i<popSize;i++) {
double fitness=population[i].getFitness();
if(fitness>maxFitness) {
maxFitness=fitness;
}
if(fitness<minFitness) {
minFitness=fitness;
}
}
}
public void resetBest(){
flagResetBest=1;
}
public void checkBestIndividual(){
int currVer = Parameters.is.getCurrentVersion();
if (best[currVer]==null) {
best[currVer] = cf.cloneClassifier(populationRank[0].ind);
} else {
best[currVer].fitnessComputation();
if (best[currVer].compareToIndividual(populationRank[0].ind, Parameters.optimizationMethod) < 0) {
best[currVer] = cf.cloneClassifier(populationRank[0].ind);
}
}
}
}