sim.util.media.chart.MinGapDataCuller Maven / Gradle / Ivy
Show all versions of mason Show documentation
/* Copyright 2006 by Sean Luke and George Mason University Licensed under the Academic Free License version 3.0 See the file "LICENSE" for more information */ package sim.util.media.chart; import sim.util.*; /** * This is meant as an on-line algorithm for keeping a constant number of data points * from an on-going time series. It only looks at the X values of the time series data points. * *
to do it. * * This works by finding the element that would leave the * smallest gap (if dropped), then repeat. This means I won't touch * the first and last element. **/ static public IntBag cullToSize(double[] xValues, int size, IntBag droppedIndices) { droppedIndices.clear(); int pointsToDrop = xValues.length-size; if(pointsToDrop<=0) return droppedIndices; if(xValues.length<=2) { //I shouldn't be in this situation. I'll just drop something and get out. for(int i=0;iSpecifically, this algorithm eliminates the point the leaves the smallest gap * (i.e. has the closest neighbors). The first and last data point are never touched. * *
In case of ties, it chooses the first. This is meant to make the older data sparse while keeping * more/most of the fresh data. * * * Few gaps change between removes (2 old are merged, 1 new is introduced; * 1. I could cache the gap sums * 2. I could use a heap (although the tie breaking might be off) * * *
For efficiency reasons, multiple points are dropped in one culling. * The suggested (default) amount of points dropped in one culling is 50%. * * * @author Gabriel Balan */ public class MinGapDataCuller implements DataCuller { int maxPointCount; int pointCountAfterCulling; IntBag reusableIntBag; public MinGapDataCuller(int maxPointCount) { this(maxPointCount, maxPointCount/2+1); } public MinGapDataCuller(int maxPointCount, int pointCountAfterCulling) { setMaxAndMinCounts(maxPointCount, pointCountAfterCulling); this.reusableIntBag = new IntBag(maxPointCount-pointCountAfterCulling+1); //+1 cause you need 1 over maxPointCount to trigger the culling } public boolean tooManyPoints(int currentPointCount) { return currentPointCount >maxPointCount; } void setMaxAndMinCounts(int maxPointCount, int pointCountAfterCulling) { this.maxPointCount = maxPointCount; this.pointCountAfterCulling = pointCountAfterCulling; } // O(maxPoints) static void sort(IntBag indices, int maxPoints) { boolean[] map = new boolean[maxPoints]; for(int i=0;i
sort = 1 ; i-- ) heapify(i); } Record extractMin() { if( heapsize == 0 ) return null; // remove the info Record result = heap[1-1]; heap[1-1] = heap[heapsize-1]; heap[1-1].heapPosition=1; heap[heapsize-1] = null; heapsize--; // rebuild heap if (heapsize > 1) {// no need to heapify if there's only zero or one element! heapify(1); //lets update the previous and next record. Record leftRecord = result.leftRecord; Record rightRecord = result.rightRecord; if(rightRecord!=null) { if(rightRecord.leftGap!=result.rightGap) throw new RuntimeException("BUG");//TODO delete these checks } if(leftRecord!=null) { if(leftRecord.rightGap!=result.leftGap) throw new RuntimeException("BUG");//TODO delete these checks //leftRecord.rightGap+=result.rightGap; leftRecord.setRightGap(result.key); leftRecord.rightRecord = result.rightRecord; heapify(leftRecord.heapPosition); } if(rightRecord!=null) { rightRecord.setLeftGap(result.key); rightRecord.leftRecord = result.leftRecord; heapify(rightRecord.heapPosition); } } return result; } void heapify(int i) { while(true) { int l = 2*i; int r = 2*i+1; int smallest; if( l <= heapsize && heap[l-1].compareTo(heap[i-1])<0) smallest = l; else smallest = i; if( r <= heapsize && heap[r-1].compareTo(heap[smallest-1]) < 0) smallest = r; if( smallest != i ) { // swap records Record tmp = heap[i-1]; heap[i-1] = heap[smallest-1]; heap[smallest-1] = tmp; heap[i-1].heapPosition=i; heap[smallest-1].heapPosition = smallest; // recursive call.... :) i = smallest; } else return; } } } }