/***********************************************************************
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.Rule_Learning.UnoR;
import java.io.IOException;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Collections;
import keel.Dataset.*;
import java.util.*;
import org.core.Fichero;
/**
* <p>Title: Clase UnoRSD</p>
*
* <p>Description: Contiene los metodos principales del algoritmo UnoRsd</p>
*
* <p>Copyright: Copyright Rosa (c) 2007</p>
*
* <p>Company: Mi casa </p>
*
* @author Rosa Venzala
* @version 1.0
*/
public class UnoR {
private Dataset train ; //ficheroTrain);Dataset eval;
private Dataset test; //ficheroTest); }
private String ficheroSalida;
private String ficheroSalidaTr;
private String ficheroSalidaTst;
private String []clases=null;
private String []clasesTest=null;//para cuando no coinciden los indices de las clases
//como por ejemplo en abalone
private String []nombre_atributos=null;
private ConjReglas conjunto_reglas[];
private Selector s;
private Complejo regla;
private ConjDatos datosTrain,datosTest;
private EvaluaCalidadReglas evReg[]; // Para evaluar la calidad de las reglas
private int muestPorClaseEval[];
private int muestPorClaseTest[];
private long seed;
private int ganador; //identifica al atributo finalmente ganador
private int []tipos;//indica si el atributo de entrada es nominal(0) o numerico(1)
public UnoR(){
}
public UnoR(String ficheroTrain,String ficheroTest,
String fSalidaTr,
String fSalidaTst, String fsalida,long semilla,int SMALL){
ficheroSalida = fsalida;ficheroSalidaTr = fSalidaTr;
ficheroSalidaTst = fSalidaTst;
datosTrain = new ConjDatos();datosTest = new ConjDatos();
train=new Dataset();test=new Dataset();
s=new Selector(0,0,0.);
seed=semilla;
try {
train.leeConjunto(ficheroTrain, true);
test.leeConjunto(ficheroTest,false);
train.calculaMasComunes();//eval.calculaMasComunes();
test.calculaMasComunes();
datosTrain = creaConjunto(train);
datosTest = creaConjunto(test);
conjunto_reglas=new ConjReglas[train.getnentradas()];
tipos=new int [train.getnentradas()];
tipos=train.tiposVar();
clases=train.dameClases();
clasesTest=test.dameClases();
/*for (int j=0; j<train.getnclases();j++)
System.out.println(clases[j]);*/
double[][]lista;//almacenamos para cada atributo la lista ordenada de valores
lista=train.getListValues();
int []num_valores=new int [train.getnentradas()];
//getNumValues2 solo se puede llamar despues de getListValues();
num_valores=train.getNumValues2();
//en num_valores guardamos el numero de valores que tiene cada atributo
/*for (int j=0; j<train.getnentradas();j++){
System.out.println(num_valores[j]);
for (int k=0; k<num_valores[j];k++)System.out.print(lista[j][k]+" ");
System.out.println();
}*/
int [][][]matriz;
matriz=train.creaCount();
/*for (int i=0; i<train.getnclases();i++) {
for (int j=0; j<train.getnentradas();j++){
for (int k=0; k<num_valores[j];k++)System.out.print(matriz[i][j][k]+" ");
System.out.println();
}
System.out.println();
}*/
//ahora el siguiente paso es obtener la clase optima para cada atributo-valor
int [][]optima;
optima=train.getClaseOptima(matriz,seed);
/* for (int j=0; j<train.getnentradas();j++){
for (int k=0; k<num_valores[j];k++)System.out.print(optima[j][k]+" ");
System.out.println();
}*/
/*ahora el siguiente paso es DISCRETIZAR, clasificar los valores de cada
atributo en intervalos*/
int optimalClass;
nombre_atributos=train.dameNombres();
for (int i=0; i<train.getnentradas();i++){
conjunto_reglas[i]=new ConjReglas();
Interval I1=new Interval(SMALL,train.getndatos());
for (int j=0; j<num_valores[i];j++){
if(tipos[i]==0){//es nominal, no hay q hacer intervalos
regla=createRule(i,train.findNominalValue(i,lista[i][j]),lista[i][j],optima[i][j]);
conjunto_reglas[i].addRegla(regla);
}
else{
//tenems q obtener la clase optima provisional dl intervalo
optimalClass=I1.optimalClass(train.getnclases(),seed,false);
//todavia no hay mas de small valores,no hay clase optima
//o la clase de este nuevo valor coincide con la optima
if((I1.getNumValues()<=SMALL) || (optimalClass==-1)
||(optima[i][j]==optimalClass)){
I1.add(lista[i][j]);
I1.setClass(optima[i][j],I1.getNumValues()-1);
}
else{//si coincide cn la clase optima lo metemos,si no, pasa a otro nuevo intervalo
//System.out.println("El intervalo tiene "+I1.getNumValues());
//I1.print();
j--;//para q empiece con este valor que corto el intervalo
regla=createRule(i,I1,false);
//INCLUIMOS ESTA REGLA YA PARA EL CONJUNTO FINAL DE REGLAS
conjunto_reglas[i].addRegla(regla);
I1.clear();
}
}
}
if(tipos[i]==1){//solo numerico, si se han creado intervalos
//System.out.println(i+"El intervalo tiene ya fuera"+I1.getNumValues());
//I1.print();
//the rightmost interval (true)
regla=createRule(i,I1,true);
//regla.print(tipos[i]);
conjunto_reglas[i].addRegla(regla);
}
}
//INTERVALOS CREADOS!!!!
//POR CADA INTERVALO hemos CREAdo UNA REGLA
//EVALUAMOS LA CALIDAD DE LAS REGLAS
int [] clasesEval;
clasesEval = train.getC();
muestPorClaseEval = new int[train.getnclases()];
for (int j = 0; j < train.getnclases(); j++) {
muestPorClaseEval[j] = 0;
for (int i = 0; i < datosTrain.size(); i++) {
if (/*valorClases[j]*/j == clasesEval[i]) {
muestPorClaseEval[j]++;
}
}}
//TAMBIEN PARA TEST!! NO TIENEN POR QUE SER IGUALES!!!
clasesEval = test.getC();
muestPorClaseTest = new int[test.getnclases()];
for (int j = 0; j < test.getnclases(); j++) {
muestPorClaseTest[j] = 0;
for (int i = 0; i < datosTest.size(); i++) {
if (/*valorClases[j]*/j == clasesEval[i]) {
muestPorClaseTest[j]++;
}
}}
evReg=new EvaluaCalidadReglas[train.getnentradas()];
double []aciertos=new double[train.getnentradas()];
for (int i=0; i<train.getnentradas();i++){
conjunto_reglas[i].adjuntaNombreClases(clases);
conjunto_reglas[i].adjuntaNombreClase(nombre_atributos[train.getnentradas()]);
conjunto_reglas[i].print(tipos[i]);
evReg[i] = new EvaluaCalidadReglas(conjunto_reglas[i], datosTrain, datosTest,muestPorClaseEval, muestPorClaseTest,clases,clasesTest);
aciertos[i]=evReg[i].getAccuracyTrain();
}
//quedarnos con el maximo de aciertos y este sera el atributo final
//GENERAMOS LA SALIDA
ganador=train.getMaximo(aciertos,seed);
generaSalida(evReg[ganador],ganador);
}
catch (IOException e) {
System.err.println("There was a problem while trying to read the dataset files:");
System.err.println("-> " + e);
//System.exit(0);
}
}
/*Crea una regla para un atributo numerico dado un intervalo
*El consecuente de la regla es la clase optima del intervalo
*El antecedente son los valores del intervalo
*@param rightmost es true si es el ultimo intervalo para el atributo atr
*return la regla creada
*/
private Complejo createRule(int atr,Interval I1,boolean rightmost){
Complejo Regla;int op;
Selector s = new Selector(atr, 0,I1.getValues(),I1.getNumValues());
Regla=new Complejo(train.getnclases());
if(rightmost)op=I1.optimalClass(train.getnclases(),seed,true);
Regla.setClase(I1.getOptimalClass());
Regla.adjuntaNombreAtributos(nombre_atributos);
Regla.addSelector(s);
//Regla.print(tipos[atr]);//numerico o nominal
evaluarComplejo(Regla,datosTrain);
return Regla;
}
/*Crea una regla en el caso de q el atributo sea nominal*/
private Complejo createRule(int atr,String nombre,/*String*/double valor,int claseOptima){
Complejo Regla;
Selector s = new Selector(atr, 0,nombre,valor,true);
Regla=new Complejo(train.getnclases());
Regla.setClase(claseOptima);
Regla.adjuntaNombreAtributos(nombre_atributos);
Regla.addSelector(s);
//Regla.print(tipos[atr]);//numerico-1 o nominal-0
evaluarComplejo(Regla,datosTrain);
return Regla;
}
/** Evaluacion de los complejos sobre el conjunto de ejemplo para ver cuales se
* cubren de cada clase
* @param c Complejo a evaluar
* @param e Conjunto de datos
*/
private void evaluarComplejo(Complejo c, ConjDatos e) {
c.borraDistrib();
for (int i = 0; i < e.size(); i++) {
int cl = e.getDato(i).getClase();
if (c.cubre(e.getDato(i))) {
c.incrementaDistrib(cl);
}
}
c.calculaLaplaciano();
}
/**
* Calcula los datos estad�ticos necesarios y crea los ficheros KEEL de salida
*/
private void generaSalida(EvaluaCalidadReglas evReg,int atrib) {
Fichero f = new Fichero();
String cad = "";
String miSalida = new String("");
miSalida = train.copiaCabeceraTest();
//System.out.println("\n Estas son las reglas encontradas:");
//conjReglasFinal.print();
//clases=train.dameClases();
conjunto_reglas[atrib].adjuntaNombreClases(clases);
conjunto_reglas[atrib].adjuntaNombreClase(nombre_atributos[train.getnentradas()]);
cad = conjunto_reglas[atrib].printString(tipos[atrib]);
cad += "\n\n" + evReg.printString() + "\n\n Time (seconds); ";
f.escribeFichero(ficheroSalida, cad);
f.escribeFichero(ficheroSalidaTr,
miSalida + evReg.salida(datosTrain,true));
f.escribeFichero(ficheroSalidaTst,
miSalida + evReg.salida(datosTest,false));
}
/**
* Crea un conjunto de datos (atributos/clase) segun los obtenidos de un fichero de datos
* @param mis_datos Debe ser un conjunto de datos leido del fichero (mirar doc Dataset.java)
* @return El conjunto de datos ya creado, es decir, una lista enlazada de muestras (consultar ConjDatos.java y Muestra.java)
*/
private ConjDatos creaConjunto(Dataset mis_datos) {
ConjDatos datos = new ConjDatos(); //Creo un nuevo conjunto de datos
int tam = mis_datos.getnentradas(); //Pillo el nmero de atributos de entrada (suponemos una sola salida [clase])
double[] vars = new double[tam]; //Creamos el vector que guardar�los valores de los atributos (aun siendo enteros o enum)
double[][] X;
int[] C;
int clase = 0; //Variable que contendr�el valor para la clase
X = mis_datos.getX();
C = mis_datos.getC();
for (int i = 0; i < mis_datos.getndatos(); i++) {
//System.out.print("\n"+i+":");
for (int j = 0; (j < tam); j++) {
//System.out.print(" "+X[i][j]);
if (mis_datos.isMissing(i, j)) {
vars[j] = mis_datos.masComun(j);
} else { //CAMBIAR POR OTROS METODOS DE MANEJO DE VALORES PERDIDOS (15-NN).
vars[j] = X[i][j]; //Double.parseDouble(mis_datos.getDatosIndex(i, j)); //pillo el valor del atributo j para el ejemplo i
}
}
//if (!salir) {
clase = C[i]; //Integer.parseInt(mis_datos.getDatosIndex(i, tam));
Muestra m = new Muestra(vars, clase, tam); //Creo un nuevo dato del conjunto con sus variables, su clase y el num variables
m.setPosFile(i);
datos.addDato(m);
//}
}
return datos;
}
}