package com.yahoo.labs.samoa.moa.evaluation; /* * #%L * SAMOA * %% * Copyright (C) 2010 RWTH Aachen University, Germany * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * #L% */ import java.util.ArrayList; import java.util.HashMap; import com.yahoo.labs.samoa.moa.AbstractMOAObject; import com.yahoo.labs.samoa.moa.cluster.Clustering; import com.yahoo.labs.samoa.moa.core.DataPoint; public abstract class MeasureCollection extends AbstractMOAObject{ private String[] names; private ArrayList<Double>[] values; private ArrayList<Double>[] sortedValues; private ArrayList<String> events; private double[] minValue; private double[] maxValue; private double[] sumValues; private boolean[] enabled; private boolean[] corrupted; private double time; private boolean debug = true; private MembershipMatrix mm = null; private HashMap<String, Integer> map; private int numMeasures = 0; 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]; corrupted = new boolean[numMeasures]; enabled = getDefaultEnabled(); time = 0; events = new ArrayList<String>(); 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; corrupted[i] = false; sumValues[i] = 0.0; } } protected abstract String[] getNames(); public void addValue(int index, double value){ if(Double.isNaN(value)){ if(debug) System.out.println("NaN for "+names[index]); corrupted[index] = true; } if(value < 0){ if(debug) System.out.println("Negative value 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(map.containsKey(name)){ addValue(map.get(name),value); } else{ System.out.println(name+" is not a valid measure key, no value added"); } } //add an empty entry e.g. if evaluation crashed internally public void addEmptyValue(int index){ values[index].add(Double.NaN); corrupted[index] = true; } 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(corrupted[index] || 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/10e5/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/=10e5; return duration; } public void getDescription(StringBuilder sb, int indent) { } public void addEventType(String type){ events.add(type); } public String getEventType(int index){ if(index < events.size()) return events.get(index); else return null; } }