The Univariate interface now contains getWindow and setWindow in

addition to a constant which signifies an "infinite" window.  Windowing
has been added to all three Univariate implementations:

* UnivariateImpl - If the window is not infinite, we keep track of
0..n elements and discount the contribution of the discarded element when
our "window" is moved.  If the window is infinite no extra storage is used
beyond an empty ContractableDoubleArray.

- In the following two implementations, the window size can be changed at anytime.

* ListStoreUnivariateImpl - If the window is not infinite, this
implementation only takes into account the last n elements of the List.

* StoreUnivariateImpl - Uses an internal ContractableDoubleArray, window size
can be changed at any time.


git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/math/trunk@140835 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Tim O'Brien 2003-05-16 05:23:29 +00:00
parent 0700b0f482
commit 71dfdabde1
6 changed files with 225 additions and 18 deletions

View File

@ -120,4 +120,14 @@ public interface DoubleArray {
* @param i number of elements to discard from the front of the array.
*/
public abstract void discardFrontElements(int i);
/**
* Returns the minimum value stored in this array
*/
public abstract double getMin();
/**
* Returns the maximum value stored in this array
*/
public abstract double getMax();
}

View File

@ -359,4 +359,34 @@ public class ExpandableDoubleArray implements Serializable, DoubleArray {
return elementArray;
}
/* (non-Javadoc)
* @see org.apache.commons.math.DoubleArray#getMax()
*/
public double getMax() {
double max = internalArray[startIndex];
for( int i = startIndex + 1; i < numElements; i++) {
if( internalArray[i] > max ) {
max = internalArray[i];
}
}
return max;
}
/* (non-Javadoc)
* @see org.apache.commons.math.DoubleArray#getMin()
*/
public double getMin() {
double min = internalArray[startIndex];
for( int i = startIndex + 1; i < numElements; i++) {
if( internalArray[i] < min ) {
min = internalArray[i];
}
}
return min;
}
}

View File

