/*********************************************************************** 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_Methods.TSK_IRL; import java.lang.Math; import org.core.*; class Est_mu_landa { 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 Structure[] Padres; public Structure[] Hijos; private double PI = 3.1415926; public static double Beta = 0.0873; public static double Epsilon_sigma = 0.0001; /* parameter of the function "f" */ public static int q = 5; /* Percentage of the maximum matching with which a example is considerated in the initial population */ public static double porcentaje_h = 0.7; /* Individual Percentage of initial population generate with the 'a' values to 0 and a random 'b' value */ public static double porcentaje_Mu = 0.2; /* Initial value of the sigmas */ public static double Valor_Inicial_Sigma = 0.001; public BaseR base_reglas; public Adap fun_adap; public MiDataset tabla; public Est_mu_landa(BaseR base_r, Adap fun, MiDataset t, int gen_ee, 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 = gen_ee; 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]; 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 * 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[fun_adap.indices_ep[0]].ejemplo[tabla. n_var_estado]; h_max = tabla.datos[fun_adap.indices_ep[0]].nivel_cubrimiento; for (i = 1; i < fun_adap.n_ejemplos_positivos; i++) { if (tabla.datos[fun_adap.indices_ep[i]].ejemplo[tabla.n_var_estado] > y_max) { y_max = tabla.datos[fun_adap.indices_ep[i]].ejemplo[tabla.n_var_estado]; } if (tabla.datos[fun_adap.indices_ep[i]].ejemplo[tabla.n_var_estado] < y_min) { y_min = tabla.datos[fun_adap.indices_ep[i]].ejemplo[tabla.n_var_estado]; } y_med += tabla.datos[fun_adap.indices_ep[i]].ejemplo[tabla.n_var_estado]; if (tabla.datos[fun_adap.indices_ep[i]].nivel_cubrimiento > h_max) { h_max = tabla.datos[fun_adap.indices_ep[i]].nivel_cubrimiento; } } if (fun_adap.n_ejemplos_positivos > 0) { y_med /= fun_adap.n_ejemplos_positivos; } else { y_med = Double.MAX_VALUE; } 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 + 1; i < Mu; i++) { for (j = 0; j < tabla.n_var_estado; j++) { if (Randomize.Rand() < 0.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[fun_adap.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[fun_adap.indices_ep[pos_ep]].ejemplo[j]; } Padres[i].Gene[tabla.n_var_estado] = Math.atan(tabla.datos[fun_adap.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 * 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 * PI * 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] < - (PI / 2.0)) { Hijos[n_hijo].Gene[i] = - (PI / 2.0) + 1E-10; } if (Hijos[n_hijo].Gene[i] > (PI / 2.0)) { Hijos[n_hijo].Gene[i] = (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_ml(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]; } Padres[i].Perf = Hijos[indices_seleccion[i]].Perf; } } /* ------------------------------------------------------------------------- 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 void guardar_solucion(Structure Padre) { int i, pos_individuo; pos_individuo = tabla.n_var_estado + 3 * tabla.n_var_estado; for (i = 0; i < tabla.n_var_estado; i++) { /* Valores 'a' del Consecuente */ Padre.Gene[pos_individuo + i] = Padres[0].Gene[i]; } /* Valor 'b' del Consecuente */ Padre.Gene[pos_individuo + i] = Padres[0].Gene[tabla.n_var_estado]; } public double[] solucion() { return (Padres[0].Gene); } public double fitness_solucion() { return (Padres[0].Perf); } }