You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by lu...@apache.org on 2013/03/08 16:59:29 UTC

svn commit: r1454439 - in /commons/proper/math/trunk: ./ src/changes/ src/main/java/org/apache/commons/math3/distribution/ src/test/java/org/apache/commons/math3/distribution/

Author: luc
Date: Fri Mar  8 15:59:29 2013
New Revision: 1454439

URL: http://svn.apache.org/r1454439
Log:
Added discrete distributions.

Patch contributed by Piotr Wydrych.

JIRA: MATH-941

Added:
    commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/DiscreteDistribution.java   (with props)
    commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/DiscreteIntegerDistribution.java   (with props)
    commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/DiscreteRealDistribution.java   (with props)
    commons/proper/math/trunk/src/test/java/org/apache/commons/math3/distribution/DiscreteIntegerDistributionTest.java   (with props)
    commons/proper/math/trunk/src/test/java/org/apache/commons/math3/distribution/DiscreteRealDistributionTest.java   (with props)
Modified:
    commons/proper/math/trunk/pom.xml
    commons/proper/math/trunk/src/changes/changes.xml

Modified: commons/proper/math/trunk/pom.xml
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/pom.xml?rev=1454439&r1=1454438&r2=1454439&view=diff
==============================================================================
--- commons/proper/math/trunk/pom.xml (original)
+++ commons/proper/math/trunk/pom.xml Fri Mar  8 15:59:29 2013
@@ -280,6 +280,9 @@
       <name>Christian Winter</name>
     </contributor>
     <contributor>
+      <name>Piotr Wydrych</name>
+    </contributor>
+    <contributor>
       <name>Xiaogang Zhang</name>
     </contributor>
   </contributors>

Modified: commons/proper/math/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/changes/changes.xml?rev=1454439&r1=1454438&r2=1454439&view=diff
==============================================================================
--- commons/proper/math/trunk/src/changes/changes.xml (original)
+++ commons/proper/math/trunk/src/changes/changes.xml Fri Mar  8 15:59:29 2013
@@ -55,6 +55,9 @@ This is a minor release: It combines bug
   Changes to existing features were made in a backwards-compatible
   way such as to allow drop-in replacement of the v3.1[.1] JAR file.
 ">
+      <action dev="luc" type="add" issue="MATH-941" due-to="Piotr Wydrych" >
+        Added discrete distributions.
+      </action>
       <action dev="luc" type="fix" issue="MATH-940" due-to="Piotr Wydrych" >
         Fixed abstract test class naming that broke ant builds.
       </action>

