Line data Source code
1 : /****************************************************************************/ 2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo 3 : // Copyright (C) 2001-2024 German Aerospace Center (DLR) and others. 4 : // This program and the accompanying materials are made available under the 5 : // terms of the Eclipse Public License 2.0 which is available at 6 : // https://www.eclipse.org/legal/epl-2.0/ 7 : // This Source Code may also be made available under the following Secondary 8 : // Licenses when the conditions for such availability set forth in the Eclipse 9 : // Public License 2.0 are satisfied: GNU General Public License, version 2 10 : // or later which is available at 11 : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html 12 : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later 13 : /****************************************************************************/ 14 : /// @file RandHelper.cpp 15 : /// @author Daniel Krajzewicz 16 : /// @author Michael Behrisch 17 : /// @date Tue, 29.05.2005 18 : /// 19 : // 20 : /****************************************************************************/ 21 : #include <config.h> 22 : 23 : #include <ctime> 24 : #include <utils/options/OptionsCont.h> 25 : #include <utils/common/SysUtils.h> 26 : #include "StdDefs.h" 27 : #include "RandHelper.h" 28 : 29 : 30 : // debug vehicle movement randomness (dawdling in finalizeSpeed) 31 : //#define DEBUG_FLAG1 32 : //#define DEBUG_RANDCALLS 33 : //#define DEBUG_RANDCALLS_PARALLEL 34 : 35 : 36 : // =========================================================================== 37 : // static member variables 38 : // =========================================================================== 39 : SumoRNG RandHelper::myRandomNumberGenerator("default"); 40 : 41 : #ifdef DEBUG_RANDCALLS 42 : unsigned long long int myDebugIndex(7); 43 : std::string myDebugId(""); 44 : #endif 45 : 46 : #ifdef DEBUG_RANDCALLS_PARALLEL 47 : #include <thread> 48 : #include <utils/iodevices/OutputDevice.h> 49 : std::map<std::thread::id, int> threadIndices; 50 : std::map<std::string, int> lastThreadIndex; // by rng 51 : #endif 52 : 53 : 54 : // =========================================================================== 55 : // member method definitions 56 : // =========================================================================== 57 : 58 : void 59 44511 : RandHelper::insertRandOptions(OptionsCont& oc) { 60 : // registers random number options 61 44511 : oc.addOptionSubTopic("Random Number"); 62 : 63 44511 : oc.doRegister("random", new Option_Bool(false)); 64 89022 : oc.addSynonyme("random", "abs-rand", true); 65 89022 : oc.addDescription("random", "Random Number", TL("Initialises the random number generator with the current system time")); 66 : 67 44511 : oc.doRegister("seed", new Option_Integer(23423)); 68 89022 : oc.addSynonyme("seed", "srand", true); 69 89022 : oc.addDescription("seed", "Random Number", TL("Initialises the random number generator with the given value")); 70 44511 : } 71 : 72 : 73 : void 74 2525607 : RandHelper::initRand(SumoRNG* which, const bool random, const int seed) { 75 2525607 : if (which == nullptr) { 76 : which = &myRandomNumberGenerator; 77 : } 78 2525607 : if (random) { 79 0 : which->seed((unsigned long)time(nullptr)); 80 : } else { 81 2525607 : which->seed(seed); 82 : } 83 2525607 : } 84 : 85 : 86 : void 87 255783 : RandHelper::initRandGlobal(SumoRNG* which) { 88 255783 : OptionsCont& oc = OptionsCont::getOptions(); 89 511566 : initRand(which, oc.getBool("random"), oc.getInt("seed")); 90 255783 : } 91 : 92 : 93 : double 94 881286186 : RandHelper::rand(SumoRNG* rng) { 95 881286186 : if (rng == nullptr) { 96 : rng = &myRandomNumberGenerator; 97 : } 98 881286186 : const double res = double((*rng)() / 4294967296.0); 99 881286186 : rng->count++; 100 : #ifdef DEBUG_RANDCALLS 101 : if (rng->count == myDebugIndex 102 : && (myDebugId == "" || rng->id == myDebugId)) { 103 : std::cout << "DEBUG\n"; // for setting breakpoint 104 : } 105 : std::stringstream stream; // to reduce output interleaving from different threads 106 : #ifdef DEBUG_RANDCALLS_PARALLEL 107 : auto threadID = std::this_thread::get_id(); 108 : if (threadIndices.count(threadID) == 0) { 109 : const int tmp = threadIndices.size(); 110 : threadIndices[threadID] = tmp; 111 : } 112 : int threadIndex = threadIndices[threadID]; 113 : auto it = lastThreadIndex.find(rng->id); 114 : if ((it == lastThreadIndex.end() || it->second != threadIndex) 115 : && (myDebugId == "" || rng->id == myDebugId)) { 116 : std::cout << "DEBUG rng " << rng->id << " change thread old=" << (it == lastThreadIndex.end() ? -1 : it->second) << " new=" << threadIndex << " (" << std::this_thread::get_id() << ")\n"; // for setting breakpoint 117 : } 118 : lastThreadIndex[rng->id] = threadIndex; 119 : stream << "rng " << rng->id << " call=" << rng->count << " thread=" << threadIndex << " val=" << res << "\n"; 120 : OutputDevice::getDevice(rng->id) << stream.str(); 121 : #else 122 : stream << "rng " << rng->id << " call=" << rng->count << " val=" << res << "\n"; 123 : std::cout << stream.str(); 124 : #endif 125 : #endif 126 : #ifdef DEBUG_FLAG1 127 : if (gDebugFlag1) { 128 : std::stringstream stream; // to reduce output interleaving from different threads 129 : stream << "rng " << rng->id << " call=" << rng->count << " val=" << res << "\n"; 130 : std::cout << stream.str(); 131 : } 132 : #endif 133 881286186 : return res; 134 : } 135 : 136 : double 137 37942166 : RandHelper::randNorm(double mean, double variance, SumoRNG* rng) { 138 : // Polar method to avoid cosine 139 : double u, q; 140 : do { 141 48352779 : u = rand(2.0, rng) - 1; 142 48352779 : const double v = rand(2.0, rng) - 1; 143 48352779 : q = u * u + v * v; 144 48352779 : } while (q == 0.0 || q >= 1.0); 145 37942166 : const double logRounded = ceil(log(q) * 1e14) / 1e14; 146 37942166 : return mean + variance * u * sqrt(-2 * logRounded / q); 147 : } 148 : 149 : double 150 334902 : RandHelper::randExp(double rate, SumoRNG* rng) { 151 334902 : return -log(rand(rng)) / rate; 152 : } 153 : 154 : // template<class T> 155 : // void RandHelper::shuffle(const std::vector<T>& v) { 156 : // std::shuffle(v.begin(), v.end(), rng); 157 : // } 158 : 159 : /****************************************************************************/