/*********************************************************************** 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 java.util.ArrayList; import keel.Dataset.Attribute; /** * <p> * This class implements a gene as specified by 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 Gene { int negationBit = 0; char featureBits[]; int bits; Attribute att; /** * <p> * Default constructor * </p> */ public Gene(){ negationBit = 0; featureBits = null; } /** * <p> * this constructor builds up a gene from the information of an attribute * </p> * @param a the attribute */ public Gene(Attribute a){ int nvalues; att = a; negationBit = 0; if(att.getType()==Attribute.NOMINAL) nvalues = att.getNumNominalValues(); else nvalues =(int) (att.getMaxAttribute() - att.getMinAttribute() +1); bits = (int)Math.ceil(Math.log(nvalues)/Math.log(2)); if(bits==0) bits = 1; featureBits = new char [bits]; } /** * <p> * Copy constructor, performs a deep copy of the passed object * </p> * @param gen the gene to be copied */ public Gene(Gene gen){ this.negationBit = gen.negationBit; this.bits = gen.bits; this.att = gen.att; featureBits = new char[gen.featureBits.length]; for(int i=0;i<gen.featureBits.length;i++){ this.featureBits[i] = gen.featureBits[i]; } } /** * <p> * Obtains the status of the negation bit * </p> * */ public int getNegationBit(){ return negationBit; } /** * <p> * Obtains the number of bits (computed from the attribute associated) * </p> * */ public int getNumBits(){ return bits; } /** * <p> * Get the bit indicated * </p> * @param pos position of the bit to be retrieved * @return the status of the bit */ public char getBit(int pos){ return featureBits[pos]; } /** * <p> * Sets the negation bit of this gene * </p> * @param isNeg The new negation status */ public void setNegation(int isNeg){ negationBit = isNeg; } /** * <p> * Sets the bits status indicated by index and value * </p> * @param i the index of the bit * @param newBit the new status (0 or 1) */ public void setBit(int i,char newBit){ featureBits[i] = newBit; } /** * <p> * This method converts from the status of the gene to a * list of nominals values of the attribute which are currently covered * </p> * @return the arraylist of currently covered nominal values */ public ArrayList<Integer> bin2nominal(){ ArrayList<String> binaries = new ArrayList<String>(); ArrayList<String> complement; ArrayList<Integer> nominalList; int num; String cad = new String(""); String clone; binaries.add(cad); for(int i=0;i<featureBits.length;i++){ //concat the bit to the binary String if(featureBits[i]!='#'){ for(int j=0;j<binaries.size();j++){ cad = binaries.get(j); cad = cad + featureBits[i]; binaries.set(j, cad); } } //the '#' implies to add the '0' and '1' possibilites else{ complement = new ArrayList<String>(); for(int j=0;j<binaries.size();j++){ cad = binaries.get(j); clone = new String(cad); cad = cad + "1"; binaries.set(j, cad); clone = clone + "0"; complement.add(clone); } binaries.addAll(complement); } } nominalList = new ArrayList<Integer>(); for(int i=0;i<binaries.size();i++){ num = Integer.parseInt(binaries.get(i),2); nominalList.add(new Integer(num)); } return nominalList; } /** * <p> * Test if the passed value (index of the nominal in the * attribute) is covered by this gene * </p> * @param value the index of the nominal value in the attribute list * @return True if the value is covered by the gene, False otherwise */ public boolean test(double value){ int nominalValue = (int)value; String binaryRep; boolean found; boolean allPossibleValuesPattern = true; ArrayList<Integer> nominalValues; //obtain the codified values of the gene // nominalValues = bin2nominal(); // found = false; // for(int i=0;i<nominalValues.size() && !found;i++){ // if(nominalValues.get(i).intValue() == nominalValue) // found = true; // } binaryRep = Integer.toBinaryString(nominalValue); found = true; for(int i=binaryRep.length()-1, j=featureBits.length-1;i>=0 && found;i--,j--){ if(featureBits[j]!='#'){ allPossibleValuesPattern = false; if( binaryRep.charAt(i)!=featureBits[j]) found = false; } } if(allPossibleValuesPattern) return true; if(found && negationBit == 0) return true; if(!found && negationBit == 1) return true; return false; } /** * <p> * Transforms the current gene, so the attribute value is now covered * by this gene * </p> * @param value the nominal value to be covered */ public void applydiffs(double value){ String binaryRep; int nominalValue = (int)value; binaryRep = Integer.toBinaryString(nominalValue); for(int i=binaryRep.length()-1, j=featureBits.length-1;i>=0;i--,j--){ if(featureBits[j]!='#' && binaryRep.charAt(i)!=featureBits[j] && negationBit==0){ // if(Randomize.Rand() < 0.5) featureBits[j] = binaryRep.charAt(i); // else // featureBits[j] = '#'; } else if(featureBits[j]=='#' ||( binaryRep.charAt(i)==featureBits[j] && negationBit==1)){ if(binaryRep.charAt(i) == '1') featureBits[j] = '0'; if(binaryRep.charAt(i) == '0') featureBits[j] = '1'; } } } }