Added: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/DiscreteDistribution.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/DiscreteDistribution.java?rev=1454439&view=auto
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/DiscreteDistribution.java (added)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/DiscreteDistribution.java Fri Mar  8 15:59:29 2013
@@ -0,0 +1,197 @@
+/*
+ * 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 org.apache.commons.math3.distribution;
+
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.math3.exception.MathArithmeticException;
+import org.apache.commons.math3.exception.MathIllegalArgumentException;
+import org.apache.commons.math3.exception.NotPositiveException;
+import org.apache.commons.math3.exception.NotStrictlyPositiveException;
+import org.apache.commons.math3.exception.util.LocalizedFormats;
+import org.apache.commons.math3.random.RandomGenerator;
+import org.apache.commons.math3.random.Well19937c;
+import org.apache.commons.math3.util.MathArrays;
+import org.apache.commons.math3.util.Pair;
+
+/**
+ * Generic implementation of the discrete distribution.
+ *
+ * @param <T> type of the random variable.
+ * @see <a href="http://en.wikipedia.org/wiki/Probability_distribution#Discrete_probability_distribution">Discrete probability distribution (Wikipedia)</a>
+ * @see <a href="http://mathworld.wolfram.com/DiscreteDistribution.html">Discrete Distribution (MathWorld)</a>
+ * @version $Id: DiscreteDistribution.java 169 2013-03-08 09:02:38Z wydrych $
+ */
+public class DiscreteDistribution<T> {
+
+    /**
+     * RNG instance used to generate samples from the distribution.
+     */
+    protected final RandomGenerator random;
+    /**
+     * List of random variable values.
+     */
+    private final List<T> singletons;
+    /**
+     * Normalized array of probabilities of respective random variable values.
+     */
+    private final double[] probabilities;
+
+    /**
+     * Create a discrete distribution using the given probability mass function
+     * definition.
+     *
+     * @param samples definition of probability mass function in the format of
+     * list of pairs.
+     * @throws NotPositiveException if probability of at least one value is
+     * negative.
+     * @throws MathArithmeticException if the probabilities sum to zero.
+     * @throws MathIllegalArgumentException if probability of at least one value
+     * is infinite.
+     */
+    public DiscreteDistribution(final List<Pair<T, Double>> samples)
+        throws NotPositiveException, MathArithmeticException, MathIllegalArgumentException {
+        this(new Well19937c(), samples);
+    }
+
+    /**
+     * Create a discrete distribution using the given random number generator
+     * and probability mass function definition.
+     *
+     * @param rng random number generator.
+     * @param samples definition of probability mass function in the format of
+     * list of pairs.
+     * @throws NotPositiveException if probability of at least one value is
+     * negative.
+     * @throws MathArithmeticException if the probabilities sum to zero.
+     * @throws MathIllegalArgumentException if probability of at least one value
+     * is infinite.
+     */
+    public DiscreteDistribution(final RandomGenerator rng, final List<Pair<T, Double>> samples)
+        throws NotPositiveException, MathArithmeticException, MathIllegalArgumentException {
+        random = rng;
+
+        singletons = new ArrayList<T>(samples.size());
+        final double[] probs = new double[samples.size()];
+
+        for (int i = 0; i < samples.size(); i++) {
+            final Pair<T, Double> sample = samples.get(i);
+            singletons.add(sample.getKey());
+            if (sample.getValue() < 0) {
+                throw new NotPositiveException(sample.getValue());
+            }
+            probs[i] = sample.getValue();
+        }
+
+        probabilities = MathArrays.normalizeArray(probs, 1.0);
+    }
+
+    /**
+     * Reseed the random generator used to generate samples.
+     *
+     * @param seed the new seed
+     */
+    public void reseedRandomGenerator(long seed) {
+        random.setSeed(seed);
+    }
+
+    /**
+     * For a random variable {@code X} whose values are distributed according to
+     * this distribution, this method returns {@code P(X = x)}. In other words,
+     * this method represents the probability mass function (PMF) for the
+     * distribution.
+     *
+     * @param x the point at which the PMF is evaluated
+     * @return the value of the probability mass function at {@code x}
+     */
+    double probability(final T x) {
+        double probability = 0;
+
+        for (int i = 0; i < probabilities.length; i++) {
+            if ((x == null && singletons.get(i) == null) ||
+                (x != null && x.equals(singletons.get(i)))) {
+                probability += probabilities[i];
+            }
+        }
+
+        return probability;
+    }
+
+    /**
+     * Return the definition of probability mass function in the format of list
+     * of pairs.
+     *
+     * @return definition of probability mass function.
+     */
+    public List<Pair<T, Double>> getSamples() {
+        final List<Pair<T, Double>> samples = new ArrayList<Pair<T, Double>>(probabilities.length);
+
+        for (int i = 0; i < probabilities.length; i++) {
+            samples.add(new Pair<T, Double>(singletons.get(i), probabilities[i]));
+        }
+
+        return samples;
+    }
+
+    /**
+     * Generate a random value sampled from this distribution.
+     *
+     * @return a random value.
+     */
+    public T sample() {
+        final double randomValue = random.nextDouble();
+        double sum = 0;
+
+        for (int i = 0; i < probabilities.length; i++) {
+            sum += probabilities[i];
+            if (randomValue < sum) {
+                return singletons.get(i);
+            }
+        }
+
+        /* This should never happen, but it ensures we will return a correct
+         * object in case the loop above has some floating point inequality
+         * problem on the final iteration. */
+        return singletons.get(singletons.size() - 1);
+    }
+
+    /**
+     * Generate a random sample from the distribution.
+     *
+     * @param sampleSize the number of random values to generate.
+     * @return an array representing the random sample.
+     * @throws NotStrictlyPositiveException if {@code sampleSize} is not
+     * positive.
+     */
+    public T[] sample(int sampleSize) throws NotStrictlyPositiveException {
+        if (sampleSize <= 0) {
+            throw new NotStrictlyPositiveException(LocalizedFormats.NUMBER_OF_SAMPLES,
+                    sampleSize);
+        }
+        @SuppressWarnings("unchecked")
+        final T[]out = (T[]) Array.newInstance(singletons.get(0).getClass(), sampleSize);
+
+        for (int i = 0; i < sampleSize; i++) {
+            out[i] = sample();
+        }
+
+        return out;
+
+    }
+
+}

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/DiscreteDistribution.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/DiscreteDistribution.java
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"

