//--------------------------------------------------------------------------------//
// 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.xfsp.model.types;
import xfuzzy.lang.ParamMemFunc;
import xfuzzy.lang.LinguisticLabel;
import xfuzzy.lang.Type;
import xfuzzy.lang.Specification;
/**
* <p> <b>Descripci�n:</b> simplificador de tipos de sistemas difusos por el
* m�todo de <i>clustering</i> de las funciones de pertenencia del tipo en
* cuesti�n.
* <p> <b>E-mail</b>: <ADDRESS>joragupra@us.es</ADDRRESS>
* @author Jorge Agudo Praena
* @version 1.4
* @see IXfspTypeSimplifier
* @see XfspTypeSimplifierFactory
*
*/
public class XfspClustering
implements IXfspTypeSimplifier {
//n�mero de clusters en que se agrupan los datos (por defecto se iniciliza a
//-1)
private int clusters = -1;
//pesos que se le debe asignar a cada uno de los elementos de cada dato
private double[] weights;
/**
* <p> <b>Descripci�n:</b> crea un simplificador de tipos por clustering de
* las funciones de pertenencia.
* @param num N�mero de clusters en que se deben agrupar los datos.
* @param weights Pesos que se debe asignar a cada uno de los elementos de
* los datos
*
*/
public XfspClustering(int num, double[] weights) {
//establece el n�mero de clusters en que se deben agrupar los datos
this.clusters = num;
//establece los pesos que hay que asignar a los elementos de cada dato
this.weights = weights;
}
/**
* <p> <b>Descripci�n:</b> simplifica un tipo y actualiza la especificaci�n
* de un sistema difuso para que refleje la simplificaci�n realizada.
* @param type Tipo que debe ser simplificado.
* @param spec Especificaci�n de un sistema difuso que debe ser actualizada
* tras la simplificaci�n del tipo.
*
*/
public void simplify(Type type, Specification spec) {
if (reducible(type)) {
//conjunto de datos de las funciones de pertenencia del tipo a simplificar
double[][] data = null;
//inicializa los clusters del tipo
data = setupClusters(type);
//simplifica el tipo y actualiza la especificaci�n
simplifyType(type, spec, data, clusters);
}
}
/**
* <p> <b>Descripci�n:</b> determina si un tipo es reducible mediante
* <i>clustering</i>.
* @param type Tipo que se quiere simplificar.
* @return Devuelve cierto si el tipo es reducible por <i>clustering</i> y
* falso en caso contrario.
*
*/
private boolean reducible(Type type) {
//por defecto el tipo es reducible...
boolean res = true;
//...y busca los casos en los que no lo sea
//obtiene todas las funciones de pertenencia del tipo
LinguisticLabel[] mf = type.getMembershipFunctions();
//si el tipo no tiene funciones de pertenencia...
if (mf.length == 0) {
//...no es reducible
res = false;
}
//si la primera fiuncion de pertenencia no es parametrica...
else if ( !(mf[0] instanceof ParamMemFunc) ) {
//...no es reducible
res = false;
}
//en otro caso...
else {
//obtiene el nombre de la primera funci�n de pertenencia del tipo...
String mfclass = mf[0].getClass().getName();
//...comprueba que todas las funciones de pertenencia del tipo son
//iguales...
for (int i = 0; i < mf.length; i++) {
//...y si alguna no lo es...
if (!mf[i].getClass().getName().equals(mfclass)) {
//...entonces el tipo no es reducible
res = false;
}
}
}
//devuelve el resultado de todas las comprobaciones anteriores
return res;
}
/**
* <p> <b>Descripci�n:</b> calcula el conjunto de datos iniciales para el
* proceso de clustering.
* @param type Tipo que se va a simplificar mediante clustering.
* @return Conjunto de datos que se emplear�n durante el proceso de
* clustering.
*
*/
private double[][] setupClusters(Type type) {
//obtiene todas las funciones de pertenencia del tipo que se va a
//simplificar
ParamMemFunc[] mf = type.getParamMembershipFunctions();
//calcula el n�mero de datos que maneja cada una de las funciones de
//pertenencia
double[][] data = new double[mf.length][];
//para cada una de las funciones de pertenencia del tipo a simplificar...
for (int i = 0; i < mf.length; i++) {
//...obtiene el conjunto de datos y lo almacena en el elemento
//correspondiente del array de datos
data[i] = mf[i].get();
}
//devuelve un array con todos los datos de todas las funciones de
//pertenencia del tipo a simplificar
return data;
}
/**
* <p> <b>Descripci�n:</b> simplifica un tipo y sustituye el tipo
* simplificado por el nuevo en el sistema al que pertence.
* @param type Tipo que se va a simplificar mediante clustering.
* @param spec Especificacion del sistema al que pertenece el tipo que se va
* a simplificar.
* @param data
* @param C N�mero de <i>clusters</i> en que se agrupar�n las funciones de
* pertenencia del tipo a simplificar.
*
*/
private void simplifyType(Type type, Specification spec, double[][] data,
int C) {
//obtiene las funciones de pertenencia del tipo
ParamMemFunc[] omf = type.getParamMembershipFunctions();
//obtiene la clase a que pertenecen las funciones de pertenencia del tipo
Class mfclass = omf[0].getClass();
//array de funciones de pertenencia para el tipo simplificado
ParamMemFunc[] pmf = new ParamMemFunc[C];
//crea un nuevo objeto simplificador de tipos por clustering para el
//n�mero de clusters en que se quieren agrupar las funciones de pertenencia
//del tipo a simplificar
XfspCluster c = new XfspCluster(data, C, weights);
//aplica el proceso de clustering
c.apply();
//para todos los clusters en que se agrupar�n las funciones de pertenencia
//del tipo...
for (int i = 0; i < C; i++) {
try {
//...crea una nueva instancia de funci�n de pertenencia del tipo
//original...
pmf[i] = (ParamMemFunc) mfclass.newInstance();
//...le asigna un nombre...
pmf[i].set("mf" + i, type.getUniverse());
//...y le asigna los par�metros
pmf[i].set(c.cluster[i]);
}
catch (Exception e) {
}
}
//para todas las funciones de pertenencia del tipo original...
for (int j = 0; j < omf.length; j++) {
//...la sustituye por la nueva
spec.exchange(omf[j], pmf[c.assign[j]]);
}
//establece el nuevo conjunto de funciones de pertencia para el tipo
//simplificado
type.setMembershipFunctions(pmf);
}
}