/*********************************************************************** 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.UnsupervisedLearning.AssociationRules.IntervalRuleLearning.MOPNAR; /** * <p> * @author Written by Diana Mart�n (dmartin@ceis.cujae.edu.cu) * @version 1.1 * @since JDK1.6 * </p> */ import org.core.Randomize; public class Gene { /** * <p> * It is used for representing and handling a Gene throughout the evolutionary learning * </p> */ public static final int NOT_INVOLVED = -1; public static final int ANTECEDENT = 0; public static final int CONSEQUENT = 1; private int attr; private int ac; private boolean pn; private double lb; private double ub; private double min_attr; private double max_attr; private int type; public int getType() { return type; } public void setType(int type) { this.type = type; } /** * <p> * It creates a new gene * </p> */ public Gene() { } /** * <p> * It allows to clone correctly a gene * </p> * @return A copy of the gene */ public Gene copy() { Gene gene = new Gene(); gene.attr = this.attr; gene.ac = this.ac; gene.pn = this.pn; gene.lb = this.lb; gene.ub = this.ub; gene.type = this.type; gene.min_attr = this.min_attr; gene.max_attr = this.max_attr; return gene; } /** * <p> * It does inversions for each part of a gene which were specifically designed for this algorithm * </p> * @param type The domain type of gene * @param min_attr The minimum domain value depending on the type of gene * @param max_attr The maximum domain value depending on the type of gene */ public void invert(int type, double min_attr, double max_attr) { switch (this.ac) { case Gene.NOT_INVOLVED: this.ac = Gene.ANTECEDENT; break; case Gene.ANTECEDENT: this.ac = Gene.CONSEQUENT; break; case Gene.CONSEQUENT: this.ac = Gene.NOT_INVOLVED; } this.pn = !this.pn; if ( type != myDataset.NOMINAL ) { if ( type == myDataset.REAL ) { this.lb = Randomize.RandClosed() * (this.lb - min_attr) + min_attr; this.ub = Randomize.RandClosed() * (max_attr - this.ub) + this.ub; } else { this.lb = Randomize.RandintClosed((int)min_attr, (int)this.lb); this.ub = Randomize.RandintClosed((int)this.ub, (int)max_attr); } } else { if (this.lb == max_attr) this.lb = this.ub = min_attr; else { this.lb++; this.ub++; } } } /** * <p> * It returns whether a gene is involved in the chromosome being considered. * In case it is involved, returns if it acts as antecedent or consequent * </p> * @return A constant value indicating the "role" played by the gene */ public int getActAs() { return this.ac; } /** * <p> * It sets whether a gene is involved in the chromosome being considered. * In case it is involved, the user must specify if it acts as antecedent or consequent * </p> * @param ac The constant value indicating the "role" played by the gene */ public void setActAs(int ac) { this.ac = ac; } /** * <p> * It returns if a gene treats a positive or negative interval * </p> * @return A value indicating whether the interval must be considered as positive */ public boolean getIsPositiveInterval() { return this.pn; } /** * <p> * It sets if a gene treats positive or negative interval * </p> * @param pn The value indicating whether the interval must be considered as positive */ public void setIsPositiveInterval(boolean pn) { this.pn = pn; } /** * <p> * It returns the lower bound of the interval stored in a gene * </p> * @return A value indicating the lower bound of the interval */ public double getLowerBound() { return this.lb; } /** * <p> * It sets the lower bound of the interval stored in a gene * </p> * @param lb The value indicating the lower bound of the interval */ public void setLowerBound(double lb) { this.lb = lb; } /** * <p> * It returns the upper bound of the interval stored in a gene * </p> * @return A value indicating the upper bound of the interval */ public double getUpperBound() { return this.ub; } /** * <p> * It sets the upper bound of the interval stored in a gene * </p> * @param lb The value indicating the upper bound of the interval */ public void setUpperBound(double ub) { this.ub = ub; } /** * <p> * It indicates whether some other gene is "equal to" this one * </p> * @param obj The reference object with which to compare * @return True if this gene is the same as the argument; False otherwise */ public boolean equals(Gene g) { double lb_posit, ub_posit; if (g.attr == this.attr) { if (g.ac == this.ac) { if (g.pn == this.pn) { if (Math.abs(g.lb - this.lb) <= 0.00001) { if (Math.abs(g.ub - this.ub) <= 0.00001) return true; } } else { if (!g.pn){ if(g.lb == this.min_attr){ lb_posit = g.ub; ub_posit = this.max_attr; if (type == myDataset.REAL) lb_posit+= 0.0001; else lb_posit += 1; if (Math.abs(lb_posit - this.lb) <= 0.00001) { if (Math.abs(ub_posit - this.ub) <= 0.00001) return true; } } if(g.ub == this.max_attr){ lb_posit = this.min_attr; ub_posit = g.lb; if(type == myDataset.REAL) ub_posit -= 0.0001; else ub_posit -= 1; if (Math.abs(lb_posit - this.lb) <= 0.00001) { if (Math.abs(ub_posit - this.ub) <= 0.00001) return true; } } } else { if(!this.pn){ if(this.lb == this.min_attr){ lb_posit = this.ub; ub_posit = this.max_attr; if (type == myDataset.REAL) lb_posit+= 0.0001; else lb_posit += 1; if (Math.abs(lb_posit - g.lb) <= 0.00001) { if (Math.abs(ub_posit - g.ub) <= 0.00001) return true; } } if(this.ub == this.max_attr){ lb_posit =this.min_attr; ub_posit = this.lb; if(type == myDataset.REAL) ub_posit -= 0.0001; else ub_posit -= 1; if (Math.abs(lb_posit - g.lb) <= 0.00001) { if (Math.abs(ub_posit - g.ub) <= 0.00001) return true; } } } } } } } return false; } /** * <p> * It returns a string representation of a gene * </p> * @return A string representation of the gene */ public String toString() { return "Attr: " + attr + "AC: " + ac + "; PN: " + pn + "; LB: " + lb + "; UB: " + ub; } public int getAttr() { return this.attr; } public void setAttr(int var) { this.attr = var; } public int randAct () { return (Randomize.RandintClosed(Gene.NOT_INVOLVED, Gene.CONSEQUENT)); } public void tuneInterval (myDataset dataset, int[] covered) { int i, r, nData; double min, max, delta; double[] example; nData = dataset.getnTrans(); if(this.pn){ min = this.ub; max = this.lb; for (i=0; i < nData; i++) { if (covered[i] > 0) { example = dataset.getExample(i); if (example[this.attr] < min) min = example[this.attr]; if (example[this.attr] > max) max = example[this.attr]; } } this.ub = max; this.lb = min; } else//negative interval { if(dataset.getAttributeType(this.attr)== myDataset.REAL) delta = 0.0001; else delta = 1.0; min = dataset.getMax(this.attr) + delta; max = dataset.getMin(this.attr) - delta; for (r=0; r < nData; r++) { if (covered[r] > 0) { example = dataset.getExample(r); if ( (example[this.attr] < min) && (example[this.attr] > this.ub) ) min = example[this.attr]; if ( (example[this.attr] > max) && (example[this.attr] < this.lb) ) max = example[this.attr]; } } this.lb = max + delta; this.ub = min - delta; } } public boolean isCover (int var, double value) { boolean covered; if (this.attr != var) return (false); covered = true; if (this.pn) { if ((value < this.lb) || (value > this.ub)) covered = false; } else { if ((value >= this.lb) && (value <= this.ub)) covered = false; } return (covered); } public boolean isSubGen (Gene g) { double lb_posit, ub_posit; if (this.attr != g.attr) return (false); if (this.ac != g.ac) return (false); if ((this.pn) && (g.pn)){ if (Math.abs(g.lb - this.lb) > 0.00001) return (false); if (Math.abs(g.ub - this.ub) > 0.00001) return (false); } else if ((!this.pn) && (!g.pn)){//negative interval if (Math.abs(g.lb - this.lb) > 0.00001) return (false); if (Math.abs(g.ub - this.ub) > 0.00001) return (false); } else { if(!g.pn){ // g negative interval if(g.lb == this.min_attr){ lb_posit = g.ub; ub_posit = this.max_attr; if (type == myDataset.REAL) lb_posit+= 0.0001; else lb_posit += 1; if (Math.abs(lb_posit - this.lb) > 0.00001) return (false); if (Math.abs(ub_posit - this.ub) > 0.00001) return (false); } if(g.ub == this.max_attr){ lb_posit = this.min_attr; ub_posit = g.lb; if(type == myDataset.REAL) ub_posit -= 0.0001; else ub_posit -= 1; if (Math.abs(lb_posit - this.lb) > 0.00001) return (false); if (Math.abs(ub_posit - this.ub) > 0.00001) return (false); } } else { // this negative interval if(!this.pn){ if(this.lb == this.min_attr){ lb_posit = this.ub; ub_posit = this.max_attr; if(type == myDataset.REAL) lb_posit+= 0.0001; else lb_posit += 1; if (Math.abs(lb_posit - g.lb) > 0.00001) return (false); if (Math.abs(ub_posit - this.ub) > 0.00001) return (false); } if(this.ub == this.max_attr){ lb_posit = this.min_attr; ub_posit = this.lb; if(type == myDataset.REAL) ub_posit -= 0.0001; else ub_posit -= 1; if (Math.abs(lb_posit - g.lb) > 0.00001) return (false); if (Math.abs(ub_posit - this.ub) > 0.00001) return (false); } } } } return (true); } public double getMax_attr() { return max_attr; } public void setMax_attr(double max_attr) { this.max_attr = max_attr; } public double getMin_attr() { return min_attr; } public void setMin_attr(double min_attr) { this.min_attr = min_attr; } }