00001 /************************************************************************** 00002 *** 00003 *** Copyright (c) 1995-2000 Regents of the University of California, 00004 *** Andrew E. Caldwell, Andrew B. Kahng and Igor L. Markov 00005 *** Copyright (c) 2000-2004 Regents of the University of Michigan, 00006 *** Saurabh N. Adya, Jarrod A. Roy and Igor L. Markov 00007 *** 00008 *** Contact author(s): abk@cs.ucsd.edu, imarkov@umich.edu 00009 *** Original Affiliation: UCLA, Computer Science Department, 00010 *** Los Angeles, CA 90095-1596 USA 00011 *** 00012 *** Permission is hereby granted, free of charge, to any person obtaining 00013 *** a copy of this software and associated documentation files (the 00014 *** "Software"), to deal in the Software without restriction, including 00015 *** without limitation 00016 *** the rights to use, copy, modify, merge, publish, distribute, sublicense, 00017 *** and/or sell copies of the Software, and to permit persons to whom the 00018 *** Software is furnished to do so, subject to the following conditions: 00019 *** 00020 *** The above copyright notice and this permission notice shall be included 00021 *** in all copies or substantial portions of the Software. 00022 *** 00023 *** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 00024 *** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 00025 *** OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 00026 *** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 00027 *** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 00028 *** OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 00029 *** THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00030 *** 00031 *** 00032 ***************************************************************************/ 00033 00034 00035 00036 00038 00039 #ifndef _ABKSEED_H_ 00040 #define _ABKSEED_H_ 00041 00042 //#include <stl_config.h> 00043 #include <stdlib.h> 00044 #include <math.h> 00045 #include <fstream> 00046 #include <limits.h> 00047 #include <map> 00048 #include <string> 00049 00050 using std::ifstream; 00051 using std::ofstream; 00052 00053 //: Maintains all random seeds used by a process. 00054 //Idea: First time you create a random object, an initial nondeterministic 00055 // seed (also called the "external seed" is created from system 00056 // information and logged to seeds.out. 00057 // Any random object created with a seed of UINT_MAX ("nondeterministic"), 00058 // and that does not use the snazzy new "local independence" feature, 00059 // then uses seeds from a sequence starting with the initial value 00060 // and increasing by 1 with each new nondeterministic random object 00061 // created. 00062 // 00063 // If the seed is overridden with a value other than UINT_MAX it is used, 00064 // and logged to seeds.out . 00065 // 00066 // However if seeds.in exists, the initial nondeterministic value 00067 // is taken from the second line of seeds.in rather than the system 00068 // clock, and subsequent *deterministic* values are taken from successive 00069 // lines of seeds.in rather than from the value passed. 00070 // 00071 // If seeds.out is in use or other errors occur trying to create it, 00072 // a warning is generated that the seeds will not be logged, and 00073 // the initial nondeterministic seed is printed (which should be 00074 // sufficient to recreate the run provided that all "deterministic" 00075 // seeds truly *are* deterministic (e.g. don't depend on external 00076 // devices). 00077 // 00078 // You can disable the logging function by calling the static 00079 // function SeedHandler::turnOffLogging(). This will not disable 00080 // the ability to override seeding with seeds.in . 00081 //NEW ULTRA-COOL FEATURE: (17 June 1999) 00082 // You now have the option, which I (Mike) highly recommend, 00083 // of specifying, instead of a seed, a "local identifier", which 00084 // is a string that should identify uniquely the random variable 00085 // (not necessarily the random object) being used. The suggested 00086 // format of this string is as follows: If your 00087 // RNG is called _rng and is a member of MyClass, pass 00088 // the string "MyClass::_rng". If it's a local variable 00089 // called rng in the method MyClass::myMethod(), pass 00090 // the string "MyClass::myMethod(),_rng". 00091 // 00092 // SeedHandler will maintain a collection of counters associated 00093 // with each of these strings. The sequence of random numbers 00094 // from a random object will be determined by three things: 00095 // 1) the "external seed" (same as "initial nondeterm seed"). 00096 // 2) the "local identifier" (the string described above). 00097 // 3) the counter saying how many RNG objects have previously 00098 // been created with the same local identifier. 00099 // When any one of these changes, the output should be effectively 00100 // independent of the previous RNG. Moreover you don't have 00101 // to worry about your regressions changing simply because someone 00102 // else's code which you call has changed the number of RNG objects 00103 // it uses. 00104 //ANOTHER NEW FEATURE (21 February 2001) 00105 // At times you may wish to control the external seed yourself, e.g. 00106 // by specifying the seed on the command line, rather than 00107 // using either seeds.in or the nondeterministic chooser. 00108 // To enable this, a static method SeedHandler::overrideExternalSeed() 00109 // has been added. If you call this method before any random 00110 // object has been created, you can set the external seed. 00111 // The file seeds.out will still be created unless you call 00112 // SeedHandler::turnOffLogging(). If seeds.in exists, it 00113 // will control -- your call to overrideExternalSeed() will 00114 // print a warning message and otherwise be ignored. 00115 00116 struct SeedHandlerCompareStrings 00117 { 00118 bool operator()(std::string firstString, std::string secondString) const 00119 { 00120 return strcmp(firstString.c_str(), secondString.c_str()) < 0; 00121 } 00122 }; 00123 class SeedHandler 00124 { 00125 private: 00126 SeedHandler(unsigned seed); 00127 00128 SeedHandler(const char *locIdent, 00129 unsigned counterOverride=UINT_MAX); 00130 00131 public: 00132 00133 ~SeedHandler(); 00134 00135 private: 00136 00137 void _init(); 00138 00139 unsigned _seed; 00140 00141 char *_locIdent; 00142 unsigned _counter; 00143 bool _isSeedMultipartite; 00144 00145 static ofstream *_PseedOutFile; 00146 static ifstream *_PseedInFile; 00147 static unsigned _nextSeed; 00148 // slight misnomer, This is the next nondeterministic seed. 00149 00150 static unsigned _externalSeed; 00151 static unsigned _progOverrideExternalSeed; 00152 00153 static std::map<std::string,unsigned,SeedHandlerCompareStrings > 00154 _counters; 00155 00156 static bool _loggingOff; 00157 // don't log seeds 00158 static bool _haveRandObj; 00159 // starts false, true after first 00160 static bool _cleaned; 00161 // clean() has been called 00162 void _chooseInitNondetSeed(); 00163 // first nondeterministic seed thereafter, increment. 00164 void _initializeOutFile(); 00165 // create log file and write first two lines. 00166 00167 00168 friend class RandomRoot; 00169 friend class SeedCleaner; 00170 public: 00171 static void turnOffLogging(); 00172 static void overrideExternalSeed(unsigned extseed); 00173 static bool isInitialized() { return _haveRandObj; } 00174 private: 00175 static void clean(); 00176 }; 00177 00178 /* One global object of the following class, declared in seeds.cxx, will 00179 make sure that SeedHandler::clean() is called at the end of execution*/ 00180 //: Makes it sure that SeedHandler will be cleaned at the end of execution 00181 class SeedCleaner 00182 { 00183 public: 00184 SeedCleaner(){} 00185 00186 ~SeedCleaner(){SeedHandler::clean();} 00187 }; 00188 00189 #endif