/*********************************************************************** 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: Clase Regla</p> * * <p>Description: Se encarga de manejar los objeto Regla, que contienes antecedentes, consecuentes y lista </p> * <p>de atribtutos invalidos</p> * * <p>Company: KEEL</p> * * @author Ismael Duque García * @version 1.0 */ public class Regla { private LinkedList<Atributo_valor> antecedentes = new LinkedList <Atributo_valor> (); private String consecuente; //la consistencia se genera en la funicon getScore() private boolean consistencia; //Cada posicion de la lista representa un atributo, y cada valor de su //lista asociada representa el valor invalido de este atributo para la regla private LinkedList<LinkedList<Double>> valoresinvalidos = new LinkedList <LinkedList<Double>> (); /** * Constructor de Regla * @param c String consecuente de la reglas * @param numAtributos int numero de atributos que hay en el dataset */ public Regla(String c,int numAtributos){ antecedentes = new LinkedList <Atributo_valor> (); consecuente = c; consistencia = false; for (int i=0;i<numAtributos;i++){//para asegurar que tiene un tamaño distinto de 0 valoresinvalidos.add(new LinkedList<Double>()); } } /** * Contructor copia de Regla * @param r Regla regla desde la que se copia */ public Regla(Regla r){ antecedentes = (LinkedList) r.getAntecedente().clone(); consecuente = r.getConsecuente(); consistencia = r.getConsistencia(); valoresinvalidos = (LinkedList) r.getValoresInvalidos().clone(); } /** * Devuelve la lista de antecedentes de la regla. * @return LinkedList<Atributo_valor> lista de antecedentes */ public LinkedList<Atributo_valor> getAntecedente(){ return antecedentes;} /** * Devuelve la lista de valores invalidos de la regla * @return LinkedList<LinkedList<Double>> lista de valores invalidos */ public LinkedList<LinkedList<Double>> getValoresInvalidos(){ return valoresinvalidos;} /** * Devuelve el consecuente de la regla * @return String consecuente */ public String getConsecuente(){ return consecuente;} /** * Devuelve el tamaño de la lista de antecedentes * @return int tamaño de la lista de antecedentes */ public int getSizeAntecedentes(){ return antecedentes.size();} /** * Devuelve la consistencia de la regla * @return boolean consistencia de la regla */ public boolean getConsistencia() { return consistencia; } /** * Devuelve verdadero o falso dependiendo de si un atributo y su valor * están en la lista de valores invalidos * @param atributo Integer Entero que representa el atributo * @param valor Double Doble que representa el valor del atributo * @return boolean Si la condicion es verdadera o falsa */ public boolean contenidoValoreInval(Integer atributo,Double valor){ return valoresinvalidos.get(atributo).contains((Double) valor); } /** * Devuelve el Atributo_valor deseado de la lista de antecedentes * @return Atributo_valor */ public Atributo_valor getAV(int i){ return antecedentes.get(i); } /** * Devuelve el último Atributo_valor añadido de la lista de antecedentes * @return Atributo_valor */ public Atributo_valor getLastAV(){ return antecedentes.getLast(); } /** * Añade un Atributo_valor a la lista de antecedentes * @param av Atributo_valor Objeto a añadir a la lista */ public void addAntecedente(Atributo_valor av){ antecedentes.add(av); } /** * Añade un Atributo_valor a la lista de valores invalidos * @param i Integer Atributo a añadir a la lista * @param vinv Double Valor del atributo a añadir */ public void addValoresInv(Integer i,Double vinv){ //si no esta ya contenido if(!valoresinvalidos.get(i).contains(vinv)) valoresinvalidos.get(i).add(vinv); } /** * Elimina un Atributo_valor a la lista de valores invalidos * @param i Integer Atributo a añadir a la lista * @param vinv Double Valor del atributo a añadir */ public void removeValorInv(Integer i,Double vinv){ //si no esta ya contenido if(!valoresinvalidos.get(i).contains(vinv)) valoresinvalidos.get(i).remove(vinv); } /** * Compara dos reglas * @param rule Regla regla con la que se compara * @return boolea Verdadero si es igual, Falso si es diferente */ public boolean equals(Regla rule){ boolean igual = true; //si tiene el mismo tamaño en los antecedentes if (this.antecedentes.size() == rule.getAntecedente().size()){ for(int i=0; i<this.antecedentes.size();i++){ if(!rule.getAntecedente().get(i).equals(antecedentes.get(i))) igual = false; } if (!igual) return false; }else{ return false; } //ahora se compara que tienen el mismo consecuente if (this.consecuente.equals(rule.getConsecuente())) return true; else return false; } /** * Devuelve el padre de la regla, su antecesor de esta * @return Regla La regla sin el ultimo valor añadido */ public Regla parentRule(){ //generamos la nueva regla, padre de la actual Regla parent = new Regla(this); //se elimina el ultimo atributo añadido Atributo_valor aux = parent.antecedentes.removeLast(); //se elimina de la lista de valores invalidos si estuviera parent.removeValorInv(aux.getAtributo(),aux.getValor()); return parent; } /** * Muestra por pantalla la regla actual */ public void mostrarRegla(){ Attribute a[] = Attributes.getInputAttributes(); Attribute s[] = Attributes.getOutputAttributes(); System.out.print("Regla: "); for (int i=0; i<this.antecedentes.size(); i++){ Atributo_valor av = antecedentes.get(i); System.out.print("("+a[av.getAtributo()].getName()+"," + a[av.getAtributo()].getNominalValue(av.getValor().intValue()) +")"); if (i<this.antecedentes.size()-1) System.out.print(" & "); } System.out.println(" -> ("+ s[0].getName() +","+this.consecuente+")"); System.out.println("------------------------------------"); } /** * Calcula y devuelve la puntuacion de una regla, mediante la m-probability-estimate * @param instances Instances Objeto que contiene todas la filas del dataset de entrenamiento * @return Double Valor de la m-probability-estimate de la regla */ public Double getScore(Instances instances){ Integer casos_positivos=0; Integer casos_negativos=0; Integer k = instances.getnClass(); Integer num_mismo_valor_salida=0; //si es una regla con el cuerpo vacio, se devuelve 0 if (!this.getAntecedente().isEmpty()){ for(int i=0;i<instances.getnData();i++){ //Para cada fila LinkedList<Double> fila = instances.getExample(i); //cogemos la fila String valor_salida = instances.getOutputAsString(i);//cogemos el valor de salida de la fila boolean filacubierta=true; for(int j=0; j<antecedentes.size();j++){//para cada para atributo_valor de la regla Integer atributo = getAV(j).getAtributo(); Double valor = getAV(j).getValor(); //compara el valor del atributo de la regla con el valor del atributo de la fila actual if(!(valor.equals(fila.get(atributo)))){ filacubierta=false;//si en algun atributo es diferente el valor } } //si es de la clase objetivo, el valor de salida de la regla if (this.getConsecuente().equals(valor_salida)){ num_mismo_valor_salida++; //almacena P, que se utiliza en la P0 = P/N if(filacubierta) casos_positivos++; }else if(filacubierta) casos_negativos++;} }else{ for(int i=0;i<instances.getnData();i++){ //Para cada fila String valor_salida = instances.getOutputAsString(i); if (this.getConsecuente().equals(valor_salida)) num_mismo_valor_salida++; //almacena P, que se utiliza en la P0 = P/N } } //se aprovecha el calculo para calcular la consistencia de la regla if(casos_negativos == 0) this.consistencia=true; //Po = P/N double p = (num_mismo_valor_salida.doubleValue()/instances.getnData()); //m-probability-estimate (m = n_positivos + k * Po/n_pos_neg + k Double salida1 = (casos_positivos.doubleValue() + (k * p)); Double salida2 = ((casos_positivos.doubleValue()+casos_negativos.doubleValue())+k.doubleValue()); Double salida = salida1/salida2; return salida; } }