/*********************************************************************** 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/ **********************************************************************/ /* * To change this template, choose Tools | Templates * and open the template in the editor. */ package keel.Algorithms.Rule_Learning.SRI; import java.util.*; import keel.Dataset.Attribute; import keel.Dataset.Attributes; /** * <p>Title: Induce One Rule</p> * * <p>Description: Tiene como objetivo encontrar la mejor regla para un ejemplo del dataset dado</p> * * <p>Company: KEEL</p> * * @author Ismael Duque García * @version 1.0 */ public class InduceOneRule { /** * Devuelve una la mejor regla generada en cada llamada a esta funcion * @param instances Instances Tabla con los datos de entrenamiento * @param clases int Valor de salida a analizar, posicion de la lista de valores de salida * @param w int, valor definido manualmente para tener en cuenta en la reduccion de reglas * @return Regla mejor regla generada */ public static Regla induce_One_Rule(Instances instances,int clases , int w, int min_positives, int min_negatives){ Attribute a[] = Attributes.getInputAttributes(); Attribute s[] = Attributes.getOutputAttributes(); LinkedList<Regla> partial_rules = new LinkedList <Regla> (); LinkedList<Regla> new_partial_rules = new LinkedList <Regla>(); Regla best_rule = new Regla(s[0].getNominalValue(clases),instances.getnInputs()); partial_rules.add(new Regla(best_rule));//Se añade la mjor regla a partial_rules while(!partial_rules.isEmpty()){ //Recorre todas las reglas contenidas en partial_rules for(int i=0; i<partial_rules.size();i++){ Regla rule =partial_rules.get(i); //Devuelve la lista de atributos que no están contenidos en la regla actual LinkedList<Integer> atributos_no_contenidos = getListAttribNotRule(rule, instances); for(int j=0; j<atributos_no_contenidos.size();j++){ //Devuelve el valor del atributo del ejemplo analizado for (int k=0; k < a[atributos_no_contenidos.get(j)].getNumNominalValues();k++){ Double valor = new Integer(k).doubleValue(); //Si es verdad que el valor no pertenece a los valores invalidos que no puedo tomar el atributo if (!rule.contenidoValoreInval(atributos_no_contenidos.get(j),valor)){ Atributo_valor av_aux = new Atributo_valor(atributos_no_contenidos.get(j),valor); Regla new_rule= new Regla(rule);//copia la regla que estamos viendo new_rule.addAntecedente(av_aux);//añade el atributo valor //actualiza las instancias cubiertas de la nueva regla //new_rule.coveredInstances(rule.getIntances()); //si la comparacion es verdadera, la regla generada pasa a ser la mejor regla if (new_rule.getScore(instances)>best_rule.getScore(instances)){ best_rule = new Regla(new_rule); } if ((coveredPositive(new_rule,instances)<= min_positives) || (Math.abs((coveredNegative(rule,instances))-(coveredNegative(new_rule,instances)))<= min_negatives) || new_rule.getConsistencia()) { //si se cumple alguna de las condiciones anteriores, se añada como valor invalido a rule rule.addValoresInv(atributos_no_contenidos.get(j), valor); }else{ //si no se cumple alguna de las condicines, se añada la nueva regla a new_partial_rules new_partial_rules.add(new Regla(new_rule)); } } } } } partial_rules.clear();//se borran las reglas de partial_rules for(int i=0; i<new_partial_rules.size();i++){ //si el valor de la regla de new_partial_rule es menor o igual que el de la mejor regla if (new_partial_rules.get(i).getScore(instances)<= best_rule.getScore(instances)){ //se toma el ultimo valor de la regla Atributo_valor aux_av = new_partial_rules.get(i).getLastAV(); //a la regla antecesora a la actual evaluda se le añade el atributo valor invalido new_partial_rules.get(i).parentRule().addValoresInv(aux_av.getAtributo(), aux_av.getValor()); //borrar la regla de new_partial_rules new_partial_rules.remove(i); } } for(int i=0; i<new_partial_rules.size();i++){//para cada regla contenida en new_partial_rules LinkedList<LinkedList<Double>> atrib_invalidos = new_partial_rules.get(i).parentRule().getValoresInvalidos(); for(int j=0; j<atrib_invalidos.size(); j++){//para cada atributo for(int k=0; k<atrib_invalidos.get(j).size();k++){//para cada valor del atributo //se añaden a la regla de new_partial_rules todos los atibutos invalidos de su antecesor new_partial_rules.get(i).addValoresInv(j,atrib_invalidos.get(j).get(k)); } } } if (w>1){ //se eliminan la reglas repetidas new_partial_rules = quitarRepetidas(new_partial_rules); //se añaden las w mejores reglas partial_rules = bestWRules(new_partial_rules,w,instances); //se limpia la lista new_partial_rules new_partial_rules.clear(); } } return best_rule; }; /** * Devuelve una lista de los atributos no contenidos en la regla * @param rule Regla regla sobre la que vamos a obtner los atributos no contenidos en esta * @param intances Instances Conjunto de datos que nos facilita todos los atributo que existen * @return LinkedList<Integer> Atributos no contenidos en la regla */ private static LinkedList<Integer> getListAttribNotRule(Regla rule, Instances instances){ LinkedList<Integer> list_atributos = new LinkedList<Integer>(); //en list_atributos, cada posicion de la lista contiene el valor entero de un atributo for(int i=0; i<instances.getnInputs();i++){list_atributos.add(i);} //para todos los antecedentes de la regla, elimina de la list_atributos for(int i=0; i<rule.getAntecedente().size();i++){ //utiliza remove(Object), para eliminar el atributo de la list_atributos list_atributos.remove((Integer) rule.getAntecedente().get(i).getAtributo()); } //devuelve la lista de atributos no contenidos en la regla return list_atributos; } /** * Devuelve el numero de casos positivos cubiertos por la regla * Se consideran positivos aquellos casos o filas, cuyos atributos son cubiertos * por los antecedentes de la regla y ademas el consecuente es el mismo * @param rule Regla regla sobre la que vamos a obtener los antecedentes y cosecuente * @param intances Instances Conjunto de datos a analizar * @return Integer Numero de casos cubiertos positivos */ private static Integer coveredPositive(Regla rule, Instances instances){ Integer casos_positivos=0; LinkedList<Double> fila; String consecuente=""; if (rule.getAntecedente().size()>0){ for(int i=0;i<instances.getnData();i++){ //Para cada fila fila = instances.getExample(i); //cogemos la fila consecuente = instances.getOutputAsString(i); if (rule.getConsecuente().equals(consecuente)){ boolean filacubierta=true; for(int j=0; j<rule.getSizeAntecedentes();j++){ Integer atributo = rule.getAV(j).getAtributo(); Double valor = rule.getAV(j).getValor(); if(!(valor.equals(fila.get(atributo) ))){ filacubierta=false; } } if(filacubierta) casos_positivos++; } } } return casos_positivos; } /** * Devuelve el numero de casos negativos cubiertos por la regla * Se consideran negativos aquellos casos o filas, cuyos atributos son cubiertos * por los antecedentes de la regla, pero el consecuente es distinto * @param rule Regla regla sobre la que vamos a obtener los antecedentes y cosecuente * @param intances Instances Conjunto de datos a analizar * @return Integer Numero de casos cubiertos negativos */ private static Integer coveredNegative(Regla rule, Instances instances){ Integer casos_negativos=0; LinkedList<Double> fila; String consecuente=""; if (rule.getAntecedente().size()>0){ for(int i=0;i<instances.getnData();i++){ //Para cada fila fila = instances.getExample(i); //cogemos la fila consecuente = instances.getOutputAsString(i); if (!rule.getConsecuente().equals(consecuente)){ boolean filacubierta=true; for(int j=0; j<rule.getSizeAntecedentes();j++){ Integer atributo = rule.getAV(j).getAtributo(); Double valor = rule.getAV(j).getValor(); if(!(valor.equals(fila.get(atributo)) )){ filacubierta=false; } } if(filacubierta) casos_negativos++; } } } return casos_negativos; } /** * Elimina las reglas repetidas del conjunto de reglas suministrado * @param reglas LinkedList<Regla> Conjunto de reglas a dejar sin repetidos * @return LinkeList<Reglas> Conjunto de reglas sin repeticiones */ private static LinkedList<Regla> quitarRepetidas(LinkedList<Regla> reglas){ LinkedList <Regla> reglas_aux = new LinkedList <Regla>();//lista auxiliar boolean repetida = false;//controla si esta repetida o no for(int tam=0; tam<reglas.size();tam++){//para todas la reglas de reglas for(int i=0; i<reglas_aux.size();i++){//comprobar con las reglas de la lista auxiliar if(reglas.get(tam).equals(reglas_aux.get(i))) repetida = true;//si aparece en la lista auxiliar, esta repetida } //si no esta repetida if(!repetida) reglas_aux.add(reglas.get(tam)); repetida = false; //se restablece el boolean } return reglas_aux;//devuelve la lista auxiliar } /** * Seleciona de un conjunto de reglas, las w mejores reglas segun su puntuacion * @param reglas LinkedList<Regla> Conjunto de reglas * @param w int Numero de reglas a elegir * @return LinkeList<Reglas> Conjunto de las w mejores reglas */ private static LinkedList<Regla> bestWRules(LinkedList<Regla> new_partial_rules, int w,Instances instances) { if (new_partial_rules.size()<=w) return (LinkedList) new_partial_rules.clone(); else{ LinkedList<Regla> aux_reglas = new LinkedList <Regla>(); //para el numero de w best rules for(int i=0; i<w; i++){ Double mayor=-1.0; int posicion_mayor=-1;//se inicializa el mayor y la posicion //recorre el vector buscando el mejor valor de las reglas que quedan for(int tam_reglas=0; tam_reglas<new_partial_rules.size(); tam_reglas++){ Double actual = new_partial_rules.get(tam_reglas).getScore(instances); if(actual >= mayor){ //se va quedando con el mejor valor mayor = actual; posicion_mayor=tam_reglas; } } //añade el mejor valor encontrado a la lista auxiliar y lo borra de la original aux_reglas.add(new_partial_rules.remove(posicion_mayor)); } return (LinkedList) aux_reglas.clone(); } } }