Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2024-06-26 07:05:12

0001 #pragma once
0002 
0003 #include <cstdint>
0004 #include <functional>
0005 #include <mutex>
0006 #include <random>
0007 
0008 #include <algorithms/detail/random.h>
0009 #include <algorithms/logger.h>
0010 #include <algorithms/service.h>
0011 
0012 namespace algorithms {
0013 
0014 // Random Engine callback function:
0015 //   - Signature: std::function<std::vector<value_type>(size_t N)> --> generates a vector
0016 //     of N numbers
0017 //   - RandomEngineCB is required to return N random numbers between 0 and
0018 //     std::numeric_limits<uint_fast64_t>::max()
0019 //   - RandomEngineCB is responsible to deal with possible simultaneous access by multiple
0020 //     Generator instances (required to be thread-safe).
0021 using RandomEngineCB = detail::CachedBitGenerator::GenFunc;
0022 
0023 // thread-safe generator front-end. Requires that the underlying random engine used by
0024 // the RandomSvc is thread-safe.
0025 class Generator {
0026 public:
0027   Generator(const RandomEngineCB& gen, const size_t cache_size) : m_gen{gen, cache_size} {}
0028 
0029   template <class Int = int> Int uniform_int(const Int min, const Int max) const {
0030     std::uniform_int_distribution<Int> d{min, max};
0031     std::lock_guard<std::mutex> lock{m_mutex};
0032     return d(m_gen);
0033   }
0034   template <class Float = double> Float uniform_double(const Float min, const Float max) const {
0035     std::uniform_real_distribution<Float> d{min, max};
0036     std::lock_guard<std::mutex> lock{m_mutex};
0037     return d(m_gen);
0038   }
0039   template <class Int = int> Int poisson(const Int mean) const {
0040     std::poisson_distribution<Int> d{mean};
0041     std::lock_guard<std::mutex> lock{m_mutex};
0042     return d(m_gen);
0043   }
0044   template <class Float = double> Float exponential(const Float lambda) const {
0045     std::exponential_distribution<Float> d{lambda};
0046     std::lock_guard<std::mutex> lock{m_mutex};
0047     return d(m_gen);
0048   }
0049   template <class Float = double> Float gaussian(const Float mu, const Float sigma) const {
0050     std::normal_distribution<Float> d{mu, sigma};
0051     std::lock_guard<std::mutex> lock{m_mutex};
0052     return d(m_gen);
0053   }
0054 
0055 private:
0056   mutable detail::CachedBitGenerator m_gen;
0057   mutable std::mutex m_mutex;
0058 };
0059 
0060 // Random service that creates multiple Generators that are linked to a single random
0061 // engine. The Generators are safe to be used in parallel as long as the Engine itself is
0062 // thread-safe (this is a hard requirement for MT). The Generators avoid unnecesary locking
0063 // by running off a auto-refreshing cached random sequence.
0064 class RandomSvc : public LoggedService<RandomSvc> {
0065 public:
0066   using value_type = detail::CachedBitGenerator::result_type;
0067 
0068   Generator generator() { return {m_gen, m_cache_size}; }
0069 // FIXME fix the CMake setup so these are properly found in Gaudi
0070 #if 0 
0071   void init();
0072   void init(const RandomEngineCB& gen);
0073 #endif
0074   void init() {
0075     if (m_seed.hasValue()) {
0076       info() << "Custom random seed requested: " << m_seed << endmsg;
0077       m_gen = createEngine(m_seed);
0078     }
0079   }
0080   void init(const RandomEngineCB& gen) {
0081     info() << "Loading external generator function." << endmsg;
0082     m_gen = gen;
0083     if (m_seed.hasValue()) {
0084       warning() << "Custom random seed request ignored when using external generator function"
0085                 << endmsg;
0086     }
0087   }
0088 
0089 #if 0
0090 private:
0091   RandomEngineCB createEngine(const size_t seed = 1);
0092 #endif
0093   RandomEngineCB createEngine(const size_t seed = 1) {
0094     return [=](const size_t size) {
0095       static std::mutex m;
0096       static std::mt19937_64 gen{seed};
0097       std::lock_guard<std::mutex> lock{m};
0098       std::vector<value_type> ret(size);
0099       std::generate(ret.begin(), ret.end(), gen);
0100       return ret;
0101     };
0102   }
0103   // end of FIXME
0104 
0105 private:
0106   RandomEngineCB m_gen{createEngine()};
0107   Property<size_t> m_seed{this, "seed", "Random seed for the internal random engine"};
0108   Property<size_t> m_cache_size{this, "cacheSize", 1024, "Cache size for each generator instance"};
0109   std::mutex m_mutex;
0110 
0111   ALGORITHMS_DEFINE_LOGGED_SERVICE(RandomSvc)
0112 };
0113 
0114 } // namespace algorithms