[EMAIL PROTECTED] a écrit : > Author: brentworden > Date: Thu Sep 25 20:09:53 2008 > New Revision: 699157 > > URL: http://svn.apache.org/viewvc?rev=699157&view=rev > Log: > MATH-227. fixed F distribution inverse CDF computation for small denominator > degrees of freedom.
I would like to propagate this change to the 2.0 branch where most work happens now. However I don't want to apply it directly using svn commands because lots of noise has been added by some space characters being replaced with tab characters everywhere in this commit. I tracked the modification to the following change. Could you confirm the only thing related to bug fix is the replacement of: protected double getInitialDomain(double p) { return getDenominatorDegreesOfFreedom() / (getDenominatorDegreesOfFreedom() - 2.0); } by: protected double getInitialDomain(double p) { double ret = 1.0; double d = getDenominatorDegreesOfFreedom(); if (d > 2.0) { // use mean ret = d / (d - 2.0); } return ret; } thanks, Luc > > Modified: > > commons/proper/math/trunk/src/java/org/apache/commons/math/distribution/FDistributionImpl.java > commons/proper/math/trunk/src/site/xdoc/changes.xml > > commons/proper/math/trunk/src/test/org/apache/commons/math/distribution/FDistributionTest.java > > Modified: > commons/proper/math/trunk/src/java/org/apache/commons/math/distribution/FDistributionImpl.java > URL: > http://svn.apache.org/viewvc/commons/proper/math/trunk/src/java/org/apache/commons/math/distribution/FDistributionImpl.java?rev=699157&r1=699156&r2=699157&view=diff > ============================================================================== > --- > commons/proper/math/trunk/src/java/org/apache/commons/math/distribution/FDistributionImpl.java > (original) > +++ > commons/proper/math/trunk/src/java/org/apache/commons/math/distribution/FDistributionImpl.java > Thu Sep 25 20:09:53 2008 > @@ -24,168 +24,188 @@ > /** > * Default implementation of > * [EMAIL PROTECTED] org.apache.commons.math.distribution.FDistribution}. > - * > - * @version $Revision$ $Date$ > + * > + * @version $Revision$ $Date: 2008-02-08 09:44:11 -0600 (Fri, 08 Feb > + * 2008) $ > */ > -public class FDistributionImpl > - extends AbstractContinuousDistribution > - implements FDistribution, Serializable { > - > - /** Serializable version identifier */ > - private static final long serialVersionUID = -8516354193418641566L; > - > - /** The numerator degrees of freedom*/ > - private double numeratorDegreesOfFreedom; > - > - /** The numerator degrees of freedom*/ > - private double denominatorDegreesOfFreedom; > - > - /** > - * Create a F distribution using the given degrees of freedom. > - * @param numeratorDegreesOfFreedom the numerator degrees of freedom. > - * @param denominatorDegreesOfFreedom the denominator degrees of freedom. > - */ > - public FDistributionImpl(double numeratorDegreesOfFreedom, > - double denominatorDegreesOfFreedom) { > - super(); > - setNumeratorDegreesOfFreedom(numeratorDegreesOfFreedom); > - setDenominatorDegreesOfFreedom(denominatorDegreesOfFreedom); > - } > - > - /** > - * For this distribution, X, this method returns P(X < x). > - * > - * The implementation of this method is based on: > - * <ul> > - * <li> > - * <a href="http://mathworld.wolfram.com/F-Distribution.html"> > - * F-Distribution</a>, equation (4).</li> > - * </ul> > - * > - * @param x the value at which the CDF is evaluated. > - * @return CDF for this distribution. > - * @throws MathException if the cumulative probability can not be > - * computed due to convergence or other numerical errors. > - */ > - public double cumulativeProbability(double x) throws MathException { > - double ret; > - if (x <= 0.0) { > - ret = 0.0; > - } else { > - double n = getNumeratorDegreesOfFreedom(); > - double m = getDenominatorDegreesOfFreedom(); > - > - ret = Beta.regularizedBeta((n * x) / (m + n * x), > - 0.5 * n, > - 0.5 * m); > - } > - return ret; > - } > - > - /** > - * For this distribution, X, this method returns the critical point x, > such > - * that P(X < x) = <code>p</code>. > - * <p> > - * Returns 0 for p=0 and <code>Double.POSITIVE_INFINITY</code> for > p=1.</p> > - * > - * @param p the desired probability > - * @return x, such that P(X < x) = <code>p</code> > - * @throws MathException if the inverse cumulative probability can not be > - * computed due to convergence or other numerical errors. > - * @throws IllegalArgumentException if <code>p</code> is not a valid > - * probability. > - */ > - public double inverseCumulativeProbability(final double p) > - throws MathException { > - if (p == 0) { > - return 0d; > - } > - if (p == 1) { > - return Double.POSITIVE_INFINITY; > - } > - return super.inverseCumulativeProbability(p); > - } > - > - /** > - * Access the domain value lower bound, based on <code>p</code>, used to > - * bracket a CDF root. This method is used by > - * [EMAIL PROTECTED] #inverseCumulativeProbability(double)} to find > critical values. > - * > - * @param p the desired probability for the critical value > - * @return domain value lower bound, i.e. > - * P(X < <i>lower bound</i>) < <code>p</code> > - */ > - protected double getDomainLowerBound(double p) { > - return 0.0; > - } > - > - /** > - * Access the domain value upper bound, based on <code>p</code>, used to > - * bracket a CDF root. This method is used by > - * [EMAIL PROTECTED] #inverseCumulativeProbability(double)} to find > critical values. > - * > - * @param p the desired probability for the critical value > - * @return domain value upper bound, i.e. > - * P(X < <i>upper bound</i>) > <code>p</code> > - */ > - protected double getDomainUpperBound(double p) { > - return Double.MAX_VALUE; > - } > - > - /** > - * Access the initial domain value, based on <code>p</code>, used to > - * bracket a CDF root. This method is used by > - * [EMAIL PROTECTED] #inverseCumulativeProbability(double)} to find > critical values. > - * > - * @param p the desired probability for the critical value > - * @return initial domain value > - */ > - protected double getInitialDomain(double p) { > - return getDenominatorDegreesOfFreedom() / > - (getDenominatorDegreesOfFreedom() - 2.0); > - } > - > - /** > - * Modify the numerator degrees of freedom. > - * @param degreesOfFreedom the new numerator degrees of freedom. > - * @throws IllegalArgumentException if <code>degreesOfFreedom</code> is > not > - * positive. > - */ > - public void setNumeratorDegreesOfFreedom(double degreesOfFreedom) { > - if (degreesOfFreedom <= 0.0) { > - throw new IllegalArgumentException( > - "degrees of freedom must be positive."); > - } > - this.numeratorDegreesOfFreedom = degreesOfFreedom; > - } > - > - /** > - * Access the numerator degrees of freedom. > - * @return the numerator degrees of freedom. > - */ > - public double getNumeratorDegreesOfFreedom() { > - return numeratorDegreesOfFreedom; > - } > - > - /** > - * Modify the denominator degrees of freedom. > - * @param degreesOfFreedom the new denominator degrees of freedom. > - * @throws IllegalArgumentException if <code>degreesOfFreedom</code> is > not > - * positive. > - */ > - public void setDenominatorDegreesOfFreedom(double degreesOfFreedom) { > - if (degreesOfFreedom <= 0.0) { > - throw new IllegalArgumentException( > - "degrees of freedom must be positive."); > - } > - this.denominatorDegreesOfFreedom = degreesOfFreedom; > - } > - > - /** > - * Access the denominator degrees of freedom. > - * @return the denominator degrees of freedom. > - */ > - public double getDenominatorDegreesOfFreedom() { > - return denominatorDegreesOfFreedom; > - } > +public class FDistributionImpl extends AbstractContinuousDistribution > implements > + FDistribution, Serializable { > + > + /** Serializable version identifier */ > + private static final long serialVersionUID = -8516354193418641566L; > + > + /** The numerator degrees of freedom */ > + private double numeratorDegreesOfFreedom; > + > + /** The numerator degrees of freedom */ > + private double denominatorDegreesOfFreedom; > + > + /** > + * Create a F distribution using the given degrees of freedom. > + * > + * @param numeratorDegreesOfFreedom > + * the numerator degrees of freedom. > + * @param denominatorDegreesOfFreedom > + * the denominator degrees of freedom. > + */ > + public FDistributionImpl(double numeratorDegreesOfFreedom, > + double denominatorDegreesOfFreedom) { > + super(); > + setNumeratorDegreesOfFreedom(numeratorDegreesOfFreedom); > + setDenominatorDegreesOfFreedom(denominatorDegreesOfFreedom); > + } > + > + /** > + * For this distribution, X, this method returns P(X < x). > + * > + * The implementation of this method is based on: > + * <ul> > + * <li> > + * <a href="http://mathworld.wolfram.com/F-Distribution.html"> > + * F-Distribution</a>, equation (4).</li> > + * </ul> > + * > + * @param x > + * the value at which the CDF is evaluated. > + * @return CDF for this distribution. > + * @throws MathException > + * if the cumulative probability can not be computed due to > + * convergence or other numerical errors. > + */ > + public double cumulativeProbability(double x) throws MathException { > + double ret; > + if (x <= 0.0) { > + ret = 0.0; > + } else { > + double n = getNumeratorDegreesOfFreedom(); > + double m = getDenominatorDegreesOfFreedom(); > + > + ret = Beta.regularizedBeta((n * x) / (m + n * x), 0.5 * > n, 0.5 * m); > + } > + return ret; > + } > + > + /** > + * For this distribution, X, this method returns the critical point x, > such > + * that P(X < x) = <code>p</code>. > + * <p> > + * Returns 0 for p=0 and <code>Double.POSITIVE_INFINITY</code> for p=1. > + * </p> > + * > + * @param p > + * the desired probability > + * @return x, such that P(X < x) = <code>p</code> > + * @throws MathException > + * if the inverse cumulative probability can not be > computed due > + * to convergence or other numerical errors. > + * @throws IllegalArgumentException > + * if <code>p</code> is not a valid probability. > + */ > + public double inverseCumulativeProbability(final double p) > + throws MathException { > + if (p == 0) { > + return 0d; > + } > + if (p == 1) { > + return Double.POSITIVE_INFINITY; > + } > + return super.inverseCumulativeProbability(p); > + } > + > + /** > + * Access the domain value lower bound, based on <code>p</code>, used to > + * bracket a CDF root. This method is used by > + * [EMAIL PROTECTED] #inverseCumulativeProbability(double)} to find > critical values. > + * > + * @param p > + * the desired probability for the critical value > + * @return domain value lower bound, i.e. P(X < <i>lower bound</i>) > < > + * <code>p</code> > + */ > + protected double getDomainLowerBound(double p) { > + return 0.0; > + } > + > + /** > + * Access the domain value upper bound, based on <code>p</code>, used to > + * bracket a CDF root. This method is used by > + * [EMAIL PROTECTED] #inverseCumulativeProbability(double)} to find > critical values. > + * > + * @param p > + * the desired probability for the critical value > + * @return domain value upper bound, i.e. P(X < <i>upper bound</i>) > > > + * <code>p</code> > + */ > + protected double getDomainUpperBound(double p) { > + return Double.MAX_VALUE; > + } > + > + /** > + * Access the initial domain value, based on <code>p</code>, used to > bracket > + * a CDF root. This method is used by > + * [EMAIL PROTECTED] #inverseCumulativeProbability(double)} to find > critical values. > + * > + * @param p > + * the desired probability for the critical value > + * @return initial domain value > + */ > + protected double getInitialDomain(double p) { > + double ret = 1.0; > + double d = getDenominatorDegreesOfFreedom(); > + if (d > 2.0) { > + // use mean > + ret = d / (d - 2.0); > + } > + return ret; > + } > + > + /** > + * Modify the numerator degrees of freedom. > + * > + * @param degreesOfFreedom > + * the new numerator degrees of freedom. > + * @throws IllegalArgumentException > + * if <code>degreesOfFreedom</code> is not positive. > + */ > + public void setNumeratorDegreesOfFreedom(double degreesOfFreedom) { > + if (degreesOfFreedom <= 0.0) { > + throw new IllegalArgumentException( > + "degrees of freedom must be positive."); > + } > + this.numeratorDegreesOfFreedom = degreesOfFreedom; > + } > + > + /** > + * Access the numerator degrees of freedom. > + * > + * @return the numerator degrees of freedom. > + */ > + public double getNumeratorDegreesOfFreedom() { > + return numeratorDegreesOfFreedom; > + } > + > + /** > + * Modify the denominator degrees of freedom. > + * > + * @param degreesOfFreedom > + * the new denominator degrees of freedom. > + * @throws IllegalArgumentException > + * if <code>degreesOfFreedom</code> is not positive. > + */ > + public void setDenominatorDegreesOfFreedom(double degreesOfFreedom) { > + if (degreesOfFreedom <= 0.0) { > + throw new IllegalArgumentException( > + "degrees of freedom must be positive."); > + } > + this.denominatorDegreesOfFreedom = degreesOfFreedom; > + } > + > + /** > + * Access the denominator degrees of freedom. > + * > + * @return the denominator degrees of freedom. > + */ > + public double getDenominatorDegreesOfFreedom() { > + return denominatorDegreesOfFreedom; > + } > } > > Modified: commons/proper/math/trunk/src/site/xdoc/changes.xml > URL: > http://svn.apache.org/viewvc/commons/proper/math/trunk/src/site/xdoc/changes.xml?rev=699157&r1=699156&r2=699157&view=diff > ============================================================================== > --- commons/proper/math/trunk/src/site/xdoc/changes.xml (original) > +++ commons/proper/math/trunk/src/site/xdoc/changes.xml Thu Sep 25 20:09:53 > 2008 > @@ -65,6 +65,9 @@ > <action dev="brentworden" type="fix" issue="MATH-204" due-to="Mick"> > Added root checks for the endpoints. > </action> > + <action dev="brentworden" type="fix" issue="MATH-227" due-to="Joerg > Henning"> > + Fixed F distribution inverse CDF computation for small denominator > degrees of freedom. > + </action> > </release> > <release version="1.2" date="2008-02-24" > description="This release combines bug fixes and new features. Most > notable > > Modified: > commons/proper/math/trunk/src/test/org/apache/commons/math/distribution/FDistributionTest.java > URL: > http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/org/apache/commons/math/distribution/FDistributionTest.java?rev=699157&r1=699156&r2=699157&view=diff > ============================================================================== > --- > commons/proper/math/trunk/src/test/org/apache/commons/math/distribution/FDistributionTest.java > (original) > +++ > commons/proper/math/trunk/src/test/org/apache/commons/math/distribution/FDistributionTest.java > Thu Sep 25 20:09:53 2008 > @@ -105,4 +105,18 @@ > double x = fd.inverseCumulativeProbability(p); > assertEquals(.999, x, 1.0e-5); > } > + > + public void testSmallDegreesOfFreedom() throws Exception { > + org.apache.commons.math.distribution.FDistributionImpl fd = > + new org.apache.commons.math.distribution.FDistributionImpl( > + 1.0, 1.0); > + double p = fd.cumulativeProbability(0.975); > + double x = fd.inverseCumulativeProbability(p); > + assertEquals(0.975, x, 1.0e-5); > + > + fd.setDenominatorDegreesOfFreedom(2.0); > + p = fd.cumulativeProbability(0.975); > + x = fd.inverseCumulativeProbability(p); > + assertEquals(0.975, x, 1.0e-5); > + } > } > > > --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]