/***********************************************************************
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 01-may-2005
*/
package keel.Algorithms.Genetic_Rule_Learning.Hider;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.Vector;
import org.core.*;
/**
* @author Sebas
*
*/
public class Evolucion {
private Vector bc;
private Vector sumaBondades = null;
private double sumaFi = 0;
private Vector poblacion;
private double probMutacion = 0.5; //[0-1]
private double probMutExtremo = 0.2; //[0-1]
private double cep = 0;
private Vector erroresClase;
private String funcionEvaluacionXmlFileName = null;
/**
* Constructor
* @param basec
* @param probMut
*/
public Evolucion(Vector basec, double probMut, String filename) {
bc = (Vector) basec.clone();
poblacion = new Vector();
erroresClase = new Vector();
probMutacion = probMut;
funcionEvaluacionXmlFileName = filename;
}
//Limits
/**
* Left limit
* @param n
* @param k
* @return The left limit
*/
public static int liz(int n, int k) {
int f = Codificacion.descodificaF(n, k);
return k * f + 1;
}
/**
* Right limit
* @param n
* @param k
* @return The right limit
*/
public static int lde(int n, int k) {
int f = Codificacion.descodificaF(n, k);
return (k - 1) * (f + 1);
}
/**
* Upper limit
* @param n
* @param k
* @return The up limit
*/
public static int lsu(int n, int k) {
return Codificacion.descodificaC(n, k) + 1;
}
/**
* Lower limit
* @param n
* @param k
* @return The down limit
*/
public static int lin(int n, int k) {
int c = Codificacion.descodificaC(n, k);
return k * c + 1;
}
//Movements
/**
* Left
* @param n
* @param k
* @return The number at the left
*/
public static int iz(int n, int k) {
return Math.max(liz(n, k), n - 1);
}
/**
* Right
* @param n
* @param k
* @return The number at the right
*/
public static int de(int n, int k) {
return Math.min(lde(n, k), n + 1);
}
/**
* Up
* @param n
* @param k
* @return The number upper
*/
public static int su(int n, int k) {
return Math.max(lsu(n, k), n - k + 1);
}
/**
* Down
* @param n
* @param k
* @return The number below
*/
public static int in(int n, int k) {
return Math.min(lin(n, k), n + k - 1);
}
//m order movements
/**
* Left
* @param n
* @param k
* @param m
* @return The number 'm' positions at the left
*/
public static int iz(int n, int k, int m) {
return Math.max(liz(n, k), n - m);
}
/**
* Right
* @param n
* @param k
* @param m
* @return The number 'm' positions at the right
*/
public static int de(int n, int k, int m) {
return Math.min(lde(n, k), n + m);
}
/**
* Up
* @param n
* @param k
* @param m
* @return The number 'm' positions upper
*/
public static int su(int n, int k, int m) {
return Math.max(lsu(n, k), n - m * k + m);
}
/**
* Down
* @param n
* @param k
* @param m
* @return The number below 'm' positions
*/
public static int in(int n, int k, int m) {
return Math.min(lin(n, k), n + m * k - m);
}
/**
* @param padre
* @param madre
* @param cortes
* @return Crossed children
*/
public static Vector[] cruza(Vector padre, Vector madre, Vector cortes) {
Vector[] hijos = new Vector[2];
double aleatorio = Randomize.RandClosed(); //Math.random();
if (aleatorio < 0.5) {
hijos[0] = (Vector) padre.clone();
} else {
hijos[0] = (Vector) madre.clone();
}
aleatorio = Randomize.RandClosed(); //Math.random();
if (aleatorio < 0.5) {
hijos[1] = (Vector) padre.clone();
} else {
hijos[1] = (Vector) madre.clone();
}
//Cross every gen
for (int i = 0; i < cortes.size() - 1; i++) {
int k = 0;
int[] genHijo = new int[2];
//System.err.println("Cruzando en el corte "+(i+1)+"-esimo!");
if (cortes.get(i) instanceof Vector) { //Continuous
k = ((Vector) cortes.get(i)).size();
//System.err.println("aki llega?? [continuo]");
genHijo = cruza(((Long) padre.get(i)).intValue(),
((Long) madre.get(i)).intValue(), k);
} else { //Discrete
//k = ((Integer) cortes.get(i)).intValue();
//System.err.println("aki llega?? [discreto] ");
Vector aux = cruza(((Long) padre.get(i)).intValue(),
((Long) madre.get(i)).intValue(), cortes, i);
//Take first two ones
genHijo[0] = ((Long) aux.get(0)).intValue();
if (aux.size() > 1) {
genHijo[1] = ((Long) aux.get(1)).intValue();
}
}
if (genHijo[1] == 0) {
hijos[1] = null;
} else if (hijos[1] != null) {
hijos[1].setElementAt(new Long(genHijo[1]), i);
}
hijos[0].setElementAt(new Long(genHijo[0]), i);
}
return hijos;
}
/**
* Discrete cross
* @param n
* @param m
* @param cortes
* @param genAMutar
* @return Returns the intersection individual
*/
private static Vector cruza(int n, int m, Vector cortes, int genAMutar) {
Set mutacionesN = new HashSet();
Set mutacionesM = new HashSet();
//Add the gen to mutations' list
mutacionesN.add(new Long(n));
mutacionesM.add(new Long(m));
//k will be the 'k' bit position
//every bit has the same mutation probability
Vector interseccion = new Vector();
//System.err.println("N -> "+n+" M -> "+m);
while (interseccion.size() == 0) {
//If there is no intersection, then mutate previous mutations in list
int bitsN = 0;
int rangoN = ((Integer) cortes.get(genAMutar)).intValue();
bitsN = rangoN;
Object[] arrayN = mutacionesN.toArray();
int i = 0;
int tam = mutacionesN.size();
while (i < tam) {
//System.err.println("sigo en el while --> "+i+" < "+tam);
int nh = ((Long) arrayN[i]).intValue();
for (int k = 0; k < bitsN; k++) {
int nuevoN = (int) ((nh + Math.pow(2, k)) %
Math.pow(2, k + 1) +
Math.pow(2, k + 1) *
Math.floor(n / Math.pow(2, k + 1)));
if (!mutacionesN.contains(new Long(nuevoN))) {
mutacionesN.add(new Long(nuevoN));
arrayN = mutacionesN.toArray();
}
}
i++;
}
int bitsM = 0;
int rangoM = ((Integer) cortes.get(genAMutar)).intValue();
bitsM = rangoM;
Object[] arrayM = mutacionesM.toArray();
i = 0;
tam = mutacionesM.size();
while (i < tam) {
//System.err.println("sigo en el while --> "+i+" < "+tam);
int mh = ((Long) arrayM[i]).intValue();
for (int k = 0; k < bitsM; k++) {
int nuevoM = (int) ((mh + Math.pow(2, k)) %
Math.pow(2, k + 1) +
Math.pow(2, k + 1) *
Math.floor(m / Math.pow(2, k + 1)));
if (!mutacionesM.contains(new Long(nuevoM))) {
mutacionesM.add(new Long(nuevoM));
arrayM = mutacionesM.toArray();
}
}
i++;
}
//Calculate intersections...
Iterator itN2 = mutacionesN.iterator();
while (itN2.hasNext()) {
//System.err.println("sigo en el while --> "+itN2.hasNext());
Long aux = (Long) itN2.next();
if (mutacionesM.contains(aux)) {
interseccion.add(aux);
}
}
}
return interseccion;
}
/**
* Continuous cross
* @param n
* @param m
* @param k
* @return Children gens
*/
public static int[] cruza(int n, int m, int k) {
int[] hijos = new int[2];
hijos[0] = 0;
hijos[1] = 0;
//System.err.println("descodificando Filas ["+n+","+k+"]");
int fn = Codificacion.descodificaF(n, k);
//System.err.println("descodificando Filas ["+m+","+k+"]");
int fm = Codificacion.descodificaF(m, k);
//System.err.println("descodificando Columnas ["+n+","+k+"]");
int cn = Codificacion.descodificaC(n, k);
//System.err.println("descodificando Columnas ["+m+","+k+"]");
int cm = Codificacion.descodificaC(m, k);
int ch1 = -1;
int fh1 = -1;
int ch2 = -1;
int fh2 = -1;
if (cn != cm && fn != fm) { //If doesn't coincide neither row nor column...
fh1 = fn;
ch1 = cm;
fh2 = fm;
ch2 = cn;
int h = 0;
//Check if it's upper the main diagonal
if (ch1 >= fh1) {
h = Codificacion.codifica(fh1, ch1, k);
hijos[0] = h;
if (ch2 >= fh2) {
h = Codificacion.codifica(fh2, ch2, k);
hijos[1] = h;
}
} else if (ch2 >= fh2) {
h = Codificacion.codifica(fh2, ch2, k);
hijos[0] = h;
}
} else if (cn == cm && fn != fm) { //If they coincide only in column
//Both children will have the same column
ch1 = cn;
ch2 = cn;
int max = Math.abs(fn - fm);
if (max > 1) {
int base = Math.min(fm, fn);
//Take randomly two rows within parents' rows for children
double aleatorio = Randomize.RandClosed(); //Math.random();
int offset1 = (int) Math.rint(aleatorio * max);
fh1 = base + offset1;
aleatorio = Randomize.RandClosed(); //Math.random();
int offset2 = (int) Math.rint(aleatorio * max);
if (offset2 == offset1) {
offset2 = (offset2 + 1) > max ? 0 : (offset2 + 1);
}
fh2 = base + offset2;
//Encode children...
hijos[0] = Codificacion.codifica(fh1, ch1, k);
hijos[1] = Codificacion.codifica(fh2, ch2, k);
} else {
hijos[0] = n;
hijos[1] = m;
}
} else if (cn != cm && fn == fm) { //If they coincide only in row
//Both children will have the same row
fh1 = fn;
fh2 = fn;
int max = Math.abs(cn - cm);
if (max > 1) {
int base = Math.min(cm, cn);
//Take randomly two columns within parents' columns for children
double aleatorio = Randomize.RandClosed(); // Math.random();
int offset1 = (int) Math.rint(aleatorio * max);
ch1 = base + offset1;
aleatorio = Randomize.RandClosed(); // Math.random();
int offset2 = (int) Math.rint(aleatorio * max);
if (offset2 == offset1) {
offset2 = (offset2 + 1) > max ? 0 : (offset2 + 1);
}
ch2 = base + offset2;
//Encode children...
hijos[0] = Codificacion.codifica(fh1, ch1, k);
hijos[1] = Codificacion.codifica(fh2, ch2, k);
} else {
hijos[0] = n;
hijos[1] = m;
}
} else if (cn == cm && fn == fm) { //If both parents are the same...
hijos[0] = n;
hijos[1] = n;
}
return hijos;
}
/**
* @param individuosIniciales
* @param baseCodificada
* @param cortes
* @return poblacionInicial
*/
public static Vector inicializaPoblacion(int individuosIniciales,
Vector baseCodificada,
Vector cortes) {
Vector poblacionInicial = new Vector();
int tam = baseCodificada.size();
for (int i = 0; i < individuosIniciales; i++) {
//Take an element randomly from database
double aleatorio = Randomize.RandClosed(); //Math.random();
int pos = (int) Math.rint(aleatorio * (tam - 1));
//System.err.println("Mira -> "+pos+", a:"+aleatorio+", tam: "+tam);
Vector ejemplo = (Vector) baseCodificada.get(pos);
int numAtributos = ejemplo.size();
//System.err.println("Atributos -> "+numAtributos);
Vector nuevoEjemplo = new Vector();
//Move up and right to obtain a rule that covers current example
//to do that, is necessary to obtain the number of cuts (k) for the attribute that is going to be moved
int j = 0;
//System.err.println("");
boolean malo = false; //Parcheado
while ((j < numAtributos - 1)&&(!malo)) { //Parcheado
int n = ((Long) ejemplo.get(j)).intValue();
int k = 0;
if (cortes.get(j) instanceof Vector) {
k = ((Vector) cortes.get(j)).size();
} else {
k = ((Integer) cortes.get(j)).intValue();
}
int fc = Codificacion.descodificaF(n, k);
aleatorio = Randomize.RandClosed(); //Math.random();
int mArriba = (int) Math.rint(aleatorio * fc);
aleatorio = Randomize.RandClosed(); //Math.random();
int mDerecha = (int) Math.rint(aleatorio * (k - fc - 2));
int nuevoN = su(n, k, mArriba);
nuevoN = de(nuevoN, k, mDerecha);
nuevoEjemplo.add(new Long(nuevoN));
if (nuevoN < 0){
//System.err.print("Mira: (att: "+j+", fila: "+fc+", ej: "+n+", cortes:"+k+" )[" + mArriba + "," + mDerecha +
// "] -> " + n + "," + nuevoN + "...");
malo = true; //Parcheado
}
j++;
}
//Add output attribute
if (!malo){ //Parcheado
int n = ((Long) ejemplo.get(numAtributos - 1)).intValue();
nuevoEjemplo.add(new Long(n));
poblacionInicial.add(nuevoEjemplo);
}else{
i--; //porque hago i++ (parcheado)
}
}
/*for (int i = 0; i < poblacionInicial.size(); i++){
System.err.println("Tam regla -> "+((Vector)poblacionInicial.get(i)).size());
}*/
return poblacionInicial;
}
/**
* Implements Evolutionary Learning
* @param nIndPobIni
* @param nGenerac
* @param crossPerc
* @param cortes
* @param rangos
* @param fp
* @return Best rule
* @throws Exception
*/
public Vector algoritEvol(int nIndPobIni, int nGenerac, double crossPerc,
Vector cortes, Vector rangos, double fp) throws
Exception {
Vector mejorRegla = new Vector();
Entero[] errorMejorRegla = new Entero[2];
poblacion = inicializaPoblacion(nIndPobIni, bc, cortes);
/*for (int i = 0; i < poblacion.size(); i++){
System.err.println("");
for(int j = 0; j < ((Vector)poblacion.get(i)).size(); j++){
System.err.print((Long)((Vector)poblacion.get(i)).get(j)+",");
}
}*/
//System.exit(0);
//System.out.println("Population Initializated.");
for (int i = 0; i < nGenerac; i++) {
//System.out.println("Generation " + (i + 1) + " of " + nGenerac);
evaluacion(rangos, cortes, fp);
reemplazo(cortes, crossPerc, nIndPobIni);
}
evaluacion(rangos, cortes, fp);
//The best rule is now at the first position so...
mejorRegla = (Vector) poblacion.get(0);
errorMejorRegla = (Entero[]) erroresClase.get(0);
Vector ret = new Vector();
ret.add(mejorRegla);
ret.add(errorMejorRegla);
return ret;
}
/**
* @param rangos
* @param cortes
* @param fp
* @throws Exception
*/
public void evaluacion(Vector rangos, Vector cortes, double fp) throws
Exception {
int N = bc.size();
erroresClase = new Vector();
//to mark the best rule...
int max = -1;
double bondadMax = 0;
//Look through the individual
for (int i = 0; i < poblacion.size(); i++) {
//System.out.println("Treating chromosome "+(i+1)+" of "+poblacion.size());
Entero EC = new Entero( -1);
Entero A = new Entero( -1);
Vector reglaActual = (Vector) poblacion.get(i);
ec_a(reglaActual, cortes, EC, A);
double fiActual = 0;
double error = 0;
try {
error = Discretizacion.divide(EC.getValor(),
EC.getValor() + A.getValor());
} catch (ArithmeticException ae) {
error = Double.MAX_VALUE;
}
double valorCobertura = cobertura(reglaActual, rangos, cortes);
if (funcionEvaluacionXmlFileName != null) { //If there is a XML file for the evaluation function...
Operacion opActual = FuncionEvaluacionBean.getOperacion(this.
funcionEvaluacionXmlFileName);
if (error < cep) {
fiActual = evalua(opActual, A.getValor(), 0, N, fp,
valorCobertura);
} else {
fiActual = evalua(opActual, A.getValor(), EC.getValor(), N,
fp, valorCobertura);
}
} else { //If there isn't...
if (error < cep) {
fiActual = N + A.getValor();
} else {
fiActual = N - Discretizacion.multiplica(EC.getValor(), fp) +
A.getValor();
}
fiActual = Discretizacion.suma(fiActual, valorCobertura);
}
if (fiActual > bondadMax) {
max = i;
bondadMax = fiActual;
}
//adding goodness at the end of individual
if (((Vector) poblacion.get(i)).size() == cortes.size()) {
((Vector) poblacion.get(i)).add(new Double(fiActual));
} else if (((Vector) poblacion.get(i)).size() > cortes.size()) {
((Vector) poblacion.get(i)).setElementAt(new Double(fiActual),
((Vector) poblacion.get(0)).size() - 1);
}
//Store EC in the appropriate Vector
Entero[] aux = new Entero[2];
aux[0] = EC;
aux[1] = A;
erroresClase.add(aux); //Vector contains type 'Entero[2]'
//Addition of goodness
sumaFi = Discretizacion.suma(sumaFi, fiActual);
} //for(individuals...)
if (max > 0) {
Vector temp = (Vector) poblacion.remove(max);
poblacion.insertElementAt(temp, 0); //puts the best rule at first position...
Entero[] tempEnt = new Entero[2];
tempEnt = (Entero[]) erroresClase.remove(max);
erroresClase.insertElementAt(tempEnt, 0); //puts class errors for best rule at first position...
}
}
/**
* Gets evaluation function
* @param op
* @param a
* @param ec
* @param n
* @param fp
* @param cobertura
* @return the value of individual's goodness
* @throws Exception
*/
private double evalua(Operacion op, int a, int ec, int n, double fp,
double cobertura) throws Exception {
Object operador1 = null;
Object operador2 = null;
double resultado = 0;
if (op.getA() != 0) {
if (op.getIniOp() != null && op.getIniOp().equalsIgnoreCase("A")) {
operador1 = new Double(a * op.getA());
} else {
operador2 = new Double(a * op.getA());
}
}
if (op.getEC() != 0) {
if (op.getIniOp() != null && op.getIniOp().equalsIgnoreCase("EC")) {
operador1 = new Double(ec * op.getEC());
} else {
operador2 = new Double(ec * op.getEC());
}
}
if (op.getFp() != 0) {
if (op.getIniOp() != null && op.getIniOp().equalsIgnoreCase("fp")) {
operador1 = new Double(Discretizacion.multiplica(fp, op.getFp()));
} else {
operador2 = new Double(Discretizacion.multiplica(fp, op.getFp()));
}
}
if (op.getN() != 0) {
if (op.getIniOp() != null && op.getIniOp().equalsIgnoreCase("N")) {
operador1 = new Double(n * op.getN());
} else {
operador2 = new Double(n * op.getN());
}
}
if (op.getCob() != 0) {
if (op.getIniOp() != null && op.getIniOp().equalsIgnoreCase("cover")) {
operador1 = new Double(n * op.getCob());
} else {
operador2 = new Double(n * op.getCob());
}
}
if (op.getValorConstante() != 0) {
//to prevent integer-formed values
if (op.getIniOp().indexOf(".") < 0) {
op.setIniOp(op.getIniOp() + ".0");
}
if (op.getIniOp() != null &&
op.getIniOp().equals("" + op.getValorConstante())) {
operador1 = new Double(op.getValorConstante());
} else {
operador2 = new Double(op.getValorConstante());
}
}
if (op.getValorOperacion1() != null) {
operador1 = op.getValorOperacion1();
}
if (op.getValorOperacion2() != null) {
operador2 = op.getValorOperacion2();
}
if (operador1 != null && operador2 != null) {
//Base case
if (operador1 instanceof Double && operador2 instanceof Double) {
if (op.getOperacion().equals("add")) {
resultado = Discretizacion.suma(((Double) operador1).
doubleValue(), ((Double) operador2).doubleValue());
} else if (op.getOperacion().equals("sub")) {
resultado = Discretizacion.resta(((Double) operador1).
doubleValue(), ((Double) operador2).doubleValue());
} else if (op.getOperacion().equals("mult")) {
resultado = Discretizacion.multiplica(((Double) operador1).
doubleValue(), ((Double) operador2).doubleValue());
} else if (op.getOperacion().equals("div")) {
resultado = Discretizacion.divide(((Double) operador1).
doubleValue(), ((Double) operador2).doubleValue());
}
} else { //Recursive case
if (operador1 instanceof Operacion) {
double op1 = evalua((Operacion) operador1, a, ec, n, fp,
cobertura);
if (operador2 instanceof Operacion) {
double op2 = evalua((Operacion) operador2, a, ec, n, fp,
cobertura);
if (op.getOperacion().equals("add")) {
resultado = Discretizacion.suma(op1, op2);
} else if (op.getOperacion().equals("sub")) {
resultado = Discretizacion.resta(op1, op2);
} else if (op.getOperacion().equals("mult")) {
resultado = Discretizacion.multiplica(op1, op2);
} else if (op.getOperacion().equals("div")) {
resultado = Discretizacion.divide(op1, op2);
}
} else { //operador2 instanceof Double
if (op.getOperacion().equals("add")) {
resultado = Discretizacion.suma(op1,
((Double) operador2).doubleValue());
} else if (op.getOperacion().equals("sub")) {
resultado = Discretizacion.resta(op1,
((Double) operador2).doubleValue());
} else if (op.getOperacion().equals("mult")) {
resultado = Discretizacion.multiplica(op1,
((Double) operador2).doubleValue());
} else if (op.getOperacion().equals("div")) {
resultado = Discretizacion.divide(op1,
((Double) operador2).doubleValue());
}
}
} else if (operador2 instanceof Operacion) {
double op2 = evalua((Operacion) operador2, a, ec, n, fp,
cobertura);
if (op.getOperacion().equals("add")) {
resultado = Discretizacion.suma(((Double) operador1).
doubleValue(), op2);
} else if (op.getOperacion().equals("sub")) {
resultado = Discretizacion.resta(((Double) operador1).
doubleValue(), op2);
} else if (op.getOperacion().equals("mult")) {
resultado = Discretizacion.multiplica(((Double)
operador1).doubleValue(), op2);
} else if (op.getOperacion().equals("div")) {
resultado = Discretizacion.divide(((Double) operador1).
doubleValue(), op2);
}
}
}
} else {
Exception e = new Exception(
"Operacion object must contain two operators.");
throw e;
}
return resultado;
}
/**
* Build the next generation
* @param cortes
* @param por100Cruces
* @param numIndSigGen
*/
public void reemplazo(Vector cortes, double por100Cruces, int numIndSigGen) {
Vector nextG = new Vector(); //Next generation temporary 'Vector'
//Is not necessary to sort because the best rule is at the first position
Vector mejor = (Vector) poblacion.get(0); //Take the greatest goodness individual that will be at position 0
nextG.add(mejor); //The best individual passes to the next generation immutable...
Vector mejorMutado = muta(mejor, cortes);
nextG.add(mejorMutado); //The same individual passes to the next generation mutated...
if (numIndSigGen <= 0) {
numIndSigGen = poblacion.size();
}
numIndSigGen -= 2; //There is two positions fewer
if (por100Cruces <= 0 || por100Cruces > 100) {
//By default 80% cross...
por100Cruces = 80;
}
double por100Replicas = Math.rint(Discretizacion.resta(100,
por100Cruces));
//Copies
//Number of individual that pass without crossing (copies)
int limite = (int) Math.round(Discretizacion.multiplica(por100Replicas,
numIndSigGen));
limite = (int) Math.round(Discretizacion.divide(limite, 100));
numIndSigGen -= limite;
for (int i = 0; i < limite; i++) {
//System.out.println("Selecting individual "+(i+1)+" of "+limite+" for mutation");
//1� Select individual
Vector individuo = new Vector();
select(individuo);
//2� Mutate
double aleatorio = Randomize.RandClosed(); //Math.random();
if (aleatorio <= probMutacion) {
aleatorio = Randomize.RandClosed(); //Math.random();
if (aleatorio <= probMutExtremo) {
nextG.add(mutaExtremo(individuo, cortes));
} else {
Vector mutado = muta(individuo, cortes);
nextG.add(mutado);
}
} else {
nextG.add(individuo);
}
}
//Crosses
//Number of individual that will be crossed...
for (int i = 0; i < numIndSigGen; i++) {
//1� Select individual
//don't delete individual after crossing
//System.err.println("Selecting individual "+(i+1)+" of "+numIndSigGen+" for croosing");
Vector individuo1 = new Vector();
Vector individuo2 = new Vector();
select(individuo1, false);
int pos2 = select(individuo2, false);
int class1 = ((Long) individuo1.get(individuo1.size() - 2)).
intValue();
int class2 = ((Long) individuo2.get(individuo2.size() - 2)).
intValue();
//cross both individual when they have the same class but they are different
//if they not, take the next one
int cont = 0;
while ((equalIndividual(individuo1, individuo2) ||
(!equalIndividual(individuo1, individuo2) &&
class1 != class2)) && cont < poblacion.size()) {
if (pos2 < poblacion.size() - 1) {
pos2++;
} else {
pos2 = 0;
}
individuo2 = (Vector) poblacion.get(pos2);
class2 = ((Long) individuo2.get(individuo2.size() - 2)).
intValue();
//System.err.println("while son iguales o tienen distinta clase [mientras haya donde elegir]");
cont++;
}
//if classes are the same...
if (class1 == class2) {
Vector[] hijos = cruza(individuo1, individuo2, cortes);
double aleatorio = Randomize.RandClosed(); // Math.random();
if (aleatorio <= probMutacion) {
nextG.add(muta(hijos[0], cortes));
} else {
nextG.add(hijos[0]);
}
if (hijos[1] != null) {
aleatorio = Randomize.RandClosed(); //Math.random();
if (aleatorio <= probMutacion) {
nextG.add(muta(hijos[1], cortes));
} else {
nextG.add(hijos[1]);
}
i++;
}
} else { //if there are not any individual with the same class, just make a mutation to the individual 1
Vector aux = muta(individuo1, cortes);
nextG.add(aux);
}
}
poblacion = (Vector) nextG.clone();
}
/**
* @param individuo
* @param cortes
* @return a extreme mutation for individual
*/
private Vector mutaExtremo(Vector individuo, Vector cortes) {
Vector result = (Vector) individuo.clone();
double aleatorio = Randomize.RandClosed(); //Math.random();
int nGenes = cortes.size() - 1; //Don't take care of the output attribute
int genAMutar = (int) Math.rint(aleatorio * nGenes);
int nuevoN = 0;
if (cortes.get(genAMutar) instanceof Vector) { //Continuous
int k = ((Vector) cortes.get(genAMutar)).size();
nuevoN = k - 1;
} else { //Discrete
int rango = ((Integer) cortes.get(genAMutar)).intValue();
nuevoN = (int) Discretizacion.resta(Math.pow(2, rango), 1);
}
result.setElementAt(new Long(nuevoN), genAMutar);
return result;
}
/**
* @param individuo1
* @param individuo2
* @return true if the both individual are equals
*/
private boolean equalIndividual(Vector individuo1, Vector individuo2) {
boolean res = true;
for (int i = 0; i < individuo1.size() && res; i++) {
if (!individuo1.get(i).equals(individuo2.get(i))) {
res = false;
}
}
return res;
}
/**
* This method without parameters deletes individual by default
* @param indiv
*/
private void select(Vector indiv) {
//This method without parameters deletes individual by default
select(indiv, true);
}
/**
* Implements roulette algorithm
* @param indiv
* @param elimina
* @return Returns the position of the selected individual
*/
private int select(Vector indiv, boolean elimina) {
double aleatorio = Randomize.RandClosed(); //Math.random();
if (sumaBondades == null) {
sumaBondades = new Vector();
sumaBondades.add(new Double(0)); //sumaBondades[0]=0
for (int i = 0; i < poblacion.size(); i++) {
double bondad = ((Double) ((Vector) poblacion.get(i)).get(((
Vector) poblacion.get(i)).size() - 1)).doubleValue(); //Take the goodness
bondad = Discretizacion.divide(bondad, sumaFi);
sumaBondades.add(new Double(Discretizacion.suma(((Double)
sumaBondades.get(i)).doubleValue(), bondad)));
}
}
boolean seleccionado = false;
int i;
for (i = 0; i < poblacion.size() - 1 && !seleccionado; i++) {
if (aleatorio >= ((Double) sumaBondades.get(i)).doubleValue() &&
aleatorio < ((Double) sumaBondades.get(i + 1)).doubleValue()) {
seleccionado = true;
//Clone the individual to return it
for (int j = 0; j < ((Vector) poblacion.get(i)).size(); j++) {
indiv.add(((Vector) poblacion.get(i)).get(j));
}
}
}
if (!seleccionado) {
for (int j = 0;
j <
((Vector) poblacion.get(poblacion.size() - 1)).size();
j++) {
indiv.add(((Vector) poblacion.get(poblacion.size() - 1)).get(j));
}
if (elimina) {
poblacion.remove(poblacion.size() - 1); //Remove this individual from population to avoid repeated ones
}
}
return (i - 1);
}
/**
* @param individuo
* @param cortes
* @return mutado
*/
private Vector muta(Vector individuo, Vector cortes) {
Vector mutado = (Vector) individuo.clone();
double aleatorio = Randomize.RandClosed(); //Math.random();
int nGenes = cortes.size() - 2; //Don't take care of the output attribute
int genAMutar = (int) Math.rint(aleatorio * nGenes);
int n = ((Long) individuo.get(genAMutar)).intValue();
int nuevoN = 0;
if (cortes.get(genAMutar) instanceof Vector) { //If it's continuous...
int k = ((Vector) cortes.get(genAMutar)).size(); //Obtain the number of cuts for the attribute
int f = Codificacion.descodificaF(n, k);
int c = Codificacion.descodificaC(n, k);
aleatorio = Randomize.RandClosed(); //Math.random();
int mArriba = (int) Math.rint(aleatorio * f);
aleatorio = Randomize.RandClosed(); //Math.random();
int mDerecha = (int) Math.rint(aleatorio * (k - c - 2));
aleatorio = Randomize.RandClosed(); //Math.random();
int mAbajo = (int) Math.rint(aleatorio * (c - f));
aleatorio = Randomize.RandClosed(); //Math.random();
int mIzquierda = (int) Math.rint(aleatorio * (c - f));
nuevoN = su(n, k, mArriba);
nuevoN = de(nuevoN, k, mDerecha);
nuevoN = in(nuevoN, k, mAbajo);
nuevoN = iz(nuevoN, k, mIzquierda);
} else { //If it's discrete...
//k will be the position of 'k' bit
//every bit has the same mutation probability
int rango = ((Integer) cortes.get(genAMutar)).intValue();
int bits = (int) Math.round(Math.log(rango) / Math.log(2));
aleatorio = Randomize.RandClosed(); //Math.random();
int k = (int) Math.rint(aleatorio * bits);
nuevoN = (int) ((n + Math.pow(2, k - 1)) % Math.pow(2, k) +
Math.pow(2, k) * Math.floor(n / Math.pow(2, k)));
}
mutado.setElementAt(new Long(nuevoN), genAMutar);
return mutado;
}
/**
*
* @param v
* @param titulo
*/
public static void imprime(Vector v, String titulo) {
System.out.println("\n\n----------------------------------------------");
System.out.println(titulo + ": ");
System.out.print("[");
for (int ii = 0; ii < v.size() - 1; ii++) {
if (v.get(ii) instanceof Integer) {
System.out.print(((Integer) v.get(ii)).intValue() + ", ");
} else if (v.get(ii) instanceof Double) {
System.out.print(((Double) v.get(ii)).doubleValue() + ", ");
} else if (v.get(ii) instanceof Long) {
System.out.print(((Long) v.get(ii)).intValue() + ", ");
} else {
System.out.print(v.get(ii) + ", ");
}
}
if (v.get(v.size() - 1) instanceof Integer) {
System.out.print(((Integer) v.get(v.size() - 1)).intValue() + "]\n");
} else if (v.get(v.size() - 1) instanceof Double) {
System.out.print(((Double) v.get(v.size() - 1)).doubleValue() +
"]\n");
} else if (v.get(v.size() - 1) instanceof Long) {
System.out.print(((Long) v.get(v.size() - 1)).intValue() + "]\n");
} else {
System.out.print(v.get(v.size() - 1) + "]\n");
}
}
/**
*
* @param reglaActual
* @param cortes
* @param EC
* @param A
*/
private void ec_a(Vector reglaActual, Vector cortes, Entero EC, Entero A) {
int errorClase = 0;
int aciertos = 0;
//Look through the elements...
for (int i = 0; i < bc.size(); i++) {
Vector ejemploActual = (Vector) bc.get(i);
boolean cumple = true;
for (int j = 0; (j < (cortes.size() - 1)) && cumple; j++) { //'cortes' has the same number of elements than the number of attributes of 'bc'
int k = 0;
int actualEjemplo = ((Long) ejemploActual.get(j)).intValue();
int actualRegla = ((Long) reglaActual.get(j)).intValue();
//If it's discrete...
if (cortes.get(j) instanceof Integer) {
k = ((Integer) cortes.get(j)).intValue(); //If it's discrete, store in 'cortes' the range of attribute.
//cumple = 'Rule's current attribute covers the element'
if ((actualRegla & actualEjemplo) != 0) {
cumple = true;
} else {
cumple = false;
}
} else { //If it's continuous... (instance of 'Corte')
k = ((Vector) cortes.get(j)).size(); //Number of cuts of the attribute
int fr = Codificacion.descodificaF(actualRegla, k);
int fe = Codificacion.descodificaF(actualEjemplo, k);
int cr = Codificacion.descodificaC(actualRegla, k);
int ce = Codificacion.descodificaC(actualEjemplo, k);
//cumple = 'Rule's current attribute covers the element'
if ((fr <= fe) && (cr >= ce)) {
cumple = true;
} else {
cumple = false;
}
}
}
if (cumple) {
//If rule covers the element but they have different output values, we add an error
if (!reglaActual.get(cortes.size() -
1).equals(ejemploActual.get(cortes.size() -
1))) {
errorClase++;
} else { //Hit!!!
aciertos++;
}
}
}
EC.setValor(errorClase);
A.setValor(aciertos);
}
/**
*
* @param regla
* @param rangos
* @param cortes
* @return Cover coefficient
*/
public double cobertura(Vector regla, Vector rangos, Vector cortes) {
double cobert = 1;
for (int i = 0; i < cortes.size() - 1; i++) {
double temp = Discretizacion.divide(cob((Long) regla.get(i),
cortes.get(i)), rango(rangos.get(i)));
cobert = Discretizacion.multiplica(cobert, temp);
}
return cobert;
}
/**
*
* @param reglai
* @param cortesi
* @return a measure for the cover of the rule
*/
private double cob(Long reglai, Object cortesi) {
double res = 0;
//If it's discrete...
if (cortesi instanceof Integer) {
res = ((Integer) cortesi).doubleValue();
} else { //If it's continuous... (it's a 'Vector' of 'Corte' objects)
int k = ((Vector) cortesi).size();
int f = Codificacion.descodificaF(reglai.intValue(), k);
int c = Codificacion.descodificaC(reglai.intValue(), k);
double li = ((Corte) ((Vector) cortesi).get(f)).getCorte();
double ls = ((Corte) ((Vector) cortesi).get(c + 1)).getCorte();
res = Discretizacion.resta(ls, li);
}
return res;
}
/**
*
* @param rangoi
* @return the 'double' value of 'rangoi'
*/
private double rango(Object rangoi) {
double res = 0;
if (rangoi instanceof Double) { //Continuous
res = ((Double) rangoi).doubleValue();
} else { //Discrete
res = ((Integer) rangoi).doubleValue();
}
return res;
}
/**
* @return Returns the bc.
*/
public Vector getBc() {
return bc;
}
/**
* @param bc The bc to set.
*/
public void setBc(Vector bc) {
this.bc = bc;
}
/**
* @return Returns the probMutacion.
*/
public double getProbMutacion() {
return probMutacion;
}
/**
* @param probMutacion The probMutacion to set.
*/
public void setProbMutacion(double probMutacion) {
this.probMutacion = probMutacion;
}
/**
* @return Returns the probMutExtremo.
*/
public double getProbMutExtremo() {
return probMutExtremo;
}
/**
* @param probMutExtremo The probMutExtremo to set.
*/
public void setProbMutExtremo(double probMutExtremo) {
this.probMutExtremo = probMutExtremo;
}
/**
* @return Returns the erroresClase.
*/
public Vector getErroresClase() {
return erroresClase;
}
/**
* @param erroresClase The erroresClase to set.
*/
public void setErroresClase(Vector erroresClase) {
this.erroresClase = erroresClase;
}
/**
* @return Returns the erroresClase.
*/
public Entero[] getErroresClase(int i) {
return (Entero[]) erroresClase.get(i);
}
/**
* @return Returns the cep.
*/
public double getCep() {
return cep;
}
/**
* @param cep The cep to set.
*/
public void setCep(double cep) {
this.cep = cep;
}
/**
* @return Returns the funcionEvaluacionXmlFileName.
*/
public String getFuncionEvaluacionXmlFileName() {
return funcionEvaluacionXmlFileName;
}
/**
* @param funcionEvaluacionXmlFileName The funcionEvaluacionXmlFileName to set.
*/
public void setFuncionEvaluacionXmlFileName(
String funcionEvaluacionXmlFileName) {
this.funcionEvaluacionXmlFileName = funcionEvaluacionXmlFileName;
}
}