/*********************************************************************** 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: BNGE.java * * The BNGE Algorithm. * The algorithm tries to show that is enough to consider a small neighbourhood * to achieve classification accuracy comparable to an algorithm considering the * whole learning set, combining this k-nearest neighbours method and a * rule-based algorithm. * * @author Written by Joaquin Derrac (University of Granada) 8/7/2009 * @author Modified by Joaquin Derrac (University of Granada) 17/10/2009 * @version 1.2 * @since JDK1.5 * */ package keel.Algorithms.Hyperrectangles.BNGE; import java.util.StringTokenizer; import org.core.*; import keel.Dataset.Attribute; import keel.Dataset.Attributes; import keel.Algorithms.Hyperrectangles.Basic.HyperrectanglesAlgorithm; public class BNGE extends HyperrectanglesAlgorithm{ Rule ruleset[]; /** * The main method of the class * * @param script Name of the configuration script * */ public BNGE (String script) { readDataFiles(script); //Naming the algorithm name="BNGE"; Rule.setSize(inputAtt); Rule.setAttributes(inputs); for(int i=0;i<inputAtt;i++){ if(inputs[i].getType()==Attribute.NOMINAL){ Rule.setNumValue(Attributes.getInputAttribute(i).getNumNominalValues(),i); } else{ Rule.setNumValue(1,i); } } ruleset=new Rule[trainData.length]; //Initialization of random generator Randomize.setSeed(seed); //Initialization stuff ends here. So, we can start time-counting setInitialTime(); } //end-method /** * Reads configuration script, to extract the parameter's values. * * @param script Name of the configuration script * */ protected void readParameters (String script) { String file; String line; StringTokenizer fileLines, tokens; file = Fichero.leeFichero (script); fileLines = new StringTokenizer (file,"\n\r"); //Discard in/out files definition fileLines.nextToken(); fileLines.nextToken(); fileLines.nextToken(); //Getting the seed line = fileLines.nextToken(); tokens = new StringTokenizer (line, "="); tokens.nextToken(); seed = Long.parseLong(tokens.nextToken().substring(1)); }//end-method /** * Extract the rules from the training set. This is the main part of the * BNGE algorithm. */ public void getRules(){ int randomIndex[]=new int [trainData.length]; int pos,tmp; boolean canMerge,testing; int indexMerge; double distMerge,auxDist; Rule newRule; Rule newSet []; //random initialization of the ruleset for (int i=0; i<trainData.length; i++){ randomIndex[i] = i; } for (int i=0; i<trainData.length; i++) { pos = Randomize.Randint (0, trainData.length); tmp = randomIndex[i]; randomIndex[i] = randomIndex[pos]; randomIndex[pos] = tmp; } for(int i=0;i<trainData.length;i++){ ruleset[i]=new Rule(trainData[randomIndex[i]],trainOutput[randomIndex[i]]); } //merging process canMerge=true; while(canMerge){ canMerge=false; for(int i=0;i<ruleset.length&& !canMerge;i++){ //find their nearest hyperrectangle indexMerge=-1; distMerge=Double.MAX_VALUE; for(int j=i+1;j<ruleset.length;j++){ if(ruleset[i].getOutput()==ruleset[j].getOutput()){ auxDist=ruleset[i].distanceRule(ruleset[j]); if(distMerge>auxDist){ distMerge=auxDist; indexMerge=j; } } } //try to merge if(indexMerge>-1){ newRule=ruleset[i].clone(); newRule.merge(ruleset[indexMerge]); testing=true; for(int j=0;j<ruleset.length&&testing;j++){ if((j!=i)&&(j!=indexMerge)&&(newRule.getOutput()!=ruleset[j].getOutput())){ if(newRule.overlap(ruleset[j])){ testing=false; } } } if(testing){ ruleset[i]=newRule.clone(); newSet=new Rule[ruleset.length-1]; System.arraycopy(ruleset, 0, newSet, 0, indexMerge); System.arraycopy(ruleset, indexMerge+1, newSet, indexMerge, (ruleset.length-indexMerge-1)); ruleset=new Rule[newSet.length]; System.arraycopy(newSet, 0, ruleset, 0, newSet.length); canMerge=true; } } } }//end-while }//end-method /** * Classifies an instance using the ruleset * * @param instance Instance to classify * @return Class assigned to the instance */ protected int evaluate(double instance[]){ double minArea=Double.MAX_VALUE; double minDist=Double.MAX_VALUE; int selected=-1; for(int i=0;i<ruleset.length;i++){ if(ruleset[i].distance(instance)==minDist){ if(ruleset[i].getArea()<minArea){ minArea=ruleset[i].getArea(); selected=i; } } if(ruleset[i].distance(instance)<minDist){ minDist=ruleset[i].distance(instance); minArea=ruleset[i].getArea(); selected=i; } } selected=ruleset[selected].getOutput(); return selected; }//end-method /** * Writes the final ruleset obtained, in the ruleSetText variable. * * @return The number of rules of the final rule set */ protected int writeRules(){ String text=""; text+="\n"; for(int i=0;i<ruleset.length;i++){ text+="\n"; text+=ruleset[i]; } ruleSetText=text; return ruleset.length; }//end-method } //end-class