package weka.core.spectral_distance_functions; /** **/ import java.util.ArrayList; import java.util.Enumeration; import weka.core.EuclideanDistance; import weka.core.Instance; import weka.core.Instances; import weka.core.neighboursearch.PerformanceStats; public class LikelihoodRatioDistance extends EuclideanDistance{ private static final long serialVersionUID = 1L; public LikelihoodRatioDistance(){ super(); } public LikelihoodRatioDistance(Instances data) { super(data); } //Needs overriding to avoid cutoff check public double distance(Instance first, Instance second){ return distance(first, second, Double.POSITIVE_INFINITY, null, false); } public double distance(Instance first, Instance second, PerformanceStats stats) { //debug method pls remove after use return distance(first, second, Double.POSITIVE_INFINITY, stats, false); } /* ASSUMES THE CLASS INDEX IS THE LAST DATA FOR THE NORMALISATION. But dont do the normalisation here anyway. * Euclidean distance normalises to [0..1] based on the flag m_DontNormalize, but it does this in the calculation. More efficient to do this as a filter, otherwise you are repeatedly recalculating.Basic normalisation is implemented, but advised not to use it, so flag set by default to true. */ public double distance(Instance first, Instance second, double cutOffValue, PerformanceStats stats){ return distance(first,second,cutOffValue,stats,false); } public double distance(Instance first, Instance second, double cutOffValue, PerformanceStats stats, boolean print) { //Get the double arrays return distance(first,second,cutOffValue); } public double distance(Instance first, Instance second, double cutOffValue) { double[] f; double[] s; int fClass=first.classIndex(); if(fClass>=0) { f=new double[first.numAttributes()-1]; int count=0; for(int i=0;i<f.length+1;i++){ if(i!=fClass){ f[count]=first.value(i); count++; } } } else f=first.toDoubleArray(); int sClass=second.classIndex(); if(sClass>=0) { s=new double[second.numAttributes()-1]; int count=0; for(int i=0;i<s.length;i++){ if(i!=sClass){ s[count]=second.value(i); count++; } } } else s=second.toDoubleArray(); if(f.length!=s.length){ //Error here System.out.println("Error in distance calculation for Likelihhod ratio, unequal lengths, exiting program!"); System.exit(0); } return distance(f,s,cutOffValue); } /* Likelihood ratio distance * */ public double distance(double[] a,double[] b, double cutoff){ double dist=0; double n1,n2,n; n1=a[0]; for(int i=1;i<a.length;i++) n1+=a[i]; n2=b[0]; for(int i=1;i<b.length;i++) n2+=b[i]; n=n1+n2; for(int i=0;i<a.length;i++){ if(a[i]>0) dist+=(a[i]/n1)*Math.log((a[i]/n1)/((a[i]+b[i])/n)); if(b[i]>0) dist+=(b[i]/n2)*Math.log((b[i]/n2)/((a[i]+b[i])/n)); if(dist>cutoff) return Double.POSITIVE_INFINITY; } return dist; } public String toString() { return "Likelihood Ratio"; } public String globalInfo() { return "Likelihood Ratio"; } @Override protected double updateDistance(double currDist, double diff) { // TODO Auto-generated method stub return 0; } public String getRevision() { return null; } /* JML Implementation version * */ }