1dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond/*
2dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Licensed to the Apache Software Foundation (ASF) under one or more
3dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * contributor license agreements.  See the NOTICE file distributed with
4dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * this work for additional information regarding copyright ownership.
5dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * The ASF licenses this file to You under the Apache License, Version 2.0
6dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * (the "License"); you may not use this file except in compliance with
7dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * the License.  You may obtain a copy of the License at
8dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond *
9dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond *      http://www.apache.org/licenses/LICENSE-2.0
10dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond *
11dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Unless required by applicable law or agreed to in writing, software
12dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * distributed under the License is distributed on an "AS IS" BASIS,
13dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * See the License for the specific language governing permissions and
15dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * limitations under the License.
16dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */
17dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
18dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondpackage org.apache.commons.math.distribution;
19dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
20dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport java.io.Serializable;
21dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
22dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport org.apache.commons.math.MathRuntimeException;
23dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport org.apache.commons.math.exception.util.LocalizedFormats;
24dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport org.apache.commons.math.util.MathUtils;
25dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport org.apache.commons.math.util.FastMath;
26dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
27dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond/**
28dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * The default implementation of {@link HypergeometricDistribution}.
29dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond *
30dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @version $Revision: 1054524 $ $Date: 2011-01-03 05:59:18 +0100 (lun. 03 janv. 2011) $
31dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */
32dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondpublic class HypergeometricDistributionImpl extends AbstractIntegerDistribution
33dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        implements HypergeometricDistribution, Serializable {
34dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
35dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Serializable version identifier */
36dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static final long serialVersionUID = -436928820673516179L;
37dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
38dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** The number of successes in the population. */
39dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private int numberOfSuccesses;
40dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
41dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** The population size. */
42dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private int populationSize;
43dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
44dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** The sample size. */
45dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private int sampleSize;
46dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
47dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
48dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Construct a new hypergeometric distribution with the given the population
49dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * size, the number of successes in the population, and the sample size.
50dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
51dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param populationSize the population size.
52dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param numberOfSuccesses number of successes in the population.
53dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param sampleSize the sample size.
54dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
55dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public HypergeometricDistributionImpl(int populationSize,
56dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            int numberOfSuccesses, int sampleSize) {
57dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        super();
58dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (numberOfSuccesses > populationSize) {
59dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            throw MathRuntimeException
60dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    .createIllegalArgumentException(
61dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                            LocalizedFormats.NUMBER_OF_SUCCESS_LARGER_THAN_POPULATION_SIZE,
62dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                            numberOfSuccesses, populationSize);
63dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
64dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (sampleSize > populationSize) {
65dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            throw MathRuntimeException
66dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    .createIllegalArgumentException(
67dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                            LocalizedFormats.SAMPLE_SIZE_LARGER_THAN_POPULATION_SIZE,
68dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                            sampleSize, populationSize);
69dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
70dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
71dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        setPopulationSizeInternal(populationSize);
72dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        setSampleSizeInternal(sampleSize);
73dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        setNumberOfSuccessesInternal(numberOfSuccesses);
74dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
75dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
76dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
77dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * For this distribution, X, this method returns P(X ≤ x).
78dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
79dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param x the value at which the PDF is evaluated.
80dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return PDF for this distribution.
81dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
82dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    @Override
83dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public double cumulativeProbability(int x) {
84dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double ret;
85dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
86dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        int[] domain = getDomain(populationSize, numberOfSuccesses, sampleSize);
87dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (x < domain[0]) {
88dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            ret = 0.0;
89dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        } else if (x >= domain[1]) {
90dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            ret = 1.0;
91dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        } else {
92dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            ret = innerCumulativeProbability(domain[0], x, 1, populationSize,
93dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                                             numberOfSuccesses, sampleSize);
94dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
95dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
96dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return ret;
97dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
98dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
99dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
100dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Return the domain for the given hypergeometric distribution parameters.
101dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
102dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param n the population size.
103dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param m number of successes in the population.
104dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param k the sample size.
105dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return a two element array containing the lower and upper bounds of the
106dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *         hypergeometric distribution.
107dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
108dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private int[] getDomain(int n, int m, int k) {
109dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return new int[] { getLowerDomain(n, m, k), getUpperDomain(m, k) };
110dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
111dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
112dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
113dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Access the domain value lower bound, based on <code>p</code>, used to
114dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * bracket a PDF root.
115dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
116dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param p the desired probability for the critical value
117dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return domain value lower bound, i.e. P(X &lt; <i>lower bound</i>) &lt;
118dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *         <code>p</code>
119dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
120dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    @Override
121dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    protected int getDomainLowerBound(double p) {
122dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return getLowerDomain(populationSize, numberOfSuccesses, sampleSize);
123dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
124dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
125dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
126dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Access the domain value upper bound, based on <code>p</code>, used to
127dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * bracket a PDF root.
128dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
129dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param p the desired probability for the critical value
130dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return domain value upper bound, i.e. P(X &lt; <i>upper bound</i>) &gt;
131dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *         <code>p</code>
132dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
133dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    @Override
134dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    protected int getDomainUpperBound(double p) {
135dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return getUpperDomain(sampleSize, numberOfSuccesses);
136dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
137dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
138dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
139dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Return the lowest domain value for the given hypergeometric distribution
140dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * parameters.
141dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
142dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param n the population size.
143dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param m number of successes in the population.
144dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param k the sample size.
145dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return the lowest domain value of the hypergeometric distribution.
146dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
147dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private int getLowerDomain(int n, int m, int k) {
148dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return FastMath.max(0, m - (n - k));
149dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
150dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
151dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
152dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Access the number of successes.
153dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
154dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return the number of successes.
155dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
156dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public int getNumberOfSuccesses() {
157dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return numberOfSuccesses;
158dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
159dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
160dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
161dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Access the population size.
162dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
163dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return the population size.
164dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
165dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public int getPopulationSize() {
166dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return populationSize;
167dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
168dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
169dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
170dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Access the sample size.
171dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
172dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return the sample size.
173dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
174dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public int getSampleSize() {
175dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return sampleSize;
176dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
177dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
178dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
179dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Return the highest domain value for the given hypergeometric distribution
180dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * parameters.
181dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
182dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param m number of successes in the population.
183dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param k the sample size.
184dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return the highest domain value of the hypergeometric distribution.
185dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
186dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private int getUpperDomain(int m, int k) {
187dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return FastMath.min(k, m);
188dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
189dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
190dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
191dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * For this distribution, X, this method returns P(X = x).
192dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
193dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param x the value at which the PMF is evaluated.
194dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return PMF for this distribution.
195dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
196dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public double probability(int x) {
197dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double ret;
198dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
199dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        int[] domain = getDomain(populationSize, numberOfSuccesses, sampleSize);
200dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (x < domain[0] || x > domain[1]) {
201dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            ret = 0.0;
202dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        } else {
203dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double p = (double) sampleSize / (double) populationSize;
204dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double q = (double) (populationSize - sampleSize) / (double) populationSize;
205dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double p1 = SaddlePointExpansion.logBinomialProbability(x,
206dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    numberOfSuccesses, p, q);
207dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double p2 =
208dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                SaddlePointExpansion.logBinomialProbability(sampleSize - x,
209dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    populationSize - numberOfSuccesses, p, q);
210dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            double p3 =
211dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                SaddlePointExpansion.logBinomialProbability(sampleSize, populationSize, p, q);
212dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            ret = FastMath.exp(p1 + p2 - p3);
213dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
214dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
215dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return ret;
216dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
217dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
218dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
219dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * For the distribution, X, defined by the given hypergeometric distribution
220dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * parameters, this method returns P(X = x).
221dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
222dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param n the population size.
223dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param m number of successes in the population.
224dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param k the sample size.
225dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param x the value at which the PMF is evaluated.
226dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return PMF for the distribution.
227dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
228dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private double probability(int n, int m, int k, int x) {
229dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return FastMath.exp(MathUtils.binomialCoefficientLog(m, x) +
230dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond               MathUtils.binomialCoefficientLog(n - m, k - x) -
231dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond               MathUtils.binomialCoefficientLog(n, k));
232dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
233dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
234dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
235dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Modify the number of successes.
236dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
237dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param num the new number of successes.
238dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @throws IllegalArgumentException if <code>num</code> is negative.
239dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @deprecated as of 2.1 (class will become immutable in 3.0)
240dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
241dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    @Deprecated
242dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public void setNumberOfSuccesses(int num) {
243dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        setNumberOfSuccessesInternal(num);
244dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
245dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
246dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
247dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Modify the number of successes.
248dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
249dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param num the new number of successes.
250dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @throws IllegalArgumentException if <code>num</code> is negative.
251dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
252dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private void setNumberOfSuccessesInternal(int num) {
253dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (num < 0) {
254dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            throw MathRuntimeException.createIllegalArgumentException(
255dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    LocalizedFormats.NEGATIVE_NUMBER_OF_SUCCESSES, num);
256dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
257dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        numberOfSuccesses = num;
258dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
259dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
260dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
261dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Modify the population size.
262dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
263dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param size the new population size.
264dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @throws IllegalArgumentException if <code>size</code> is not positive.
265dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @deprecated as of 2.1 (class will become immutable in 3.0)
266dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
267dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    @Deprecated
268dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public void setPopulationSize(int size) {
269dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        setPopulationSizeInternal(size);
270dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
271dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
272dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
273dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Modify the population size.
274dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
275dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param size the new population size.
276dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @throws IllegalArgumentException if <code>size</code> is not positive.
277dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
278dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private void setPopulationSizeInternal(int size) {
279dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (size <= 0) {
280dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            throw MathRuntimeException.createIllegalArgumentException(
281dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    LocalizedFormats.NOT_POSITIVE_POPULATION_SIZE, size);
282dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
283dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        populationSize = size;
284dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
285dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
286dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
287dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Modify the sample size.
288dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
289dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param size the new sample size.
290dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @throws IllegalArgumentException if <code>size</code> is negative.
291dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @deprecated as of 2.1 (class will become immutable in 3.0)
292dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
293dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    @Deprecated
294dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public void setSampleSize(int size) {
295dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        setSampleSizeInternal(size);
296dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
297dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
298dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Modify the sample size.
299dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
300dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param size the new sample size.
301dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @throws IllegalArgumentException if <code>size</code> is negative.
302dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
303dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private void setSampleSizeInternal(int size) {
304dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (size < 0) {
305dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            throw MathRuntimeException.createIllegalArgumentException(
306dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    LocalizedFormats.NOT_POSITIVE_SAMPLE_SIZE, size);
307dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
308dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        sampleSize = size;
309dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
310dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
311dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
312dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * For this distribution, X, this method returns P(X &ge; x).
313dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
314dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param x the value at which the CDF is evaluated.
315dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return upper tail CDF for this distribution.
316dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @since 1.1
317dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
318dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public double upperCumulativeProbability(int x) {
319dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double ret;
320dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
321dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final int[] domain = getDomain(populationSize, numberOfSuccesses, sampleSize);
322dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (x < domain[0]) {
323dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            ret = 1.0;
324dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        } else if (x > domain[1]) {
325dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            ret = 0.0;
326dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        } else {
327dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            ret = innerCumulativeProbability(domain[1], x, -1, populationSize, numberOfSuccesses, sampleSize);
328dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
329dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
330dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return ret;
331dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
332dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
333dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
334dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * For this distribution, X, this method returns P(x0 &le; X &le; x1). This
335dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * probability is computed by summing the point probabilities for the values
336dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * x0, x0 + 1, x0 + 2, ..., x1, in the order directed by dx.
337dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
338dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param x0 the inclusive, lower bound
339dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param x1 the inclusive, upper bound
340dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param dx the direction of summation. 1 indicates summing from x0 to x1.
341dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *            0 indicates summing from x1 to x0.
342dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param n the population size.
343dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param m number of successes in the population.
344dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param k the sample size.
345dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return P(x0 &le; X &le; x1).
346dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
347dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private double innerCumulativeProbability(int x0, int x1, int dx, int n,
348dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            int m, int k) {
349dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        double ret = probability(n, m, k, x0);
350dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        while (x0 != x1) {
351dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            x0 += dx;
352dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            ret += probability(n, m, k, x0);
353dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
354dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return ret;
355dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
356dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
357dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
358dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Returns the lower bound for the support for the distribution.
359dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
360dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * For population size <code>N</code>,
361dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * number of successes <code>m</code>, and
362dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * sample size <code>n</code>,
363dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * the lower bound of the support is
364dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <code>max(0, n + m - N)</code>
365dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
366dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return lower bound of the support
367dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @since 2.2
368dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
369dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public int getSupportLowerBound() {
370dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return FastMath.max(0,
371dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                getSampleSize() + getNumberOfSuccesses() - getPopulationSize());
372dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
373dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
374dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
375dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Returns the upper bound for the support of the distribution.
376dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
377dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * For number of successes <code>m</code> and
378dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * sample size <code>n</code>,
379dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * the upper bound of the support is
380dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <code>min(m, n)</code>
381dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
382dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return upper bound of the support
383dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @since 2.2
384dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
385dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public int getSupportUpperBound() {
386dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return FastMath.min(getNumberOfSuccesses(), getSampleSize());
387dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
388dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
389dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
390dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Returns the mean.
391dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
392dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * For population size <code>N</code>,
393dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * number of successes <code>m</code>, and
394dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * sample size <code>n</code>, the mean is
395dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <code>n * m / N</code>
396dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
397dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return the mean
398dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @since 2.2
399dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
400dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    protected double getNumericalMean() {
401dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return (double)(getSampleSize() * getNumberOfSuccesses()) / (double)getPopulationSize();
402dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
403dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
404dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
405dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Returns the variance.
406dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
407dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * For population size <code>N</code>,
408dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * number of successes <code>m</code>, and
409dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * sample size <code>n</code>, the variance is
410dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <code>[ n * m * (N - n) * (N - m) ] / [ N^2 * (N - 1) ]</code>
411dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
412dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return the variance
413dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @since 2.2
414dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
415dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public double getNumericalVariance() {
416dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double N = getPopulationSize();
417dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double m = getNumberOfSuccesses();
418dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final double n = getSampleSize();
419dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return ( n * m * (N - n) * (N - m) ) / ( (N*N * (N - 1)) );
420dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
421dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond}
422