/***********************************************************************
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;
/**
* <p>T�ulo: Clase Dataset</p>
* <p>Descripci�: Contiene los metodos de lectura del fichero de train y test</p>
* <p>Copyright: Copyright Rosa (c) 2007</p>
* <p>Empresa: Mi Casa</p>
* @author Rosa Venzala
* @version 1.0
*/
import java.io.*;
import keel.Dataset.*;
import java.util.*;
//import java.util.Arrays;
import org.core.*;
public class Dataset {
private double[][] X = null;
private String [][]X2=null;//para los datos nominales
private boolean[][] missing = null;
private int[] C = null;
private String[] C2=null;//para las clases nominales
private double[] emaximo;
private double[] eminimo;
private int ndatos; // Number of examples
private int nvariables; // Numer of variables
private int nentradas; // Number of inputs
private int nclases; // Number of classes
final static boolean debug = false;
private InstanceSet IS;
private int[] comunes;
private int []num_valores;//numero de valores distintos para cada entrada
private double[][]sortedValuesList;//para cada entrada se tiene la lista de valores
//ordenados en orden ascendente y sin repeticiones
private String []auxiliar2=null;//vector tamaño numero real de clases en train que contiene el nombre de las clases en nominal
/**
* Devuelve los valores de los atributos de entrada
* @return double[][] Un array con los atributos de entrada
*/
public double[][] getX() {
return X;
}
public String[][]getX2(){
return X2;
}
/**
* Devuelve los valores de los atributos de entrada para una instancia determinada
*@param pos La posicion de la instancia en el conjunto de datos
* @return double[] Un array con los atributos de entrada para esa instancia
*/
public double []getX(int pos){
return X[pos];
}
public InstanceSet getInstanceSet(){
return IS;
}
/*Devuelve el valor nominal del valor double del atributo
*/
public String findNominalValue(int atr,double valor){
String dev="";
boolean parar=false;
for (int i=0;i<ndatos&&!parar;i++){
if(valor==X[i][atr]){dev=X2[i][atr];parar=true;}
}
return dev;
}
/*
*Comprueba si en el conjunto de instancias quedan aun instancias de una clase
* determinada
@param La clase de la que se busca si hay instancias
@return true si hay instancias, false en otro caso
*/
public boolean hayInstanciasDeClaseC(int whichClass)throws ArrayIndexOutOfBoundsException{
boolean resul=false;
int cadena;
Instance[] instanceSet;
if (whichClass <0 || whichClass >= nclases) {throw new ArrayIndexOutOfBoundsException("You are trying to access to "+whichClass+" class and there are only "+nclases+".");}
instanceSet=IS.getInstances();
//este bucle va a sustituir a la funcion antes definida en instance set
for(int i=0;i<IS.getNumInstances();i++){
cadena=instanceSet[i].getOutputNominalValuesInt(0);
if(cadena==whichClass){resul=true;
//System.out.println(i);
}
}
//resul=IS.hayInstanciasDeClaseC(whichClass);
return resul;
}
/*
Obtiene para cada atributo la lista ordenada de sus posibles valores sin repetir
*/
public double [][]getListValues(){
double [][]lista_valores=new double[nentradas] [ndatos];
for (int i=0;i<nentradas;i++){
double []vector=new double [ndatos];
for(int j=0;j<ndatos;j++){
vector[j]=X[j][i];
}
vector=elimina_repetidos(vector,i);
Arrays.sort(vector,0,num_valores[i]);
lista_valores[i]=vector;
}
sortedValuesList=lista_valores;
return lista_valores;
}
private double[] elimina_repetidos(double[]v,int atributo){
int contador=0;
boolean encontrado;
double[]aux=new double[v.length];
for(int i=0;i<v.length;i++){
encontrado=false;
for(int j=0;j<contador&&(!encontrado);j++){
if(aux[j]==v[i])encontrado=true;//el valor ya esta
}
if(!encontrado){aux[contador]=v[i];contador++;}
}
num_valores[atributo]=contador;
return aux;//v=aux;
}
/**
* Crea un 3-D array a partir del training set, almacenando para cada clase, cada atributo
* y cada valor el numero de ejemplos de clase C que tienen el valor V para el atributo A
* COUNT[C,V,A]
* @return int [][][] Una matriz con el numero de ejemplos
*/
public int [][][] creaCount(){
int [][][] Count=new int [nclases][nentradas] [ndatos];;
//para definir la matriz Count, nvalores podria ser en el peor caso
// el numero de instancias, es decir, no se repite ningun valor para algun atributo
//ndatos es IS.getNumInstances();
//obtener un array ordenado de los valores de un atributo sin repetirse
//esta seria la nueva funcion getNumValues, la de antes no sirve
//buscar el valor actual en este vector y devolver el indice
double valor_actual;String nominal_actual;int indice;
int []num_valores=new int [nentradas];
int []tipos=new int [nentradas];
num_valores=getNumValues();
for (int i=0; i<nclases;i++) {for (int j=0; j<nentradas;j++){
for (int k=0; k<ndatos;k++)Count[i][j][k]=0;
}}
for (int i=0; i<nclases;i++) {
for (int j=0; j<nentradas;j++){
tipos=tiposVar();
for (int k=0; k<ndatos;k++){
//System.out.println("clase "+C[k]);
if(C[k]==i){//esta instancia es de la clase actual i
valor_actual=X[k][j];nominal_actual=X2[k][j];
//System.out.println("valor actual es "+X[k][j]);
// System.out.println("valor actual NOMINAL es "+X2[k][j]);
//El atributo es nominal
if(tipos[j]==0)Count[i][j][(int)valor_actual]++;
//para los numericos es cuando tenemos que ordenar
else{
indice=buscar(sortedValuesList[j],valor_actual);
if(indice==-1)System.err.println("Error: el valor no se encontro en el vector");
Count[i][j][indice]++;
}// System.out.println("la clase atributo y valor "+i+" "+j+" "+(int)valor_actual+" lleva "+Count[i][j][(int)valor_actual]);
}
}}}//de los 3for
return Count;
}
/*
busca un elemento en un vector previamente ordenado en orden ascendente
Devuelve el indice donde se encuentra el valor
Devuelve -1 si no se encuentra el valor
*/
private int buscar(double[]v,double valor){
boolean encontrado=false;
int indice=-1;
for(int i=0;i<v.length&&(!encontrado);i++){
if(v[i]==valor){encontrado=true;indice=i;}
}
return indice;
}
/*
* Devuelve un vector con la clase optima para cada par atributo-valor
* @return int [][]el vector con las clases optimas
*/
public int [][]getClaseOptima(int [][][]Count,long seed){
int [][]optima=new int[nentradas] [ndatos];
int []vector=new int[nclases];
for (int i=0; i<nentradas;i++){
for (int j=0; j<num_valores[i];j++){
for(int k=0;k<nclases;k++)vector[k]=Count[k][i][j];
optima[i][j]=getMaximo(vector,seed);
}
}
return optima;
}
/*
* Devuelve el indice donde se encuentra el maximo de un array de enteros
* Si hay varios maximo devuelve uno aleatoriamente
* @return int el indice donde se encuentra el maximo valor
*/
private int getMaximo(int []num, long seed){
Randomize.setSeed(seed);
int max=num[0];int indice=0;
int []opciones=new int[nclases];int contador=0;
opciones[contador]=0;contador++;
for(int i=1;i<num.length;i++){
if(num[i]>max){max=num[i];indice=i;contador=0;opciones[contador]=i;contador++;}
else{if(num[i]==max){opciones[contador]=i;contador++;}}
}
if((contador-1)>0){//es que hay mas de una clase que es optima, la elegimos aleatoriamente
indice=Randomize.RandintClosed(0, contador);
indice=opciones[indice];
}
return indice;
}
/*
* Devuelve el indice donde se encuentra el maximo de un array de doubles
* Si hay varios maximo devuelve uno aleatoriamente
* @return int el indice donde se encuentra el maximo valor
*/
public int getMaximo(double []num, long seed){
Randomize.setSeed(seed);
double max=num[0];int indice=0;
int []opciones=new int[nentradas];int contador=0;
opciones[contador]=0;contador++;
for(int i=1;i<num.length;i++){
if(num[i]>max){max=num[i];indice=i;contador=0;opciones[contador]=i;contador++;}
else{if(num[i]==max){opciones[contador]=i;contador++;}}
}
if((contador-1) > 0){//es que hay mas de una clase que es optima, la elegimos aleatoriamente
indice=Randomize.RandintClosed(0, contador);
System.out.println("Elegimos "+indice);
indice=opciones[indice];
}
return indice;
}
/*
* Devuelve para cada atributo el numero de valores distintos que toma para el conjunto
* de datos
* @return int [] un array con el numero de valores distintos para cada atributo
*/
public int []getNumValues(){
int []num=new int [nentradas];
for(int i=0;i<nentradas;i++){
num[i]=0;
for (int j=1;j<ndatos;j++){
if((int)X[j][i]> num[i])num[i]=(int)X[j][i];
}
num[i]++;
}
return num;
}
/*
* Devuelve para cada atributo el numero de valores distintos que toma para el conjunto
* de datos
* @return int [] un array con el numero de valores distintos para cada atributo
*/
public int []getNumValues2(){
return num_valores;
}
/**
* Devuelve los valores para la salida (clase)
* @return int[] Un array con los valores de la clase
*/
public int[] getC() {
int[] retorno = new int[C.length];
for (int i = 0; i < C.length; i++) {
retorno[i] = C[i];
}
return retorno;
}
public String[] getC2() {
String[] retorno = new String[C2.length];
for (int i = 0; i < C2.length; i++) {
retorno[i] = C2[i];
}
return retorno;
}
/**
* Devuelve un array con los valores m�imos de los atributos de entrada
* @return double[] idem
*/
public double[] getemaximo() {
return emaximo;
}
/**
* Devuelve un array con los valores m�imos de los atributos de entrada
* @return double[] idem
*/
public double[] geteminimo() {
return eminimo;
}
/**
* Devuelve el nmero de datos
* @return int el nmero de ejemplos
*/
public int getndatos() {
return ndatos;
}
/**
* Devuelve el nmero de variables
* @return int El nmero de variables (incluyendo entrada y salida)
*/
public int getnvariables() {
return nvariables;
}
/**
* Devuelve el nmero de variables de entrada
* @return int El total de variables de entrada
*/
public int getnentradas() {
return nentradas;
}
/**
* Devuelve el nmero total de clases
* @return int el nmero de clases distintas
*/
public int getnclases() {
return nclases;
}
/**
* Comprueba si un atributo est�"perdido" o no
* @param i int Nmero de ejemplo
* @param j int Nmero de atributo
* @return boolean True si falta, False en otro caso
*/
public boolean isMissing(int i, int j) {
// True is the value is missing (0 in the table)
return missing[i][j];
}
/**
* Constructor. Crea un nuevo conjunto de instancias
*/
public Dataset() {
IS = new InstanceSet(); // Init a new set of instances
}
/**
* Lee el fichero de ejemplos (train o test)
* @param nfejemplos String Nombre del fichero de ejemplos
* @param train boolean True si se refiere al conjunto de entrenamiento. False si es test
* @throws IOException Un posible error de E/S
*/
public void leeConjunto(String nfejemplos, boolean train) throws IOException {
try {
// Load in memory a dataset that contains a classification problem
IS.readSet(nfejemplos, train);
ndatos = IS.getNumInstances();
nentradas = Attributes.getInputNumAttributes();
nvariables = nentradas + Attributes.getOutputNumAttributes();
/* System.out.println(ndatos);
System.out.println(nentradas);
System.out.println(nvariables);*/
// Check that there is only one output variable
if (Attributes.getOutputNumAttributes() > 1) {
System.out.println(
"This algorithm can not process MIMO datasets");
System.out.println(
"All outputs but the first one will be removed");
System.exit(1); //TERMINAR
}
boolean noOutputs = false;
if (Attributes.getOutputNumAttributes() < 1) {
System.out.println(
"This algorithm can not process datasets without outputs");
System.out.println("Zero-valued output generated");
noOutputs = true;
System.exit(1); //TERMINAR
}
// Initialice and fill our own tables
X = new double[ndatos][nentradas];
X2 = new String[ndatos][nentradas];
missing = new boolean[ndatos][nentradas];
C = new int[ndatos];
C2=new String[ndatos];
num_valores=new int[nentradas];
sortedValuesList=new double[nentradas] [ndatos];
// Maximum and minimum of inputs
emaximo = new double[nentradas];
eminimo = new double[nentradas];
// All values are casted into double/integer
nclases = 0;
int posiblesClases;
boolean clasesQueAparecen[];
Vector nose;
Attribute at = Attributes.getOutputAttribute(0);
posiblesClases=at.getNumNominalValues();
nose=at.getNominalValuesList();
int []auxiliar = new int[posiblesClases];
auxiliar2=new String[posiblesClases];
System.out.println("posibles "+posiblesClases);
clasesQueAparecen=new boolean[posiblesClases];
for(int j=0;j<posiblesClases;j++)clasesQueAparecen[j]=false;
for (int i = 0; i < ndatos; i++) {
Instance inst = IS.getInstance(i);
for (int j = 0; j < nentradas; j++) {
X2[i][j] = IS.getInputNominalValue(i, j); //inst.getInputRealValues(j);
X[i][j] = IS.getInputNumericValue(i, j);
// System.out.println(X[i][j]);
missing[i][j] = inst.getInputMissingValues(j);
if (X[i][j] > emaximo[j] || i == 0) {
emaximo[j] = X[i][j];
}
if (X[i][j] < eminimo[j] || i == 0) {
eminimo[j] = X[i][j];
}
}
if (noOutputs) {
C[i] = 0;
} else {
int num= (int)IS.getOutputNumericValue(i, 0);
//marcamos esta clase como aparecida
clasesQueAparecen[num/*C[i]*/]=true;
C[i] = (int)IS.getOutputNumericValue(i, 0);
C2[i] = IS.getOutputNominalValue(i, 0); //(int)inst.getOutputRealValues(i);
}
//System.out.println("valor leido=" + C[i]+" "+C2[i]);
/*if (C[i] > nclases) { //ESTO NO ES BUENA SOLUCION
nclases = C[i];
}*/
}
//del vector clasesAparecen solo nos quedamos con los valores true
int indiceaux=0;
for(int i=0;i<posiblesClases;i++){//System.out.println(clasesQueAparecen[i]);
if(clasesQueAparecen[i]==true){
auxiliar[indiceaux]=i;auxiliar2[indiceaux]=(String)nose.elementAt(i);
indiceaux++;
}
}
// nclases++;
nclases=indiceaux;
//auxiliar contiene el indice de la clase y auxiliar2 el valor en nominal
/* for(int i=0;i<nclases;i++){
System.out.println("holaaa" + auxiliar[i]+" "+auxiliar2[i]);}*/
System.out.println("Number of classes=" + nclases);
//IMPRIME TODOS LOS ATRIBUTOS Y TODAS LAS INSTANCIAS
// IS.print();
//AHORA C NECESITA LA NUEVA NUMERACION, SOLO LAS CLASES QUE APARECEN EN LAS
//INSTANCIAS, NO TODAS LAS POSIBLES EN @ATTRIBUTE, ORDENADAS
for(int i=0;i<nclases;i++){
for (int j = 0; j < ndatos; j++) {
if(auxiliar2[i].compareTo(IS.getOutputNominalValue(j, 0))==0) {
C[j]=i;}//System.out.println(C[j]+" ahora es "+i);}
}
}
// for (int j = 0; j < ndatos; j++)System.out.println("ahora leido=" + C[j]+" "+C2[j]);
} catch (Exception e) {
System.out.println("DBG: Exception in readSet");
e.printStackTrace();
}
}
/**
* Devuelve un String con la cabecera del fichero
* @return String Los datos de la cabecera del fichero (train)
*/
public String copiaCabeceraTest() {
// Header of the output file
String p = new String("");
p = "@relation " + Attributes.getRelationName() + "\n";
p += Attributes.getInputAttributesHeader();
p += Attributes.getOutputAttributesHeader();
p += Attributes.getInputHeader() + "\n";
p += Attributes.getOutputHeader() + "\n";
p += "@data\n";
return p;
}
/**
* Convierte todos los valores del conjunto de datos en el intervalo [0,1]
*/
public void normaliza() {
int atts = this.getnentradas();
double maximos[] = new double[atts];
for (int j = 0; j < atts; j++) {
maximos[j] = 1.0 / (emaximo[j] - eminimo[j]);
}
for (int i = 0; i < this.getndatos(); i++) {
for (int j = 0; j < atts; j++) {
if (isMissing(i, j)) {
; //no escojo este ejemplo
} else {
X[i][j] = (X[i][j] - eminimo[j]) * maximos[j];
}
}
}
}
/**
* Devuelve los tipos de cada entrada (NOMINAL[0] o NUMERICO[1])
* @return int[] Un vector que contiene 0 o 1 en funcion de si los atributos son nominales o numericos
*/
public int[] tiposVar() {
int[] tipos = new int[this.nentradas];
for (int i = 0; i < this.nentradas; i++) {
tipos[i] = 1;
if (Attributes.getInputAttribute(i).getType() == Attribute.NOMINAL) {
tipos[i] = 0;
}
}
return tipos;
}
/**
* Calcula los valores mas comunes para cada columna o atributo
*/
public void calculaMasComunes() {
comunes = new int[nentradas];
int[] aux = new int[ndatos];
for (int i = 0; i < nentradas; i++) {
for (int j = 0; j < ndatos; j++) {
if (this.isMissing(j, i)) {
aux[j] = -1;
} else {
aux[j] = (int) X[j][i];
}
}
Arrays.sort(aux);
int mascomun = aux[0];
int contador = 1, j;
for (j = 1; (aux[j] == mascomun) && (j < ndatos - 1); j++, contador++) {
;
}
int contador2 = 1;
int mascomun2 = aux[j];
if (j + 1 < ndatos) {
for (j = j + 1; j < ndatos; j++) {
if (aux[j] == mascomun2) {
contador2++;
} else {
mascomun2 = aux[j];
if (contador2 > contador) {
contador = contador2;
mascomun = mascomun2;
contador2 = 1;
}
}
}
}
comunes[i] = mascomun;
}
}
/**
* Devuelve el valor mas comn del atributo i-esimo
* @param i int Nmero de atributo
* @return int Valor mas comnun para esta variable
*/
public int masComun(int i) {
return comunes[i];
}
/**
* Devuelve el nombre de las variables del problema
* @return String[] Un Array con los nombres de las variables del problema
*/
public String[] dameNombres() {
String[] salida = new String[nvariables];
for (int i = 0; i < nentradas; i++) {
salida[i] = Attributes.getInputAttribute(i).getName();
}
salida[nentradas] = Attributes.getOutputAttribute(0).getName();
return salida;
}
/**
* Devuelve el valor de las clases
* @return String[] Un array con el valor para las distintas salidas (clases)
*/
public String[] dameClases(){
String [] salida = new String[nclases];
Attribute at = Attributes.getOutputAttribute(0);
System.out.println(+at.getNumNominalValues());
if (at.getType() == at.NOMINAL){
for (int i = 0; i < nclases; i++) {
salida[i] = auxiliar2[i];/*YA NO ES ESTO at.getNominalValue(i);*/
}
}
else{
salida = null; //luego guardar�el valor de las clases num�icas
}
return salida;
}
/**
* Comprueba si en la base de datos hay alguna entrada de tipo real o cont�ua
* @return boolean True si existe alguna entrada continua. False en caso contrario
*/
public boolean hayAtributosContinuos(){
return Attributes.hasRealAttributes();
}
}