00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef lint
00020 static const char rcsid[] =
00021 "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/tools/ranvar.cc,v 1.18 2002/03/19 07:10:16 ddutta Exp $ (Xerox)";
00022 #endif
00023
00024 #include <stdio.h>
00025 #include "ranvar.h"
00026
00027 RandomVariable::RandomVariable()
00028 {
00029 rng_ = RNG::defaultrng();
00030 }
00031
00032 int RandomVariable::command(int argc, const char*const* argv)
00033 {
00034 Tcl& tcl = Tcl::instance();
00035
00036 if (argc == 2) {
00037 if (strcmp(argv[1], "value") == 0) {
00038 tcl.resultf("%6e", value());
00039 return(TCL_OK);
00040 }
00041 }
00042 if (argc == 3) {
00043 if (strcmp(argv[1], "use-rng") == 0) {
00044 rng_ = (RNG*)TclObject::lookup(argv[2]);
00045 if (rng_ == 0) {
00046 tcl.resultf("no such RNG %s", argv[2]);
00047 return(TCL_ERROR);
00048 }
00049 return(TCL_OK);
00050 }
00051 }
00052 return(TclObject::command(argc, argv));
00053 }
00054
00055
00056
00057
00058
00059
00060 int RandomVariable::seed(char *x){
00061
00062 Tcl& tcl = Tcl::instance();
00063
00064 rng_ = (RNG*)TclObject::lookup(x);
00065 if (rng_ == 0) {
00066 tcl.resultf("no such RNG %s", x);
00067 return(TCL_ERROR);
00068 }
00069 return(TCL_OK);
00070
00071 }
00072
00073
00074 static class UniformRandomVariableClass : public TclClass {
00075 public:
00076 UniformRandomVariableClass() : TclClass("RandomVariable/Uniform"){}
00077 TclObject* create(int, const char*const*) {
00078 return(new UniformRandomVariable());
00079 }
00080 } class_uniformranvar;
00081
00082 UniformRandomVariable::UniformRandomVariable()
00083 {
00084 bind("min_", &min_);
00085 bind("max_", &max_);
00086 }
00087
00088 UniformRandomVariable::UniformRandomVariable(double min, double max)
00089 {
00090 min_ = min;
00091 max_ = max;
00092 }
00093
00094 double UniformRandomVariable::value()
00095 {
00096 return(rng_->uniform(min_, max_));
00097 }
00098
00099
00100 static class ExponentialRandomVariableClass : public TclClass {
00101 public:
00102 ExponentialRandomVariableClass() : TclClass("RandomVariable/Exponential") {}
00103 TclObject* create(int, const char*const*) {
00104 return(new ExponentialRandomVariable());
00105 }
00106 } class_exponentialranvar;
00107
00108 ExponentialRandomVariable::ExponentialRandomVariable()
00109 {
00110 bind("avg_", &avg_);
00111 }
00112
00113 ExponentialRandomVariable::ExponentialRandomVariable(double avg)
00114 {
00115 avg_ = avg;
00116 }
00117
00118 double ExponentialRandomVariable::value()
00119 {
00120 return(rng_->exponential(avg_));
00121 }
00122
00123
00124 static class ParetoRandomVariableClass : public TclClass {
00125 public:
00126 ParetoRandomVariableClass() : TclClass("RandomVariable/Pareto") {}
00127 TclObject* create(int, const char*const*) {
00128 return(new ParetoRandomVariable());
00129 }
00130 } class_paretoranvar;
00131
00132 ParetoRandomVariable::ParetoRandomVariable()
00133 {
00134 bind("avg_", &avg_);
00135 bind("shape_", &shape_);
00136 }
00137
00138 ParetoRandomVariable::ParetoRandomVariable(double avg, double shape)
00139 {
00140 avg_ = avg;
00141 shape_ = shape;
00142 }
00143
00144 double ParetoRandomVariable::value()
00145 {
00146
00147
00148
00149
00150
00151
00152
00153 return(rng_->pareto(avg_ * (shape_ -1)/shape_, shape_));
00154 }
00155
00156
00157 static class ParetoIIRandomVariableClass : public TclClass {
00158 public:
00159 ParetoIIRandomVariableClass() : TclClass("RandomVariable/ParetoII") {}
00160 TclObject* create(int, const char*const*) {
00161 return(new ParetoIIRandomVariable());
00162 }
00163 } class_paretoIIranvar;
00164
00165 ParetoIIRandomVariable::ParetoIIRandomVariable()
00166 {
00167 bind("avg_", &avg_);
00168 bind("shape_", &shape_);
00169 }
00170
00171 ParetoIIRandomVariable::ParetoIIRandomVariable(double avg, double shape)
00172 {
00173 avg_ = avg;
00174 shape_ = shape;
00175 }
00176
00177 double ParetoIIRandomVariable::value()
00178 {
00179 return(rng_->paretoII(avg_ * (shape_ - 1), shape_));
00180 }
00181
00182 static class NormalRandomVariableClass : public TclClass {
00183 public:
00184 NormalRandomVariableClass() : TclClass("RandomVariable/Normal") {}
00185 TclObject* create(int, const char*const*) {
00186 return(new NormalRandomVariable());
00187 }
00188 } class_normalranvar;
00189
00190 NormalRandomVariable::NormalRandomVariable()
00191 {
00192 bind("avg_", &avg_);
00193 bind("std_", &std_);
00194 }
00195
00196 double NormalRandomVariable::value()
00197 {
00198 return(rng_->normal(avg_, std_));
00199 }
00200
00201 static class LogNormalRandomVariableClass : public TclClass {
00202 public:
00203 LogNormalRandomVariableClass() : TclClass("RandomVariable/LogNormal") {}
00204 TclObject* create(int, const char*const*) {
00205 return(new LogNormalRandomVariable());
00206 }
00207 } class_lognormalranvar;
00208
00209 LogNormalRandomVariable::LogNormalRandomVariable()
00210 {
00211 bind("avg_", &avg_);
00212 bind("std_", &std_);
00213 }
00214
00215 double LogNormalRandomVariable::value()
00216 {
00217 return(rng_->lognormal(avg_, std_));
00218 }
00219
00220 static class ConstantRandomVariableClass : public TclClass {
00221 public:
00222 ConstantRandomVariableClass() : TclClass("RandomVariable/Constant"){}
00223 TclObject* create(int, const char*const*) {
00224 return(new ConstantRandomVariable());
00225 }
00226 } class_constantranvar;
00227
00228 ConstantRandomVariable::ConstantRandomVariable()
00229 {
00230 bind("val_", &val_);
00231 }
00232
00233 ConstantRandomVariable::ConstantRandomVariable(double val)
00234 {
00235 val_ = val;
00236 }
00237
00238 double ConstantRandomVariable::value()
00239 {
00240 return(val_);
00241 }
00242
00243
00244
00245
00246
00247
00248 static class HyperExponentialRandomVariableClass : public TclClass {
00249 public:
00250 HyperExponentialRandomVariableClass() :
00251 TclClass("RandomVariable/HyperExponential") {}
00252 TclObject* create(int, const char*const*) {
00253 return(new HyperExponentialRandomVariable());
00254 }
00255 } class_hyperexponentialranvar;
00256
00257 HyperExponentialRandomVariable::HyperExponentialRandomVariable()
00258 {
00259 bind("avg_", &avg_);
00260 bind("cov_", &cov_);
00261 alpha_ = .95;
00262 }
00263
00264 HyperExponentialRandomVariable::HyperExponentialRandomVariable(double avg, double cov)
00265 {
00266 alpha_ = .95;
00267 avg_ = avg;
00268 cov_ = cov;
00269 }
00270
00271 double HyperExponentialRandomVariable::value()
00272 {
00273 double temp, res;
00274 double u = Random::uniform();
00275
00276 temp = sqrt((cov_ * cov_ - 1.0)/(2.0 * alpha_ * (1.0 - alpha_)));
00277 if (u < alpha_)
00278 res = Random::exponential(avg_ - temp * (1.0 - alpha_) * avg_);
00279 else
00280 res = Random::exponential(avg_ + temp * (alpha_) * avg_);
00281 return(res);
00282 }
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293 static class EmpiricalRandomVariableClass : public TclClass {
00294 public:
00295 EmpiricalRandomVariableClass() : TclClass("RandomVariable/Empirical"){}
00296 TclObject* create(int, const char*const*) {
00297 return(new EmpiricalRandomVariable());
00298 }
00299 } class_empiricalranvar;
00300
00301 EmpiricalRandomVariable::EmpiricalRandomVariable() : minCDF_(0), maxCDF_(1), maxEntry_(32), table_(0)
00302 {
00303 bind("minCDF_", &minCDF_);
00304 bind("maxCDF_", &maxCDF_);
00305 bind("interpolation_", &interpolation_);
00306 bind("maxEntry_", &maxEntry_);
00307 }
00308
00309 int EmpiricalRandomVariable::command(int argc, const char*const* argv)
00310 {
00311 Tcl& tcl = Tcl::instance();
00312 if (argc == 3) {
00313 if (strcmp(argv[1], "loadCDF") == 0) {
00314 if (loadCDF(argv[2]) == 0) {
00315 tcl.resultf("%s loadCDF %s: invalid file",
00316 name(), argv[2]);
00317 return (TCL_ERROR);
00318 }
00319 return (TCL_OK);
00320 }
00321 }
00322 return RandomVariable::command(argc, argv);
00323 }
00324
00325 int EmpiricalRandomVariable::loadCDF(const char* filename)
00326 {
00327 FILE* fp;
00328 char line[256];
00329 CDFentry* e;
00330
00331 fp = fopen(filename, "r");
00332 if (fp == 0)
00333 return 0;
00334
00335
00336 if (table_ == 0)
00337 table_ = new CDFentry[maxEntry_];
00338 for (numEntry_=0; fgets(line, 256, fp); numEntry_++) {
00339 if (numEntry_ >= maxEntry_) {
00340 maxEntry_ *= 2;
00341 e = new CDFentry[maxEntry_];
00342 for (int i=numEntry_-1; i >= 0; i--)
00343 e[i] = table_[i];
00344 delete table_;
00345 table_ = e;
00346 }
00347 e = &table_[numEntry_];
00348
00349 sscanf(line, "%lf %*f %lf", &e->val_, &e->cdf_);
00350 }
00351 fclose(fp);
00352 return numEntry_;
00353 }
00354
00355 double EmpiricalRandomVariable::value()
00356 {
00357 if (numEntry_ <= 0)
00358 return 0;
00359 double u = rng_->uniform(minCDF_, maxCDF_);
00360 int mid = lookup(u);
00361 if (mid && interpolation_ && u < table_[mid].cdf_)
00362 return interpolate(u, table_[mid-1].cdf_, table_[mid-1].val_,
00363 table_[mid].cdf_, table_[mid].val_);
00364 return table_[mid].val_;
00365 }
00366
00367 double EmpiricalRandomVariable::interpolate(double x, double x1, double y1, double x2, double y2)
00368 {
00369 double value = y1 + (x - x1) * (y2 - y1) / (x2 - x1);
00370 if (interpolation_ == INTER_INTEGRAL)
00371 return ceil(value);
00372 return value;
00373 }
00374
00375 int EmpiricalRandomVariable::lookup(double u)
00376 {
00377
00378 int lo, hi, mid;
00379 if (u <= table_[0].cdf_)
00380 return 0;
00381 for (lo=1, hi=numEntry_-1; lo < hi; ) {
00382 mid = (lo + hi) / 2;
00383 if (u > table_[mid].cdf_)
00384 lo = mid + 1;
00385 else hi = mid;
00386 }
00387 return lo;
00388 }