//--------------------------------------------------------------------------------// // 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.xfsw; import xfuzzy.lang.*; import java.io.*; /** * Generador del fichero de c�digo de la descripci�n C * * @author Francisco Jos� Moreno Velo * */ public class XfswCCode { //----------------------------------------------------------------------------// // MIEMBROS PRIVADOS // //----------------------------------------------------------------------------// /** * Sistema difuso a compilar */ private Specification spec; /** * Directorio base para la creaci�n del archivo */ private File dir; /** * Clase que analiza los funciones utilizadas en el sistema */ private XfswDataUsage usage; //----------------------------------------------------------------------------// // CONSTRUCTOR // //----------------------------------------------------------------------------// /** * Constructor */ public XfswCCode(Specification spec, File dir) { this.spec = spec; this.dir = dir; this.usage = new XfswDataUsage(spec); } //----------------------------------------------------------------------------// // M�TODOS P�BLICOS EST�TICOS // //----------------------------------------------------------------------------// /** * Genera el fichero C asociado al sistema difuso */ public static final String create(Specification spec,File dir) throws XflException { XfswCCode creator = new XfswCCode(spec,dir); creator.createFile(); return creator.getMessage(); } //----------------------------------------------------------------------------// // M�TODOS P�BLICOS // //----------------------------------------------------------------------------// /** * M�todo que describe el resultado */ public String getMessage() { File file = new File(dir,spec.getName()+".c"); return file.getAbsolutePath(); } /** * Genera el fichero "sistema.c" */ public void createFile() throws XflException { File file = new File(dir,spec.getName()+".c"); try { OutputStream ostream = new FileOutputStream(file); PrintStream stream = new PrintStream(ostream); writeHeading(stream); writeSource(stream); stream.close(); } catch(IOException e) {} } //----------------------------------------------------------------------------// // M�TODOS PRIVADOS // //----------------------------------------------------------------------------// //----------------------------------------------------------------------------// // M�todos que generan el contenido del fichero // //----------------------------------------------------------------------------// /** * Genera el c�digo de cabecera */ private void writeHeading(PrintStream stream) { stream.println("/*++++++++++++++++++++++++++++++++++++++++++++++++++++++*/"); stream.println("/* */"); stream.println(complete("/* File: "+spec.getName()+".c")); stream.println("/* */"); stream.println("/* Author: Automatically generated by Xfuzzy */"); stream.println("/* */"); stream.println("/*++++++++++++++++++++++++++++++++++++++++++++++++++++++*/"); stream.println(); } /** * Genera el contenido del fichero */ private void writeSource(PrintStream stream) throws XflException { String name = spec.getName(); Operatorset[] opset = spec.getOperatorsets(); Type[] type = spec.getTypes(); Rulebase[] base = spec.getRulebases(); CrispBlock[] crisp = spec.getCrispBlockSet().getBlocks(); stream.println("#include <stdio.h>"); stream.println("#include <math.h>"); stream.println("#include \""+name+".h\""); stream.println(); if(usage.isComputeUsed()) createComputeFunction(stream); Family[] famlist = usage.getFamilyList(); for(int i=0; i<famlist.length; i++) createFamilyCode(stream, famlist[i]); ParamMemFunc[] mflist = usage.getMFList(); for(int i=0; i<mflist.length; i++) createMFCode(stream, mflist[i]); for(int i=0; i<opset.length; i++) createOperatorSetCode(stream,opset[i]); for(int i=0; i<type.length; i++) createTypeCode(stream,type[i]); for(int i=0; i<base.length; i++) createRulebaseCode(stream,base[i]); for(int i=0; i<crisp.length; i++) createCrispBlockCode(stream,crisp[i]); createSystemModuleCode(stream); } //----------------------------------------------------------------------------// // M�todos que generan el c�digo de las familias // //----------------------------------------------------------------------------// private void createComputeFunction(PrintStream stream) { stream.println("/*======================================================*/"); stream.println("/* Common function to compute a fuzzy number */"); stream.println("/*======================================================*/"); stream.println(); stream.println("static double compute(FuzzyNumber fn,double x) {"); stream.println(" int length = fn.length;"); stream.println(" int i;"); stream.println(" double imp = fn.imp(fn.degree[0],fn.conc[0].equal(x));"); stream.println(" double mu = imp"); stream.println(); stream.println(" for(i=1; i<length; i++) {"); stream.println(" imp = fn.imp(fn.degree[i],fn.conc[i].equal(x));"); stream.println(" mu = fn.also(mu,imp);"); stream.println(" }"); stream.println(" return mu;"); stream.println("}"); stream.println(); } //----------------------------------------------------------------------------// // M�todos que generan el c�digo de las familias // //----------------------------------------------------------------------------// /** * Descripci�n de una familia de funciones de pertenencia */ private void createFamilyCode(PrintStream stream, Family fam) throws XflException { String classname = usage.getFamilyName(fam); String equal = fam.getEqualCCode(); if(equal==null || equal.length()==0) throw new XflException(); stream.println("/*======================================================*/"); stream.println(complete("/* MembershipFunction "+classname)); stream.println("/*======================================================*/"); stream.println(); stream.println("/*------------------------------------------------------*/"); stream.println("/* Function to compute an equal relationship */"); stream.println("/*------------------------------------------------------*/"); stream.println(); stream.print("static double "+classname+"_equal(double x"); createFamVariableCode(stream, fam); stream.println(") {"); stream.print(equal); stream.println("}"); stream.println(); if(usage.isFamilyGreqUsed( classname )) { String greq = fam.getGreqCCode(); stream.println("/*------------------------------------------------------*/"); stream.println("/* Function to compute a greater_or_equal relationship */"); stream.println("/*------------------------------------------------------*/"); stream.println(); stream.print("static double "+classname+"_greq(double x, "); createFamVariableCode(stream,fam); stream.println(") {"); if(greq != null && greq.length()>0) { stream.print(greq); } else { stream.println(" double _y, _mu, _degree=0;"); stream.println(" for(_y = min; _y <= x ; _y += step) {"); stream.print(" _mu = "+classname+"_equal(_y,"); createFamVariableCallCode(stream,fam); stream.println(");"); stream.println(" if( _mu > _degree) _degree = _mu;"); stream.println(" }"); stream.println(" return _degree;"); } stream.println("}"); stream.println(); } if(usage.isFamilySmeqUsed( classname )) { String smeq = fam.getSmeqCCode(); stream.println("/*------------------------------------------------------*/"); stream.println("/* Function to compute a smaller_or_equal relationship */"); stream.println("/*------------------------------------------------------*/"); stream.println(); stream.print("static double "+classname+"_smeq(double x, "); createFamVariableCode(stream,fam); stream.println(") {"); if(smeq != null && smeq.length()>0) { stream.print(smeq); } else { stream.println(" double _y, _mu, _degree=0;"); stream.println(" for(_y = max; _y >= x ; _y -= step) {"); stream.print( " _mu = "+classname+"_equal(_y,"); createFamVariableCallCode(stream,fam); stream.println(");"); stream.println(" if( _mu > _degree) _degree = _mu;"); stream.println(" }"); stream.println(" return _degree;"); } stream.println("}"); stream.println(); } if(usage.isFamilyCenterUsed( classname )) { String center = fam.getCenterCCode(); stream.println("/*------------------------------------------------------*/"); stream.println("/* Function to compute the center of the MF */"); stream.println("/*------------------------------------------------------*/"); stream.println(); stream.print("static double "+classname+"_center("); createFamVariableCode(stream,fam); stream.println(") {"); if(center != null && center.length()>0) { stream.print(center); } else { stream.println(" return 0;"); } stream.println("}"); stream.println(); } if(usage.isFamilyBasisUsed( classname )) { String basis = fam.getBasisCCode(); stream.println("/*------------------------------------------------------*/"); stream.println("/* Function to compute the basis of the MF */"); stream.println("/*------------------------------------------------------*/"); stream.println(); stream.print("static double "+classname+"_basis("); createFamVariableCode(stream,fam); stream.println(") {"); if(basis != null && basis.length()>0) { stream.print(basis); } else { stream.println(" return 0;"); } stream.println("}"); stream.println(); } if(usage.isFamilyParamUsed( classname )) { Parameter[] single = fam.getSingleParameters(); String listname = fam.getParamListName(); stream.println("/*------------------------------------------------------*/"); stream.println("/* Function to get a parameter of the MF */"); stream.println("/*------------------------------------------------------*/"); stream.println(); stream.print("static double "+classname+"_param(int _i, "); createFamVariableCode(stream,fam); stream.println(") {"); for(int i=0; i<single.length; i++) { stream.println(" if(_i == "+i+") return "+single[i].getName()+";"); } if(listname != null && listname.length()>0) { stream.println(" return "+listname+"[_i-"+single.length+"];"); } else { stream.println(" return 0.0;"); } stream.println("}"); stream.println(); } } /** * M�todo auxiliar para generar las variables de la funci�n */ private void createFamVariableCode(PrintStream stream, Family fam) { Parameter single[] = fam.getSingleParameters(); String listname = fam.getParamListName(); stream.print("int i, double min, double max, double step"); for(int i=0; i<single.length; i++) { stream.print(", double "+single[i].getName()); } if(listname != null && listname.length() > 0) { stream.print(", double *"+listname+", int length"); } } /** * M�todo auxiliar para generar las variables de la funci�n */ private void createFamVariableCallCode(PrintStream stream, Family fam) { Parameter single[] = fam.getSingleParameters(); String listname = fam.getParamListName(); stream.print(" i, min, max, step"); for(int i=0; i<single.length; i++) { stream.print(", "+single[i].getName()); } if(listname != null && listname.length() > 0) { stream.print(", "+listname+", length"); } } //----------------------------------------------------------------------------// // M�todos que generan el c�digo de las M.F. // //----------------------------------------------------------------------------// /** * Descripci�n de un funci�n de pertenencia */ private void createMFCode(PrintStream stream,ParamMemFunc mf) throws XflException { String classname = usage.getMFname(mf); String equal = mf.getEqualCCode(); if(equal==null || equal.length()==0) throw new XflException(); stream.println("/*======================================================*/"); stream.println(complete("/* MembershipFunction "+classname)); stream.println("/*======================================================*/"); stream.println(); stream.println("/*------------------------------------------------------*/"); stream.println("/* Function to compute an equal relationship */"); stream.println("/*------------------------------------------------------*/"); stream.println(); stream.print("static double "+classname+"_equal(double x, "); createVariableCode(stream,mf); stream.println(") {"); stream.println(equal); stream.println("}"); stream.println(); if(usage.isMFGreqUsed( classname )) { String greq = mf.getGreqCCode(); stream.println("/*------------------------------------------------------*/"); stream.println("/* Function to compute a greater_or_equal relationship */"); stream.println("/*------------------------------------------------------*/"); stream.println(); stream.print("static double "+classname+"_greq(double x, "); createVariableCode(stream,mf); stream.println(") {"); if(greq != null && greq.length()>0) { stream.println(greq); } else { stream.println(" double _y, _mu, _degree=0;"); stream.println(" for(_y = min; _y <= x ; _y += step) {"); stream.print(" _mu = "+classname+"_equal(_y,"); createVariableCallCode(stream,mf); stream.println(");"); stream.println(" if( _mu > _degree) _degree = _mu;"); stream.println(" }"); stream.println(" return _degree;"); } stream.println("}"); stream.println(); } if(usage.isMFSmeqUsed( classname )) { String smeq = mf.getSmeqCCode(); stream.println("/*------------------------------------------------------*/"); stream.println("/* Function to compute a smaller_or_equal relationship */"); stream.println("/*------------------------------------------------------*/"); stream.println(); stream.print("static double "+classname+"_smeq(double x, "); createVariableCode(stream,mf); stream.println(") {"); if(smeq != null && smeq.length()>0) { stream.println(smeq); } else { stream.println(" double _y, _mu, _degree=0;"); stream.println(" for(_y = max; _y >= x ; _y -= step) {"); stream.print( " _mu = "+classname+"_equal(_y,"); createVariableCallCode(stream,mf); stream.println(");"); stream.println(" if( _mu > _degree) _degree = _mu;"); stream.println(" }"); stream.println(" return _degree;"); } stream.println("}"); stream.println(); } if(usage.isMFParamUsed( classname )) { Parameter[] single = mf.getSingleParameters(); String listname = mf.getParamListName(); stream.println("/*------------------------------------------------------*/"); stream.println("/* Function to get a parameter of the MF */"); stream.println("/*------------------------------------------------------*/"); stream.println(); stream.print("static double "+classname+"_param(int _i, "); createVariableCode(stream,mf); stream.println(") {"); for(int i=0; i<single.length; i++) { stream.println(" if(_i == "+i+") return "+single[i].getName()+";"); } if(listname != null && listname.length()>0) { stream.println(" return "+listname+"[_i-"+single.length+"];"); } else { stream.println(" return 0.0;"); } stream.println("}"); stream.println(); } } /** * M�todo auxiliar para generar las variables de la funci�n */ private void createVariableCode(PrintStream stream, ParamMemFunc mf) { Parameter single[] = mf.getSingleParameters(); String listname = mf.getParamListName(); stream.print("double min, double max, double step"); for(int i=0; i<single.length; i++) { stream.print(", double "+single[i].getName()); } if(listname != null && listname.length() > 0) { stream.print(", double *"+listname+", int length"); } } /** * M�todo auxiliar para generar las variables de la funci�n */ private void createVariableCallCode(PrintStream stream, ParamMemFunc mf) { Parameter single[] = mf.getSingleParameters(); String listname = mf.getParamListName(); stream.print(" min, max, step"); for(int i=0; i<single.length; i++) { stream.print(", "+single[i].getName()); } if(listname != null && listname.length() > 0) { stream.print(", "+listname+", length"); } } //----------------------------------------------------------------------------// // M�todos que generan el c�digo de los conjuntos de operadores // //----------------------------------------------------------------------------// /** * Descripci�n de un conjunto de operadores */ private void createOperatorSetCode(PrintStream stream, Operatorset opset) throws XflException { boolean[] flags = usage.getOpsetUsages(opset); String name = opset.getName(); stream.println("/*======================================================*/"); stream.println(complete("/* Operatorset OP_"+name)); stream.println("/*======================================================*/"); stream.println(); if(flags[0]) { stream.println("/*------------------------------------------------------*/"); stream.println("/* Description of the operator AND */"); stream.println("/*------------------------------------------------------*/"); stream.println(); createBinaryCode(stream,opset.and, "OP_"+name+"_And"); } if(flags[1]) { stream.println("/*------------------------------------------------------*/"); stream.println("/* Description of the operator OR */"); stream.println("/*------------------------------------------------------*/"); stream.println(); createBinaryCode(stream,opset.or, "OP_"+name+"_Or"); } if(flags[2]) { stream.println("/*------------------------------------------------------*/"); stream.println("/* Description of the operator NOT */"); stream.println("/*------------------------------------------------------*/"); stream.println(); createUnaryCode(stream,opset.not, "OP_"+name+"_Not"); } if(flags[3]) { stream.println("/*------------------------------------------------------*/"); stream.println("/* Description of the operator MORE OR LESS */"); stream.println("/*------------------------------------------------------*/"); stream.println(); createUnaryCode(stream,opset.moreorless, "OP_"+name+"_MoreOrLess"); } if(flags[4]) { stream.println("/*------------------------------------------------------*/"); stream.println("/* Description of the operator SLIGHTLY */"); stream.println("/*------------------------------------------------------*/"); stream.println(); createUnaryCode(stream,opset.slightly, "OP_"+name+"_Slightly"); } if(flags[5]) { stream.println("/*------------------------------------------------------*/"); stream.println("/* Description of the operator STRONGLY */"); stream.println("/*------------------------------------------------------*/"); stream.println(); createUnaryCode(stream,opset.very, "OP_"+name+"_Very"); } if(flags[6]) { stream.println("/*------------------------------------------------------*/"); stream.println("/* Description of the operator ALSO */"); stream.println("/*------------------------------------------------------*/"); stream.println(); createBinaryCode(stream,opset.also, "OP_"+name+"_Also"); stream.println("/*------------------------------------------------------*/"); stream.println("/* Description of the operator IMPLICATION */"); stream.println("/*------------------------------------------------------*/"); stream.println(); createBinaryCode(stream,opset.imp, "OP_"+name+"_Imp"); } stream.println("/*------------------------------------------------------*/"); stream.println("/* Description of the defuzzification method */"); stream.println("/*------------------------------------------------------*/"); stream.println(); createDefuzCode(stream,opset.defuz, "OP_"+name+"_Defuz"); stream.println(); } /** * Descripcion de un operador binario */ private void createBinaryCode(PrintStream stream, Binary op, String name) throws XflException { stream.println("static double "+name+"(double a, double b) {"); Parameter singleparam[] = op.getSingleParameters(); for(int i=0; i<singleparam.length; i++) { stream.print(" double "+singleparam[i].getName()); stream.println(" = "+singleparam[i].value+";"); } String listname = op.getParamListName(); if(listname != null && listname.length() > 0) { Parameter paramlist[] = op.getParamList(); stream.print(" double "+listname+"["+paramlist.length+"] = {"); for(int i=0; i<paramlist.length; i++) stream.print((i>0? ",":"")+paramlist[i].value); stream.println("};"); } stream.println(op.getCCode()); stream.println("}"); stream.println(); } /** * Descripci�n de un operador unario */ private void createUnaryCode(PrintStream stream, Unary op, String name) throws XflException { stream.println("static double "+name+"(double a) {"); Parameter singleparam[] = op.getSingleParameters(); for(int i=0; i<singleparam.length; i++) { stream.print(" double "+singleparam[i].getName()); stream.println(" = "+singleparam[i].value+";"); } String listname = op.getParamListName(); if(listname != null && listname.length() > 0) { Parameter paramlist[] = op.getParamList(); stream.print(" double "+listname+"["+paramlist.length+"] = {"); for(int i=0; i<paramlist.length; i++) stream.print((i>0? ",":"")+paramlist[i].value); stream.println("};"); } stream.println(op.getCCode()); stream.println("}"); stream.println(); } /** * Descripci�n de un m�todo de concreci�n */ private void createDefuzCode(PrintStream stream, DefuzMethod op, String name) { String defuzcode = op.getCCode(); stream.println("static double "+name+"(FuzzyNumber mf) {"); if(defuzcode.indexOf("min")!=-1) stream.println(" double min = mf.min;"); if(defuzcode.indexOf("max")!=-1) stream.println(" double max = mf.max;"); if(defuzcode.indexOf("step")!=-1) stream.println(" double step = mf.step;"); Parameter singleparam[] = op.getSingleParameters(); for(int i=0; i<singleparam.length; i++) { stream.print(" double "+singleparam[i].getName()); stream.println(" = "+singleparam[i].value+";"); } String listname = op.getParamListName(); if(listname != null && listname.length() > 0) { Parameter paramlist[] = op.getParamList(); stream.print(" double "+listname+"["+paramlist.length+"] = {"); for(int i=0; i<paramlist.length; i++) stream.print((i>0? ",":"")+paramlist[i].value); stream.println("};"); } stream.println(defuzcode); stream.println("}"); stream.println(); } //----------------------------------------------------------------------------// // M�todos que generan el c�digo de los tipos // //----------------------------------------------------------------------------// /** * Descripci�n de un tipo de variable ling��stica */ private void createTypeCode(PrintStream stream, Type type) throws XflException { Family[] fam = type.getFamilies(); LinguisticLabel[] allmf = type.getAllMembershipFunctions(); stream.println("/*======================================================*/"); stream.println(complete("/* Type TP_"+type.getName())); stream.println("/*======================================================*/"); stream.println(); for(int i=0; i<fam.length; i++) { createTypeFamilyCode(stream,type,fam[i]); } for(int i=0; i<allmf.length; i++) { if(allmf[i] instanceof ParamMemFunc) { createTypePMFCode(stream, type, (ParamMemFunc) allmf[i]); } else { createTypeFMFCode(stream, type, (FamiliarMemFunc) allmf[i]); } } } /** * Descripci�n de una familia pertenenciente a un tipo de variable * @param stream * @param type * @param fam */ private void createTypeFamilyCode(PrintStream stream, Type type, Family fam) { String typename = type.getName(); double min = type.min(); double max = type.max(); double step = type.step(); boolean isUsedAsInput = usage.isUsedAsInput(type); boolean isUsedAsOutput = usage.isUsedAsOutput(type); String famname = usage.getFamilyName(fam); Parameter single[] = fam.getSingleParameters(); Parameter list[] = fam.getParamList(); String listname = fam.getParamListName(); if(listname == null || listname.length() == 0) list = null; stream.println("/*------------------------------------------------------*/"); stream.println(complete("/* Description of the family "+fam)); stream.println("/*------------------------------------------------------*/"); stream.println(); stream.println("static double TP_"+typename+"_"+fam+"_equal(double x, int i){"); createParamListCode(stream,list); stream.print(" return "+famname+"_equal(x,i,"+min+","+max+","+step); createParamCallCode(stream,single,list); stream.println(");"); stream.println("}"); stream.println(); if(isUsedAsInput && usage.isFamilyGreqUsed(famname)) { stream.println("static double TP_"+typename+"_"+fam+"_greq(double x, int i){"); createParamListCode(stream,list); stream.print(" return "+famname+"_greq(x,i,"+min+","+max+","+step); createParamCallCode(stream,single,list); stream.println(");"); stream.println("}"); stream.println(); } if(isUsedAsInput && usage.isFamilySmeqUsed(famname)) { stream.println("static double TP_"+typename+"_"+fam+"_smeq(double x, int i){"); createParamListCode(stream,list); stream.print(" return "+famname+"_smeq(x,i,"+min+","+max+","+step); createParamCallCode(stream,single,list); stream.println(");"); stream.println("}"); stream.println(); } if(isUsedAsOutput && usage.isFamilyParamUsed(famname)) { stream.println("static double TP_"+typename+"_"+fam+"_param(int index, int i){"); createParamListCode(stream,list); stream.print(" return "+famname+"_param(index,i,"+min+","+max+","+step); createParamCallCode(stream,single,list); stream.println(");"); stream.println("}"); stream.println(); } } /** * Descripci�n de las funciones asociadas a una funci�n de pertenencia param�trica * @param stream * @param type * @param pmf */ private void createTypePMFCode(PrintStream stream, Type type, ParamMemFunc pmf) { String typename = type.getName(); double min = type.min(); double max = type.max(); double step = type.step(); boolean isUsedAsInput = usage.isUsedAsInput(type); boolean isUsedAsOutput = usage.isUsedAsOutput(type); String mfname = usage.getMFname(pmf); String labelname = "TP_"+typename+"_"+pmf; Parameter single[] = pmf.getSingleParameters(); Parameter list[] = pmf.getParamList(); String listname = pmf.getParamListName(); if(listname == null || listname.length() == 0) list = null; stream.println("/*------------------------------------------------------*/"); stream.println(complete("/* Description of the label "+pmf)); stream.println("/*------------------------------------------------------*/"); stream.println(); stream.println("static double "+labelname+"_equal(double x){"); createParamListCode(stream,list); stream.print(" return "+mfname+"_equal(x,"+min+","+max+","+step); createParamCallCode(stream,single,list); stream.println(");"); stream.println("}"); stream.println(); if(isUsedAsInput && usage.isMFGreqUsed(mfname)) { stream.println("static double "+labelname+"_greq(double x){"); createParamListCode(stream,list); stream.print(" return "+mfname+"_greq(x,"+min+","+max+","+step); createParamCallCode(stream,single,list); stream.println(");"); stream.println("}"); stream.println(); } if(isUsedAsInput && usage.isMFSmeqUsed(mfname)) { stream.println("static double "+labelname+"_smeq(double x){"); createParamListCode(stream,list); stream.print(" return "+mfname+"_smeq(x,"+min+","+max+","+step); createParamCallCode(stream,single,list); stream.println(");"); stream.println("}"); stream.println(); } if(isUsedAsOutput && usage.isMFCenterUsed(mfname)) { double center = pmf.center(); stream.println("static double "+labelname+"_center(){"); stream.println(" return "+center+";"); stream.println("}"); stream.println(); } if(isUsedAsOutput && usage.isMFBasisUsed(mfname)) { double basis = pmf.basis(); stream.println("static double "+labelname+"_basis(){"); stream.println(" return "+basis+";"); stream.println("}"); stream.println(); } if(isUsedAsOutput && usage.isMFParamUsed(mfname)) { stream.println("static double "+labelname+"_param(int index){"); createParamListCode(stream,list); stream.print(" return "+mfname+"_param(index,"+min+","+max+","+step); createParamCallCode(stream,single,list); stream.println(");"); stream.println("}"); stream.println(); } } /** * Descripci�n de las funciones asociadas a una funci�n de pertenencia familiar * @param stream * @param type * @param fmf */ private void createTypeFMFCode(PrintStream stream, Type type, FamiliarMemFunc fmf) { String typename = type.getName(); Family fam = fmf.getFamily(); int index = fmf.getIndex(); boolean isUsedAsInput = usage.isUsedAsInput(type); boolean isUsedAsOutput = usage.isUsedAsOutput(type); String famname = "TP_"+typename+"_"+fam; String labelname = "TP_"+typename+"_"+fmf; String classname = usage.getFamilyName(fam); stream.println("/*------------------------------------------------------*/"); stream.println(complete("/* Description of the label "+fmf)); stream.println("/*------------------------------------------------------*/"); stream.println(); stream.println("static double "+labelname+"_equal(double x){"); stream.print(" return "+famname+"_equal(x,"+index+");"); stream.println("}"); stream.println(); if(isUsedAsInput && usage.isFamilyGreqUsed(classname)) { stream.println("static double "+labelname+"_greq(double x){"); stream.println(" return "+famname+"_greq(x,"+index+");"); stream.println("}"); stream.println(); } if(isUsedAsInput && usage.isFamilySmeqUsed(classname)) { stream.println("static double "+labelname+"_smeq(double x){"); stream.println(" return "+famname+"_smeq(x,"+index+");"); stream.println("}"); stream.println(); } if(isUsedAsOutput && usage.isFamilyCenterUsed(classname)) { double center = fmf.center(); stream.println("static double "+labelname+"_center(){"); stream.println(" return "+center+";"); stream.println("}"); stream.println(); } if(isUsedAsOutput && usage.isFamilyBasisUsed(classname)) { double basis = fmf.basis(); stream.println("static double "+labelname+"_basis(){"); stream.println(" return "+basis+";"); stream.println("}"); stream.println(); } if(isUsedAsOutput && usage.isFamilyParamUsed(classname)) { stream.println("static double "+labelname+"_param(int index){"); stream.println(" return "+famname+"_param(index,"+index+");"); stream.println("}"); stream.println(); } } /** * Crea la declaraci�n de la lista de par�metros * @param stream * @param list */ private void createParamListCode(PrintStream stream, Parameter[] list) { if(list == null) return; stream.print(" double list["+list.length+"] = {"); for(int i=0; i<list.length; i++) stream.print((i==0? "":",")+list[i].value); stream.println("};"); } /** * Escribe los valores de los par�metros en una llamada * @param stream * @param single * @param list */ private void createParamCallCode(PrintStream stream, Parameter[] single, Parameter[] list) { for(int i=0; i<single.length; i++) { stream.print(","+single[i].value); } if(list != null) { stream.print(",list,"+list.length); } } //----------------------------------------------------------------------------// // M�todos que generan el c�digo de las bases de reglas // //----------------------------------------------------------------------------// /** * Descripcion de una base de reglas */ private void createRulebaseCode(PrintStream stream, Rulebase base) throws XflException { String rbname = base.getName(); Operatorset opset = base.getOperatorset(); boolean center = usage.isCenterUsed(opset.defuz); boolean basis = usage.isBasisUsed(opset.defuz); boolean param = usage.isParamUsed(opset.defuz); boolean input = usage.isInputUsed(opset.defuz); String opsetname = "OP_"+opset.getName()+"_"; Variable[] inputvar = base.getInputs(); Variable[] outputvar = base.getOutputs(); Rule[] rule = base.getRules(); stream.println("/*======================================================*/"); stream.println(complete("/* Rulebase RL_"+rbname)); stream.println("/*======================================================*/"); stream.println(); stream.print("static void RL_"+rbname+"("); for(int i=0; i<inputvar.length; i++) stream.print((i==0? "": ", ")+"double "+inputvar[i]); for(int i=0; i<outputvar.length; i++) stream.print(", double *"+outputvar[i]); stream.println(") {"); stream.println(" double _rl;"); stream.println(); if(input) { stream.println(" double _input["+inputvar.length+"];"); for(int i=0; i<inputvar.length; i++) { stream.println(" _input["+i+"] = "+inputvar[i]+";"); } stream.println(); } for(int i=0; i<outputvar.length; i++) { createRulebaseOutputInitialization(stream,base,outputvar[i]); } for(int i=0; i<inputvar.length; i++) { createRulebaseInputInitialization(stream,base,inputvar[i]); } for(int i=0; i<rule.length; i++) { createRuleCode(stream,rule[i],opsetname,center,basis,param); } for(int i=0; i<outputvar.length; i++) { stream.print(" *"+outputvar[i]+" = "+opsetname+"Defuz("); stream.println("_"+outputvar[i]+");"); } stream.println("}"); stream.println(); } /** * C�digo de inicializaci�n de la salida de una base de reglas * @param stream * @param base * @param output */ private void createRulebaseOutputInitialization(PrintStream stream, Rulebase base, Variable output){ Operatorset opset = base.getOperatorset(); boolean imp_also = usage.isComputeUsed(opset.defuz); boolean input = usage.isInputUsed(opset.defuz); String opsetname = "OP_"+opset.getName()+"_"; int inputlength = base.getInputs().length; /* Contar el n�mero de conclusiones */ int outputcount = getNumberOfConsequents(base,output); double min = output.getType().min(); double max = output.getType().max(); double step = output.getType().step(); stream.println(" double _"+output+"_degree["+outputcount+"];"); stream.println(" Consequent _"+output+"_conc["+outputcount+"];"); stream.println(" FuzzyNumber _"+output+";"); stream.println(" _"+output+".min = "+min+";"); stream.println(" _"+output+".max = "+max+";"); stream.println(" _"+output+".step = "+step+";"); if(imp_also) { stream.println(" _"+output+".imp = "+opsetname+"Imp;"); stream.println(" _"+output+".also = "+opsetname+"Also;"); } if(input) { stream.println(" _"+output+".inputlength = "+inputlength+";"); stream.println(" _"+output+".input = _input;"); } stream.println(" _"+output+".length = "+outputcount+";"); stream.println(" _"+output+".degree = _"+output+"_degree;"); stream.println(" _"+output+".conc = _"+output+"_conc;"); stream.println(" int _"+output+"_i = 0;"); stream.println(); } /** * Cuenta el n�mero de veces que una variable de salida aparece en el * consecuente de una base de reglas * @param base * @param output * @return */ private int getNumberOfConsequents(Rulebase base, Variable output) { Rule[] rule = base.getRules(); int count = 0; for(int i=0; i<rule.length; i++) { Conclusion[] conc = rule[i].getConclusions(); for(int j=0; j<conc.length; j++) { if(conc[j].getVariable() == output) count++; } } return count; } /** * Genera el c�digo de inicializaci�n de una variable de entrada de una * base de reglas. * * @param stream * @param base * @param input */ private void createRulebaseInputInitialization(PrintStream stream, Rulebase base, Variable input) { LinguisticLabel[] label = input.getType().getAllMembershipFunctions(); boolean[] lbGreqUsed = new boolean[label.length]; boolean[] lbSmeqUsed = new boolean[label.length]; boolean globalGreqUsed = false; boolean globalSmeqUsed = false; for(int i=0; i<label.length; i++) { if(label[i] instanceof ParamMemFunc) { String mfname = usage.getMFname( (ParamMemFunc) label[i]); if(usage.isMFGreqUsed(mfname)) { lbGreqUsed[i] = true; globalGreqUsed = true; } if(usage.isMFSmeqUsed(mfname)) { lbSmeqUsed[i] = true; globalSmeqUsed = true; } } else { FamiliarMemFunc fmf = (FamiliarMemFunc) label[i]; String famname = usage.getFamilyName(fmf.getFamily()); if(usage.isFamilyGreqUsed(famname)) { lbGreqUsed[i] = true; globalGreqUsed = true; } if(usage.isFamilySmeqUsed(famname)) { lbSmeqUsed[i] = true; globalSmeqUsed = true; } } } stream.println(" double _"+input+"_eq["+label.length+"];"); if(globalGreqUsed) stream.println(" double _"+input+"_greq["+label.length+"];"); if(globalSmeqUsed) stream.println(" double _"+input+"_smeq["+label.length+"];"); for(int i=0; i<label.length; i++) { String lbname = "TP_"+input.getType().getName()+"_"+label[i].getLabel(); stream.print(" _"+input+"_eq["+i+"] = "); stream.println(lbname+"_equal("+input+");"); if(lbGreqUsed[i]) { stream.print(" _"+input+"_greq["+i+"] = "); stream.println(lbname+"_greq("+input+");"); } if(lbSmeqUsed[i]) { stream.print(" _"+input+"_smeq["+i+"] = "); stream.println(lbname+"_smeq("+input+");"); } } stream.println(); } /** * Descripci�n de una regla */ private void createRuleCode(PrintStream stream, Rule rule, String op, boolean center, boolean basis, boolean param) throws XflException { double degree = rule.getDegree(); Relation premise = rule.getPremise(); Conclusion[] conc = rule.getConclusions(); stream.print(" _rl = "); stream.println(createRelationCode(premise, op)+";"); if(degree != 1.0) stream.println(" _rl = "+degree+" * _rl;"); for(int j=0; j<conc.length; j++) createConclusionCode(stream,conc[j],center,basis,param); stream.println(); } /** * Descripci�n de una conclusi�n de una regla */ private void createConclusionCode(PrintStream stream, Conclusion conc, boolean center, boolean basis, boolean param) throws XflException { Variable var = conc.getVariable(); LinguisticLabel mf = conc.getMembershipFunction(); String mfname = "TP_"+var.getType().getName()+"_"+mf.getLabel()+"_"; stream.println(" _"+var+"_degree[_"+var+"_i] = _rl;"); stream.println(" _"+var+"_conc[_"+var+"_i].equal = "+mfname+"equal;"); if(center) stream.println(" _"+var+"_conc[_"+var+"_i].center = "+mfname+"center;"); if(basis) stream.println(" _"+var+"_conc[_"+var+"_i].basis = "+mfname+"basis;"); if(param) stream.println(" _"+var+"_conc[_"+var+"_i].param = "+mfname+"param;"); stream.println(" _"+var+"_i++;"); } /** * Descripci�n de una proposici�n de una regla */ private String createRelationCode(Relation rel, String op) throws XflException { Variable var = rel.getVariable(); LinguisticLabel mf = rel.getMembershipFunction(); Relation l = rel.getLeftRelation(); Relation r = rel.getRightRelation(); int index = 0; if(mf != null) { LinguisticLabel[] lb = var.getType().getAllMembershipFunctions(); for(int i=0; i<lb.length; i++) if(lb[i] == mf) index = i; } switch(rel.getKind()) { case Relation.AND: return op+"And("+createRelationCode(l,op)+","+createRelationCode(r,op)+")"; case Relation.OR: return op+"Or("+createRelationCode(l,op)+","+createRelationCode(r,op)+")"; case Relation.IS: return "_"+var+"_eq["+index+"]"; case Relation.ISNOT: return op+"Not( _"+var+"_eq["+index+"] )"; case Relation.GR_EQ: return "_"+var+"_greq["+index+"]"; case Relation.SM_EQ: return "_"+var+"_smeq["+index+"]"; case Relation.GREATER: return op+"Not( _"+var+"_smeq["+index+"] )"; case Relation.SMALLER: return op+"Not( _"+var+"_greq["+var+"] )"; case Relation.APP_EQ: return op+"MoreOrLess( _"+var+"_eq["+index+"] )"; case Relation.VERY_EQ: return op+"Very( _"+var+"_eq["+index+"] )"; case Relation.SL_EQ: return op+"Slightly( _"+var+"_eq["+index+"] )"; case Relation.NOT: return op+"Not("+createRelationCode(r,op)+")"; case Relation.MoL: return op+"MoreOrLess("+createRelationCode(r,op)+")"; case Relation.SLIGHTLY: return op+"Slightly("+createRelationCode(r,op)+")"; case Relation.VERY: return op+"Very("+createRelationCode(r,op)+")"; default: return ""; } } //----------------------------------------------------------------------------// // M�todos que generan el c�digo de un bloque no difuso // //----------------------------------------------------------------------------// /** * Descripci�n de un bloque no difuso */ private void createCrispBlockCode(PrintStream stream, CrispBlock crisp) throws XflException { String name = crisp.getName(); int inputs = crisp.inputs(); stream.println("/*======================================================*/"); stream.println(complete("/* CrispBlock CB_"+name)); stream.println("/*======================================================*/"); stream.println(); stream.print("static double CB_"+name+"("); for(int i=0; i<inputs; i++) stream.print((i==0? "":", ")+"double _i"+i); stream.println(") {"); Parameter singleparam[] = crisp.getSingleParameters(); for(int i=0; i<singleparam.length; i++) { stream.print(" double "+singleparam[i].getName()); stream.println(" = "+singleparam[i].value+";"); } if(crisp.hasParamList()) { Parameter paramlist[] = crisp.getParamList(); int listlength = (paramlist == null? 0 : paramlist.length); stream.print(" double "+crisp.getParamListName()+"["+listlength+"] = {"); for(int i=0; i<listlength; i++) stream.print((i>0? ",":"")+paramlist[i].value); stream.println("};"); } stream.println(" double x["+inputs+"];"); for(int i=0; i<inputs; i++) stream.println(" x["+i+"] = _i"+i+";"); stream.println(crisp.getCCode()); stream.println("}"); stream.println(); } //----------------------------------------------------------------------------// // M�todos que generan el c�digo de ejecuci�n del sistema // //----------------------------------------------------------------------------// /** * Descripci�n de la estructura jer�rquica del sistema */ private void createSystemModuleCode(PrintStream stream) throws XflException { SystemModule system = spec.getSystemModule(); Variable input[] = system.getInputs(); Variable output[] = system.getOutputs(); Variable inner[] = system.getInners(); ModuleCall call[] = system.getModuleCalls(); String name = spec.getName()+"InferenceEngine"; stream.println(); stream.println("/*======================================================*/"); stream.println("/* Inference Engine */"); stream.println("/*======================================================*/"); stream.println(); stream.print("void "+name+"("); for(int i=0; i<input.length; i++) stream.print((i==0? "" : ", ")+"double "+input[i]); for(int i=0; i<output.length; i++) stream.print(", double *_d_"+output[i]); stream.println(") {"); for(int i=0; i<inner.length; i++) { if(!inner[i].equals("NULL")) stream.println(" double "+inner[i]+";"); } for(int i=0; i<output.length; i++) stream.println(" double "+output[i]+";"); for(int i=0; i<call.length; i++) if(call[i] instanceof RulebaseCall) { createRulebaseCallCode(stream, (RulebaseCall) call[i]); } else createCrispBlockCallCode( stream, (CrispBlockCall) call[i]); for(int i=0; i<output.length; i++) { stream.println(" *_d_"+output[i]+" = "+output[i]+";"); } stream.println("}"); stream.println(); } /** * Descripci�n de una llamada a una base de reglas */ private void createRulebaseCallCode(PrintStream stream, RulebaseCall call) throws XflException { Rulebase base = call.getRulebase(); Variable[] inputvar = call.getInputVariables(); Variable[] outputvar = call.getOutputVariables(); stream.print(" RL_"+base+"("); for(int i=0; i < inputvar.length; i++) stream.print((i==0? "" : ", ")+inputvar[i]); for(int i=0; i < outputvar.length; i++) stream.print(", &"+outputvar[i]); stream.println(");"); } /** * Descripci�n de una llamada a un bloque no difuso */ private void createCrispBlockCallCode(PrintStream stream, CrispBlockCall call) throws XflException { Variable[] inputvar = call.getInputVariables(); Variable outputvar = call.getOutputVariable(); stream.print(" "+outputvar+" = CB_"+call.getName()+"("); for(int j=0; j < inputvar.length; j++) stream.print((j==0? "":",")+inputvar[j]); stream.println(");"); } //----------------------------------------------------------------------------// // M�todos auxiliares // //----------------------------------------------------------------------------// /** * Completa la cadena hasta 58 caracteres */ private String complete(String begining) { String line = begining; for(int i=begining.length(); i<56; i++) line += " "; line += "*/"; return line; } }