Added: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/DiscreteIntegerDistribution.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/DiscreteIntegerDistribution.java?rev=1454439&view=auto
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/DiscreteIntegerDistribution.java (added)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/DiscreteIntegerDistribution.java Fri Mar  8 15:59:29 2013
@@ -0,0 +1,209 @@
+/*
+ * 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 org.apache.commons.math3.distribution;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.math3.exception.DimensionMismatchException;
+import org.apache.commons.math3.exception.MathArithmeticException;
+import org.apache.commons.math3.exception.MathIllegalArgumentException;
+import org.apache.commons.math3.exception.NotPositiveException;
+import org.apache.commons.math3.random.RandomGenerator;
+import org.apache.commons.math3.random.Well19937c;
+import org.apache.commons.math3.util.Pair;
+
+/**
+ * Implementation of the integer-valued discrete distribution.
+ *
+ * Note: values with zero-probability are allowed but they do not extend the
+ * support.
+ *
+ * @see <a href="http://en.wikipedia.org/wiki/Probability_distribution#Discrete_probability_distribution">Discrete probability distribution (Wikipedia)</a>
+ * @see <a href="http://mathworld.wolfram.com/DiscreteDistribution.html">Discrete Distribution (MathWorld)</a>
+ * @version $Id: DiscreteIntegerDistribution.java 169 2013-03-08 09:02:38Z wydrych $
+ */
+public class DiscreteIntegerDistribution extends AbstractIntegerDistribution {
+
+    /** Serializable UID. */
+    private static final long serialVersionUID = 20130308L;
+
+    /**
+     * {@link DiscreteDistribution} instance (using the {@link Integer} wrapper)
+     * used to generate samples.
+     */
+    protected final DiscreteDistribution<Integer> innerDistribution;
+
+    /**
+     * Create a discrete distribution using the given probability mass function
+     * definition.
+     *
+     * @param singletons array of random variable values.
+     * @param probabilities array of probabilities.
+     * @throws DimensionMismatchException if
+     * {@code singletons.length != probabilities.length}
+     * @throws NotPositiveException if probability of at least one value is
+     * negative.
+     * @throws MathArithmeticException if the probabilities sum to zero.
+     * @throws MathIllegalArgumentException if probability of at least one value
+     * is infinite.
+     */
+    public DiscreteIntegerDistribution(final int[] singletons, final double[] probabilities)
+        throws DimensionMismatchException, NotPositiveException, MathArithmeticException, MathIllegalArgumentException {
+        this(new Well19937c(), singletons, probabilities);
+    }
+
+    /**
+     * Create a discrete distribution using the given random number generator
+     * and probability mass function definition.
+     *
+     * @param rng random number generator.
+     * @param singletons array of random variable values.
+     * @param probabilities array of probabilities.
+     * @throws DimensionMismatchException if
+     * {@code singletons.length != probabilities.length}
+     * @throws NotPositiveException if probability of at least one value is
+     * negative.
+     * @throws MathArithmeticException if the probabilities sum to zero.
+     * @throws MathIllegalArgumentException if probability of at least one value
+     * is infinite.
+     */
+    public DiscreteIntegerDistribution(final RandomGenerator rng,
+                                       final int[] singletons, final double[] probabilities)
+        throws DimensionMismatchException, NotPositiveException, MathArithmeticException, MathIllegalArgumentException {
+        super(rng);
+        if (singletons.length != probabilities.length) {
+            throw new DimensionMismatchException(probabilities.length, singletons.length);
+        }
+
+        final List<Pair<Integer, Double>> samples = new ArrayList<Pair<Integer, Double>>(singletons.length);
+
+        for (int i = 0; i < singletons.length; i++) {
+            samples.add(new Pair<Integer, Double>(singletons[i], probabilities[i]));
+        }
+
+        innerDistribution = new DiscreteDistribution<Integer>(rng, samples);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public double probability(final int x) {
+        return innerDistribution.probability(x);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public double cumulativeProbability(final int x) {
+        double probability = 0;
+
+        for (final Pair<Integer, Double> sample : innerDistribution.getSamples()) {
+            if (sample.getKey() <= x) {
+                probability += sample.getValue();
+            }
+        }
+
+        return probability;
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * @return {@code sum(singletons[i] * probabilities[i])}
+     */
+    public double getNumericalMean() {
+        double mean = 0;
+
+        for (final Pair<Integer, Double> sample : innerDistribution.getSamples()) {
+            mean += sample.getValue() * sample.getKey();
+        }
+
+        return mean;
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * @return {@code sum((singletons[i] - mean) ^ 2 * probabilities[i])}
+     */
+    public double getNumericalVariance() {
+        double mean = 0;
+        double meanOfSquares = 0;
+
+        for (final Pair<Integer, Double> sample : innerDistribution.getSamples()) {
+            mean += sample.getValue() * sample.getKey();
+            meanOfSquares += sample.getValue() * sample.getKey() * sample.getKey();
+        }
+
+        return meanOfSquares - mean * mean;
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * Returns the lowest value with non-zero probability.
+     *
+     * @return the lowest value with non-zero probability.
+     */
+    public int getSupportLowerBound() {
+        int min = Integer.MAX_VALUE;
+        for (final Pair<Integer, Double> sample : innerDistribution.getSamples()) {
+            if (sample.getKey() < min && sample.getValue() > 0) {
+                min = sample.getKey();
+            }
+        }
+
+        return min;
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * Returns the highest value with non-zero probability.
+     *
+     * @return the highest value with non-zero probability.
+     */
+    public int getSupportUpperBound() {
+        int max = Integer.MIN_VALUE;
+        for (final Pair<Integer, Double> sample : innerDistribution.getSamples()) {
+            if (sample.getKey() > max && sample.getValue() > 0) {
+                max = sample.getKey();
+            }
+        }
+
+        return max;
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * The support of this distribution is connected.
+     *
+     * @return {@code true}
+     */
+    public boolean isSupportConnected() {
+        return true;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int sample() {
+        return innerDistribution.sample();
+    }
+}

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/DiscreteIntegerDistribution.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/DiscreteIntegerDistribution.java
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"

Added: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/DiscreteRealDistribution.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/DiscreteRealDistribution.java?rev=1454439&view=auto
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/DiscreteRealDistribution.java (added)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/DiscreteRealDistribution.java Fri Mar  8 15:59:29 2013
@@ -0,0 +1,245 @@
+/*
+ * 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 org.apache.commons.math3.distribution;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.math3.exception.DimensionMismatchException;
+import org.apache.commons.math3.exception.MathArithmeticException;
+import org.apache.commons.math3.exception.MathIllegalArgumentException;
+import org.apache.commons.math3.exception.NotPositiveException;
+import org.apache.commons.math3.random.RandomGenerator;
+import org.apache.commons.math3.random.Well19937c;
+import org.apache.commons.math3.util.Pair;
+
+/**
+ * Implementation of the discrete distribution on the reals.
+ *
+ * Note: values with zero-probability are allowed but they do not extend the
+ * support.
+ *
+ * @see <a href="http://en.wikipedia.org/wiki/Probability_distribution#Discrete_probability_distribution">Discrete probability distribution (Wikipedia)</a>
+ * @see <a href="http://mathworld.wolfram.com/DiscreteDistribution.html">Discrete Distribution (MathWorld)</a>
+ * @version $Id: DiscreteRealDistribution.java 169 2013-03-08 09:02:38Z wydrych $
+ */
+public class DiscreteRealDistribution extends AbstractRealDistribution {
+
+    /** Serializable UID. */
+    private static final long serialVersionUID = 20130308L;
+
+    /**
+     * {@link DiscreteDistribution} instance (using the {@link Double} wrapper)
+     * used to generate samples.
+     */
+    protected final DiscreteDistribution<Double> innerDistribution;
+
+    /**
+     * Create a discrete distribution using the given probability mass function
+     * definition.
+     *
+     * @param singletons array of random variable values.
+     * @param probabilities array of probabilities.
+     * @throws DimensionMismatchException if
+     * {@code singletons.length != probabilities.length}
+     * @throws NotPositiveException if probability of at least one value is
+     * negative.
+     * @throws MathArithmeticException if the probabilities sum to zero.
+     * @throws MathIllegalArgumentException if probability of at least one value
+     * is infinite.
+     */
+    public DiscreteRealDistribution(final double[] singletons, final double[] probabilities)
+        throws DimensionMismatchException, NotPositiveException, MathArithmeticException, MathIllegalArgumentException {
+        this(new Well19937c(), singletons, probabilities);
+    }
+
+    /**
+     * Create a discrete distribution using the given random number generator
+     * and probability mass function definition.
+     *
+     * @param rng random number generator.
+     * @param singletons array of random variable values.
+     * @param probabilities array of probabilities.
+     * @throws DimensionMismatchException if
+     * {@code singletons.length != probabilities.length}
+     * @throws NotPositiveException if probability of at least one value is
+     * negative.
+     * @throws MathArithmeticException if the probabilities sum to zero.
+     * @throws MathIllegalArgumentException if probability of at least one value
+     * is infinite.
+     */
+    public DiscreteRealDistribution(final RandomGenerator rng,
+                                    final double[] singletons, final double[] probabilities)
+        throws DimensionMismatchException, NotPositiveException, MathArithmeticException, MathIllegalArgumentException {
+        super(rng);
+        if (singletons.length != probabilities.length) {
+            throw new DimensionMismatchException(probabilities.length, singletons.length);
+        }
+
+        List<Pair<Double, Double>> samples = new ArrayList<Pair<Double, Double>>(singletons.length);
+
+        for (int i = 0; i < singletons.length; i++) {
+            samples.add(new Pair<Double, Double>(singletons[i], probabilities[i]));
+        }
+
+        innerDistribution = new DiscreteDistribution<Double>(rng, samples);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public double probability(final double x) {
+        return innerDistribution.probability(x);
+    }
+
+    /**
+     * For a random variable {@code X} whose values are distributed according to
+     * this distribution, this method returns {@code P(X = x)}. In other words,
+     * this method represents the probability mass function (PMF) for the
+     * distribution.
+     *
+     * @param x the point at which the PMF is evaluated
+     * @return the value of the probability mass function at point {@code x}
+     */
+    public double density(final double x) {
+        return probability(x);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public double cumulativeProbability(final double x) {
+        double probability = 0;
+
+        for (final Pair<Double, Double> sample : innerDistribution.getSamples()) {
+            if (sample.getKey() <= x) {
+                probability += sample.getValue();
+            }
+        }
+
+        return probability;
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * @return {@code sum(singletons[i] * probabilities[i])}
+     */
+    public double getNumericalMean() {
+        double mean = 0;
+
+        for (final Pair<Double, Double> sample : innerDistribution.getSamples()) {
+            mean += sample.getValue() * sample.getKey();
+        }
+
+        return mean;
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * @return {@code sum((singletons[i] - mean) ^ 2 * probabilities[i])}
+     */
+    public double getNumericalVariance() {
+        double mean = 0;
+        double meanOfSquares = 0;
+
+        for (final Pair<Double, Double> sample : innerDistribution.getSamples()) {
+            mean += sample.getValue() * sample.getKey();
+            meanOfSquares += sample.getValue() * sample.getKey() * sample.getKey();
+        }
+
+        return meanOfSquares - mean * mean;
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * Returns the lowest value with non-zero probability.
+     *
+     * @return the lowest value with non-zero probability.
+     */
+    public double getSupportLowerBound() {
+        double min = Double.POSITIVE_INFINITY;
+        for (final Pair<Double, Double> sample : innerDistribution.getSamples()) {
+            if (sample.getKey() < min && sample.getValue() > 0) {
+                min = sample.getKey();
+            }
+        }
+
+        return min;
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * Returns the highest value with non-zero probability.
+     *
+     * @return the highest value with non-zero probability.
+     */
+    public double getSupportUpperBound() {
+        double max = Double.NEGATIVE_INFINITY;
+        for (final Pair<Double, Double> sample : innerDistribution.getSamples()) {
+            if (sample.getKey() > max && sample.getValue() > 0) {
+                max = sample.getKey();
+            }
+        }
+
+        return max;
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * The support of this distribution includes the lower bound.
+     *
+     * @return {@code true}
+     */
+    public boolean isSupportLowerBoundInclusive() {
+        return true;
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * The support of this distribution includes the upper bound.
+     *
+     * @return {@code true}
+     */
+    public boolean isSupportUpperBoundInclusive() {
+        return true;
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * The support of this distribution is connected.
+     *
+     * @return {@code true}
+     */
+    public boolean isSupportConnected() {
+        return true;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public double sample() {
+        return innerDistribution.sample();
+    }
+}

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/DiscreteRealDistribution.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/distribution/DiscreteRealDistribution.java
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"

Added: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/distribution/DiscreteIntegerDistributionTest.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math3/distribution/DiscreteIntegerDistributionTest.java?rev=1454439&view=auto
==============================================================================
--- commons/proper/math/trunk/src/test/java/org/apache/commons/math3/distribution/DiscreteIntegerDistributionTest.java (added)
+++ commons/proper/math/trunk/src/test/java/org/apache/commons/math3/distribution/DiscreteIntegerDistributionTest.java Fri Mar  8 15:59:29 2013
@@ -0,0 +1,171 @@
+/*
+ * 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 org.apache.commons.math3.distribution;
+
+import org.apache.commons.math3.exception.DimensionMismatchException;
+import org.apache.commons.math3.exception.MathArithmeticException;
+import org.apache.commons.math3.exception.MathIllegalArgumentException;
+import org.apache.commons.math3.exception.NotPositiveException;
+import org.apache.commons.math3.util.FastMath;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Test class for {@link DiscreteIntegerDistribution}.
+ * 
+ * @version $Id: DiscreteIntegerDistributionTest.java 161 2013-03-07 09:47:32Z wydrych $
+ */
+public class DiscreteIntegerDistributionTest {
+
+    /**
+     * The distribution object used for testing.
+     */
+    private final DiscreteIntegerDistribution testDistribution;
+
+    /**
+     * Creates the default distribution object uded for testing.
+     */
+    public DiscreteIntegerDistributionTest() {
+        // Non-sorted singleton array with duplicates should be allowed.
+        // Values with zero-probability do not extend the support.
+        testDistribution = new DiscreteIntegerDistribution(
+                new int[]{3, -1, 3, 7, -2, 8},
+                new double[]{0.2, 0.2, 0.3, 0.3, 0.0, 0.0});
+    }
+
+    /**
+     * Tests if the {@link DiscreteIntegerDistribution} constructor throws
+     * exceptions for ivalid data.
+     */
+    @Test
+    public void testExceptions() {
+        DiscreteIntegerDistribution invalid = null;
+        try {
+            invalid = new DiscreteIntegerDistribution(new int[]{1, 2}, new double[]{0.0});
+            Assert.fail("Expected DimensionMismatchException");
+        } catch (DimensionMismatchException e) {
+        }
+        try {
+            invalid = new DiscreteIntegerDistribution(new int[]{1, 2}, new double[]{0.0, -1.0});
+            Assert.fail("Expected NotPositiveException");
+        } catch (NotPositiveException e) {
+        }
+        try {
+            invalid = new DiscreteIntegerDistribution(new int[]{1, 2}, new double[]{0.0, 0.0});
+            Assert.fail("Expected MathArithmeticException");
+        } catch (MathArithmeticException e) {
+        }
+        try {
+            invalid = new DiscreteIntegerDistribution(new int[]{1, 2}, new double[]{0.0, Double.NaN});
+            Assert.fail("Expected MathArithmeticException");
+        } catch (MathArithmeticException e) {
+        }
+        try {
+            invalid = new DiscreteIntegerDistribution(new int[]{1, 2}, new double[]{0.0, Double.POSITIVE_INFINITY});
+            Assert.fail("Expected MathIllegalArgumentException");
+        } catch (MathIllegalArgumentException e) {
+        }
+        Assert.assertNull("Expected non-initialized DiscreteRealDistribution", invalid);
+    }
+
+    /**
+     * Tests if the distribution returns proper probability values.
+     */
+    @Test
+    public void testProbability() {
+        int[] points = new int[]{-2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8};
+        double[] results = new double[]{0, 0.2, 0, 0, 0, 0.5, 0, 0, 0, 0.3, 0};
+        for (int p = 0; p < points.length; p++) {
+            double probability = testDistribution.probability(points[p]);
+            Assert.assertEquals(results[p], probability, 0.0);
+        }
+    }
+
+    /**
+     * Tests if the distribution returns proper cumulative probability values.
+     */
+    @Test
+    public void testCumulativeProbability() {
+        int[] points = new int[]{-2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8};
+        double[] results = new double[]{0, 0.2, 0.2, 0.2, 0.2, 0.7, 0.7, 0.7, 0.7, 1.0, 1.0};
+        for (int p = 0; p < points.length; p++) {
+            double probability = testDistribution.cumulativeProbability(points[p]);
+            Assert.assertEquals(results[p], probability, 1e-10);
+        }
+    }
+
+    /**
+     * Tests if the distribution returns proper mean value.
+     */
+    @Test
+    public void testGetNumericalMean() {
+        Assert.assertEquals(3.4, testDistribution.getNumericalMean(), 1e-10);
+    }
+
+    /**
+     * Tests if the distribution returns proper variance.
+     */
+    @Test
+    public void testGetNumericalVariance() {
+        Assert.assertEquals(7.84, testDistribution.getNumericalVariance(), 1e-10);
+    }
+
+    /**
+     * Tests if the distribution returns proper lower bound.
+     */
+    @Test
+    public void testGetSupportLowerBound() {
+        Assert.assertEquals(-1, testDistribution.getSupportLowerBound());
+    }
+
+    /**
+     * Tests if the distribution returns proper upper bound.
+     */
+    @Test
+    public void testGetSupportUpperBound() {
+        Assert.assertEquals(7, testDistribution.getSupportUpperBound());
+    }
+
+    /**
+     * Tests if the distribution returns properly that the support is connected.
+     */
+    @Test
+    public void testIsSupportConnected() {
+        Assert.assertTrue(testDistribution.isSupportConnected());
+    }
+
+    /**
+     * Tests sampling.
+     */
+    @Test
+    public void testSample() {
+        final int n = 1000000;
+        testDistribution.reseedRandomGenerator(-334759360); // fixed seed
+        final int[] samples = testDistribution.sample(n);
+        Assert.assertEquals(n, samples.length);
+        double sum = 0;
+        double sumOfSquares = 0;
+        for (int i = 0; i < samples.length; i++) {
+            sum += samples[i];
+            sumOfSquares += samples[i] * samples[i];
+        }
+        Assert.assertEquals(testDistribution.getNumericalMean(),
+                sum / n, 1e-2);
+        Assert.assertEquals(testDistribution.getNumericalVariance(),
+                sumOfSquares / n - FastMath.pow(sum / n, 2), 1e-2);
+    }
+}

Propchange: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/distribution/DiscreteIntegerDistributionTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/distribution/DiscreteIntegerDistributionTest.java
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"

Added: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/distribution/DiscreteRealDistributionTest.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math3/distribution/DiscreteRealDistributionTest.java?rev=1454439&view=auto
==============================================================================
--- commons/proper/math/trunk/src/test/java/org/apache/commons/math3/distribution/DiscreteRealDistributionTest.java (added)
+++ commons/proper/math/trunk/src/test/java/org/apache/commons/math3/distribution/DiscreteRealDistributionTest.java Fri Mar  8 15:59:29 2013
@@ -0,0 +1,202 @@
+/*
+ * 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 org.apache.commons.math3.distribution;
+
+import org.apache.commons.math3.exception.DimensionMismatchException;
+import org.apache.commons.math3.exception.MathArithmeticException;
+import org.apache.commons.math3.exception.MathIllegalArgumentException;
+import org.apache.commons.math3.exception.NotPositiveException;
+import org.apache.commons.math3.util.FastMath;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Test class for {@link DiscreteRealDistribution}.
+ * 
+ * @version $Id: DiscreteRealDistributionTest.java 161 2013-03-07 09:47:32Z wydrych $
+ */
+public class DiscreteRealDistributionTest {
+
+    /**
+     * The distribution object used for testing.
+     */
+    private final DiscreteRealDistribution testDistribution;
+
+    /**
+     * Creates the default distribution object uded for testing.
+     */
+    public DiscreteRealDistributionTest() {
+        // Non-sorted singleton array with duplicates should be allowed.
+        // Values with zero-probability do not extend the support.
+        testDistribution = new DiscreteRealDistribution(
+                new double[]{3.0, -1.0, 3.0, 7.0, -2.0, 8.0},
+                new double[]{0.2, 0.2, 0.3, 0.3, 0.0, 0.0});
+    }
+
+    /**
+     * Tests if the {@link DiscreteRealDistribution} constructor throws
+     * exceptions for ivalid data.
+     */
+    @Test
+    public void testExceptions() {
+        DiscreteRealDistribution invalid = null;
+        try {
+            invalid = new DiscreteRealDistribution(new double[]{1.0, 2.0}, new double[]{0.0});
+            Assert.fail("Expected DimensionMismatchException");
+        } catch (DimensionMismatchException e) {
+        }
+        try{
+        invalid = new DiscreteRealDistribution(new double[]{1.0, 2.0}, new double[]{0.0, -1.0});
+            Assert.fail("Expected NotPositiveException");
+        } catch (NotPositiveException e) {
+        }
+        try {
+            invalid = new DiscreteRealDistribution(new double[]{1.0, 2.0}, new double[]{0.0, 0.0});
+            Assert.fail("Expected MathArithmeticException");
+        } catch (MathArithmeticException e) {
+        }
+        try {
+            invalid = new DiscreteRealDistribution(new double[]{1.0, 2.0}, new double[]{0.0, Double.NaN});
+            Assert.fail("Expected MathArithmeticException");
+        } catch (MathArithmeticException e) {
+        }
+        try {
+            invalid = new DiscreteRealDistribution(new double[]{1.0, 2.0}, new double[]{0.0, Double.POSITIVE_INFINITY});
+            Assert.fail("Expected MathIllegalArgumentException");
+        } catch (MathIllegalArgumentException e) {
+        }
+        Assert.assertNull("Expected non-initialized DiscreteRealDistribution", invalid);
+    }
+
+    /**
+     * Tests if the distribution returns proper probability values.
+     */
+    @Test
+    public void testProbability() {
+        double[] points = new double[]{-2.0, -1.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0};
+        double[] results = new double[]{0, 0.2, 0, 0, 0, 0.5, 0, 0, 0, 0.3, 0};
+        for (int p = 0; p < points.length; p++) {
+            double density = testDistribution.probability(points[p]);
+            Assert.assertEquals(results[p], density, 0.0);
+        }
+    }
+
+    /**
+     * Tests if the distribution returns proper density values.
+     */
+    @Test
+    public void testDensity() {
+        double[] points = new double[]{-2.0, -1.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0};
+        double[] results = new double[]{0, 0.2, 0, 0, 0, 0.5, 0, 0, 0, 0.3, 0};
+        for (int p = 0; p < points.length; p++) {
+            double density = testDistribution.density(points[p]);
+            Assert.assertEquals(results[p], density, 0.0);
+        }
+    }
+
+    /**
+     * Tests if the distribution returns proper cumulative probability values.
+     */
+    @Test
+    public void testCumulativeProbability() {
+        double[] points = new double[]{-2.0, -1.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0};
+        double[] results = new double[]{0, 0.2, 0.2, 0.2, 0.2, 0.7, 0.7, 0.7, 0.7, 1.0, 1.0};
+        for (int p = 0; p < points.length; p++) {
+            double probability = testDistribution.cumulativeProbability(points[p]);
+            Assert.assertEquals(results[p], probability, 1e-10);
+        }
+    }
+
+    /**
+     * Tests if the distribution returns proper mean value.
+     */
+    @Test
+    public void testGetNumericalMean() {
+        Assert.assertEquals(3.4, testDistribution.getNumericalMean(), 1e-10);
+    }
+
+    /**
+     * Tests if the distribution returns proper variance.
+     */
+    @Test
+    public void testGetNumericalVariance() {
+        Assert.assertEquals(7.84, testDistribution.getNumericalVariance(), 1e-10);
+    }
+
+    /**
+     * Tests if the distribution returns proper lower bound.
+     */
+    @Test
+    public void testGetSupportLowerBound() {
+        Assert.assertEquals(-1, testDistribution.getSupportLowerBound(), 0);
+    }
+
+    /**
+     * Tests if the distribution returns proper upper bound.
+     */
+    @Test
+    public void testGetSupportUpperBound() {
+        Assert.assertEquals(7, testDistribution.getSupportUpperBound(), 0);
+    }
+
+    /**
+     * Tests if the distribution returns properly that the support includes the
+     * lower bound.
+     */
+    @Test
+    public void testIsSupportLowerBoundInclusive() {
+        Assert.assertTrue(testDistribution.isSupportLowerBoundInclusive());
+    }
+
+    /**
+     * Tests if the distribution returns properly that the support includes the
+     * upper bound.
+     */
+    @Test
+    public void testIsSupportUpperBoundInclusive() {
+        Assert.assertTrue(testDistribution.isSupportUpperBoundInclusive());
+    }
+
+    /**
+     * Tests if the distribution returns properly that the support is connected.
+     */
+    @Test
+    public void testIsSupportConnected() {
+        Assert.assertTrue(testDistribution.isSupportConnected());
+    }
+
+    /**
+     * Tests sampling.
+     */
+    @Test
+    public void testSample() {
+        final int n = 1000000;
+        testDistribution.reseedRandomGenerator(-334759360); // fixed seed
+        final double[] samples = testDistribution.sample(n);
+        Assert.assertEquals(n, samples.length);
+        double sum = 0;
+        double sumOfSquares = 0;
+        for (int i = 0; i < samples.length; i++) {
+            sum += samples[i];
+            sumOfSquares += samples[i] * samples[i];
+        }
+        Assert.assertEquals(testDistribution.getNumericalMean(),
+                sum / n, 1e-2);
+        Assert.assertEquals(testDistribution.getNumericalVariance(),
+                sumOfSquares / n - FastMath.pow(sum / n, 2), 1e-2);
+    }
+}

Propchange: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/distribution/DiscreteRealDistributionTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/distribution/DiscreteRealDistributionTest.java
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"