//--------------------------------------------------------------------------------//
// 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.rulebases;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import xfuzzy.lang.Conclusion;
import xfuzzy.lang.LinguisticLabel;
import xfuzzy.lang.Relation;
import xfuzzy.lang.Rule;
import xfuzzy.lang.Rulebase;
import xfuzzy.lang.Variable;
/**
* <p> <b>Descripci�n:</b> construye un conjunto de reglas para una determinada
* conclusi�n a partir del cubrimiento m�nimo de sus mint�rminos.
* <p> <b>E-mail</b>: <ADDRESS>joragupra@us.es</ADDRRESS>
* @author Jorge Agudo Praena
* @version 2.2
* @see XfspModel
* @see XfspTabularSimplifier
* @see XfspRulebaseTabularDirector
*
*/
public class XfspRulebaseTabularBuilder {
//nueva base de reglas que se va a construir
private Rulebase newRulebase;
//indica si se deben de mantener las funciones de pertenencia situadas en los
//extremos del universo de discurso de las variables
private boolean maintainExtremeMF;
/**
* <p> <b>Descripci�n:</b> crea un constructor de reglas a partir de un
* cubrimiento m�nimo de los mint�rminos asociados a una conclusi�n.
* @param maintainExtremeMF Si vale cierto se mantienen las funciones de
* pertenencia en los extremos de cada tipo y si vale falso no lo hace.
* @param rulebase Base de reglas original para la que se construir� una
* nueva base de reglas equivalente.
*
*/
public XfspRulebaseTabularBuilder(boolean maintainExtremeMF, Rulebase rulebase) {
//indica si se deben mantener las funciones de pertenencia que est�n en los
//extremos del universo de discurso de las variables o, por el contrario, si
//pueden ser eliminadas
this.maintainExtremeMF = maintainExtremeMF;
//inicializa la nueva base de reglas clonando la original...
newRulebase = new Rulebase(rulebase.getName());
newRulebase.setOperatorset(rulebase.getOperatorset());
for(int i=0;i<rulebase.getInputs().length;i++){
newRulebase.addInputVariable(rulebase.getInputs()[i]);
}
for(int i=0;i<rulebase.getOutputs().length;i++){
newRulebase.addOutputVariable(rulebase.getOutputs()[i]);
}
//newRulebase = (Rulebase) rulebase.clone();
//...y le quita todas las reglas que contiene
//newRulebase.removeAllRules();
}
/**
* <p> <b>Descripci�n:</b> devuelve la base de reglas que se ha ido
* construyendo al tratar cada uno de los mint�rminos que se le han pasado.
* @return Base de reglas construida de forma incremental.
*
*/
public Rulebase getRulebase() {
return newRulebase;
}
/**
* <p> <b>Descripci�n:</b> construye un conjunto de reglas para una
* conclusi�n a partir de los mint�rminos que forman el cubrimiento m�nimo.
* @param conc Conclusi�n de las reglas que se van a crear.
* @param minterms Mint�rminos que forman el cubrimiento para la conclusi�n
* anterior.
*
*/
public void buildRule(Conclusion conc, Set minterms) {
System.out.println("Para la conclusi�n " + conc.toXfl() + " el cubrimiento m�nimo encontrado es:");
Iterator it1 = minterms.iterator();
while(it1.hasNext()){
System.out.println("" + (XfspMinterm) it1.next());
}
//premisa de la regla que se est� creando en cada momento
Relation premise = null;
//cuenta el n�mero de mint�rminos que se han tratado
int numMinterms = 0;
//iterador que permite recorrer todos los mint�rminos que forman el
//cubrimiento m�nimo para una conclusi�n
Iterator it = minterms.iterator();
//mientras quedan mint�rminos por ser tratados...
while (it.hasNext()) {
//...obtiene un nuevo mint�rmino
XfspMinterm minterm = (XfspMinterm) it.next();
//obtiene el conjunto la relaci�n asociada al mint�rmino anterior
Relation mintermRel = buildMinterm(minterm);
//si se ha tratado alg�n mint�rmino anteriormente...
if (numMinterms > 0) {
//...la premisa la formar� la disyunci�n de la premisa anterior y la
//relaci�n asociada al mint�rmino actual
premise = Relation.create(Relation.OR, premise, mintermRel, null, null,
newRulebase);
}
//en caso de que sea el primer mint�rmino tratado...
else if (numMinterms == 0) {
//...la premisa la formar� la relaci�n asociada al mint�rmino actual
premise = mintermRel;
}
//incrementa el n�mero de mint�rminos tratados
numMinterms++;
}
//crea una nueva regla que tiene como premisa la que se ha creado a partir
//del conjunto de mint�rminos tratado...
Rule rule = new Rule(premise);
//...y le a�ade la conclusi�n
rule.add(conc);
//a�ade la regla creada a la base de reglas que se est� creando
newRulebase.addRule(rule);
//TODO - eliminar esto
//System.out.println("Para la conclusi�n " + conc.toXfl() + " el cubrimiento m�nimo encontrado es:");
//Iterator it1 = minterms.iterator();
//while(it1.hasNext()){
//System.out.println("" + (XfspMinterm) it1.next());
//}
}
/**
* <p> <b>Descripci�n:</b> construye una relaci�n a partir de un mint�rmino.
* @param minterm Mint�rmino a partir del cual se construir� la nueva
* relaci�n.
* @return Relaci�n que expresa los valores que pueden tomar todas las
* variables que aparecen en el mint�rmino tratado.
*
*/
private Relation buildMinterm(XfspMinterm minterm) {
//map cuya clave son las variables del mint�rmino y cuyos valores son las
//funciones que toman dichas variables en el mint�rmino
Map variables = minterm.getVariables();
//relaci�n obtenida a partir del mint�rmino
Relation result = null;
//cuenta el n�mero de variables que se han tratado
int numVars = 0;
//iterador que permite obtener todas las variables del mint�rmino
Iterator it1 = variables.keySet().iterator();
//para todas las variables del mint�rmino que se est� tratando...
while (it1.hasNext()) {
//...obtiene una variable...
Variable var = (Variable) it1.next();
//...y el conjunto de funciones de pertenencia que toma dicha variable
Set s = (Set) variables.get(var);
//TODO - quitar esto
System.out.println("Construyendo premisa para el mint�rmino " + minterm.toString() + " *****************");
//construye una relaci�n para la variable que se est� tratando a partir
//del conjunto de funciones de pertenencia que puede tomar
Relation rel = buildVariable(var, s);
//si no se ha tratado ninguna variable anteriormente...
if (numVars == 0) {
//...la relaci�n resultado ser� la que se acaba de construir
result = rel;
}
//si se ha tratado alguna variable anteriormente pero no se ha contruido
//ninguna relaci�n...
else if (numVars > 0 && result == null) {
//...la relaci�n resultado ser� la que se acaba de construir
result = rel;
}
//si se ha tratado alguna variable anteriormente y se ha podido contruir
//alguna relaci�n...
else if (numVars > 0 && rel != null) {
//...la nueva relaci�n ser� igual a la conjunci�n de la relaci�n
//antigua y la relaci�n que se acaba de construir
result = Relation.create(Relation.AND, result, rel, null, null,
newRulebase);
}
//incremente el n�mero de variables que se han tratado
numVars++;
}
if(result==null){
maintainExtremeMF = true;
result = buildMinterm(minterm);
maintainExtremeMF = false;
}
System.out.println("la premisa construida es " + result.toXfl());
//devuelve la relaci�n creada
return result;
}
/**
* <p> <b>Descripci�n:</b> construye una relaci�n a partir de una variable y
* el conjunto de funciones de pertenencia que dicha variable puede tomar.
* @param var Variable para la que se crear� la relaci�n.
* @param MFs Funciones de pertenenica que puede tomar la variable.
* @return Relaci�n que expresa las funciones de pertenencia que puede tomar
* la variable como valor.
*
*/
private Relation buildVariable(Variable var, Set MFs) {
//relaci�n que se construir� a partir de la variable y el conjunto de
//funciones de pertenencia que puede tomar
Relation result = null;
//si la variable tiene asignadas todas las funciones de pertenencia de su
//tipo menos una y, adem�s, no se deben mantener las funciones de pertenecia
//de los extremos del tipo...
if (!maintainExtremeMF && MFs.size() == (var.getType().getMembershipFunctions().length - 1)) {
//indica si se ha encontrado la �nica funci�n de pertenencia que no se
//asignado a la variable
boolean found = false;
//guardar� la �nica funci�n de pertenencia no asignada a la variable
LinguisticLabel mf = null;
//funciones de pertenencia del tipo al que pertenece la variable
LinguisticLabel [] mfs = var.getType().getMembershipFunctions();
//para todas las funciones de pertenencia del tipo de la variable y
//mientras que no se haya encontrado a�n la �nica funci�n de pertenencia
//no asignada a la variable...
for (int i = 0; i < mfs.length && !found; i++) {
//...obtiene la siguiente funci�n de pertenencia del tipo
mf = mfs[i];
//si el conjunto de funciones de pertenencia asignadas a la variable no
//contiene la funci�n de pertenencia actual...
if (!MFs.contains(new Integer(i))) {
//...ha encontrado la �nica funci�n de pertenencia no asignada a la
//variable y termina la b�squeda
found = true;
}
}
//la relaci�n correspondiente a la asignaci�n de la variable analizada es
//de tipo ISNOT con la funci�n de pertenencia que se ha encontrado
result = Relation.create(Relation.ISNOT, null, null, var, mf, newRulebase);
}
else if (maintainExtremeMF || (MFs.size() < (var.getType().getMembershipFunctions().length - 1) && !maintainExtremeMF)) {
//System.out.println("variable " + var + " con funciones de pertenencia " + MFs);
TreeSet sortedMFs = new TreeSet(MFs);
//Iterator it = sortedMFs.iterator();
//Integer lower = null;
//Integer upper = null;
Relation newRel = null;
//System.out.println("Para la variable " + var + " la menor funci�n de pertenencia es " + sortedMFs.first() + " y la mayor es " + sortedMFs.last());
if (((Integer)sortedMFs.first()).intValue() == ((Integer)sortedMFs.last()).intValue()) {
newRel = Relation.create(Relation.IS, null, null, var, var.getType().getMembershipFunctions()[((Integer)sortedMFs.first()).intValue()], newRulebase);
}
else if(((Integer)sortedMFs.last()).intValue() == (var.getType().getMembershipFunctions().length-1) && !maintainExtremeMF){
newRel = Relation.create(Relation.GR_EQ, null, null, var, var.getType().getMembershipFunctions()[((Integer)sortedMFs.first()).intValue()], newRulebase);
}
else if(((Integer)sortedMFs.first()).intValue() == 0 && !maintainExtremeMF){
newRel = Relation.create(Relation.SM_EQ, null, null, var, var.getType().getMembershipFunctions()[((Integer)sortedMFs.last()).intValue()], newRulebase);
}
else if(((Integer)sortedMFs.first()).intValue() == 0 && ((Integer)sortedMFs.last()).intValue() == var.getType().getMembershipFunctions().length && maintainExtremeMF){
Relation lowerRel = Relation.create(Relation.GR_EQ, null, null, var,
var.getType().
getMembershipFunctions()[((Integer)sortedMFs.first()).intValue()], newRulebase);
Relation upperRel = Relation.create(Relation.SM_EQ, null, null, var,
var.getType().
getMembershipFunctions()[((Integer)sortedMFs.last()).intValue()], newRulebase);
newRel = Relation.create(Relation.AND, lowerRel, upperRel, null, null,
newRulebase);
}
else { //if(((Integer)sortedMFs.first()).intValue() < ((Integer)sortedMFs.last()).intValue() && maintainExtremeMF) {
Relation lowerRel = Relation.create(Relation.GR_EQ, null, null, var,
var.getType().
getMembershipFunctions()[((Integer)sortedMFs.first()).intValue()], newRulebase);
Relation upperRel = Relation.create(Relation.SM_EQ, null, null, var,
var.getType().
getMembershipFunctions()[((Integer)sortedMFs.last()).intValue()], newRulebase);
newRel = Relation.create(Relation.AND, lowerRel, upperRel, null, null,
newRulebase);
}
if (result != null) {
result = Relation.create(Relation.OR, result, newRel, null, null,
newRulebase);
}
else {
result = newRel;
}
}
/*
if(it.hasNext()){
lower = (Integer) it.next();
upper = lower;
}
while (it.hasNext()) {
Integer aux = (Integer) it.next();
if (aux.intValue() == (upper.intValue() + 1)) {
//System.out.println("seguimos mirando funciones de pertenencia...");
upper = aux;
//System.out.println("ahora upper vale " + upper.intValue() + " y lower vale " + lower.intValue());
}
else{
System.out.println("no hemos entrado por la primera rama!!! revisar!!!");
}
//estas opciones se toman cuando ya no se pueden seguir agrupando
//funciones de pertenencia
if (aux.intValue() > (upper.intValue() + 1) &&
upper.intValue() > lower.intValue()) {
//System.out.println("hemos terminado por aki..");
Relation lowerRel = Relation.create(Relation.GR_EQ, null, null, var,
var.getType().
getMembershipFunctions()[
lower.intValue()], newRulebase);
Relation upperRel = Relation.create(Relation.SM_EQ, null, null, var,
var.getType().
getMembershipFunctions()[
upper.intValue()], newRulebase);
newRel = Relation.create(Relation.AND, lowerRel, upperRel, null, null,
newRulebase);
//System.out.println("regla creada en la primera opci�n " + newRel.toXfl());
if (result != null) {
//result = Relation.create(Relation.AND, result, newRel, null, null,
// newRulebase);
result = Relation.create(Relation.OR, result, newRel, null, null,
newRulebase);
}
else {
result = newRel;
}
lower = aux;
upper = aux;
}
else if (aux.intValue() > (upper.intValue() + 1) &&
upper.intValue() == lower.intValue()) {
newRel = Relation.create(Relation.IS, null, null, var,
var.getType().getMembershipFunctions()[lower.
intValue()], newRulebase);
//System.out.println("regla creada en la quinta opcion " + newRel.toXfl());
if (result != null) {
result = Relation.create(Relation.OR, result, newRel, null, null,
newRulebase);
}
else {
result = newRel;
}
lower = aux;
upper = aux;
}
}
if (!it.hasNext() &&
upper.intValue() == var.getType().getMembershipFunctions().length &&
upper.intValue() > lower.intValue()) {
//System.out.println("ya hemos terminado por ahora...");
newRel = Relation.create(Relation.GR_EQ, null, null, var,
var.getType().getMembershipFunctions()[
lower.intValue()], newRulebase);
//System.out.println("regla creada al final en la primera opcion " + newRel.toXfl());
if (result != null) {
result = Relation.create(Relation.OR, result, newRel, null, null,
newRulebase);
}
else {
result = newRel;
}
}
if (!it.hasNext() &&
upper.intValue() < var.getType().getMembershipFunctions().length &&
upper.intValue() > lower.intValue()) {
Relation lowerRel = Relation.create(Relation.GR_EQ, null, null, var,
var.getType().
getMembershipFunctions()[
lower.intValue()], newRulebase);
Relation upperRel = Relation.create(Relation.SM_EQ, null, null, var,
var.getType().
getMembershipFunctions()[
upper.intValue()], newRulebase);
newRel = Relation.create(Relation.AND, lowerRel, upperRel, null, null,
newRulebase);
//System.out.println("regla creada al final en la segunda opcion " + newRel.toXfl());
if (result != null) {
result = Relation.create(Relation.OR, result, newRel, null, null,
newRulebase);
}
else {
result = newRel;
}
}
else if (!it.hasNext() && upper.intValue() == lower.intValue()) {
newRel = Relation.create(Relation.IS, null, null, var,
var.getType().getMembershipFunctions()[lower.
intValue()], newRulebase);
//System.out.println("regla creada al final en la tercera opcion " + newRel.toXfl());
if (result != null) {
result = Relation.create(Relation.OR, result, newRel, null, null,
newRulebase);
}
else {
result = newRel;
}
}
}
*/
//parte antigua
/*
Relation newRel;
int numMFs = 0;
while (it2.hasNext()) {
Integer i = (Integer) it2.next();
LinguisticLabel mf = var.getType().getMembershipFunctions()[i.intValue()];
newRel = Relation.create(Relation.IS, null, null, var, mf, newRulebase);
if (numMFs > 0) {
result = Relation.create(Relation.OR, result, newRel, null, null,
newRulebase);
}
else if (numMFs == 0) {
result = newRel;
}
numMFs++;
}*/
return result;
}
}