//--------------------------------------------------------------------------------// // COPYRIGHT NOTICE // //--------------------------------------------------------------------------------// // Copyright (c) 2012, Instituto de Microelectronica de Sevilla (IMSE-CNM) // // // // All rights reserved. // // // // Redistribution and use in source and binary forms, with or without // // modification, are permitted provided that the following conditions are met: // // // // * Redistributions of source code must retain the above copyright notice, // // this list of conditions and the following disclaimer. // // // // * Redistributions in binary form must reproduce the above copyright // // notice, this list of conditions and the following disclaimer in the // // documentation and/or other materials provided with the distribution. // // // // * Neither the name of the IMSE-CNM nor the names of its contributors may // // be used to endorse or promote products derived from this software // // without specific prior written permission. // // // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE // // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, // // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //--------------------------------------------------------------------------------// //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++// // ALGORITMOS DE CLUSTERING FIJO // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++// package xfuzzy.xfdm; import xfuzzy.lang.*; import xfuzzy.xfsl.*; public class XfdmFixedClustering extends XfdmAlgorithm { // Whether to give verbose output/debug mode public static final boolean debug = false; //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++// // CONSTANTES PUBLICAS // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++// public static final int HARD_CMEANS = 0; public static final int CMEANS = 1; public static final int GUSTAFSON_KESSEL = 2; public static final int GATH_GEVA = 3; //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++// // MIEMBROS PRIVADOS // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++// private int clustering; private int num_clusters; private int num_iterations; private double fuzziness; private double epsilon; private boolean learning; private int width; private double point[][]; private double cluster[][]; private double degree[][]; private double old_degree[][]; //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++// // CONSTRUCTOR // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++// //-------------------------------------------------------------// // Constructor por defecto // //-------------------------------------------------------------// public XfdmFixedClustering() { this.clustering = HARD_CMEANS; this.num_clusters = 10; this.num_iterations = 10; this.fuzziness = 2.0; this.epsilon = 0.01; this.learning = false; } //-------------------------------------------------------------// // Constructor desde la interfaz grafica // //-------------------------------------------------------------// public XfdmFixedClustering(int algorithm, int clusters, int iterations, double fuzziness, double epsilon, boolean lrn) { this.clustering = algorithm; this.num_clusters = clusters; this.num_iterations = iterations; this.fuzziness = fuzziness; this.epsilon = epsilon; this.learning = lrn; } //-------------------------------------------------------------// // Constructor desde el fichero de configuracion // //-------------------------------------------------------------// public XfdmFixedClustering(int algorithm, double[] param) { this.clustering = algorithm; this.num_clusters = (int) param[0]; this.num_iterations = (int) param[1]; this.fuzziness = param[2]; this.epsilon = param[3]; this.learning = (((int) param[4]) == 1); } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++// // METODOS PUBLICOS // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++// //=============================================================// // Metodos de acceso a la configuracion // //=============================================================// //-------------------------------------------------------------// // Obtiene el codigo del algoritmo de clustering elegido // //-------------------------------------------------------------// public int getClustering() { return this.clustering; } //-------------------------------------------------------------// // Asigna el codigo del algoritmo de clustering // //-------------------------------------------------------------// public void setClustering(int algorithm) { this.clustering = algorithm; } //-------------------------------------------------------------// // Obtiene el valor del numero de clusters elegido // //-------------------------------------------------------------// public int getNumberOfClusters() { return this.num_clusters; } //-------------------------------------------------------------// // Asigna el valor del numero de clusters // //-------------------------------------------------------------// public void setNumberOfClusters(int num) { this.num_clusters = num; } //-------------------------------------------------------------// // Obtiene el valor del indice de borrosidad // //-------------------------------------------------------------// public double getFuzziness() { return this.fuzziness; } //-------------------------------------------------------------// // Asigna el valor del indice de borrosidad // //-------------------------------------------------------------// public void setFuzziness(double fuzz) { this.fuzziness = fuzz; } //-------------------------------------------------------------// // Obtiene el valor del numero maximo de iteraciones // //-------------------------------------------------------------// public int getNumberOfIterations() { return this.num_iterations; } //-------------------------------------------------------------// // Asigna el valor del numero maximo de iteraciones // //-------------------------------------------------------------// public void setNumberOfIterations(int num) { this.num_iterations = num; } //-------------------------------------------------------------// // Obtiene el valor del minimo grado de variacion // //-------------------------------------------------------------// public double getEpsilon() { return this.epsilon; } //-------------------------------------------------------------// // Asigna el valor del minimo grado de variacion // //-------------------------------------------------------------// public void setEpsilon(double degree) { this.epsilon = degree; } //-------------------------------------------------------------// // Obtiene el valor de la opcion de aprendizaje // //-------------------------------------------------------------// public boolean getLearning() { return this.learning; } //-------------------------------------------------------------// // Asigna el valor de la opcion de aprendizaje // //-------------------------------------------------------------// public void setLearning(boolean lrn) { this.learning = lrn; } //=============================================================// // Metodos de desarrollo de XfdmAlgorithm // //=============================================================// //-------------------------------------------------------------// // Obtiene un duplicado del objeto // //-------------------------------------------------------------// public Object clone() { return new XfdmFixedClustering(clustering, num_clusters, num_iterations, fuzziness, epsilon, learning); } //-------------------------------------------------------------// // Obtiene el nombre del algoritmo // //-------------------------------------------------------------// public String toString() { switch(clustering) { case HARD_CMEANS: return "Fixed Clustering (Hard-CMeans Algorithm)"; case CMEANS: return "Fixed Clustering (CMeans Algorithm)"; case GUSTAFSON_KESSEL:return "Fixed Clustering (Gustafson-Kessel Algorithm)"; case GATH_GEVA: return "Fixed Clustering (Gath-Geva Algorithm)"; default: return ""; } } //-------------------------------------------------------------// // Representacion en el fichero de configuracion // //-------------------------------------------------------------// public String toCode() { String code = "xfdm_algorithm("; switch(clustering) { case HARD_CMEANS: code += "HardCMeans,"; break; case CMEANS: code += "CMeans,"; break; case GUSTAFSON_KESSEL: code += "GustafsonKessel,"; break; case GATH_GEVA: code += "GathGeva,"; break; } code += " "+num_clusters+", "+num_iterations+", "+fuzziness+", "+epsilon; code += ", "+(learning? "1" : "0")+" )"; return code; } //-------------------------------------------------------------// // Metodo que construye el sistema a partir de los datos // //-------------------------------------------------------------// public void compute(Specification spec,XfdmConfig config) throws XflException { this.spec = spec; this.config = config; this.pattern = config.getPatterns(); this.opset = createOperatorSet(); spec.addOperatorset(opset); this.inputtype = createInputTypes(); for(int i=0; i<inputtype.length; i++) spec.addType(inputtype[i]); this.outputtype = createOutputTypes(); for(int i=0; i<outputtype.length; i++) spec.addType(outputtype[i]); this.rulebase = createEmptyRulebase(); this.spec.addRulebase(rulebase); createSystemStructure(); this.spec.setModified(true); this.pattern.setRanges(spec); this.width = this.inputtype.length + this.outputtype.length; this.point = createPointsFromPatterns(); this.cluster = createClusters(); this.degree = new double[point.length][cluster.length]; this.old_degree = new double[point.length][cluster.length]; clustering(); createContent(); if(learning) learning(); } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++// // METODOS PRIVADOS // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++// //=============================================================// // Metodos que desarrollan el algoritmo // //=============================================================// //-------------------------------------------------------------// // Aplica el algoritmo de clustering elegido // //-------------------------------------------------------------// private void clustering() { switch(clustering) { case HARD_CMEANS: HardCMeans(); break; case CMEANS: CMeans(); break; case GUSTAFSON_KESSEL: GustafsonKessel(); break; case GATH_GEVA: GathGeva(); break; } } //-------------------------------------------------------------// // Obtiene el conjunto normalizado de patrones // //-------------------------------------------------------------// private double[][] createPointsFromPatterns() { int length = this.pattern.input.length; double point[][] = new double[length][width]; for(int i=0; i<length; i++) for(int j=0; j<width; j++) { if(j<inputtype.length) { point[i][j] = pattern.input[i][j]; } else { point[i][j] = pattern.output[i][j-inputtype.length]; } } return point; } //-------------------------------------------------------------// // Obtiene una representacion inicial aleatoria de los clusters// //-------------------------------------------------------------// private double[][] createClusters() { int width = inputtype.length + outputtype.length; double cl[][] = new double[num_clusters][width]; for(int j=0; j<inputtype.length; j++) { double min = inputtype[j].getUniverse().min(); double max = inputtype[j].getUniverse().max(); for(int i=0; i<num_clusters; i++) { cl[i][j] = min + Math.random()*(max-min); } } for(int j=0; j<outputtype.length; j++) { double min = outputtype[j].getUniverse().min(); double max = outputtype[j].getUniverse().max(); for(int i=0; i<num_clusters; i++) { cl[i][inputtype.length+j] = min + Math.random()*(max-min); } } return cl; } //-------------------------------------------------------------// // Intercambia old_cluster y cluster // //-------------------------------------------------------------// private void setOldDegree() { double[][] aux; aux = old_degree; old_degree = degree; degree = aux; } //-------------------------------------------------------------// // Calcula la variacion de clusters entre dos iteraciones // //-------------------------------------------------------------// private double computeVariation() { double max = 0; for(int i=0; i<degree.length; i++) for(int j=0; j<degree[i].length; j++) { double diff = degree[i][j] - old_degree[i][j]; if(diff < 0) diff = -diff; if(diff > max) max = diff; } return max; } //-------------------------------------------------------------// // Calcula la distancia euclidea entre dos puntos (al cuadrado)// //-------------------------------------------------------------// private double distance(double[] x, double[] y) { double dist = 0; for(int i=0; i<x.length; i++) dist += (x[i]-y[i])*(x[i]-y[i]); return dist; } //=============================================================// // Metodos que desarrollan el algoritmo HardCMeans // //=============================================================// //-------------------------------------------------------------// // Algoritmo HardCMeans // //-------------------------------------------------------------// private void HardCMeans() { double var = epsilon+1; for(int iter=0; iter<num_iterations && (epsilon<0 || var>epsilon); iter++) { setOldDegree(); HardCMeansUpdateDegree(); HardCMeansUpdateClusters(); var = computeVariation(); } } //-------------------------------------------------------------// // Actualiza el grado de pertenencia de los puntos a los // // clusters // //-------------------------------------------------------------// private void HardCMeansUpdateDegree() { for(int i=0; i<point.length; i++) { double min = distance(point[i],cluster[0]); int index = 0; for(int j=1; j<cluster.length; j++) { double dist = distance(point[i],cluster[j]); if(dist < min) { min = dist; index = j; } } for(int j=0; j<cluster.length; j++) { degree[i][j] = (j==index? 1.0 : 0.0); } } } //-------------------------------------------------------------// // Actualiza el valor de los clusters // //-------------------------------------------------------------// private void HardCMeansUpdateClusters() { for(int i=0; i<cluster.length; i++) { for(int j=0; j<cluster[i].length; j++) cluster[i][j] = 0.0; int sum = 0; for(int k=0; k<degree.length; k++) if(degree[k][i] == 1.0) { sum++; for(int j=0; j<cluster[i].length; j++) cluster[i][j] += point[k][j]; } if(sum != 0) { for(int j=0; j<cluster[i].length; j++) { cluster[i][j] = cluster[i][j]/sum; } } else { /// Instead using 0 and center, we place the "empty" cluster at the last point for(int j=0; j<cluster[i].length; j++) { cluster[i][j] = point[point.length-1][j]; } } } } //=============================================================// // Metodos que desarrollan el algoritmo CMeans // //=============================================================// //-------------------------------------------------------------// // Algoritmo CMeans // //-------------------------------------------------------------// private void CMeans() { double var = epsilon+1; for(int iter=0; iter<num_iterations && (epsilon<0 || var>epsilon); iter++) { setOldDegree(); CMeansUpdateDegree(); updateClusters(); var = computeVariation(); } } //-------------------------------------------------------------// // Actualiza el grado de pertenencia de los puntos a los // // clusters // //-------------------------------------------------------------// private void CMeansUpdateDegree() { double dist[] = new double[cluster.length]; for(int i=0; i<point.length; i++) { for(int j=0; j<cluster.length; j++) dist[j] = distance(point[i],cluster[j]); updateDegree(i,dist); } } //=============================================================// // Metodos que desarrollan el algoritmo de Gustafson-Kessel // //=============================================================// //-------------------------------------------------------------// // Algoritmo Gustafson-Kessel // //-------------------------------------------------------------// private void GustafsonKessel() { double[][][] covar = new double[cluster.length][width][width]; double[][][] inverse = new double[cluster.length][width][width]; double[] determ = new double[cluster.length]; CMeansUpdateDegree(); double var = epsilon+1; for(int iter=0; iter<num_iterations && (epsilon<0 || var>epsilon); iter++) { updateClusters(); updateCovariance(covar); updateDeterminant(covar, determ); updateInverse(covar, inverse); setOldDegree(); GustafsonKesselUpdateDegree(determ, inverse); var = computeVariation(); } } //-------------------------------------------------------------// // Calcula la distancia segun el algoritmo de GustafsonKessel // //-------------------------------------------------------------// private double distanceGK(double[] x,double[] y,double determ,double[][] inv) { double alpha = Math.pow(determ,1/width); double dist = 0; for(int i=0; i<width; i++) for(int j=0; j<width; j++) { dist += (x[i]-y[i])*inv[i][j]*(x[j]-y[j]); } return alpha*dist; } //-------------------------------------------------------------// // Actualiza el grado de pertenencia de los puntos a los // // clusters // //-------------------------------------------------------------// private void GustafsonKesselUpdateDegree(double[] determ,double[][][] inverse){ double dist[] = new double[cluster.length]; for(int i=0; i<point.length; i++) { for(int j=0; j<cluster.length; j++) { dist[j] = distanceGK(point[i],cluster[j],determ[j],inverse[j]); } updateDegree(i,dist); } } //=============================================================// // Metodos que desarrollan el algoritmo de Gath-Geva // //=============================================================// //-------------------------------------------------------------// // Algoritmo Gath-Geva // //-------------------------------------------------------------// private void GathGeva() { double[][][] covar = new double[cluster.length][width][width]; double[][][] inverse = new double[cluster.length][width][width]; double[] determ = new double[cluster.length]; double[] rho = new double[cluster.length]; CMeansUpdateDegree(); double var = epsilon+1; for(int iter=0; iter<num_iterations && (epsilon<0 || var>epsilon); iter++) { if ( debug ) System.out.println("ITERACION "+iter); updateClusters(); if ( debug ) debug("CLUSTERS",cluster); updateCovariance(covar); if ( debug ) debug("COVARIANZA",covar); updateDeterminant(covar, determ); if ( debug ) debug("DETERMINANTE",determ); updateInverse(covar, inverse); if ( debug ) debug("INVERSA",inverse); updateRho(rho); if ( debug ) debug("RHO",rho); setOldDegree(); GathGevaUpdateDegree(rho, determ, inverse); if ( debug ) debug("PERTENENCIA",degree); var = computeVariation(); } } //-------------------------------------------------------------// //-------------------------------------------------------------// private void debug(String matrix, double[][] cl) { System.out.println(""); System.out.println(matrix); for(int i=0; i<cl.length; i++) { for(int j=0; j<cl[i].length; j++) System.out.print(""+cl[i][j]+" "); System.out.println(""); } System.out.println(""); } private void debug(String vector, double[] v) { System.out.println(vector); for(int i=0; i<v.length; i++) System.out.println(""+v[i]+" "); System.out.println(""); } private void debug(String matrix, double[][][] cl) { System.out.println(""); System.out.println(matrix); for(int i=0; i<cl.length; i++) { System.out.println("Matriz "+i); for(int j=0; j<width; j++) { for(int k=0; k<width; k++) System.out.print(""+cl[i][j][k]+" "); System.out.println(""); } System.out.println(""); } System.out.println(""); } //-------------------------------------------------------------// // Actualiza el vector Rho // //-------------------------------------------------------------// private void updateRho(double[] rho) { for(int i=0; i<cluster.length; i++) { double sum = 0.0; for(int j=0; j<point.length; j++) sum += degree[j][i]; rho[i] = sum/point.length; } } //-------------------------------------------------------------// // Calcula la distancia segun el algoritmo de GathGeva // //-------------------------------------------------------------// private double distanceGG(double[] x,double[] y,double alpha,double[][] inv) { double dist = 0; for(int i=0; i<width; i++) for(int j=0; j<width; j++) { dist += (x[i]-y[i])*inv[i][j]*(x[j]-y[j]); } return alpha*Math.exp(dist/2); } //-------------------------------------------------------------// // Actualiza el grado de pertenencia de los puntos a los // // clusters // //-------------------------------------------------------------// private void GathGevaUpdateDegree(double[] rho,double[] determ, double[][][] inverse) { double dist[] = new double[cluster.length]; double alpha[] = new double[cluster.length]; for(int j=0; j<cluster.length; j++) alpha[j] = Math.sqrt(determ[j])/rho[j]; for(int i=0; i<point.length; i++) { for(int j=0; j<cluster.length; j++) { dist[j] = distanceGG(point[i],cluster[j],alpha[j],inverse[j]); } updateDegree(i,dist); } } //=============================================================// // Metodos auxiliares de calculo de matrices // //=============================================================// //-------------------------------------------------------------// // Actualiza el valor de los clusters // //-------------------------------------------------------------// private void updateClusters() { for(int i=0; i<cluster.length; i++) { for(int j=0; j<cluster[i].length; j++) cluster[i][j] = 0.0; double sum = 0; for(int k=0; k<degree.length; k++) { double alpha = Math.pow(degree[k][i],fuzziness); sum += alpha; for(int j=0; j<cluster[i].length; j++) { cluster[i][j] += alpha*point[k][j]; } } if(sum != 0) { for(int j=0; j<cluster[i].length; j++) { cluster[i][j] = cluster[i][j]/sum; } } else { /// Instead of centering at 0, we center the "empty" cluster at the last point for(int j=0; j<cluster[i].length; j++) { cluster[i][j] = point[point.length-1][j]; } } } } //-------------------------------------------------------------// // Calcula la covarianza // //-------------------------------------------------------------// private void updateCovariance(double[][][] covar) { double alpha = 0.0; double denom[][] = new double[width][width]; for(int i=0; i<cluster.length; i++) { double num = 0.0; for(int l=0;l<width; l++) for(int m=0;m<width; m++) { denom[l][m] = 0.0; } for(int j=0; j<point.length; j++) { alpha = Math.pow(degree[j][i],fuzziness); for(int l=0;l<width; l++) for(int m=0;m<width; m++) { double beta = (point[j][l] - cluster[i][l])*(point[j][m] - cluster[i][m]); denom[l][m] += alpha*beta; } num += alpha; } for(int l=0;l<width; l++) for(int m=0;m<width; m++) { covar[i][l][m] = denom[l][m]/num; } } } //-------------------------------------------------------------// // Calcula los determinantes de las matrices de covarianza // //-------------------------------------------------------------// private void updateDeterminant(double[][][] covar, double[] determ) { for(int c=0; c<cluster.length; c++) { double[][] temp = new double[width][width]; for(int i=0;i<width;i++) for(int j=0;j<width;j++) temp[i][j]=covar[c][i][j]; for(int k=0; k<(temp.length-1); k++) for(int i=k+1; i<temp.length; i++) for(int j=k+1; j<temp.length; j++) temp[i][j]-=temp[i][k]*temp[k][j]/temp[k][k]; double determinant = 1.0; for(int i=0; i<temp.length; i++) determinant*=temp[i][i]; determ[c] = determinant; } } //-------------------------------------------------------------// // Calcula las matrices inversas de las covarianzas // //-------------------------------------------------------------// private void updateInverse(double[][][] covar, double[][][] inverse) { for(int cl=0; cl<cluster.length; cl++) { double[][] temp = new double[width][width]; for(int i=0;i<width;i++) for(int j=0;j<width;j++) temp[i][j]=covar[cl][i][j]; double[][] b=new double[width][width]; double[][] c=new double[width][width]; for(int i=0; i<width; i++) for(int j=0;j<width;j++) { b[i][j]=0; c[i][j]=0;} for(int i=0; i<width; i++) b[i][i]=1.0; for(int k=0; k<width-1; k++) { for(int i=k+1; i<width; i++) { for(int s=0; s<width; s++) b[i][s]-=temp[i][k]*b[k][s]/temp[k][k]; for(int j=k+1; j<width; j++) temp[i][j]-=temp[i][k]*temp[k][j]/temp[k][k]; } } for(int s=0; s<width; s++) { c[width-1][s]=b[width-1][s]/temp[width-1][width-1]; for(int i=width-2; i>=0; i--) { c[i][s]=b[i][s]/temp[i][i]; for(int k=width-1; k>i; k--) c[i][s]-=temp[i][k]*c[k][s]/temp[i][i]; } } for(int i=0;i<width;i++) for(int j=0;j<width;j++) inverse[cl][i][j]=c[i][j]; } } //-------------------------------------------------------------// // Actualiza los grados de pertenencia de un punto teniendo en // // cuenta la distancia a los clusters // //-------------------------------------------------------------// private void updateDegree(int i, double[] dist) { double pow = 2/(fuzziness-1); boolean crisp = false; for(int j=0; j<cluster.length; j++) if(dist[j] == 0) crisp = true; if(crisp) { for(int j=0; j<cluster.length; j++) { if(dist[j] == 0) degree[i][j] = 1.0; else degree[i][j] = 0.0; } return; } for(int j=0; j<cluster.length; j++) { if(Double.isNaN(dist[j])) { degree[i][j] = 0; continue; } double sum = 0; for(int k=0; k<cluster.length; k++) { if(!Double.isNaN(dist[k])) sum += Math.pow((dist[j]/dist[k]), pow); } degree[i][j] = 1/sum; } int NaNcount = 0; double sum = 0; for(int j=0; j<cluster.length; j++) { if(Double.isNaN(degree[i][j])) NaNcount++; else sum += degree[i][j]; } if(NaNcount != 0) for(int j=0; j<cluster.length; j++) { if(Double.isNaN(degree[i][j])) degree[i][j] = (1-sum)/NaNcount; } } //=============================================================// // Metodos que generan el contenido del sistema // //=============================================================// //-------------------------------------------------------------// // Genera el contenido del sistema a partir de los clusters // //-------------------------------------------------------------// private void createContent() { for(int i=0; i<inputtype.length; i++) createBells(inputtype[i],i); for(int i=0; i<outputtype.length; i++) { switch(config.systemstyle.defuz) { case XfdmSystemStyle.FUZZYMEAN: createSingletons(outputtype[i],inputtype.length + i); break; case XfdmSystemStyle.WEIGHTED: createBells(outputtype[i],inputtype.length + i); break; case XfdmSystemStyle.TAKAGI: createParametric(outputtype[i],inputtype.length + i); break; } } createRules(); } //-------------------------------------------------------------// // Genera las reglas correspondientes a los clusters // //-------------------------------------------------------------// private void createRules() { Variable ivar[] = rulebase.getInputs(); Variable ovar[] = rulebase.getOutputs(); int is = Relation.IS; for(int i=0; i<cluster.length; i++) { LinguisticLabel pmf = ivar[0].getType().getAllMembershipFunctions()[i]; Relation rel = Relation.create(is,null,null,ivar[0],pmf,rulebase); for(int j=1; j<ivar.length; j++) { pmf = ivar[j].getType().getAllMembershipFunctions()[i]; Relation nrel = Relation.create(is,null,null,ivar[j],pmf,rulebase); rel = Relation.create(Relation.AND,rel,nrel,null,null,rulebase); } Rule rule = new Rule(rel); for(int j=0; j<ovar.length; j++) { pmf = ovar[j].getType().getAllMembershipFunctions()[i]; rule.add(new Conclusion(ovar[j],pmf,rulebase)); } rulebase.addRule(rule); } } //-------------------------------------------------------------// // Genera el conjunto de tipos de variables de entrada // //-------------------------------------------------------------// protected Type[] createInputTypes() { Type itp[] = new Type[config.numinputs]; for(int i=0; i<config.numinputs; i++) { String tname = "Tin"+i; Universe universe = null; if(config.commonstyle.isUniverseDefined()) { try { universe=new Universe(config.commonstyle.min,config.commonstyle.max);} catch(Exception ex) {} } if(config.inputstyle != null && config.inputstyle.length > i && config.inputstyle[i] != null) { tname = "T"+config.inputstyle[i].name; if(config.inputstyle[i].isUniverseDefined()) { try { universe=new Universe(config.inputstyle[i].min,config.inputstyle[i].max); } catch(Exception ex) { } } else { universe = null; } } if(universe == null) universe = pattern.getUniverse(i,true); itp[i] = new Type(tname,universe); } return itp; } //-------------------------------------------------------------// // Genera el conjunto de tipos de variables de salida // //-------------------------------------------------------------// private Type[] createOutputTypes() { Type otp[] = new Type[config.numoutputs]; for(int i=0; i<config.numoutputs; i++) { String tname = "T"+config.systemstyle.outputname; if(config.numoutputs>1) tname += ""+i; otp[i] = new Type(tname,pattern.getUniverse(i,false)); } return otp; } //=============================================================// // Metodos que generan las funciones de pertenencia // //=============================================================// //-------------------------------------------------------------// // Crea un conjunto de singularidades // //-------------------------------------------------------------// private void createSingletons(Type type, int index) { Universe u = type.getUniverse(); for(int cl=0; cl<cluster.length; cl++) { ParamMemFunc pmf = new pkg.xfl.mfunc.singleton(); pmf.set("mf"+cl, u); pmf.set( cluster[cl][index] ); try { type.add(pmf); } catch(XflException e) {} } } //-------------------------------------------------------------// // Crea un conjunto de funciones parametricas // //-------------------------------------------------------------// private void createParametric(Type type, int index) { Universe u = type.getUniverse(); double param[] = new double[inputtype.length+1]; for(int i=0; i<cluster.length; i++) { ParamMemFunc pmf = new pkg.xfl.mfunc.parametric(); pmf.set("mf"+i, u); param[0] = cluster[i][index]; try { pmf.set(param); type.add(pmf); } catch(XflException ex) {} } } //-------------------------------------------------------------// // Crea un conjunto de campanas // //-------------------------------------------------------------// private void createBells(Type type, int index) { Universe u = type.getUniverse(); double param[] = new double[2]; for(int cl=0; cl<cluster.length; cl++) { param[0] = cluster[cl][index]; param[1] = getWidthForMF(type,index,cl); ParamMemFunc pmf = new pkg.xfl.mfunc.bell(); pmf.set("mf"+cl, u); try { pmf.set(param); type.add(pmf); } catch(XflException ex) {} } } //-------------------------------------------------------------// // Obtiene la anchura de una MF en funcion de los grados de // // pertenencia de los puntos a cada cluster // //-------------------------------------------------------------// private double getWidthForMF(Type type, int var, int cl) { double min = type.getUniverse().min(); double max = type.getUniverse().max(); double center = cluster[cl][var]; double dist1 = max-min; boolean test1 = false; for(int i=0; i<point.length; i++) { double mu = degree[i][cl]; double x = point[i][var]; if(mu>0.3) continue; test1 = true; double d = (x>center? x-center : center-x); if(d < dist1) dist1 = d; } double dist2 = 0; boolean test2 = false; for(int i=0; i<point.length; i++) { double mu = degree[i][cl]; double x = point[i][var]; if(mu<0.3) continue; test2 = true; double d = (x>center? x-center : center-x); if(d > dist2) dist2 = d; } double dist = 0; if(test1 & test2) dist = (dist1+dist2)/2; else if(test1) dist = dist1; else if(test2) dist = dist2; if(dist==0) return (max-min)/100; return dist; } //-------------------------------------------------------------// // Ajusta las salidas del sistema con el algoritmo de // // Marquardt-Levenberg // //-------------------------------------------------------------// private void learning() { double param[] = { 0.1, 10.0, 0.1}; int alg = XfslAlgorithm.MARQUARDT; int err = XfslErrorFunction.MEAN_SQUARE_ERROR; int end = XfslEndCondition.TRN_VAR; XfslConfig xfslconfig = new XfslConfig(); try { xfslconfig.trainingfile = config.patternfile; xfslconfig.algorithm = XfslAlgorithm.create(alg,param); xfslconfig.errorfunction = new XfslErrorFunction(err); xfslconfig.endcondition.setLimit(end,0.001); xfslconfig.addSetting("ANY.ANY.ANY",false); for(int i=0; i<outputtype.length; i++) { xfslconfig.addSetting(outputtype[i].getName()+".ANY.ANY",true); } XfslThread lrnthread = new XfslThread(spec,xfslconfig); lrnthread.run(); } catch (Exception ex) { } } }