/***********************************************************************
This file is part of KEEL-software, the Data Mining tool for regression,
classification, clustering, pattern mining and so on.
Copyright (C) 2004-2010
F. Herrera (herrera@decsai.ugr.es)
L. S�nchez (luciano@uniovi.es)
J. Alcal�-Fdez (jalcala@decsai.ugr.es)
S. Garc�a (sglopez@ujaen.es)
A. Fern�ndez (alberto.fernandez@ujaen.es)
J. Luengo (julianlm@decsai.ugr.es)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see http://www.gnu.org/licenses/
**********************************************************************/
package keel.Algorithms.Fuzzy_Rule_Learning.Genetic.GP_COACH;
import org.core.Randomize;
import java.util.ArrayList;
import java.util.Collections;
/**
* <p>Title: Fuzzy Antecedent </p>
*
* <p>Description: Fuzzy Antecedent for a variable in the GP-COACH algorithm </p>
*
* <p>Company: KEEL </p>
*
* @author Written by Victoria Lopez (University of Granada) 19/11/2011
* @version 1.5
* @since JDK1.5
*/
public class FuzzyAntecedent implements Comparable {
private ArrayList <Fuzzy> labels;
private int max_label;
private int var;
/**
* Default constructor
*/
public FuzzyAntecedent () {
}
/**
* Constructor with parameters. It creates a random fuzzy antecedent
* for a specified variable
*
* @param database Data Base associated to the rule that uses this antecedent
* @param var_selected Specified variable that uses this antecedent
*/
public FuzzyAntecedent (DataBase database, int var_selected) {
Fuzzy label;
max_label = database.numLabels();
labels = new ArrayList <Fuzzy> (max_label);
var = var_selected;
// Select randomly a set of labels and create the fuzzy labels for each selected value
for (int i=0; i<max_label; i++) {
if (Randomize.Rand() < 0.5) {
label = database.clone(var_selected, i);
labels.add(label);
}
}
}
/**
* Constructor with parameters. It creates a fuzzy antecedent using a given fuzzy label
* for a specified variable
*
* @param label Fuzzy label given to create this fuzzy antecedent
* @param var_selected Specified variable that uses this antecedent
* @param max_label Maximum number of labels this antecedent can tolerate
*/
public FuzzyAntecedent (Fuzzy label, int var_selected, int max) {
max_label = max;
labels = new ArrayList <Fuzzy> ();
var = var_selected;
labels.add(label);
}
/**
* Copy constructor for a FuzzyAntecedent from another FuzzyAntecedent
*
* @param original FuzzyAntecedent which will be used as base to create another FuzzyAntecedent
*/
public FuzzyAntecedent (FuzzyAntecedent original) {
max_label = original.max_label;
var = original.var;
labels = new ArrayList <Fuzzy> (original.labels.size());
for (int i=0; i<original.labels.size(); i++) {
Fuzzy copy_label = ((Fuzzy)original.labels.get(i)).clone();
labels.add(copy_label);
}
}
/**
* Checks if the fuzzy antecedent is a valid and representative antecedent for a rule
* or not. If there are no labels in the antecedent or if all the labels are in the
* antecedent, it is no use to use this antecedent.
*
* @return true if the labels selected form an antecedent, false if the labels selected
* do not form an antecedent (there are no labels, or all labels are selected)
*/
public boolean isValid() {
if ((labels.size() == 0) || (labels.size() == max_label))
return false;
else
return true;
}
/**
* Checks if the fuzzy antecedent represents an any condition. It happens when all the
* labels are in the antecedent, so it is no use to use this antecedent.
*
* @return true if all labels are selected to form an antecedent, thus creating an any condition
*/
public boolean isAny() {
if (labels.size() == max_label)
return true;
else
return false;
}
/**
* Obtains the variable related to the fuzzy antecedent
*
* @return the variable that uses this antecedent
*/
public int getAttribute () {
return var;
}
/**
* Obtains the number of labels used in this fuzzy antecedent as condition
*
* @return number of labels used in this fuzzy antecedent as condition
*/
public int getnLabels() {
return labels.size();
}
/**
* Computes the matching degree of a specified value with a set of fuzzy labels, using
* a specified t_conorm as OR operator
*
* @param value Real value that is going to be matched with the fuzzy labels in this fuzzy antecedent
* @param t_conorm T-conorm used as OR operator
* @return matching degree of the double value with the set of labels that represent an attribute
*/
public double matchingDegree(double value, int t_conorm) {
if (t_conorm == GP_COACH.MAXIMUM) {
return maximumMatchingDegree (value);
}
else if (t_conorm == GP_COACH.PROBABILISTIC_SUM) {
return probabilisticSumMatchingDegree (value);
}
else {
System.err.println("Unknown t-conorm for the computation of the compatibility degree");
System.exit(-1);
return -1.0;
}
}
/**
* Computes the matching degree of a specified value with a set of fuzzy labels, using
* MAXIMUM as OR operator
*
* @param value Real value that is going to be matched with the fuzzy labels in this fuzzy antecedent
* @return matching degree of the double value with the set of labels that represent an attribute
* using MAXIMUM as OR operator
*/
private double maximumMatchingDegree (double value) {
double maximum, membershipDegree;
maximum = 0.0;
for (int i = 0; i < labels.size() ; i++) {
membershipDegree = ((Fuzzy)labels.get(i)).Fuzzify(value);
maximum = Math.max(membershipDegree, maximum);
}
return (maximum);
}
/**
* Computes the matching degree of a specified value with a set of fuzzy labels, using
* PROBABILISTIC_SUM as OR operator
*
* @param value Real value that is going to be matched with the fuzzy labels in this fuzzy antecedent
* @return matching degree of the double value with the set of labels that represent an attribute
* using PROBABILISTIC_SUM as OR operator
*/
private double probabilisticSumMatchingDegree (double value) {
double probabilistic_sum, membershipDegree;
probabilistic_sum = 0.0;
for (int i = 0; i < labels.size() ; i++) {
membershipDegree = ((Fuzzy)labels.get(i)).Fuzzify(value);
probabilistic_sum = probabilistic_sum + membershipDegree - (probabilistic_sum * membershipDegree);
}
return (probabilistic_sum);
}
/**
* Change the labels associated to this fuzzy antecedent with the labels of the given
* antecedent
*
* @param var antecedent whose labels are going to be assigned to this antecedent
* @param data data base containing all the information about the labels used in this
* program
*/
public void changeLabels (FuzzyAntecedent var_fuzzy, DataBase data) {
Fuzzy label;
// First, we copy the maximum number of labels
max_label = data.numLabels();
// Then we copy the labels according to the variable that this antecedent uses
labels = new ArrayList <Fuzzy>(var_fuzzy.labels.size());
for (int i=0; i<var_fuzzy.labels.size(); i++) {
label = data.clone(var, ((Fuzzy)var_fuzzy.labels.get(i)).label);
labels.add(label);
}
}
/**
* Mix the labels associated to this FuzzyAntecedent with the labels associated to
* another FuzzyAntecedent
*
* @param var antecedent whose labels are going to be mixed to this antecedent
*/
public void mixLabels (FuzzyAntecedent var_fuzzy) {
Fuzzy label;
// First, we check if both fuzzy antecedents are compatible
if ((max_label != var_fuzzy.max_label) || (var != var_fuzzy.var)) {
System.err.println("We cannot mix incompatible fuzzy antecedents");
System.exit(-1);
}
// Mix the labels from the new fuzzy antecedent
for (int i=0; i<var_fuzzy.labels.size(); i++) {
boolean found = false;
for (int j=0; j<labels.size() && !found; j++) {
if (((Fuzzy)var_fuzzy.labels.get(i)).label == ((Fuzzy)labels.get(j)).label) {
found = true;
}
}
if (!found) {
label = (Fuzzy)var_fuzzy.labels.get(i);
labels.add(label);
}
}
}
/**
* Adds randomly a label to the label set of this fuzzy antecedent
*
* @param data data base containing all the information about the labels used
*/
public void addLabel (DataBase data) {
boolean found_label = false;
int selected_label;
// Find a label that we do not have in the label set yet
do {
selected_label = Randomize.Randint(0, max_label);
found_label = false;
for (int i=0; i<labels.size() && !found_label; i++) {
if (((Fuzzy)labels.get(i)).label == selected_label) {
found_label = true;
}
}
} while (found_label);
// Add this label to the Fuzzy set
Fuzzy new_label;
new_label = data.clone(var, selected_label);
labels.add(new_label);
}
/**
* Deletes randomly a label from the label set of this fuzzy antecedent
*/
public void deleteLabel () {
int selected_label;
// Select a label from the fuzzy antecedent
selected_label = Randomize.Randint(0, labels.size());
// Delete this label from the Fuzzy set
labels.remove(selected_label);
}
/**
* Changes randomly a label from the label set of this fuzzy antecedent to a non-existing label
* in this fuzzy antecedent
*
* @param data data base containing all the information about the labels used
*/
public void changeLabel (DataBase data) {
boolean found_label = false;
int new_label, old_label;
// Find a label that we do not have in the label set yet
do {
new_label = Randomize.Randint(0, max_label);
found_label = false;
for (int i=0; i<labels.size() && !found_label; i++) {
if (((Fuzzy)labels.get(i)).label == new_label) {
found_label = true;
}
}
} while (found_label);
// Select a label from the fuzzy antecedent
old_label = Randomize.Randint(0, labels.size());
// Delete this label from the Fuzzy set
labels.remove(old_label);
// Add the selected label to the Fuzzy set
Fuzzy new_label_in_antecedent;
new_label_in_antecedent = data.clone(var, new_label);
labels.add(new_label_in_antecedent);
}
/**
* String representation of a Fuzzy Antecedent in the GP-COACH algorithm.
*
* @return String a string containing the Fuzzy Antecedent
*/
public String printString() {
String fuzzy_string = "";
if (labels.size() == 1) {
fuzzy_string += (labels.get(0)).name;
}
else {
Collections.sort(labels);
fuzzy_string += "(";
for (int i=0; i<labels.size()-1; i++) {
fuzzy_string = fuzzy_string + labels.get(i).name + " OR ";
}
fuzzy_string = fuzzy_string + labels.get(labels.size()-1).name + ")";
}
return fuzzy_string;
}
/**
* Compares this object with the specified object for order, according to the number of variable measure
*
* @return a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object
*/
public int compareTo(Object a) {
if (((FuzzyAntecedent) a).var > this.var) {
return -1;
}
if (((FuzzyAntecedent) a).var < this.var) {
return 1;
}
return 0;
}
}