eu.amidst.core.exponentialfamily.EF_InverseGamma.java Source code

Java tutorial

Introduction

Here is the source code for eu.amidst.core.exponentialfamily.EF_InverseGamma.java

Source

/*
 *
 *
 *    Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.
 *    See the NOTICE file distributed with this work for additional information regarding copyright ownership.
 *    The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use
 *    this file except in compliance with the License.  You may obtain a copy of the License at
 *
 *            http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software distributed under the License is
 *    distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and limitations under the License.
 *
 *
 */

package eu.amidst.core.exponentialfamily;

import eu.amidst.core.distribution.UnivariateDistribution;
import eu.amidst.core.utils.ArrayVector;
import eu.amidst.core.utils.Utils;
import eu.amidst.core.utils.Vector;
import eu.amidst.core.variables.Variable;
import org.apache.commons.math3.special.Gamma;

import java.util.ArrayList;
import java.util.Random;

/**
 *
 * This class extends the abstract class {@link EF_UnivariateDistribution} and defines an inverse Gamma distribution in exponential family canonical form.
 *
 * <p> For further details about how exponential family models are considered in this toolbox take a look at the following paper:
 *  <i>Representation, Inference and Learning of Bayesian Networks as Conjugate Exponential Family Models. Technical Report.</i>
 * (<a href="http://amidst.github.io/toolbox/docs/ce-BNs.pdf">pdf</a>) </p>
 */
public class EF_InverseGamma extends EF_UnivariateDistribution {

    public static final int LOGX = 0;
    public static final int INVX = 1;
    public static final double DELTA = 0.0001;

    /**
     * Creates a new EF_InverseGamma distribution for a given {@link Variable} object.
     * @param var1 a {@link Variable} object.
     */
    public EF_InverseGamma(Variable var1) {

        if (!var1.isInverseGammaParameter())
            throw new IllegalArgumentException("The variable is not Inverse Gamma parameter");

        this.parents = new ArrayList();

        this.var = var1;
        this.naturalParameters = this.createZeroNaturalParameters();
        this.momentParameters = this.createZeroMomentParameters();

        this.naturalParameters.set(0, -2.1); //alpha = 1.1
        this.naturalParameters.set(1, -1); //beta = 1
        this.setNaturalParameters(naturalParameters);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public double computeLogBaseMeasure(double val) {
        return 0;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public SufficientStatistics getSufficientStatistics(double val) {
        SufficientStatistics vec = this.createZeroSufficientStatistics();
        vec.set(LOGX, Math.log(val));
        vec.set(INVX, 1.0 / val);
        return vec;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public EF_UnivariateDistribution deepCopy(Variable var) {
        EF_InverseGamma copy = new EF_InverseGamma(var);
        copy.getNaturalParameters().copy(this.getNaturalParameters());
        copy.getMomentParameters().copy(this.getMomentParameters());

        return copy;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public EF_UnivariateDistribution randomInitialization(Random random) {
        double alpha = random.nextGaussian() * 2 + 1;
        double beta = random.nextDouble() * 1 + 0.1;

        this.getNaturalParameters().set(0, -alpha - 1);
        this.getNaturalParameters().set(1, -beta);
        this.fixNumericalInstability();
        this.updateMomentFromNaturalParameters();

        return this;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public <E extends UnivariateDistribution> E toUnivariateDistribution() {
        throw new UnsupportedOperationException("Inverse Gamma is not included yet in the Distributions package.");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void updateNaturalFromMomentParameters() {
        double m0 = this.getMomentParameters().get(0);
        double m1 = this.getMomentParameters().get(1);
        // Coordinate ascent until convergence
        double newalpha = 2.0, alpha = 0.0;
        double newbeta = 2.0, beta = 0.0;
        while (Math.abs(newalpha - alpha) > DELTA || Math.abs(newbeta - beta) > DELTA) {
            alpha = newalpha;
            beta = newbeta;
            newalpha = Utils.invDigamma(Math.log(beta) - m0);
            newbeta = newalpha / m1;
        }
        this.naturalParameters.set(0, newalpha);
        this.naturalParameters.set(1, newbeta);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void updateMomentFromNaturalParameters() {
        double alpha = -this.naturalParameters.get(0) - 1;
        double beta = -this.naturalParameters.get(1);
        this.momentParameters.set(0, Math.log(beta) - Gamma.digamma(alpha));
        this.momentParameters.set(1, alpha / beta);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int sizeOfSufficientStatistics() {
        return 2;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public double computeLogNormalizer() {
        double alpha = -this.naturalParameters.get(0) - 1;
        double beta = -this.naturalParameters.get(1);
        return Gamma.logGamma(alpha) - alpha * Math.log(beta);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Vector createZeroVector() {
        return new ArrayVector(2);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Vector getExpectedParameters() {
        //if ((-this.naturalParameters.get(0)-2)<=0){
        //    throw new UnsupportedOperationException("The expected value is negative, so we do not have a valid inverse gamma distributions ");
        //}
        Vector vec = new ArrayVector(1);
        vec.set(0, -this.naturalParameters.get(1) / (-this.naturalParameters.get(0) - 1));
        return vec;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void fixNumericalInstability() {

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public SufficientStatistics createInitSufficientStatistics() {

        ArrayVector vector = new ArrayVector(this.sizeOfSufficientStatistics());

        double alpha = 1.0;
        double beta = 1.0;
        vector.set(0, Math.log(beta) - Gamma.digamma(alpha));
        vector.set(1, alpha / beta);

        return vector;
    }

}