//--------------------------------------------------------------------------------// // 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. // //--------------------------------------------------------------------------------// package xfuzzy.xfsg; import java.util.ArrayList; import xfuzzy.lang.CrispBlockCall; import xfuzzy.lang.FamiliarMemFunc; import xfuzzy.lang.LinguisticLabel; import xfuzzy.lang.ModuleCall; import xfuzzy.lang.ParamMemFunc; import xfuzzy.lang.Parameter; import xfuzzy.lang.RulebaseCall; import xfuzzy.lang.Specification; import xfuzzy.lang.SystemModule; import xfuzzy.lang.Variable; /** * Clase que incluye los m�todos "inicializarFLCs" e "inicializarCrispBlocks" * encargados de construir los objetos de tipo XfsgFLC y XfsgCrisp de una * especificaci�n XFL. Tambi�n incluye m�todos para determinar los tipos de * funciones de pertenencia y para calcular el segundo par�metro de ponderaci�n * usado en determinados m�todos de defuzzificacci�n. * * @author Jes�s Izquierdo Tena * @author Santiago S�nchez-Solano */ public class XfsgLeerXfl { // ATRIBUTOS private ArrayList<XfsgFLC> listaflc; private ArrayList<XfsgCrisp> listacrisp; private Specification spec; // El siguiente atributo es para las funciones de pertenencia de las // variables de entrada ordenadas private XfsgInOrderMemFunc[] inOrderMfInput; // El siguiente atributo es para las funciones de pertenencia de las // variables de salida ordenadas private XfsgInOrderMemFunc[] inOrderMfOutput; private XfsgSTPrintRules printer; // CONSTRUCTOR public XfsgLeerXfl(Specification spec) { this.spec = spec; listaflc = new ArrayList<XfsgFLC>(); listacrisp = new ArrayList<XfsgCrisp>(); } // M�TODOS GET public ArrayList<XfsgFLC> getlistaflc() { return listaflc; } public ArrayList<XfsgCrisp> getlistacrisp() { return listacrisp; } public Specification getspec() { return spec; } // M�TODOS SET public void setlistaflc(ArrayList<XfsgFLC> listaflc) { this.listaflc = listaflc; } public void setlistacrisp(ArrayList<XfsgCrisp> listacrisp) { this.listacrisp = listacrisp; } public void setspec(Specification spec) { this.spec = spec; } public void inicializarFLCs() { String num_mf = "", puntos_corte = "", pendientes = ""; SystemModule sistema = spec.getSystemModule(); RulebaseCall rbcarray[] = sistema.getRulebaseCalls(); try { for (int s = 0; s < rbcarray.length; s++) { RulebaseCall rbc = rbcarray[s]; String name = rbc.getName(); /* MFC */ // Crea el FLC XfsgFLC flc = new XfsgFLC(name, rbc); String defuzzy = rbc.getRulebase().getOperatorset().defuz .getFunctionName(); flc.setdefuzzy(defuzzy); String connective = rbc.getRulebase().getOperatorset().and .getFunctionName(); flc.setconnective(connective); Variable[] var_inputs = rbc.getRulebase().getInputs(); double min, max; int total_inputs = var_inputs.length; flc.setinputs(total_inputs); LinguisticLabel mf, mf2; int nmf; // Crea la estructura inOrderMfInput[i] (donde el �ndice i // direcciona las distintas variables de entrada) que contiene // una lista con las funciones de pertenencia ordenadas inOrderMfInput = new XfsgInOrderMemFunc[total_inputs]; for (int i = 0; i < total_inputs; i++) { inOrderMfInput[i] = new XfsgInOrderMemFunc(var_inputs[i]); inOrderMfInput[i].sort(); } /* Inicializa los MFCs */ for (int i = 0; i < total_inputs; i++) { String tipo_input = tipo_input(inOrderMfInput[i]); // System.out.println(tipo_input); if (tipo_input.equals("not found")) { XfsgError err = new XfsgError(); err.newWarning(12, inOrderMfInput[i].getVariable() .getName()); } else { nmf = inOrderMfInput[i].getSize(); // N�mero de funciones de pertenencia num_mf = new Integer(nmf).toString(); // Las pendientes que se calculan son las crecientes // Familia de tipo "triangular" if (tipo_input.equals("triangular")) { puntos_corte = "[ "; for (int j = 0; j < nmf; j++) { mf = inOrderMfInput[i].getMemFunc(j); double x1 = roundNum((mf.center() - mf.min()) / (mf.max() - mf.min())); puntos_corte += x1 + " "; } puntos_corte += "];\n"; pendientes = "[ "; for (int j = 0; j < nmf - 1; j++) { mf = inOrderMfInput[i].getMemFunc(j); mf2 = inOrderMfInput[i].getMemFunc(j + 1); double pendiente = roundNum((mf.max() - mf .min()) / (mf2.center() - mf.center())); pendientes += pendiente + " "; } pendientes += "];\n"; // Familia de tipo "sh_triangular" } else if (tipo_input.equals("sh_triangular")) { puntos_corte = "[ "; for (int j = 0; j < nmf; j++) { mf = inOrderMfInput[i].getMemFunc(j); double x1 = 0.0; x1 = roundNum((mf.get()[j] - mf.min()) / (mf.max() - mf.min())); puntos_corte += x1 + " "; } puntos_corte += "];\n"; pendientes = "[ "; for (int j = 0; j < nmf - 1; j++) { mf = inOrderMfInput[i].getMemFunc(j); double pendiente; pendiente = roundNum((mf.max() - mf.min()) / (mf.get()[j + 1] - mf.get()[j])); pendientes += pendiente + " "; } pendientes += "];\n"; // MFCs de tipo "triangle" } else if (tipo_input.equals("triangle")) { puntos_corte = "[ "; for (int j = 0; j < nmf; j++) { mf = inOrderMfInput[i].getMemFunc(j); double x1 = roundNum((mf.center() - mf.min()) / (mf.max() - mf.min())); puntos_corte += x1 + " "; } puntos_corte += "];\n"; pendientes = "[ "; for (int j = 0; j < nmf - 1; j++) { mf = inOrderMfInput[i].getMemFunc(j); mf2 = inOrderMfInput[i].getMemFunc(j + 1); double pendiente = roundNum((mf.max() - mf .min()) / (mf2.center() - mf.center())); pendientes += pendiente + " "; } pendientes += "];\n"; // MFCs de tipo "trapezoid" } else if (tipo_input.equals("sh_triangle")) { /* Puntos de Corte */ puntos_corte = "[ "; for (int j = 0; j < nmf; j++) { mf = inOrderMfInput[i].getMemFunc(j); double x1 = 0.0; if (j == 0) { if (mf.getClass().toString().contains( "trapezoid")) x1 = roundNum((mf.get()[2] - mf.min()) / (mf.max() - mf.min())); else if (mf.getClass().toString().contains( "triangle")) x1 = roundNum((mf.center() - mf.min()) / (mf.max() - mf.min())); } else if (j == nmf - 1) { if (mf.getClass().toString().contains( "trapezoid")) x1 = roundNum((mf.get()[1] - mf.min()) / (mf.max() - mf.min())); else if (mf.getClass().toString().contains( "triangle")) x1 = roundNum((mf.center() - mf.min()) / (mf.max() - mf.min())); } else { x1 = roundNum((mf.center() - mf.min()) / (mf.max() - mf.min())); } puntos_corte += x1 + " "; // System.out.println(puntos_corte); } puntos_corte += "];\n"; pendientes = "[ "; for (int j = 0; j < nmf - 1; j++) { mf = inOrderMfInput[i].getMemFunc(j); mf2 = inOrderMfInput[i].getMemFunc(j + 1); double pendiente = 0.0; if (j == 0) { if (mf.getClass().toString().contains( "trapezoid")) pendiente = roundNum((mf.max() - mf .min()) / (mf2.center() - mf.get()[2])); else if (mf.getClass().toString().contains( "triangle")) pendiente = roundNum((mf.max() - mf .min()) / (mf2.center() - mf.center())); } else if (j == nmf - 2) { if (mf2.getClass().toString().contains( "trapezoid")) pendiente = roundNum((mf.max() - mf .min()) / (mf2.get()[1] - mf.center())); else if (mf.getClass().toString().contains( "triangle")) pendiente = roundNum((mf.max() - mf .min()) / (mf2.center() - mf.center())); } else pendiente = roundNum((mf.max() - mf.min()) / (mf2.center() - mf.center())); pendientes += pendiente + " "; } pendientes += "];\n"; } flc.crear_a�adirMFC(num_mf, puntos_corte, pendientes); } } Variable[] var_outputs = rbc.getRulebase().getOutputs(); int total_outputs = var_outputs.length; flc.setoutputs(total_outputs); // Crea la estructura inOrderMfOutput[i] (donde el �ndice i // direcciona las distintas variables de salida) que contiene // una lista con las funciones de pertenencia ordenadas inOrderMfOutput = new XfsgInOrderMemFunc[total_outputs]; for (int i = 0; i < total_outputs; i++) { inOrderMfOutput[i] = new XfsgInOrderMemFunc(var_outputs[i]); inOrderMfOutput[i].sort(); } int maxn_fp = XfsgStaticMethods.CalculaMaximon_fp(rbc); // System.out.println(maxn_fp); int bitsn_fp = XfsgStaticMethods.ceillog2(maxn_fp); XfsgRulesMemData contenido = new XfsgRulesMemData(rbc .getNumberOfInputs() * bitsn_fp, rbc.getRulebase(), defuzzy); for (int i = 0; i < total_outputs; i++) { // code += "\n% RB" + (i+1) + "\n"; /* Nombre de las funciones y Puntos */ nmf = inOrderMfOutput[i].getSize(); XfsgOutData outdata = new XfsgOutData(nmf, defuzzy); // Obtiene las etiquetas String[] labels = new String[nmf]; // Calcula los valores para cada etiqueta seg�n el // m�todo de defuzzificaci�n. if (defuzzy.equals("FuzzyMean") || defuzzy.equals("MaxLabel")) { double[] values = new double[nmf]; for (int j = 0; j < nmf; j++) { mf = inOrderMfOutput[i].getMemFunc2(j); labels[j] = mf.getLabel(); min = mf.min(); max = mf.max(); values[j] = roundNum((mf.center() - min) / (max - min)); } outdata.setvalues(values); } else if (defuzzy.equals("WeightedFuzzyMean") || defuzzy.equals("Quality") || defuzzy.equals("GammaQuality")) { double[][] values2 = new double[nmf][2]; for (int j = 0; j < nmf; j++) { mf = inOrderMfOutput[i].getMemFunc2(j); labels[j] = mf.getLabel(); min = mf.min(); max = mf.max(); values2[j][0] = roundNum((mf.center() - min) / (max - min)); double gamma = 0; // Si el m�todo de defuzzificaci�n es GammaQuality // hay que calcular el valor de gamma. En los otros // casos no hace falta. if (defuzzy.equals("GammaQuality")) { gamma = rbc.getRulebase().getOperatorset().defuz .getSingleParameters()[0].value; } String clase = mf.getClass().toString(); if (clase.contains("singleton")) { XfsgError err = new XfsgError(); err.newWarning(10, "Defuzzification method: " + defuzzy + ". Membership function: " + mf.getClass() + "."); } else values2[j][1] = roundNum(calculateWeight2(mf, defuzzy, gamma)); } outdata.setvalues2(values2); } else if (defuzzy.equals("TakagiSugeno")) { double[][] values2 = new double[nmf][3]; for (int j = 0; j < nmf; j++) { mf = inOrderMfOutput[i].getMemFunc2(j); labels[j] = mf.getLabel(); min = mf.min(); max = mf.max(); Parameter[] params = ((ParamMemFunc) mf) .getParameters(); values2[j][0] = roundNum(params[0].value); values2[j][1] = roundNum(params[1].value); values2[j][2] = roundNum(params[2].value); } outdata.setvalues2(values2); } outdata.setlabels(labels); if (total_outputs != 1) outdata.setnombre("_" + var_outputs[i].getName()); XfsgPrintRulesFactory factory = new XfsgPrintRulesFactory( total_inputs); printer = factory.create(contenido, defuzzy, name, bitsn_fp, outdata, inOrderMfInput, i); printer.printRules(); outdata.setRB(printer.getRB()); outdata.setpesos(printer.getPesos()); // System.out.println(printer.getPesos()); if (i == 0) { flc.setgrados(printer.getGrados()); flc.setcomplete(printer.getComplete()); } flc.a�adirRB(outdata); } // flc.generaComponente(); listaflc.add(flc); } } catch (Exception e) { e.printStackTrace(); } } public void inicializarCrispBlocks() { // String code=""; int count = 0; SystemModule sistema = spec.getSystemModule(); ModuleCall[] call = sistema.getModuleCalls(); for (int i = 0; i < call.length; i++) if (call[i] instanceof CrispBlockCall) count++; CrispBlockCall cbcarray[] = new CrispBlockCall[count]; for (int i = 0, j = 0; i < call.length; i++) if (call[i] instanceof CrispBlockCall) { cbcarray[j] = (CrispBlockCall) call[i]; j++; } for (int i = 0; i < count; i++) { CrispBlockCall cbc = cbcarray[i]; XfsgCrisp c = new XfsgCrisp(cbc.getName(), cbc); c.setinputs(cbc.getNumberOfInputs()); c.setoutputs(cbc.getNumberOfOutputs()); // c.generaComponente(); listacrisp.add(c); } } private static double roundNum(double num) throws Exception { double valor = 0; valor = num; valor = valor * 10000; valor = java.lang.Math.round(valor); valor = valor / 10000; return valor; } /** * * @param p * Representa una funci�n de pertenencia * @param defuzzy * Cadena que indica el m�todo de defuzzificaci�n * @param gamma * Valor para la variable gamma en caso de que el metodo de * defuzzificaci�n sea GammaQuality, en otro caso, vale 0 * @return el valor del par�metro w para ponderar la salida de una regla */ private double calculateWeight2(LinguisticLabel p, String defuzzy, double gamma) { double universeRange = 0, w = 0; universeRange = p.max() - p.min(); try { if (defuzzy.equals("WeightedFuzzyMean")) { w = p.basis() / universeRange; } else if (defuzzy.equals("GammaQuality")) { double aux = Math.pow(p.basis(), gamma); w = (1 / aux) / universeRange; } else if (defuzzy.equals("Quality")) { w = (1 / p.basis()) / universeRange; } } catch (Exception e) { new XfsgError(5, defuzzy); // err.show(); return 0; } return w; } public String tipo_input(XfsgInOrderMemFunc input) { String res; // !!! CUIDADO: El orden es importante ya que, como est� definido // actualmente, si sh_triang_fam es true tambi�n es true triang_fam if (sh_triang_fam(input)) res = "sh_triangular"; else if (triang_fam(input)) res = "triangular"; else if (triang_libres_norm_trap(input)) res = "sh_triangle"; else if (triang_libres_norm(input)) res = "triangle"; else res = "not found"; return res; } private boolean triang_libres_norm(XfsgInOrderMemFunc input) { try { boolean res = true; int size = input.getSize(); // comprueba primero que todos son triangulos libres for (int i = 0; i < size && res; i++) { LinguisticLabel mf = input.getMemFunc(i); if (mf instanceof ParamMemFunc) { String clase = mf.getClass().toString(); if (!clase.contains("triangle")) res = false; } else res = false; } if (res) { // comprueba si est�n normalizados for (int i = 1; i < size && res; i++) { if (roundNum(input.getMemFunc(i).get()[0]) != roundNum(input .getMemFunc(i - 1).get()[1])) res = false; if (i == size - 1) { if (roundNum(input.getMemFunc(i).get()[1]) != roundNum(input .getMemFunc(i - 1).get()[2])) res = false; /* * if (roundNum(input.getMemFunc(i).get()[0]) != * roundNum(input .getMemFunc(i - 1).get()[1])) res = * false; */ } } } return res; } catch (Exception e) { return false; } } private boolean triang_libres_norm_trap(XfsgInOrderMemFunc input) { try { boolean res = true; boolean uno = false, dos = false, ambos = false; int size = input.getSize(); // comprueba que los extremos son trapecios y el restos triangulos // libres for (int i = 0; i < size && res; i++) { LinguisticLabel mf = input.getMemFunc(i); if (mf instanceof ParamMemFunc) { String clase = mf.getClass().toString(); if (i == 0) { if (clase.contains("trapezoid")) uno = true; else if (clase.contains("triangle")) uno = false; else res = false; } else if (i == size - 1) { if (clase.contains("trapezoid")) { dos = true; if (uno) ambos = true; } else if (clase.contains("triangle")) { dos = false; if (!uno) res = false; } else res = false; } else { if (!clase.contains("triangle")) res = false; } } else res = false; } if (res) { // comprueba si est�n normalizados (ambos extremos son // trapecios) if (ambos) { for (int i = 1; i < size && res; i++) { if (i == 1) { if (roundNum(input.getMemFunc(i).get()[0]) != roundNum(input .getMemFunc(i - 1).get()[2])) res = false; } else if (i == size - 1) { if (roundNum(input.getMemFunc(i).get()[0]) != roundNum(input .getMemFunc(i - 1).get()[1])) res = false; if (roundNum(input.getMemFunc(i).get()[1]) != roundNum(input .getMemFunc(i - 1).get()[2])) res = false; } else { if (roundNum(input.getMemFunc(i).get()[0]) != roundNum(input .getMemFunc(i - 1).get()[1])) res = false; } } } // comprueba si est�n normalizados (s�lo el primer extremo es // trapecio) else if (uno) { for (int i = 1; i < size && res; i++) { if (i == 1) { if (roundNum(input.getMemFunc(i).get()[0]) != roundNum(input .getMemFunc(i - 1).get()[2])) res = false; } else if (i == size - 1) { if (roundNum(input.getMemFunc(i).get()[0]) != roundNum(input .getMemFunc(i - 1).get()[1])) res = false; if (roundNum(input.getMemFunc(i).get()[1]) != roundNum(input .getMemFunc(i - 1).get()[2])) res = false; } else { if (roundNum(input.getMemFunc(i).get()[0]) != roundNum(input .getMemFunc(i - 1).get()[1])) res = false; } } } // comprueba si est�n normalizados (s�lo el segundo extremo es // trapecio) else if (dos) { for (int i = 1; i < size && res; i++) { if (i == 1) { if (roundNum(input.getMemFunc(i).get()[0]) != roundNum(input .getMemFunc(i - 1).get()[1])) res = false; } else if (i == size - 1) { if (roundNum(input.getMemFunc(i).get()[0]) != roundNum(input .getMemFunc(i - 1).get()[1])) res = false; if (roundNum(input.getMemFunc(i).get()[1]) != roundNum(input .getMemFunc(i - 1).get()[2])) res = false; } else { if (roundNum(input.getMemFunc(i).get()[0]) != roundNum(input .getMemFunc(i - 1).get()[1])) res = false; } } } } return res; } catch (Exception e) { return false; } } private boolean triang_fam(XfsgInOrderMemFunc input) { try { boolean res = true; int size = input.getSize(); // comprueba que todos son de tipo triangular, es decir, // triangulos pertenecientes a una familia, y no libres for (int i = 0; i < size && res; i++) { LinguisticLabel mf = input.getMemFunc(i); if (mf instanceof FamiliarMemFunc) { String clase = ((FamiliarMemFunc) mf).getFamily() .getFunctionName(); if (!clase.contains("triangular")) res = false; } else res = false; } return res; } catch (Exception e) { return false; } } private boolean sh_triang_fam(XfsgInOrderMemFunc input) { try { boolean res = true; int size = input.getSize(); // comprueba que todos son de tipo triangular, es decir, // triangulos pertenecientes a una familia, y no libres, // excepto los extremos, que deben ser trapecios. for (int i = 0; i < size && res; i++) { LinguisticLabel mf = input.getMemFunc(i); if (mf instanceof FamiliarMemFunc) { String clase = ((FamiliarMemFunc) mf).getFamily() .getFunctionName(); if (!clase.contains("sh_triangular")) res = false; } else res = false; } return res; } catch (Exception e) { return false; } } }