From 93a6d754cc1ca0fc245e411d4b2d02058d3d4fc7 Mon Sep 17 00:00:00 2001 From: Brent Worden Date: Thu, 17 Mar 2005 03:20:12 +0000 Subject: [PATCH] added weibull distribution git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/math/trunk@157874 13f79535-47bb-0310-9956-ffa450edef68 --- .../distribution/CauchyDistributionImpl.java | 6 +- .../distribution/DistributionFactory.java | 17 +- .../distribution/WeibullDistribution.java | 63 +++++++ .../distribution/WeibullDistributionImpl.java | 171 ++++++++++++++++++ .../DistributionFactoryImplTest.java | 48 +++++ .../distribution/WeibullDistributionTest.java | 113 ++++++++++++ xdocs/changes.xml | 3 + xdocs/userguide/distribution.xml | 1 + 8 files changed, 418 insertions(+), 4 deletions(-) create mode 100644 src/java/org/apache/commons/math/distribution/WeibullDistribution.java create mode 100644 src/java/org/apache/commons/math/distribution/WeibullDistributionImpl.java create mode 100644 src/test/org/apache/commons/math/distribution/WeibullDistributionTest.java diff --git a/src/java/org/apache/commons/math/distribution/CauchyDistributionImpl.java b/src/java/org/apache/commons/math/distribution/CauchyDistributionImpl.java index eea492e9b..cbcc22298 100644 --- a/src/java/org/apache/commons/math/distribution/CauchyDistributionImpl.java +++ b/src/java/org/apache/commons/math/distribution/CauchyDistributionImpl.java @@ -22,7 +22,7 @@ import java.io.Serializable; * Default implementation of * {@link org.apache.commons.math.distribution.CauchyDistribution}. * - * @version $Revision$ $Date$ + * @version $Revision: 1.13 $ $Date$ */ public class CauchyDistributionImpl extends AbstractContinuousDistribution implements CauchyDistribution, Serializable { @@ -37,8 +37,8 @@ public class CauchyDistributionImpl extends AbstractContinuousDistribution private double scale = 1; /** - * Creates normal distribution with the mean equal to zero and standard - * deviation equal to one. + * Creates cauchy distribution with the medain equal to zero and scale + * equal to one. */ public CauchyDistributionImpl(){ this(0.0, 1.0); diff --git a/src/java/org/apache/commons/math/distribution/DistributionFactory.java b/src/java/org/apache/commons/math/distribution/DistributionFactory.java index 0e60a613e..beb485276 100644 --- a/src/java/org/apache/commons/math/distribution/DistributionFactory.java +++ b/src/java/org/apache/commons/math/distribution/DistributionFactory.java @@ -32,6 +32,7 @@ import org.apache.commons.discovery.tools.DiscoverClass; *
  • Poisson
  • *
  • Normal
  • *
  • Student's t
  • + *
  • Weibull
  • * * * Common usage:
    @@ -175,8 +176,22 @@ public abstract class DistributionFactory {
          * Create a new Poisson distribution with poisson parameter lambda.
          * 
          * @param lambda poisson parameter
    -     * @return a new normal distribution.  
    +     * @return a new poisson distribution.  
          */               
         public abstract PoissonDistribution 
             createPoissonDistribution(double lambda);
    +    
    +    /**
    +     * Create a new Weibull distribution with the given shape and scale
    +     * parameters.
    +     * 
    +     * @param alpha the shape parameter.
    +     * @param beta the scale parameter.
    +     * @return a new Weibull distribution.  
    +     */               
    +    public WeibullDistribution createWeibullDistribution(
    +        double alpha, double beta)
    +    {
    +        return new WeibullDistributionImpl(alpha, beta);
    +    }
     }
    diff --git a/src/java/org/apache/commons/math/distribution/WeibullDistribution.java b/src/java/org/apache/commons/math/distribution/WeibullDistribution.java
    new file mode 100644
    index 000000000..3333f051f
    --- /dev/null
    +++ b/src/java/org/apache/commons/math/distribution/WeibullDistribution.java
    @@ -0,0 +1,63 @@
    +/*
    + * Copyright 2005 The Apache Software Foundation.
    + *
    + * Licensed 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.math.distribution;
    +
    +/**
    + * Weibull Distribution.  This interface defines the two parameter form of the
    + * distribution as defined by
    + * 
    + * Weibull Distribution, equations (1) and (2).
    + *
    + * Instances of WeibullDistribution objects should be created using
    + * {@link DistributionFactory#createWeibullDistribution(double, double)}
    + *
    + * 

    + * References: + *

    + *

    + * + * @version $Revision: 1.12 $ $Date: 2004-06-23 11:26:18 -0500 (Wed, 23 Jun 2004) $ + */ +public interface WeibullDistribution extends ContinuousDistribution { + + /** + * Access the shape parameter. + * @return the shape parameter. + */ + double getShape(); + + /** + * Access the scale parameter. + * @return the scale parameter. + */ + double getScale(); + + /** + * Modify the shape parameter. + * @param alpha The new shape parameter value. + */ + void setShape(double alpha); + + /** + * Modify the scale parameter. + * @param beta The new scale parameter value. + */ + void setScale(double beta); +} diff --git a/src/java/org/apache/commons/math/distribution/WeibullDistributionImpl.java b/src/java/org/apache/commons/math/distribution/WeibullDistributionImpl.java new file mode 100644 index 000000000..3d1dfef8b --- /dev/null +++ b/src/java/org/apache/commons/math/distribution/WeibullDistributionImpl.java @@ -0,0 +1,171 @@ +/* + * Copyright 2005 The Apache Software Foundation. + * + * Licensed 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.math.distribution; + +import java.io.Serializable; + +/** + * Default implementation of + * {@link org.apache.commons.math.distribution.WeibullDistribution}. + * + * @version $Revision: 1.13 $ $Date: 2004-07-24 16:41:37 -0500 (Sat, 24 Jul 2004) $ + */ +public class WeibullDistributionImpl extends AbstractContinuousDistribution + implements WeibullDistribution, Serializable { + + /** Serializable version identifier */ + static final long serialVersionUID = 8589540077390120676L; + + /** The shape parameter. */ + private double alpha; + + /** The scale parameter. */ + private double beta; + + /** + * Creates weibull distribution with the given shape and scale and a + * location equal to zero. + * @param alpha the shape parameter. + * @param beta the scale parameter. + */ + public WeibullDistributionImpl(double alpha, double beta){ + super(); + setShape(alpha); + setScale(beta); + } + + /** + * For this disbution, X, this method returns P(X < x). + * @param x the value at which the CDF is evaluated. + * @return CDF evaluted at x. + */ + public double cumulativeProbability(double x) { + double ret; + if (x <= 0.0) { + ret = 0.0; + } else { + ret = 1.0 - Math.exp(-Math.pow(x / getScale(), getShape())); + } + return ret; + } + + /** + * Access alpha. + * @return the alpha. + */ + public double getShape() { + return alpha; + } + + /** + * Access beta. + * @return the beta. + */ + public double getScale() { + return beta; + } + + /** + * For this distribution, X, this method returns the critical point x, such + * that P(X < x) = p. + *

    + * Returns Double.NEGATIVE_INFINITY for p=0 and + * Double.POSITIVE_INFINITY for p=1. + * + * @param p the desired probability + * @return x, such that P(X < x) = p + * @throws IllegalArgumentException if p is not a valid + * probability. + */ + public double inverseCumulativeProbability(double p) { + double ret; + if (p < 0.0 || p > 1.0) { + throw new IllegalArgumentException + ("probability argument must be between 0 and 1 (inclusive)"); + } else if (p == 0) { + ret = 0.0; + } else if (p == 1) { + ret = Double.POSITIVE_INFINITY; + } else { + ret = getScale() * Math.pow(-Math.log(1.0 - p), 1.0 / getShape()); + } + return ret; + } + + /** + * Modify alpha. + * @param alpha The new alpha value. + */ + public void setShape(double alpha) { + if (alpha <= 0.0) { + throw new IllegalArgumentException( + "Shape must be positive."); + } + this.alpha = alpha; + } + + /** + * Modify beta. + * @param beta The new beta value. + */ + public void setScale(double beta) { + if (beta <= 0.0) { + throw new IllegalArgumentException( + "Scale must be positive."); + } + this.beta = beta; + } + + /** + * Access the domain value lower bound, based on p, used to + * bracket a CDF root. This method is used by + * {@link #inverseCumulativeProbability(double)} to find critical values. + * + * @param p the desired probability for the critical value + * @return domain value lower bound, i.e. + * P(X < lower bound) < p + */ + protected double getDomainLowerBound(double p) { + return 0.0; + } + + /** + * Access the domain value upper bound, based on p, used to + * bracket a CDF root. This method is used by + * {@link #inverseCumulativeProbability(double)} to find critical values. + * + * @param p the desired probability for the critical value + * @return domain value upper bound, i.e. + * P(X < upper bound) > p + */ + protected double getDomainUpperBound(double p) { + return Double.MAX_VALUE; + } + + /** + * Access the initial domain value, based on p, used to + * bracket a CDF root. This method is used by + * {@link #inverseCumulativeProbability(double)} to find critical values. + * + * @param p the desired probability for the critical value + * @return initial domain value + */ + protected double getInitialDomain(double p) { + // use median + return Math.pow(getScale() * Math.log(2.0), 1.0 / getShape()); + } +} diff --git a/src/test/org/apache/commons/math/distribution/DistributionFactoryImplTest.java b/src/test/org/apache/commons/math/distribution/DistributionFactoryImplTest.java index 479a97193..255930934 100644 --- a/src/test/org/apache/commons/math/distribution/DistributionFactoryImplTest.java +++ b/src/test/org/apache/commons/math/distribution/DistributionFactoryImplTest.java @@ -325,4 +325,52 @@ public class DistributionFactoryImplTest extends TestCase { } catch(IllegalArgumentException ex) { } } + + public void testCauchyDistributionNegative() { + try { + factory.createCauchyDistribution(0.0, -1.0); + fail("invalid scale. IllegalArgumentException expected"); + } catch(IllegalArgumentException ex) { + } + } + + public void testCauchyDistributionZero() { + try { + factory.createCauchyDistribution(0.0, 0.0); + fail("invalid scale. IllegalArgumentException expected"); + } catch(IllegalArgumentException ex) { + } + } + + public void testWeibullDistributionNegativePositive() { + try { + factory.createWeibullDistribution(-1.0, 1.0); + fail("invalid shape. IllegalArgumentException expected"); + } catch(IllegalArgumentException ex) { + } + } + + public void testWeibullDistributionZeroPositive() { + try { + factory.createWeibullDistribution(0.0, 1.0); + fail("invalid shape. IllegalArgumentException expected"); + } catch(IllegalArgumentException ex) { + } + } + + public void testWeibullDistributionPositiveNegative() { + try { + factory.createWeibullDistribution(1.0, -1.0); + fail("invalid scale. IllegalArgumentException expected"); + } catch(IllegalArgumentException ex) { + } + } + + public void testWeibullDistributionPositiveZero() { + try { + factory.createWeibullDistribution(1.0, 0.0); + fail("invalid scale. IllegalArgumentException expected"); + } catch(IllegalArgumentException ex) { + } + } } diff --git a/src/test/org/apache/commons/math/distribution/WeibullDistributionTest.java b/src/test/org/apache/commons/math/distribution/WeibullDistributionTest.java new file mode 100644 index 000000000..5ba7249de --- /dev/null +++ b/src/test/org/apache/commons/math/distribution/WeibullDistributionTest.java @@ -0,0 +1,113 @@ +/* + * Copyright 2005 The Apache Software Foundation. + * + * Licensed 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.math.distribution; + +/** + * Test cases for WeibullDistribution. + * Extends ContinuousDistributionAbstractTest. See class javadoc for + * ContinuousDistributionAbstractTest for details. + * + * @version $Revision: 1.8 $ $Date: 2004-07-24 16:41:37 -0500 (Sat, 24 Jul 2004) $ + */ +public class WeibullDistributionTest extends ContinuousDistributionAbstractTest { + + /** + * Constructor for CauchyDistributionTest. + * @param arg0 + */ + public WeibullDistributionTest(String arg0) { + super(arg0); + } + + //-------------- Implementations for abstract methods ----------------------- + + /** Creates the default continuous distribution instance to use in tests. */ + public ContinuousDistribution makeDistribution() { + return DistributionFactory.newInstance().createWeibullDistribution(1.2, 2.1); + } + + /** Creates the default cumulative probability distribution test input values */ + public double[] makeCumulativeTestPoints() { + // quantiles computed using Mathematica + return new double[] {0.00664355181d, 0.04543282833d, 0.09811627374d, + 0.1767135246d, 0.3219468654d, 4.207902826d, 5.23968437d, + 6.232056007d, 7.497630467d, 10.51154969d}; + } + + /** Creates the default cumulative probability density test expected values */ + public double[] makeCumulativeTestValues() { + return new double[] {0.001d, 0.01d, 0.025d, 0.05d, 0.1d, 0.900d, 0.950d, + 0.975d, 0.990d, 0.999d}; + } + + //---------------------------- Additional test cases ------------------------- + + public void testInverseCumulativeProbabilityExtremes() throws Exception { + setInverseCumulativeTestPoints(new double[] {0.0, 1.0}); + setInverseCumulativeTestValues( + new double[] {0.0, Double.POSITIVE_INFINITY}); + verifyInverseCumulativeProbabilities(); + } + + public void testAlpha() { + WeibullDistribution distribution = (WeibullDistribution) getDistribution(); + double expected = Math.random(); + distribution.setShape(expected); + assertEquals(expected, distribution.getShape(), 0.0); + } + + public void testBeta() { + WeibullDistribution distribution = (WeibullDistribution) getDistribution(); + double expected = Math.random(); + distribution.setScale(expected); + assertEquals(expected, distribution.getScale(), 0.0); + } + + public void testSetAlpha() { + WeibullDistribution distribution = (WeibullDistribution) getDistribution(); + try { + distribution.setShape(0.0); + fail("Can not have 0.0 alpha."); + } catch (IllegalArgumentException ex) { + // success + } + + try { + distribution.setShape(-1.0); + fail("Can not have negative alpha."); + } catch (IllegalArgumentException ex) { + // success + } + } + + public void testSetBeta() { + WeibullDistribution distribution = (WeibullDistribution) getDistribution(); + try { + distribution.setScale(0.0); + fail("Can not have 0.0 beta."); + } catch (IllegalArgumentException ex) { + // success + } + + try { + distribution.setScale(-1.0); + fail("Can not have negative beta."); + } catch (IllegalArgumentException ex) { + // success + } + } +} diff --git a/xdocs/changes.xml b/xdocs/changes.xml index 8b11e7776..b3294c3f2 100644 --- a/xdocs/changes.xml +++ b/xdocs/changes.xml @@ -39,6 +39,9 @@ The type attribute can be add,update,fix,remove. + + Added Weibull distribution implementation. + Added Cauchy distribution implementation. diff --git a/xdocs/userguide/distribution.xml b/xdocs/userguide/distribution.xml index 0fd10ffbc..a953cb42a 100644 --- a/xdocs/userguide/distribution.xml +++ b/xdocs/userguide/distribution.xml @@ -63,6 +63,7 @@ BinomialDistribution binomial = factory.createBinomialDistribution(10, .75);Normal (Gaussian)createNormalDistribution

    Mean
    Standard Deviation
    PoissoncreatePoissonDistribution
    Mean
    tcreateTDistribution
    Degrees of freedom
    + WeibullcreateWeibullDistribution
    Shape
    Scale
    Location