/***********************************************************************
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.MPLCS;
/**
* <p>
* @author Written by Jose A. Saez Munoz (ETSIIT, Universidad de Granada - Granada) 10/09/10
*
* @version 1.0
* @since JDK1.2
* </p>
*/
import java.util.Vector;
import keel.Algorithms.Genetic_Rule_Learning.MPLCS.Assistant.Globals.*;
public class ruleOrderAgent{
int numClasses;
int defaultClass;
int numInstances;
Vector<Integer> selectedRules;
Vector<matchProfileAgent> profiles;
double accuracy;
boolean[] ClassifiedOK;
int[] MatchedByRule;
double[] ratioOfClass;
int numRules;
int numOK;
int[] reglaDelPerfil;
matchProfileAgent mpaDR;
public ruleOrderAgent(int pDefaultClass, int pNumInstances, int capacity){
InstanceWrapper examples[]=PopulationWrapper.ilas.getInstances(); //instancias de la iteracion actual
int i;
defaultClass=pDefaultClass;
numInstances=pNumInstances;
numClasses=Parameters.numClasses;
selectedRules = new Vector<Integer>(capacity);
profiles = new Vector<matchProfileAgent>(capacity);
ClassifiedOK=new boolean[numInstances];
MatchedByRule=new int[numInstances];
ratioOfClass = new double[numClasses];
numRules=1;
numOK=0;
for(i=0;i<numClasses;i++) ratioOfClass[i]=0;
mpaDR=new matchProfileAgent(numInstances,defaultClass);
for(i=0;i<numInstances;i++) {
MatchedByRule[i]=0;
int cl=examples[i].instanceClass;
if(cl==defaultClass) {
numOK++;
ClassifiedOK[i]=true;
mpaDR.addOK(i);
} else {
ClassifiedOK[i]=false;
mpaDR.addKO(i);
}
ratioOfClass[cl]++;
}
mpaDR.generateProfiles();
for(i=0;i<numClasses;i++) {
int num=(int)ratioOfClass[i];
ratioOfClass[i]*=Parameters.filterSmartCrossover;
if(ratioOfClass[i]<5) ratioOfClass[i]=5;
if(ratioOfClass[i]>num*0.20) {
ratioOfClass[i]=num*0.20;
}
}
accuracy=(double)numOK/(double)numInstances;
}
public int insertRule(int whichRule, matchProfileAgent mpa){
int i;
int bestPos = 0;
double bestAcc=0;
for(i=0;i<numRules;i++) {
double acc=accuracyOfPosition(i,mpa);
if(i==0 || acc>bestAcc) {
bestPos=i;
bestAcc=acc;
}
}
if(bestAcc>accuracy) {
addRule(whichRule,mpa,bestPos);
return bestPos;
}
return -1;
}
public void addRule(int whichRule,matchProfileAgent mpa,int whichPos){
int i;
if(selectedRules.size()==0) {
selectedRules.addElement(whichRule);
profiles.addElement(mpa);
} else if(selectedRules.size()==whichPos) {
selectedRules.addElement(whichRule);
profiles.addElement(mpa);
} else {
selectedRules.insertElementAt(whichRule,whichPos);
profiles.insertElementAt(mpa,whichPos);
}
for(i=0;i<numInstances;i++) {
if(MatchedByRule[i]>=whichPos) {
MatchedByRule[i]++;
if(mpa.mapOK[i]) {
MatchedByRule[i]=whichPos;
if(ClassifiedOK[i]==false) {
numOK++;
ClassifiedOK[i]=true;
}
}
if(mpa.mapKO[i]) {
MatchedByRule[i]=whichPos;
if(ClassifiedOK[i]==true) {
numOK--;
ClassifiedOK[i]=false;
}
}
}
}
numRules++;
accuracy=(double)numOK/(double)numInstances;
}
public void updateMPA(int whichPos,matchProfileAgent mpa){
int i,j;
profiles.set(whichPos, mpa);
for(i=0;i<numInstances;i++) {
if(MatchedByRule[i]>=whichPos) {
boolean matched=false;
if(mpa.mapOK[i]) {
matched=true;
MatchedByRule[i]=whichPos;
if(ClassifiedOK[i]==false) {
numOK++;
ClassifiedOK[i]=true;
}
}
if(mpa.mapKO[i]) {
matched=true;
MatchedByRule[i]=whichPos;
if(ClassifiedOK[i]==true) {
numOK--;
ClassifiedOK[i]=false;
}
}
if(!matched && MatchedByRule[i]==whichPos) {
boolean corr=ClassifiedOK[i];
boolean found=false;
for(j=whichPos+1;j<numRules-1 && !found;j++) {
if(profiles.get(j).mapOK[i]) {
MatchedByRule[i]=j;
if(!corr) {
ClassifiedOK[i]=true;
numOK++;
}
found=true;
} else if(profiles.get(j).mapKO[i]) {
MatchedByRule[i]=j;
if(corr) {
ClassifiedOK[i]=false;
numOK--;
}
found=true;
}
}
if(!found) {
MatchedByRule[i]=numRules-1;
if(mpaDR.mapOK[i]) {
if(!corr) {
ClassifiedOK[i]=true;
numOK++;
}
} else {
if(corr) {
ClassifiedOK[i]=false;
numOK--;
}
}
}
}
}
}
accuracy=(double)numOK/(double)numInstances;
}
public double accuracyOfPosition(int pos,matchProfileAgent mpa){
int i;
int newOK=numOK;
for(i=0;i<mpa.numOK;i++) {
int ex=mpa.listOK[i];
if(MatchedByRule[ex]>=pos && ClassifiedOK[ex]==false) {
newOK++;
}
}
for(i=0;i<mpa.numKO;i++) {
int ex=mpa.listKO[i];
if(MatchedByRule[ex]>=pos && ClassifiedOK[ex]==true) {
newOK--;
}
}
return (double)newOK/(double)numInstances;
}
public int ruleNeedsInstances(int rule){
int j;
int ruleOK=0;
for(j=0;j<numInstances;j++) {
if(MatchedByRule[j]==rule && ClassifiedOK[j]==true) {
ruleOK++;
}
}
if(ruleOK<ratioOfClass[profiles.get(rule).ruleClass]) {
return (int)(ratioOfClass[profiles.get(rule).ruleClass]-ruleOK+0.5);
}
return 0;
}
public void refineRuleSet(){
int i,j;
i=0;
while(i<numRules-1) {
int ruleOK=0;
for(j=0;j<numInstances;j++) {
if(MatchedByRule[j]==i && ClassifiedOK[j]==true) {
ruleOK++;
}
}
if(ruleOK<ratioOfClass[profiles.get(i).ruleClass]) {
removeRule(i);
} else {
i++;
}
}
}
public void copyOrder(Vector<Integer> finalRules){
int i;
finalRules.removeAllElements();
finalRules.ensureCapacity(selectedRules.size());
for(i=0;i<selectedRules.size();i++) {
finalRules.addElement(selectedRules.get(i));
}
}
public matchProfileAgent generateActualMPA(int rule){
int i;
matchProfileAgent mpa = new matchProfileAgent(numInstances, profiles.get(rule).ruleClass);
for(i=0;i<numInstances;i++) {
if(MatchedByRule[i]==rule) {
if(ClassifiedOK[i]) {
mpa.addOK(i);
} else {
mpa.addKO(i);
}
}
}
mpa.generateProfiles();
return mpa;
}
public void removeMatchesOfRule(int rule,matchProfileAgent mpa){
int i,j;
for(i=0;i<numInstances;i++) {
if(MatchedByRule[i]==rule) {
if(!mpa.mapOK[i] && !mpa.mapKO[i]) {
boolean corr=ClassifiedOK[i];
boolean found=false;
for(j=rule+1;j<numRules-1 && !found;j++) {
if(profiles.get(j).mapOK[i]) {
MatchedByRule[i]=j;
if(!corr) {
ClassifiedOK[i]=true;
numOK++;
}
found=true;
} else if(profiles.get(j).mapKO[i]) {
MatchedByRule[i]=j;
if(corr) {
ClassifiedOK[i]=false;
numOK--;
}
found=true;
}
}
if(!found) {
MatchedByRule[i]=numRules-1;
if(mpaDR.mapOK[i]) {
if(!corr) {
ClassifiedOK[i]=true;
numOK++;
}
} else {
if(corr) {
ClassifiedOK[i]=false;
numOK--;
}
}
}
}
}
}
accuracy=(double)numOK/(double)numInstances;
}
public void removeRule(int rule){
int i,j;
for(i=0;i<numInstances;i++) {
if(MatchedByRule[i]==rule) {
boolean corr=ClassifiedOK[i];
boolean found=false;
for(j=rule+1;j<numRules-1 && !found;j++) {
if(profiles.get(j).mapOK[i]) {
MatchedByRule[i]=j;
if(!corr) {
ClassifiedOK[i]=true;
numOK++;
}
found=true;
} else if(profiles.get(j).mapKO[i]) {
MatchedByRule[i]=j;
if(corr) {
ClassifiedOK[i]=false;
numOK--;
}
found=true;
}
}
if(!found) {
MatchedByRule[i]=numRules-1;
if(mpaDR.mapOK[i]) {
if(!corr) {
ClassifiedOK[i]=true;
numOK++;
}
} else {
if(corr) {
ClassifiedOK[i]=false;
numOK--;
}
}
}
}
if(MatchedByRule[i]>rule) {
MatchedByRule[i]--;
}
}
selectedRules.removeElementAt(rule);
profiles.removeElementAt(rule);
numRules--;
accuracy=(double)numOK/(double)numInstances;
}
public int getPossibleInstancesOfRule(int rule, int[] instances){
int i;
int numInst=0;
for(i=0;i<numInstances;i++) {
if(MatchedByRule[i]>rule) {
instances[numInst++]=i;
}
}
return numInst;
}
public void addPositiveExamples(int rule,int[]instances,int numInst, matchProfileAgent mpa){
int i;
profiles.set(rule, mpa);
for(i=0;i<numInst;i++) {
int inst=instances[i];
MatchedByRule[inst]=rule;
if(ClassifiedOK[inst]==false) {
numOK++;
ClassifiedOK[inst]=true;
}
}
accuracy=(double)numOK/(double)numInstances;
}
public double min(double a,double b) {
if(a<b) return a;
return b;
}
public double getAccuracy() {return accuracy;}
public int getNumRules() {return numRules;}
public int getRule(int rule) { return selectedRules.get(rule);}
}