com.ibm.og.util.Distributions.java Source code

Java tutorial

Introduction

Here is the source code for com.ibm.og.util.Distributions.java

Source

/* Copyright (c) IBM Corporation 2016. All Rights Reserved.
 * Project name: Object Generator
 * This project is licensed under the Apache License 2.0, see LICENSE.
 */

package com.ibm.og.util;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

import org.apache.commons.math3.distribution.ConstantRealDistribution;
import org.apache.commons.math3.distribution.IntegerDistribution;
import org.apache.commons.math3.distribution.LogNormalDistribution;
import org.apache.commons.math3.distribution.NormalDistribution;
import org.apache.commons.math3.distribution.PoissonDistribution;
import org.apache.commons.math3.distribution.RealDistribution;
import org.apache.commons.math3.distribution.UniformRealDistribution;

import com.google.common.math.DoubleMath;

/**
 * A utility class for creating distribution instances
 * 
 * @since 1.0
 */
public class Distributions {
    private static final double ERR = Math.pow(0.1, 6);

    private Distributions() {
    }

    /**
     * Creates a uniform distribution with a range of [average - spread, average + spread].
     * 
     * @param average the average value of this distribution
     * @param spread distance from the average
     * @return a uniform distribution instance
     * @throws IllegalArgumentException if average or spread are negative, or if average - spread is
     *         negative
     */
    public static Distribution uniform(final double average, final double spread) {
        checkArgument(average >= 0.0, "average must be >= 0.0 [%s]", average);
        checkArgument(spread >= 0.0, "spread must be >= 0.0 [%s]", spread);

        if (DoubleMath.fuzzyEquals(spread, 0.0, Distributions.ERR)) {
            return constant(average);
        }

        final double lower = average - spread;
        final double upper = average + spread;
        checkArgument(lower >= 0.0, "average - spread must be >= 0.0 [%s]", lower);
        final String s = String.format("UniformDistribution [average=%s, spread=%s]", average, spread);
        return new RealDistributionAdapter(new UniformRealDistribution(lower, upper), s);
    }

    /**
     * Creates a normal distribution with a rangge of [average - 3*spread, average + 3*spread].
     * 
     * @param average the center of this distribution
     * @param spread distance of one standard deviation
     * @return a normal distribution instance
     * @throws IllegalArgumentException if average or spread are negative, or if average - 3*spread is
     *         negative
     */
    public static Distribution normal(final double average, final double spread) {
        checkArgument(average >= 0.0, "average must be >= 0.0 [%s]", average);
        checkArgument(spread >= 0.0, "spread must be >= 0.0 [%s]", spread);

        if (DoubleMath.fuzzyEquals(spread, 0.0, Distributions.ERR)) {
            return constant(average);
        }

        final double min = average - (3 * spread);
        checkArgument(min >= 0.0, "three standard deviations must be >= 0.0 [%s]", min);
        final String s = String.format("NormalDistribution [average=%s, spread=%s]", average, spread);
        return new RealDistributionAdapter(new NormalDistribution(average, spread), s);
    }

    /**
     * Creates a lognormal distribution.
     * 
     * @param average the average
     * @param spread the spread
     * @return a lognormal distribution instance
     * @throws IllegalArgumentException if average or spread are negative, or if average - 3*spread is
     *         negative
     */
    public static Distribution lognormal(final double average, final double spread) {
        // FIXME configure lognormal distribution range correctly
        checkArgument(average >= 0.0, "average must be >= 0.0 [%s]", average);
        checkArgument(spread >= 0.0, "spread must be >= 0.0 [%s]", spread);

        if (DoubleMath.fuzzyEquals(spread, 0.0, Distributions.ERR)) {
            return constant(average);
        }

        final double min = average - (3 * spread);
        checkArgument(min >= 0.0, "three standard deviations must be >= 0.0 [%s]", min);
        final String s = String.format("LogNormalDistribution [average=%s, spread=%s]", average, spread);
        return new RealDistributionAdapter(new LogNormalDistribution(average, spread), s);
    }

    /**
     * Creates a poisson distribution.
     * 
     * @param average the average value generated by this distribution
     * @return a poisson distribution instance
     * @throws IllegalArgumentException if average is negative
     */
    public static Distribution poisson(final double average) {
        checkArgument(average >= 0.0, "average must be >= 0.0 [%s]", average);
        final String s = String.format("PoissonDistribution [average=%s]", average);
        return new IntegerDistributionAdapter(new PoissonDistribution(average), s);
    }

    private static Distribution constant(final double average) {
        checkArgument(average >= 0.0, "average must be >= 0.0 [%s]", average);
        final String s = String.format("ConstantDistribution [average=%s]", average);
        return new RealDistributionAdapter(new ConstantRealDistribution(average), s);
    }

    // adapt apache's RealDistribution interface to og's Distribution interface
    private static class RealDistributionAdapter implements Distribution {
        private final RealDistribution d;
        private final String stringRepresentation;

        public RealDistributionAdapter(final RealDistribution d, final String stringRepresentation) {
            this.d = checkNotNull(d);
            this.stringRepresentation = checkNotNull(stringRepresentation);
        }

        @Override
        public double getAverage() {
            return this.d.getNumericalMean();
        }

        @Override
        public double nextSample() {
            return this.d.sample();
        }

        @Override
        public String toString() {
            return this.stringRepresentation;
        }
    }

    // adapt apache's IntegerDistribution interface to og's Distribution interface
    private static class IntegerDistributionAdapter implements Distribution {
        private final IntegerDistribution d;
        private final String stringRepresentation;

        public IntegerDistributionAdapter(final IntegerDistribution d, final String stringRepresentation) {
            this.d = checkNotNull(d);
            this.stringRepresentation = checkNotNull(stringRepresentation);
        }

        @Override
        public double getAverage() {
            return this.d.getNumericalMean();
        }

        @Override
        public double nextSample() {
            return this.d.sample();
        }

        @Override
        public String toString() {
            return this.stringRepresentation;
        }
    }
}