package tr.gov.ulakbim.jDenetX.evaluation;
import tr.gov.ulakbim.jDenetX.AbstractMOAObject;
import tr.gov.ulakbim.jDenetX.cluster.Clustering;
import tr.gov.ulakbim.jDenetX.gui.visualization.DataPoint;
import java.util.ArrayList;
import java.util.HashMap;
/**
* @author jansen
*/
public abstract class MeasureCollection extends AbstractMOAObject {
private static final long serialVersionUID = 1L;
private String[] names;
private ArrayList<Double>[] values;
private ArrayList<Double>[] sortedValues;
private double[] minValue;
private double[] maxValue;
private double[] sumValues;
private boolean[] enabled;
private double time;
private HashMap<String, Integer> map;
private int numMeasures = 0;
@SuppressWarnings("unchecked")
public MeasureCollection() {
names = getNames();
numMeasures = names.length;
map = new HashMap<String, Integer>(numMeasures);
for (int i = 0; i < names.length; i++) {
map.put(names[i], i);
}
values = (ArrayList<Double>[]) new ArrayList[numMeasures];
sortedValues = (ArrayList<Double>[]) new ArrayList[numMeasures];
maxValue = new double[numMeasures];
minValue = new double[numMeasures];
sumValues = new double[numMeasures];
enabled = getDefaultEnabled();
time = 0;
for (int i = 0; i < numMeasures; i++) {
values[i] = new ArrayList<Double>();
sortedValues[i] = new ArrayList<Double>();
maxValue[i] = Double.MIN_VALUE;
minValue[i] = Double.MAX_VALUE;
sumValues[i] = 0.0;
}
}
protected abstract String[] getNames();
protected void addValue(int index, double value) {
if (Double.isNaN(value)) {
System.out.println("NaN for " + names[index]);
}
values[index].add(value);
sumValues[index] += value;
if (value < minValue[index]) minValue[index] = value;
if (value > maxValue[index]) maxValue[index] = value;
}
protected void addValue(String name, double value) {
if (Double.isNaN(value)) {
System.out.println("NaN for " + name);
}
if (map.containsKey(name)) {
addValue(map.get(name), value);
} else {
System.out.println(name + " is not a valid measure key, no value added");
}
}
public int getNumMeasures() {
return numMeasures;
}
public String getName(int index) {
return names[index];
}
public double getMaxValue(int index) {
return maxValue[index];
}
public double getMinValue(int index) {
return minValue[index];
}
public double getLastValue(int index) {
if (values[index].size() < 1) return Double.NaN;
return values[index].get(values[index].size() - 1);
}
public double getMean(int index) {
if (values[index].size() < 1) return Double.NaN;
return sumValues[index] / values[index].size();
}
private void updateSortedValues(int index) {
//naive implementation of insertion sort
for (int i = sortedValues[index].size(); i < values[index].size(); i++) {
double v = values[index].get(i);
int insertIndex = 0;
while (!sortedValues[index].isEmpty() && insertIndex < sortedValues[index].size() && v > sortedValues[index].get(insertIndex))
insertIndex++;
sortedValues[index].add(insertIndex, v);
}
// for (int i = 0; i < sortedValues[index].size(); i++) {
// System.out.print(sortedValues[index].get(i)+" ");
// }
// System.out.println();
}
public void clean(int index) {
sortedValues[index].clear();
}
public double getMedian(int index) {
updateSortedValues(index);
int size = sortedValues[index].size();
if (size > 0) {
if (size % 2 == 1)
return sortedValues[index].get((int) (size / 2));
else
return (sortedValues[index].get((size - 1) / 2) + sortedValues[index].get((size - 1) / 2 + 1)) / 2.0;
}
return Double.NaN;
}
public double getLowerQuartile(int index) {
updateSortedValues(index);
int size = sortedValues[index].size();
if (size > 11) {
return sortedValues[index].get(Math.round(size * 0.25f));
}
return Double.NaN;
}
public double getUpperQuartile(int index) {
updateSortedValues(index);
int size = sortedValues[index].size();
if (size > 11) {
return sortedValues[index].get(Math.round(size * 0.75f - 1));
}
return Double.NaN;
}
public int getNumberOfValues(int index) {
return values[index].size();
}
public double getValue(int index, int i) {
if (i >= values[index].size()) return Double.NaN;
return values[index].get(i);
}
public ArrayList<Double> getAllValues(int index) {
return values[index];
}
public void setEnabled(int index, boolean value) {
enabled[index] = value;
}
public boolean isEnabled(int index) {
return enabled[index];
}
public double getMeanRunningTime() {
if (values[0].size() != 0)
return (time / 10e6 / values[0].size());
else
return 0;
}
protected boolean[] getDefaultEnabled() {
boolean[] defaults = new boolean[numMeasures];
for (int i = 0; i < defaults.length; i++) {
defaults[i] = true;
}
return defaults;
}
protected abstract void evaluateClustering(Clustering clustering, Clustering trueClustering, ArrayList<DataPoint> points) throws Exception;
/*
* Evaluate Clustering
*
* return Time in milliseconds
*/
public double evaluateClusteringPerformance(Clustering clustering, Clustering trueClustering, ArrayList<DataPoint> points) throws Exception {
long start = System.nanoTime();
evaluateClustering(clustering, trueClustering, points);
long duration = System.nanoTime() - start;
time += duration;
duration /= 10e6;
return duration;
}
public void getDescription(StringBuilder sb, int indent) {
}
// @Deprecated
// //we only use this now for batch runs to make import / export easier
// //we need to delete it asap
// public void setTime(double time){
//
// }
}