/*********************************************************************** 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 RuleSet implements Comparable { Vector <Rule> reglas; public double fitness; public double completeness; public double consistency; public double cost; public RuleSet () { reglas = new Vector <Rule> (); } /**It initializates a new rule set or chromosome (randomly and using positive examples)*/ public RuleSet (myDataset train, int classAct) { int size, i, j, pos, ej; Vector <Integer> contain = new Vector <Integer> (); reglas = new Vector <Rule> (); size = Randomize.Randint(1, (train.getnData()/20+2)); for (i=0; i<size; i++) { if (Randomize.Rand() < 0.5) { reglas.addElement(new Rule(train)); } else { /*Search examples belonging to the positive class*/ for (j=0; j<train.getnData(); j++) { if (train.getOutputAsInteger(j) == classAct) { contain.addElement(new Integer(j)); } } if (contain.size() > 0) { pos = Randomize.Randint(0, contain.size()); ej = contain.elementAt(pos); reglas.addElement(new Rule(train,ej)); } else { reglas.addElement(new Rule(train)); } } } } /**It creates a copy of the r Rule Set*/ public RuleSet (RuleSet r) { int i; reglas = new Vector <Rule> (); for (i=0; i<r.getRuleSet().size(); i++) { reglas.addElement(new Rule(r.getRule(i))); } } public Vector <Rule> getRuleSet () { return reglas; } public Rule getRule (int i) { return reglas.elementAt(i); } public void setiRule (int i, Rule rule) { reglas.setElementAt(rule, i); } public void insertRule (Rule rule) { reglas.insertElementAt(rule, 0); } public Rule dropiRule (int i) { return reglas.remove(i); } public void rulesExchange (RuleSet padre, double P1b) { int i; Rule tmp; for (i=0; i<reglas.size(); i++) { if (Randomize.Rand() < P1b) { tmp = reglas.remove(i); i--; padre.insertRule(tmp); } } for (i=0; i<padre.getRuleSet().size(); i++) { if (Randomize.Rand() < P1b) { tmp = padre.dropiRule(i); i--; this.insertRule(tmp); } } } public void rulesCopy (RuleSet padre) { int pos; if (padre.getRuleSet().size() > 0) { pos = Randomize.Randint(0, padre.getRuleSet().size()); reglas.addElement(new Rule(padre.getRule(pos))); } } public void newEvent (myDataset train, int classAct) { boolean rules[][]; int i, j, pos, id; boolean example[]; boolean entra; Vector <Integer> contain = new Vector <Integer> (); Rule tmp; rules = new boolean[reglas.size()][]; /*Search examples which match with the rule and belonging to the positive class*/ for (i=0; i<reglas.size(); i++) { rules[i] = reglas.elementAt(i).toBitString(); } for (i=0; i<train.getnData(); i++) { if (train.getOutputAsInteger(i) == classAct) { example = Rule.toBitString(train, i); entra = false; for (j=0; j<rules.length && !entra; j++) { if (Rule.match(rules[j], example)) { entra = true; } } if (!entra) { contain.addElement(new Integer(i)); } } } /*Choose a positive example not covered by the rule*/ if (contain.size() > 0){ pos = Randomize.Randint(0, contain.size()); id = contain.elementAt(pos); /*Create a new rule from the not covered positive example*/ example = Rule.toBitString(train, id); tmp = new Rule(train); tmp.fromBitString(example, train); reglas.addElement(new Rule(tmp)); } } public void rulesGeneralization (myDataset train) { int pos1, pos2, i; boolean regla1[], regla2[]; boolean generalRule[]; Rule tmp; if (reglas.size() > 1) { pos1 = Randomize.Randint(0, reglas.size()); do { pos2 = Randomize.Randint(0, reglas.size()); } while (pos1 == pos2); regla1 = reglas.elementAt(pos1).toBitString(); regla2 = reglas.elementAt(pos2).toBitString(); generalRule = new boolean[regla1.length]; for (i=0; i<generalRule.length; i++) { if (regla1[i] || regla2[i]) { generalRule[i] = true; } else { generalRule[i] = false; } } if (pos1 > pos2) { reglas.remove(pos1); reglas.remove(pos2); } else { reglas.remove(pos2); reglas.remove(pos1); } tmp = new Rule(train); tmp.fromBitString(generalRule, train); reglas.addElement(new Rule(tmp)); } } void rulesDrop () { int pos; if (reglas.size() > 0) { pos = Randomize.Randint(0, reglas.size()); reglas.remove(pos); } } void rulesSpecialization (myDataset train) { int pos1, pos2, i; boolean regla1[], regla2[]; boolean generalRule[]; Rule tmp; if (reglas.size() > 1) { pos1 = Randomize.Randint(0, reglas.size()); do { pos2 = Randomize.Randint(0, reglas.size()); } while (pos1 == pos2); regla1 = reglas.elementAt(pos1).toBitString(); regla2 = reglas.elementAt(pos2).toBitString(); generalRule = new boolean[regla1.length]; for (i=0; i<generalRule.length; i++) { if (regla1[i] && regla2[i]) { generalRule[i] = true; } else { generalRule[i] = false; } } if (pos1 > pos2) { reglas.remove(pos1); reglas.remove(pos2); } else { reglas.remove(pos2); reglas.remove(pos1); } tmp = new Rule(train); tmp.fromBitString(generalRule, train); reglas.addElement(new Rule(tmp)); } } boolean applyOperators (double p7a, double p7b, double p7c, double p8, double p9, double p10, double p11, double p12, double p13, double p14, double condProb, myDataset train, int classAct) { Rule tmpRule1[][]; Rule tmpRule2[][]; Rule tmpRule3[][]; int i, j, l; double comp, cons; boolean act = false; tmpRule1 = new Rule[reglas.size()][]; tmpRule2 = new Rule[reglas.size()][]; tmpRule3 = new Rule[reglas.size()][]; for (i=0; i<reglas.size();i++) { tmpRule1[i] = new Rule[0]; tmpRule2[i] = new Rule[0]; tmpRule3[i] = new Rule[0]; } for (i=0, l=0; i<reglas.size(); i++,l++) { if (Randomize.Rand() < p7a) { tmpRule1[l] = reglas.elementAt(i).ruleSplit(p7b, p7c, train); reglas.remove(i); i--; act = true; } } for (i=0, l=0; i<reglas.size(); i++,l++) { cons = reglas.elementAt(i).computeConsistency(train, classAct); comp = reglas.elementAt(i).computeCompleteness(train, classAct); if (Randomize.Rand() < (p8*(1.5-comp)*(0.5+cons))) { reglas.elementAt(i).conditionDrop(); act = true; } if (Randomize.Rand() < (p9*(1.5-comp)*(0.5+cons))) { tmpRule2[l] = reglas.elementAt(i).turningConjunctionIntoDisjunction(train); reglas.remove(i); i--; act = true; } } for (i=0, l=0; i<reglas.size(); i++,l++) { cons = reglas.elementAt(i).computeConsistency(train, classAct); comp = reglas.elementAt(i).computeCompleteness(train, classAct); if (Randomize.Rand() < (p10*(0.5+comp)*(1.5-cons))) { reglas.elementAt(i).conditionIntroduce(train); act = true; } if (Randomize.Rand() < (p11*(0.5+comp)*(1.5-cons))) { tmpRule3[l] = reglas.elementAt(i).ruleDirectedSplit(train, classAct); reglas.remove(i); i--; act = true; } } for (i=0; i<tmpRule1.length; i++) { for (j=0; j<tmpRule1[i].length; j++) { reglas.add(new Rule(tmpRule1[i][j])); } } for (i=0; i<tmpRule2.length; i++) { for (j=0; j<tmpRule2[i].length; j++) { reglas.add(new Rule(tmpRule2[i][j])); } } for (i=0; i<tmpRule3.length; i++) { for (j=0; j<tmpRule3[i].length; j++) { reglas.add(new Rule(tmpRule3[i][j])); } } for (i=0; i<reglas.size(); i++) { cons = reglas.elementAt(i).computeConsistency(train, classAct); comp = reglas.elementAt(i).computeCompleteness(train, classAct); act |= reglas.elementAt(i).applyOperators(p12, p13, p14, condProb, cons, comp); } return act; } double computeCost() { int i, j; int contCond = 0; for (i=0; i<reglas.size(); i++) { for (j=0; j<reglas.elementAt(i).getRule().length; j++) { if (!reglas.elementAt(i).getRule()[j].empty()) { contCond++; } } } cost = (2.0 * (double)reglas.size()) + (double)contCond; return cost; } double computeCompleteness(myDataset train, int classAct) { int i, j; boolean example[]; boolean rule[]; int e = 0, E = 0; boolean valido; for (i=0; i<train.getnData(); i++) { if (train.getOutputAsInteger(i) == classAct) { example = Rule.toBitString(train, i); valido = false; for (j=0; j<reglas.size(); j++) { rule = reglas.elementAt(j).toBitString(); if (Rule.match(rule, example)) { valido = true; } } E++; if (valido) e++; } } completeness = (double)e / (double)E; return completeness; } double computeConsistency(myDataset train, int classAct) { int i, j; boolean example[]; boolean rule[]; int e = 0, E = 0; boolean valido; for (i=0; i<train.getnData(); i++) { if (train.getOutputAsInteger(i) != classAct) { example = Rule.toBitString(train, i); valido = false; for (j=0; j<reglas.size(); j++) { rule = reglas.elementAt(j).toBitString(); if (Rule.match(rule, example)) { valido = true; } } E++; if (valido) e++; } } consistency = 1.0 - ((double)e / (double)E); return consistency; } double computeFitness (myDataset train, int classAct, double minCost, double maxCost, double f, double w1, double w2, double w3) { double correctness; computeCompleteness(train, classAct); computeConsistency(train, classAct); correctness = (w1*completeness + w2*consistency) / (w1+w2); fitness = correctness * Math.pow(1 + w3 * (1 - ((cost - minCost)/(maxCost - minCost))), f); return fitness; } /**Function that lets compare cromosomes to sort easily*/ public int compareTo (Object o1) { if (this.fitness > ((RuleSet)o1).fitness) return -1; else if (this.fitness < ((RuleSet)o1).fitness) return 1; else return 0; } public String toString (myDataset train) { int i; String cadena = ""; for (i=0; i<reglas.size(); i++) { cadena += reglas.elementAt(i).toString(train) + "\n"; } return cadena; } }