001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018 package org.apache.commons.math.distribution; 019 020 import java.io.Serializable; 021 022 import org.apache.commons.math.MathRuntimeException; 023 024 /** 025 * Default implementation of 026 * {@link org.apache.commons.math.distribution.WeibullDistribution}. 027 * 028 * @since 1.1 029 * @version $Revision: 925812 $ $Date: 2010-03-21 11:49:31 -0400 (Sun, 21 Mar 2010) $ 030 */ 031 public class WeibullDistributionImpl extends AbstractContinuousDistribution 032 implements WeibullDistribution, Serializable { 033 034 /** 035 * Default inverse cumulative probability accuracy 036 * @since 2.1 037 */ 038 public static final double DEFAULT_INVERSE_ABSOLUTE_ACCURACY = 1e-9; 039 040 /** Serializable version identifier */ 041 private static final long serialVersionUID = 8589540077390120676L; 042 043 /** The shape parameter. */ 044 private double shape; 045 046 /** The scale parameter. */ 047 private double scale; 048 049 /** Inverse cumulative probability accuracy */ 050 private final double solverAbsoluteAccuracy; 051 052 /** 053 * Creates weibull distribution with the given shape and scale and a 054 * location equal to zero. 055 * @param alpha the shape parameter. 056 * @param beta the scale parameter. 057 */ 058 public WeibullDistributionImpl(double alpha, double beta){ 059 this(alpha, beta, DEFAULT_INVERSE_ABSOLUTE_ACCURACY); 060 } 061 062 /** 063 * Creates weibull distribution with the given shape, scale and inverse 064 * cumulative probability accuracy and a location equal to zero. 065 * @param alpha the shape parameter. 066 * @param beta the scale parameter. 067 * @param inverseCumAccuracy the maximum absolute error in inverse cumulative probability estimates 068 * (defaults to {@link #DEFAULT_INVERSE_ABSOLUTE_ACCURACY}) 069 * @since 2.1 070 */ 071 public WeibullDistributionImpl(double alpha, double beta, double inverseCumAccuracy){ 072 super(); 073 setShapeInternal(alpha); 074 setScaleInternal(beta); 075 solverAbsoluteAccuracy = inverseCumAccuracy; 076 } 077 078 /** 079 * For this distribution, X, this method returns P(X < <code>x</code>). 080 * @param x the value at which the CDF is evaluated. 081 * @return CDF evaluted at <code>x</code>. 082 */ 083 public double cumulativeProbability(double x) { 084 double ret; 085 if (x <= 0.0) { 086 ret = 0.0; 087 } else { 088 ret = 1.0 - Math.exp(-Math.pow(x / scale, shape)); 089 } 090 return ret; 091 } 092 093 /** 094 * Access the shape parameter. 095 * @return the shape parameter. 096 */ 097 public double getShape() { 098 return shape; 099 } 100 101 /** 102 * Access the scale parameter. 103 * @return the scale parameter. 104 */ 105 public double getScale() { 106 return scale; 107 } 108 109 /** 110 * Returns the probability density for a particular point. 111 * 112 * @param x The point at which the density should be computed. 113 * @return The pdf at point x. 114 * @since 2.1 115 */ 116 @Override 117 public double density(double x) { 118 if (x < 0) { 119 return 0; 120 } 121 122 final double xscale = x / scale; 123 final double xscalepow = Math.pow(xscale, shape - 1); 124 125 /* 126 * Math.pow(x / scale, shape) = 127 * Math.pow(xscale, shape) = 128 * Math.pow(xscale, shape - 1) * xscale 129 */ 130 final double xscalepowshape = xscalepow * xscale; 131 132 return (shape / scale) * xscalepow * Math.exp(-xscalepowshape); 133 } 134 135 /** 136 * For this distribution, X, this method returns the critical point x, such 137 * that P(X < x) = <code>p</code>. 138 * <p> 139 * Returns <code>Double.NEGATIVE_INFINITY</code> for p=0 and 140 * <code>Double.POSITIVE_INFINITY</code> for p=1.</p> 141 * 142 * @param p the desired probability 143 * @return x, such that P(X < x) = <code>p</code> 144 * @throws IllegalArgumentException if <code>p</code> is not a valid 145 * probability. 146 */ 147 @Override 148 public double inverseCumulativeProbability(double p) { 149 double ret; 150 if (p < 0.0 || p > 1.0) { 151 throw MathRuntimeException.createIllegalArgumentException( 152 "{0} out of [{1}, {2}] range", p, 0.0, 1.0); 153 } else if (p == 0) { 154 ret = 0.0; 155 } else if (p == 1) { 156 ret = Double.POSITIVE_INFINITY; 157 } else { 158 ret = scale * Math.pow(-Math.log(1.0 - p), 1.0 / shape); 159 } 160 return ret; 161 } 162 163 /** 164 * Modify the shape parameter. 165 * @param alpha the new shape parameter value. 166 * @deprecated as of 2.1 (class will become immutable in 3.0) 167 */ 168 @Deprecated 169 public void setShape(double alpha) { 170 setShapeInternal(alpha); 171 } 172 /** 173 * Modify the shape parameter. 174 * @param alpha the new shape parameter value. 175 */ 176 private void setShapeInternal(double alpha) { 177 if (alpha <= 0.0) { 178 throw MathRuntimeException.createIllegalArgumentException( 179 "shape must be positive ({0})", 180 alpha); 181 } 182 this.shape = alpha; 183 } 184 185 /** 186 * Modify the scale parameter. 187 * @param beta the new scale parameter value. 188 * @deprecated as of 2.1 (class will become immutable in 3.0) 189 */ 190 @Deprecated 191 public void setScale(double beta) { 192 setScaleInternal(beta); 193 } 194 /** 195 * Modify the scale parameter. 196 * @param beta the new scale parameter value. 197 */ 198 private void setScaleInternal(double beta) { 199 if (beta <= 0.0) { 200 throw MathRuntimeException.createIllegalArgumentException( 201 "scale must be positive ({0})", 202 beta); 203 } 204 this.scale = beta; 205 } 206 207 /** 208 * Access the domain value lower bound, based on <code>p</code>, used to 209 * bracket a CDF root. This method is used by 210 * {@link #inverseCumulativeProbability(double)} to find critical values. 211 * 212 * @param p the desired probability for the critical value 213 * @return domain value lower bound, i.e. 214 * P(X < <i>lower bound</i>) < <code>p</code> 215 */ 216 @Override 217 protected double getDomainLowerBound(double p) { 218 return 0.0; 219 } 220 221 /** 222 * Access the domain value upper bound, based on <code>p</code>, used to 223 * bracket a CDF root. This method is used by 224 * {@link #inverseCumulativeProbability(double)} to find critical values. 225 * 226 * @param p the desired probability for the critical value 227 * @return domain value upper bound, i.e. 228 * P(X < <i>upper bound</i>) > <code>p</code> 229 */ 230 @Override 231 protected double getDomainUpperBound(double p) { 232 return Double.MAX_VALUE; 233 } 234 235 /** 236 * Access the initial domain value, based on <code>p</code>, used to 237 * bracket a CDF root. This method is used by 238 * {@link #inverseCumulativeProbability(double)} to find critical values. 239 * 240 * @param p the desired probability for the critical value 241 * @return initial domain value 242 */ 243 @Override 244 protected double getInitialDomain(double p) { 245 // use median 246 return Math.pow(scale * Math.log(2.0), 1.0 / shape); 247 } 248 249 /** 250 * Return the absolute accuracy setting of the solver used to estimate 251 * inverse cumulative probabilities. 252 * 253 * @return the solver absolute accuracy 254 * @since 2.1 255 */ 256 @Override 257 protected double getSolverAbsoluteAccuracy() { 258 return solverAbsoluteAccuracy; 259 } 260 }