/*********************************************************************** 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/ **********************************************************************/ /** * * File: Rule.java * * Auxiliary class to repressent rules for the RISE algorithm * * @author Written by Joaquin Derrac (University of Granada) 8/7/2009 * @version 1.1 * @since JDK1.5 * */ package keel.Algorithms.Hyperrectangles.RISE; import keel.Dataset.Attribute; public class Rule { private static int size; //attributes of the rule private static boolean isNominal[]; //for nominal attributes private double valueMin[]; //for numeric attributes private double valueMax[]; //for numeric attributes private double valueNom[]; //for nominal attributes private boolean dontCare[]; //for nominal attributes private int output; //output attribute private double laplaceAcc; //accuracy private static int S; //SVDM parameter private static int ACV [][][]; //SVDM private static int AC [][]; //SVDM private static int nClasses; //SVDM private static int nValues[]; //SVDM private static int maxValue; //SVDM private static int Q; //distance parameter /** * Sets the size of the rule * * @param value Number of attributes of the rule * */ public static void setSize(int value){ size=value; }//end-method /** * Sets the Q parameter * * @param value Value of the Q parameter * */ public static void setQ(int value){ Q=value; }//end-method /** * Sets the S parameter * * @param value Value of the S parameter * */ public static void setS(int value){ S=value; }//end-method /** * Test which attributes are nominal * * @param inputs Attributes' descriptions * */ public static void setAttributes(Attribute[] inputs){ isNominal=new boolean[size]; for(int i=0;i<size;i++){ if(inputs[i].getType()==Attribute.NOMINAL){ isNominal[i]=true; } else{ isNominal[i]=false; } } }//end-method /** * Sets the number of classes * * @param value Number of classes * */ public static void setNClasses(int value){ nClasses=value; nValues=new int[size]; maxValue=-1; }//end-method /** * Sets the number of different values for an attribute * * @param value Number of values * @param pos Index of the attribute * */ public static void setNumValue(int value,int pos){ nValues[pos]=value; if(maxValue<value){ maxValue=value; } }//end-method /** * Sets the Laplace accuracy of the rule * * @param acc Accuracy of the rule */ public void setLaplaceAcc(double acc){ laplaceAcc=acc; }//end-method /** * Returns the output class of the rule * * @return Output class of the rule */ public int getOutput(){ return output; }//end-method /** * Returns the Laplace accuracy of the rule * * @return The accuracy of the rule */ public double getLaplaceAcc(){ return laplaceAcc; }//end-method /** * Computes the SVDM distance matrix * * @param instances Instances of the data set * @param outputs Output attribute of the instances */ public static void loadSVDMmatrix(double instances[][],int outputs[]){ ACV=new int [size][nClasses][maxValue]; AC=new int [size][nClasses]; int intValue; for(int i=0;i<size;i++){ for(int j=0;j<nClasses;j++){ for(int k=0;k<maxValue;k++){ ACV[i][j][k]=0; } AC[i][j]=0; } } for(int i=0;i<instances.length;i++){ for(int j=0;j<instances[i].length;j++){ if(isNominal[j]==true){ intValue=(int)(instances[i][j]*(nValues[j]-1)); ACV[j][outputs[i]][intValue]++; AC[j][outputs[i]]++; } } } }//end-method /** * Default builder. Generates a void rule */ public Rule(){ valueMin=new double[size]; valueMax=new double[size]; valueNom=new double[size]; dontCare=new boolean[size]; output=-1; laplaceAcc=-1.0; }//end-method /** * Builder. Generates a rule covering only a point * * @param instance Basic instance * @param out Ouput of the instance */ public Rule(double instance[],int out){ valueMin=new double[size]; valueMax=new double[size]; valueNom=new double[size]; dontCare=new boolean[size]; for(int i=0;i<size;i++){ if(isNominal[i]){ valueNom[i]=instance[i]; } else{ valueMax[i]=instance[i]; valueMin[i]=instance[i]; } dontCare[i]=false; } output=out; }//end-method /** * Reinitialices a rule, loading it with the contents of a single instance * * @param instance Basic instance * @param out Ouput of the instance */ public void loadRule(double instance[],int out){ for(int i=0;i<size;i++){ if(isNominal[i]){ valueNom[i]=instance[i]; } else{ valueMax[i]=instance[i]; valueMin[i]=instance[i]; } dontCare[i]=false; } output=out; }//end-method /** * Tests if an instance is covered by the rule * * @param instance Instance to be tested * @return True if it is covered. False, if not. */ public boolean inside(double instance[]){ boolean isInside=true; for(int i=0;i<size && isInside;i++){ if(isNominal[i]){ if((dontCare[i]==false)&&(instance[i]!=valueNom[i])){ isInside=false; } } else{ if(instance[i]<valueMin[i]){ isInside=false; } if(instance[i]>valueMax[i]){ isInside=false; } } } return isInside; }//end-method /** * Performs the most specific possible generalization over the rule to cover * a new instance * * @param instance Instance to be covered */ public void mostSpecificGeneralization(double instance[]){ for(int i=0;i<size;i++){ if(isNominal[i]){ if((dontCare[i]==false)&&(instance[i]!=valueNom[i])){ dontCare[i]=true; } } else{ if(instance[i]<valueMin[i]){ valueMin[i]=instance[i]; } if(instance[i]>valueMax[i]){ valueMax[i]=instance[i]; } } } }//end-method /** * Clone method * * @return A intialized copy of the rule */ @Override public Rule clone(){ Rule clon=new Rule(); for(int i=0;i<size;i++){ if(isNominal[i]){ clon.valueNom[i]=valueNom[i]; } else{ clon.valueMax[i]=valueMax[i]; clon.valueMin[i]=valueMin[i]; } clon.dontCare[i]=dontCare[i]; } clon.output=output; clon.laplaceAcc=laplaceAcc; return clon; }//end-method /** * Equals method * * @param rul Another rule * @return True of both rules are equal. False, if not */ @Override public boolean equals(Object rul) { Rule another=(Rule)rul; boolean isEqual=true; if(output!=another.output){ isEqual=false; } for(int i=0;i<size && isEqual;i++){ if(isNominal[i]){ if(dontCare[i]!=another.dontCare[i]){ isEqual=false; } else{ if((dontCare[i]==false)&&(valueNom[i]!=another.valueNom[i])){ isEqual=false; } } } else{ if(valueMin[i]!=another.valueMin[i]){ isEqual=false; } if(valueMax[i]!=another.valueMax[i]){ isEqual=false; } } } return isEqual; }//end-method /** * To String method * * @return A text string representing the contents of the rule */ @Override public String toString() { String text=""; for(int i=0;i<size;i++){ text+="Att"+i+": "; if(isNominal[i]){ if(dontCare[i]){ text+="TRUE "; } else{ text+=valueNom+" "; } } else{ text+=valueMin[i]+"-"; text+=valueMax[i]+" "; } } text+="Class = "+output; text+=" Acc= "+laplaceAcc; return text; }//end-method /** * Computes the distance between a given instance and the rule. Employs SVDM * distance for nominal attributes and Euclidean distance for numerical * attributes. * * @param instance Instance to be tested * * @return Distance computed */ public double distance(double instance[]){ double dist=0.0; double inc; for(int i=0;i<size;i++){ if(dontCare[i]==false){ if(isNominal[i]){ inc=SVDM(valueNom[i],instance[i],i); dist+=Math.pow(inc, S); } else{ if(instance[i]<valueMin[i]){ inc=(valueMin[i]-instance[i]); dist+=Math.pow(inc, S); } if(instance[i]>valueMax[i]){ inc=(instance[i]-valueMax[i]); dist+=Math.pow(inc, S); } } } } return dist; }//end-method /** * Gets the SVDM distance between two nominal values * * @param value1 First value * @param value2 Second value * @param att Attribute of the values * @return The SVDM distance */ private double SVDM(double value1, double value2,int att){ double dist=0.0; double aux; int count1,count2; int max,min; int denom1,denom2; denom1=(int)(value1*(nValues[att]-1)); denom2=(int)(value2*(nValues[att]-1)); for(int i=0;i<nClasses;i++){ count1=ACV[att][i][denom1]; count2=ACV[att][i][denom2]; if(count1!=count2){ max=min=0; if(count1>count2){ max=count1; min=count2; } if(count2>count1){ max=count2; min=count1; } aux=((double)(max-min)/AC[att][i]); dist+=Math.pow(aux,Q); } } return dist; }//end-method }//end-class