All Downloads are FREE. Search and download functionalities are using the official Maven repository.

gov.sandia.cognition.statistics.distribution.InverseGammaDistribution Maven / Gradle / Ivy

There is a newer version: 4.0.1
Show newest version
/*
 * File:                InverseGammaDistribution.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.MathUtil;
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.UnivariateProbabilityDensityFunction;
import gov.sandia.cognition.statistics.SmoothCumulativeDistributionFunction;
import java.util.ArrayList;
import java.util.Random;

/**
 * Defines an inverse-gamma distribution.  That is, if X is drawn from IG(a,b),
 * then 1/X follows a Gamma(a,1.0/b) distribution.
 * @author Kevin R. Dixon
 * @since 3.0
 */
@PublicationReference(
    author="Wikipedia",
    title="Inverse-gamma distribution",
    type=PublicationType.WebPage,
    year=2010,
    url="http://en.wikipedia.org/wiki/Inverse-gamma_distribution"
)
public class InverseGammaDistribution 
    extends AbstractClosedFormSmoothUnivariateDistribution
{

    /**
     * Default shape, {@value}.
     */
    public static final double DEFAULT_SHAPE = 3.0;

    /**
     * Default scale, {@value}.
     */
    public static final double DEFAULT_SCALE = 1.0;

    /**
     * Shape parameter, must be greater than zero.
     */
    protected double shape;

    /**
     * Scale parameter, must be greater than zero.
     */
    protected double scale;

    /** 
     * Creates a new instance of InverseGammaDistribution 
     */
    public InverseGammaDistribution()
    {
        this( DEFAULT_SHAPE, DEFAULT_SCALE );
    }

    /**
     * Creates a new instance of InverseGammaDistribution
     * @param shape
     * Shape parameter, must be greater than zero.
     * @param scale
     * Scale parameter, must be greater than zero.
     */
    public InverseGammaDistribution(
        final double shape,
        final double scale)
    {
        this.shape = shape;
        this.scale = scale;
    }

    /**
     * Copy constructor
     * @param other
     * InverseGammaDistribution to copy
     */
    public InverseGammaDistribution(
        final InverseGammaDistribution other )
    {
        this( other.getShape(), other.getScale() );
    }

    @Override
    public InverseGammaDistribution clone()
    {
        return (InverseGammaDistribution) 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 the scale to set
     * 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 sampleAsDouble(
        final Random random)
    {
        final double g = GammaDistribution.sampleAsDouble(
            this.shape, 1.0 / this.scale, random);
        return 1.0 / g;
    }
    
    @Override
    public void sampleInto(
        final Random random,
        final double[] output,
        final int start,
        final int length)
    {
        // Sample the requested number of gammas.
        GammaDistribution.sampleInto(this.shape, 1.0 / this.scale, 
            random, output, start, length);
        
        // Now invert the gammas.
        final int end = start + length;
        for (int i = start; i < end; i++)
        {
            output[i] = 1.0 / output[i];
        }
    }
    
    @Override
    public Vector convertToVector()
    {
        return VectorFactory.getDefault().copyValues( this.shape, this.scale );
    }

    @Override
    public void convertFromVector(
        Vector parameters)
    {
        parameters.assertDimensionalityEquals(2);
        this.setShape( parameters.getElement(0) );
        this.setScale( parameters.getElement(1) );
    }

    @Override
    public double getMeanAsDouble()
    {
        if( this.shape > 1.0 )
        {
            return this.scale / (this.shape - 1.0);
        }
        else
        {
            throw new IllegalArgumentException(
                "Shape must be > 1.0" );
        }
    }

    @Override
    public double getVariance()
    {
        if( this.shape > 2.0 )
        {
            final double am1 = this.shape - 1.0;
            final double am2 = this.shape - 2.0;
            return this.scale*this.scale / (am1*am1*am2);
        }
        else
        {
            throw new IllegalArgumentException(
                "Shape must be > 2.0" );
        }
    }

    @Override
    public InverseGammaDistribution.CDF getCDF()
    {
        return new InverseGammaDistribution.CDF( this );
    }

    @Override
    public InverseGammaDistribution.PDF getProbabilityFunction()
    {
        return new InverseGammaDistribution.PDF( this );
    }

    @Override
    public String toString()
    {
        return "Shape = " + this.getShape() + ", Scale = " + this.getScale();
    }

    @Override
    public Double getMinSupport()
    {
        return 0.0;
    }

    @Override
    public Double getMaxSupport()
    {
        return Double.POSITIVE_INFINITY;
    }

    /**
     * CDF of the inverseRootFinder-gamma distribution.
     */
    public static class CDF
        extends InverseGammaDistribution
        implements SmoothCumulativeDistributionFunction
    {

        /**
         * Default constructor
         */
        public CDF()
        {
            super();
        }

        /**
         * Creates a new instance of InverseGammaDistribution
         * @param shape
         * Shape parameter, must be greater than zero.
         * @param scale
         * Scale parameter, must be greater than zero.
         */
        public CDF(
            final double shape,
            final double scale)
        {
            super( shape, scale );
        }

        /**
         * Copy constructor
         * @param other
         * InverseGammaDistribution to copy
         */
        public CDF(
            final InverseGammaDistribution other )
        {
            super( other );
        }

        @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)
        {
            if( input > 0.0 )
            {
                return 1.0-GammaDistribution.CDF.evaluate(1.0/input, shape, 1.0/scale);
            }
            else
            {
                return 0.0;
            }
        }

        @Override
        public InverseGammaDistribution.CDF getCDF()
        {
            return this;
        }

        @Override
        public InverseGammaDistribution.PDF getDerivative()
        {
            return this.getProbabilityFunction();
        }

        @Override
        public Double differentiate(
            final Double input)
        {
            return this.getDerivative().evaluate(input);
        }

    }

    /**
     * PDF of the inverseRootFinder-Gamma distribution.
     */
    public static class PDF
        extends InverseGammaDistribution
        implements UnivariateProbabilityDensityFunction
    {

        /**
         * Default constructor
         */
        public PDF()
        {
            super();
        }

        /**
         * Creates a new instance of InverseGammaDistribution
         * @param shape
         * Shape parameter, must be greater than zero.
         * @param scale
         * Scale parameter, must be greater than zero.
         */
        public PDF(
            final double shape,
            final double scale)
        {
            super( shape, scale );
        }

        /**
         * Copy constructor
         * @param other
         * InverseGammaDistribution to copy
         */
        public PDF(
            final InverseGammaDistribution other )
        {
            super( other );
        }

        @Override
        public InverseGammaDistribution.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 > 0.0 )
            {
                double logSum = 0.0;
                logSum += this.shape * Math.log(this.scale);
                logSum -= MathUtil.logGammaFunction( this.shape );
                logSum -= (this.shape+1.0) * Math.log(input);
                logSum -= this.scale / input;
                return logSum;
            }
            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));
        }

    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy