/*********************************************************************** 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 Pedro Gonz�lez (University of Jaen) 15/02/2004 * @version 1.0 * @since JDK1.5 * </p> */ package keel.Algorithms.Subgroup_Discovery.MESDIF.Calculate; import org.core.Files; public class Individual { /** * <p> * Defines an individual, composed by a cromosome * Includes variables to store the size, the fitness, and if the individual is evaluated or not * </p> */ private Chromosome cromosoma; // Individual contents private int tamano; // Number of genes private float fitness; // Individual Fitness private boolean evaluado; // Individual evaluated or not private String clase_obj; // Value of the selected Class for the target variable -- from param private int n_clasObj; // Number of the label corresponding the target class -- from globals private int total_clase; // Number of examples of the database belonging to the class of this individual private int num_var; // Number of variables taking part in the individual /** * <p> * Creates new instance of Individual * </p> * @param length Length of the chromosome for the individual * @param datos_v Contents the type of the variable, and the number of labels. */ public Individual(int length, TypeVar datos_v[]) { tamano = length; cromosoma = new Chromosome(length, datos_v); fitness = 0; evaluado = false; } /** * <p> * Empty initialization of the individual. Performed by init_crom method * </p> */ public void InitIndEmp () { cromosoma.InitCromEmp(); // Empty initialization method evaluado = false; // Individual not evaluated fitness = 0 ; // Current fitness } /** * <p> * Returns the size of the Chromosome * </p> * @return The size of the Chromosome */ public int getIndivSize () { return tamano; } /** * <p> * Returns the hole Chromosome * </p> * @return The Chromosome of the individual */ public Chromosome getIndivCrom () { return cromosoma; } /** * <p> * Returns the indicated value of the gene of the Chromosome * </p> * @param pos Position of the variable in the Chromosome * @param elem Position of the gen of the variable * @return Value of the gen of the variable */ public int getCromElem (int pos, int elem) { return cromosoma.getCromElem (pos, elem); } /** * <p> * Sets the value of the indicated value of the gene of the Chromosome * </p> * @param pos Position of the variable in the Chromosome * @param elem Position of the gen of the variable */ public void setCromElem (int pos, int elem, int val) { cromosoma.setCromElem(pos, elem, val); } /** * <p> * Returns the number of variables of the rule (including the consequent) * </p> * @return Number of variables of the Chromosome */ public int getNumVar () { return num_var; } /** * <p> * Sets the number of variables of the rule (including the consequent) * </p> * @param num Sets the number of variables of the Chromosome */ public void setNumVar (int num) { num_var = num; } /** * <p> * Returns the number of the class of the individual * </p> * @return Number of the class of the individual */ public int getNumClass () { return n_clasObj; } /** * <p> * Sets the number of the class of the individual * </p> * @param val Sets the number of classes */ public void setNumClass (int val) { n_clasObj = val; } /** * <p> * Returns the string with the name of the class of the individual * </p> * @return Name of the class of the individual */ public String getNameClass () { return clase_obj; } /** * <p> * Sets the value of the name of the class of the individual * </p> * @param val Value to introduce in the name of the class */ public void setNameClass (String val) { clase_obj = val; } /** * <p> * Returns the number of the class of the invividual * </p> * @return Number of total classes of the individual */ public int getTotalClass () { return total_clase; } /** * <p> * Sets the number of the class of the individual * </p> * @param val Number of total classes of the individual */ public void setTotalClass (int val) { total_clase = val; } /** * <p> * Returns if the individual has been evaluated * </p> * @return If the individual has been evaluated */ public boolean getIndivEvaluated () { return evaluado; } /** * <p> * Sets state of the individual * </p> * @param val Boolean value with the state of evaluated */ public void setIndivEvaluated (boolean val) { evaluado = val; } /** * <p> * Returns the fitness of the individual * </p> * @return Value of the fitness of the individual */ public float getIndivPerf () { return fitness; } /** * <p> * Sets the fitness of the individual * </p> * @param perf Value to introduce in the fitnees of the individual */ public void setIndivPerf (float perf) { fitness = perf; } /** * <p> * Returns if the indicated individual is equal to another individual * </p> * @param a Individual to compare * @return If both individuals are equal or not */ public boolean EqualTo (Individual a) { boolean equals= true; int number; for (int i=0;i<this.tamano;i++) { number = this.getIndivCrom().getCromGeneLength(i); for (int j=0;j<number;j++) { if (this.getCromElem(i,j) != a.getCromElem(i,j)) { equals = false; break; } } } return equals; } /** * <p> * Counts the number of examples of the DataSet belonging to the number of the class indicated * </p> * @param num_clase The number of the class * @return The number of examples for the class "num_clase" **/ private int ExamplesClass (int num_clase) { int num=0; // Initialize to 0 for (int i=0; i<StCalculate.n_eje; i++) { /* If the example class is the target class, increase the number of examples of the target class */ if (StCalculate.tabla[i].clase == num_clase) num++; } return num; } /** * <p> * Return the number of interval of a value in a variable * </p> */ private int NumInterval (float value, int num_var) { float pertenencia, new_pert; int interv; interv = -1; pertenencia = new_pert = 0; for (int i=0; i<StCalculate.var[num_var].n_etiq;i++) { new_pert = StCalculate.BaseDatos[num_var][i].Fuzzy (value); if (new_pert>pertenencia) { interv = i; pertenencia = new_pert; } } return interv; } /** * <p> * Evaluate the individual * </p> * @param GI Gain Info array * @param total_class Total number of examples of the class * @return An Result object */ public Result CalcInd (float[] GI, int total_class) { int ejCompAntFuzzy=0; // Number of compatible examples with the antecedent of any class - fuzzy version --- unused int ejCompAntCrisp=0; // Number of compatible examples with the antecedent of any class - crisp version int ejCompAntClassFuzzy=0; // Number of compatible examples (antecedent and class) - fuzzy version int ejCompAntClassCrisp=0; // Number of compatible examples (antecedent and class) - crisp version int ejCompAntClassNewFuzzy=0; // Number of new covered compatible examples (antec and class) - fuzzy version int ejCompAntClassNewCrisp=0; // Number of new covered compatible examples (antec and class) - crisp version float gradoCompAntFuzzy=0; // Total compatibility degree with the antecedent - fuzzy version float gradoCompAntClassFuzzy=0; // Tot compatibility degree with antecedent and class - fuzzy version float gradoCompAntClassNewEjFuzzy=0; // Tot compatibility degree with antecedent and class of new covered examples - fuzzy version float disparoFuzzy; // Final compatibility degree of the example with the individual - fuzzy version float disparoCrisp; // Final compatibility degree of the example with the individual - crisp version float pertenencia, pert, completitud, fsupport, csupport, confianza, cconfianza, interes; float accuracy, coverage, /*n_support,*/ significance, unusualness; float suma, /*p_obj,*/ logaritmo; Result res = new Result(); int cubreClase[] = new int[StCalculate.n_clases]; // Para el calculo de Significance necesitamos saber cuantos ejemplos de cada clase cubre int ejClase[] = new int[StCalculate.n_clases]; // Para el calculo de Significance necesitamos saber cuantos ejemplos hay de cada clase for (int i=0; i<StCalculate.n_clases; i++) { cubreClase[i]=0; ejClase[i] = ExamplesClass(i); } int num_var_no_interv=0; // Number of variables that don't take part in the rule for (int i=0; i<StCalculate.n_eje; i++) { // For each example of the dataset disparoFuzzy = 1; disparoCrisp = 1; num_var_no_interv = 0; // Compute all chromosome values for (int j=0; j<StCalculate.num_vars; j++) { if (!StCalculate.var[j].continua) { // Discrete variable if (cromosoma.getCromElem(j,StCalculate.var[j].n_etiq)==1){ // Variable j takes part in the rule if ((cromosoma.getCromElem(j,(int)StCalculate.tabla[i].ejemplo[j])==0) && (!Calculate.getLost(i,j))) { disparoFuzzy = 0; disparoCrisp =0; } } else num_var_no_interv++; // Variable does not take part } else { // Continuous variable if (cromosoma.getCromElem(j, StCalculate.var[j].n_etiq)==1){ // Variable takes part in the rule // Fuzzy computation if (!Calculate.getLost(i,j)) { // If the value is not a lost value pertenencia = 0; for (int k=0; k<StCalculate.var[j].n_etiq; k++) { if (cromosoma.getCromElem(j,k)==1) // if the value takes part in the rule pert = StCalculate.BaseDatos[j][k].Fuzzy (StCalculate.tabla[i].ejemplo[j]); else pert = 0; pertenencia = Utils.Maximum (pertenencia, pert); } disparoFuzzy = Utils.Minimum (disparoFuzzy, pertenencia); } // Crisp computation if (!Calculate.getLost(i,j)) if (cromosoma.getCromElem(j,NumInterval (StCalculate.tabla[i].ejemplo[j], j))==0) disparoCrisp = 0; } else num_var_no_interv++; // Variable does not take part } } // Update globals counters gradoCompAntFuzzy += disparoFuzzy; if (disparoFuzzy>0) { ejCompAntFuzzy++; if (StCalculate.tabla[i].clase == this.n_clasObj) { gradoCompAntClassFuzzy +=disparoFuzzy; ejCompAntClassFuzzy ++; } if ((!StCalculate.tabla[i].fcubierto) && (StCalculate.tabla[i].clase == this.n_clasObj)) { ejCompAntClassNewFuzzy++; // Increments the number of covered examples gradoCompAntClassNewEjFuzzy += disparoFuzzy; StCalculate.tabla[i].fcubierto = true; // Marks example } } if (disparoCrisp>0) { ejCompAntCrisp++; if (StCalculate.tabla[i].clase == this.n_clasObj) { ejCompAntClassCrisp ++; } cubreClase[StCalculate.tabla[i].clase]++; if ((!StCalculate.tabla[i].ccubierto) && (StCalculate.tabla[i].clase == /*StCalculate*/this.n_clasObj)) { // If example was not previusly covered and belongs to the target class increments the number of covered examples ejCompAntClassNewCrisp++; StCalculate.tabla[i].ccubierto = true; // Marks example } } } // End of cycle for each example // Compute the measures // Compute Completitud // Examples of the rule->class / examples of the class if (total_class != 0) completitud = ((float)ejCompAntClassFuzzy/total_class); else completitud = 0; // Compute CSupport (lavac) // (Crisp): Number of examples compatibles with antecedent and class / total number of exammples csupport = ((float)ejCompAntClassCrisp/StCalculate.n_eje); // Compute FSupport // (Fuzzy): degree of compatibility with antecedent and class / total examples fsupport = ((float)gradoCompAntClassFuzzy/StCalculate.n_eje); // Compute FConfianza // Compatibility grade with the antec. and class between the total grade with the antec. if (gradoCompAntFuzzy != 0) confianza = (float)gradoCompAntClassFuzzy/gradoCompAntFuzzy; else confianza = 0; // Compute CConfianza // (Crisp): number of examples compatibles with antecedent and class / number examples compatibles with antecedent if (ejCompAntCrisp != 0) cconfianza = (float)ejCompAntClassCrisp/ejCompAntCrisp; else cconfianza = 0; // Compute accuracy // (Crisp) Defined in Lavrac04: // examples compatibles with antecedent and class +1) / (crisp examples comp. with antecedent + classes) accuracy = (float)(ejCompAntClassCrisp+1) / (ejCompAntCrisp + StCalculate.n_clases); // Compute coverage // Number of examples covered for the antecedent between the total examples coverage = ((float)ejCompAntCrisp/StCalculate.n_eje); // Compute significance float sumaSignClase=0; for (int i=0; i<StCalculate.n_clases; i++) { // cubreClase[i] has the frequency observed if (cubreClase[i]!=0) { // If 0 don�t add sumaSignClase += cubreClase[i] * Math.log10((float)cubreClase[i]/(ejClase[i]*coverage)); } } significance = 2 * sumaSignClase; // Compute unusualness // p(cond) * (p(class|cond) - p(class)) if (ejCompAntCrisp==0) unusualness = 0; else unusualness = coverage * ( (float)ejCompAntClassCrisp/ejCompAntCrisp - (float)total_class/StCalculate.n_eje); /* Support, confidence and coverage is set to 0 if no variable takes part */ if (num_var_no_interv >= StCalculate.num_vars) { completitud = fsupport = csupport = confianza = cconfianza = interes = 0; accuracy = coverage = significance = unusualness = 0; } /* Store the quality measures to be returned */ res.perf = -1; res.comp = completitud; res.csup = csupport; res.fsup = fsupport; res.fconf = confianza; res.cconf = cconfianza; res.accu = accuracy; res.cov = coverage; res.sign = significance; res.unus = unusualness; return (res); } /** * <p> * Method to Print the contents of the individual * </p> * @param nFile Files to write the individual */ public void Print(String nFile) { String contents; cromosoma.Print(nFile); contents = "Fitness "+fitness + "\n"; contents+= "Evaluated? " + evaluado + "\n"; Files.addToFile(nFile, contents); } }