Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Compound Members | File Members

ranvar.cc

Go to the documentation of this file.
00001 /* -*-  Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
00002 /*
00003  * Copyright (c) Xerox Corporation 1997. All rights reserved.
00004  *
00005  * License is granted to copy, to use, and to make and to use derivative
00006  * works for research and evaluation purposes, provided that Xerox is
00007  * acknowledged in all documentation pertaining to any such copy or derivative
00008  * work. Xerox grants no other licenses expressed or implied. The Xerox trade
00009  * name should not be used in any advertising without its written permission.
00010  *
00011  * XEROX CORPORATION MAKES NO REPRESENTATIONS CONCERNING EITHER THE
00012  * MERCHANTABILITY OF THIS SOFTWARE OR THE SUITABILITY OF THIS SOFTWARE
00013  * FOR ANY PARTICULAR PURPOSE.  The software is provided "as is" without
00014  * express or implied warranty of any kind.
00015  *  
00016  * These notices must be retained in any copies of any part of this software.
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 // Added by Debojyoti Dutta 12 October 2000
00056 // This allows us to seed a randomvariable with 
00057 // our own RNG object. This command is called from 
00058 // expoo.cc and pareto.cc 
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         /* yuck, user wants to specify shape and avg, but the
00147          * computation here is simpler if we know the 'scale'
00148          * parameter.  right thing is to probably do away with
00149          * the use of 'bind' and provide an API such that we
00150          * can update the scale everytime the user updates shape
00151          * or avg.
00152          */
00153         return(rng_->pareto(avg_ * (shape_ -1)/shape_, shape_));
00154 }
00155 
00156 /* Pareto distribution of the second kind, aka. Lomax distribution */
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 /* Hyperexponential distribution code adapted from code provided
00245  * by Ion Stoica.
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 // Empirical Random Variable:
00286 //  CDF input from file with the following column
00287 //   1.  Possible values in a distrubutions
00288 //   2.  Number of occurances for those values
00289 //   3.  The CDF for those value
00290 //  code provided by Giao Nguyen
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_) {   // resize the CDF table
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                 // Use * and l together raises a warning
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)   // round up
00371                 return ceil(value);
00372         return value;
00373 }
00374 
00375 int EmpiricalRandomVariable::lookup(double u)
00376 {
00377         // always return an index whose value is >= u
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 }

Generated on Tue Apr 20 12:14:28 2004 for NS2.26SourcesOriginal by doxygen 1.3.3