/***********************************************************************
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.Fuzzy_Rule_Learning.Genetic.Thrift;
import org.core.*;
import java.util.ArrayList;
/**
* <p>Title: </p>
*
* <p>Description: </p>
*
* <p>Copyright: Copyright (c) 2007</p>
*
* <p>Company: </p>
*
* @author not attributable
* @version 1.0
*/
public class GA {
myDataset train, test;
BaseD baseDatos;
static BaseR baseReglas;
int populationSize, nEvaluations, n_genes;
double crossProb, mutProb;
ArrayList<Individuo> New, Old;
static int Trials, Trials_mejor;
int Best_guy;
int n_var_estado;
String output;
int Mu_next;
double Best_perf;
public GA(myDataset train, myDataset test, BaseD baseDatos,
BaseR baseReglas,
int populationSize,
int nEvaluations, int n_genes,
double crossProb, double mutProb, String output) {
this.train = train;
this.test = test;
this.baseDatos = baseDatos;
this.baseReglas = baseReglas;
this.populationSize = populationSize;
this.nEvaluations = nEvaluations;
this.n_genes = n_genes;
this.crossProb = crossProb;
this.mutProb = mutProb;
this.output = output;
n_var_estado = train.getnInputs();
Fichero.escribeFichero(output, "");
}
// Cambiar si voy a maximizar
public static boolean BETTER(double X, double Y) {
return (X) < (Y);
}
public Individuo lanzar() {
Individuo solucion = new Individuo();
Trials = Trials_mejor = 0;
Best_perf = Double.MAX_VALUE;
init();
Evaluacion();
//for (int Gen = 0; Gen <= this.nGenerations; Gen++) {
int Gen = 0;
do {
int n_r = baseReglas.decodifica(New.get(Best_guy).getGene());
//System.out.println("desv: " + train.variance(train.getnInputs()));
double ecn_tra = (2.0 / train.variance(train.getnInputs())) *
New.get(Best_guy).Perf;
double ecn_tst = (2.0 / test.variance(test.getnInputs())) *
Error(test, n_r);
System.out.println("Gen: " + Gen + ", #Ev: " + Trials +
"; ECMntra-tst = " +
ecn_tra + "-" + ecn_tst + " #R: " +
n_r + "; EMS: " + Trials_mejor);
/* Intercambio de las poblaciones nueva y antigua */
//Old = (ArrayList) New.clone();
Old.clear();
for (int i = 0; i < populationSize; i++) {
Old.add(New.get(i).copia());
}
New.clear();
/* Seleccion mediante el metodo de Baker */
Select();
/* Cruce */
Cruce();
/* Mutacion */
Mutacion();
/* Seleccion elitista */
Elitist();
/* Evaluacion de los individuos de la poblacion actual */
Evaluacion();
Gen++;
} while (Trials <= nEvaluations);
/*APRENDER_PESOS_GA*/
solucion.copia(New.get(Best_guy));
int n_r = baseReglas.decodifica(New.get(Best_guy).getGene());
double ecm_tst = Error(test, n_r);
System.out.println("Gen: " + Gen + ", #Ev: " + Trials +
"; ECMtra-tst = " +
New.get(Best_guy).Perf + "-" + ecm_tst + " #R: " +
n_r + "; EMS: " + Trials_mejor);
return solucion; //guarda la mejor solucion
}
private void init() {
New = new ArrayList<Individuo>(populationSize);
Old = new ArrayList<Individuo>(populationSize);
if (this.mutProb < 1.0) {
Mu_next = (int) Math.ceil(Math.log(Randomize.Rand()) /
Math.log(1.0 - mutProb));
} else {
Mu_next = 1;
}
//System.err.println("Mu-next: "+this.Mu_next);
//System.err.println("Genes: "+n_genes);
for (int i = 0; i < populationSize; i++) {
Individuo ind = new Individuo(n_genes);
for (int j = 0; j < n_genes; j++) {
ind.setGene(j,
Randomize.RandintClosed(0,
baseDatos.getnLabels(n_var_estado)));
}
New.add(ind);
//System.out.print("Cromosoma["+i+"]: ");
//ind.print();
}
}
private void Evaluacion() {
double performance, Best_current_perf;
Best_current_perf = Double.MAX_VALUE;
boolean eval = false;
for (int i = 0; i < this.populationSize; i++) {
if (New.get(i).noEvaluado()) { /* Si no esta evaluado, se evalua */
New.get(i).Perf = evalua(New.get(i).getGene());
performance = New.get(i).Perf;
//System.out.println("Individuo[" + i + "]: " + performance);
New.get(i).evaluado();
eval = true;
} else {
performance = New.get(i).Perf;
eval = false;
}
if (performance < Best_perf) {
Best_perf = performance;
Trials_mejor = Trials;
}
if (eval) {
String cadena = new String("Trails: " + Trials + ", Perf: " +
Best_perf + "\n");
Fichero.AnadirtoFichero(output, cadena);
}
/* Calculo de la posicion del mejor individuo en la poblacion actual */
if (i == 0) {
Best_current_perf = performance;
Best_guy = 0;
} else
if (BETTER(performance, Best_current_perf)) {
Best_current_perf = performance;
Best_guy = i;
}
}
}
public double evalua(int[] cromosoma) {
double ecm;
Trials++;
/* Se obtiene la BR seg�n los consecuentes utilizados */
int n_reglas = baseReglas.decodifica(cromosoma);
ecm = Error(train, n_reglas);
return ecm;
}
public static double Error(myDataset datos, int n_reglas) {
int j;
double suma, fuerza;
for (j = 0, suma = 0.0; j < datos.getnData(); j++) {
fuerza = baseReglas.FLC(datos.getExample(j), n_reglas);
suma += 0.5 * Math.pow(datos.getOutputAsReal(j) - fuerza, 2.0);
}
return (suma / (double) datos.getnData());
}
private void Select() {
double expected, factor, perf, ptr, sum, rank_max, rank_min;
int i, j, k, best, temp;
int[] sample = new int[populationSize];
/* La seleccion se hara siguiendo el modelo de ranking lineal r_min=0.75 */
rank_min = 0.75;
/* Asignamos a cada elemento su ranking en la poblacion:
rank = populationSize-1 para el mejor y ranking = 0 para el peor.
Se usa el campo n_e para almacenar el ranking de cada elemento */
for (i = 0; i < populationSize; i++) {
Old.get(i).setRanking(0);
}
for (i = 0; i < populationSize - 1; i++) {
/* Se encuentra el mejor elemento de los que restan por ordenar*/
best = -1;
perf = 0.0;
for (j = 0; j < populationSize; j++) {
if (Old.get(j).getRanking() == 0 &&
(best == -1 || this.BETTER(Old.get(j).Perf, perf))) {
perf = Old.get(j).Perf;
best = j;
}
}
/* Se marca dicho elemento con su ranking */
Old.get(best).setRanking(populationSize - 1 - i);
}
/* Se normaliza para crear las probabilidades */
rank_max = 2.0 - rank_min;
factor = (rank_max - rank_min) / (double) (populationSize - 1);
/* Se asigna el numero de copias esperadas a cada cromosoma en funcion de
la probabilidad de seleccion que tenga asociada. Se procede a la seleccion
de los cromosomas segun el metodo de Baker */
k = 0;
ptr = Randomize.Rand();
for (sum = i = 0; i < populationSize; i++) {
expected = rank_min + Old.get(i).getRanking() * factor;
for (sum += expected; sum >= ptr; ptr++) {
sample[k++] = i;
}
}
if (k != populationSize) {
/* Aseguro que se seleccione toda la poblacion si falta algun miembro */
for (; k < populationSize; k++) {
sample[k] = Randomize.RandintClosed(0, populationSize-1);
}
}
/*for (i = 0; i < populationSize; i++) {
System.out.print(sample[i]+", ");
}
System.out.println("");*/
/* Se procede a barajar los cromosomas seleccionados para aplicar posterior-
mente los operadores geneticos */
for (i = 0; i < populationSize; i++) {
j = Randomize.RandintClosed(i, populationSize-1);
temp = sample[j];
sample[j] = sample[i];
sample[i] = temp;
}
/* Se crea la nueva poblacion con los individuos seleccionados */
for (i = 0; i < populationSize; i++) {
k = sample[i];
Individuo ind = new Individuo(n_genes);
for (j = 0; j < n_genes; j++) {
//New.get(i).Gene[j] = Old.get(k).Gene[j];
ind.setGene(j, Old.get(k).getGene(j));
}
//New.get(i).Perf = Old.get(k).Perf;
//New.get(i).evaluado();
ind.Perf = Old.get(k).Perf;
ind.evaluado();
New.add(ind);
//System.out.print("Individuo[" + i + "][" + k + "]: ");
//New.get(i).print();
}
}
private void Cruce()
/* Operador de cruce multipunto en dos puntos */
{
int mom, dad, xpoint1, xpoint2, i;
int temp;
for (mom = 0; mom < (int) crossProb; mom += 2) {
dad = mom + 1;
/* Se generan los dos puntos de cruce*/
xpoint1 = Randomize.RandintClosed(0, n_genes-1);
if (xpoint1 != n_genes - 1) {
xpoint2 = Randomize.RandintClosed(xpoint1 + 1, n_genes-1);
} else {
xpoint2 = n_genes - 1;
}
/* Se cruzan las partes contenidas entre ambos puntos */
for (i = xpoint1; i <= xpoint2; i++) {
temp = New.get(mom).Gene[i];
New.get(mom).Gene[i] = New.get(dad).Gene[i];
New.get(dad).Gene[i] = temp;
}
/* Se marcan los dos nuevos cromosomas para su posterior evaluacion */
New.get(mom).setNoEvaluado();
New.get(dad).setNoEvaluado();
/*System.out.print("Individuo["+mom+"]: ");
New.get(mom).print();
System.out.print("Individuo["+dad+"]: ");
New.get(dad).print();*/
}
}
private void Mutacion() {
int posiciones, i, j;
double m;
posiciones = n_genes * populationSize;
if (mutProb > 0) {
while (Mu_next < posiciones) {
/* Se determina el cromosoma y el gen que corresponden a la posicion que
se va a mutar */
i = (int) Mu_next / n_genes;
j = (int) Mu_next % n_genes;
/* Se efectua la mutacion sobre ese gen */
if (New.get(i).getGene(j) == 0)
/* Si estoy en la primera etiqueta, es */
{
New.get(i).Gene[j] += 1; /* obligatorio sumar */
} else {
if (New.get(i).Gene[j] ==
baseDatos.getnLabels(n_var_estado) - 1)
/* Si estoy en la */
{
New.get(i).Gene[j] -= 1;
/* ultima, lo obligatorio es restar */
} else {
if (New.get(i).Gene[j] ==
baseDatos.getnLabels(n_var_estado))
/* Si es el simbolo */
{
New.get(i).Gene[j] = Randomize.RandintClosed(0,
baseDatos.getnLabels(n_var_estado)-1);
/* nulo, le asocio cualquiera */
} else {
/* En cualquier otro caso, sumo o resto aleatoriamente */
m = Randomize.Rand();
if (m < 0.5) {
New.get(i).Gene[j] += 1;
} else {
New.get(i).Gene[j] -= 1;
}
}
}
}
New.get(i).setNoEvaluado();
/* Se calcula la siguiente posicion a mutar */
if (mutProb < 1.0) {
m = Randomize.Rand();
Mu_next +=
(int) Math.ceil(Math.log(m) /
Math.log(1.0 - mutProb));
} else {
Mu_next += 1;
}
}
}
Mu_next -= posiciones;
}
private void Elitist()
/* Seleccion elitista */
{
int i, k;
boolean found = false;
/* Se estudia a ver si el mejor cromosoma de la poblacion anterior ha sido
seleccionado para formar parte de la nueva */
for (i = 0; i < populationSize && (!found); i++) {
for (k = 0, found = true; (k < n_genes) && (found); k++) {
found = (New.get(i).Gene[k] == Old.get(Best_guy).Gene[k]);
}
}
/* Si el mejor cromosoma no ha perdurado, se sustituye el ultimo de la
poblacion por este. */
if (!found) {
for (k = 0; k < n_genes; k++) {
New.get(populationSize - 1).Gene[k] = Old.get(Best_guy).Gene[k];
}
New.get(populationSize - 1).Perf = Old.get(Best_guy).Perf;
New.get(populationSize - 1).evaluado();
}
}
public static int dameTrials() {
return Trials_mejor;
}
}