/***********************************************************************
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.IVTURS;
import java.util.*;
import org.core.Randomize;
/**
* <p>Title: Rule</p>
* <p>Description: This class codes a Fuzzy Rule</p>
* <p>Copyright: KEEL Copyright (c) 2008</p>
* <p>Company: KEEL </p>
* @author Written by Jesus Alcala (University of Granada) 09/02/2011
* @author Modified by Jose Antonio Sanz (University of Navarra) 19/12/2011
* @author Modified by Alberto Fernandez (University of Jaen) 24/10/2013
* @version 1.2
* @since JDK1.6
*/
public class Rule implements Comparable {
int[] antecedent;
int clas, nAnts;
double conf[], supp[], wracc[];
DataBase dataBase;
/**
* <p>
* Create a rule with another one
* </p>
* @param r This a rule
* @return A copy of r
*/
public Rule(Rule r) {
this.antecedent = new int[r.antecedent.length];
for (int k = 0; k < this.antecedent.length; k++) {
this.antecedent[k] = r.antecedent[k];
}
this.clas = r.clas;
this.dataBase = r.dataBase;
this.conf = new double[2];
this.supp = new double[2];
this.wracc = new double[2];
this.conf[0] = r.conf[0];
this.conf[1] = r.conf[1];
this.supp[0] = r.supp[0];
this.supp[1] = r.supp[1];
this.nAnts = r.nAnts;
this.wracc[0] = r.wracc[0];
this.wracc[1] = r.wracc[1];
}
/**
* <p>
* Create a new rule
* </p>
* @param dataBase The database
* @return A rule
*/
public Rule(DataBase dataBase) {
this.antecedent = new int[dataBase.numVariables()];
for (int i = 0; i < this.antecedent.length; i++) this.antecedent[i] = -1; // Don't care
this.clas = -1;
this.dataBase = dataBase;
this.conf = new double[2];
this.supp = new double[2];
this.wracc = new double[2];
this.conf[0] = 0.0;
this.conf[1] = 0.0;
this.supp[0] = 0.0;
this.supp[1] = 0.0;
this.nAnts = 0;
this.wracc[0] = 0.0;
this.wracc[1] = 0.0;
}
/**
* <p>
* Clone
* </p>
* @return A copy of the rule
*/
public Rule clone() {
Rule r = new Rule(this.dataBase);
r.antecedent = new int[antecedent.length];
for (int i = 0; i < this.antecedent.length; i++) {
r.antecedent[i] = this.antecedent[i];
}
r.clas = this.clas;
r.dataBase = this.dataBase;
r.conf[0] = this.conf[0];
r.conf[1] = this.conf[1];
r.supp[0] = this.supp[0];
r.supp[1] = this.supp[1];
r.nAnts = this.nAnts;
r.wracc[0] = this.wracc[0];
r.wracc[1] = this.wracc[1];
return (r);
}
public void asignaAntecedente(int [] antecedent){
this.nAnts = 0;
for (int i = 0; i < antecedent.length; i++) {
this.antecedent[i] = antecedent[i];
if (this.antecedent[i] > -1) this.nAnts++;
}
}
public void setConsequent(int clas) {
this.clas = clas;
}
public double[] matching(double[] example) {
return (this.degreeProduct(example));
}
private double[] degreeProduct(double[] example) {
double degree[] = new double[2];
double var1[] = new double[2];
double dP[] = new double[2];
degree[0] = degree[1] = 1.0;
for (int i = 0; i < antecedent.length && degree[0] > 0.0; i++) {
var1 = dataBase.matching(i, antecedent[i], example[i]);
degree[0] *= var1[0];
degree[1] *= var1[1];
}
dP[0] = degree[0] * this.conf[0];
dP[1] = degree[1] * this.conf[1];
return (dP);
}
public double[] similaridadJurio(double[] example){
double degree[] = new double[2];
double roL1,roU1,aux;
double sim[] = new double[2];
sim[0] = sim[1] = 1.0;
for (int i = 0; i < antecedent.length; i++) {//&& sim[0] > 0.0
degree = dataBase.matching(i, antecedent[i], example[i]);
roL1 = 1;
roU1 = 0;
aux = Math.pow(Math.pow(degree[0], dataBase.aut2[i]),(1/dataBase.aut1[i]));
roL1 = Math.min(roL1,aux); //singleton is A
aux = Math.pow(Math.pow(degree[1], dataBase.aut2[i]),(1/dataBase.aut1[i]));
roU1 = Math.max(roU1,aux); //singleton is A
sim[0] *= roL1;
sim[1] *= roU1;
if ((sim[0] == 0) && (sim[1] == 0)) break;
}
sim[0] *= this.conf[0];
sim[1] *= this.conf[1];
return (sim);
}
public void setConfidence(Itemset itemset) {
double var1[] = new double[2];
double var2[] = new double[2];
var1 = itemset.getSupportClass();
var2 = itemset.getSupport();
this.conf = division(var1, var2, 0);
}
public double[] division(double[] int1, double[] int2, int tipo){
double resultado[] = new double[2];
double aux, maximo, lower, upper, minimo;
resultado[0] = resultado[1] = 0.0;
if (tipo == 0){
//DIVISION DE BENJA
resultado[1] = int1[1] / int2[1];
resultado[0] = int1[0] / int2[0];
if (resultado[1]<resultado[0]){
aux = resultado[1];
resultado[1] = resultado[0];
resultado[0] = aux;
}
}else if (tipo == 1){
//WANG's DIVISION
int2[0] = int2[0]-int1[0];// for normalizing with the remaining classes
int2[1] = int2[1]-int1[1];//for normalizing with the remaining classes
if ((int1[1]-int1[0])>=(int2[1]-int2[0]))
maximo = int1[1]-int1[0];
else maximo = int2[1]-int2[0];
lower = int1[0] + int2[0] + maximo;
upper = int1[1] + int2[1] + maximo;
if ((lower<=1)&&(upper>=1)){
resultado[0] = int1[0];
resultado[1] = int1[1];
}else{
lower = int1[0] + int2[0];
upper = int1[1] + int2[1];
if ((lower>1)||(upper<1)){
resultado[0] = int1[0]/(int1[0]+int2[1]);
resultado[1] = int1[1]/(int1[1]+int2[0]);
}else{
if ((lower<=1)&&(upper>=1)){
upper = 1 - (int2[0]);
lower = 1 - (int2[1]);
if (int1[0]>=lower) maximo = int1[0];
else maximo = lower;
if (int1[1]<=upper) minimo = int1[1];
else minimo = upper;
resultado[0] = maximo;
resultado[1] = minimo;
}else{
resultado[0] = int1[0]/(int1[0]+int2[1]);
resultado[1] = int1[1]/(int1[1]+int2[0]);
}
}
}
}
return(resultado);
}
public void setSupport(Itemset itemset) {
this.supp[0] = itemset.getSupportClass()[0];
this.supp[1] = itemset.getSupportClass()[1];
}
public void setWracc(double[] wracc) {
this.wracc[0] = wracc[0];
this.wracc[1] = wracc[1];
}
public double[] getConfidence() {
return (this.conf);
}
public double[] getSupport() {
return (this.supp);
}
public double[] getWracc() {
return (this.wracc);
}
public int getClas() {
return (this.clas);
}
public boolean isSubset(Rule a) {
if ((this.clas != a.clas) || (this.nAnts > a.nAnts)) return (false);
else {
for (int k = 0; k < this.antecedent.length; k++) {
if (this.antecedent[k] > -1) {
if (this.antecedent[k] != a.antecedent[k]) return (false);
}
}
return (true);
}
}
/**
* <p>
* Calculate Wracc for this rule
* </p>
* @param train Training dataset
* @param exampleWeight Weights of the patterns
* @return the value of the measure Wracc for this rule
*/
public void calculateWracc (myDataset train, ArrayList<ExampleWeight> exampleWeight) {
int i;
double n_A, n_AC, n_C;//, degree;
double degree[] = new double[2];
ExampleWeight ex;
n_A = n_AC = 0.0;
n_C = 0.0;
for (i=0; i < train.size(); i++) {
ex = exampleWeight.get(i);
if (ex.isActive()) {
degree = this.matching(train.getExample(i));
if (degree[0] > 0.0) {
degree[0] *= ex.getWeight();
degree[1] *= ex.getWeight();
n_A += degree[0];
if (train.getOutputAsInteger(i) == this.clas) {
n_AC += degree[0];
n_C += ex.getWeight();
}
}
else if (train.getOutputAsInteger(i) == this.clas) n_C += ex.getWeight();
}
}
if ((n_A < 0.0000000001) || (n_AC < 0.0000000001) || (n_C < 0.0000000001)) {this.wracc[0] = this.wracc[1] = -1.0;}
else {this.wracc[0] = this.wracc[1] = (n_AC / n_C) * ((n_AC / n_A) - train.frecuentClass(this.clas));}
}
public int reduceWeight (myDataset train, ArrayList<ExampleWeight> exampleWeight) {
int i, count;
ExampleWeight ex;
count = 0;
for (i=0; i < train.size(); i++) {
ex = exampleWeight.get(i);
if (ex.isActive()) {
if (this.matching(train.getExample(i))[0] > 0.0) {
ex.incCount();
if ((!ex.isActive()) && (train.getOutputAsInteger(i) == this.clas)) count++;
}
}
}
return (count);
}
public void setLabel(int pos, int label) {
if ((antecedent[pos] < 0) && (label > -1)) this.nAnts++;
if ((antecedent[pos] > -1) && (label < 0)) this.nAnts--;
this.antecedent[pos] = label;
}
public int compareTo(Object a) {
if (((Rule) a).wracc[0] < this.wracc[0]) return -1;
if (((Rule) a).wracc[0] > this.wracc[0]) return 1;
return 0;
}
}