Main Page   Namespace List   Compound List   File List   Compound Members   File Members  

copy-ocsRanNumGen.cc

Go to the documentation of this file.
00001 // $Id: ocsRanNumGen.cc,v 1.14 2002/04/30 01:08:28 zweck Exp $
00002 
00003 //###################################################################
00004 //
00005 //           Optical Communication Systems Simulator
00006 //
00007 //       Copyright (2000):
00008 //       Optical Fiber Communications Laboratory (OFCL)
00009 //       Computer Science & Electrical Engineering Department (CSEE)
00010 //       University of Maryland Baltimore County (UMBC)
00011 //
00012 //###################################################################
00013 
00014 // Created by John Zweck, Nov 8th, 2000
00015 // The RanNumGen class uses the Random Number Generator
00016 // ran2 from Numerical Recipes in C. 
00017 // A helpful discussion of this random number generator 
00018 // can be found in the book  Numerical Recipes in C or
00019 // online at http://www.nr.com/
00020 // Additional discussion can be found in "Random Number Generation and 
00021 // Monte Carlo Methods" by James E. Gentle (Springer).
00022 // See the application  ocsExampleApplication.cc for 
00023 // how to use the class in our code.
00024 
00025 // Methods for the generation of random number for importance 
00026 // sampling were created by Ivan Lima
00027 
00028 // Addition of ResetRanNumGen() in 2/15/01 (see code)
00029 
00030 #include "ocsRanNumGen.hh"
00031 
00032 extern ofstream LogFile;
00033 
00034 // ##########################################################
00035 
00064 RanNumGen::RanNumGen(string InFileName)
00065 {
00066 
00067  ifstream InFile(InFileName.c_str(),ios::in);    
00068    
00069    if (!InFile) 
00070     {
00071       cerr << "Error: Input file "<< InFileName 
00072            << " could not be opened."<< endl;
00073       exit(1);
00074     }
00075 
00076 
00077 LogFileSeparator();
00078 LogFile << InFileName << endl;
00079 
00080 ContinuationFileName = InFileName + ".continue";
00081 RestartFileName = InFileName + ".restart";
00082 
00083 int OperationMode =  ReadInt("OperationMode"," ",1,3,LOWER_AND_UPPER,&InFile);
00084 
00085 switch(OperationMode)
00086    {
00087 
00088    case 1: // Initialize using seed from InFile
00089 
00090          LogFile << "Initializing RanNumGen using seed provided in "
00091                  << InFileName << endl; 
00092 
00093           idum =  ReadLongInt("Seed"," ",1,-1,LOWER_ONLY,&InFile);
00094           idum2=123456789;  // Do NOT change this line
00095           iy=0;             // Do NOT change this line
00096 
00097           idum = -idum; 
00098 
00099           WriteRanSeqParameters(RestartFileName);
00100           // Since idum value in RestartFileName < 0 the Restart will 
00101           // work just fine!
00102 
00103           break;
00104 
00105    case 2:  // Continue random sequence from
00106             // previous run using values in 
00107             // ContinuationFileName
00108 
00109            LogFile << "Continuing along random sequence using parameters in "
00110                    << ContinuationFileName << endl;
00111 
00112            ReadRanSeqParameters(ContinuationFileName);
00113            WriteRanSeqParameters(RestartFileName);
00114 
00115            break;
00116 
00117    case 3:  // Restart random sequence where 
00118             // previous run started using values in
00119             // RestartFileName
00120 
00121           LogFile << "Restarting random sequence using parameters in "
00122                    << RestartFileName << endl;
00123 
00124           ReadRanSeqParameters(RestartFileName);
00125 
00126           break;
00127 
00128    default:
00129 
00130      LogFile << "Invalid choice of OperationMode" << endl
00131              << "ABORTING NOW!!" << endl;
00132 
00133      exit(1);
00134 
00135 
00136    }
00137 
00138    // ## Makes a copy of the input parameters to allow a restart
00139    // #  See ResetRanNumGen() for further information.
00140 
00141  SaveCurrentState();
00142 
00143 } // ## end Constructor
00144 
00145 // ######################################################
00146 
00147 RanNumGen::~RanNumGen()
00148 {
00149   WriteRanSeqParameters(ContinuationFileName);
00150 }
00151 
00152 // #######################################################
00153 
00154 void RanNumGen::SaveCurrentState(void)
00155 {
00156 
00157    idumStart  = idum;
00158    idum2Start = idum2;
00159    iyStart    = iy; 
00160    for(int ii=0;ii<NTAB;ii++)
00161       ivStart[ii]= iv[ii];
00162 
00163 }
00164 
00165 // ########################################################
00166 
00167 float RanNumGen::GetRanNum(void)
00168 {
00169 
00170 // (C) Copr. 1986-92 Numerical Recipes Software 
00171 
00172 int j;
00173 long k;
00174 float temp;
00175 
00176 
00177 if(idum <= 0) 
00178   {
00179      if (-idum < 1) 
00180            idum=1;
00181      else 
00182        idum = -idum;
00183 
00184 
00185      idum2=idum;
00186                 
00187 
00188      for(j=NTAB+7;j>=0;j--) 
00189        {
00190          k=idum/IQ1;
00191          idum=IA1*(idum-k*IQ1)-k*IR1;
00192                         
00193          if (idum < 0) 
00194              idum += IM1;
00195                         
00196          if (j < NTAB) 
00197              iv[j] = idum;
00198 
00199        } // end for loop
00200 
00201 
00202       iy=iv[0];
00203 
00204   } // end if(idum <= 0) 
00205 
00206 
00207  k=(idum)/IQ1;
00208  idum=IA1*(idum-k*IQ1)-k*IR1;
00209 
00210  if (idum < 0) 
00211      idum += IM1;
00212 
00213  k=idum2/IQ2;
00214  idum2=IA2*(idum2-k*IQ2)-k*IR2;
00215 
00216  if (idum2 < 0) 
00217      idum2 += IM2;
00218 
00219  j=iy/NDIV;
00220  iy=iv[j]-idum2;
00221  iv[j] = idum;
00222 
00223  if (iy < 1) 
00224      iy += IMM1; 
00225        
00226  if ((temp=AM*iy) > RNMX) 
00227      return RNMX;
00228  else return temp;
00229 
00230 
00231 } // end GetRanNum
00232 
00233 // ####################################################
00234 
00235 
00236 float RanNumGen::GetGaussianDeviate(void)
00237 {
00238 
00239   //(C) Copr. 1986-92 Numerical Recipes Software
00240   //float gasdev(long *idum)
00241 
00242 static int iset=0;
00243 static float gset;
00244 float fac,rsq,v1,v2;
00245 
00246 if(iset == 0) 
00247   {
00248      do {
00249           v1=2.0*GetRanNum()-1.0;
00250           v2=2.0*GetRanNum()-1.0;
00251           rsq=v1*v1+v2*v2;
00252 
00253          } while (rsq >= 1.0 || rsq == 0.0);
00254 
00255       fac=sqrt(-2.0*log(rsq)/rsq);
00256       gset=v1*fac;
00257       iset=1;
00258       return v2*fac;
00259     } 
00260 
00261 else
00262  {
00263    iset=0;
00264    return gset;
00265  }
00266 
00267 } //## end GetGaussianDeviate()
00268 
00269 // ###################################################
00270 
00271 void RanNumGen::ReadRanSeqParameters(string InFileName)
00272 {
00273 
00274 ifstream InFile(InFileName.c_str(),ios::in);
00275    
00276 if (!InFile) 
00277   {
00278 
00279     // We should change the next line to intialize with a seed whose
00280     // value comes from the system clock somehow.
00281 
00282     idum = -1;
00283     WriteRanSeqParameters(InFileName);
00284     InFile.open(InFileName.c_str(),ios::in);
00285 
00286     if (!InFile)
00287       {
00288        LogFile << "ERROR in RanNumGen::ReadRanSeqParameters" << exit
00289                << "ABORTING NOW!";
00290        exit(1);   
00291       }   
00292    }
00293 
00294  InFile >> idum 
00295         >> idum2
00296         >> iy;
00297 
00298  for(int i=0;i<NTAB;i++)
00299    InFile >> iv[i];
00300 
00301 } // end ReadRanSeqParameters
00302 
00303 // ####################################################
00304 
00305 void RanNumGen::WriteRanSeqParameters(string OutFileName)
00306 {
00307 
00308 ofstream OutFile(OutFileName.c_str(),ios::out);
00309    
00310 if (!OutFile) 
00311   {
00312     cerr << "Error: " <<OutFileName << " could not be opened." 
00313          << endl << flush;
00314     exit(1);
00315   }
00316 
00317  OutFile << idum << endl
00318          << idum2 << endl
00319          << iy << endl;
00320 
00321  for(int i=0;i<NTAB;i++)
00322    OutFile << iv[i] << endl;
00323 
00324 
00325 } //  end WriteRanSeqParameters
00326 
00327 // ##################################################
00328 
00329 
00330 //#############################################################
00331 //## This function resets the RanNumGen to its original value
00332 //#  It can be very useful to assist parameters sweeping
00333 //## By: Ivan Lima, 2/15/01
00334 
00335 void RanNumGen::ResetRanNumGen(void)
00336 {
00337    idum  = idumStart;
00338    idum2 = idum2Start;
00339    iy    = iyStart; 
00340    for(int ii=0;ii<NTAB;ii++)
00341       iv[ii]= ivStart[ii];
00342 }
00343 
00344 
00345 //#############################################################
00346 //## Random source for importance sampling applications
00347 //#  The pdf returns a random value between -1 and 1, 
00348 //#  biased towards 1. Thus, this method is  
00349 //#  is adequate for biasing the cosine of the angles
00350 //#  between two vectors towards 1. Thus, it is biasing 
00351 //#  the two vectors to be aligned to each other.
00352 //#  Please, remember that the acos does not recover 
00353 //#  a angle from 0 to 2*pi, but only from 0 to pi.
00354 //#  One can overcome this by multiplying the angle 
00355 //#  by a discrete random variable with equal 
00356 //#  probability of being equal to -1 that 1.
00357 //#  This can be waived in case an extra uniform 
00358 //#  rotation from 0 to 2*pi is added along the biased
00359 //#  axis.
00360 //#  This pdf was proposed by Ivan Lima.
00361 //#  The application of importance sampling to PMD was 
00362 //#  developed by Biondini and Kath during Fall'00.
00363 //#  The application of importance sampling to PDL was
00364 //#  developed by I. T. Lima et al.
00365 //## By: Ivan Lima (10/18/01)
00366 
00367 float RanNumGen::GetRanCosineBiased(double alpha,
00368                                double *LikelihoodRatio)
00369 {
00370    //# alpha -> defines the amount of bias
00371    //#          If alpha > 0; bias towards 1
00372    //#          If alpha < 0; bias towards -1
00373    
00374    double ValFunction;
00375    double Z = GetRanNum();
00376 
00377    //## Prevent numerical problems due to division by zero
00378 
00379    if ( abs(alpha) < 1e-5 ) 
00380     {
00381 
00382       alpha = 1e-5;
00383     }     
00384    
00385 
00386    //## Generate a value for the biased cosine
00387 
00388    ValFunction = 1 + 1./alpha * log( exp(-2*alpha)+Z*(1-exp(-2*alpha) ) );   
00389      
00390    
00391    *LikelihoodRatio *= (1-exp(-2*alpha) )/(2*alpha)
00392                       *( exp(alpha*(1 - ValFunction)));   
00393              
00394    return ValFunction;      
00395 }
00396 
00397              
00398 // ################################################################
00399 
00400 
00401 //#############################################################
00402 //## Random source for importance sampling applications
00403 //## By: Ivan Lima (4/3/02)
00404 float RanNumGen::GetRanSignBiased(double alpha,
00405                                double *LikelihoodRatio)
00406 {
00407    //# alpha -> defines the amount of bias
00408    //#          If alpha > 0; bias towards 1
00409    //#          If alpha < 0; bias towards -1
00410    
00411    double Z = GetRanNum();
00412    double RandomSign;
00413    double cdfcAtZero;
00414 
00415    //## Prevent numerical problems due to division by zero
00416    if ( abs(alpha) < 1e-5 ) {
00417 
00418       alpha = 1e-5;
00419    }     
00420    
00421 
00422    //## Generate a value for the biased cosine
00423    RandomSign = sgn( 1 + 1./alpha * log( exp(-2*alpha) 
00424                     +Z*(1-exp(-2*alpha) ) )  );  
00425    
00426    cdfcAtZero = ( exp(-alpha)-exp(-2*alpha) )/(1-exp(-2*alpha));
00427    
00428    //cout << "cdfcAtZero = " << cdfcAtZero << endl;
00429    
00430    if (RandomSign == -1) {
00431       *LikelihoodRatio *= 0.5/cdfcAtZero;     
00432    }
00433    else if (RandomSign == 1) {
00434       *LikelihoodRatio *= 0.5/(1. - cdfcAtZero);        
00435    }
00436    else {
00437       cout << "Error: From RanNumGen::GetRanSignBiased()" << endl
00438            << "The sgn(.) function got a serios problem" << endl; 
00439       exit(1);     
00440    }                     
00441    
00442 //   *LikelihoodRatio *= (1-exp(-2*alpha) )/(2*alpha)
00443 //                      *( exp(alpha*(1 - ValFunction)));   
00444 
00445              
00446    return RandomSign;      
00447 }
00448 
00449 // #######################################################
00450 
00451 //#############################################################
00452 //## Plot pdf for importance sampling applications
00453 //#  The pdf returns a random value between -1 and 1, 
00454 //#  biased towards beta. Thus, this method is  
00455 //#  is adequate for biasing the cosine of angles.
00456 //#  This method was developed to the application of the 
00457 //#  importance sampling to the second order PMD.
00458 //## The LikelihoodRation of the first sample in a set must
00459 //#  setart with the identity with respect to the multiplication,
00460 //#  that's the unitary value `1'.
00461 //## The actual pdf is equal to half of the multiplicand 
00462 //#  of the LikelihoodRatio contribution ( thats U[-1,1]).
00463 //## By: Ivan Lima (10/18/01)
00464 float RanNumGen::GetRanCosineBiased(double alpha, double beta, 
00465                                double *LikelihoodRatio)
00466 {
00467    //# alpha -> defines the amount of bias
00468    //#          If alpha > 0; bias towards beta
00469    //#          If alpha < 0; bias away from beta
00470    //# beta  -> defines where to bias (between -1 and 1).
00471    //#          If beta < -1; beta = -1
00472    //#          if beta > 1; beta = 1
00473    
00474    double ValFunction;
00475    double Z = GetRanNum();
00476    double W = GetRanNum();
00477 
00478    //## Prevent numerical problems due to division by zero
00479    if ( abs(alpha) < 1e-5 ) {
00480 
00481       alpha = 1e-5;
00482    }     
00483    
00484    //## Adjust the limits of beta
00485    if (beta < -1) {
00486       beta = -1;
00487    }
00488    else if (beta > 1) {
00489       beta = 1;
00490    }
00491 
00492    //## Generate a value for the biased cosine
00493    if (W < (1-exp(-alpha*(1+beta)))
00494           /(2-exp(-alpha*(1+beta))-exp(-alpha*(1-beta)) ) ) {
00495       //## Valfunction < beta    
00496       ValFunction = beta + 1./alpha * log( exp(-alpha*(1+beta)) 
00497                     +Z*(1-exp(-alpha*(1+beta)) ) );   //## A
00498    }                 
00499    else {            
00500       //## Valfunction > beta     
00501       ValFunction = beta - 1./alpha * log( 1 
00502                     -Z*(1-exp(-alpha*(1-beta)) ) );    //## B                   
00503    }       
00504    
00505    *LikelihoodRatio *= 1./(2*alpha)
00506                      *(2-exp(-alpha*(1+beta))-exp(-alpha*(1-beta)) )
00507                      *( exp(alpha*abs(ValFunction - beta)));
00508              
00509    return ValFunction;      
00510 }
00511 

Generated at Mon Jun 9 20:08:10 2003 for OCS by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000