/***********************************************************************
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.Genetic_Rule_Learning.COGIN;
import org.core.Randomize;
import keel.Dataset.Instance;
/**
* <p>
* This class implements a binary chromosome as specified in the COGIN algorithm
* </p>
*
* <p>
* @author Written by Juli�n Luengo Mart�n 08/02/2007
* @version 0.2
* @since JDK 1.5
* </p>
*/
public class Chromosome implements Comparable{
Gene rule[];
int numGenes;
int totalBits;
int _class;
int coveredInstances;
double fitness;
/**
* <p>
* Default constructor
* </p>
*/
public Chromosome(){
rule = null;
numGenes = 0;
_class = -1;
totalBits = 0;
}
/**
* <p>
* Builds up a new chromosome with specified number of genes
* </p>
* @param nGenes number of genes of this chromosome
*/
public Chromosome(int nGenes){
numGenes = nGenes;
rule = new Gene[numGenes];
_class = -1;
totalBits = 0;
}
/**
* <p>
* Copy constructor. Performs a deep-copy
* </p>
* @param ch the original chromosome
*/
public Chromosome(Chromosome ch){
this.numGenes = ch.numGenes;
this.totalBits = ch.totalBits;
this._class = ch._class;
this.coveredInstances = ch.coveredInstances;
this.fitness = ch.fitness;
this.rule = new Gene[ch.rule.length];
for(int i=0;i<ch.rule.length;i++){
this.rule[i] = new Gene(ch.rule[i]);
}
}
/**
* <p>
* Gets the class output associated to this individual
* </p>
* @return the index of the class associated
*/
public int getClas(){
return _class;
}
/**
* <p>
* Gives the fitness of the chromosome
* </p>
* @return the current fitness
*/
public double getFitness(){
return fitness;
}
/**
* <p>
* Gets the gene at specified position
* </p>
* @param whichGene the index of the gene
* @return the value of the indicated gene
*/
public Gene getGene(int whichGene){
return rule[whichGene];
}
/**
* <p>
* the number of genes of this individual
* </p>
* @return the number of genes
*/
public int getNumGenes(){
return numGenes;
}
/**
* <p>
* Gets the number of instances covered by this chromosome
* </p>
* @return the number of instances covered
*/
public int getCoveredInstances(){
return coveredInstances;
}
/**
* <p>
* Set the class of this chromosome
* </p>
* @param c the new class
*/
public void setClass(int c){
_class = c;
}
/**
* <p>
* Set the value of the specified gene
* </p>
* @param pos the index of the gene to be changed
* @param gen The new gene value
*/
public void setGene(int pos,Gene gen){
if(rule[pos]!=null)
totalBits -= rule[pos].getNumBits();
rule[pos] = gen;
totalBits += rule[pos].getNumBits();
}
/**
* <p>
* Set the fitness of this individual
* </p>
* @param fit the new fitness
*/
public void setFitness(double fit){
fitness = fit;
}
/**
* <p>
* Set the number of covered instances
* </p>
* @param cov the new count of covered instances
*/
public void setCoveredInstances(int cov){
coveredInstances = cov;
}
/**
* <p>
* Test if the instances is covered by the rule
* </p>
* @param inst The instance to be tested
* @return True if it is covered by this rule, False if not
*/
public boolean covers(Instance inst){
boolean covered;
covered = true;
//conjunctive rule, so all Genes must match
for(int i=0;i<numGenes && covered;i++){
covered = rule[i].test(inst.getAllInputValues()[i]);
}
return covered;
}
/**
* <p>
* Forces this individual to cover the provided instance
* </p>
* @param inst the instance to be covered
*/
public void makeCover(Instance inst){
boolean covered;
for(int i=0;i<numGenes;i++){
covered = rule[i].test(inst.getAllInputValues()[i]);
if(!covered){
rule[i].applydiffs(inst.getAllInputValues()[i]);
}
}
if(_class != (int)inst.getAllOutputValues()[0])
_class = (int)inst.getAllOutputValues()[0];
}
/**
* <p>
* Crossover between chromosomes, using the swap from one point approach
* </p>
* @param ch the chromosome to be coupled with
*/
public void swapOnePoint(Chromosome ch){
int swapPoint,actualPoint,i,tmp;
Gene gen;
//count the feature bits -totalBits- and the unique negation bits per gene -numGenes-
swapPoint = Randomize.Randint(0, totalBits+numGenes);
actualPoint = rule[0].getNumBits();
//swap complete genes between the parents
for(i=0;i<numGenes && actualPoint<swapPoint;i++){
gen = this.rule[i];
this.rule[i] = ch.rule[i];
ch.rule[i] = gen;
actualPoint = actualPoint + rule[i+1].getNumBits() + 1;
}
//swap the partial gene if needed
actualPoint = actualPoint - rule[i].getNumBits() - 1;
actualPoint = swapPoint - actualPoint;
if(actualPoint >= 1){
tmp = this.rule[i].getNegationBit();
this.rule[i].setNegation(ch.rule[i].getNegationBit());
ch.rule[i].setNegation(tmp);
actualPoint--;
}
for(int j=0;j<actualPoint;j++){
tmp = this.rule[i].getBit(j);
this.rule[i].setBit(j, ch.rule[i].getBit(j));
ch.rule[i].setBit(j,(char)tmp);
}
}
/**
* <p>
* classifies the provided instance with this chromosome
* </p>
* @param inst the instance to be classified
* @return the predicted class (the class of the chromosome if covered, -1 if not)
*/
public int classify(Instance inst){
boolean covered;
covered = true;
//conjunctive rule, so all Genes must match
for(int i=0;i<numGenes && covered;i++){
covered = rule[i].test(inst.getAllInputValues()[i]);
}
if(covered)
return _class;
else
return -1;
}
/**
* Implements the Comparator method to sort chromosomes by
* its fitness.
*/
public int compareTo(Object o){
Chromosome ch = (Chromosome) o;
if(this.fitness > ch.fitness)
return 1;
if(this.fitness < ch.fitness)
return -1;
return 0;
}
}