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
*
*/
}