gov.sandia.cognition.statistics.distribution.ParetoDistribution Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cognitive-foundry Show documentation
Show all versions of cognitive-foundry Show documentation
A single jar with all the Cognitive Foundry components.
/*
* File: ParetoDistribution.java
* Authors: Kevin R. Dixon
* Company: Sandia National Laboratories
* Project: Cognitive Foundry
*
* Copyright Mar 10, 2010, Sandia Corporation.
* Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
* license for use of this work by or on behalf of the U.S. Government.
* Export of this program may require a license from the United States
* Government. See CopyrightHistory.txt for complete details.
*
*/
package gov.sandia.cognition.statistics.distribution;
import gov.sandia.cognition.annotation.PublicationReference;
import gov.sandia.cognition.annotation.PublicationType;
import gov.sandia.cognition.math.matrix.Vector;
import gov.sandia.cognition.math.matrix.VectorFactory;
import gov.sandia.cognition.statistics.AbstractClosedFormSmoothUnivariateDistribution;
import gov.sandia.cognition.statistics.InvertibleCumulativeDistributionFunction;
import gov.sandia.cognition.statistics.UnivariateProbabilityDensityFunction;
import gov.sandia.cognition.statistics.SmoothCumulativeDistributionFunction;
import java.util.ArrayList;
import java.util.Random;
/**
* This class describes the Pareto distribution, sometimes called the Bradford
* Distribution. The Pareto distribution tends to be used to model social
* phenomena, such as the distribution of wealth in a society, price returns of
* stocks, file sizes on a computer, etc. It encapsulates the notion that
* there are few large entities and many smaller ones (80 percent of the wealth
* is controlled by 20 percent of the population).
* @author Kevin R. Dixon
* @since 3.0
*/
@PublicationReference(
author="Wikipedia",
title="Normal distribution",
type=PublicationType.WebPage,
year=2010,
url="http://en.wikipedia.org/wiki/Pareto_distribution"
)
public class ParetoDistribution
extends AbstractClosedFormSmoothUnivariateDistribution
{
/**
* Default shape, {@value}.
*/
public static final double DEFAULT_SHAPE = 2.0;
/**
* Default scale, {@value}.
*/
public static final double DEFALUT_SCALE = 1.0;
/**
* Default shift, {@value}.
*/
public static final double DEFAULT_SHIFT = 0.0;
/**
* Scale parameter, must be greater than zero.
*/
protected double shape;
/**
* Scale parameter, must be greater than zero.
*/
protected double scale;
/**
* Amount to shift the distribution to the left.
*/
protected double shift;
/**
* Creates a new instance of ParetoDistribution
*/
public ParetoDistribution()
{
this( DEFAULT_SHAPE, DEFALUT_SCALE, DEFAULT_SHIFT );
}
/**
* Creates a new instance of ParetoDistribution
* @param shape
* Scale parameter, must be greater than zero.
* @param scale
* Scale parameter, must be greater than zero.
* @param shift
* Amount to shift the distribution to the left.
*/
public ParetoDistribution(
final double shape,
final double scale,
final double shift )
{
this.setShape(shape);
this.setScale(scale);
this.setShift(shift);
}
/**
* Copy constructor
* @param other
* ParetoDistribution to copy
*/
public ParetoDistribution(
final ParetoDistribution other )
{
this( other.getShape(), other.getScale(), other.getShift() );
}
@Override
public ParetoDistribution clone()
{
return (ParetoDistribution) super.clone();
}
/**
* Getter for shape
* @return
* Shape parameter, must be greater than zero.
*/
public double getShape()
{
return this.shape;
}
/**
* Setter for shape
* @param shape
* Shape parameter, must be greater than zero.
*/
public void setShape(
final double shape)
{
if( shape <= 0.0 )
{
throw new IllegalArgumentException(
"Shape must be > 0.0 " );
}
this.shape = shape;
}
/**
* Getter for scale.
* @return
* Scale parameter, must be greater than zero.
*/
public double getScale()
{
return this.scale;
}
/**
* Setter for scale
* @param scale
* Scale parameter, must be greater than zero.
*/
public void setScale(
final double scale)
{
if( scale <= 0.0 )
{
throw new IllegalArgumentException(
"Scale must be > 0.0 " );
}
this.scale = scale;
}
@Override
public double getMeanAsDouble()
{
if( this.shape > 1.0 )
{
return this.shape * this.scale / (this.shape-1.0) - this.shift;
}
else
{
throw new IllegalArgumentException(
"Mean is undefined when shape is <= 1.0" );
}
}
@Override
public double getVariance()
{
if( this.shape > 2.0 )
{
final double numerator = this.scale*this.scale * this.shape;
final double am1 = this.shape-1.0;
final double am2 = this.shape-2.0;
final double denominator = am1*am1*am2;
return numerator / denominator;
}
else
{
throw new IllegalArgumentException(
"Variance is undefined when shape is <= 2.0" );
}
}
@Override
public double sampleAsDouble(
final Random random)
{
final double exp = 1.0 / this.shape;
final double u = random.nextDouble();
return this.scale / Math.pow(u, exp) - this.shift;
}
@Override
public void sampleInto(
final Random random,
final double[] output,
final int start,
final int length)
{
final double exp = 1.0 / this.shape;
final int end = start + length;
for (int i = start; i < end; i++)
{
final double u = random.nextDouble();
output[i] = this.scale / Math.pow(u, exp) - this.shift;
}
}
@Override
public Vector convertToVector()
{
return VectorFactory.getDefault().copyValues(
this.shape, this.scale, this.shift );
}
@Override
public void convertFromVector(
Vector parameters)
{
parameters.assertDimensionalityEquals(3);
this.setShape( parameters.getElement(0) );
this.setScale( parameters.getElement(1) );
this.setShift( parameters.getElement(2) );
}
@Override
public ParetoDistribution.PDF getProbabilityFunction()
{
return new ParetoDistribution.PDF( this );
}
@Override
public ParetoDistribution.CDF getCDF()
{
return new ParetoDistribution.CDF( this );
}
@Override
public Double getMinSupport()
{
return this.scale - this.shift;
}
@Override
public Double getMaxSupport()
{
return Double.POSITIVE_INFINITY;
}
@Override
public String toString()
{
return "Shape = " + this.getShape() + ", Scale = " + this.getScale() + ", Shift = " + this.getShift();
}
/**
* Getter for shift.
* @return
* Amount to shift the distribution to the left.
*/
double getShift()
{
return this.shift;
}
/**
* Setter for shift.
* @param shift
* Amount to shift the distribution to the left.
*/
public void setShift(
final double shift)
{
this.shift = shift;
}
/**
* CDF of the Pareto Distribution.
*/
public static class CDF
extends ParetoDistribution
implements SmoothCumulativeDistributionFunction,
InvertibleCumulativeDistributionFunction
{
/**
* Creates a new instance of CDF
*/
public CDF()
{
super();
}
/**
* Creates a new instance of CDF
* @param shape
* Scale parameter, must be greater than zero.
* @param scale
* Scale parameter, must be greater than zero.
* @param shift
* Amount to shift the distribution to the left.
*/
public CDF(
final double shape,
final double scale,
final double shift )
{
super( shape, scale, shift );
}
/**
* Copy constructor
* @param other
* ParetoDistribution to copy
*/
public CDF(
final ParetoDistribution other )
{
super( other );
}
@Override
public Double evaluate(
Double input)
{
return this.evaluate(input.doubleValue());
}
@Override
public double evaluateAsDouble(
final Double input)
{
return this.evaluate(input.doubleValue());
}
@Override
public double evaluate(
double input)
{
if( (input+this.shift) > this.scale )
{
return 1.0 - Math.pow( this.scale/(input+this.shift), this.shape);
}
else
{
return 0.0;
}
}
@Override
public ParetoDistribution.CDF getCDF()
{
return this;
}
@Override
public ParetoDistribution.PDF getDerivative()
{
return this.getProbabilityFunction();
}
@Override
public Double differentiate(
final Double input)
{
return this.getDerivative().evaluate(input);
}
@Override
public Double inverse(
final double probability)
{
if( probability <= 0.0 )
{
return this.getMinSupport();
}
else if( probability >= 1.0 )
{
return this.getMaxSupport();
}
else
{
return this.scale / Math.pow(1.0-probability, 1.0/this.shape)-this.shift;
}
}
}
/**
* PDF of the ParetoDistribution
*/
public static class PDF
extends ParetoDistribution
implements UnivariateProbabilityDensityFunction
{
/**
* Creates a new instance of PDF
*/
public PDF()
{
super();
}
/**
* Creates a new instance of PDF
* @param shape
* Scale parameter, must be greater than zero.
* @param scale
* Scale parameter, must be greater than zero.
* @param shift
* Amount to shift the distribution to the left.
*/
public PDF(
final double shape,
final double scale,
final double shift )
{
super( shape, scale, shift );
}
/**
* Copy constructor
* @param other
* ParetoDistribution to copy
*/
public PDF(
final ParetoDistribution other )
{
super( other );
}
@Override
public ParetoDistribution.PDF getProbabilityFunction()
{
return this;
}
@Override
public double logEvaluate(
final Double input)
{
return this.logEvaluate((double) input);
}
@Override
public double logEvaluate(
final double input)
{
// if( input > this.scale )
if( (input+this.shift) > this.scale )
{
double numerator = Math.log(this.shape) + this.shape*Math.log(this.scale);
double denominator = (this.shape+1.0)*Math.log(input+this.shift);
return numerator - denominator;
}
else
{
return Math.log(0.0);
}
}
@Override
public Double evaluate(
final Double input)
{
return this.evaluate(input.doubleValue());
}
@Override
public double evaluateAsDouble(
final Double input)
{
return this.evaluate(input.doubleValue());
}
@Override
public double evaluate(
final double input)
{
return Math.exp(this.logEvaluate(input));
}
}
}