/*********************************************************************** 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/ **********************************************************************/ /** * <p> * @author Written by Juli�n Luengo Mart�n 13/02/2007 * @version 0.1 * @since JDK 1.5 * </p> */ package keel.Algorithms.Genetic_Rule_Learning.CORE; import keel.Dataset.*; import org.core.*; import java.util.*; /** * <p> * This class represents a gene (i.e. a relation for a set of attribute values). * The real values are stored in normalized form, and the nominal values are stored * in a list form. * </p> */ public class Gene { int index; int relation; double realValue; double bound1,bound2; boolean nominalValue []; Attribute att; int type; double min; double max; String nominalValueList[]; /* for nominal attributes*/ final static int equal = 0; final static int notEqual = 1; /* for real-valued attributes */ final static int greaterThan = 2; final static int greaterThanOrEqual = 3; final static int lessThanOrEqual = 4; final static int lessThan = 5; final static int inBound = 6; final static int outOfBound = 7; /** * <p> * Parameterized constructor * </p> * @param a the attribute of this gene * @param rel the type of relation for the values of this gene */ public Gene(Attribute a,int rel){ att = a; type = a.getType(); relation = rel; if(type != Attribute.NOMINAL){ min = a.getMinAttribute(); max = a.getMaxAttribute(); } else{ nominalValueList = new String[a.getNominalValuesList().size()]; for(int i=0;i<a.getNominalValuesList().size();i++) nominalValueList[i] = a.getNominalValue(i); nominalValue = new boolean[ a.getNumNominalValues()]; } } /** * <p> * Deep-copy constructor * </p> * @param g the original gene */ public Gene(Gene g){ this.att = g.att; this.bound1 = g.bound2; this.bound2 = g.bound2; this.index = g.index; this.max = g.max; this.min = g.min; this.relation = g.relation; this.realValue = g.realValue; this.type = g.type; if(type != Attribute.NOMINAL){ min = att.getMinAttribute(); max = att.getMaxAttribute(); } else{ nominalValueList = new String[att.getNominalValuesList().size()]; for(int i=0;i<att.getNominalValuesList().size();i++) nominalValueList[i] = att.getNominalValue(i); nominalValue = new boolean[ att.getNumNominalValues()]; for(int i=0;i<nominalValue.length;i++){ this.nominalValue[i] = g.nominalValue[i]; } } } /** * <p> * Sets the real value of this gene (for one value relations, i.e. "greater than", "less or equal than", etc.) * </p> * @param _value the new real value */ public void setRealValue(double _value){ realValue = (_value - min)/(max - min); } /** * <p> * Sets the minimum bound of this gene for the real values (for interval-based relations) * </p> * @param _value the new minimum bound */ public void setRealminBound(double _value){ bound1 = (_value - min)/(max - min); } /** * <p> * Sets the maximum bound of this gene for the real values (for interval-based relations) * </p> * @param _value the new maximum bound */ public void setRealmaxBound(double _value){ bound2 = (_value - min)/(max - min); } /** * <p> * Retrieves the real value of this gene * </p> * @return the real value of this relation (normalized!) */ public double getRealValue(){ return realValue; } /** * <p> * sets the activation for a nominal value, represented by its index in the * nominal values list of the attribute * </p> * @param index the index of the nominal value * @param activation the new activation status */ public void setNominalValue(int index, boolean activation){ nominalValue[index] = activation; } /** * <p> * add a set of nominal values, so their status are now active * </p> * @param values the arraylist with the nominal values to be added */ public void addNominalValues(ArrayList<String> values){ for(int i =0;i<values.size();i++){ nominalValue[att.convertNominalValue(values.get(i))] = true; } } /** * <p> * removes a set of nominal values from the active list (if active) * </p> * @param values arraylist with the proper nominal values */ public void removeNominalValues(ArrayList<String> values){ for(int i =0;i<values.size();i++){ nominalValue[att.convertNominalValue(values.get(i))] = false; } } /** * <p> * Gets the attribute associated to this gene * </p> * @return the attribute of this gene */ public Attribute getAttribute(){ return att; } /** * <p> * Mutates this gene. If nominal, swaps its activation status with 0.5 probability. * If real valued, generates a random new value or new bounds. * </p> */ public void mutate(){ double rand1,rand2; if(type==Attribute.NOMINAL){ for(int i=0;i<nominalValueList.length;i++){ if(Randomize.Rand()<0.5) nominalValue[i] = !nominalValue[i]; } // relation = Randomize.Randint(0, 2); } if(type!=Attribute.NOMINAL){ if(relation!=Gene.inBound && relation!=Gene.outOfBound) realValue = Randomize.RandClosed(); else{ rand1 = Randomize.RandClosed(); rand2 = Randomize.RandClosed(); bound1 = Math.min(rand1, rand2); bound2 = Math.max(rand1, rand2); } } } /** * <p> * Test if two genes are the same, comparing all their values. * </p> * @param g the reference gene to be compared with * @return True if equals in values, false otherwise */ public boolean same(Gene g){ if(g.att != this.att) return false; if(this.type != Attribute.NOMINAL){ if(this.relation != g.relation) return false; if(this.relation == Gene.inBound || this.relation == Gene.outOfBound){ if(this.bound1 != g.bound1 || this.bound2 != g.bound2) return false; } else if(this.realValue != g.realValue) return false; } else{ for(int i=0;i<nominalValue.length;i++){ return this.nominalValue[i] == g.nominalValue[i]; } } return true; } /** * <p> * Test a value from an instance (of the data set), to see if it is covered. * </p> * @param input the input value (of the same attribute as this Gene!) * @return true if covered, false if not */ public boolean test(double input){ if(type==Attribute.NOMINAL){ if(nominalValue[(int)input] && relation==Gene.equal) return true; if(!nominalValue[(int)input] && relation==Gene.notEqual) return true; } if(type!=Attribute.NOMINAL){ input = (input - min)/(max - min); if(relation==Gene.greaterThanOrEqual && input >= realValue) return true; else if(relation==Gene.greaterThan && input > realValue) return true; else if (relation==Gene.lessThan && input < realValue) return true; else if (relation==Gene.lessThanOrEqual && input <= realValue) return true; else if(relation==Gene.inBound && input>=bound1 && input<=bound2) return true; else if(relation==Gene.outOfBound && input<bound1 && input>bound2) return true; } return false; } }