/*********************************************************************** 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/ **********************************************************************/ /** * * File: KNN.java * * An auxiliary implementation of the KNN classifier for using in Instance Selection algorithms * * @author Written by Salvador Garc�a (University of Granada) 20/07/2004 * @author Modified by Isaac Triguero (University of Granada) 20/06/2010 * @version 0.2 * @since JDK1.5 * */ package keel.Algorithms.ImbalancedClassification.Ensembles.Preprocess.Basic; import keel.Dataset.Attribute; import keel.Dataset.Attributes; import keel.Dataset.Instance; import keel.Dataset.InstanceSet; import org.core.Files; public class KNN { /** * Prints output files. * * @param filename Name of output file * @param realClass Real output of instances * @param prediction Predicted output for instances */ public static void writeOutput(String filename, int [][] realClass, int [][] prediction, Attribute inputs[], Attribute output, String relation) { String text = ""; /*Printing input attributes*/ text += "@relation "+ relation +"\n"; for (int i=0; i<inputs.length; i++) { text += "@attribute "+ inputs[i].getName()+" "; if (inputs[i].getType() == Attribute.NOMINAL) { text += "{"; for (int j=0; j<inputs[i].getNominalValuesList().size(); j++) { text += (String)inputs[i].getNominalValuesList().elementAt(j); if (j < inputs[i].getNominalValuesList().size() -1) { text += ", "; } } text += "}\n"; } else { if (inputs[i].getType() == Attribute.INTEGER) { text += "integer"; } else { text += "real"; } text += " ["+String.valueOf(inputs[i].getMinAttribute()) + ", " + String.valueOf(inputs[i].getMaxAttribute())+"]\n"; } } /*Printing output attribute*/ text += "@attribute "+ output.getName()+" "; if (output.getType() == Attribute.NOMINAL) { text += "{"; for (int j=0; j<output.getNominalValuesList().size(); j++) { text += (String)output.getNominalValuesList().elementAt(j); if (j < output.getNominalValuesList().size() -1) { text += ", "; } } text += "}\n"; } else { text += "integer ["+String.valueOf(output.getMinAttribute()) + ", " + String.valueOf(output.getMaxAttribute())+"]\n"; } /*Printing data*/ text += "@data\n"; Files.writeFile(filename, text); if (output.getType() == Attribute.INTEGER) { text = ""; for (int i=0; i<realClass.length; i++) { for (int j=0; j<realClass[0].length; j++){ text += "" + realClass[i][j] + " "; } for (int j=0; j<realClass[0].length; j++){ text += "" + prediction[i][j] + " "; } text += "\n"; if((i%10)==9){ Files.addToFile(filename, text); text = ""; } } if((realClass.length%10)!=0){ Files.addToFile(filename, text); } } else{ text = ""; for (int i=0; i<realClass.length; i++) { for (int j=0; j<realClass[0].length; j++){ text += "" + (String)output.getNominalValuesList().elementAt(realClass[i][j]) + " "; } for (int j=0; j<realClass[0].length; j++){ if(prediction[i][j]>-1){ text += "" + (String)output.getNominalValuesList().elementAt(prediction[i][j]) + " "; } else{ text += "" + "Unclassified" + " "; } } text += "\n"; if((i%10)==9){ Files.addToFile(filename, text); text = ""; } } if((realClass.length%10)!=0){ Files.addToFile(filename, text); } } }//end-method /** * Calculates the Euclidean distance between two instances * * @param instance1 First instance * @param instance2 Second instance * @return The Euclidean distance * */ protected static double distance(double instance1[],double instance2[]){ double length=0.0; for (int i=0; i<instance1.length; i++) { length += (instance1[i]-instance2[i])*(instance1[i]-instance2[i]); } length = Math.sqrt(length); return length; } //end-method /** * Evaluates a instance to predict its class. * * @param example Instance evaluated * @return Class predicted * */ public static int evaluate (double example[], double trainData[][],int nClasses,int trainOutput[],int k) { double minDist[]; int nearestN[]; int selectedClasses[]; double dist; int prediction; int predictionValue; boolean stop; nearestN = new int[k]; minDist = new double[k]; for (int i=0; i<k; i++) { nearestN[i] = 0; minDist[i] = Double.MAX_VALUE; } //KNN Method starts here for (int i=0; i<trainData.length; i++) { dist = distance(trainData[i],example); if (dist > 0.0){ //leave-one-out //see if it's nearer than our previous selected neighbors stop=false; for(int j=0;j<k && !stop;j++){ if (dist < minDist[j]) { for (int l = k - 1; l >= j+1; l--) { minDist[l] = minDist[l - 1]; nearestN[l] = nearestN[l - 1]; } minDist[j] = dist; nearestN[j] = i; stop=true; } } } } //we have check all the instances... see what is the most present class selectedClasses= new int[nClasses]; for (int i=0; i<nClasses; i++) { selectedClasses[i] = 0; } for (int i=0; i<k; i++) { // System.out.println("nearestN i ="+i + " =>"+nearestN[i]); // System.out.println("trainOutput ="+trainOutput[nearestN[i]]); selectedClasses[trainOutput[nearestN[i]]]+=1; } prediction=0; predictionValue=selectedClasses[0]; for (int i=1; i<nClasses; i++) { if (predictionValue < selectedClasses[i]) { predictionValue = selectedClasses[i]; prediction = i; } } return prediction; } //end-method /** * Executes KNN * * @param nvec Number of neighbors * @param conj Reference to the training set * @param clases Output attribute of each instance * @param ejemplo New instance to classifiy * @param nClases Number of classes of the problem * * @return Class of the new instance */ public static int evaluacionKNN (int nvec, double conj[][], int clases[], double ejemplo[], int nClases) { return evaluacionKNN2 (nvec,conj, clases, ejemplo, nClases); } //end-method /** * Executes KNN * * @param nvec Number of neighbors * @param conj Reference to the training set * @param clases Output attribute of each instance * @param ejemplo New instance to classifiy * @param nClases Number of classes of the problem * * @return Class of the new instance */ public static int evaluacionKNN2 (int nvec, double conj[][], int clases[], double ejemplo[], int nClases) { int i, j, l; boolean parar = false; int vecinosCercanos[]; double minDistancias[]; int votos[]; double dist; int votada, votaciones; if (nvec > conj.length) nvec = conj.length; nClases = Attributes.getOutputAttribute(0).getNumNominalValues(); votos = new int[nClases]; vecinosCercanos = new int[nvec]; minDistancias = new double[nvec]; for (i=0; i<nvec; i++) { vecinosCercanos[i] = -1; minDistancias[i] = Double.POSITIVE_INFINITY; } for (i=0; i<conj.length; i++) { dist = distancia(conj[i], ejemplo); if (dist > 0) { parar = false; for (j = 0; j < nvec && !parar; j++) { if (dist < minDistancias[j]) { parar = true; for (l = nvec - 1; l >= j+1; l--) { minDistancias[l] = minDistancias[l - 1]; vecinosCercanos[l] = vecinosCercanos[l - 1]; } minDistancias[j] = dist; vecinosCercanos[j] = i; } } } } for (j=0; j<nClases; j++) { votos[j] = 0; } for (j=0; j<nvec; j++) { if (vecinosCercanos[j] >= 0) votos[clases[vecinosCercanos[j]]] ++; } votada = 0; votaciones = votos[0]; for (j=1; j<nClases; j++) { if (votaciones < votos[j]) { votaciones = votos[j]; votada = j; } } return votada; } //end-method /** * Executes KNN * * @param nvec Number of neighbors * @param conj Reference to the training set * @param clases Output attribute of each instance * @param ejemplo New instance to classifiy * @param nClases Number of classes of the problem * * @return The neighboors' classes. */ public static int[] evaluacionKNN3 (int nvec, double conj[][], int clases[], double ejemplo[], int nClases) { int i, j, l; boolean parar = false; int vecinosCercanos[]; int clasesVecinosCercanos[]; double minDistancias[]; double dist; if (nvec > conj.length) nvec = conj.length; vecinosCercanos = new int[nvec]; clasesVecinosCercanos= new int[nvec]; minDistancias = new double[nvec]; for (i=0; i<nvec; i++) { vecinosCercanos[i] = -1; clasesVecinosCercanos[i]=-1; minDistancias[i] = Double.POSITIVE_INFINITY; } for (i=0; i<conj.length; i++) { dist = distancia(conj[i], ejemplo); if (dist > 0) { parar = false; for (j = 0; j < nvec && !parar; j++) { if (dist < minDistancias[j]) { parar = true; for (l = nvec - 1; l >= j+1; l--) { minDistancias[l] = minDistancias[l - 1]; vecinosCercanos[l] = vecinosCercanos[l - 1]; } minDistancias[j] = dist; vecinosCercanos[j] = i; } } } } for (j=0; j<vecinosCercanos.length; j++) { if(vecinosCercanos[j]!=-1) clasesVecinosCercanos[j] =clases[vecinosCercanos[j]]; } return clasesVecinosCercanos; } //end-method /** * Executes KNN * * @param nvec Number of neighbors * @param conj Reference to the training set * @param clases Output attribute of each instance * @param ejemplo New instance to classifiy * @param nClases Number of classes of the problem * @param nVotos Maximun number of votes achieved * * @return Class of the new instance */ public static int evaluacionKNN2 (int nvec, double conj[][], int clases[], double ejemplo[], int nClases, Referencia nVotos) { int i, j, l; boolean parar = false; int vecinosCercanos[]; double minDistancias[]; int votos[]; double dist; int votada, votaciones; if (nvec > conj.length) nvec = conj.length; votos = new int[nClases]; vecinosCercanos = new int[nvec]; minDistancias = new double[nvec]; for (i=0; i<nvec; i++) { vecinosCercanos[i] = -1; minDistancias[i] = Double.POSITIVE_INFINITY; } for (i=0; i<conj.length; i++) { dist = distancia(conj[i], ejemplo); if (dist > 0) { parar = false; for (j = 0; j < nvec && !parar; j++) { if (dist < minDistancias[j]) { parar = true; for (l = nvec - 1; l >= j+1; l--) { minDistancias[l] = minDistancias[l - 1]; vecinosCercanos[l] = vecinosCercanos[l - 1]; } minDistancias[j] = dist; vecinosCercanos[j] = i; } } } } for (j=0; j<nClases; j++) { votos[j] = 0; } for (j=0; j<nvec; j++) { if (vecinosCercanos[j] >= 0) votos[clases[vecinosCercanos[j]]] ++; } votada = 0; votaciones = votos[0]; for (j=1; j<nClases; j++) { if (votaciones < votos[j]) { votaciones = votos[j]; votada = j; } } nVotos.entero = votaciones; return votada; } //end-method /** * Executes KNN * * @param nvec Number of neighbors * @param conj Reference to the training set * @param clases Output attribute of each instance * @param ejemplo New instance to classifiy * @param nClases Number of classes of the problem * @param vecinos Neighbors of the new instance * * @return Class of the new instance */ public static int evaluacionKNN2 (int nvec, double conj[][], int clases[], double ejemplo[], int nClases, int vecinos[]) { int i, j, l; boolean parar = false; int vecinosCercanos[]; double minDistancias[]; int votos[]; double dist; int votada, votaciones; nClases = Attributes.getOutputAttribute(0).getNumNominalValues(); if (nvec > conj.length) nvec = conj.length; votos = new int[nClases]; vecinosCercanos = new int[nvec]; minDistancias = new double[nvec]; for (i=0; i<nvec; i++) { vecinosCercanos[i] = -1; minDistancias[i] = Double.POSITIVE_INFINITY; } for (i=0; i<conj.length; i++) { dist = distancia(conj[i], ejemplo); if (dist > 0) { parar = false; for (j = 0; j < nvec && !parar; j++) { if (dist < minDistancias[j]) { parar = true; for (l = nvec - 1; l >= j+1; l--) { minDistancias[l] = minDistancias[l - 1]; vecinosCercanos[l] = vecinosCercanos[l - 1]; } minDistancias[j] = dist; vecinosCercanos[j] = i; } } } } for (j=0; j<nClases; j++) { votos[j] = 0; } for (j=0; j<nvec; j++) { if (vecinosCercanos[j] >= 0) votos[clases[vecinosCercanos[j]]] ++; } votada = 0; votaciones = votos[0]; for (j=1; j<nClases; j++) { if (votaciones < votos[j]) { votaciones = votos[j]; votada = j; } } for (i=0; i<vecinosCercanos.length; i++) vecinos[i] = vecinosCercanos[i]; return votada; } //end-method /** * Calculates the Euclidean distance between two instances * * @param ej1 First instance * @param ej2 Second instance * @return The Euclidean distance * */ public static double distancia (double ej1[], double ej2[]) { int i; double suma = 0; for (i=0; i<ej1.length; i++) { suma += (ej1[i]-ej2[i])*(ej1[i]-ej2[i]); } suma = Math.sqrt(suma); return suma; } //end-method /** * Calculates the unsquared Euclidean distance between two instances * * @param ej1 First instance * @param ej2 Second instance * @return The unsquared Euclidean distance * */ public static double distancia2 (double ej1[], double ej2[]) { int i; double suma = 0; for (i=0; i<ej1.length; i++) { suma += (ej1[i]-ej2[i])*(ej1[i]-ej2[i]); } return suma; } //end-method /*****************************************************************************/ /*Adapted Methods for HVDM distance*/ /** * Executes KNN * * @param nvec Number of neighbors * @param conj Reference to the training set * @param real Reference to the training set (real valued) * @param nominal Reference to the training set (nominal valued) * @param nulos Reference to the training set (null values) * @param clases Output attribute of each instance * @param ejemplo New instance to classifiy * @param ejReal New instance to classifiy (real valued) * @param ejNominal New instance to classifiy (nominal valued) * @param ejNulos New instance to classifiy (null values) * @param nClases Number of classes of the problem * @param distance True= Euclidean distance; False= HVDM * * @return Class of the new instance */ public static int evaluacionKNN (int nvec, double conj[][], double real[][], int nominal[][], boolean nulos[][], int clases[], double ejemplo[], double ejReal[], int ejNominal[], boolean ejNulos[], int nClases, boolean distance) { return evaluacionKNN2 (nvec, conj, real, nominal, nulos, clases, ejemplo, ejReal, ejNominal, ejNulos, nClases, distance); } //end-method /** * Executes KNN * * @param nvec Number of neighbors * @param conj Reference to the training set * @param real Reference to the training set (real valued) * @param nominal Reference to the training set (nominal valued) * @param nulos Reference to the training set (null values) * @param clases Output attribute of each instance * @param ejemplo New instance to classifiy * @param ejReal New instance to classifiy (real valued) * @param ejNominal New instance to classifiy (nominal valued) * @param ejNulos New instance to classifiy (null values) * @param nClases Number of classes of the problem * @param distance True= Euclidean distance; False= HVDM * * @return Class of the new instance */ public static int evaluacionKNN2 (int nvec, double conj[][], double real[][], int nominal[][], boolean nulos[][], int clases[], double ejemplo[], double ejReal[], int ejNominal[], boolean ejNulos[], int nClases, boolean distance) { int i, j, l; boolean parar = false; int vecinosCercanos[]; double minDistancias[]; int votos[]; double dist; int votada, votaciones; if (nvec > conj.length) nvec = conj.length; votos = new int[nClases]; vecinosCercanos = new int[nvec]; minDistancias = new double[nvec]; for (i=0; i<nvec; i++) { vecinosCercanos[i] = -1; minDistancias[i] = Double.POSITIVE_INFINITY; } for (i=0; i<conj.length; i++) { dist = distancia(conj[i], real[i], nominal[i], nulos[i], ejemplo, ejReal, ejNominal, ejNulos, distance); if (dist > 0) { parar = false; for (j = 0; j < nvec && !parar; j++) { if (dist < minDistancias[j]) { parar = true; for (l = nvec - 1; l >= j+1; l--) { minDistancias[l] = minDistancias[l - 1]; vecinosCercanos[l] = vecinosCercanos[l - 1]; } minDistancias[j] = dist; vecinosCercanos[j] = i; } } } } for (j=0; j<nClases; j++) { votos[j] = 0; } for (j=0; j<nvec; j++) { if (vecinosCercanos[j] >= 0) votos[clases[vecinosCercanos[j]]] ++; } votada = 0; votaciones = votos[0]; for (j=1; j<nClases; j++) { if (votaciones < votos[j]) { votaciones = votos[j]; votada = j; } } return votada; } //end-method /** * Executes KNN * * @param nvec Number of neighbors * @param conj Reference to the training set * @param real Reference to the training set (real valued) * @param nominal Reference to the training set (nominal valued) * @param nulos Reference to the training set (null values) * @param clases Output attribute of each instance * @param ejemplo New instance to classifiy * @param ejReal New instance to classifiy (real valued) * @param ejNominal New instance to classifiy (nominal valued) * @param ejNulos New instance to classifiy (null values) * @param nClases Number of classes of the problem * @param distance True= Euclidean distance; False= HVDM * @param nVotos Maximun number of votes achieved * * @return Class of the new instance */ public static int evaluacionKNN2 (int nvec, double conj[][], double real[][], int nominal[][], boolean nulos[][], int clases[], double ejemplo[], double ejReal[], int ejNominal[], boolean ejNulos[], int nClases, boolean distance, Referencia nVotos) { int i, j, l; boolean parar = false; int vecinosCercanos[]; double minDistancias[]; int votos[]; double dist; int votada, votaciones; if (nvec > conj.length) nvec = conj.length; votos = new int[nClases]; vecinosCercanos = new int[nvec]; minDistancias = new double[nvec]; for (i=0; i<nvec; i++) { vecinosCercanos[i] = -1; minDistancias[i] = Double.POSITIVE_INFINITY; } for (i=0; i<conj.length; i++) { dist = distancia(conj[i], real[i], nominal[i], nulos[i], ejemplo, ejReal, ejNominal, ejNulos, distance); if (dist > 0) { parar = false; for (j = 0; j < nvec && !parar; j++) { if (dist < minDistancias[j]) { parar = true; for (l = nvec - 1; l >= j+1; l--) { minDistancias[l] = minDistancias[l - 1]; vecinosCercanos[l] = vecinosCercanos[l - 1]; } minDistancias[j] = dist; vecinosCercanos[j] = i; } } } } for (j=0; j<nClases; j++) { votos[j] = 0; } for (j=0; j<nvec; j++) { if (vecinosCercanos[j] >= 0) votos[clases[vecinosCercanos[j]]] ++; } votada = 0; votaciones = votos[0]; for (j=1; j<nClases; j++) { if (votaciones < votos[j]) { votaciones = votos[j]; votada = j; } } nVotos.entero = votaciones; return votada; } //end-method /** * Executes KNN * * @param nvec Number of neighbors * @param conj Reference to the training set * @param real Reference to the training set (real valued) * @param nominal Reference to the training set (nominal valued) * @param nulos Reference to the training set (null values) * @param clases Output attribute of each instance * @param ejemplo New instance to classifiy * @param ejReal New instance to classifiy (real valued) * @param ejNominal New instance to classifiy (nominal valued) * @param ejNulos New instance to classifiy (null values) * @param nClases Number of classes of the problem * @param distance True= Euclidean distance; False= HVDM * * @return The neighboors' classes. */ public static int[] evaluacionKNN3 (int nvec, double conj[][], double real[][], int nominal[][], boolean nulos[][], int clases[], double ejemplo[], double ejReal[], int ejNominal[], boolean ejNulos[], int nClases, boolean distance) { int i, j, l; boolean parar = false; int vecinosCercanos[]; int clasesVecinosCercanos[]; double minDistancias[]; double dist; if (nvec > conj.length) nvec = conj.length; vecinosCercanos = new int[nvec]; clasesVecinosCercanos= new int[nvec]; minDistancias = new double[nvec]; for (i=0; i<nvec; i++) { vecinosCercanos[i] = -1; clasesVecinosCercanos[i]=-1; minDistancias[i] = Double.POSITIVE_INFINITY; } for (i=0; i<conj.length; i++) { dist = distancia(conj[i], real[i], nominal[i], nulos[i], ejemplo, ejReal, ejNominal, ejNulos, distance); if (dist > 0) { parar = false; for (j = 0; j < nvec && !parar; j++) { if (dist < minDistancias[j]) { parar = true; for (l = nvec - 1; l >= j+1; l--) { minDistancias[l] = minDistancias[l - 1]; vecinosCercanos[l] = vecinosCercanos[l - 1]; } minDistancias[j] = dist; vecinosCercanos[j] = i; } } } } for (j=0; j<vecinosCercanos.length; j++) { if(vecinosCercanos[j]!=-1) clasesVecinosCercanos[j] =clases[vecinosCercanos[j]]; } return clasesVecinosCercanos; } //end-method /** * Executes KNN * * @param nvec Number of neighbors * @param conj Reference to the training set * @param real Reference to the training set (real valued) * @param nominal Reference to the training set (nominal valued) * @param nulos Reference to the training set (null values) * @param clases Output attribute of each instance * @param ejemplo New instance to classifiy * @param ejReal New instance to classifiy (real valued) * @param ejNominal New instance to classifiy (nominal valued) * @param ejNulos New instance to classifiy (null values) * @param nClases Number of classes of the problem * @param distance True= Euclidean distance; False= HVDM * @param vecinos Neighbors of the new instance * * @return Class of the new instance */ public static int evaluacionKNN2 (int nvec, double conj[][], double real[][], int nominal[][], boolean nulos[][], int clases[], double ejemplo[], double ejReal[], int ejNominal[], boolean ejNulos[], int nClases, boolean distance, int vecinos[]) { int i, j, l; boolean parar = false; int vecinosCercanos[]; double minDistancias[]; int votos[]; double dist; int votada, votaciones; nClases = Attributes.getOutputAttribute(0).getNumNominalValues(); if (nvec > conj.length) nvec = conj.length; votos = new int[nClases]; vecinosCercanos = new int[nvec]; minDistancias = new double[nvec]; for (i=0; i<nvec; i++) { vecinosCercanos[i] = -1; minDistancias[i] = Double.POSITIVE_INFINITY; } for (i=0; i<conj.length; i++) { dist = distancia(conj[i], real[i], nominal[i], nulos[i], ejemplo, ejReal, ejNominal, ejNulos, distance); if (dist > 0) { parar = false; for (j = 0; j < nvec && !parar; j++) { if (dist < minDistancias[j]) { parar = true; for (l = nvec - 1; l >= j+1; l--) { minDistancias[l] = minDistancias[l - 1]; vecinosCercanos[l] = vecinosCercanos[l - 1]; } minDistancias[j] = dist; vecinosCercanos[j] = i; } } } } for (j=0; j<nClases; j++) { votos[j] = 0; } for (j=0; j<nvec; j++) { if (vecinosCercanos[j] >= 0) votos[clases[vecinosCercanos[j]]] ++; } votada = 0; votaciones = votos[0]; for (j=1; j<nClases; j++) { if (votaciones < votos[j]) { votaciones = votos[j]; votada = j; } } for (i=0; i<vecinosCercanos.length; i++) vecinos[i] = vecinosCercanos[i]; return votada; } //end-method /** * Calculates the HVDM distance between two instances * * @param ej1 First instance * @param ej1Real First instance (Real valued) * @param ej1Nom First instance (Nominal valued) * @param ej1Nul First instance (Null values) * @param ej2 Second instance * @param ej2Real First instance (Real valued) * @param ej2Nom First instance (Nominal valued) * @param ej2Nul First instance (Null values) * @param Euc Use euclidean distance instead of HVDM * * @return The HVDM distance */ public static double distancia (double ej1[], double ej1Real[], int ej1Nom[], boolean ej1Nul[], double ej2[], double ej2Real[], int ej2Nom[], boolean ej2Nul[], boolean Euc) { int i; double suma = 0; if (Euc == true) { for (i=0; i<ej1.length; i++) { suma += (ej1[i]-ej2[i])*(ej1[i]-ej2[i]); } suma = Math.sqrt(suma); } else { for (i=0; i<ej1.length; i++) { if (ej1Nul[i] == true || ej2Nul[i] == true) { suma += 1; } else if (Attributes.getInputAttribute(i).getType() == Attribute.NOMINAL) { suma += Metodo.nominalDistance[i][ej1Nom[i]][ej2Nom[i]]; } else { if (Metodo.stdDev[i] != 0) suma += Math.abs(ej1Real[i]-ej2Real[i]) / (4*Metodo.stdDev[i]); } } suma = Math.sqrt(suma); } return suma; } //end-method /** * Calculates the unsquared HVDM distance between two instances * * @param ej1 First instance * @param ej1Real First instance (Real valued) * @param ej1Nom First instance (Nominal valued) * @param ej1Nul First instance (Null values) * @param ej2 Second instance * @param ej2Real First instance (Real valued) * @param ej2Nom First instance (Nominal valued) * @param ej2Nul First instance (Null values) * @param Euc Use euclidean distance instead of HVDM * * @return The unsquared HVDM distance */ public static double distancia2 (double ej1[], double ej1Real[], int ej1Nom[], boolean ej1Nul[], double ej2[], double ej2Real[], int ej2Nom[], boolean ej2Nul[], boolean Euc) { int i; double suma = 0; if (Euc == true) { for (i=0; i<ej1.length; i++) { suma += (ej1[i]-ej2[i])*(ej1[i]-ej2[i]); } } else { for (i=0; i<ej1.length; i++) { if (ej1Nul[i] == true || ej2Nul[i] == true) { suma += 1; } else if (Attributes.getInputAttribute(i).getType() == Attribute.NOMINAL) { suma += Metodo.nominalDistance[i][ej1Nom[i]][ej2Nom[i]]; } else { if (Metodo.stdDev[i] != 0) suma += Math.abs(ej1Real[i]-ej2Real[i]) / (4*Metodo.stdDev[i]); } } } return suma; } //end-method } //end-class