/*********************************************************************** 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.Fuzzy_Rule_Learning.Genetic.ClassifierFuzzySGERD; import java.util.*; import org.core.*; /** * <p>This class contains the population for the genetic algorithm</p> * * @author Written by Alberto Fern�ndez (University of Granada) 29/10/2007 * @author Modified by Jesus Alcal� (University of Granada) 24/05/2009 * @version 1.2 * @since JDK1.5 */ public class Population { ArrayList<RuleBase> population; ArrayList<RuleBase> populationAux; RuleBase finalRuleBase; int Q, nClasses, totalLabels; myDataset train; double best_clasif, bestAccuracy; /** * Maximization * @param a int first number * @param b int second number * @return boolean true if a is better than b */ public boolean BETTER(int a, int b) { if (a > b) { return true; } return false; } /** * Default Constructor */ public Population() { } /** * Constructor with parameters * @param ruleBase RuleBase a given rule base * @param Q int a given factor * @param train myDataset the training set * @param totalLabels int the total number of fuzzy labels */ public Population(RuleBase ruleBase, int Q, myDataset train, int totalLabels) { this.Q = Q; this.train = train; this.nClasses = train.getnClasses(); this.totalLabels = totalLabels; this.finalRuleBase = ruleBase.cloneEmpty(); this.initialization(ruleBase); } /** * It initilises the population * @param ruleBase RuleBase a given Rule base */ private void initialization(RuleBase ruleBase) { int i, j; Rule rule; RuleBase base, baseAux; this.population = new ArrayList<RuleBase>(); this.populationAux = new ArrayList<RuleBase>(); for (i = 0; i < this.nClasses; i++) { this.population.add(ruleBase.cloneEmpty()); this.populationAux.add(ruleBase.cloneEmpty()); } for (i = 0; i < ruleBase.size(); i++) { rule = (ruleBase.get(i)).clone(); base = this.population.get(rule.getClas()); base.add(rule); } for (i = 0; i < this.nClasses; i++) { base = this.population.get(i); baseAux = this.populationAux.get(i); base.sort(); base.selection(baseAux, this.Q); } } /** * It performs the generation process */ public void Generation() { int j; int[] nRules = new int[nClasses]; do { for (j = 0; j < this.nClasses; j++) { nRules[j] = (this.population.get(j)).size(); } for (j = 0; j < this.nClasses; j++) { this.reproduction(j, nRules[j]); } this.elitist(); } while (this.stop()); } /** * It computes the stopping criterion * @return boolean true if no more generations must be carried out, false otherwise */ private boolean stop() { int i, j; boolean stop; RuleBase ruleBase; Rule rule; stop = true; for (i = 0; i < this.nClasses; i++) { ruleBase = population.get(i); for (j = 0; j < ruleBase.size(); j++) { rule = ruleBase.get(j); if (rule.isNew()) { stop = false; rule.offNew(); } } } return (stop); } /** * Reproduction step * @param iClass int class id * @param nRules int the number of rules to create */ private void reproduction(int iClass, int nRules) { RuleBase ruleBase, ruleBaseAux; Rule rulej, rulep; int j, p; ruleBase = this.population.get(iClass); ruleBaseAux = this.populationAux.get(iClass); for (j = 0; j < nRules; j++) { rulej = ruleBase.get(j); p = Randomize.Randint(0, ruleBase.size()-1); if (j != p) { rulep = ruleBase.get(p); crossover(rulej, rulep); } else if (ruleBaseAux.size() > 0) { p = Randomize.Randint(0, ruleBaseAux.size()-1); rulep = ruleBaseAux.get(p); mutation(rulej, rulep); } } } /** * Crossover operator * @param rulej Rule First rule to cross * @param rulep Rule Second rule to cross */ private void crossover(Rule rulej, Rule rulep) { RuleBase ruleBase; Rule rule; int antecedent; antecedent = rulep.getPosActive(Randomize.RandintClosed(1, rulep.getActive()-1)); if (!rulej.isActive(antecedent)) { for (int i = 0; i < this.totalLabels; i++) { rule = rulej.clone(); rule.setLabel(antecedent, i); rule.setConsequent(this.train); rule.evaluation(this.train); rule.onNew(); ruleBase = population.get(rule.getClas()); ruleBase.add(rule); } } } /** * Mutation operator * @param rulej Rule First rule to mutate * @param rulep Rule Second rule to mutate */ private void mutation(Rule rulej, Rule rulep) { RuleBase ruleBase; Rule rule; if (!rulej.isActive(rulep.firstActive)) { for (int i = 0; i < this.totalLabels; i++) { rule = rulej.clone(); rule.setLabel(rulep.firstActive, i); rule.setConsequent(this.train); rule.evaluation(this.train); rule.onNew(); ruleBase = population.get(rule.getClas()); ruleBase.add(rule); } } } /** * Elitism: only the best rules remain in the popluation */ private void elitist() { RuleBase ruleBase; for (int i = 0; i < this.nClasses; i++) { ruleBase = population.get(i); ruleBase.sort(); ruleBase.removeRules(this.Q); } } /* private void clasifica(ArrayList<Individuo> individuos, int generation) { boolean entrar = false; for (int i = 0; i < individuos.size(); i++) { double acc = individuos.get(i).clasifica(); if (acc > best_clasif) { best_clasif = acc; entrar = true; } } if (entrar) { System.out.println("Best Accuracy obtained in generation[" + generation + "]: " + best_clasif); } } */ /** * It writes the best rule base obtained into file * @param filename String the name of the file */ public void writeFile(String filename) { this.finalRuleBase.saveFile(filename); } /** * It returns the best rule base obtained * @return RuleBase the best rule base obtained */ public RuleBase bestRB() { this.selectRules(); return this.finalRuleBase.clone(); } /** * It select the best rules in the population */ private void selectRules() { int i, j, nActive; int[] classActive; double accuracy; RuleBase ruleBase; Rule rule; while (this.finalRuleBase.size() > 0) { this.finalRuleBase.remove(0); } for (i = 0; i < this.nClasses; i++) { ruleBase = population.get(i); if (ruleBase.size() > 0) { this.finalRuleBase.add((ruleBase.get(0)).clone()); } } this.bestAccuracy = this.finalRuleBase.classify(); nActive = 0; classActive = new int[this.nClasses]; for (i = 0; i < nClasses; i++) { ruleBase = population.get(i); if (ruleBase.size() > 1) { classActive[i] = 1; nActive++; } else { classActive[i] = 0; } } for (i = 1; nActive > 0; i++) { for (j = 0; j < this.nClasses; j++) { if (classActive[j] > 0) { ruleBase = population.get(j); rule = (ruleBase.get(i)).clone(); this.finalRuleBase.add(rule); accuracy = this.finalRuleBase.classify(); if (accuracy > this.bestAccuracy) { this.bestAccuracy = accuracy; } else { this.finalRuleBase.remove(this.finalRuleBase.size() - 1); classActive[j] = 0; nActive--; } if (ruleBase.size() == (i + 1)) { classActive[j] = 0; nActive--; } } } } this.finalRuleBase.evaluate(); } }