/***********************************************************************
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.AdHoc.Chi_RW;
import java.util.ArrayList;
import org.core.Files;
/**
* This class contains the representation of a Rule Set</p>
*
* @author Written by Alberto Fern�ndez (University of Granada) 29/10/2007
* @version 1.0
* @since JDK1.5
*/
public class RuleBase {
ArrayList<Rule> ruleBase;
DataBase dataBase;
int n_variables, n_labels, ruleWeight, inferenceType, compatibilityType;
String[] names, classes;
/**
* Rule Base Constructor
* @param dataBase DataBase the Data Base containing the fuzzy partitions
* @param inferenceType int the inference type for the FRM
* @param compatibilityType int the compatibility type for the t-norm
* @param ruleWeight int the rule weight heuristic
* @param names String[] the names for the features of the problem
* @param classes String[] the labels for the class attributes
*/
public RuleBase(DataBase dataBase, int inferenceType, int compatibilityType,
int ruleWeight, String[] names, String[] classes) {
ruleBase = new ArrayList<Rule>();
this.dataBase = dataBase;
n_variables = dataBase.numVariables();
n_labels = dataBase.numLabels();
this.inferenceType = inferenceType;
this.compatibilityType = compatibilityType;
this.ruleWeight = ruleWeight;
this.names = names.clone();
this.classes = classes.clone();
}
/**
* It checks if a specific rule is already in the rule base
* @param r Rule the rule for comparison
* @return boolean true if the rule is already in the rule base, false in other case
*/
private boolean duplicated(Rule r) {
int i = 0;
boolean found = false;
while ((i < ruleBase.size()) && (!found)) {
found = ruleBase.get(i).comparison(r);
i++;
}
return found;
}
/**
* Rule Learning Mechanism for the Chi et al.'s method
* @param train myDataset the training data-set
*/
public void Generation(myDataset train) {
for (int i = 0; i < train.size(); i++) {
Rule r = searchForBestAntecedent(train.getExample(i),
train.getOutputAsInteger(i));
r.assingConsequent(train, ruleWeight);
if ((!duplicated(r)) &&
(r.weight > 0)) {
ruleBase.add(r);
}
}
}
/**
* This function obtains the best fuzzy label for each variable of the example and assigns
* it to the rule
* @param example double[] the input example
* @param clas int the class of the input example
* @return Rule the fuzzy rule with the highest membership degree with the example
*/
private Rule searchForBestAntecedent(double[] example, int clas) {
Rule r = new Rule(n_variables, this.compatibilityType);
r.setClass(clas);
for (int i = 0; i < n_variables; i++) {
double max = 0.0;
int etq = -1;
double per;
for (int j = 0; j < n_labels; j++) {
per = dataBase.membershipFunction(i, j, example[i]);
if (per > max) {
max = per;
etq = j;
}
}
if (max == 0.0) {
System.err.println(
"There was an Error while searching for the antecedent of the rule");
System.err.println("Example: ");
for (int j = 0; j < n_variables; j++) {
System.err.print(example[j] + "\t");
}
System.err.println("Variable " + i);
System.exit(1);
}
r.antecedent[i] = dataBase.clone(i, etq);
}
return r;
}
/**
* It prints the rule base into an string
* @return String an string containing the rule base
*/
public String printString() {
int i, j;
String cadena = "";
cadena += "@Number of rules: " + ruleBase.size() + "\n\n";
for (i = 0; i < ruleBase.size(); i++) {
Rule r = ruleBase.get(i);
cadena += (i + 1) + ": ";
for (j = 0; j < n_variables - 1; j++) {
cadena += names[j] + " IS " + r.antecedent[j].name + " AND ";
}
cadena += names[j] + " IS " + r.antecedent[j].name + ": " +
classes[r.clas] + " with Rule Weight: " + r.weight + "\n";
}
return (cadena);
}
/**
* It writes the rule base into an ouput file
* @param filename String the name of the output file
*/
public void writeFile(String filename) {
String outputString = new String("");
outputString = printString();
Files.writeFile(filename, outputString);
}
/**
* Fuzzy Reasoning Method
* @param example double[] the input example
* @return int the predicted class label (id)
*/
public int FRM(double[] example) {
if (this.inferenceType == Fuzzy_Chi.WINNING_RULE) {
return FRM_WR(example);
} else {
return FRM_AC(example);
}
}
/**
* Winning Rule FRM
* @param example double[] the input example
* @return int the class label for the rule with highest membership degree to the example
*/
private int FRM_WR(double[] example) {
int clas = -1;
double max = 0.0;
for (int i = 0; i < ruleBase.size(); i++) {
Rule r = ruleBase.get(i);
double produc = r.compatibility(example);
produc *= r.weight;
if (produc > max) {
max = produc;
clas = r.clas;
}
}
return clas;
}
/**
* Additive Combination FRM
* @param example double[] the input example
* @return int the class label for the set of rules with the highest sum of membership degree per class
*/
private int FRM_AC(double[] example) {
int clas = -1;
double[] class_degrees = new double[1];
for (int i = 0; i < ruleBase.size(); i++) {
Rule r = ruleBase.get(i);
double produc = r.compatibility(example);
produc *= r.weight;
if (r.clas > class_degrees.length - 1) {
double[] aux = new double[class_degrees.length];
for (int j = 0; j < aux.length; j++) {
aux[j] = class_degrees[j];
}
class_degrees = new double[r.clas + 1];
for (int j = 0; j < aux.length; j++) {
class_degrees[j] = aux[j];
}
}
class_degrees[r.clas] += produc;
}
double max = 0.0;
for (int l = 0; l < class_degrees.length; l++) {
if (class_degrees[l] > max) {
max = class_degrees[l];
clas = l;
}
}
return clas;
}
}