/*********************************************************************** 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.Shared.OptimLocal; /** * Main class of the Ameba algorithm. * <p> * @author Written by Luciano S�nchez (University of Oviedo) 03/03/2004 * @author Modified by M.R. Su�rez (University of Oviedo) 18/12/2008 * @author Modified by Enrique A. de la Cal (University of Oviedo) 21/12/2008 * @version 1.0 * @since JDK1.5 * </p> */ public class Ameba { // This algorithm is applied with the crossover operator. // This algorithm is an optimization of Nelder and Mead Simplex. boolean debug=false; /** * <p> * It makes the iterations of the algorithm * </p> * * @param f1 fitness function * @param ctes constants of the algorithm * @param max_iter The maximum number of iterations * @return The fitness */ public double itera(FUN f1, double [] ctes, int max_iter) { int i; final double volsimplex=1; // Initial side for simplex algorithm double end_sumdi=0; double[][]x = new double[ctes.length+1][ctes.length]; // x is the simplex double[] xf = new double[ctes.length+1]; // xf are fitness values // Initial simples. The last values is the centroid. x[x.length-1]=duplicate(ctes); xf[x.length-1]=f1.evaluate(ctes); for (i=0;i<xf.length-1;i++) { x[i]= duplicate(x[x.length-1]); x[i][i]+=volsimplex; } int iter=0; double max,min; int best,worst; double []xc; double []xr; double []xe; double []xp; double []xi; double []xo; double tmpfit,tmpfit1; double fit_o=-1; // Solution fitness xo = duplicate(ctes); boolean compress; for (i=0;i<xf.length;i++) xf[i]=f1.evaluate(x[i]); double oldmin; do { compress=false; //Best and worst simplex point max=xf[0]; min=xf[0]; worst=0; best=0; for (i=1;i<xf.length;i++) { if (max<=xf[i]) { worst=i; max=xf[i]; } if (xf[i]<min) { best=i; min=xf[i]; } } if (debug) { System.out.println("Debug ameba="); for (i=0;i<xf.length;i++) { System.out.println(" fitness="+xf[i]); } } // Simplex centroid, worst point excluded xc=new double[ctes.length]; for (i=0;i<x.length;i++) if (i!=worst) xc=OPV.sum(xc,x[i]); xc=OPV.multiply(1.0/(x.length-1),xc); // Reflected point xr=OPV.sum(xc,OPV.sum(xc,OPV.multiply(-1.0,x[worst]))); tmpfit=f1.evaluate(xr); // if the reflected point is the best one, you must // calcute the expanded one if (tmpfit<xf[best]) { xe=OPV.sum(xr,OPV.sum(xr,OPV.multiply(-1.0,xc))); tmpfit1=f1.evaluate(xe); // One of both is the solution if (tmpfit1<xf[best]) { xo=duplicate(xe); fit_o=tmpfit1; } else { xo=duplicate(xr); fit_o=tmpfit; } } else { // Reflected one is not the best // The reflected point is not point: Let's count how much points are best of worst than original one. int mu=0; for (i=0;i<x.length;i++) if (tmpfit<xf[i]) mu++; // If there are more than one point, the solution is the reflected one if (mu>1) { xo=duplicate(xr); fit_o=tmpfit; } else if (mu==1) { // There is only point worst than reflected one // Partial contraction to exterior xp=OPV.multiply(0.5,OPV.sum(xc,xr)); tmpfit1=f1.evaluate(xp); // If point is better than reflected one, xp is the solution if (tmpfit1<tmpfit) { xo=duplicate(xp); fit_o=tmpfit1; } else { //Partial contraction to interior xi=OPV.multiply(0.5,OPV.sum(xc,x[worst])); tmpfit1=f1.evaluate(xi); // It's the solution If the worst is improved if (tmpfit1<xf[worst]) { xo=duplicate(xi); fit_o=tmpfit1; } else compress=true; } } else compress=true; if (compress) { // Total contraction: Simplex size reduction xo=duplicate(x[best]); for (i=0;i<x.length;i++) { x[i]=OPV.multiply(0.5,OPV.sum(xo,x[i])); xf[i]=f1.evaluate(x[i]); } } } if (!compress) { x[worst]=duplicate(xo); xf[worst]=fit_o; } iter++; // if fitness has reduced volume, it's so much double faverage=0,sumdi=0; for (i=0;i<xf.length;i++) faverage+=xf[i]; for (i=0;i<xf.length;i++) sumdi+=Math.abs(xf[i]-faverage); if (debug) System.out.println("** It="+iter+" Fitness="+xf[best]+" Suma dif="+sumdi); if (sumdi<0.0001) break; if (sumdi==end_sumdi) break; end_sumdi=sumdi; } while(iter<max_iter); // Solution is searched min=xf[0]; best=0; for (i=1;i<x.length;i++) { if (xf[i]<min) { best=i; min=xf[i]; } } // Argument is modified for (i=0;i<ctes.length;i++) ctes[i]=x[best][i]; // Fitness is returned return min; } /** * <p> * The method duplicate a set of double values * </p> * @param x The set of double values * @return The duplicate set */ double[] duplicate(double []x) { double[] result = new double[x.length]; for (int i=0;i<x.length;i++) result[i]=x[i]; return result; } }