/*********************************************************************** 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.DMEL; import org.core.*; import java.util.*; public class RuleSet implements Comparable { Rule reglas[]; public double fitness; public RuleSet () { } /**It initializates a new rule set or chromosome (using rules from a previous level)*/ public RuleSet (Vector <Rule> conjR) { Condition almacen[]; int i, j, k; int L; int baraja[]; Condition cdotmp[]; int tmp, pos; almacen = new Condition[conjR.size()*conjR.elementAt(0).getRule().length]; for (i=0, k=0; i<conjR.size(); i++) { for (j=0; j<conjR.elementAt(i).getRule().length; j++, k++) { almacen[k] = new Condition(conjR.elementAt(i).getiCondition(j)); } } L = conjR.elementAt(0).getRule().length; baraja = new int[almacen.length]; for (i=0; i<almacen.length; i++) { baraja[i] = i; } cdotmp = new Condition[L+1]; reglas = new Rule[conjR.size()]; for (i=0; i<reglas.length; i++) { for (j=0; j<L+1; j++) { pos = Randomize.Randint(j, baraja.length); tmp = baraja[pos]; baraja[pos] = baraja[j]; baraja[j] = tmp; cdotmp[j] = new Condition(almacen[baraja[j]]); } reglas[i] = new Rule(cdotmp); } } /**It creates a copy of the r Rule Set*/ public RuleSet (RuleSet r) { int i; reglas = new Rule[r.getRuleSet().length]; for (i=0; i<reglas.length; i++) { reglas[i] = new Rule(r.getRule(i)); } } public Rule[] getRuleSet () { return reglas; } public Rule getRule (int i) { return reglas[i]; } public void setiRule (int i, Rule rule) { reglas[i] = new Rule(rule); } public static void crossover1 (RuleSet hijo1, RuleSet hijo2) { int pos1, pos2; int tmp; Rule ruleTmp; int i; pos1 = Randomize.Randint(0, hijo1.getRuleSet().length); pos2 = Randomize.Randint(0, hijo1.getRuleSet().length); if (pos2 < pos1) { tmp = pos1; pos1 = pos2; pos2 = tmp; } for (i=pos1; i<=pos2; i++) { ruleTmp = new Rule(hijo1.getRule(i)); hijo1.setiRule(i, hijo2.getRule(i)); hijo2.setiRule(i, ruleTmp); } } public static void crossover2 (RuleSet hijo1, RuleSet hijo2) { int pos1, pos2, pos3; int tmp; Rule ruleTmp; int i; Condition conditionTmp; pos1 = Randomize.Randint(0, hijo1.getRuleSet().length); pos2 = Randomize.Randint(0, hijo1.getRuleSet().length); pos3 = Randomize.Randint(0, hijo1.getRule(0).getRule().length); if (pos2 < pos1) { tmp = pos1; pos1 = pos2; pos2 = tmp; } for (i=pos1+1; i<pos2; i++) { ruleTmp = new Rule(hijo1.getRule(i)); hijo1.setiRule(i, hijo2.getRule(i)); hijo2.setiRule(i, ruleTmp); } for (i=pos3; i<hijo1.getRule(pos1).getRule().length; i++) { conditionTmp = new Condition(hijo1.getRule(pos1).getRule()[i]); hijo1.getRule(pos1).setiCondition(i, hijo2.getRule(pos1).getRule()[i]); hijo2.getRule(pos1).setiCondition(i, conditionTmp); } for (i=0; i<=pos3; i++) { conditionTmp = new Condition(hijo1.getRule(pos2).getRule()[i]); hijo1.getRule(pos2).setiCondition(i, hijo2.getRule(pos1).getRule()[i]); hijo2.getRule(pos2).setiCondition(i, conditionTmp); } } public static void mutation (RuleSet cromosoma, Vector <Rule> conjR, double pMut, int data[][], int classData[], int infoAttr[], Vector <Rule> contenedor, int nClases) { Condition almacen[]; int i, j, k; double gain, gain2; RuleSet tmp; almacen = new Condition[conjR.size()*conjR.elementAt(0).getRule().length]; for (i=0, k=0; i<conjR.size(); i++) { for (j=0; j<conjR.elementAt(i).getRule().length; j++, k++) { almacen[k] = new Condition(conjR.elementAt(i).getiCondition(j)); } } for (i=0; i<cromosoma.getRuleSet().length; i++) { if (Randomize.Rand() < pMut) { k = Randomize.Randint(0, cromosoma.getRule(i).getRule().length); gain = cromosoma.computeFitness(data, classData, infoAttr, contenedor, nClases); tmp = new RuleSet(cromosoma); for (j=0; j<almacen.length; j++) { tmp.getRule(i).setiCondition(k, almacen[j]); gain2 = tmp.computeFitness(data, classData, infoAttr, contenedor, nClases); if (gain2 > gain) { gain = gain2; cromosoma = new RuleSet(tmp); } } } } } double computeFitness (int data[][], int classData[], int infoAttr[], Vector <Rule> contenedor, int nClases) { int i, j, k, l; boolean match; double tmp1, tmp2; int pos = 0, classPredicted; double cont = 0; double Waip; for (i=0; i<data.length; i++) { classPredicted = -1; Waip = 0; /*Search a match of the example (beginning from the chromosome)*/ for (j=0; j<reglas.length; j++) { match = true; for (k=0; k<reglas[j].getRule().length && match; k++) { if (data[i][reglas[j].getiCondition(k).getAttribute()] != reglas[j].getiCondition(k).getValue()) { match = false; } } if (match) { tmp1 = Double.NEGATIVE_INFINITY; for (l=0; l<nClases; l++) { tmp2 = 0; for (k=0; k<reglas[j].getRule().length; k++) { tmp2 += computeWeightEvidence (data, classData, reglas[j].getiCondition(k), l, infoAttr); } if (tmp2 > tmp1) { tmp1 = tmp2; pos = l; } } if (tmp1 > Waip) { classPredicted = pos; Waip = tmp1; } } } /*Search a match of the example (following by the container)*/ for (j=contenedor.size()-1; j>=0; j--) { match = true; for (k=0; k<contenedor.elementAt(j).getRule().length && match; k++) { if (data[i][contenedor.elementAt(j).getiCondition(k).getAttribute()] != contenedor.elementAt(j).getiCondition(k).getValue()) { match = false; } } if (match) { tmp1 = Double.NEGATIVE_INFINITY; for (l=0; l<nClases; l++) { tmp2 = 0; for (k=0; k<contenedor.elementAt(j).getRule().length; k++) { tmp2 += computeWeightEvidence (data, classData, contenedor.elementAt(j).getiCondition(k), l, infoAttr); } if (tmp2 > tmp1) { tmp1 = tmp2; pos = l; } } if (tmp1 > Waip) { classPredicted = pos; Waip = tmp1; } } } if (classPredicted == classData[i]) { cont++; } } fitness = cont / (double) data.length; return fitness; } public static double computeWeightEvidence (int data[][], int classData[], Condition cond, int clase, int infoAttr[]) { double sigmaAi, sigma, B; double ProbPos, ProbNeg; double prob; prob = Prob(data, classData, cond, clase); sigmaAi = 0.5 * (1 - prob); sigma = 0.5 * (1 - infoAttr.length * prob); B = sigma / (sigma + sigmaAi); ProbPos = B * ProbCondPositive(data, classData, cond, clase) + (1-B) * ProbClass(data, classData, cond, clase); ProbNeg = B * ProbCondNegative(data, classData, cond, clase) + (1-B) * ProbClass(data, classData, cond, clase); return (Math.log(ProbPos/ProbNeg)/Math.log(Math.E)); } public static double ProbCondPositive (int data[][], int classData[], Condition cond, int clase) { int i; double tmp1, tmp2; boolean hecho; tmp1 = 0; tmp2 = 0; for (i=0; i<data.length; i++) { if (data[i][cond.getAttribute()] == cond.getValue()) { tmp1++; hecho = true; if (classData[i] != clase) { hecho = false; } if (hecho) { tmp2++; } } } return tmp2/tmp1; } public static double ProbCondNegative (int data[][], int classData[], Condition cond, int clase) { int i; double tmp1, tmp2; boolean hecho; tmp1 = 0; tmp2 = 0; for (i=0; i<data.length; i++) { if (data[i][cond.getAttribute()] != cond.getValue()) { tmp1++; hecho = true; if (classData[i] != clase) { hecho = false; } if (hecho) { tmp2++; } } } return tmp2/tmp1; } public static double ProbClass (int data[][], int classData[], Condition cond, int clase) { int i; double tmp1, tmp3; boolean hecho; tmp3 = tmp1 = 0; for (i=0; i<data.length; i++) { if (classData[i] == clase) { tmp1++; } hecho = true; if (data[i][cond.getAttribute()] == -1) { hecho = false; } if (hecho) { tmp3++; } } return tmp1/tmp3; } public static double Prob (int data[][], int classData[], Condition cond, int clase) { int i; double tmp3; boolean hecho; tmp3 = 0; for (i=0; i<data.length; i++) { hecho = true; if (data[i][cond.getAttribute()] == -1) { hecho = false; } if (hecho) { tmp3++; } } return tmp3 / (double)data.length; } /**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.length; i++) { cadena += reglas[i].toString(train) + "\n"; } return cadena; } public boolean equals (Object a) { int i, j; RuleSet tmp = (RuleSet) a; boolean mascara[] = new boolean [reglas.length]; Arrays.fill(mascara, false); for (i=0; i<reglas.length; i++) { for (j=0; j<tmp.getRuleSet().length; j++) { if (reglas[i].equals(tmp.getRule(i))) { mascara[i] = true; } } } for (i=0; i<mascara.length; i++) if (!mascara[i]) return false; return true; } }