/* XXL: The eXtensible and fleXible Library for data processing
Copyright (C) 2000-2011 Prof. Dr. Bernhard Seeger
Head of the Database Research Group
Department of Mathematics and Computer Science
University of Marburg
Germany
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; If not, see <http://www.gnu.org/licenses/>.
http://code.google.com/p/xxl/
*/
package xxl.core.math.statistics.parametric.aggregates;
import xxl.core.functions.Function;
import xxl.core.functions.Functions;
import xxl.core.math.functions.AggregationFunction;
/**
* Estimates iteratively the fourth central moment of given {@link java.lang.Number numerical data} without any error control.
* In contrast to aggregation functions provided by {@link xxl.core.math.statistics.parametric.aggregates.ConfidenceAggregationFunction}
* objects of this class don't compute confidence intervals for processed data.
* The fourth central moment itself is computed iteratively, i.e. the data is successively consumed and
* the current fourth central moment
* is computed with the 'old' average and the new data element.
* <br>
* <p><b>Objects of this type are recommended for the usage with aggregator cursors!</b></p>
* <br>
* Generally, each aggregation function must support a function call of the following type:<br>
* <tt>agg_n = f (agg_n-1, next)</tt>, <br>
* where <tt>agg_n</tt> denotes the computed aggregation value after <tt>n</tt> steps,
* <tt>f</tt> the aggregation function,
* <tt>agg_n-1</tt> the computed aggregation value after <tt>n-1</tt> steps
* and <tt>next</tt> the next object to use for computation.
* An aggregation function delivers only <tt>null</tt> as aggregation result as long as the aggregation
* function has not yet fully initialized.
* Objects of this type have a two-step phase for initialization.
* <br>
* Also objects of this class are using internally stored information to obtain the standard deviation,
* objects of this type don't support on-line features.
* See {@link xxl.core.math.statistics.parametric.aggregates.OnlineAggregation OnlineAggregation} for further details about
* aggregation function using internally stored information supporting <tt>on-line aggregation</tt>.
*
* <br>
* Consider the following example:
* <code><pre>
* Aggregator aggregator = new Aggregator(
new DiscreteRandomNumber(new JavaDiscreteRandomWrapper(100), 50), // input-Cursor
new FourthCentralMomentEstimator() // aggregate function
);
* <\code><\pre>
* <br>
* A more detailed coverage of online aggregation is given in [HHW97]: P. Haas, J. Hellerstein,
* H. Wang. Online Aggregation. 1997.
*
* @see xxl.core.cursors.mappers.Aggregator
* @see xxl.core.functions.Function
* @see xxl.core.math.statistics.parametric.aggregates.StatefulStandardDeviation
*/
public class FourthCentralMomentEstimator extends AggregationFunction<Number,Number> {
/** internal average estimator */
protected Function<Number, Number> avg;
/** internal third moment estimator */
protected Function<Number, Number> mom3;
/** internal variance estimator */
protected Function<Number, Number> var;
/** internal counter */
protected long n;
/** internally stored value of the third central moment*/
private double m3;
/** internally stored value of the fourth central moment*/
private double m4;
/** internally stored value of the variance*/
private double v;
/** internally stored value of the average*/
private double a;
/** internal variable storing the next value*/
private double xn;
/** Constructs a new Object of type ForthCentralMoment. */
public FourthCentralMomentEstimator() {}
/** Two-figured function call for supporting aggregation by this function.
* Each aggregation function must support a function call like <tt>agg_n = f (agg_n-1, next)</tt>,
* where <tt>agg_n</tt> denotes the computed aggregation value after <tt>n</tt> steps, <tt>f</tt>
* the aggregation function, <tt>agg_n-1</tt> the computed aggregation value after <tt>n-1</tt> steps
* and <tt>next</tt> the next object to use for computation.
* This method delivers only <tt>null</tt> as aggregation result as long as the aggregation
* has not yet initialized.
* Objects of this type have a two-step phase for initialization.
*
* @param old result of the aggregation function in the previous computation step
* @param next next object used for computation
* @return aggregation value after n steps
*/
public Number invoke(Number old, Number next) {
if (next == null)
return old;
else {
if (old == null) {
avg = Functions.aggregateUnaryFunction(new StatefulAverage());
a = avg.invoke(next).doubleValue();
var = Functions.aggregateUnaryFunction(new StatefulVarianceEstimator());
v = var.invoke(next).doubleValue();
mom3 = Functions.aggregateUnaryFunction(new ThirdCentralMomentEstimator());
m3 = mom3.invoke(next).doubleValue();
n = 1;
m4 = 0.0;
} else {
xn = next.doubleValue();
n++;
a = avg.invoke(next).doubleValue();
m4 = (n - 2) * m4 + (4.0 * m3 * (a - xn)) / n;
m4 += (6.0 * v * Math.pow((a - xn), 2.0)) / ((double) n * (double) n);
double temp = (Math.pow(n, 2.0) - 3.0 * n + 3.0) / n;
temp *= (double) (n - 1) / (double) (n);
temp *= Math.pow((a - xn), 4.0) / (n);
m4 += temp;
m4 = m4 / (n - 1);
v = var.invoke(next).doubleValue();
m3 = mom3.invoke(next).doubleValue();
}
return new Double(m4);
}
}
}