BetaRV.cpp

Go to the documentation of this file.
00001 /* ****************************************************************** **
00002 **    OpenSees - Open System for Earthquake Engineering Simulation    **
00003 **          Pacific Earthquake Engineering Research Center            **
00004 **                                                                    **
00005 **                                                                    **
00006 ** (C) Copyright 2001, The Regents of the University of California    **
00007 ** All Rights Reserved.                                               **
00008 **                                                                    **
00009 ** Commercial use of this program without express permission of the   **
00010 ** University of California, Berkeley, is strictly prohibited.  See   **
00011 ** file 'COPYRIGHT'  in main directory for information on usage and   **
00012 ** redistribution,  and for a DISCLAIMER OF ALL WARRANTIES.           **
00013 **                                                                    **
00014 ** Developed by:                                                      **
00015 **   Frank McKenna (fmckenna@ce.berkeley.edu)                         **
00016 **   Gregory L. Fenves (fenves@ce.berkeley.edu)                       **
00017 **   Filip C. Filippou (filippou@ce.berkeley.edu)                     **
00018 **                                                                    **
00019 ** Reliability module developed by:                                   **
00020 **   Terje Haukaas (haukaas@ce.berkeley.edu)                          **
00021 **   Armen Der Kiureghian (adk@ce.berkeley.edu)                       **
00022 **                                                                    **
00023 ** ****************************************************************** */
00024                                                                         
00025 // $Revision: 1.6 $
00026 // $Date: 2003/03/04 00:44:33 $
00027 // $Source: /usr/local/cvs/OpenSees/SRC/reliability/domain/distributions/BetaRV.cpp,v $
00028 
00029 
00030 //
00031 // Written by Terje Haukaas (haukaas@ce.berkeley.edu) 
00032 //
00033 
00034 #include <BetaRV.h>
00035 #include <GammaRV.h>
00036 #include <math.h>
00037 #include <string.h>
00038 #include <classTags.h>
00039 #include <OPS_Globals.h>
00040 
00041 BetaRV::BetaRV(int passedTag, 
00042                  double passedParameter1,
00043                  double passedParameter2,
00044                  double passedParameter3,
00045                  double passedParameter4,
00046                  double passedStartValue)
00047 :RandomVariable(passedTag, RANDOM_VARIABLE_beta)
00048 {
00049         tag = passedTag ;
00050         a = passedParameter1;
00051         b = passedParameter2;
00052         q = passedParameter3;
00053         r = passedParameter4;
00054         startValue = passedStartValue;
00055 }
00056 BetaRV::BetaRV(int passedTag, 
00057                  double passedParameter1,
00058                  double passedParameter2,
00059                  double passedParameter3,
00060                  double passedParameter4)
00061 :RandomVariable(passedTag, RANDOM_VARIABLE_beta)
00062 {
00063         tag = passedTag ;
00064         a = passedParameter1;
00065         b = passedParameter2;
00066         q = passedParameter3;
00067         r = passedParameter4;
00068         startValue = getMean();
00069 }
00070 
00071 
00072 BetaRV::~BetaRV()
00073 {
00074 }
00075 
00076 
00077 void
00078 BetaRV::Print(OPS_Stream &s, int flag)
00079 {
00080 }
00081 
00082 
00083 double
00084 BetaRV::getPDFvalue(double rvValue)
00085 {
00086         double result;
00087         if ( a <= rvValue && rvValue <= b ) {
00088                 double par1 = pow(rvValue-a,q-1.0);
00089                 double par2 = pow(b-rvValue,r-1.0);
00090                 double par3 = betaFunction(q,r);
00091                 double par4 = pow(b-a,q+r-1.0);
00092                 result = par1*par2/(par3*par4);
00093         }
00094         else {
00095                 result = 0.0;
00096         }
00097         return result;
00098 }
00099 
00100 
00101 double
00102 BetaRV::getCDFvalue(double rvValue)
00103 {
00104 
00105         double result = 0.0;
00106 
00107         if ( a < rvValue && rvValue < b ) {
00108                 // There exists no closed form expression for the Beta CDF.
00109                 // In this preliminary implementation of the Beta random variable,
00110                 // numerical integration - using Simpsons rule - is employed.
00111                 // The aim is to integrate the PDF from 'a' to 'rvValue'.
00112                 int n_2 = 100; // Half the number of intervals
00113                 double h = rvValue-a;
00114                 double fa = getPDFvalue(a);
00115                 double fb = getPDFvalue(rvValue);
00116                 double sum_fx2j = 0.0;
00117                 double sum_fx2j_1 = 0.0;
00118                 for (int j=1;  j<=n_2;  j++) {
00119                         sum_fx2j = sum_fx2j + getPDFvalue(   (double) (a+(j*2)*h/(2*n_2))   );
00120                         sum_fx2j_1 = sum_fx2j_1 + getPDFvalue(   (double)(a+(j*2-1)*h/(2*n_2))   );
00121                 }
00122                 sum_fx2j = sum_fx2j - getPDFvalue((double)(rvValue));
00123                 result = h/(2*n_2)/3.0*(fa + 2.0*sum_fx2j + 4.0*sum_fx2j_1 + fb);
00124         }
00125         else if (rvValue<=a) {
00126                 result = 0.0;
00127         }
00128         else {
00129                 result = 1.0;
00130         }
00131 
00132         return result;
00133 }
00134 
00135 
00136 double
00137 BetaRV::getInverseCDFvalue(double probValue)
00138 {
00139         double result = 0.0;
00140         // Here we want to solve the nonlinear equation:
00141         //         probValue = getCDFvalue(x)
00142         // with respect to x. 
00143         // A Newton scheme to find roots - f(x)=0 - looks something like:
00144         //         x(i+1) = x(i) - f(xi)/f'(xi)
00145         // In our case the function f(x) is: f(x) = probValue - getCDFvalue(x)
00146         // The derivative of the function can be found approximately by a
00147         // finite difference scheme where e.g. stdv/200 is used as perturbation.
00148         double tol = 0.000001;
00149         double x_old = getMean();   // Start at the mean of the random variable
00150         double x_new;
00151         double f;
00152         double df;
00153         double h;
00154         double perturbed_f;
00155         for (int i=1;  i<=100;  i++ )  {
00156 
00157                 // Evaluate function
00158                 f = probValue - getCDFvalue(x_old);
00159                 // Evaluate perturbed function
00160                 h = getStdv()/200.0;
00161                 perturbed_f = probValue - getCDFvalue(x_old+h);
00162 
00163                 // Evaluate derivative of function
00164                 df = ( perturbed_f - f ) / h;
00165 
00166                 if ( fabs(df) < 1.0e-15) {
00167                         opserr << "WARNING: BetaRV::getInverseCDFvalue() -- zero derivative " << endln
00168                                 << " in Newton algorithm. " << endln;
00169                 }
00170                 else {
00171 
00172                         // Take a Newton step
00173                         x_new = x_old - f/df;
00174                         
00175                         // Check convergence; quit or continue
00176                         if (fabs(1.0-fabs(x_old/x_new)) < tol) {
00177                                 return x_new;
00178                         }
00179                         else {
00180                                 if (i==100) {
00181                                         opserr << "WARNING: Did not converge to find inverse CDF!" << endln;
00182                                         return 0.0;
00183                                 }
00184                                 else {
00185                                         x_old = x_new;
00186                                 }
00187                         
00188                         }
00189                 }
00190         }
00191 
00192         return result;
00193 }
00194 
00195 
00196 const char *
00197 BetaRV::getType()
00198 {
00199         return "BETA";
00200 }
00201 
00202 
00203 double 
00204 BetaRV::getMean()
00205 {
00206         return (a*r+b*q)/(q+r);
00207 }
00208 
00209 
00210 
00211 double 
00212 BetaRV::getStdv()
00213 {
00214         return ((b-a)/(q+r)) * sqrt(q*r/(q+r+1));
00215 }
00216 
00217 
00218 double 
00219 BetaRV::getStartValue()
00220 {
00221         return startValue;
00222 }
00223 
00224 double BetaRV::getParameter1()  {return a;}
00225 double BetaRV::getParameter2()  {return b;}
00226 double BetaRV::getParameter3()  {return q;}
00227 double BetaRV::getParameter4()  {return r;}
00228 
00229 
00230 
00231 double 
00232 BetaRV::betaFunction(double q, double r)
00233 {
00234 /*      OLD CODE: 
00235         GammaRV *aGammaRV = new GammaRV(1, 0.0, 1.0, 0.0);
00236         double par1,par2,par3;
00237         par1 = aGammaRV->gammaFunction(q);
00238         par2 = aGammaRV->gammaFunction(q);
00239         par3 = aGammaRV->gammaFunction(q+r);
00240         delete aGammaRV;
00241         return par1*par2/par3;
00242 */
00243 
00244         // Matlab definition of the beta function:
00245         //    y = exp(gammaln(q)+gammaln(r)-gammaln(q+r));
00246         //    ... where gammaln(.) = ln(gamma(.))
00247         // So, try this instead:
00248         GammaRV *aGammaRV = new GammaRV(1, 0.0, 1.0, 0.0);
00249         double gammaq,gammar,gammaqpr;
00250         gammaq = aGammaRV->gammaFunction(q);
00251         gammar = aGammaRV->gammaFunction(r);
00252         gammaqpr = aGammaRV->gammaFunction(q+r);
00253         delete aGammaRV;
00254         double loggammaq,loggammar,loggammaqpr;
00255         loggammaq = log(gammaq);
00256         loggammar = log(gammar);
00257         loggammaqpr = log(gammaqpr);
00258         return exp(loggammaq+loggammar-loggammaqpr);
00259 }

Generated on Mon Oct 23 15:05:26 2006 for OpenSees by doxygen 1.5.0