/*********************************************************************** 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.Genetic_Rule_Learning.GIL; import org.core.*; import java.util.*; public class Rule { Condition regla[]; public double completeness; public double consistency; public Rule () { } /**Creates a random rule*/ public Rule (myDataset train) { double prob = Randomize.Rand(); int i; regla = new Condition[train.getnInputs()]; for (i=0; i<train.getnInputs(); i++) { if (Randomize.Rand() < prob) { regla[i] = new Condition(i,train,true); } else { regla[i] = new Condition(i,train); } } } /**Creates a rule that matches with a certain example*/ public Rule (myDataset train, int ej) { double prob = Randomize.Rand(); int i; regla = new Condition[train.getnInputs()]; boolean codigo[]; for (i=0; i<train.getnInputs(); i++) { if (Randomize.Rand() < prob) { codigo = new boolean[train.numberValues(i)]; Arrays.fill(codigo, false); codigo[train.valueExample(ej, i)] = true; regla[i] = new Condition(i,codigo); } else { regla[i] = new Condition(i,train); } } } /**Creates a copy of a rule*/ public Rule (Rule a) { int i; regla = new Condition[a.getRule().length]; for (i=0; i<regla.length; i++) { regla[i] = new Condition(i,a.getiCondition(i).getCondition()); } } public Condition[] getRule() { return regla; } public Condition getiCondition(int i) { return regla[i]; } public void setiCondition (int i, Condition c) { regla[i] = new Condition(i,c.getCondition()); } public Rule[] ruleSplit(double p7B, double p7C, myDataset train) { Rule reglas[]; int attr = 0; int i, j, k; boolean tmp[], tmp2[]; attr = Randomize.Randint(0, regla.length); if (regla[attr].empty()) { for (i=0; i<regla[attr].getSizeCondition(); i++) { regla[attr].getCondition()[i] = true; } } if (train.getTipo(attr) == myDataset.NOMINAL) { if (Randomize.Rand() < p7C) { //all values reglas = new Rule[regla[attr].getnValues()]; for (i=0; i<reglas.length; i++) reglas[i] = new Rule(train); for (i=0; i<regla.length; i++) { if (i != attr) { for (j=0; j<reglas.length; j++) { reglas[j].setiCondition(i, new Condition(i,regla[i].getCondition())); } } else { k = 0; for (j=0; j<reglas.length; j++) { tmp = new boolean[train.numberValues(i)]; for ( ;k<train.numberValues(i) && !regla[i].getCondition()[k]; k++); tmp[k] = true; reglas[j].setiCondition(i, new Condition(i,tmp)); k++; } } } } else { //subset reglas = new Rule[2]; reglas[0] = new Rule(train); reglas[1] = new Rule(train); for (i=0; i<regla.length; i++) { if (i != attr) { reglas[0].setiCondition(i, new Condition(i,regla[i].getCondition())); reglas[1].setiCondition(i, new Condition(i,regla[i].getCondition())); } else { tmp = new boolean[train.numberValues(i)]; tmp2 = new boolean[train.numberValues(i)]; for (j=0; j<tmp.length; j++) { if (regla[i].getCondition()[j]) { if (Randomize.Rand() < 0.5) { tmp[j] = regla[i].getCondition()[j]; tmp2[j] = !regla[i].getCondition()[j]; } else { tmp2[j] = regla[i].getCondition()[j]; tmp[j] = !regla[i].getCondition()[j]; } } } reglas[0].setiCondition(i, new Condition(i,tmp)); reglas[1].setiCondition(i, new Condition(i,tmp2)); } } } } else { if (Randomize.Rand() < p7B) { //all values reglas = new Rule[regla[attr].getnValues()]; for (i=0; i<reglas.length; i++) reglas[i] = new Rule(train); for (i=0; i<regla.length; i++) { if (i != attr) { for (j=0; j<reglas.length; j++) { reglas[j].setiCondition(i, new Condition(i,regla[i].getCondition())); } } else { k = 0; for (j=0; j<reglas.length; j++) { tmp = new boolean[train.numberValues(i)]; for ( ;k<train.numberValues(i) && !regla[i].getCondition()[k]; k++); tmp[k] = true; reglas[j].setiCondition(i, new Condition(i,tmp)); k++; } } } } else { //subset reglas = new Rule[2]; reglas[0] = new Rule(train); reglas[1] = new Rule(train); for (i=0; i<regla.length; i++) { if (i != attr) { reglas[0].setiCondition(i, new Condition(i,regla[i].getCondition())); reglas[1].setiCondition(i, new Condition(i,regla[i].getCondition())); } else { tmp = new boolean[train.numberValues(i)]; tmp2 = new boolean[train.numberValues(i)]; for (j=0; j<tmp.length; j++) { if (Randomize.Rand() < 0.5) { tmp[j] = regla[i].getCondition()[j]; tmp2[j] = !regla[i].getCondition()[j]; } else { tmp2[j] = regla[i].getCondition()[j]; tmp[j] = !regla[i].getCondition()[j]; } } reglas[0].setiCondition(i, new Condition(i,tmp)); reglas[1].setiCondition(i, new Condition(i,tmp2)); } } } } return reglas; } public void conditionDrop() { int attr = 0; int i; int cont=0; /*Check that rule is not a complete domain rule*/ for (i=0; i<regla.length; i++) { if (regla[i].empty()) { cont++; } } if (cont < regla.length) { do { attr = Randomize.Randint(0, regla.length); } while (regla[attr].empty()); regla[attr].vaciar(); } } public Rule[] turningConjunctionIntoDisjunction (myDataset train) { Rule pareja[] = new Rule[2]; int i; int ale; pareja[0] = new Rule(train); pareja[1] = new Rule(train); for (i=0; i<regla.length;i++) { ale = Randomize.Randint(0, 2); if (ale == 0) { pareja[0].setiCondition(i, regla[i]); pareja[1].setiCondition(i, new Condition(i,train)); } else { pareja[1].setiCondition(i, regla[i]); pareja[0].setiCondition(i, new Condition(i,train)); } } return pareja; } public void conditionIntroduce (myDataset train) { Vector <Integer> cont = new Vector <Integer>(); int i; int pos; for (i=0; i<regla.length; i++) { if (regla[i].empty()) { cont.add(new Integer(i)); } } if (cont.size() > 0) { pos = Randomize.Randint(0, cont.size()); regla[cont.elementAt(pos)] = new Condition(cont.elementAt(pos),train,true); } } public Rule[] ruleDirectedSplit (myDataset train, int classAct) { Vector <Integer> contain = new Vector <Integer> (); boolean rule[]; boolean example[]; int i, pos, id, j, k; Rule directed[]; boolean dRules[][]; int cont = 0; Vector <Integer> subreglas = new Vector <Integer> (); int contAnt = 0; boolean todosFalsos; directed = new Rule[train.getnInputs()]; /*Search examples which match with the rule and belonging to the negative class*/ rule = this.toBitString(); for (i=0; i<train.getnData(); i++) { if (train.getOutputAsInteger(i) != classAct) { example = Rule.toBitString(train, i); if (Rule.match(rule, example)) { contain.addElement(new Integer(i)); } } } /*Choose a negative example of the covered by the rule*/ if (contain.size() > 0){ pos = Randomize.Randint(0, contain.size()); id = contain.elementAt(pos); /*Create the new rule set which does not cover the negative example*/ dRules = new boolean[train.getnInputs()][rule.length]; for (i=0; i<rule.length; i++) { for (j=0; j<train.getnInputs(); j++) { dRules[j][i] = rule[i]; } } for (i=0; i<train.getnInputs(); i++) { subreglas.addElement(i); } example = Rule.toBitString(train, id); for (i=0, k=-1; i<rule.length; i++) { if (i>=cont) { if (k >=0) { todosFalsos = true; for (j=contAnt; j<cont && todosFalsos; j++) { if (dRules[k][j] == true) todosFalsos = false; } if (todosFalsos) { subreglas.remove(new Integer(k)); } } k++; contAnt = cont; cont += regla[k].getSizeCondition(); } if (example[i] && rule[i]) { dRules[k][i] = false; } } directed = new Rule[subreglas.size()]; for (i=0; i<subreglas.size(); i++) { directed[i] = new Rule (train); directed[i].fromBitString(dRules[subreglas.elementAt(i)], train); } } else { directed = new Rule[1]; directed[0] = new Rule(this); } return directed; } boolean applyOperators (double p12, double p13, double p14, double condProb, double cons, double comp) { int i; boolean act = false; for (i=0; i<regla.length; i++) { if (Randomize.Rand() < p12) { regla[i].referenceChange(); act = true; } if (Randomize.Rand() < (p13*(1.5-comp)*(0.5+cons))) { regla[i].referenceExtension(condProb); act = true; } if (Randomize.Rand() < (p14*(1.5-comp)*(0.5+cons))) { regla[i].referenceRestriction(condProb); act = true; } } return act; } public boolean[] toBitString () { int cont= 0, i, j, k; boolean cadena[]; for (i=0; i<regla.length; i++) { cont += regla[i].getSizeCondition(); } cadena = new boolean[cont]; for (i=0, k=0; i<regla.length; i++) { if (regla[i].empty()) { for (j=0; j<regla[i].getSizeCondition(); j++, k++) { cadena[k] = true; } } else { for (j=0; j<regla[i].getSizeCondition(); j++, k++) { cadena[k] = regla[i].getiBit(j); } } } return cadena; } public void fromBitString (boolean cadena[], myDataset train) { int i, j, k; boolean vacio; boolean codigo[]; for (i=0, k=0; i<regla.length; i++) { vacio = true; for (j=k; j<(regla[i].getSizeCondition()+k) && vacio; j++) { if (cadena[j] == false) vacio = false; } if (vacio) { regla[i] = new Condition(i, train); k += regla[i].getSizeCondition(); } else { codigo = new boolean[regla[i].getSizeCondition()]; for (j=0; j<codigo.length; j++, k++) { codigo[j] = cadena[k]; } regla[i] = new Condition (i,codigo); } } } public static boolean match (boolean rule[], boolean example[]) { int i; for (i=0; i<rule.length; i++) { if (example[i] && !rule[i]) return false; } return true; } /** * It return a bit string correspoding to a certain example * @param train myDataset input dataset * @param ej identification of the example within the train set */ public static boolean[] toBitString (myDataset train, int ej) { int cont= 0, i, j, k; boolean cadena[]; boolean codigo[]; for (i=0; i<train.getnInputs(); i++) { cont += train.numberValues(i); } cadena = new boolean[cont]; for (i=0, k=0; i<train.getnInputs(); i++) { codigo = new boolean[train.numberValues(i)]; Arrays.fill(codigo, false); codigo[train.valueExample(ej, i)] = true; for (j=0; j<codigo.length; j++, k++) { cadena[k] = codigo[j]; } } return cadena; } double computeCompleteness(myDataset train, int classAct) { int i; boolean example[]; boolean rule[]; int e = 0, E = 0; for (i=0; i<train.getnData(); i++) { example = Rule.toBitString(train, i); rule = this.toBitString(); if (Rule.match(rule, example)) { E++; if (train.getOutputAsInteger(i) == classAct) { e++; } } } completeness = (double)e / (double)E; return completeness; } double computeConsistency(myDataset train, int classAct) { int i; boolean example[]; boolean rule[]; int e = 0, E = 0; for (i=0; i<train.getnData(); i++) { example = Rule.toBitString(train, i); rule = this.toBitString(); if (Rule.match(rule, example)) { E++; if (train.getOutputAsInteger(i) != classAct) { e++; } } } consistency = 1.0 - ((double)e / (double)E); return consistency; } public String toString (myDataset train) { int i; String cadena = ""; int cont=0; for (i=0; i<regla.length; i++) { if (!regla[i].empty()) { cadena += regla[i].toString(train) + " "; } else { cont++; } } if (cont == regla.length) cadena = "Complete Domain"; return cadena; } }