/*********************************************************************** 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.Decision_Trees.Target; /** * <p>Title: </p> * * <p>Description: </p> * * <p>Copyright: Copyright (c) 2007</p> * * <p>Company: </p> * * @author not attributable * @version 1.0 */ import org.core.Randomize; public class Nodo { String clase; int claseInt; boolean nominal, isLeaf; String[] valoresNom; double valor; int numAtributos; //uno, dos � tres (combinaci�n lineal) int[] atributos; double[] pesos; //para la combinaci�n lineal myDataset train; public Nodo() { } public Nodo(boolean isLeaf, myDataset train, double prob1, double prob2) { this.train = train; this.isLeaf = isLeaf; if (isLeaf) { //solo almaceno la clase clase = "?"; //se genera dinamicamente al evaluar/clasificar } else { nuevo(prob1,prob2); } } public void nuevo(double prob1,double prob2) { //primero elijo la variable: int atributo = Randomize.RandintClosed(0, train.getnInputs()-1); nominal = train.esNominal(atributo); splitSet(atributo,prob1,prob2); } public void splitSet(int atributo,double prob1,double prob2){ if (nominal) { //el atributo es cualitativo //hago una divisi�n en dos conjuntos (aunque solo necesito guardar uno) int totalNominales = train.totalNominales(atributo); int nominalesEscogidos = Randomize.RandintClosed(1, totalNominales); valoresNom = new String[nominalesEscogidos]; int[] noSeleccionados = new int[totalNominales]; for (int i = 0; i < totalNominales; i++) { noSeleccionados[i] = i; } for (int i = 0; i < valoresNom.length; i++) { int seleccion = Randomize.RandintClosed(0, totalNominales-1); double aux = 1.0 * noSeleccionados[seleccion]; valoresNom[i] = train.valorNominal(atributo, aux); noSeleccionados[seleccion] = noSeleccionados[totalNominales - 1]; totalNominales--; } numAtributos = 1; atributos = new int[1]; atributos[0] = atributo; } else { //es cuantitativo //Hay dos opciones: a) At <= valor, b) Combinacion lineal: b.1) w1�X1 + w2�X2 <= w1�s1+w2�s2, b.2) 3 atributos if (Randomize.Rand() <= prob1) { //At <= valor int ejemplo = Randomize.RandintClosed(0, train.size()-1); this.valor = train.getExample(ejemplo)[atributo]; numAtributos = 1; atributos = new int[1]; atributos[0] = atributo; pesos = new double[1]; pesos[0] = 1; } else { if (Randomize.Rand() <= prob2) { //2 variables solo numAtributos = 2; atributos = new int[2]; atributos[0] = atributo; int att2; do { att2 = Randomize.RandintClosed(0, train.getnInputs()-1); //System.err.println("Mira -> "+att2+"/"+train.getnInputs()); } while ( (att2 == atributo) || (train.esNominal(att2))); atributos[1] = att2; int ejemplo = Randomize.RandintClosed(0, train.size()-1); double valor1 = train.getExample(ejemplo)[atributo]; ejemplo = Randomize.RandintClosed(0, train.size()-1); double valor2 = train.getExample(ejemplo)[att2]; pesos = new double[2]; asignaPesos(1.0); valor = pesos[0] * valor1 + pesos[1] * valor2; } else { //tomo tres variables numAtributos = 3; atributos = new int[3]; atributos[0] = atributo; int att2, att3; do { att2 = Randomize.RandintClosed(0, train.getnInputs()-1); //System.err.println("Mira -> "+att2+"/"+train.getnInputs()); } while ( (att2 == atributo) || (train.esNominal(att2))); atributos[1] = att2; do { att3 = Randomize.RandintClosed(0, train.getnInputs()-1); //System.err.println("Mira -> "+att2+"/"+train.getnInputs()); } while ( (att3 == atributo) || (att3 == att2) || (train.esNominal(att3))); atributos[2] = att3; int ejemplo = Randomize.RandintClosed(0, train.size()-1); double valor1 = train.getExample(ejemplo)[atributo]; ejemplo = Randomize.RandintClosed(0, train.size()-1); double valor2 = train.getExample(ejemplo)[att2]; ejemplo = Randomize.RandintClosed(0, train.size()-1); double valor3 = train.getExample(ejemplo)[att3]; pesos = new double[3]; asignaPesos(1.0); valor = pesos[0] * valor1 + pesos[1] * valor2 + pesos[2] * valor3; } } } } public void asignaPesos(double prob){ for (int i = 0; i < numAtributos; i++) { if (Randomize.Rand() <= prob){ pesos[i] = Randomize.RanddoubleClosed( -1, 1); } } } public Nodo copia() { Nodo n = new Nodo(); n.clase = clase; n.claseInt = claseInt; n.isLeaf = isLeaf; n.train = train; if (!isLeaf) { n.nominal = nominal; n.numAtributos = numAtributos; n.atributos = new int[atributos.length]; n.atributos = atributos.clone(); if (nominal) { n.valoresNom = new String[valoresNom.length]; n.valoresNom = valoresNom.clone(); } else { n.valor = valor; n.pesos = new double[pesos.length]; n.pesos = pesos.clone(); } } return n; } public String printString() { String cadena = new String(""); if (isLeaf) { cadena += train.nombreVar(train.getnInputs()) + " = " + clase; } else { //imprimir <at, op, valor> if (nominal) { cadena += train.nombreVar(atributos[0]); //atributo cadena += " = {"; for (int i = 0; i < valoresNom.length; i++) { cadena += ", " + valoresNom[i]; } cadena += "} "; } else { if (numAtributos == 1) { cadena += train.nombreVar(atributos[0]); //atributo cadena += " <= " + valor; } else { //combinacion lineal int i; for (i = 0; i < numAtributos - 1; i++) { cadena += pesos[i] + "*" + train.nombreVar(atributos[i]) + " + "; } cadena += pesos[i] + "*" + train.nombreVar(atributos[i]); cadena += " <= " + valor; } } } return cadena; } /* double valor; int numAtributos; //uno, dos � tres (combinaci�n lineal) int[] atributos; double[] pesos; //para la combinaci�n lineal */ public boolean cubre(int posEjemplo) { double[] ejemplo = train.getExample(posEjemplo); return cubre(ejemplo); } public boolean cubre(double [] ejemplo){ boolean cubierto = false; if (nominal) { String valorN = train.valorNominal(atributos[0], ejemplo[atributos[0]]); for (int i = 0; (i < valoresNom.length) && (!cubierto); i++) { cubierto = (valoresNom[i] == valorN); } } else { if (numAtributos == 1) { cubierto = (ejemplo[atributos[0]] <= valor); } else { double valorAux = 0; for (int i = 0; i < numAtributos; i++) { valorAux += pesos[i] * ejemplo[atributos[i]]; } cubierto = (valorAux <= valor); } } return cubierto; } public void copiar(Nodo copia) { this.clase = copia.clase; this.claseInt = copia.claseInt; this.isLeaf = copia.isLeaf; this.train = copia.train; if (!isLeaf) { this.numAtributos = copia.numAtributos; this.nominal = copia.nominal; this.atributos = new int[copia.atributos.length]; this.atributos = copia.atributos.clone(); if (nominal) { this.valoresNom = new String[copia.valoresNom.length]; this.valoresNom = copia.valoresNom.clone(); } else { this.valor = copia.valor; this.pesos = new double[copia.pesos.length]; this.pesos = copia.pesos.clone(); } } } }