00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include <GammaRV.h>
00035 #include <math.h>
00036 #include <string.h>
00037 #include <Vector.h>
00038 #include <classTags.h>
00039
00040 GammaRV::GammaRV(int passedTag,
00041 double passedMean,
00042 double passedStdv,
00043 double passedStartValue)
00044 :RandomVariable(passedTag, RANDOM_VARIABLE_gamma)
00045 {
00046 tag = passedTag ;
00047 k = (passedMean/passedStdv) * (passedMean/passedStdv);
00048 lambda = passedMean / (passedStdv*passedStdv);
00049 startValue = passedStartValue;
00050 }
00051 GammaRV::GammaRV(int passedTag,
00052 double passedParameter1,
00053 double passedParameter2,
00054 double passedParameter3,
00055 double passedParameter4,
00056 double passedStartValue)
00057 :RandomVariable(passedTag, RANDOM_VARIABLE_gamma)
00058 {
00059 tag = passedTag ;
00060 k = passedParameter1;
00061 lambda = passedParameter2;
00062 startValue = passedStartValue;
00063 }
00064 GammaRV::GammaRV(int passedTag,
00065 double passedMean,
00066 double passedStdv)
00067 :RandomVariable(passedTag, RANDOM_VARIABLE_gamma)
00068 {
00069 tag = passedTag ;
00070 k = (passedMean/passedStdv) * (passedMean/passedStdv);
00071 lambda = passedMean / (passedStdv*passedStdv);
00072 startValue = getMean();
00073 }
00074 GammaRV::GammaRV(int passedTag,
00075 double passedParameter1,
00076 double passedParameter2,
00077 double passedParameter3,
00078 double passedParameter4)
00079 :RandomVariable(passedTag, RANDOM_VARIABLE_gamma)
00080 {
00081 tag = passedTag ;
00082 k = passedParameter1;
00083 lambda = passedParameter2;
00084 startValue = getMean();
00085 }
00086
00087
00088 GammaRV::~GammaRV()
00089 {
00090 }
00091
00092
00093 void
00094 GammaRV::Print(OPS_Stream &s, int flag)
00095 {
00096 }
00097
00098
00099 double
00100 GammaRV::getPDFvalue(double rvValue)
00101 {
00102 double result;
00103 if ( 0.0 < rvValue ) {
00104 result = lambda*pow((lambda*rvValue),(k-1.0))*exp(-lambda*rvValue) / gammaFunction(k);
00105 }
00106 else {
00107 result = 0.0;
00108 }
00109 return result;
00110 }
00111
00112
00113 double
00114 GammaRV::getCDFvalue(double rvValue)
00115 {
00116 double result;
00117 if ( 0.0 < rvValue ) {
00118 result = incompleteGammaFunction(k,(lambda*rvValue));
00119 }
00120 else {
00121 result = 0.0;
00122 }
00123
00124 return result;
00125 }
00126
00127
00128 double
00129 GammaRV::getInverseCDFvalue(double probValue)
00130 {
00131 double result = 0.0;
00132
00133
00134
00135
00136
00137
00138
00139
00140 double tol = 0.000001;
00141 double x_old = getMean();
00142 double x_new;
00143 double f;
00144 double df;
00145 double h;
00146 double perturbed_f;
00147 for (int i=1; i<=100; i++ ) {
00148
00149 f = probValue - getCDFvalue(x_old);
00150
00151 h = getStdv()/200.0;
00152 perturbed_f = probValue - getCDFvalue(x_old+h);
00153
00154 df = ( perturbed_f - f ) / h;
00155
00156 x_new = x_old - f/df;
00157
00158 if (fabs(1.0-fabs(x_old/x_new)) < tol) {
00159 result = x_new;
00160 }
00161 else {
00162 if (i==100) {
00163 opserr << "WARNING: Did not converge to find inverse CDF!" << endln;
00164 result = 0.0;
00165 }
00166 else {
00167 x_old = x_new;
00168 }
00169 }
00170 }
00171 return result;
00172 }
00173
00174
00175 const char *
00176 GammaRV::getType()
00177 {
00178 return "GAMMA";
00179 }
00180
00181
00182 double
00183 GammaRV::getMean()
00184 {
00185 return k/lambda;
00186 }
00187
00188
00189
00190 double
00191 GammaRV::getStdv()
00192 {
00193 return sqrt(k)/lambda;
00194 }
00195
00196
00197 double
00198 GammaRV::getStartValue()
00199 {
00200 return startValue;
00201 }
00202
00203
00204
00205 double GammaRV::getParameter1() {return k;}
00206 double GammaRV::getParameter2() {return lambda;}
00207 double GammaRV::getParameter3() {opserr<<"No such parameter in r.v. #"<<tag<<endln; return 0.0;}
00208 double GammaRV::getParameter4() {opserr<<"No such parameter in r.v. #"<<tag<<endln; return 0.0;}
00209
00210
00211
00212
00213
00214 double
00215 GammaRV::gammaFunction(double x)
00216 {
00217 double res;
00218
00219 if (x==0 || ( x < 0.0 && floor(x)==x ) ) {
00220 opserr << "Invalid input to the gamma function" << endln;
00221 }
00222 else {
00223 Vector p(9);
00224 Vector q(9);
00225 Vector c(8);
00226
00227 p(0) = 0.0;
00228 p(1) = -1.71618513886549492533811e+0;
00229 p(2) = 2.47656508055759199108314e+1;
00230 p(3) = -3.79804256470945635097577e+2;
00231 p(4) = 6.29331155312818442661052e+2;
00232 p(5) = 8.66966202790413211295064e+2;
00233 p(6) = -3.14512729688483675254357e+4;
00234 p(7) = -3.61444134186911729807069e+4;
00235 p(8) = 6.64561438202405440627855e+4;
00236
00237 q(0) = 0.0;
00238 q(1) = -3.08402300119738975254353e+1;
00239 q(2) = 3.15350626979604161529144e+2;
00240 q(3) = -1.01515636749021914166146e+3;
00241 q(4) = -3.10777167157231109440444e+3;
00242 q(5) = 2.25381184209801510330112e+4;
00243 q(6) = 4.75584627752788110767815e+3;
00244 q(7) = -1.34659959864969306392456e+5;
00245 q(8) = -1.15132259675553483497211e+5;
00246
00247 c(0) = 0.0;
00248 c(1) = -1.910444077728e-03;
00249 c(2) = 8.4171387781295e-04;
00250 c(3) = -5.952379913043012e-04;
00251 c(4) = 7.93650793500350248e-04;
00252 c(5) = -2.777777777777681622553e-03;
00253 c(6) = 8.333333333333333331554247e-02;
00254 c(7) = 5.7083835261e-03;
00255
00256 double pi = 3.14159265358979;
00257 double y;
00258 double y1;
00259 double fact;
00260 double x1;
00261 double xn;
00262 double ysq;
00263 double sum;
00264 double spi;
00265 bool flag01 = false;
00266 bool flag1_12 = false;
00267 bool flagNegative = false;
00268
00269
00270 if (x<0.0) {
00271 y = -x;
00272 y1 = floor(y);
00273 res = y - y1;
00274 fact = -pi / sin(pi*res) * (1 - 2*fmod(y1,2));
00275 x = y + 1;
00276 flagNegative = true;
00277 }
00278
00279
00280
00281 if (x<1.0) {
00282 x1 = x;
00283 x = x1 + 1.0;
00284 flag01 = true;
00285 }
00286
00287
00288 if (x<12.0) {
00289 xn = floor(x) - 1;
00290 x = x - xn;
00291
00292 double z = x - 1.0;
00293 double xnum = 0.0;
00294 double xden = xnum + 1.0;
00295
00296
00297 for (int i = 1 ; i<=8; i++ ) {
00298 xnum = (xnum + p(i)) * z;
00299 xden = xden * z + q(i);
00300 }
00301
00302 res = xnum / xden + 1.0;
00303 flag1_12 = true;
00304 }
00305
00306
00307 if (flag01) {
00308 res = res / x1;
00309 }
00310 else if (flag1_12){
00311 double max_xn = xn;
00312 for (int m=1; m<=max_xn; m++) {
00313 res = res * x;
00314 x = x + 1;
00315 xn = xn - 1;
00316 }
00317 }
00318
00319
00320 if (x>=12.0) {
00321 y = x;
00322 ysq = y * y;
00323 sum = c(7);
00324 for (int i = 1; i<=6; i++ ) {
00325 sum = sum / ysq + c(i);
00326 }
00327
00328 spi = 0.9189385332046727417803297;
00329 sum = sum / y - y + spi;
00330 sum = sum + (y-0.5)*log(y);
00331 res = exp(sum);
00332 }
00333
00334 if (flagNegative) {
00335 res = fact / res;
00336 }
00337 }
00338
00339 return res;
00340 }
00341
00342
00343
00344 double
00345 GammaRV::incompleteGammaFunction(double x, double a)
00346 {
00347 double gam = log(gammaFunction(a));
00348 double b = x;
00349 if (x==0.0) {
00350 b = 0.0;
00351 }
00352 if (a==0.0) {
00353 b = 1.0;
00354 }
00355
00356 if (a!=0.0 && x!=0.0 && x<a+1.0) {
00357 double ap = a;
00358 double sum = 1.0/ap;
00359 double del = sum;
00360 while (fabs(del) >= 1.0e-10*fabs(sum)) {
00361 ap = ap + 1.0;
00362 del = x * del / ap;
00363 sum = sum + del;
00364 }
00365 b = sum * exp(-x + a*log(x) - gam);
00366 }
00367
00368
00369 if ((a != 0) && (x != 0) && (x >= a+1.0)) {
00370 double a0 = 1.0;
00371 double a1 = x;
00372 double b0 = 0.0;
00373 double b1 = a0;
00374 double fac = 1.0;
00375 double n = 1;
00376 double g = b1;
00377 double gold = b0;
00378 while (fabs(g-gold) >= 1.0e-10*fabs(g)) {
00379 gold = g;
00380 double ana = n - a;
00381 a0 = (a1 + a0 *ana) * fac;
00382 b0 = (b1 + b0 *ana) * fac;
00383 double anf = n*fac;
00384 a1 = x * a0 + anf * a1;
00385 b1 = x * b0 + anf * b1;
00386 fac = 1.0 / a1;
00387 g = b1 * fac;
00388 n = n + 1.0;
00389 }
00390 b = 1 - exp(-x + a*log(x) - gam) * g;
00391 }
00392
00393 return b;
00394 }