/*********************************************************************** 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); } } } }