/***********************************************************************
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/
**********************************************************************/
/**
* <p>
* @author Written by Jaume Bacardit (La Salle, Ram�n Llull University - Barcelona) 28/03/2004
* @author Modified by Xavi Sol� (La Salle, Ram�n Llull University - Barcelona) 23/12/2008
* @author Modified by Jose A. Saez Munoz (ETSIIT, Universidad de Granada - Granada) 10/09/10
*
* @version 1.1
* @since JDK1.2
* </p>
*/
package keel.Algorithms.Genetic_Rule_Learning.MPLCS;
import java.util.Vector;
import keel.Dataset.*;
import keel.Algorithms.Genetic_Rule_Learning.MPLCS.Assistant.Globals.*;
public class ClassifierGABIL
extends Classifier implements Cloneable {
/**
* <p>
* Contains the classifier for the GABIL knowledge representation
* </p>
*/
public class cleanTarget{
int maxAtt;
int maxValue;
int maxNeg;
public cleanTarget(){}
}
public class activationsAtt{
int numValues;
int[][] actValues;
public activationsAtt(){}
}
public class attInstances{
int numValues;
int[][][] valueInstances;
int[][] numInst;
public attInstances(){}
}
public class splittedRule{
int[] rule1;
matchProfileAgent mpa1;
int[] rule2;
matchProfileAgent mpa2;
public splittedRule(){}
}
// The cromosome
int[] crm;
int defaultClass;
public ClassifierGABIL() {
isEvaluated = false;
}
public void initRandomClassifier() {
numRules = Parameters.initialNumberOfRules;
int ruleSize = Globals_GABIL.ruleSize;
double prob = Parameters.probOne;
int nC = Parameters.numClasses;
crm = new int[numRules * ruleSize];
int base = 0;
if (Globals_DefaultC.defaultClassPolicy == Globals_DefaultC.AUTO) {
defaultClass = Rand.getInteger(0, Parameters.numClasses - 1);
}
else {
defaultClass = Globals_DefaultC.defaultClass;
}
for (int i = 0; i < numRules; i++) {
InstanceWrapper ins = null;
if (PopulationWrapper.smartInit) {
if (Globals_DefaultC.defaultClassPolicy != Globals_DefaultC.DISABLED) {
ins = PopulationWrapper.getInstanceInit(defaultClass);
}
else {
ins = PopulationWrapper.getInstanceInit(Parameters.numClasses);
}
}
int base2 = base;
for (int j = 0; j < Parameters.numAttributes; j++) {
int value;
if (ins != null) {
value = ins.getNominalValue(j);
}
else {
value = -1;
}
for (int k = 0; k < Globals_GABIL.size[j]; k++) {
if (k != value) {
if (Rand.getReal() < prob) {
crm[base2 + k] = 1;
}
else {
crm[base2 + k] = 0;
}
}
else {
crm[base2 + k] = 1;
}
}
base2 += Globals_GABIL.size[j];
}
if (ins != null) {
crm[base2] = ins.classOfInstance();
}
else {
do {
crm[base2] = Rand.getInteger(0, nC - 1);
}
while (Globals_DefaultC.enabled &&
crm[base2] == defaultClass);
}
base += ruleSize;
}
resetPerformance();
}
public double computeTheoryLength() {
int base = 0;
int ruleSize = Globals_GABIL.ruleSize;
theoryLength = 0;
for (int i = 0; i < numRules; i++) {
if (PerformanceAgent.getActivationsOfRule(i) > 0) {
int base2 = base;
for (int j = 0; j < Parameters.numAttributes; j++) {
double countFalses = 0;
int numValues = Globals_GABIL.size[j];
for (int k = 0; k < numValues; k++) {
if (crm[base2 + k] == 0) {
countFalses++;
}
}
theoryLength += numValues + countFalses;
base2 += Globals_GABIL.size[j];
}
}
base += ruleSize;
}
if (Globals_DefaultC.enabled) {
theoryLength += 0.00000001;
}
return theoryLength;
}
/**
* This function classifies input instances. It returns a class
* prediction of -1 if the input example cannot be classified
*/
public int doMatch(InstanceWrapper ins) {
int nA = Parameters.numAttributes;
boolean okMatch;
int i, j;
int base = 0;
int ruleSize = Globals_GABIL.ruleSize;
int[] val = ins.getNominalValues();
for (i = 0; i < numRules; i++) {
okMatch = true;
for (j = 0; okMatch && j < nA; j++) {
if (crm[base + Globals_GABIL.offset[j] + val[j]] == 0) {
okMatch = false;
}
}
if (okMatch) {
positionRuleMatch = i;
return crm[base + ruleSize - 1];
}
base += ruleSize;
}
if (Globals_DefaultC.enabled) {
positionRuleMatch = numRules;
return defaultClass;
}
return -1;
}
public void printClassifier() {
int nA = Parameters.numAttributes;
int ruleSize = Globals_GABIL.ruleSize;
String str;
int base = 0;
for (int i = 0; i < numRules; i++) {
str = i + ":";
for (int j = 0; j < nA; j++) {
Attribute att = Attributes.getAttribute(j);
String temp = "Att " + att.getName() + " is ";
boolean irr = true;
boolean first = true;
for (int k = 0; k < Globals_GABIL.size[j]; k++) {
if (crm[base + Globals_GABIL.offset[j] + k] == 1) {
if (first) {
temp += att.getNominalValue(k);
first = false;
}
else {
temp += "," + att.getNominalValue(k);
}
}
else {
irr = false;
}
}
if (!irr) {
Main.numAttsBest++;
str += temp + "|";
}
}
int cl = crm[base + ruleSize - 1];
String name = Attributes.getAttribute(Parameters.numAttributes).
getNominalValue(cl);
str += name;
LogManager.println(str);
base += ruleSize;
}
if (Globals_DefaultC.enabled) {
LogManager.println(numRules + ":Default rule -> "
+
Attributes.getAttribute(Parameters.numAttributes).
getNominalValue(defaultClass));
}
}
public int getNumRules() {
if (Globals_DefaultC.enabled) {
return numRules + 1;
}
return numRules;
}
public Classifier[] crossoverClassifiers(Classifier _parent2) {
ClassifierGABIL offspring1 = new ClassifierGABIL();
ClassifierGABIL offspring2 = new ClassifierGABIL();
ClassifierGABIL parent2 = (ClassifierGABIL) _parent2;
int ruleSize = Globals_GABIL.ruleSize;
int ruleP1 = (int) Rand.getInteger(0, numRules - 1);
int ruleP2 = (int) Rand.getInteger(0, parent2.numRules - 1);
offspring1.numRules = ruleP1 + parent2.numRules - ruleP2;
offspring2.numRules = ruleP2 + numRules - ruleP1;
int cutPoint = (int) Rand.getInteger(0, Globals_GABIL.ruleSize);
offspring1.defaultClass = offspring2.defaultClass = defaultClass;
offspring1.crm = new int[ruleSize * offspring1.numRules];
offspring2.crm = new int[ruleSize * offspring2.numRules];
System.arraycopy(crm, 0, offspring1.crm, 0, ruleP1 * ruleSize);
System.arraycopy(parent2.crm, 0, offspring2.crm, 0, ruleP2 * ruleSize);
int base1 = ruleP1 * ruleSize;
int base2 = ruleP2 * ruleSize;
System.arraycopy(crm, base1, offspring1.crm, base1, cutPoint);
System.arraycopy(parent2.crm, base2, offspring2.crm, base2, cutPoint);
System.arraycopy(crm, base1 + cutPoint, offspring2.crm, base2 + cutPoint,
ruleSize - cutPoint);
System.arraycopy(parent2.crm, base2 + cutPoint, offspring1.crm,
base1 + cutPoint, ruleSize - cutPoint);
base1 += ruleSize;
base2 += ruleSize;
System.arraycopy(crm, base1, offspring2.crm, base2,
(numRules - ruleP1 - 1) * ruleSize);
System.arraycopy(parent2.crm, base2, offspring1.crm, base1,
(parent2.numRules - ruleP2 - 1) * ruleSize);
Classifier[] ret = new Classifier[2];
ret[0] = offspring1;
ret[1] = offspring2;
return ret;
}
public Classifier copy() {
int ruleSize = Globals_GABIL.ruleSize;
ClassifierGABIL ret = new ClassifierGABIL();
ret.numRules = numRules;
ret.theoryLength = theoryLength;
ret.exceptionsLength = ret.exceptionsLength;
ret.crm = new int[numRules * ruleSize];
System.arraycopy(crm, 0, ret.crm, 0, numRules * ruleSize);
ret.defaultClass = defaultClass;
ret.setAccuracy(accuracy);
ret.setFitness(fitness);
ret.isEvaluated = isEvaluated;
ret.setNumAliveRules(numAliveRules);
return ret;
}
public void doMutation() {
int whichRule = (int) Rand.getInteger(0, numRules - 1);
int ruleSize = Globals_GABIL.ruleSize;
int base = whichRule * ruleSize;
int gene;
if (Globals_DefaultC.numClasses > 1
&& Rand.getReal() < 0.1) {
gene = ruleSize - 1;
}
else {
gene = (int) Rand.getInteger(0, ruleSize - 2);
}
if (gene < ruleSize - 1) {
if (crm[base + gene] == 1) {
crm[base + gene] = 0;
}
else {
crm[base + gene] = 1;
}
}
else {
int oldValue = crm[base + gene];
int newValue;
do {
newValue = (int) Rand.getInteger(0, Parameters.numClasses - 1);
}
while (newValue == oldValue ||
(Globals_DefaultC.enabled && newValue == defaultClass));
crm[base + gene] = newValue;
}
isEvaluated = false;
}
public void deleteRules(int[] whichRules) {
if (numRules == 1 || whichRules.length == 0) {
return;
}
int ruleSize = Globals_GABIL.ruleSize;
int rulesToDelete = whichRules.length;
if (whichRules[rulesToDelete - 1] == numRules) {
rulesToDelete--;
}
int[] newCrm = new int[ruleSize * (numRules - rulesToDelete)];
int countPruned = 0;
int baseOrig = 0;
int baseNew = 0;
for (int i = 0; i < numRules; i++) {
if (countPruned < rulesToDelete) {
if (i != whichRules[countPruned]) {
System.arraycopy(crm, baseOrig, newCrm, baseNew, ruleSize);
baseNew += ruleSize;
}
else {
countPruned++;
}
}
else {
System.arraycopy(crm, baseOrig, newCrm, baseNew, ruleSize);
baseNew += ruleSize;
}
baseOrig += ruleSize;
}
numRules -= rulesToDelete;
crm = newCrm;
}
public double getLength() {
return numAliveRules;
}
public int numSpecialStages() {
return 0;
}
public void doSpecialStage(int stage) {}
public int getNiche() {
if (Globals_DefaultC.defaultClassPolicy != Globals_DefaultC.AUTO) {
return 0;
}
return defaultClass;
}
public int getNumNiches() {
if (Globals_DefaultC.defaultClassPolicy != Globals_DefaultC.AUTO) {
return 1;
}
return Parameters.numClasses;
}
public void crossoverRSW(Classifier[] parents, int num){
int ruleSize=Globals_GABIL.ruleSize;
int i, k;
Vector<int[]> candidateRules = new Vector<int[]>(50,10);
Vector<matchProfileAgent>profiles = new Vector<matchProfileAgent>(50,10);
int ruleCount=0;
for(k=0;k<num;k++) {
ClassifierGABIL parent=(ClassifierGABIL)parents[k];
int pos=0;
for(i=0;i<parent.numRules;pos+=Globals_GABIL.ruleSize,i++) {
int[] newRule = new int[ruleSize];
System.arraycopy(parent.crm, pos, newRule, 0, ruleSize);
matchProfileAgent mpa = evaluateRuleCX(newRule);
candidateRules.addElement(newRule);
ruleCount++;
profiles.addElement(mpa);
}
}
Vector<Integer> ruleOrder = new Vector<Integer>(50,10);
findOrder(profiles,candidateRules,ruleOrder);
numRules = ruleOrder.size();
int length2 = numRules * ruleSize;
crm = new int[length2];
for (i = 0; i < numRules; i++){
System.arraycopy(candidateRules.get(ruleOrder.get(i)), 0, crm,i*ruleSize , ruleSize);
}
}
public matchProfileAgent evaluateRuleCX(int[] rule){
int i;
int cl = rule[Globals_GABIL.ruleSize-1];
int max = PopulationWrapper.ilas.getNumInstancesOfIteration();
InstanceWrapper[] instances = PopulationWrapper.ilas.getInstances();
matchProfileAgent mpa=new matchProfileAgent(max,cl);
for (i = 0; i < max; i++) {
if (ruleMatches(rule, instances[i])) {
if (instances[i].instanceClass == cl) {
mpa.addOK(i);
} else {
mpa.addKO(i);
}
}
}
mpa.generateProfiles();
return mpa;
}
public void findOrder(Vector<matchProfileAgent> profiles, Vector<int[]>candidateRules,Vector<Integer> ruleOrder){
int numInst=PopulationWrapper.ilas.getNumInstancesOfIteration();
int i,j;
ruleOrderAgent best=null;
for(j=0;j<Parameters.repetitionsRuleOrdering;j++) {
int totalRules=profiles.size();
Sampling samp=new Sampling(totalRules);
ruleOrderAgent roa = new ruleOrderAgent(defaultClass,numInst,totalRules);
for(i=0;i<totalRules;i++) {
int rule=samp.getSample();
roa.insertRule(rule,profiles.get(rule));
}
if(Parameters.doRuleCleaning) {
int num=roa.getNumRules()-1;
for(i=0;i<num;i++) {
matchProfileAgent mpa=roa.generateActualMPA(i);
if(cleanRule(candidateRules.get(roa.getRule(i)),mpa)) {
roa.removeMatchesOfRule(i,mpa);
}
}
}
if(Parameters.doRuleGeneralizing){
int numCand = 0;
int [] candidates = new int[numInst];
for(i=0;i<roa.getNumRules()-1;i++) {
int whichRule=roa.getRule(i);
int[] rule=candidateRules.get(whichRule);
numCand=roa.getPossibleInstancesOfRule(i,candidates);
int[] newInstances = new int[numCand];
int numNew = 0;
numNew=generalizeRule(rule,candidates,numCand,newInstances,whichRule,false);
candidateRules.set(whichRule, rule);
if(numNew>0){
matchProfileAgent mpa=evaluateRuleCX(rule);
profiles.set(whichRule, mpa);
roa.addPositiveExamples(i,newInstances,numNew,mpa);
}
}
}
if(Parameters.doRuleSplitting) {
for(i=0;i<roa.getNumRules()-1;i++) {
matchProfileAgent mpa=roa.generateActualMPA(i);
splittedRule spl=new splittedRule();
if(editRule(candidateRules.get(roa.getRule(i)),mpa,spl)) {
roa.removeRule(i);
profiles.addElement(spl.mpa1);
profiles.addElement(spl.mpa2);
candidateRules.addElement(spl.rule1);
candidateRules.addElement(spl.rule2);
roa.insertRule(profiles.size()-2,profiles.get(profiles.size()-2));
roa.insertRule(profiles.size()-1,profiles.get(profiles.size()-1));
}
}
}
roa.refineRuleSet();
if(best==null) {
best=roa;
} else {
double accOld=best.getAccuracy();
double accNew=roa.getAccuracy();
if(accNew>accOld) {
best=roa;
} else if(accNew==accOld && roa.getNumRules()<best.getNumRules()) {
best=roa;
} else {
}
}
}
best.copyOrder(ruleOrder);
if(ruleOrder.size()==0) {
int pos=Rand.getInteger(0, profiles.size()-1);
ruleOrder.addElement(pos);
}
}
public void doLocalSearch(){
int ruleSize=Globals_GABIL.ruleSize;
int numInstances = PopulationWrapper.ilas.getNumInstancesOfIteration();
int[] remainingInstances = new int[numInstances];
int[] matched = new int[numInstances];
int i;
for(i=0;i<numInstances;i++) {
remainingInstances[i]=i;
}
int index=0;
boolean lastSplitted=false;
while(index<numRules) {
int pos = index*ruleSize;
int[] rule = getRule(pos);
Integer numMatches = computeMatches(rule,remainingInstances,numInstances,matched);
if(Parameters.doRuleCleaning) {
if(ruleCleaning(rule,matched,numMatches, pos)) {
numMatches = computeMatches(rule,remainingInstances,numInstances,matched);
}
}
if(Parameters.doRuleSplitting) {
if(lastSplitted){
lastSplitted=false;
}
else{
int[] newRule=ruleSplitting(rule,matched,numMatches,pos);
if(newRule!=null) {
int[] newChromosome = new int[ruleSize*(numRules+1)];
System.arraycopy(crm, 0, newChromosome, 0, (index+1)*ruleSize);
System.arraycopy(newRule, 0, newChromosome, (index+1)*ruleSize,ruleSize);
System.arraycopy(crm, (index+1)*ruleSize, newChromosome, (index+2)*ruleSize, (numRules-index-1)*ruleSize);
crm = new int[ruleSize*(numRules+1)];
System.arraycopy(newChromosome, 0, crm, 0, (numRules+1)*ruleSize);
numRules++;
int length2=numRules*ruleSize;
pos=index*ruleSize;
newRule = getRule(pos);
numMatches = computeMatches(newRule,remainingInstances,numInstances,matched);
lastSplitted=true;
}
}
}
numInstances=updateMatches(remainingInstances,numInstances,matched,numMatches);
if(numInstances==0){
break;
}
if(Parameters.doRuleGeneralizing) {
int[] ruleG = getRule(pos);
numMatches=generalizeRule(ruleG,remainingInstances,numInstances,matched,pos, true);
if(numMatches>0) {
numInstances=updateMatches(remainingInstances,numInstances,matched,numMatches);
if(numInstances==0) {
break;
}
}
}
index++;
}
}
public int computeMatches(int[] rule, int[] candidates, int numCandidates, int[] matched)
{
int j;
int numMatches=0;
InstanceWrapper[] instances = PopulationWrapper.ilas.getInstances();
for(j=0;j<numCandidates;j++) {
int inst=candidates[j];
if(ruleMatches(rule,instances[inst])) {
matched[numMatches++]=inst;
}
}
return numMatches;
}
public boolean ruleMatches(int rule[], InstanceWrapper ins){
int j;
for (j = 0; j < Parameters.numAttributes ; j++)
if (rule[Globals_GABIL.offset[j] + ins.nominalValues[j]] == 0)
return false;
return true;
}
public boolean ruleCleaning(int[] rule, int[] matched, int numMatches, int pos){
int ruleSize=Globals_GABIL.ruleSize;
int i;
InstanceWrapper[] instances = PopulationWrapper.ilas.getInstances();
int[] listOK = new int[numMatches];
int[] listKO = new int[numMatches];
int numOK=0,numKO=0;
int cl=rule[ruleSize-1];
for(i=0;i<numMatches;i++) {
if(instances[matched[i]].instanceClass==cl) {
listOK[numOK++]=matched[i];
}
else {
listKO[numKO++]=matched[i];
}
}
cleanTarget ct=cleanTargetOfRule(listOK,numOK,listKO,numKO);
boolean changed=false;
if(ct.maxNeg>0) {
changed=true;
crm[pos+Globals_GABIL.offset[ct.maxAtt]+ct.maxValue] = 0;
}
return changed;
}
//*********************************************************************
//***************** Rule of position pos ******************************
//*********************************************************************
public int[] getRule(int pos){
int ruleSize=Globals_GABIL.ruleSize;
int rule[]=new int[ruleSize];
System.arraycopy(crm, pos, rule, 0, ruleSize);
return rule;
}
public cleanTarget cleanTargetOfRule(int[] instOK, int numOK, int[] instKO, int numKO){
InstanceWrapper[] instances = PopulationWrapper.ilas.getInstances();
int i,j;
int numAttributes=Parameters.numAttributes;
int[][] countKO=new int[numAttributes][];
int[][] countOK=new int[numAttributes][];
int[] candidateAtt=new int[numAttributes];
int[] countCandidateValues=new int[numAttributes];
cleanTarget ct = new cleanTarget();
ct.maxValue=-1;
ct.maxAtt=-1;
ct.maxNeg=0;
int numCandidateAtts=numAttributes;
for(i=0;i<numAttributes;i++) {
candidateAtt[i]=i;
int numValues=Globals_GABIL.size[i];
countOK[i]= new int[numValues];
countKO[i]= new int[numValues];
countCandidateValues[i]=numValues;
for(j=0;j<numValues;j++) {
countOK[i][j]=countKO[i][j]=0;
}
}
for(i=0;i<numOK && numCandidateAtts>0;i++) {
InstanceWrapper ins=instances[instOK[i]];
int indexAtt=0;
while(indexAtt<numCandidateAtts) {
int att=candidateAtt[indexAtt];
int value=ins.nominalValues[att];
if(countOK[att][value]==0) {
countCandidateValues[att]--;
if(countCandidateValues[att]==0) {
candidateAtt[indexAtt]=candidateAtt[numCandidateAtts-1];
numCandidateAtts--;
} else {
indexAtt++;
}
} else {
indexAtt++;
}
countOK[att][value]++;
}
}
if(numCandidateAtts==0) {
return ct;
}
for(i=0;i<numKO;i++) {
InstanceWrapper ins=instances[instKO[i]];
for(j=0;j<numCandidateAtts;j++) {
int att=candidateAtt[j];
int value=ins.nominalValues[att];
countKO[att][value]++;
}
}
for(j=0;j<numCandidateAtts;j++) {
int att=candidateAtt[j];
int numValues=Globals_GABIL.size[att];
for(i=0;i<numValues;i++) {
if(countOK[att][i]==0 && countKO[att][i]>ct.maxNeg) {
ct.maxAtt=att;
ct.maxValue=i;
ct.maxNeg=countKO[att][i];
}
}
}
return ct;
}
public int[] ruleSplitting(int[] rule, int[] matched, int numInst, int posRR){
int ruleSize=Globals_GABIL.ruleSize;
int i,j,k,l,m,n,o,p,q;
InstanceWrapper[] instances = PopulationWrapper.ilas.getInstances();
int[] listOK = new int[numInst];
int[] listKO = new int[numInst];
int numOK=0,numKO=0;
int cl=rule[ruleSize-1];
for(i=0;i<numInst;i++) {
if(instances[matched[i]].instanceClass==cl) {
listOK[numOK++]=matched[i];
} else {
listKO[numKO++]=matched[i];
}
}
if(numKO==0) return null;
activationsAtt[] act=computeActivationStats(listOK,numOK,listKO,numKO);
int maxNeg=0;
int splittedAtt = 0;
int splittedValue = 0;
int valueOrRest = 0;
Vector<Integer>conflicting = new Vector<Integer>(50,10);
int negAtt = 0;
int negValue = 0;
for(i=0;i<Parameters.numAttributes;i++) {
int numConflictingValues=0;
int[] targetConflicting=new int[act[i].numValues];
for(j=0;j<act[i].numValues;j++) {
if(act[i].actValues[j][0]>0 && act[i].actValues[j][1]>0) {
targetConflicting[numConflictingValues++]=j;
}
}
if(numConflictingValues>1) {
attInstances att=computeInstOfAtt(i,listOK,numOK,listKO,numKO);
for(l=0;l<numConflictingValues;l++) {
int target=targetConflicting[l];
int numOK1=att.numInst[target][0];
int numKO1=att.numInst[target][1];
int numOK2=numOK-numOK1;
int numKO2=numKO-numKO1;
int[] listOK2 = new int[numOK2];
int[] listKO2 = new int[numKO2];
int countOK=0;
int countKO=0;
for(m=0;m<act[i].numValues;m++) {
if(m!=target) {
for(n=0;n<att.numInst[m][0];n++) {
listOK2[countOK++]=att.valueInstances[m][0][n];
}
for(n=0;n<att.numInst[m][1];n++) {
listKO2[countKO++]=att.valueInstances[m][1][n];
}
}
}
cleanTarget ct=cleanTargetOfRule(att.valueInstances[target][0]
,numOK1,att.valueInstances[target][1],numKO1);
if(ct.maxNeg>maxNeg) {
maxNeg=ct.maxNeg;
splittedAtt=i;
splittedValue=target;
valueOrRest=1;
conflicting.removeAllElements();
for(q=0;q<numConflictingValues;q++) {
if(targetConflicting[q]!=target) {
conflicting.addElement(targetConflicting[q]);
}
}
negAtt=ct.maxAtt;
negValue=ct.maxValue;
}
ct=cleanTargetOfRule(listOK2,numOK2,listKO2,numKO2);
if(ct.maxNeg>maxNeg) {
maxNeg=ct.maxNeg;
splittedAtt=i;
splittedValue=target;
valueOrRest=0;
conflicting.removeAllElements();
for(q=0;q<numConflictingValues;q++) {
if(targetConflicting[q]!=target) {
conflicting.addElement(targetConflicting[q]);
}
}
negAtt=ct.maxAtt;
negValue=ct.maxValue;
}
}
}
}
int[] newRule=null;
if(maxNeg>0) {
newRule = new int[ruleSize];
System.arraycopy(rule, 0, newRule, 0, ruleSize);
for(i=0;i<conflicting.size();i++) {
crm[posRR+Globals_GABIL.offset[splittedAtt]+conflicting.get(i)]=0;
}
newRule[Globals_GABIL.offset[splittedAtt]+splittedValue]=0;
if(valueOrRest!=0) {
crm[posRR+Globals_GABIL.offset[negAtt]+negValue]=0;
} else {
newRule[Globals_GABIL.offset[negAtt]+negValue]=0;
}
}
return newRule;
}
public activationsAtt[] computeActivationStats(int[] instOK, int numOK, int[] instKO, int numKO){
int i,j;
InstanceWrapper[] instances = PopulationWrapper.ilas.getInstances();
activationsAtt[] act=new activationsAtt[Parameters.numAttributes];
for(int pp=0 ; pp<Parameters.numAttributes;++pp)
act[pp]=new activationsAtt();
for(i=0;i<Parameters.numAttributes;i++) {
int numValues=Globals_GABIL.size[i];
act[i].numValues=numValues;
act[i].actValues=new int[numValues][];
for(j=0;j<numValues;j++) {
act[i].actValues[j]=new int[2];
act[i].actValues[j][0]=act[i].actValues[j][1]=0;
}
}
for(j=0;j<numOK;j++) {
InstanceWrapper ins=instances[instOK[j]];
for(i=0;i<Parameters.numAttributes;i++) {
act[i].actValues[ins.nominalValues[i]][0]++;
}
}
for(j=0;j<numKO;j++) {
InstanceWrapper ins=instances[instKO[j]];
for(i=0;i<Parameters.numAttributes;i++) {
act[i].actValues[ins.nominalValues[i]][1]++;
}
}
return act;
}
public attInstances computeInstOfAtt(int attribute,int[] instOK,int numOK,int[]instKO,int numKO)
{
int numInst=numOK+numKO;
InstanceWrapper[] instances = PopulationWrapper.ilas.getInstances();
int i,j,k;
int numValues=Globals_GABIL.size[attribute];
attInstances att=new attInstances();
att.numValues=numValues;
att.valueInstances = new int[numValues][][];
att.numInst = new int[numValues][];
for(i=0;i<numValues;i++) {
att.numInst[i]= new int[2];
att.numInst[i][0]=0;
att.numInst[i][1]=0;
att.valueInstances[i]= new int[2][];
att.valueInstances[i][0] = new int[numInst];
att.valueInstances[i][1] = new int[numInst];
}
for(i=0;i<numOK;i++) {
int inst=instOK[i];
int value=instances[inst].nominalValues[attribute];
att.valueInstances[value][0][att.numInst[value][0]++]=inst;
}
for(i=0;i<numKO;i++) {
int inst=instKO[i];
int value=instances[inst].nominalValues[attribute];
att.valueInstances[value][1][att.numInst[value][1]++]=inst;
}
return att;
}
public int updateMatches(int[] candidates, int numCand, int[] matched, int numMatched){
int numLeft=0;
int i;
int[] candidatesLeft = new int[numCand-numMatched];
int indexMatched=0;
int currMatched=matched[0];
for(i=0;i<numCand;i++){
if(candidates[i]==currMatched) {
indexMatched++;
if(indexMatched<numMatched)
currMatched=matched[indexMatched];
}
else{
candidatesLeft[numLeft++]=candidates[i];
}
}
for(i=0;i<numLeft;i++){
candidates[i]=candidatesLeft[i];
}
return numLeft;
}
public int generalizeRule(int[] rule, int[] candidates, int numCand, int[] newInstances, int posRR, boolean opcion){
int i,j;
int ruleSize = Globals_GABIL.ruleSize;
int len=ruleSize-1;
int[] countPos = new int[len];
int[] countNeg = new int[len];
Vector<Vector<Integer>> candInst= new Vector<Vector<Integer>>(len,1);
InstanceWrapper[] instances = PopulationWrapper.ilas.getInstances();
int cl=rule[ruleSize-1];
for(i=0;i<len;i++) {
countPos[i]=countNeg[i]=0;
candInst.add(i, null);
}
for(i=0;i<numCand;i++) {
int posInst=candidates[i];
InstanceWrapper ins=instances[posInst];
int numMatches=0;
int whichPos = 0;
for(j=0;j<Parameters.numAttributes;j++) {
int value=ins.nominalValues[j];
int pos=Globals_GABIL.offset[j]+value;
if(rule[pos]==0) {
numMatches++;
whichPos=pos;
if(numMatches>=2) break;
}
}
if(numMatches==1) {
if(ins.instanceClass==cl) {
countPos[whichPos]++;
if(countNeg[whichPos]==0) {
if(candInst.get(whichPos)==null) {
candInst.set(whichPos, new Vector<Integer>((int)(numCand*0.1)));
}
candInst.get(whichPos).addElement(posInst);
}
} else {
countNeg[whichPos]++;
candInst.set(whichPos, null);
}
}
}
int max=0;
int bestPos=0;
for(i=0;i<len;i++) {
if(countNeg[i]==0 && countPos[i]>max) {
bestPos=i;
max=countPos[i];
}
}
if(max>0) {
if(opcion)
crm[posRR+bestPos]=1;
else{
rule[bestPos]=1;
}
for(i=0;i<max;i++) {
newInstances[i]=candInst.get(bestPos).elementAt(i);
}
}
return max;
}
public boolean editRule(int[] rule, matchProfileAgent mpa, splittedRule spl){
int i,j,k,l,m,n,o,p,q;
if(mpa.numKO==0) return false;
activationsAtt[] act=computeActivationStats(mpa.listOK,mpa.numOK,mpa.listKO,mpa.numKO);
int maxNeg=0;
int splittedAtt = 0;
int splittedValue = 0;
boolean valueOrRest = false;
Vector<Integer>conflicting=new Vector<Integer>(50,10);
int negAtt = 0;
int negValue = 0;
for(i=0;i<Parameters.numAttributes;i++) {
int numConflictingValues=0;
int[] targetConflicting=new int[act[i].numValues];
for(j=0;j<act[i].numValues;j++) {
if(act[i].actValues[j][0]>0 && act[i].actValues[j][1]>0) {
targetConflicting[numConflictingValues++]=j;
}
}
if(numConflictingValues>1) {
attInstances att=computeInstOfAtt(i,mpa.listOK,mpa.numOK,mpa.listKO,mpa.numKO);
for(l=0;l<numConflictingValues;l++) {
int target=targetConflicting[l];
int numOK1=att.numInst[target][0];
int numKO1=att.numInst[target][1];
int numOK2=mpa.numOK-numOK1;
int numKO2=mpa.numKO-numKO1;
int[]listOK2 = new int[numOK2];
int[]listKO2 = new int[numKO2];
int countOK=0;
int countKO=0;
for(m=0;m<act[i].numValues;m++) {
if(m!=target) {
for(n=0;n<att.numInst[m][0];n++) {
listOK2[countOK++]=att.valueInstances[m][0][n];
}
for(n=0;n<att.numInst[m][1];n++) {
listKO2[countKO++]=att.valueInstances[m][1][n];
}
}
}
cleanTarget ct=cleanTargetOfRule(att.valueInstances[target][0]
,numOK1,att.valueInstances[target][1],numKO1);
if(ct.maxNeg>maxNeg) {
maxNeg=ct.maxNeg;
splittedAtt=i;
splittedValue=target;
valueOrRest=true;
conflicting.removeAllElements();
for(q=0;q<numConflictingValues;q++) {
if(targetConflicting[q]!=target) {
conflicting.addElement(targetConflicting[q]);
}
}
negAtt=ct.maxAtt;
negValue=ct.maxValue;
}
ct=cleanTargetOfRule(listOK2,numOK2,listKO2,numKO2);
if(ct.maxNeg>maxNeg) {
maxNeg=ct.maxNeg;
splittedAtt=i;
splittedValue=target;
valueOrRest=false;
conflicting.removeAllElements();
for(q=0;q<numConflictingValues;q++) {
if(targetConflicting[q]!=target) {
conflicting.addElement(targetConflicting[q]);
}
}
negAtt=ct.maxAtt;
negValue=ct.maxValue;
}
}
}
}
boolean splitted=false;
if(maxNeg>0) {
splitted=true;
int[] r1= new int[Globals_GABIL.ruleSize];
System.arraycopy(rule, 0, r1, 0, Globals_GABIL.ruleSize);
int[] r2= new int[Globals_GABIL.ruleSize];
System.arraycopy(rule, 0, r2, 0, Globals_GABIL.ruleSize);
for(i=0;i<conflicting.size();i++) {
r1[Globals_GABIL.offset[splittedAtt]+conflicting.get(i)]=0;
}
r2[Globals_GABIL.offset[splittedAtt]+splittedValue]=0;
if(valueOrRest) {
r1[Globals_GABIL.offset[negAtt]+negValue]=0;
} else {
r2[Globals_GABIL.offset[negAtt]+negValue]=0;
}
spl.rule1=r1;
spl.rule2=r2;
spl.mpa1=evaluateRuleCX(r1);
spl.mpa2=evaluateRuleCX(r2);
}
return splitted;
}
public boolean cleanRule(int[] rule ,matchProfileAgent mpa)
{
int i,j;
if(mpa.numKO==0) return false;
cleanTarget ct=cleanTargetOfRule(mpa.listOK,mpa.numOK,mpa.listKO,mpa.numKO);
boolean changed=false;
if(ct.maxNeg>0) {
changed=true;
rule[Globals_GABIL.offset[ct.maxAtt]+ct.maxValue]=0;
int[] removedExamples=new int[ct.maxNeg];
instOfAttAndValue(ct.maxAtt,ct.maxValue,mpa.listOK,mpa.numOK,mpa.listKO,mpa.numKO,removedExamples);
mpa.removeMatched(removedExamples,ct.maxNeg);
}
return changed;
}
public void instOfAttAndValue(int attribute,int value, int[] instOK, int numOK,int[]instKO, int numKO, int []list)
{
InstanceWrapper[] instances = PopulationWrapper.ilas.getInstances();
int i;
int num=0;
for(i=0;i<numOK;i++) {
int instValue=instances[instOK[i]].nominalValues[attribute];
if(instValue==value) {
list[num++]=instOK[i];
}
}
for(i=0;i<numKO;i++) {
int instValue=instances[instKO[i]].nominalValues[attribute];
if(instValue==value) {
list[num++]=instKO[i];
}
}
}
}