//--------------------------------------------------------------------------------//
// 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.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import xfuzzy.lang.Conclusion;
/**
* <p> <b>Descripci�n:</b> clase de objetos que encuentran el cubrimiento
* m�nimo para un conjunto de mint�rminos.
* <p> <b>E-mail</b>: <ADDRESS>joragupra@us.es</ADDRRESS>
* @author Jorge Agudo Praena
* @version 2.0
* @see XfspModel
* @see XfspTabularSimplifier
*
*/
public class XfspMinimalCoveringFinder {
//almacena los mint�rminos que ya han sido cubiertos
private Set coveredMinterms;
//almacena el cubrimiento m�nimo para un conjunto de mint�rminos asociado a
//una conclusi�n
private Map minimalCovering;
/**
* <p> <b>Descripci�n:</b> crea un objeto capaz de hallar el cubrimiento
* m�nimo necesario para un conjunto de mint�rminos asociado a una conclusi�n.
*
*/
public XfspMinimalCoveringFinder() {
minimalCovering = new HashMap();
}
/**
* <p> <b>Descripci�n:</b> encuentra el conjunto de mint�rminos que forman el
* cubrimiento m�nimo para un conjunto de mint�rminos dado.
* @param minterms Conjunto de mint�rminos cuyo cubrimiento m�nimo se quiere
* encontrar.
* @return Cubrimiento m�nimo para el conjunto original.
*
*/
public Map findMinimalCovering(Map minterms) {
//iterador para todas las claves del map que contiene los mint�rminos y que
//corresponde a conclusiones de la base de reglas
Iterator it = minterms.keySet().iterator();
//para todas las conclusiones cuyos mint�rminos han sido encontrados en la
//base de reglas...
while (it.hasNext()) {
//...obtiene la conclusi�n actual...
Conclusion conc = (Conclusion) it.next();
//...empieza asign�ndole como cubrimiento m�nimo una lista vac�a de
//mint�rminos...
minimalCovering.put(conc, new HashSet());
//...y obtiene su lista de mint�rminos e implicantes
List l = (List) minterms.get(conc);
//calcula los mint�rminos iniciales de la conclusi�n que se est� tratando
Set initialMinterms = calculateInitialMinterms( (Set) l.get(0));
//TODO - eliminar esto
//System.out.println("*** mint�rminos a cubrir ***");
//Iterator it3 = initialMinterms.iterator();
//while (it3.hasNext()) {
//System.out.println(it3.next());
//}
//conjunto de mint�rminos cubiertos por el cubrimiento m�nimo que se ha
//encontrado
coveredMinterms = new HashSet();
//almacena si ya se han cubierto todos los mint�rminos para la conclusi�n
boolean allCovered = false;
//nuevo
//mientras no se hayan cubierto todos los mint�rminos de para la
//conclusi�n que se est� tratando...
while (!allCovered) {
//...busca mint�rminos o implicantes en la lista obtenida tras aplicar
//el m�todo de simplificaci�n tabular, comenzando por aquellas
//implicantes que agrupan m�s mint�rminos...
for (int i = (l.size() - 1); i >= 0 && !allCovered; i--) {
//System.out.println("\nMiramos una iteraci�n m�s para atr�s...\n");
//...obtiene el conjunto de mint�rminos o implicantes de la iteraci�n
//actual de algoritmo
Set s = (Set) l.get(i);
//mint�rmino o implicante elegido de entre los disponibles en la
//iteraci�n actual
XfspMinterm selectedMinterm = null;
//n�mero de mint�rminos cubiertos por el mint�rmino o implicante
//seleccionado
int newCoveredMinterms = 0;
//indica si se ha elegido un mint�rmino o implicante de la iteraci�n
//que se est� examinando (se inicializa por defecto a cierto para
//poder entrar en el bucle siguiente)
boolean added = true;
//conjunto de mint�rminos elegidos para ser a�adidos al cubrimiento
//m�nimo de entre los disponibles en la iteraci�n actual del
//algoritmo de simplificaci�n tabular
Set addedMinterms = new HashSet();
//mientras se sigan a�adiendo mint�rminos o implicantes al cubrimiento
//m�nimo y queden mint�rminos por cubrir de entre los de la conclusi�n
//que se est� analizando...
while (added && !allCovered) {
//...indica que todav�a no se ha a�adido ning�n mint�rmino o
//implicante en la iteraci�n actual
added = false;
//iterador que permite recorrer las listas de mint�rminos de la
//iteraci�n actual
Iterator it1 = s.iterator();
//mientras queden listas de mint�rminos de la iteraci�n actual por
//ser procesados...
while (it1.hasNext()) {
//...obtiene una lista de mint�rminos de la iteraci�n actual
List mintermsList = (List) it1.next();
//para todos los conjuntos de mint�rminos de la lista que se est�
//tratando...
for (int j = 0; j < mintermsList.size() && !allCovered; j++) {
//...obtiene un conjunto de mint�rminos
Set aux = (Set) mintermsList.get(j);
//iterador que permite recorrer todos los mint�rminos o
//implicantes del conjunto de mint�rminos actual
Iterator it2 = aux.iterator();
//para todos los mint�rminos o implicantes del conjunto
//actual...
while (it2.hasNext()) {
//...obtiene un mint�rmino o implicante del conjunto actual
XfspMinterm maux = (XfspMinterm) it2.next();
//obtiene el n�mero de mint�rminos de los cubiertos por el
//mint�rmino o implicante actual que no han sido cubierto a�n
//por ning�n mint�rmino o implicante de los seleccionados
//para el cubrimiento m�nimo
int nonCovered = nonCoveredMinterms(maux);
//si el n�mero de nuevos mint�rminos cubiertos por el
//mint�rmino o implicante actual es superior al mint�rmino o
//implicante seleccionado temporalmente hasta el momento para
//ser a�adido al cubrimiento m�nimo y dicho mint�rmino o
//implicante no ha sido a�adido a�n en la iteraci�n actual...
//System.out.println("Implicante analizada " + maux);
if (nonCovered > newCoveredMinterms &&
!addedMinterms.contains(maux)) {
//System.out.println("Se elige provisionalmente para el cubrimiento porque es mejor que " + selectedMinterm);
//...selecciona de manera provisional el mint�rmino o
//implicante actual...
selectedMinterm = maux;
//...indica que se ha elegido un mint�rmino o implicante de
//entre los disponibles en la iteraci�n actual...
added = true;
//...y almacena el n�mero de mint�rminos nuevos cubiertos
//por el seleccionado
newCoveredMinterms = nonCovered;
}
//si el n�mero de nuevos mint�rminos cubiertos por el
//mint�rmino o implicante actual es igual al mint�rmino o
//implicante seleccionado temporalmente hasta el momento para
//ser a�adido al cubrimiento m�nimo y dicho mint�rmino o
//implicante no ha sido a�adido a�n en la iteraci�n actual y
//ya se hab�a seleccionado un mint�rmino o implicante
//anteriormente (esto evita comportamientos extra�os para el
//primer mint�rmino o implicante tratado cuando a�n no se ha
//seleccionado ninguno anteriormente)...
else if (nonCovered == newCoveredMinterms &&
!addedMinterms.contains(maux) && selectedMinterm != null) {
//...si el n�mero de mint�rminos cubiertos por el actual es
//mayor que el que cubr�a el mint�rmino o implicante que
//hab�a sido seleccionado anteriormente...
if (maux.getCoveredMinterms().size() >
selectedMinterm.getCoveredMinterms().size()) {
//...selecciona de manera provisional el mint�rmino o
//implicante actual...
selectedMinterm = maux;
//...e indica que se ha elegido un mint�rmino o implicante
//de entre los disponibles en la iteraci�n actual
added = true;
}
}
}
}
}
//si se ha seleccionado alg�n mint�rmino o implicante de la
//iteraci�n actual...
if (added) {
//System.out.println("se ha elegido definitivamente para el cubrimiento m�nimo " + selectedMinterm);
//...a�ade el mint�rmino o implicante seleccionado al conjunto de
//mint�rminos o implicantes a�adidos de los disponibles en la
//iteraci�n actual
addedMinterms.add(selectedMinterm);
//...y tambi�n lo a�ade al cubrimiento m�nimo encontrado
( (Set) minimalCovering.get(conc)).add(selectedMinterm);
//a�ade al los mint�rminos cubiertos por el cubrimiento m�nimo
//actual los que cubre el mint�rmino o implicante seleccionado
coveredMinterms.addAll(selectedMinterm.getCoveredMinterms());
//tratamiento para redundantes
XfspMinterm redundantMinterm=findRedundantMinterms((Set) minimalCovering.get(conc));
while(redundantMinterm!=null){
System.out.println("El mintermino " + redundantMinterm + " es redundante!!!!!!");
((Set) minimalCovering.get(conc)).remove(redundantMinterm);
redundantMinterm=findRedundantMinterms((Set) minimalCovering.get(conc));
}
//si el n�mero de mint�rminos cubiertos por el cubrimiento min�mo
//iguala a los mint�rminos que ten�a que cubrir para la conclusi�n
//actual...
if (coveredMinterms.size() == initialMinterms.size()) {
//...termina con la b�squeda del cubrimiento m�nimo
allCovered = true;
}
//creo que esto lo puede resolver todo
newCoveredMinterms = 0;
selectedMinterm = null;
}
}
//if (allCovered) {
//System.out.println("Todos los minterminos fueron cubiertos!!!!!!");
//}
}
}
//antiguo
/*
//mientras no se hayan cubierto todos los mint�rminos de la conclusi�n
//que se est� tratando...
while (!allCovered) {
//...examina todas las iteraciones de la conclusi�n actual, empezando
//por la �ltima, que es la que contiene implicantes mayores
for (int i = (l.size() - 1); i >= 0 && !allCovered; i--) {
//obtiene el conjunto de mint�rminos correspondiente a la iteraci�n
//que se est� examinando
Set s = (Set) l.get(i);
//examina todas las implicantes de la iteraci�n
Iterator it1 = s.iterator();
while (it1.hasNext()) {
//obtiene una lista de implicantes
List mintermsList = (List) it1.next();
//trata todos las implicantes de la lista mientras no hayan sido
//cubiertos todos los mint�rminos
for (int j = 0; j < mintermsList.size() && !allCovered; j++) {
//obtiene una lista de mint�rminos
Set saux = (Set) mintermsList.get(j);
//itera sobre todos los mint�rminos
Iterator it2 = saux.iterator();
while (it2.hasNext()) {
//mint�rmino actual
XfspMinterm maux = (XfspMinterm) it2.next();
//si no han sido cubiertos todos los mint�rminos iniciales...
if (!allMintermsCovered(maux.getCoveredMinterms())) {
//a�ade el mint�rmino a la cubertura de la conclusi�n tratada
( (Set) minimalCovering.get(conc)).add(maux);
System.out.println("se a�ade el mintermino " + maux);
System.out.println("porque cubre los minterminos");
it3 = maux.getCoveredMinterms().iterator();
while(it3.hasNext()){
System.out.println(it3.next());
}
//a�ade al conjunto de mint�rminos cubiertos aquellos que
//cubre la implicante que se acaba de a�adir
coveredMinterms.addAll(maux.getCoveredMinterms());
//si el conjunto de mit�rminos cubiertos ha alcanzado en
//tama�o al de mint�rminos iniciales para la conclusi�n
//tratada...
if (coveredMinterms.size() == initialMinterms.size()) {
//...se indica que ya se han cubierto todos los mint�rminos
//de la conclusi�n tratada
allCovered = true;
}
}
}
}
}
}
}*/
/*
System.out.println("*** mint�rminos cubiertos ***");
it3 = coveredMinterms.iterator();
while(it3.hasNext()){
System.out.println(it3.next());
}
*/
}
//System.out.println("cubrimiento minimo encontrado");
//Iterator it3 = minimalCovering.values().iterator();
//while (it3.hasNext()) {
//System.out.println(it3.next());
//}
//devuelve el cubrimiento m�nimo encontrado
return minimalCovering;
}
/**
* <p> <b>Descripci�n:</b> busca en un conjunto de mint�rminos e implicantes
* uno que sea redundante, es decir, para el que todos los mint�rminos
* cubiertos por �l ya sean cubiertos por el resto de los miembros del
* conjunto.
* @param minimalCovering Conjunto de mint�rminos o implicantes.
* @return Devuelve una implicante redundante si la hay en el conjunto o null
* en caso contrario.
*
*/
private XfspMinterm findRedundantMinterms(Set minimalCovering){
Iterator it = minimalCovering.iterator();
Set clonedSet = (Set) ((HashSet) minimalCovering).clone();
boolean found = false;
XfspMinterm redundantMinterm = null;
while(it.hasNext() && !found){
XfspMinterm aux = (XfspMinterm) it.next();
clonedSet.remove(aux);
// System.out.println("conjunto original\n" + minimalCovering);
// System.out.println("se examina " + aux);
// System.out.println("Conjunto clonado tras quitarlo\n" + clonedSet);
Set clonedSetCoveredMinterms = getCoveredMinterms(clonedSet);
// System.out.println("Los que quedan cubren\n" + clonedSetCoveredMinterms);
if(clonedSetCoveredMinterms.containsAll(aux.getCoveredMinterms())){
redundantMinterm = aux;
found = true;
}
else{
clonedSet.add(aux);
}
}
return redundantMinterm;
}
/**
* <p> <b>Descripci�n:</b> calcula el conjunto de mint�rminos cubiertos por
* todos las implicantes de un conjunto dado.
* @param mintermsSet Conjunto de mint�rminos o implicantes.
* @return Conjunto de mint�rminos cubiertos por todas las implicantes del
* conjunto.
*
*/
private Set getCoveredMinterms(Set mintermsSet){
Set result = new HashSet();
Iterator it = mintermsSet.iterator();
while(it.hasNext()){
XfspMinterm aux = (XfspMinterm) it.next();
result.addAll(aux.getCoveredMinterms());
}
return result;
}
/**
* <p> <b>Descripci�n:</b> calcula el conjunto de mint�rminos iniciales para
* una determinada conclusi�n.
* @param minterms Conjunto de mint�rminos asociados a una conclusi�n.
* @return Conjunto inicial de mint�rminos.
*
*/
private Set calculateInitialMinterms(Set init) {
//almacena el conjunto de mint�rminos iniciales asociados a una conclusi�n
Set initialMinterms = new HashSet();
//itera sobre el conjunto de listas de mint�rminos de entrada
Iterator it = init.iterator();
while (it.hasNext()) {
//obtiene una nueva lista de mint�rminos del conjunto de entrada...
List aux = (List) it.next();
//...y a�ade todos los mint�rminos de dicha lista al conjunto de
//mint�rminos iniciales
for (int i = 0; i < aux.size(); i++) {
initialMinterms.addAll( (Set) aux.get(i));
}
}
return initialMinterms;
}
/**
* <p> <b>Descripci�n:</b> calcula el n�mero de mint�rminos de los cubiertos
* por un mint�rmino o implicante que no ha sido cubierto a�n por el
* cubrimiento m�nimo actual.
* @param minterm Mint�rmino o implicante para el que se calcular� cu�ntos
* mint�rminos de los cubiertos por �l no han sido cubiertos a�n por el
* cubrimiento m�nimo actual.
* @return N�mero de mint�rminos cubiertos por un mint�rmino o implicante que
* no han sido cubiertos por el cubrimiento m�nimo actual.
*
*/
private int nonCoveredMinterms(XfspMinterm minterm) {
//n�mero de mint�rminos cubiertos por el mint�rmino o implicante que no han
//sido cubiertos a�n por el cubrimiento m�nimo actual (se inicializa a 0)
int result = 0;
//iterador que permite acceder a los mint�rminos cubiertos por el mint�rmino
//o implicante analizado
Iterator it = minterm.getCoveredMinterms().iterator();
//para todos los mint�rminos cubiertos por el mint�rmino o implicante...
while (it.hasNext()) {
//...si el mint�rmino actual a�n no ha sido cubierto por el cubrimiento
//m�nimo actual...
if (!coveredMinterms.contains(it.next())) {
//...incrementa el n�mero de mint�rminos no cubiertos por el cubrimiento
//m�nimo que son cubiertos por el mint�rmino o implicante analizado
result++;
}
}
return result;
}
}