//--------------------------------------------------------------------------------// // 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. // //--------------------------------------------------------------------------------// //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++// //BASE DE REGLAS // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++// package xfuzzy.lang; /** * Clase que describe una base de reglas difusas * * @author Francisco Jos� Moreno Velo * */ public class Rulebase implements Cloneable { //----------------------------------------------------------------------------// // MIEMBROS P�BLICOS // //----------------------------------------------------------------------------// /** * Conjunto de operadores utilizados en la base de reglas */ public Operatorset operation; //----------------------------------------------------------------------------// // MIEMBROS PRIVADOS // //----------------------------------------------------------------------------// /** * Nombre de la base de reglas */ private String name; /** * Lista de variables de entrada de la base de reglas */ private Variable inputvar[]; /** * Lista de variables de salida de la base de reglas */ private Variable outputvar[]; /** * Lista de reglas que forman la base de reglas */ private Rule rule[]; /** * Contador de enlaces (usos) de la base de reglas */ private int link; /** * Indicador de que en un determinado momento, la base de reglas se est� * editando */ private boolean editing = false; //----------------------------------------------------------------------------// // CONSTRUCTOR // //----------------------------------------------------------------------------// /** * Constructor */ public Rulebase(String name) { this.name = name; this.operation = null; this.inputvar = new Variable[0]; this.outputvar = new Variable[0]; this.rule = new Rule[0]; } //----------------------------------------------------------------------------// // M�TODOS P�BLICOS // //----------------------------------------------------------------------------// /** * Obtiene el identificador de la base de reglas */ public String toString() { return new String(this.name); } /** * Compara un nombre con el identificador de la base de reglas */ public boolean equals(String name) { return this.name.equals(name); } /** * Obtiene un duplicado del objeto */ public Object clone() { Rulebase clone = new Rulebase(this.name); clone.setOperatorset(this.operation); Variable cloneinputvar[] = new Variable[inputvar.length]; Variable cloneoutputvar[] = new Variable[outputvar.length]; for(int i=0; i<inputvar.length; i++) { String varname = inputvar[i].getName(); Type vartype = inputvar[i].getType(); cloneinputvar[i] = new Variable(varname,vartype, Variable.INPUT); clone.addInputVariable(cloneinputvar[i]); } for(int i=0; i<outputvar.length; i++) { String varname = outputvar[i].getName(); Type vartype = outputvar[i].getType(); cloneoutputvar[i] = new Variable(varname,vartype, clone); clone.addOutputVariable(cloneoutputvar[i]); } for(int i=0; i<rule.length; i++) clone.addRule( (Rule) rule[i].clone(clone)); for(int i=0; i<inputvar.length; i++) clone.exchange(inputvar[i], cloneinputvar[i]); for(int i=0; i<outputvar.length; i++) clone.exchange(outputvar[i], cloneoutputvar[i]); return clone; } /** * Elimina los enlaces para poder eliminar la base de reglas */ public void dispose() { while(rule.length>0) remove(rule[0]); while(inputvar.length>0) removeInputVar(inputvar[0]); while(outputvar.length>0) removeOutputVar(outputvar[0]); setOperatorset(null); } //----------------------------------------------------------------------------// // M�todos de acceso a los campos // //----------------------------------------------------------------------------// /** * Obtiene el nombre de la base de reglas */ public String getName() { return this.name; } /** * Obtiene el conjunto de operadores utilizado en la base */ public Operatorset getOperatorset() { return this.operation; } /** * Obtiene la lista de variables de entrada */ public Variable[] getInputs() { return this.inputvar; } /** * Obtiene la lista de variables de salida */ public Variable[] getOutputs() { return this.outputvar; } /** * Obtiene la lista de reglas */ public Rule[] getRules() { return this.rule; } /** * Verifica si la base de reglas esta siendo utilizada */ public boolean isLinked() { return (this.link>0); } /** * Verifica si la base de reglas esta siendo editada */ public boolean isEditing() { return this.editing; } //----------------------------------------------------------------------------// // M�todos de asignaci�n de los campos // //----------------------------------------------------------------------------// /** * Asigna el conjunto de operadores utilizado */ public void setOperatorset(Operatorset op) { if(this.operation != null) this.operation.unlink(); this.operation = op; if(this.operation != null) this.operation.link(); } /** * Incrementa el contador de enlaces (usos) del objeto */ public void link() { this.link++; } /** * Decrementa el contador de enlaces (usos) del objeto */ public void unlink() { this.link--; } /** * Asigna el contenido del campo de edicion */ public void setEditing(boolean editing) { this.editing = editing; } /** * Asigna el nombre de la base de reglas */ public void setName(String name) { this.name = name; } //----------------------------------------------------------------------------// // M�todos para a�adir valores // //----------------------------------------------------------------------------// /** * A�ade una variable de entrada */ public void addInputVariable(Variable var) { Variable av[] = new Variable[this.inputvar.length+1]; System.arraycopy(this.inputvar,0,av,0,this.inputvar.length); av[this.inputvar.length] = var; this.inputvar = av; } /** * A�ade una variable de salida */ public void addOutputVariable(Variable var) { Variable av[] = new Variable[this.outputvar.length+1]; System.arraycopy(this.outputvar,0,av,0,this.outputvar.length); av[this.outputvar.length] = var; this.outputvar = av; } /** * A�ade una regla */ public void addRule(Rule rule) { Rule arl[] = new Rule[this.rule.length+1]; System.arraycopy(this.rule,0,arl,0,this.rule.length); arl[this.rule.length] = rule; this.rule = arl; } //----------------------------------------------------------------------------// // M�todos para eliminar valores // //----------------------------------------------------------------------------// /** * Elimina una regla */ public void remove(Rule rl) { int index = -1; for(int i=0; i<rule.length; i++) if(rule[i] == rl) index = i; if(index == -1) return; Rule[] aux = new Rule[rule.length-1]; System.arraycopy(rule,0,aux,0,index); System.arraycopy(rule,index+1,aux,index,aux.length-index); rl.dispose(); rule = aux; } /** * Elimina todas las reglas */ public void removeAllRules() { for(int i=0; i<this.rule.length; i++) this.rule[i].dispose(); this.rule = new Rule[0]; } /** * Elimina una variable de entrada */ public void removeInputVar(Variable var) { boolean contains = false; if(inputvar.length == 0) return; Variable[] aux = new Variable[inputvar.length-1]; for(int i=0,j=0; i<inputvar.length; i++) if(inputvar[i] != var) { aux[j]=inputvar[i]; j++; } else contains = true; if(contains) { var.getType().unlink(); inputvar = aux; } } /** * Elimina una variable de salida */ public void removeOutputVar(Variable var) { boolean contains = false; if(outputvar.length == 0) return; Variable[] aux = new Variable[outputvar.length-1]; for(int i=0,j=0; i<outputvar.length; i++) if(outputvar[i] != var) { aux[j]=outputvar[i]; j++; } else contains = true; if(contains) { var.getType().unlink(); outputvar = aux; } } //----------------------------------------------------------------------------// // M�todos de b�squeda e intercambio // //----------------------------------------------------------------------------// /** * Busca una variable */ public Variable searchVariable(String varname) { for(int i=0; i<this.inputvar.length; i++) if( this.inputvar[i].equals(varname) ) return this.inputvar[i]; for(int i=0; i<this.outputvar.length; i++) if( this.outputvar[i].equals(varname) ) return this.outputvar[i]; return null; } /** * Calcula el numero de veces que la i-esima variable de salida aparece en el * consecuente de las reglas */ public int computeOutputSize(int i) { int counter=0; for(int j=0; j<rule.length; j++) { Conclusion conc[] = rule[j].getConclusions(); for(int k=0; k<conc.length; k++) if(conc[k].getVariable() == outputvar[i]) counter++; } return counter; } /** * Intercambia dos funciones de pertenencia */ public void exchange(LinguisticLabel oldmf, LinguisticLabel newmf) { for(int i=0; i<rule.length; i++) rule[i].exchange(oldmf,newmf); } /** * Intercambia dos variables */ public void exchange(Variable oldvar, Variable newvar) { for(int i=0; i<rule.length; i++) rule[i].exchange(oldvar,newvar); } //----------------------------------------------------------------------------// // M�todos que genaran c�digo // //----------------------------------------------------------------------------// /** * Genera la descripci�n XFL3 de la base de reglas */ public String toXfl() { String eol = System.getProperty("line.separator", "\n"); String code = "rulebase "+this.name+" ("; for(int i=0; i<inputvar.length; i++) code += (i==0?"" :", ")+inputvar[i].toXfl(); code += " : "; for(int i=0; i<outputvar.length; i++) code += (i==0?"" :", ")+outputvar[i].toXfl(); code += ") "; if(!this.operation.isDefault()) code += "using "+this.operation.getName(); code += " {"+eol; for(int i=0; i<this.rule.length; i++) code += this.rule[i].toXfl(); code += " }"+eol; return code; } //----------------------------------------------------------------------------// // M�todos de c�lculo del proceso de inferencia // //----------------------------------------------------------------------------// /** * Realiza la inferencia con los valores de las variables de entrada y * almacena los valores de las variables de salida, el grado de activacion * de cada regla y la funcion de pertenencia agregada de cada salida */ public void compute(Variable[] ivar, Variable[] ovar, double[] degree, MemFunc[] value) { double ival[] = new double[ivar.length]; for(int i=0; i<this.inputvar.length; i++) try{ ival[i] = ivar[i].getCrispValue(); } catch(Exception ex) { ival[i]=0; } for(int i=0; i<this.outputvar.length; i++) this.outputvar[i].reset(); for(int i=0; i<this.inputvar.length; i++) this.inputvar[i].set(ivar[i].getValue()); try { for(int i=0; i<this.rule.length;i++) degree[i]=this.rule[i].compute(); } catch(XflException e) {} for(int i=0; i<this.outputvar.length; i++) ((AggregateMemFunc) outputvar[i].getValue()).input = ival; if(this.operation.defuz.isDefault()) for(int i=0; i<this.outputvar.length; i++) ovar[i].set(outputvar[i].getValue()); else for(int i=0; i<this.outputvar.length; i++) ovar[i].set( ((AggregateMemFunc) outputvar[i].getValue()).defuzzify() ); for(int i=0; i<this.outputvar.length; i++) value[i] = outputvar[i].getValue(); } /** * Calcula la derivada del proceso de inferencia */ public void derivative(double[] derror) throws XflException { for(int i=0; i<outputvar.length; i++) outputvar[i].derivative(derror[i]); for(int i=0; i<rule.length; i++) rule[i].derivative(); } /** * Calcula la derivada del proceso de inferencia */ public void derivative() throws XflException { for(int i=0; i<rule.length; i++) rule[i].derivative(); } /** * Actualiza el campo de ajustabilidad de las reglas */ public void setAdjustable() { for(int i=0; i<rule.length; i++) rule[i].setAdjustable(); } /** * Inicializa el grado de activaci�n m�xima de las reglas */ public void resetMaxActivation() { for(int i=0; i<rule.length; i++) rule[i].resetMaxActivation(); } }