00001
00011 #include <stdlib.h>
00012 #include <math.h>
00013 #include <errno.h>
00014 #include <string.h>
00015 #include <stdarg.h>
00016 #include <time.h>
00017 #include <float.h>
00018 #include "random.h"
00019 #include "find.h"
00020 #include "output.h"
00021 #include "exception.h"
00022
00023 #ifdef WIN32
00024 #define finite _finite
00025 #endif
00026
00027 #define QNAN sqrt(-1)
00028
00029 int random_init(void)
00030 {
00031
00032 srand((unsigned int)time(NULL));
00033 return 1;
00034 }
00035
00038 RANDOMTYPE random_type(char *name)
00039 {
00040 struct {
00041 char *name;
00042 RANDOMTYPE type;
00043 } *p, map[] = {
00044 {"degenerate", RT_DEGENERATE},
00045 {"uniform",RT_UNIFORM},
00046 {"normal",RT_NORMAL},
00047 {"bernoulli",RT_BERNOULLI},
00048 {"sampled",RT_SAMPLED},
00049 {"pareto",RT_PARETO},
00050 {"lognormal",RT_LOGNORMAL},
00051 {"exponential",RT_EXPONENTIAL},
00053 };
00054 for (p=map; p<map+sizeof(map)/sizeof(map[0]); p++)
00055 {
00056 if (strcmp(p->name,name)==0)
00057 return p->type;
00058 }
00059 return RT_INVALID;
00060 }
00061
00062
00063 double randunit(void)
00064 {
00065 double u = rand()/(RAND_MAX+1.0);
00066 if (u<1) return u;
00067 return randunit();
00068 }
00069
00076 double random_degenerate(double a)
00077 {
00078
00079 double aa = fabs(a);
00080 if (a!=0 && (aa<1e-30 || aa>1e30))
00081 output_warning("random_degenerate(a=%g): a is outside normal bounds of +/-1e(+/-30)", a);
00082 return a;
00083 }
00084
00098 double random_uniform(double a,
00099 double b)
00100 {
00101
00102 double aa=fabs(a), ab=fabs(b);
00103 if (a!=0 && (aa<1e-30 || aa>1e30))
00104 output_warning("random_uniform(a=%g, b=%g): a is outside normal bounds of +/-1e(+/-30)", a, b);
00105 if (b!=0 && (ab<1e-30 || ab>1e30))
00106 output_warning("random_uniform(a=%g, b=%g): b is outside normal bounds of +/-1e(+/-30)", a, b);
00107 if (b<a)
00108 output_warning("random_uniform(a=%g, b=%g): b is less than a", a, b);
00109 return randunit()*(b-a)+a;
00110 }
00111
00133 double random_normal(double m,
00134 double s)
00135 {
00136
00137 double r=randunit();
00138 if (s<0)
00139 output_warning("random_normal(m=%g, s=%g): s is negative", m, s);
00140 while (r<=0 || r>1)
00141 r=randunit();
00142 return sqrt(-2*log(r)) * sin(2*PI*randunit())*s+m;
00143 }
00144
00152 double random_bernoulli(double p)
00153 {
00154 double ap = fabs(p);
00155 if (ap!=0 && (ap<1e-30 || ap>1e30))
00156 output_warning("random_bernoulli(p=%g): p is not within the normal bounds of +/-1e(+/-30)", p);
00157 if (p<0 || p>1)
00158 output_warning("random_bernoulli(p=%g): p is not between 0 and 1", p);
00159
00160 return (p>=randunit()) ? 1 : 0;
00161 }
00162
00171 double random_sampled(unsigned n,
00172 double *x)
00173 {
00174 if (n>0)
00175 {
00176 double v = x[(unsigned)(randunit()*n)];
00177 double av = fabs(v);
00178 if (v!=0 && (v<1e-30 || v>1e30))
00179 output_warning("random_sampled(n=%d,...): sampled value is not within normal bounds of +/-1e(+/-30)",n);
00180 return v;
00181 }
00182 else
00183 {
00184 throw_exception("random_sampled(n=%d,...): n must be a positive number", n);
00185 return QNAN;
00186 }
00187 }
00188
00189
00198 double random_pareto(double m,
00199 double k)
00200 {
00201 double am = fabs(m);
00202 double ak = fabs(k);
00203 double r = randunit();
00204 if (am!=0 && (am<1e-03 || am>1e30))
00205 output_warning("random_pareto(m=%g, k=%g): m is not within the normal bounds of +/-1e(+/-30)", m, k);
00206 if (ak>1e30)
00207 output_warning("random_pareto(m=%g, k=%g): k is not within the normal bounds of +/-1e(+/-30)", m, k);
00208 if (k<=0)
00209 throw_exception("random_pareto(m=%g, k=%g): k must be greater than 1", m, k);
00210 while (r<=0 || r>=1)
00211 r = randunit();
00212 return m*pow(r,-1/k);
00213 }
00214
00220 double random_lognormal(double gmu,
00221 double gsigma)
00222 {
00223 return exp(random_normal(0,1)*gsigma+gmu);
00224 }
00225
00237 double random_exponential(double lambda)
00238 {
00239 double r=randunit();
00240 if (lambda<=0)
00241 throw_exception("random_exponential(l=%g): l must be greater than 0", lambda);
00242 if (lambda<1e-30 || lambda>1e30)
00243 output_warning("random_exponential(l=%g): l is not within the normal bounds of 1e(+/-30)", lambda);
00244 while (r<=0 || r>=1)
00245 r=randunit();
00246 return -log(r)/lambda;
00247 }
00248
00249
00250 static double _random_value(RANDOMTYPE type, va_list ptr)
00251 {
00252 switch (type) {
00253 case RT_DEGENERATE:
00254 return random_degenerate(va_arg(ptr,double));
00255 case RT_UNIFORM:
00256 { double min = va_arg(ptr,double);
00257 double max = va_arg(ptr,double);
00258 return random_normal(min,max);
00259 }
00260 case RT_NORMAL:
00261 { double mu = va_arg(ptr,double);
00262 double sigma = va_arg(ptr,double);
00263 return random_normal(mu,sigma);
00264 }
00265 case RT_BERNOULLI:
00266 return random_bernoulli(va_arg(ptr,double));
00267 case RT_SAMPLED:
00268 { unsigned n_samples = va_arg(ptr,unsigned);
00269 double *samples = va_arg(ptr,double*);
00270 return random_sampled(n_samples,samples);
00271 }
00272 case RT_PARETO:
00273 { double base = va_arg(ptr,double);
00274 double gamma = va_arg(ptr,double);
00275 return random_pareto(base,gamma);
00276 }
00277 case RT_LOGNORMAL:
00278 { double gmu = va_arg(ptr,double);
00279 double gsigma = va_arg(ptr,double);
00280 return random_lognormal(gmu,gsigma);
00281 }
00282 case RT_EXPONENTIAL:
00283 { double lambda = va_arg(ptr,double);
00284 return random_exponential(lambda);
00285 }
00286 default:
00287 throw_exception("_random_value(type=%d,...); type is not valid",type);
00288 }
00289 return QNAN;
00290 }
00291
00295 int random_apply(char *group_expression,
00296 char *property,
00297 RANDOMTYPE type,
00298 ...)
00299 {
00300 FINDLIST *list = find_objects(FL_GROUP, group_expression);
00301 OBJECT *obj;
00302 unsigned count=0;
00303 va_list ptr;
00304 va_start(ptr,type);
00305 for (obj=find_first(list); obj!=NULL; find_next(list,obj))
00306 {
00307
00308 object_set_double_by_name(obj,property,_random_value(type,ptr));
00309 count++;
00310 }
00311 va_end(ptr);
00312 return count;
00313 }
00314
00318 double random_value(RANDOMTYPE type,
00319 ...)
00320 {
00321 double x;
00322 va_list ptr;
00323 va_start(ptr,type);
00324 x = _random_value(type,ptr);
00325 va_end(ptr);
00326 return x;
00327 }
00328
00329
00330 static double mean(double sample[], unsigned int count)
00331 {
00332 double sum=0;
00333 unsigned int i;
00334 for (i=0; i<count; i++)
00335 sum += sample[i];
00336 return sum/count;
00337 }
00338 #ifdef min
00339 #undef min
00340 #endif
00341 static double min(double sample[], unsigned int count)
00342 {
00343 double min;
00344 unsigned int i;
00345 for (i=0; i<count; i++)
00346 {
00347 if (i==0) min=sample[0];
00348 else if (sample[i]<min) min=sample[i];
00349 }
00350 return min;
00351 }
00352 #ifdef max
00353 #undef max
00354 #endif
00355 static double max(double sample[], unsigned int count)
00356 {
00357 double max;
00358 unsigned int i;
00359 for (i=0; i<count; i++)
00360 {
00361 if (i==0) max=sample[0];
00362 else if (sample[i]>max) max=sample[i];
00363 }
00364 return max;
00365 }
00366 static double stdev(double sample[], unsigned int count)
00367 {
00368 double sum=0, mean=0;
00369 unsigned int n = 0, i;
00370 for (i=0; i<count; i++)
00371 {
00372 double delta = sample[i] - mean;
00373 n++;
00374 mean += delta/n;
00375 sum += delta*(sample[i]-mean);
00376 }
00377 return sqrt(sum/(n-1));
00378 }
00379 static void sort(double sample[], unsigned int count)
00380 {
00381 }
00382 static void report(char *parameter, double actual, double expected)
00383 {
00384 if (parameter==NULL)
00385 {
00386 output_test(" Parameter Actual Expected Error");
00387 output_test("---------------- ---------- ---------- ----------");
00388 }
00389 else
00390 {
00391 if (expected==0)
00392 output_test("%-16.16s %10.4f %10.4f %9.6f ", parameter,actual,expected,actual-expected);
00393 else
00394 output_test("%-16.16s %10.4f %10.4f %9.6f%%", parameter,actual,expected,(actual-expected)/expected*100);
00395 }
00396 }
00397
00404 int random_test(void)
00405 {
00406 static double sample[1000000];
00407 double a, b;
00408 unsigned int count = sizeof(sample)/sizeof(sample[0]);
00409 unsigned int i;
00410
00411
00412 a = 10*randunit()/2-5;
00413 output_test("\ndegenerate(x=%g)",a);
00414 for (i=0; i<count; i++)
00415 {
00416 sample[i] = random_degenerate(a);
00417 if (!finite(sample[i]))
00418 output_test("Sample %d is not a finite number!",i--);
00419 }
00420 report(NULL,0,0);
00421 report("Mean",mean(sample,count),a);
00422 report("Stdev",stdev(sample,count),0);
00423 report("Min",min(sample,count),a);
00424 report("Max",max(sample,count),a);
00425
00426
00427 a = 10*randunit()/2;
00428 b = 10*randunit()/2 + 5;
00429 output_test("\nuniform(min=%g, max=%g)",a,b);
00430 for (i=0; i<count; i++)
00431 {
00432 sample[i] = random_uniform(a,b);
00433 if (!finite(sample[i]))
00434 output_test("Sample %d is not a finite number!",i--);
00435 }
00436 report(NULL,0,0);
00437 report("Mean",mean(sample,count),(a+b)/2);
00438 report("Stdev",stdev(sample,count),sqrt((b-a)*(b-a)/12));
00439 report("Min",min(sample,count),a);
00440 report("Max",max(sample,count),b);
00441
00442
00443 a = randunit();
00444 output_test("\nBernoulli(prob=%g)",a);
00445 for (i=0; i<count; i++)
00446 {
00447 sample[i] = random_bernoulli(a);
00448 if (!finite(sample[i]))
00449 output_test("Sample %d is not a finite number!",i--);
00450 }
00451 report(NULL,0,0);
00452 report("Mean",mean(sample,count),a);
00453 report("Stdev",stdev(sample,count),sqrt(a*(1-a)));
00454 report("Min",min(sample,count),0);
00455 report("Max",max(sample,count),1);
00456
00457
00458 a = 20*randunit()-5;
00459 b = 5*randunit();
00460 output_test("\nnormal(mean=%g, stdev=%g)",a,b);
00461 for (i=0; i<count; i++)
00462 {
00463 sample[i] = random_normal(a,b);
00464 if (!finite(sample[i]))
00465 output_test("Sample %d is not a finite number!",i--);
00466 }
00467 report(NULL,0,0);
00468 report("Mean",mean(sample,count),a);
00469 report("Stdev",stdev(sample,count),b);
00470
00471
00472 a = 1/randunit()-1;
00473 output_test("\nexponential(lambda=%g)",a);
00474 for (i=0; i<count; i++)
00475 {
00476 sample[i] = random_exponential(a);
00477 if (!finite(sample[i]))
00478 output_test("Sample %d is not a finite number!",i--);
00479 }
00480 report(NULL,0,0);
00481 report("Mean",mean(sample,count),1/a);
00482 report("Stdev",stdev(sample,count),1/a);
00483 report("Min",min(sample,count),0);
00484
00485
00486 a = 2*randunit()-1;
00487 b = 2*randunit();
00488 output_test("\nlognormal(gmean=%g, gstdev=%g)",a,b);
00489 for (i=0; i<count; i++)
00490 {
00491 sample[i] = random_lognormal(a,b);
00492 if (!finite(sample[i]))
00493 output_test("Sample %d is not a finite number!",i--);
00494 }
00495 report(NULL,0,0);
00496 report("Mean",mean(sample,count),exp(a+b*b/2));
00497 report("Stdev",stdev(sample,count),sqrt((exp(b*b)-1)*exp(2*a+b*b)));
00498 report("Min",min(sample,count),0);
00499
00500
00501 a = 10*randunit();
00502 b = randunit()*2+2;
00503 output_test("\nPareto(base=%g, gamma=%g)",a,b);
00504 for (i=0; i<count; i++)
00505 {
00506 sample[i] = random_pareto(a,b);
00507 if (!finite(sample[i]))
00508 output_test("Sample %d is not a finite number!",i--);
00509 }
00510 report(NULL,0,0);
00511 report("Mean",mean(sample,count),b*a/(b-1));
00512 report("Stdev",stdev(sample,count),sqrt(a*a*b/((b-1)*(b-1)*(b-2))));
00513 report("Min",min(sample,count),a);
00514
00515
00516 output_test("\nSampled(count=10, sample=[0..9])");
00517 for (i=0; i<count; i++)
00518 {
00519 double set[10]={0,1,2,3,4,5,6,7,8,9};
00520 sample[i] = random_sampled(10,set);
00521 if (!finite(sample[i]))
00522 output_test("Sample %d is not a finite number!",i--);
00523 }
00524 report(NULL,0,0);
00525 report("Mean",mean(sample,count),4.5);
00526
00527 report("Stdev",stdev(sample,count),sqrt(99/12));
00528 report("Min",min(sample,count),0);
00529 report("Max",max(sample,count),9);
00530
00531 output_warning("random_test() not implemented yet");
00532 return 0;
00533 }
00534