@ -61,6 +61,10 @@ import java.util.List;
*/
public class ListUnivariateImpl extends AbstractStoreUnivariate {
// Holds the value of the windowSize, initial windowSize is the constant
// Univariate.INFINITE_WINDOW
private int windowSize = Univariate.INIFINTE_WINDOW;
// Holds a reference to a list - GENERICs are going to make
// out lives easier here as we could only accept List<Number>
List list;
@ -75,10 +79,23 @@ public class ListUnivariateImpl extends AbstractStoreUnivariate {
*/
public double[] getValues() {
double[] copiedArray = new double[list.size()];
// If we've got a windowSize, we might not care about the entire list.
List effectiveList = list;
// If the window size is not INIFINITE_WINDOW AND
// the current list is larger that the window size, we need to
// take into account only the last n elements of the list
// as definied by windowSize
if( windowSize != Univariate.INIFINTE_WINDOW &&
windowSize < list.size() ) {
effectiveList = list.subList( (list.size() - 1) - windowSize, (list.size()-1));
}
// Create an array to hold all values
double[] copiedArray = new double[effectiveList.size()];
int i = 0;
Iterator it = list.iterator();
Iterator it = effectiveList.iterator();
while( it.hasNext() ) {
Number n = (Number) it.next();
copiedArray[i] = n.doubleValue();
@ -92,15 +109,38 @@ public class ListUnivariateImpl extends AbstractStoreUnivariate {
* @see org.apache.commons.math.StoreUnivariate#getElement(int)
*/
public double getElement(int index) {
Number n = (Number) list.get(index);
return n.doubleValue();
double value = Double.NaN;
if( windowSize != Univariate.INIFINTE_WINDOW &&
windowSize < list.size() ) {
Number n = (Number) list.get( ( (list.size() - 1) - windowSize ) + index ) ;
value = n.doubleValue();
} else {
Number n = (Number) list.get(index);
value = n.doubleValue();
}
return value;
}
/* (non-Javadoc)
* @see org.apache.commons.math.Univariate#getN()
*/
public double getN() {
return list.size();
double N = 0.0;
if( windowSize != Univariate.INIFINTE_WINDOW ) {
if( list.size() > windowSize ) {
N = windowSize;
} else {
N = list.size();
}
} else {
N = list.size();
}
return N;
}
/* (non-Javadoc)
@ -117,4 +157,18 @@ public class ListUnivariateImpl extends AbstractStoreUnivariate {
list.clear();
}
/* (non-Javadoc)
* @see org.apache.commons.math.Univariate#getWindowSize()
*/
public int getWindowSize() {
return windowSize;
}
/* (non-Javadoc)
* @see org.apache.commons.math.Univariate#setWindowSize(int)
*/
public void setWindowSize(int windowSize) {
this.windowSize = windowSize;
}
}

View File

@ -58,10 +58,16 @@ package org.apache.commons.math;
*/
public class StoreUnivariateImpl extends AbstractStoreUnivariate {
ExpandableDoubleArray eDA;
// Use an internal double array
DoubleArray eDA;
// Store the windowSize
private int windowSize = Univariate.INIFINTE_WINDOW;
public StoreUnivariateImpl() {
eDA = new ExpandableDoubleArray();
// A contractable double array is used. memory is reclaimed when
// the storage of the array becomes too empty.
eDA = new ContractableDoubleArray();
}
/* (non-Javadoc)
@ -70,7 +76,7 @@ public class StoreUnivariateImpl extends AbstractStoreUnivariate {
public double[] getValues() {
double[] copiedArray = new double[ eDA.getNumElements() ];
System.arraycopy( eDA.getValues(), 0, copiedArray, 0, eDA.getNumElements());
System.arraycopy( eDA.getElements(), 0, copiedArray, 0, eDA.getNumElements());
return copiedArray;
}
@ -91,15 +97,48 @@ public class StoreUnivariateImpl extends AbstractStoreUnivariate {
/* (non-Javadoc)
* @see org.apache.commons.math.Univariate#addValue(double)
*/
public void addValue(double v) {
eDA.addElement( v );
public synchronized void addValue(double v) {
if( windowSize != Univariate.INIFINTE_WINDOW ) {
if( getN() == windowSize ) {
eDA.addElementRolling( v );
} else if( getN() < windowSize ) {
eDA.addElement(v);
} else {
throw new RuntimeException( "A window Univariate had more element than " +
"the windowSize. This is an inconsistent state.");
}
} else {
eDA.addElement(v);
}
}
/* (non-Javadoc)
* @see org.apache.commons.math.Univariate#clear()
*/
public void clear() {
public synchronized void clear() {
eDA.clear();
}
/* (non-Javadoc)
* @see org.apache.commons.math.Univariate#getWindowSize()
*/
public int getWindowSize() {
return windowSize;
}
/* (non-Javadoc)
* @see org.apache.commons.math.Univariate#setWindowSize(int)
*/
public synchronized void setWindowSize(int windowSize) {
this.windowSize = windowSize;
// We need to check to see if we need to discard elements
// from the front of the array. If the windowSize is less than
// the current number of elements.
if( windowSize < eDA.getNumElements() ) {
eDA.discardFrontElements( eDA.getNumElements() - windowSize);
}
}
}

View File

@ -61,7 +61,7 @@
*
* @author Phil Steitz
* @author <a href="mailto:tobrien@apache.org">Tim O'Brien</a>
* @version $Revision: 1.2 $ $Date: 2003/05/15 05:39:00 $
* @version $Revision: 1.3 $ $Date: 2003/05/16 05:23:29 $
*
*/
public interface Univariate {
@ -117,4 +117,26 @@ public interface Univariate {
/** Resets all sums to 0, resets min and max */
public abstract void clear();
/**
* This constant signals that a Univariate implementation
* takes into account the contributions of an infinite number of
* elements. In other words, if getWindow returns this
* constant, there is, in effect, no "window".
*/
public static final int INIFINTE_WINDOW = -1;
/**
* Univariate has the ability to return only measures for the
* last N elements added to the set of values. This function returns
*/
public abstract int getWindowSize();
/**
* Sets the window. windowSize controls the number of value
* which contribute to the values returned by Univariate.
* For example, a window value of 10 means that getMean()
* will return the mean of the last 10 values added.
*/
public abstract void setWindowSize(int windowSize);
}

View File

@ -64,11 +64,20 @@ import java.io.Serializable;
* to doubles by addValue().
*
* @author Phil Steitz
* @version $Revision: 1.2 $ $Date: 2003/05/15 06:33:19 $
* @version $Revision: 1.3 $ $Date: 2003/05/16 05:23:29 $
*
*/
public class UnivariateImpl implements Univariate, Serializable {
/** hold the window size **/
private int windowSize = Univariate.INIFINTE_WINDOW;
/** Just in case, the windowSize is not inifinite, we need to
* keep an array to remember values 0 to N
*/
private DoubleArray doubleArray =
new ContractableDoubleArray();
/** running sum of values that have been added */
private double sum = 0.0;
@ -140,11 +149,40 @@ public class UnivariateImpl implements Univariate, Serializable {
* @param v the value to be added
*/
private void insertValue(double v) {
n += 1.0;
if (v < min) min = v;
if (v > max) max = v;
sum += v;
sumsq += v*v;
if( windowSize != Univariate.INIFINTE_WINDOW ) {
if( windowSize == n ) {
double discarded = doubleArray.addElementRolling( v );
// Remove the influence of the discarded
sum -= discarded;
sumsq -= discarded * discarded;
// Include the influence of the new
// TODO: The next two lines seems rather expensive, but
// I don't see many alternatives.
min = doubleArray.getMin();
max = doubleArray.getMax();
sum += v;
sumsq += v*v;
} else {
doubleArray.addElement( v );
n += 1.0;
if (v < min) min = v;
if (v > max) max = v;
sum += v;
sumsq += v*v;
}
} else {
// If the windowSize is inifinite please don't take the time to
// worry about storing any values. We don't need to discard the
// influence of any single item.
n += 1.0;
if (v < min) min = v;
if (v > max) max = v;
sum += v;
sumsq += v*v;
}
}
/** Getter for property max.
@ -215,4 +253,18 @@ public class UnivariateImpl implements Univariate, Serializable {
this.max = Double.MIN_VALUE;
}
/* (non-Javadoc)
* @see org.apache.commons.math.Univariate#getWindowSize()
*/
public int getWindowSize() {
return windowSize;
}
/* (non-Javadoc)
* @see org.apache.commons.math.Univariate#setWindowSize(int)
*/
public void setWindowSize(int windowSize) {
this.windowSize = windowSize;
}
}