/*********************************************************************** 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.RE_SL_Postprocess.Mam2TSK; import java.lang.Math; import org.core.*; class Est_evol { public int n_gen_ee; public int Mu, Landa, n_sigma, n_alfa, n_total, nl_alfa, nm_alfa; public int Omega_x, Omega_sigma, Omega_alfa, Delta_x, Delta_sigma, Delta_alfa; public double Tau_0, Tau, Tau_1; public double [] Z; public int [] indices_seleccion; public int [] indices_recombinacion; public int [] ind_mayor; public int [] indices_ep; public Structure [] Padres; public Structure [] Hijos; public double Beta = 0.0873; public double Epsilon_sigma = 0.0001; /* parameter of the function "f" */ public int q = 5; /* Percentage of the maximum matching with which a example is considerated in the initial population */ public double porcentaje_h = 0.7; /* Individual Percentage of initial population generate with the 'a' values to 0 and a random 'b' value */ public double porcentaje_Mu = 0.2; /* Initial value of the sigmas */ public double Valor_Inicial_Sigma = 0.001; public BaseR base_reglas; public Adap fun_adap; public MiDataset tabla; public Est_evol (BaseR base_r, Adap fun, MiDataset t, int n_gen, int m, int l, int n_sigm, int n_alf, int Omeg_x, int Omeg_sigma, int Omeg_alfa, int Delt_x, int Delt_sigma, int Delt_alfa) { int i; base_reglas = base_r; fun_adap = fun; tabla = t; n_gen_ee = n_gen; Mu = m; Landa = l; n_sigma = n_sigm; n_alfa = n_alf; Omega_x = Omeg_x; Omega_sigma = Omeg_sigma; Omega_alfa = Omeg_alfa; Delta_x = Delt_x; Delta_sigma = Delt_sigma; Delta_alfa = Delt_alfa; n_total = tabla.n_variables + n_sigma + n_alfa; Tau_0 = 1.0 / Math.sqrt (2 * tabla.n_variables); Tau = 1.0 / Math.sqrt (2 * Math.sqrt(tabla.n_variables)); Tau_1 = 1.0 / Math.sqrt(tabla.n_variables); nl_alfa = tabla.n_variables + 1 - n_sigma; nm_alfa = tabla.n_variables - 1; Z = new double[tabla.n_variables]; indices_seleccion = new int[Landa]; indices_recombinacion = new int[(int) Adap.Maximo(Delta_x, Adap.Maximo (Delta_sigma,Delta_alfa))]; ind_mayor = new int[tabla.long_tabla]; indices_ep = new int[tabla.long_tabla]; Padres = new Structure[Mu]; Hijos = new Structure[Landa]; for (i=0; i<Mu; i++) Padres[i] = new Structure(n_total); for (i=0; i<Landa; i++) Hijos[i] = new Structure(n_total); } /* ------------------------------------------------------------------------- Recombination Process ----------------------------------------------- -------------------------- */ private double signo (double x) { if (x >= 0.0) return (1); else return (-1); } /** Rounds the generated value by the semantics */ double Asigna (double val, double tope) { if (val>-1E-4 && val<1E-4) return (0); if (val>tope-1E-4 && val<tope+1E-4) return (tope); return (val); } /** Returns the 'a' values as little as we want */ double f (double x, int y) { return (y * Math.PI/2 * Math.pow (x,q)); } /** Generates the initial population of fathers */ public void InicializaPadres () { int i, j, y, Mu_primer_grupo, pos_ep, total_mayor; double y_med, y_min, y_max, h_max, h_exigido, x; double imagen; /* we calculate the average, maximum and minimum high, and the matching with which a example is considerated in the initial population */ y_med = y_min = y_max = tabla.datos[indices_ep[0]].ejemplo[tabla.n_var_estado]; h_max = tabla.datos[indices_ep[0]].nivel_cubrimiento; for (i=1; i<fun_adap.n_ejemplos_positivos; i++) { if (tabla.datos[indices_ep[i]].ejemplo[tabla.n_var_estado] > y_max) y_max = tabla.datos[indices_ep[i]].ejemplo[tabla.n_var_estado]; if (tabla.datos[indices_ep[i]].ejemplo[tabla.n_var_estado] < y_min) y_min = tabla.datos[indices_ep[i]].ejemplo[tabla.n_var_estado]; y_med += tabla.datos[indices_ep[i]].ejemplo[tabla.n_var_estado]; if (tabla.datos[indices_ep[i]].nivel_cubrimiento > h_max) h_max = tabla.datos[indices_ep[i]].nivel_cubrimiento; } y_med /= fun_adap.n_ejemplos_positivos; h_exigido = porcentaje_h * h_max; /* Inicialization of a individual with 'b' value same as the average high and with the 'a' values to 0 */ for (j=0; j<tabla.n_var_estado; j++) Padres[0].Gene[j] = 0; Padres[0].Gene[tabla.n_var_estado] = Math.atan(y_med); /* Inicialization of the porcentaje_Mu * Mu individuals with 'b' value equal to a random value in the rank [y_min,y_max] and with the 'a' values to 0 */ Mu_primer_grupo = (int) (porcentaje_Mu * Mu + 1); for (i=1; i<Mu_primer_grupo; i++) { for (j=0; j<tabla.n_var_estado; j++) Padres[i].Gene[j] = 0; Padres[i].Gene[tabla.n_var_estado] = Math.atan(Randomize.Randdouble (y_min,y_max)); } /* Inicialization of the remaining individuals with the random 'a' values and with a the 'b' value for any to example is in the plane */ for (i=Mu_primer_grupo; i<Mu; i++) { for (j=0; j<tabla.n_var_estado; j++) { if (Randomize.Rand ()<.5) y = -1; else y=1; x = Randomize.Rand (); Padres[i].Gene[j] = f(x,y); } /* we select randomly a example with a matching more high than "h_exigido" */ for (total_mayor=pos_ep=0; pos_ep<fun_adap.n_ejemplos_positivos; pos_ep++) if (tabla.datos[indices_ep[pos_ep]].nivel_cubrimiento >= h_exigido) ind_mayor[total_mayor++] = pos_ep; if (total_mayor==0) { System.out.println("Error: The matching, with which a example is considerated in the initial population, isn't surmounted"); } pos_ep = ind_mayor[Randomize.RandintClosed (0,total_mayor-1)]; for (imagen=0.0,j=0; j<tabla.n_var_estado; j++) imagen += Math.tan (Padres[i].Gene[j]) * tabla.datos[indices_ep[pos_ep]].ejemplo[j]; Padres[i].Gene[tabla.n_var_estado] = Math.atan(tabla.datos[indices_ep[pos_ep]].ejemplo[tabla.n_var_estado]-imagen); } /* Inicialization of the vector of tipical desviations */ for (i=0; i<Mu; i++) for (j=tabla.n_variables; j<tabla.n_variables+n_sigma; j++) Padres[i].Gene[j] = Valor_Inicial_Sigma; /* Inicialization of the vector of angles: arcotangente of 1.0 */ for (i=0; i<Mu; i++) for (j=tabla.n_variables + n_sigma; j<tabla.n_variables+n_sigma+n_alfa; j++) Padres[i].Gene[j] = Math.atan (1.0); } /** Recombination Operators */ private double OperadoresRecombinacion (int omega, int delta, int pos) { double u, suma, salida; int i, padre1, padre2; switch (omega) { /* Intermediate Global Recombination */ case 1: for (suma=0.0,i=0;i<delta;i++) suma += Padres[indices_recombinacion[i]].Gene[pos]; salida=suma/delta; break; /* Intermediate Local Recombination */ case 2: padre1=Randomize.RandintClosed (0,delta-1); padre2=Randomize.RandintClosed (0,delta-1); u = Randomize.Rand (); salida = u * Padres[indices_recombinacion[padre1]].Gene[pos] + (1-u)*Padres[indices_recombinacion[padre2]].Gene[pos]; break; /* Tactfully Recombination */ default: padre1 = Randomize.RandintClosed (0,delta-1); salida = Padres[indices_recombinacion[padre1]].Gene[pos]; break; } return (salida); } /** Returns 1 if the current index is in the list of selected indexes */ private int Pertenece (int [] indices_seleccionados, int ind_act, int n_seleccionados) { int i; i=0; while (i<n_seleccionados) if (indices_seleccionados[i]==ind_act) return (1); else i++; return (0); } /** Recombination process */ private void Recombinacion () { int n_hijo, i, j, cadena, omega, delta, princ_cadena, fin_cadena, padre; for (n_hijo=0; n_hijo<Landa; n_hijo++) { /* Recombination of the individual's parties: cadena=0 -> solution vector x. cadena=1 -> standard deviation vector sigma. cadena=2 -> vector of inclination angles alfa. */ for (cadena=0;cadena<=2;cadena++) { switch (cadena) { case 0: omega = Omega_x; delta = Delta_x; princ_cadena = 0; fin_cadena = tabla.n_variables; break; case 1: omega = Omega_sigma; delta = Delta_sigma; princ_cadena = tabla.n_variables; fin_cadena = tabla.n_variables + n_sigma; break; default: omega = Omega_alfa; delta = Delta_alfa; princ_cadena = tabla.n_variables + n_sigma; fin_cadena = tabla.n_variables + n_sigma + n_alfa; break; } /* we perform if the string isn't empty */ if (princ_cadena!=fin_cadena) { /* we select the individual */ /* we copy directly all if each individual is selected */ if (delta==Mu) for (i=0; i<delta; i++) indices_recombinacion[i] = i; /* we select randomly the individuals if all individuals aren't selected */ else { for (i=0; i<delta; i++) do indices_recombinacion[i]=Randomize.RandintClosed (0,delta-1); while (Pertenece (indices_recombinacion,indices_recombinacion[i],i)==1); } if (omega==0) { /* we select randomly a individual */ padre=Randomize.RandintClosed (0,delta-1); for (j=princ_cadena; j<fin_cadena; j++) Hijos[n_hijo].Gene[j] = Padres[indices_recombinacion[padre]].Gene[j]; } else /* we recombine the current string with the selected operator omega */ for (j=princ_cadena; j<fin_cadena; j++) Hijos[n_hijo].Gene[j] = OperadoresRecombinacion (omega,delta,j); } } } } /* ------------------------------------------------------------------------- Mutation Process ------------------------------------------------------------------------- */ /** Generates a normal value with hope 0 and tipical deviation "desv */ private double ValorNormal (double desv) { double u1, u2; /* we generate 2 uniform values [0,1] */ u1=Randomize.Rand (); u2=Randomize.Rand (); /* we calcules a normal value with the uniform values */ return (desv * Math.sqrt (-2 * Math.log(u1)) * Math.sin (2*Math.PI*u2)); } /* Mutation process of the generated son by means of the recombination */ private void Mutacion () { int n_hijo, i, j, nq, n1, n2; double z0, z1, x1, x2, si, co; for (n_hijo=0; n_hijo<Landa; n_hijo++) { /* Mutation of sigma */ if (n_sigma==1) /* if we use only a sigma, the sigma is adapted with Tau_1 */ Hijos[n_hijo].Gene[tabla.n_variables] *= ValorNormal (Tau_1); else { z0 = ValorNormal (Tau_0); for (i=tabla.n_variables; i<tabla.n_variables + n_sigma; i++) { z1 = ValorNormal (Tau); Hijos[n_hijo].Gene[i] *= Math.exp (z1+z0); /* The standard desviation is Epsilon_sigma if it becomes 0 */ if (Hijos[n_hijo].Gene[i]==0.0) Hijos[n_hijo].Gene[i] = Epsilon_sigma; } } /* Mutation of alfa */ for (i = tabla.n_variables + n_sigma; i<tabla.n_variables + n_sigma + n_alfa; i++) { z0 = ValorNormal (Beta); Hijos[n_hijo].Gene[i] += z0; /* Si el valor mutado se sale del intervalo [-i,i], se proyecta circularmente el valor a dicho intervalo */ if (Math.abs(Hijos[n_hijo].Gene[i])>i) Hijos[n_hijo].Gene[i] -= 2 *i * signo (Hijos[n_hijo].Gene[i]); } /* Mutation of x */ /* we calculate the uncorrelated vector of mutations */ for (i=0; i<tabla.n_variables; i++) if (tabla.n_variables + i < tabla.n_variables + n_sigma) Z[i] = ValorNormal (Hijos[n_hijo].Gene[tabla.n_variables+i]); else /* if there aren't more tipical desviations we use the latest */ Z[i] = ValorNormal (Hijos[n_hijo].Gene[tabla.n_variables+n_sigma-1]); /* Correlation of the vector if we use the angles */ if (n_alfa!=0) { nq = n_alfa; for (j=nl_alfa; j<=nm_alfa; ++j) { n1 = tabla.n_variables - j; n2 = tabla.n_variables; for (i=1; i<=j; ++i) { x1 = Z[n1-1]; x2 = Z[n2-1]; si = Math.sin(Hijos[n_hijo].Gene[tabla.n_variables + n_sigma + nq - 1]); co = Math.cos(Hijos[n_hijo].Gene[tabla.n_variables + n_sigma + nq - 1]); Z[n2-1] = x1*si + x2*co; Z[n1-1] = x1*co - x2*si; --n2; --nq; } } } /* Final mutation of X */ for (i=0; i<tabla.n_variables; i++) { Hijos[n_hijo].Gene[i] += Z[i]; if (Hijos[n_hijo].Gene[i] < -(Math.PI/2.0)) Hijos[n_hijo].Gene[i] = -(Math.PI/2.0) + 1E-10; if (Hijos[n_hijo].Gene[i] > (Math.PI/2.0)) Hijos[n_hijo].Gene[i] = (Math.PI/2.0) - 1E-10; } } } /* ------------------------------------------------------------------------- Selection Process ------------------------------------------------------------------------- */ /** Selection process of the best Mu sons of the generated Landa sons */ private void Seleccion () { int i, j, temp; /* we evaluate the Landa sons */ for (i=0; i<Landa; i++) Hijos[i].Perf = fun_adap.eval (Hijos[i].Gene); /* we order the sons by mean of the bubble method */ for (i=0; i<Landa; i++) indices_seleccion[i]=i; for (i=0; i<Landa; i++) for (j=0; j<Landa-i-1; j++) if (Hijos[indices_seleccion[j+1]].Perf < Hijos[indices_seleccion[j]].Perf) { temp = indices_seleccion[j]; indices_seleccion[j] = indices_seleccion[j+1]; indices_seleccion[j+1] = temp; } /* we select the best Mu sons */ for (i=0; i<Mu; i++) for (j=0; j<n_total; j++) Padres[i].Gene[j] = Hijos[indices_seleccion[i]].Gene[j]; } /* ------------------------------------------------------------------------- Evolution Strategy (Mu,Landa) ------------------------------------------------------------------------- */ /** Main of the Evolution Strategy (Mu,Landa) */ public void EE_Mu_Landa () { int i; InicializaPadres (); for (i=0; i<n_gen_ee; i++) { Recombinacion (); Mutacion (); Seleccion (); } } public double [] solucion () { return (Padres[0].Gene); } }