/***********************************************************************
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/
**********************************************************************/
/*
* Created on 30-abr-2005
*
*/
package keel.Algorithms.Genetic_Rule_Learning.Hider;
import java.util.Vector;
/**
* @author Sebas
*/
public class Codificacion {
/**
* Data structure for codes
*/
private Vector baseCodificada;
/**
* Cuts to encode-decode
*/
private static Vector cortesCod;
/**
* Empty constructor
*/
public Codificacion() {
this.baseCodificada = new Vector();
}
/**
* Constructor with a 'Vector' parameter
* @param cortes
*/
public Codificacion(Vector cortes) {
cortesCod = cortes;
this.baseCodificada = new Vector();
}
/**
*
* @return the baseCodificada
*/
public Vector getBaseCodificada() {
return this.baseCodificada;
}
/**
* @param codigos The baseCodificada to set.
*/
public void setBaseCodificada(Vector codigos) {
this.baseCodificada = codigos;
}
/**
* Encodes the elements
* @param bd
*/
public void codificaBase(BaseDatos bd) {
Vector cortesAtributo = null;
int k = 0, p = 0;
Vector codigosEjemplo = null;
//Look through the elements
for (int i = 0; i < bd.getNumEjemplos(); i++) { //i => elements
codigosEjemplo = new Vector();
//Look through the attributes of each element
for (int j = 0; j < bd.getNumAtributos(); j++) { //j => attributes
Long codigo = null;
if (cortesCod.get(j) instanceof Integer) { //Discrete
if (j == bd.getClase()) { //Is the output attribute
p = ((Integer) ((Vector) bd.getBase().get(i)).get(j)).
intValue();
//If output attribute is 'integer' is necessary to adjust the value
//to count from the initial value of range
if (((String) bd.getTipos().get(j)).equals("integer")) {
int valorInicial = ((Integer) bd.getInicial().get(j)).
intValue();
p -= valorInicial;
}
codigo = new Long(p);
} else { //Is an input attribute
//Position
p = ((Integer) ((Vector) bd.getBase().get(i)).get(j)).
intValue();
//Values' range
k = ((Integer) cortesCod.get(j)).intValue(); //For discrete attributes, the cuts' Vector contains its range
//If it is an 'integer' attribute is necessary to adjust the value
//to count from the initial value of range
if (((String) bd.getTipos().get(j)).equals("integer")) {
int valorInicial = ((Integer) bd.getInicial().get(j)).
intValue();
p -= valorInicial;
}
//If it's a 'enumerado' attribute is not necessary to adjust because its initial value will be always zero
codigo = new Long((long) Math.pow(2, k - p - 1));
//System.err.println("K = "+k+", p = "+p+" codigo --> "+codigo+"...");
}
} else { //If it's a continuous attribute ('real')
//Take cuts from current attribute
cortesAtributo = (Vector) cortesCod.get(j);
double valor = ((Double) ((Vector) bd.getBase().get(i)).get(
j)).doubleValue();
k = cortesAtributo.size();
int f;
int c;
//Search for the current value's cuts and get its row and column numbers
//that numbers have to be the same because it's a minimum interval
f = c = busca(cortesAtributo, valor);
int n = f * (k - 1) + c + 1; //(k-1) is the number of rows and columns in the codification table
codigo = new Long(n);
//System.err.println("codigo -> "+codigo);
}
codigosEjemplo.add(codigo);
} //for(...) attributes
baseCodificada.add(codigosEjemplo);
} //for(...) elements
//System.exit(0);
}
/**
* Binary search
* @param cortes
* @param valor
* @return row/column number
*/
private int busca(Vector cortes, double valor) {
int ini = 0, fin = cortes.size(), med = -1;
boolean enc = false;
double minActual, maxActual;
int fc = -1;
//If 'valor' is lower than minimum value of range => return the minimum value of range
if (valor < ((Corte) cortes.get(0)).getCorte()) {
fc = 0;
}
//If 'valor' is greater than maximum value of range => return the maximum value of range
else if (valor > ((Corte) cortes.get(fin - 1)).getCorte()) {
fc = fin - 1;
}
//If 'valor' is between minimum and maximum values of range => search for it within range
else {
while ((fin >= ini) && !enc) {
med = (int) Math.floor((ini + fin) / 2);
//Take value of current attribute
//Current position 'med' is lower limit of interval
minActual = ((Corte) cortes.get(med)).getCorte();
//(med+1) mustn't be greater than vector size
if (med < cortes.size() - 1) {
maxActual = ((Corte) cortes.get(med + 1)).getCorte();
} else { //That case means that the searched interval is found, it is the last one
enc = true;
fc = cortes.size() - 2;
break;
}
if (valor >= minActual && valor <= maxActual) {
enc = true;
//If current value is upper limit of the interval, then it belongs to the next interval
//except it's the last interval
if (valor == maxActual && med < (fin - 2)) {
med++;
}
fc = med;
} else {
if (valor < minActual) {
fin = med - 1;
} else if (valor > maxActual) {
ini = med + 1;
}
}
}
}
return fc;
}
/**
* Encodes a value from its row and column numbers
* @param f
* @param c
* @param k
* @return code
*/
public static int codifica(int f, int c, int k) {
return (f * (k - 1) + c + 1);
}
/*
public static void descodifica(int n, Vector cortes, double fila, double columna)
{
int k=cortes.size();
int f=(n-1)/(k-1);
int c=(n-1)%(k-1);
fila=((Corte)cortes.get(f)).getCorte();
columna=((Corte)cortes.get(c+1)).getCorte();
}
*/
/**
* Decode row number
* @param n
* @param k
* @return row number
*/
public static int descodificaF(int n, int k) {
return (n - 1) / (k - 1);
}
/**
* Decode column number
* @param n
* @param k
* @return column number
*/
public static int descodificaC(int n, int k) {
return (n - 1) % (k - 1);
}
/**
* Decode discrete attributes
* @param n
* @param k
* @param inicio
* @return original value
*/
public static int[] descodificaD(int n, int k, int inicio) {
int[] exps = descompone(n, k);
Vector sal = new Vector();
int i = 0;
while (i < exps.length) {
if (exps[i] >= 0) {
sal.add(new Integer((k - exps[i] - 1) + inicio));
}
i++;
}
int[] res = new int[sal.size()];
for (i = 0; i < sal.size(); i++) {
res[i] = ((Integer) sal.get(i)).intValue();
}
return res;
}
/**
* If any bit is '0', its exponent will be '-1'
* @param n
* @param k
* @return array of exponents
*/
public static int[] descompone(int n, int k) {
int[] exponentes = new int[k];
for (int i = k - 1; i >= 0; i--) {
int aux = (int) Math.pow(2, i);
if ((aux & n) != 0) {
exponentes[k - i - 1] = i;
} else {
exponentes[k - i - 1] = -1;
}
}
return exponentes;
}
/*
private static boolean esPotenciaDe2(int n, Entero exp)
{
boolean es=true;
int cont=0;
if(n > 0)
{
while(n > 1 && es)
{
if(n % 2 == 0)
{
n/=2;
cont++;
}
else
{
es=false;
cont=-1;
}
}
}
else
{
cont=-1;
//dejamos exp=-1 para saber q es (2^algo)+0
}
exp.setValor(cont);
return es;
}
*/
/**
* @return Returns the cortesCod.
*/
public static Vector getCortesCod() {
return cortesCod;
}
/**
* @param cortesCod The cortesCod to set.
*/
public static void setCortesCod(Vector cortesCod) {
Codificacion.cortesCod = cortesCod;
/*System.err.println("Tam -> "+cortesCod.size());
for (int i = 0; i < cortesCod.size(); i++){
System.err.println("Puntos de corte para el atributo "+(i+1));
for (int j = 0; j < ((Vector)cortesCod.get(i)).size(); j++){
System.err.print((Corte) ((Vector) cortesCod.get(i)).get(j) + ",");
}
}
System.exit(0);*/
}
}