/***********************************************************************
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.Associative_Classification.ClassifierFuzzyFCRA;
import java.util.*;
import org.core.*;
/**
* This class contains the population for the genetic algorithm
*
* @author Written by Jesus Alcal� (University of Granada) 09/02/2010
* @version 1.2
* @since JDK1.5
*/
public class Population {
ArrayList<Individual> Population;
ArrayList<Individual> offspring;
double crossProb, mutProb, wCAR, wV, n1, n2;
int n_variables, pop_size, lengthSC, Jmax;
double best_fitness, best_accuracy;
int[] selected;
myDataset train;
DataBase dataBase;
Apriori apriori;
/**
* Maximization
* @param a int first number
* @param b int second number
* @return boolean true if a is better than b
*/
public boolean BETTER(double a, double b) {
if (a > b) {
return true;
}
return false;
}
/**
* Default Constructor
*/
public Population() {
}
/**
* Constructor with parameters
* @param train myDataset training set
* @param dataBase DataBase dataBase
* @param size int population size
* @param crossProb double crossover probability
* @param mutProb double mutation probability
* @param wCAR double relative weight of the classification accuracy rate
* @param wV double relative weight of the number of fuzzy rules
* @param n1 double learning rate (Nozaki method)
* @param n2 double learning rate (Nozaki method)
* @param Jmax int number of iterations (Nozaki method)
* @param apriori Apriori an Apriori objects
*/
public Population(myDataset train, DataBase dataBase, int size, double crossProb, double mutProb, int lengthSC, double wCAR, double wV, double n1, double n2, int Jmax, Apriori apriori) {
this.dataBase = dataBase;
this.train = train;
this.apriori = apriori;
this.n_variables = dataBase.numVariables();
this.pop_size = size;
this.mutProb = mutProb;
this.crossProb = crossProb;
this.lengthSC = lengthSC;
this.wCAR = wCAR;
this.wV = wV;
this.n1 = n1;
this.n2 = n2;
this.Jmax = Jmax;
this.selected = new int[this.pop_size];
Population = new ArrayList<Individual>();
offspring = new ArrayList<Individual>();
}
private void init() {
for (int i = 0; i < this.pop_size; i++) {
Individual ind = new Individual(this.wCAR, this.wV, this.lengthSC);
ind.randomValues();
Population.add(ind);
}
this.best_fitness = 0.0;
}
/**
* Main procedure of the GA
* @param n_Generations int number of generations
*/
public void Generation(int n_Generations) {
init();
evaluate(Population);
for (int i = 0; i < n_Generations; i++) {
selection();
crossover();
mutation();
evaluate(offspring);
elitist(i);
}
}
private void selection() {
int i, j;
double random, f_min, sum;
double[] probabilities = new double[Population.size()];
ArrayList<Selected> vector = new ArrayList<Selected>();
offspring.clear();
Collections.sort(Population);
f_min = Population.get(Population.size() - 1).fitness;
sum = 0;
for (i = 0; i < Population.size(); i++) {
probabilities[i] = Population.get(i).fitness - f_min;
sum += (probabilities[i] - f_min);
}
for (i = 0; i < Population.size(); i++) {
probabilities[i] /= sum;
Selected s = new Selected(probabilities[i], i);
vector.add(s);
}
Collections.sort(vector);
for (i = 0; i < Population.size(); i++) {
random = Randomize.Rand();
for (j = 0; random < vector.get(j).probability; j++);
selected[i] = vector.get(j).post;
}
}
private void crossover() {
double random;
int pointCross1, pointCross2;
for (int i = 0; i < Population.size(); i+=2) {
Individual dad = Population.get(selected[i]).clone();
Individual mom = Population.get(selected[i + 1]).clone();
random = Randomize.Rand();
if (random < this.crossProb) {
pointCross1 = Randomize.Randint(0, this.lengthSC);
pointCross2 = Randomize.Randint(this.lengthSC, (this.lengthSC * 2));
dad.interchangeValues(mom, pointCross1, pointCross2);
}
offspring.add(dad);
offspring.add(mom);
}
}
private void mutation() {
for (int i = 0; i < offspring.size(); i++) {
offspring.get(i).mutation(this.mutProb);
}
}
private void elitist(int generation) {
Collections.sort(Population);
Individual best = Population.get(0).clone();
Population.clear();
Population.add(best);
Collections.sort(offspring);
offspring.remove(offspring.size() - 1);
for (int i = 0; i < offspring.size(); i++) {
Individual indiv = offspring.get(i).clone();
Population.add(indiv);
}
if (BETTER(best.getFitness(), this.best_fitness)) {
this.best_fitness = best.getFitness();
this.best_accuracy = best.getAccuracy();
}
System.out.println("Best Fitness obtained in generation[" + generation + "]: " + this.best_fitness + " Accuracy: " + this.best_accuracy);
}
private void evaluate (ArrayList<Individual> Individuals) {
double fit, acc;
this.best_fitness = Double.NEGATIVE_INFINITY;
best_accuracy = 0.0;
for (int i = 0; i < Individuals.size(); i++) {
if (Individuals.get(i).isNew()) Individuals.get(i).evaluate(this.apriori, this.n1, this.n2, this.Jmax);
fit = Individuals.get(i).getFitness();
if (BETTER(fit, this.best_fitness)) {
this.best_fitness = fit;
this.best_accuracy = Individuals.get(i).getAccuracy();
}
}
}
/**
* It returns the best RB found so far
* @return RuleBase the best RB found so far
*/
public RuleBase getBestRB() {
RuleBase ruleBase;
Collections.sort(Population);
ruleBase = Population.get(0).generateRB(this.apriori, this.n1, this.n2, this.Jmax);
return ruleBase;
}
/**
* It returns the best minimum support
* @return double the best minimum support found so far
*/
public double getBestMinFS() {
Collections.sort(Population);
return Population.get(0).getMinFS();
}
/**
* It returns the best minimum confidence
* @return double the best minimum confidence found so far
*/
public double getBestMinFC() {
Collections.sort(Population);
return Population.get(0).getMinFC();
}
}