/*********************************************************************** 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.Rule_Learning.CN2; import java.util.*; /** * <p>Title: Complex</p> * <p>Description: Structure to represent a complex of one rule</p> * @author Written by Jos� Ram�n Cano de Amo (University of Granada) 28/07/2004 * @author Modified by Alberto Fern�ndez (University of Granada) 15/06/2006 * @version 1.1 * @since JDK1.5 */ public class Complex implements Comparable { /** * This class stores conjunctions of selectors */ private LinkedList compl; private int clas; private int nclass; private int distrib[]; //it contains the number of examples per class that satisfy the antecedent private double heuristic; private String[] nombreAtributos; /** * Builder. Initialize the container variable */ public Complex() { compl = new LinkedList(); } /** * Builder * @param nClas int Number of classes */ public Complex(int nClas) { compl = new LinkedList(); nclass = nClas; distrib = new int[nClas]; for (int i = 0; i < nclass; i++) { distrib[i] = 0; } } /** * Complete builder. It add the number of classes and a selector * @param sel Selector * @param nClas Number of classes */ public Complex(Selector sel, int nClas) { int i; compl = new LinkedList(); compl.add(sel); nclass = nClas; distrib = new int[nClas]; for (i = 0; i < nclass; i++) { distrib[i] = 0; } } /** * Builder. It creates a selector from an attribute,operator value and builds the complex * @param atr Id of the input attribute * @param op operator code (higher or equal, distinct...) * @param val Attribute value */ public Complex(int atr, int op, double val) { int i; Selector s; compl = new LinkedList(); s = new Selector(atr, op, val); compl.add(s); distrib = new int[nclass]; for (i = 0; i < nclass; i++) { distrib[i] = 0; } } /** * Comparison function between two objects of the class complex * @param o "complex" object to compare * @return 0 if the heuristics are equal. 1 if the current complex has a higher heuristic . * -1 if the complex to compare has a higher heuristic */ public int compareTo(Object o) { Complex c2 = (Complex) o; int sal = 0; if ((heuristic == c2.getheuristic()) && (c2.size() == compl.size())) { sal = 0; } else if ((heuristic == c2.getheuristic()) && (compl.size() < c2.size())) { sal = -1; } else if ((heuristic == c2.getheuristic()) && (compl.size() > c2.size())) { sal = 1; } else if (heuristic > c2.getheuristic()) { sal = -1; } else if (heuristic < c2.getheuristic()) { sal = 1; } return (sal); } /** * It checks if a complex is equal to another. They must have the same attribute, operator and value. * @param c Complex to compare * @return True if they are the same. False in other case */ public boolean same(Complex c) { boolean iguales = false; if (c.size() == compl.size()) { iguales = true; for (int i = 0; (i < c.size()) && (iguales); i++) { iguales = (this.getSelector(i).compareTo(c.getSelector(i)) == 0); } } return iguales; } /** * It checks if a complex is almost the same to another * @param c Complex to compare * @return True if they are the same but the last selector. False in other case */ public boolean almostSame(Complex c) { boolean iguales = true; if (c.size() == compl.size()) { iguales = true; for (int i = 0; (i < c.size() - 1) && (iguales); i++) { iguales = (this.getSelector(i).compareTo(c.getSelector(i)) == 0); } } return iguales; } /** * It checks if two complexes have the same class distribution * @param c Complex to compare * @return boolean True if they have the same class distribution for all classes. False in other case */ public boolean sameDistribution(Complex c) { boolean igual = true; for (int i = 0; (i < nclass) && (igual); i++) { igual = this.getClassDistribution(i) == c.getClassDistribution(i); } return igual; } /** * Increments the class distribution * @param i Class id */ public void addClassDistribution(int i) { distrib[i]++; } /** * Id adds the selector if it is not in the list * @param sel The selector to add [attr op value] */ public void addSelector(Selector sel) { compl.add(sel); } /** * It returns one of the selectors associated to the complex * @param i Selector index * @return The i-th selector of the complex */ public Selector getSelector(int i) { //Selector s = (Selector) compl.get(i); //Selector dos = new Selector(s.getAtributo(),s.getOperador(),s.getValores()); return (Selector) compl.get(i); } /** * It returns the number of selectors of the complex * @return Complex size */ public int size() { return (compl.size()); } /** * It prints the complex content */ public void print() { for (int x = 0; x < compl.size(); x++) { Selector s = (Selector) compl.get(x); System.out.print("(" + nombreAtributos[s.getAttribute()] + " "); switch (s.getOperator()) { case 0: System.out.print("="); break; case 1: System.out.print("<>"); break; case 2: System.out.print("<="); break; default: System.out.print(">"); } double[] valores = s.getValues(); if (valores.length > 1) { System.out.print(" " + valores[0]); for (int i = 1; i < valores.length - 1; i++) { System.out.print(" ^ " + valores[i]); } System.out.print(" ^ " + valores[valores.length - 1] + ")"); } else { System.out.print(" " + valores[0] + ")"); } if (x < compl.size() - 1) { System.out.print(" AND "); } } } /** * It prints on a string the content of the complex * @return String a string with the content of the complex */ public String printString() { String cad = ""; for (int x = 0; x < compl.size(); x++) { Selector s = (Selector) compl.get(x); cad += nombreAtributos[s.getAttribute()] + " "; switch (s.getOperator()) { case 0: cad += "="; break; case 1: cad += "<>"; break; case 2: cad += "<="; break; case 3: cad += ">"; break; } double[] valores = s.getValues(); if (valores.length > 1) { cad += " " + valores[0]; for (int i = 1; i < valores.length - 1; i++) { cad += " ^ " + valores[i]; } cad += " ^ " + valores[valores.length - 1] + ""; } else { cad += " " + valores[0] + ""; } if (x < compl.size() - 1) { cad += " AND "; } } return cad; } /** * It returns the class distribution * @return the class distribution */ public int[] getDistribution() { int ret[] = new int[nclass]; int i; for (i = 0; i < nclass; i++) { ret[i] = distrib[i]; } return ret; } /** * It returns the class distribution of a specified class * @param i clas id * @return the class distribution of a specified class */ public int getClassDistribution(int i) { return distrib[i]; } /** * It resets the distribution value for the complex */ public void deleteDistribution() { for (int i = 0; i < nclass; i++) { distrib[i] = 0; } } /** * It prints the class distribution */ public void printDistribution() { int i; System.out.print(" ["); for (i = 0; i < nclass; i++) { System.out.print(" " + distrib[i]); } System.out.print("]"); } /** * It prints the class distribution on a string * @return a string with the class distribution */ public String printDistributionString() { int i; String cad; cad = " ["; for (i = 0; i < nclass; i++) { cad += " " + distrib[i]; } cad += "]"; return cad; } /** * It return the class id * @return the class id */ public int getClas() { return clas; } /** * It assigns a class to the complex * @param i the class id */ public void setClass(int i) { clas = i; } /** * It copies the complex * @return A new cloned complex */ public Complex copyRule() { int i; Complex c = new Complex(nclass); for (i = 0; i < compl.size(); i++) { Selector aux = (Selector) compl.get(i); Selector s = new Selector(aux.getAttribute(), aux.getOperator(), aux.getValue()); c.addSelector(s); } c.distrib = this.getDistribution(); c.setClass(clas); return c; } /** * It computes the Laplacian value for the complex */ public void computeLaplacian() { double nc; double ntot; int i; nc = distrib[clas]; for (i = 0, ntot = 0; i < nclass; i++) { ntot += distrib[i]; } //heuristica = (ntot - nc + nClases - 1) / (ntot + nClases); heuristic = (nc + 1) / (ntot + nclass); } /** * Devuelve el valor heur�stico del Complex * @return double idem */ public double getHeuristic() { return heuristic; } /** * Asigna un valor heuristico (Wracc) al Complex * @param heu double el valor heuristico */ public void setHeuristic(double heu) { heuristic = heu; } /** * It checks if the complex covers a given example * @param m The example * @return boolean True if it covers the example. False in other case */ public boolean covered(Instance m) { boolean cubierto = true; double[] ejemplo = m.getMuest(); for (int i = 0; i < this.size() && cubierto; i++) { Selector s = this.getSelector(i); switch (s.getOperator()) { case 0: // equal operator double[] valor = s.getValues(); cubierto = false; for (int j = 0; (j < valor.length) && (!cubierto); j++) { cubierto = (ejemplo[s.getAttribute()] == valor[j]); } break; case 1: //distinct operator cubierto = ejemplo[s.getAttribute()] != s.getValue(); break; case 2: //lower or equal cubierto = ejemplo[s.getAttribute()] <= s.getValue(); break; case 3: //higher cubierto = ejemplo[s.getAttribute()] > s.getValue(); break; } } return cubierto; } /** * It assigns a class distribution * @param dis the given class distribution */ public void setDistribution(int dis[]) { int i; for (i = 0; i < nclass; i++) { distrib[i] = dis[i]; } } /** * It returns the number of classes * @return the number of classes */ public int getNclasses() { return nclass; } /** * It returns the heuristic of the complex (LEF function) * @return the heuristic of the example */ public double getheuristic() { return heuristic; } /** * It assigns the heuristic of the complex computed as:<br/> * Covered positives - covered negatives / number of selectors * @param heuristic The heuristic */ public void setheuristic(double heuristic) { this.heuristic = heuristic; } /** * It returns the number of selectors of the complex * @return The size or complexity of the complex */ public int getSize() { return this.compl.size(); } /** * It performs a local copy of the name of the input variables * @param atributos String[] an Array that stores the name of each variable */ public void addAttributeNames(String[] atributos) { nombreAtributos = new String[atributos.length - 1]; for (int i = 0; i < atributos.length - 1; i++) { nombreAtributos[i] = atributos[i]; } } }