/***********************************************************************
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 Jaume Bacardit (La Salle, Ram�n Llull University - Barcelona) 28/03/2004
* @author Modified by Xavi Sol� (La Salle, Ram�n Llull University - Barcelona) 23/12/2008
* @author Modified by Jose A. Saez Munoz (ETSIIT, Universidad de Granada - Granada) 10/09/10
* @version 1.1
* @since JDK1.2
* </p>
*/
package keel.Algorithms.Genetic_Rule_Learning.MPLCS;
import java.util.*;
import keel.Algorithms.Genetic_Rule_Learning.MPLCS.Assistant.Globals.*;
public class GA {
Classifier[] population;
Classifier[] bestIndiv;
int numVersions;
/** Creates a new instance of GA */
public GA() {
}
/**
* Prepares GA for a new run.
*/
public void initGA() {
//Init population
population = new Classifier[Parameters.popSize];
PopulationWrapper.initInstancesEvaluation();
numVersions = PopulationWrapper.numVersions();
bestIndiv = new Classifier[numVersions];
Factory.initialize();
initPopulation(population);
Statistics.initStatistics();
}
/**
* Inits a new population.
* @param _population Population to init.
*/
private void initPopulation(Classifier[] _population) {
for (int i = 0; i < Parameters.popSize; i++) {
_population[i] = Factory.newClassifier();
_population[i].initRandomClassifier();
}
}
public void checkBestIndividual() {
Classifier best = PopulationWrapper.getBest(population);
int currVer = PopulationWrapper.getCurrentVersion();
if (bestIndiv[currVer] == null) {
bestIndiv[currVer] = best.copy();
}
else {
if (best.compareToIndividual(bestIndiv[currVer])) {
bestIndiv[currVer] = best.copy();
}
}
}
/**
* Executes a number of iterations of GA.
*/
public void run() {
Classifier[] offsprings;
PopulationWrapper.doEvaluation(population);
int numIterations = Parameters.numIterations;
for (int iteration = 0; iteration < numIterations; iteration++) {
boolean lastIteration = (iteration == numIterations - 1);
Parameters.percentageOfLearning = (double) iteration
/ (double) numIterations;
boolean res1 = PopulationWrapper.initIteration();
boolean res2 = Timers.runTimers(iteration, population);
if (res1 || res2) {
PopulationWrapper.setModified(population);
}
// GA cycle
population = doTournamentSelection(population);
offsprings = doCrossover(population);
doMutation(offsprings);
if (!Factory.realKR){
localSearch(offsprings);
}
PopulationWrapper.doEvaluation(offsprings);
population = replacementPolicy(offsprings, lastIteration);
Statistics.computeStatistics(population);
Timers.runOutputTimers(iteration, population);
}
Statistics.statisticsToFile();
Classifier best = PopulationWrapper.getBest(population);
Main.numRulesBest = best.numRules;
if(Globals_DefaultC.enabled)
Main.numRulesBest++;
LogManager.println("\nPhenotype: ");
best.printClassifier();
PopulationWrapper.testClassifier(best,"training",Parameters.train2InputFile,Parameters.trainOutputFile);
PopulationWrapper.testClassifier(best,"test",Parameters.testInputFile,Parameters.testOutputFile);
}
public void localSearch(Classifier[] _population){
int popSize = Parameters.popSize;
double probLocalSearch = Parameters.probLocalSearch;
for (int i = 0; i < popSize ; ++i){
if (Rand.getReal() < probLocalSearch) {
_population[i].doLocalSearch();
}
}
}
Classifier[] doCrossover(Classifier[] _population){
Chronometer.startChronCrossover();
int i, j, k, countCross = 0;
int numNiches = _population[0].getNumNiches();
ArrayList[] parents = new ArrayList[numNiches];
Classifier parent1, parent2;
Classifier[] offsprings = new Classifier[2];
Classifier[] offspringPopulation = new Classifier[Parameters.popSize];
for (i = 0; i < numNiches; i++) {
parents[i] = new ArrayList();
parents[i].ensureCapacity(Parameters.popSize);
}
for (i = 0; i < Parameters.popSize; i++) {
int niche = _population[i].getNiche();
parents[niche].add(new Integer(i));
}
for (i = 0; i < numNiches; i++) {
int size = parents[i].size();
Sampling samp = new Sampling(size);
int p1 = -1;
for (j = 0; j < size; j++) {
if (Rand.getReal() < Parameters.probCrossover) {
if (Rand.getReal() < Parameters.probRSWcrossover){
int num = Parameters.numParentsRSWcrossover;
int posParents[] = new int[num];
for (k = 0; k < num; k++)
posParents[k] = (Integer)parents[i].get(samp.getSample());
offspringPopulation[countCross++] = RSW(_population, posParents, num).copy();
}
else{
if (p1 == -1) {
p1 = samp.getSample();
}
else {
int p2 = samp.getSample();
int pos1 = ( (Integer) parents[i].get(p1)).intValue();
int pos2 = ( (Integer) parents[i].get(p2)).intValue();
parent1 = _population[pos1];
parent2 = _population[pos2];
offsprings = parent1.crossoverClassifiers(parent2);
offspringPopulation[countCross++] = offsprings[0];
offspringPopulation[countCross++] = offsprings[1];
p1 = -1;
}
}
}
else {
int pos = ( (Integer) parents[i].get(samp.getSample())).intValue();
offspringPopulation[countCross++] = _population[pos].copy();
}
}
if (p1 != -1) {
int pos = ( (Integer) parents[i].get(p1)).intValue();
offspringPopulation[countCross++] = _population[pos].copy();
}
}
Chronometer.stopChronCrossover();
return offspringPopulation;
}
public Classifier RSW(Classifier[] _population, int[] parentsPos, int numParents){
Classifier parents[]=new Classifier[numParents];
for (int i = 0; i < numParents; i++)
parents[i] = _population[parentsPos[i]].copy();
Classifier newSon = _population[parentsPos[0]].copy();
newSon.crossoverRSW(parents, numParents);
return newSon;
}
private int selectNicheWOR(int[] quotas) {
int num = quotas.length;
if (num == 1) {
return 0;
}
int total = 0, i;
for (i = 0; i < num; i++) {
total += quotas[i];
}
if (total == 0) {
return Rand.getInteger(0, num - 1);
}
int pos = Rand.getInteger(0, total - 1);
total = 0;
for (i = 0; i < num; i++) {
total += quotas[i];
if (pos < total) {
quotas[i]--;
return i;
}
}
LogManager.printErr("We should not be here");
System.exit(1);
return -1;
}
private void initPool(ArrayList pool, int whichNiche,
Classifier[] _population) {
if (Globals_DefaultC.nichingEnabled) {
for (int i = 0; i < Parameters.popSize; i++) {
if (_population[i].getNiche() == whichNiche) {
pool.add(new Integer(i));
}
}
}
else {
for (int i = 0; i < Parameters.popSize; i++) {
pool.add(new Integer(i));
}
}
}
private int selectCandidateWOR(ArrayList pool, int whichNiche,
Classifier[] _population) {
if (pool.size() == 0) {
initPool(pool, whichNiche, population);
if (pool.size() == 0) {
return Rand.getInteger(0, Parameters.popSize - 1);
}
}
int pos = Rand.getInteger(0, pool.size() - 1);
int elem = ( (Integer) pool.get(pos)).intValue();
pool.remove(pos);
return elem;
}
/**
* Does Tournament Selection without replacement.
*/
public Classifier[] doTournamentSelection(Classifier[] _population) {
Chronometer.startChronSelection();
Classifier[] selectedPopulation;
selectedPopulation = new Classifier[Parameters.popSize];
int i, j, winner, candidate;
int numNiches;
if (Globals_DefaultC.nichingEnabled) {
numNiches = _population[0].getNumNiches();
}
else {
numNiches = 1;
}
ArrayList[] pools = new ArrayList[numNiches];
for (i = 0; i < numNiches; i++) {
pools[i] = new ArrayList();
}
int[] nicheCounters = new int[numNiches];
int nicheQuota = Parameters.popSize / numNiches;
for (i = 0; i < numNiches; i++) {
nicheCounters[i] = nicheQuota;
}
for (i = 0; i < Parameters.popSize; i++) {
// There can be only one
int niche = selectNicheWOR(nicheCounters);
winner = selectCandidateWOR(pools[niche], niche
, _population);
for (j = 1; j < Parameters.tournamentSize; j++) {
candidate = selectCandidateWOR(pools[niche]
, niche, _population);
if (_population[candidate].compareToIndividual(_population[winner])) {
winner = candidate;
}
}
selectedPopulation[i] = _population[winner].copy();
}
Chronometer.stopChronSelection();
return selectedPopulation;
}
public void doMutation(Classifier[] _population) {
Chronometer.startChronMutation();
int popSize = Parameters.popSize;
double probMut = Parameters.probMutationInd;
for (int i = 0; i < Parameters.popSize; i++) {
if (Rand.getReal() < probMut) {
_population[i].doMutation();
}
}
doSpecialStages(_population);
Chronometer.stopChronMutation();
}
void sortedInsert(ArrayList set, Classifier cl) {
for (int i = 0, max = set.size(); i < max; i++) {
if (cl.compareToIndividual( (Classifier) set.get(i))) {
set.add(i, cl);
return;
}
}
set.add(cl);
}
public Classifier[] replacementPolicy(Classifier[] offspring
, boolean lastIteration) {
int i;
Chronometer.startChronReplacement();
if (lastIteration) {
for (i = 0; i < numVersions; i++) {
if (bestIndiv[i] != null) {
PopulationWrapper.evaluateClassifier(
bestIndiv[i]);
}
}
ArrayList set = new ArrayList();
for (i = 0; i < Parameters.popSize; i++) {
sortedInsert(set, offspring[i]);
}
for (i = 0; i < numVersions; i++) {
if (bestIndiv[i] != null) {
sortedInsert(set, bestIndiv[i]);
}
}
for (i = 0; i < Parameters.popSize; i++) {
offspring[i] = (Classifier) set.get(i);
}
}
else {
boolean previousVerUsed = false;
int currVer = PopulationWrapper.getCurrentVersion();
if (bestIndiv[currVer] == null && currVer > 0) {
previousVerUsed = true;
currVer--;
}
if (bestIndiv[currVer] != null) {
PopulationWrapper.evaluateClassifier(bestIndiv[currVer]);
int worst = PopulationWrapper.getWorst(offspring);
offspring[worst] = bestIndiv[currVer].copy();
}
if (!previousVerUsed) {
int prevVer;
if (currVer == 0) {
prevVer = numVersions - 1;
}
else {
prevVer = currVer - 1;
}
if (bestIndiv[prevVer] != null) {
PopulationWrapper.evaluateClassifier(bestIndiv[prevVer]);
int worst = PopulationWrapper.getWorst(offspring);
offspring[worst] = bestIndiv[prevVer].copy();
}
}
}
Chronometer.stopChronReplacement();
return offspring;
}
public void doSpecialStages(Classifier[] population) {
int numStages = population[0].numSpecialStages();
for (int i = 0; i < numStages; i++) {
for (int j = 0; j < population.length; j++) {
population[j].doSpecialStage(i);
}
}
}
}