/***********************************************************************
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.Associative_Classification.ClassifierFuzzyFARCHD;
/**
* <p>Title: RuleBase</p>
* <p>Description: This class contains the representation of a Rule Set</p>
* <p>Copyright: Copyright KEEL (c) 2007</p>
* <p>Company: KEEL </p>
* @author Written by Jesus Alcala (University of Granada) 09/02/2011
* @version 1.0
* @since JDK1.5
*/
import java.util.*;
import org.core.*;
public class RuleBase {
ArrayList<Rule> ruleBase;
DataBase dataBase;
myDataset train;
int n_variables, K, nUncover, typeInference, defaultRule;
int[] nUncoverClas;
double fitness;
public boolean BETTER(int a, int b) {
if (a > b) return true;
return false;
}
public RuleBase() {
}
/**
* <p>
* Builder
* </p>
* @param dataBase Data Base
* @param train Training dataset
* @param K Covered patterns in the second stage are completely eliminated when they have been covered more than K times.
* @param typeInference Two option: 0) the class of the rule with the best matching; 1) the class with the best matching
* @return Rule Base
*/
public RuleBase(DataBase dataBase, myDataset train, int K, int typeInference) {
this.ruleBase = new ArrayList<Rule> ();
this.dataBase = dataBase;
this.train = train;
this.n_variables = dataBase.numVariables();
this.fitness = 0.0;
this.K = K;
this.typeInference = typeInference;
this.defaultRule = -1;
this.nUncover = 0;
this.nUncoverClas = new int[this.train.getnClasses()];
}
/**
* <p>
* Clone
* </p>
* @return A copy of the Rule Base
*/
public RuleBase clone() {
RuleBase br = new RuleBase();
br.ruleBase = new ArrayList<Rule> ();
for (int i = 0; i < this.ruleBase.size(); i++) br.ruleBase.add((this.ruleBase.get(i)).clone());
br.dataBase = this.dataBase;
br.train = this.train;
br.n_variables = this.n_variables;
br.fitness = this.fitness;
br.K = this.K;
br.typeInference = this.typeInference;
br.defaultRule = this.defaultRule;
br.nUncover = this.nUncover;
br.nUncoverClas = new int[this.train.getnClasses()];
for (int i = 0; i < this.train.getnClasses(); i++) br.nUncoverClas[i] = this.nUncoverClas[i];
return (br);
}
public void add(Rule rule) {
this.ruleBase.add(rule);
}
public void add(RuleBase ruleBase) {
int i;
for (i=0; i<ruleBase.size(); i++) {
this.ruleBase.add(ruleBase.get(i).clone());
}
}
public void add(Itemset itemset) {
int i;
Item item;
int[] antecedent = new int[n_variables];
for (i=0; i < n_variables; i++) antecedent[i] = -1; // Don't care
for (i=0; i < itemset.size(); i++) {
item = itemset.get(i);
antecedent[item.getVariable()] = item.getValue();
}
Rule r = new Rule(this.dataBase);
r.asignaAntecedente(antecedent);
r.setConsequent(itemset.getClas());
r.setConfidence(itemset.getSupportClass() / itemset.getSupport());
r.setSupport(itemset.getSupportClass());
this.ruleBase.add(r);
}
public Rule get(int pos) {
return (this.ruleBase.get(pos));
}
public int size() {
return (this.ruleBase.size());
}
public void sort () {
Collections.sort(this.ruleBase);
}
public Rule remove(int pos) {
return (this.ruleBase.remove(pos));
}
public void clear() {
this.ruleBase.clear();
this.fitness = 0.0;
}
public int getTypeInference() {
return (this.typeInference);
}
public double getAccuracy() {
return (this.fitness);
}
public void setDefaultRule() {
int i, bestRule;
bestRule = 0;
for (i=1; i < this.train.getnClasses(); i++) {
if (this.train.numberInstances(bestRule) < this.train.numberInstances(i)) bestRule = i;
}
this.defaultRule = bestRule;
}
public boolean hasUncover() {
return (this.nUncover > 0);
}
public int getUncover() {
return (this.nUncover);
}
public int getK() {
return (this.K);
}
public void evaluate() {
int nHits, prediction;
nHits = 0;
this.nUncover = 0;
for (int j = 0; j < this.train.getnClasses(); j++) this.nUncoverClas[j] = 0;
for (int j = 0; j < train.size(); j++) {
prediction = this.FRM(train.getExample(j));
if (this.train.getOutputAsInteger(j) == prediction) nHits++;
if (prediction < 0) {
this.nUncover++;
this.nUncoverClas[this.train.getOutputAsInteger(j)]++;
}
}
this.fitness = (100.0 * nHits) / (1.0 * this.train.size());
}
public void evaluate(double[] gene, int[] selected) {
int nHits, prediction;
this.dataBase.decode(gene);
nHits = 0;
this.nUncover = 0;
for (int j = 0; j < this.train.getnClasses(); j++) this.nUncoverClas[j] = 0;
for (int j = 0; j < train.size(); j++) {
prediction = this.FRM(train.getExample(j), selected);
if (this.train.getOutputAsInteger(j) == prediction) nHits++;
if (prediction < 0) {
this.nUncover++;
this.nUncoverClas[this.train.getOutputAsInteger(j)]++;
}
}
this.fitness = (100.0 * nHits) / (1.0 * this.train.size());
}
public int FRM(double[] example) {
if (this.typeInference == 0) return FRM_WR(example);
else return FRM_AC(example);
}
public int FRM(double[] example, int[] selected) {
if (this.typeInference == 0) return FRM_WR(example, selected);
else return FRM_AC(example, selected);
}
private int FRM_WR(double[] example, int[] selected) {
int clas;
double max, degree;
max = 0.0;
clas = defaultRule;
for (int i = 0; i < this.ruleBase.size(); i++) {
if (selected[i] > 0) {
Rule r = this.ruleBase.get(i);
degree = r.matching(example);
if (degree > max) {
max = degree;
clas = r.getClas();
}
}
}
return clas;
}
private int FRM_WR(double[] example) {
int clas;
double max, degree;
max = 0.0;
clas = defaultRule;
for (int i = 0; i < this.ruleBase.size(); i++) {
Rule r = this.ruleBase.get(i);
degree = r.matching(example);
if (degree > max) {
max = degree;
clas = r.getClas();
}
}
return clas;
}
private int FRM_AC(double[] example, int[] selected) {
int i, clas;
double degree, maxDegree;
double[] degreeClass;
clas = defaultRule;
degreeClass = new double[this.train.getnClasses()];
for (i=0; i < this.train.getnClasses(); i++) degreeClass[i] = 0.0;
for (i = 0; i < this.ruleBase.size(); i++) {
if (selected[i] > 0) {
Rule r = this.ruleBase.get(i);
degree = r.matching(example);
degreeClass[r.getClas()] += degree;
}
}
maxDegree = 0.0;
for (i = 0; i < this.train.getnClasses(); i++) {
if (degreeClass[i] > maxDegree) {
maxDegree = degreeClass[i];
clas = i;
}
}
return clas;
}
private int FRM_AC(double[] example) {
int i, clas;
double degree, maxDegree;
double[] degreeClass;
clas = defaultRule;
degreeClass = new double[this.train.getnClasses()];
for (i=0; i < this.train.getnClasses(); i++) degreeClass[i] = 0.0;
for (i = 0; i < this.ruleBase.size(); i++) {
Rule r = this.ruleBase.get(i);
degree = r.matching(example);
degreeClass[r.getClas()] += degree;
}
maxDegree = 0.0;
for (i = 0; i < this.train.getnClasses(); i++) {
if (degreeClass[i] > maxDegree) {
maxDegree = degreeClass[i];
clas = i;
}
}
return clas;
}
public int hasClassUncovered (int[] selected) {
int i, count;
int[] cover;
cover = new int[this.train.getnClasses()];
for (i=0; i < cover.length; i++) {
if (this.train.numberInstances(i) > 0) cover[i] = 0;
else cover[i] = 1;
}
for (i = 0; i < this.ruleBase.size(); i++) {
if (selected[i] > 0) {
cover[this.ruleBase.get(i).getClas()]++;
}
}
count = 0;
for (i=0; i < cover.length; i++) {
if (cover[i] == 0) count++;
}
return count;
}
public void reduceRules(int clas) {
ArrayList<ExampleWeight> exampleWeight;
int i, posBestWracc, nExamples, nRuleSelect;
double bestWracc;
int[] selected;
Rule rule;
exampleWeight = new ArrayList<ExampleWeight> ();
for (i=0; i < this.train.size(); i++) exampleWeight.add(new ExampleWeight(this.K));
selected = new int[this.ruleBase.size()];
for (i=0; i < this.ruleBase.size(); i++) selected[i] = 0;
nExamples = this.train.numberInstances(clas);
nRuleSelect = 0;
do {
bestWracc = -1.0;
posBestWracc = -1;
for (i=0; i < this.ruleBase.size(); i++) {
if (selected[i] == 0) {
rule = this.ruleBase.get(i);
rule.calculateWracc(this.train, exampleWeight);
if (rule.getWracc() > bestWracc) {
bestWracc = rule.getWracc();
posBestWracc = i;
}
}
}
if (posBestWracc > -1) {
selected[posBestWracc] = 1;
nRuleSelect++;
rule = this.ruleBase.get(posBestWracc);
nExamples -= rule.reduceWeight(this.train, exampleWeight);
}
} while ((nExamples > 0) && (nRuleSelect < this.ruleBase.size()) && (posBestWracc > -1));
for (i=this.ruleBase.size() - 1; i >= 0; i--) {
if (selected[i] == 0) this.ruleBase.remove(i);
}
exampleWeight.clear();
System.gc();
}
public String printString() {
int i, j, ant;
String [] names = this.train.names();
String [] clases = this.train.clases();
String stringOut = new String("");
ant = 0;
for (i = 0; i < this.ruleBase.size(); i++) {
Rule r = this.ruleBase.get(i);
stringOut += (i+1)+": ";
for (j = 0; j < n_variables && r.antecedent[j] < 0; j++);
if (j < n_variables && r.antecedent[j] >= 0) {
stringOut += names[j]+" IS " + r.dataBase.print(j,r.antecedent[j]);
ant++;
}
for (j++; j < n_variables-1; j++) {
if (r.antecedent[j] >=0) {
stringOut += " AND " + names[j]+" IS " + r.dataBase.print(j,r.antecedent[j]);
ant++;
}
}
if (j < n_variables && r.antecedent[j] >= 0) {
stringOut += " AND " + names[j]+" IS " + r.dataBase.print(j,r.antecedent[j]) + ": " + clases[r.clas];
ant++;
}
else stringOut += ": " + clases[r.clas];
stringOut += " CF: " + r.getConfidence() + "\n";
}
stringOut += "\n\n";
stringOut += "@supp and CF:\n\n";
for (i = 0; i < this.ruleBase.size(); i++) {
Rule rule = this.ruleBase.get(i);
stringOut += (i+1)+": ";
stringOut += "supp: " + rule.getSupport() + " AND CF: " + rule.getConfidence() + "\n";
}
stringOut = "@Number of rules: " + this.ruleBase.size() + " Number of Antecedents by rule: " + ant * 1.0 / this.ruleBase.size() + "\n\n" + stringOut;
return (stringOut);
}
public void saveFile(String filename) {
String stringOut = new String("");
stringOut = printString();
Files.writeFile(filename, stringOut);
}
}