//--------------------------------------------------------------------------------// // 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.lang; /** * Clase que describe una proposici�n difusa simple, es decir, una * proposici�n que relaciona una variable con una de sus etiquetas * ling��sticas * * @author Francisco Jos� Moreno Velo * */ public class SingleRelation extends Relation { //----------------------------------------------------------------------------// // MIEMBROS PRIVADOS // //----------------------------------------------------------------------------// /** * Tipo de proposici�n (IGUAL, MAYOR, MENOR, ...) */ private int kind; /** * Variable de la proposici�n simple */ private Variable var; /** * Etiqueta ling��stica de la proposici�n simple */ private LinguisticLabel mf; /** * Referencia a la base de reglas para poder utilizar su conjunto de operadores */ private Rulebase rb; /** * Grado de activaci�n de la proposici�n en un proceso de inferencia */ private double degree; //----------------------------------------------------------------------------// // CONSTRUCTOR // //----------------------------------------------------------------------------// /** * Constructor */ public SingleRelation(int kind, Variable var, LinguisticLabel mf, Rulebase rb) { this.kind = kind; this.var = var; this.var.link(); this.mf = mf; this.mf.link(); this.rb = rb; } //----------------------------------------------------------------------------// // M�TODOS P�BLICOS // //----------------------------------------------------------------------------// //----------------------------------------------------------------------------// // M�todos de acceso de los campos // //----------------------------------------------------------------------------// /** * Obtiene el tipo de proposici�n */ public int getKind() { return this.kind; } /** * Asigna el tipo de proposici�n */ public void setKind(int kind) { this.kind = kind; } /** * Obtiene la referencia a la variable de la proposici�n */ public Variable getVariable() { return this.var; } /** * Asigna la referencia a la variable de la proposici�n */ public void setVariable(Variable var) { this.var = var; } /** * Obtiene la referencia a la MF de la proposici�n */ public LinguisticLabel getMembershipFunction() { return this.mf; } /** * Asigna la referencia a la MF de la proposici�n */ public void setMembershipFunction(LinguisticLabel mf) { this.mf = mf; } /** * Obtiene la referencia a la componente izquierda */ public Relation getLeftRelation() { return null; } /** * Asigna la referencia a la componente izquierda */ public void setLeftRelation(Relation rel) { } /** * Obtiene la referencia a la componente derecha */ public Relation getRightRelation() { return null; } /** * Obtiene la referencia a la componente derecha */ public void setRightRelation(Relation rel) { } //----------------------------------------------------------------------------// // M�todos de c�lculo de la proposici�n // //----------------------------------------------------------------------------// /** * Calcula el grado de activaci�n de la proposici�n */ public double compute() throws XflException { switch(kind) { case IS: return compute_eq(); case GREATER: return compute_gr(); case GR_EQ: return compute_greq(); case SMALLER: return compute_sm(); case SM_EQ: return compute_smeq(); case APP_EQ: return compute_appeq(); case ISNOT: return compute_noteq(); case SL_EQ: return compute_sleq(); case VERY_EQ: return compute_vreq(); default: return 0; } } /** * Calcula la derivada de la proposici�n */ public void derivative(double de) throws XflException { switch(kind) { case IS: derivative_eq(de); break; case GREATER: derivative_gr(de); break; case GR_EQ: derivative_greq(de); break; case SMALLER: derivative_sm(de); break; case SM_EQ: derivative_smeq(de); break; case APP_EQ: derivative_appeq(de); break; case ISNOT: derivative_noteq(de); break; case SL_EQ: derivative_sleq(de); break; case VERY_EQ: derivative_vreq(de); break; } } //----------------------------------------------------------------------------// // Otros m�todos // //----------------------------------------------------------------------------// /** * Genera la descripcion XFL3 de la proposici�n */ public String toXfl() { switch(kind) { case IS: return this.var.getName()+" == "+this.mf.getLabel(); case GREATER: return this.var.getName()+" > "+ this.mf.getLabel(); case GR_EQ: return this.var.getName()+" >= "+this.mf.getLabel(); case SMALLER: return this.var.getName()+" < "+ this.mf.getLabel(); case SM_EQ: return this.var.getName()+" <= "+this.mf.getLabel(); case APP_EQ: return this.var.getName()+" ~= "+this.mf.getLabel(); case ISNOT: return this.var.getName()+" != "+this.mf.getLabel(); case SL_EQ: return this.var.getName()+" %= "+this.mf.getLabel(); case VERY_EQ: return this.var.getName()+" += "+this.mf.getLabel(); default: return ""; } } /** * Obtiene un duplicado del objeto */ public Object clone(Rulebase rbcl) { return new SingleRelation(this.kind,this.var,this.mf,rbcl); } /** * Verifica que la proposici�n sea ajustable */ public boolean isAdjustable() { return mf.isAdjustable(); } /** * Elimina los enlaces para poder eliminar la proposici�n */ public void dispose() { if(this.mf != null) this.mf.unlink(); if(this.var != null) this.var.unlink(); } /** * Sustituye una funci�n de pertenencia por otra */ public void exchange(LinguisticLabel oldmf, LinguisticLabel newmf) { if(this.mf == oldmf) { this.mf.unlink(); this.mf = newmf; this.mf.link(); } } /** * Sustituye una variable por otra */ public void exchange(Variable oldvar, Variable newvar) { if(this.var == oldvar) { this.var.unlink(); this.var = newvar; this.var.link(); } } //----------------------------------------------------------------------------// // M�TODOS PRIVADOS // //----------------------------------------------------------------------------// //----------------------------------------------------------------------------// // M�todos de c�lculo del grado de activaci�n // //----------------------------------------------------------------------------// /** * Calcula el grado de activaci�n de la proposici�n "==" */ private double compute_eq() throws XflException { MemFunc value = this.var.getValue(); if(value == null) throw new XflException(18); if(value instanceof pkg.xfl.mfunc.singleton) { return this.mf.compute( ((ParamMemFunc) value).get()[0] ); } if((value instanceof AggregateMemFunc) && ((AggregateMemFunc) value).isDiscrete() ) { double[][] val = ((AggregateMemFunc) value).getDiscreteValues(); double deg = 0; for(int i=0; i<val.length; i++){ double mu = this.mf.compute(val[i][0]); double minmu = (mu<val[i][1] ? mu : val[i][1]); if( deg<minmu ) deg = minmu; } return deg; } double min = this.mf.min(); double max = this.mf.max(); double step = this.mf.step(); double deg = 0; for(double x=min; x<=max; x+=step){ double mu1 = this.mf.compute(x); double mu2 = value.compute(x); double minmu = (mu1<mu2 ? mu1 : mu2); if( deg<minmu ) deg = minmu; } return deg; } /** * Calcula el grado de activaci�n de la proposici�n ">" */ private double compute_gr() throws XflException { MemFunc value = this.var.getValue(); if(value == null) throw new XflException(18); if(value instanceof pkg.xfl.mfunc.singleton) { degree = this.mf.smallereq( ((ParamMemFunc) value).get()[0] ); return rb.operation.not.compute(degree); } if((value instanceof AggregateMemFunc) && ((AggregateMemFunc) value).isDiscrete() ) { double[][] val = ((AggregateMemFunc) value).getDiscreteValues(); double deg = 0; for(int i=0; i<val.length; i++){ double mu = rb.operation.not.compute( this.mf.smallereq(val[i][0]) ); double minmu = (mu<val[i][1] ? mu : val[i][1]); if( deg<minmu ) deg = minmu; } return deg; } double min = this.mf.min(); double max = this.mf.max(); double step = this.mf.step(); double deg = 0, smeq = 0; for(double x=max; x>=min; x-=step){ double mu1 = value.compute(x); double mu2 = this.mf.compute(x); if( mu2>smeq ) smeq = mu2; double gr = rb.operation.not.compute(smeq); double minmu = (mu1<gr ? mu1 : gr); if( deg<minmu ) deg = minmu; } return deg; } /** * Calcula el grado de activaci�n de la proposici�n ">=" */ private double compute_greq() throws XflException { MemFunc value = this.var.getValue(); if(value == null) throw new XflException(18); if(value instanceof pkg.xfl.mfunc.singleton) { return this.mf.greatereq( ((ParamMemFunc) value).get()[0] ); } if((value instanceof AggregateMemFunc) && ((AggregateMemFunc) value).isDiscrete() ) { double[][] val = ((AggregateMemFunc) value).getDiscreteValues(); double deg = 0; for(int i=0; i<val.length; i++){ double mu = this.mf.greatereq(val[i][0]); double minmu = (mu<val[i][1] ? mu : val[i][1]); if( deg<minmu ) deg = minmu; } return deg; } double min = this.mf.min(); double max = this.mf.max(); double step = this.mf.step(); double deg=0, greq=0; for(double x=min; x<=max; x+=step){ double mu1 = value.compute(x); double mu2 = this.mf.compute(x); if( mu2>greq ) greq = mu2; double minmu = (mu1<greq ? mu1 : greq); if( deg<minmu ) deg = minmu; } return deg; } /** * Calcula el grado de activaci�n de la proposici�n "<" */ private double compute_sm() throws XflException { MemFunc value = this.var.getValue(); if(value == null) throw new XflException(18); if(value instanceof pkg.xfl.mfunc.singleton) { degree = this.mf.greatereq( ((ParamMemFunc) value).get()[0] ); return rb.operation.not.compute(degree); } if((value instanceof AggregateMemFunc) && ((AggregateMemFunc) value).isDiscrete() ) { double[][] val = ((AggregateMemFunc) value).getDiscreteValues(); double deg = 0; for(int i=0; i<val.length; i++){ double mu = rb.operation.not.compute( this.mf.greatereq(val[i][0]) ); double minmu = (mu<val[i][1] ? mu : val[i][1]); if( deg<minmu ) deg = minmu; } return deg; } double min = this.mf.min(); double max = this.mf.max(); double step = this.mf.step(); double deg = 0, greq = 0; for(double x=min; x<=max; x+=step){ double mu1 = value.compute(x); double mu2 = this.mf.compute(x); if( mu2>greq ) greq = mu2; double sm = rb.operation.not.compute(greq); double minmu = (mu1<sm ? mu1 : sm); if( deg<minmu ) deg = minmu; } return deg; } /** * Calcula el grado de activaci�n de la proposici�n "<=" */ private double compute_smeq() throws XflException { MemFunc value = this.var.getValue(); if(value == null) throw new XflException(18); if(value instanceof pkg.xfl.mfunc.singleton) { return this.mf.smallereq( ((ParamMemFunc) value).get()[0] ); } if((value instanceof AggregateMemFunc) && ((AggregateMemFunc) value).isDiscrete() ) { double[][] val = ((AggregateMemFunc) value).getDiscreteValues(); double deg = 0; for(int i=0; i<val.length; i++){ double mu = this.mf.smallereq(val[i][0]); double minmu = (mu<val[i][1] ? mu : val[i][1]); if( deg<minmu ) deg = minmu; } return deg; } double min = this.mf.min(); double max = this.mf.max(); double step = this.mf.step(); double deg=0, smeq=0; for(double x=max; x>=min; x-=step){ double mu1 = value.compute(x); double mu2 = this.mf.compute(x); if( mu2>smeq ) smeq = mu2; double minmu = (mu1<smeq ? mu1 : smeq); if( deg<minmu ) deg = minmu; } return deg; } /** * Calcula el grado de activaci�n de la proposici�n "~=" */ private double compute_appeq() throws XflException { MemFunc value = this.var.getValue(); if(value == null) throw new XflException(18); if(value instanceof pkg.xfl.mfunc.singleton) { degree = this.mf.compute( ((ParamMemFunc) value).get()[0] ); return rb.operation.moreorless.compute(degree); } if((value instanceof AggregateMemFunc) && ((AggregateMemFunc) value).isDiscrete() ) { double[][] val = ((AggregateMemFunc) value).getDiscreteValues(); double deg = 0; for(int i=0; i<val.length; i++){ double mu = rb.operation.moreorless.compute( this.mf.compute(val[i][0]) ); double minmu = (mu<val[i][1] ? mu : val[i][1]); if( deg<minmu ) deg = minmu; } return deg; } double min = this.mf.min(); double max = this.mf.max(); double step = this.mf.step(); double deg = 0; for(double x=min; x<=max; x+=step){ double mu1 = rb.operation.moreorless.compute( this.mf.compute(x) ); double mu2 = value.compute(x); double minmu = (mu1<mu2 ? mu1 : mu2); if( deg<minmu ) deg = minmu; } return deg; } /** * Calcula el grado de activaci�n de la proposici�n "!=" */ private double compute_noteq() throws XflException { MemFunc value = this.var.getValue(); if(value == null) throw new XflException(18); if(value instanceof pkg.xfl.mfunc.singleton) { degree = this.mf.compute( ((ParamMemFunc) value).get()[0] ); return rb.operation.not.compute(degree); } if((value instanceof AggregateMemFunc) && ((AggregateMemFunc) value).isDiscrete() ) { double[][] val = ((AggregateMemFunc) value).getDiscreteValues(); double deg = 0; for(int i=0; i<val.length; i++){ double mu = rb.operation.not.compute( this.mf.compute(val[i][0]) ); double minmu = (mu<val[i][1] ? mu : val[i][1]); if( deg<minmu ) deg = minmu; } return deg; } double min = this.mf.min(); double max = this.mf.max(); double step = this.mf.step(); double deg = 0; for(double x=min; x<=max; x+=step){ double mu1 = rb.operation.not.compute( this.mf.compute(x) ); double mu2 = value.compute(x); double minmu = (mu1<mu2 ? mu1 : mu2); if( deg<minmu ) deg = minmu; } return deg; } /** * Calcula el grado de activaci�n de la proposici�n "%=" */ private double compute_sleq() throws XflException { MemFunc value = this.var.getValue(); if(value == null) throw new XflException(18); if(value instanceof pkg.xfl.mfunc.singleton) { degree = this.mf.compute( ((ParamMemFunc) value).get()[0] ); return rb.operation.slightly.compute(degree); } if((value instanceof AggregateMemFunc) && ((AggregateMemFunc) value).isDiscrete() ) { double[][] val = ((AggregateMemFunc) value).getDiscreteValues(); double deg = 0; for(int i=0; i<val.length; i++){ double mu = rb.operation.slightly.compute( this.mf.compute(val[i][0]) ); double minmu = (mu<val[i][1] ? mu : val[i][1]); if( deg<minmu ) deg = minmu; } return deg; } double min = this.mf.min(); double max = this.mf.max(); double step = this.mf.step(); double deg = 0; for(double x=min; x<=max; x+=step){ double mu1 = rb.operation.slightly.compute( this.mf.compute(x) ); double mu2 = value.compute(x); double minmu = (mu1<mu2 ? mu1 : mu2); if( deg<minmu ) deg = minmu; } return deg; } /** * Calcula el grado de activaci�n de la proposici�n "+=" */ private double compute_vreq() throws XflException { MemFunc value = this.var.getValue(); if(value == null) throw new XflException(18); if(value instanceof pkg.xfl.mfunc.singleton) { degree = this.mf.compute( ((ParamMemFunc) value).get()[0] ); return rb.operation.very.compute(degree); } if((value instanceof AggregateMemFunc) && ((AggregateMemFunc) value).isDiscrete() ) { double[][] val = ((AggregateMemFunc) value).getDiscreteValues(); double deg = 0; for(int i=0; i<val.length; i++){ double mu = rb.operation.very.compute( this.mf.compute(val[i][0]) ); double minmu = (mu<val[i][1] ? mu : val[i][1]); if( deg<minmu ) deg = minmu; } return deg; } double min = this.mf.min(); double max = this.mf.max(); double step = this.mf.step(); double deg = 0; for(double x=min; x<=max; x+=step){ double mu1 = rb.operation.very.compute( this.mf.compute(x) ); double mu2 = value.compute(x); double minmu = (mu1<mu2 ? mu1 : mu2); if( deg<minmu ) deg = minmu; } return deg; } //----------------------------------------------------------------------------// // Metodos de calculo de la derivada // //----------------------------------------------------------------------------// /** * Calcula la derivada de la proposici�n "==" */ private void derivative_eq(double de) throws XflException { if(!this.mf.isAdjustable()) return; double deriv[] = this.mf.deriv_eq(this.var.getCrispValue()); for(int i=0; i<deriv.length; i++) this.mf.addDeriv(i, de*deriv[i] ); } /** * Calcula la derivada de la proposici�n ">" */ private void derivative_gr(double de) throws XflException { if(!this.mf.isAdjustable()) return; double dnot = rb.operation.not.derivative(degree); double deriv[] = this.mf.deriv_smeq(this.var.getCrispValue()); for(int i=0; i<deriv.length; i++) this.mf.addDeriv(i, de*dnot*deriv[i] ); } /** * Calcula la derivada de la proposici�n ">=" */ private void derivative_greq(double de) throws XflException { if(!this.mf.isAdjustable()) return; double deriv[] = this.mf.deriv_greq(this.var.getCrispValue()); for(int i=0; i<deriv.length; i++) this.mf.addDeriv(i, de*deriv[i] ); } /** * Calcula la derivada de la proposici�n "<" */ private void derivative_sm(double de) throws XflException { if(!this.mf.isAdjustable()) return; double dnot = rb.operation.not.derivative(degree); double deriv[] = this.mf.deriv_greq(this.var.getCrispValue()); for(int i=0; i<deriv.length; i++) this.mf.addDeriv(i, de*dnot*deriv[i] ); } /** * Calcula la derivada de la proposici�n "<=" */ private void derivative_smeq(double de) throws XflException { if(!this.mf.isAdjustable()) return; double deriv[] = this.mf.deriv_smeq(this.var.getCrispValue()); for(int i=0; i<deriv.length; i++) this.mf.addDeriv(i, de*deriv[i] ); } /** * Calcula la derivada de la proposici�n "~=" */ private void derivative_appeq(double de) throws XflException { if(!this.mf.isAdjustable()) return; double dnot = rb.operation.moreorless.derivative(degree); double deriv[] = this.mf.deriv_eq(this.var.getCrispValue()); for(int i=0; i<deriv.length; i++) this.mf.addDeriv(i, de*dnot*deriv[i] ); } /** * Calcula la derivada de la proposici�n "!=" */ private void derivative_noteq(double de) throws XflException { if(!this.mf.isAdjustable()) return; double dnot = rb.operation.not.derivative(degree); double deriv[] = this.mf.deriv_eq(this.var.getCrispValue()); for(int i=0; i<deriv.length; i++) this.mf.addDeriv(i, de*dnot*deriv[i] ); } /** * Calcula la derivada de la proposici�n "%=" */ private void derivative_sleq(double de) throws XflException { if(!this.mf.isAdjustable()) return; double dnot = rb.operation.slightly.derivative(degree); double deriv[] = this.mf.deriv_eq(this.var.getCrispValue()); for(int i=0; i<deriv.length; i++) this.mf.addDeriv(i, de*dnot*deriv[i] ); } /** * Calcula la derivada de la proposici�n "+=" */ private void derivative_vreq(double de) throws XflException { if(!this.mf.isAdjustable()) return; double dnot = rb.operation.very.derivative(degree); double deriv[] = this.mf.deriv_eq(this.var.getCrispValue()); for(int i=0; i<deriv.length; i++) this.mf.addDeriv(i, de*dnot*deriv[i] ); } }