/***********************************************************************
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 org.core.Randomize;
import java.lang.*;
/**
* This class contains the representation of the individuals of the population
*
* @author Written by Jesus Alcal� (University of Granada) 09/02/2010
* @version 1.0
* @since JDK1.5
*/
public class Individual implements Comparable{
int[] chromosome;
double fitness, accuracy;
int lengthSC, n_e;
double wCAR, wV;
/**
* Default Constructor
*/
public Individual() {
}
/**
* Constructor with parameters
* @param chromosome int[] Chromosome to build the individual
* @param wCAR double relative weight of the classification accuracy rate
* @param wV double relative weight of the number of fuzzy rules
* @param lengthSC int total length of the individual
*/
public Individual(int [] chromosome, double wCAR, double wV, int lengthSC) {
this.wCAR = wCAR;
this.wV = wV;
this.lengthSC = lengthSC;
this.n_e = 1;
this.chromosome = new int[this.lengthSC * 2];
for (int i = 0; i < this.chromosome.length; i++) this.chromosome[i] = chromosome[i];
}
public Individual(double wCAR, double wV, int lengthSC) {
this.wCAR = wCAR;
this.wV = wV;
this.lengthSC = lengthSC;
this.n_e = 1;
this.chromosome = new int[this.lengthSC * 2];
}
/**
* <p>
* Initialization of the individual with random values
* </p>
*/
public void randomValues () {
for (int i = 0; i < this.chromosome.length; i++){
if (Randomize.Rand() < 0.5) chromosome[i] = 0;
else chromosome[i] = 1;
}
this.n_e = 1;
}
/**
* <p>
* It interchanges the values between the position pointCross1 and pointCross2
* </p>
* @param indiv Inidividual an individual
* @param pointCross1 int left posotion
* @param pointCross2 int right posotion
*/
public void interchangeValues(Individual indiv, int pointCross1, int pointCross2){
int i, aux;
for (i = pointCross1; i <= pointCross2; i++) {
aux = this.chromosome[i];
this.chromosome[i] = indiv.chromosome[i];
indiv.chromosome[i] = aux;
}
this.n_e = 1;
indiv.n_e = 1;
}
/**
* <p>
* It returns the number of rules in the rule base
* </p>
* @return int Rule base's size
*/
public int size(){
return this.chromosome.length;
}
/**
* <p>
* It applies the mutation operator
* </p>
*/
public void mutation(double prob){
for (int i = 0; i < this.chromosome.length; i++){
if (Randomize.Rand() < prob) {
if (this.chromosome[i] == 0) this.chromosome[i] = 1;
else this.chromosome[i] = 0;
this.n_e = 1;
}
}
}
/**
* <p>
* Clone Function
* </p>
*/
public Individual clone(){
Individual i = new Individual();
i.lengthSC = this.lengthSC;
i.fitness = this.fitness;
i.accuracy = this.accuracy;
i.wCAR = this.wCAR;
i.wV = this.wV;
i.n_e = this.n_e;
i.chromosome = new int[this.chromosome.length];
for (int j = 0; j < this.chromosome.length; j++) i.chromosome[j] = this.chromosome[j];
return i;
}
/**
* <p>
* Function to return if this individual is new in the population
* </p>
* @return boolean true = it is-, false = it isn't
*/
public boolean isNew () {
if (this.n_e == 1) return (true);
else return (false);
}
/**
* <p>
* Function to return the accuracy of the individual
* </p>
* @return double The accuracy of the individual
*/
public double getAccuracy() {
return this.accuracy;
}
/**
* <p>
* Function to return the fitness of the individual
* </p>
* @return double The fitness of the individual
*/
public double getFitness() {
return this.fitness;
}
/**
* <p>
* Function to return the minimum support of the individual
* </p>
* @return double The minimum support of the individual
*/
public double getMinFS () {
double minFS = 0.0;
for (int i = 0, j = this.lengthSC - 1; j >= 0; i++, j--) {
if (this.chromosome[i] > 0) minFS += Math.pow(2.0, j);
}
minFS /= Math.pow(2.0, this.lengthSC);
return (minFS);
}
/**
* <p>
* Function to return the minimum confidence of the individual
* </p>
* @return double The minimum confidence of the individual
*/
public double getMinFC () {
double minFC = 0.0;
for (int i = this.lengthSC, j = this.lengthSC - 1; j >= 0; i++, j--) {
if (this.chromosome[i] > 0) minFC += Math.pow(2.0, j);
}
minFC /= Math.pow(2.0, this.lengthSC);
return (minFC);
}
/**
* <p>
* Generates the Rule Base with adjusted fuzzy confidences
* </p>
* @param apriori Apriori Apriori object
* @param n1 double learning rate (Nozaki method)
* @param n2 double learning rate (Nozaki method)
* @param Jmax int number of iterations (Nozaki method)
* @return RuleBase The whole CAR rule set
*/
public RuleBase generateRB(Apriori apriori, double n1, double n2, int Jmax) {
double minFS, minFC;
RuleBase ruleBase;
minFS = this.getMinFS();
minFC = this.getMinFC();
ruleBase = apriori.generateRB(minFS, minFC);
ruleBase.adaptiveRules(n1, n2, Jmax);
return ruleBase;
}
/**
* <p>
* Evaluates this individual
* </p>
* @param n1 double learning rate (Nozaki method)
* @param n2 double learning rate (Nozaki method)
* @param Jmax int number of iterations (Nozaki method)
*/
public void evaluate(Apriori apriori, double n1, double n2, int Jmax) {
RuleBase ruleBase;
ruleBase = this.generateRB(apriori, n1, n2, Jmax);
if (ruleBase.size() < 1) {
this.fitness = Double.NEGATIVE_INFINITY;
this.accuracy = 0.0;
}
else {
this.accuracy = ruleBase.evaluate();
this.fitness = (this.wCAR * ruleBase.getAccuracy()) - (this.wV * ruleBase.size());
}
this.n_e = 0;
}
/**
* Function to compare objects of the Individual class
* Necessary to be able to use "sort" function
* It sorts in an increasing order of fitness
*/
public int compareTo(Object a) {
if ( ( (Individual) a).fitness < this.fitness) {
return -1;
}
if ( ( (Individual) a).fitness > this.fitness) {
return 1;
}
return 0;
}
}