PerEventPolicy.h
Go to the documentation of this file.
1 /**
2  * @file PerEventPolicy.h
3  * @brief Implementation of the per-event random seed assignment policy
4  * @author Gianluca Petrillo (petrillo@fnal.gov)
5  * @date 20150211
6  * @see SeedMaster.h
7  *
8  * No code in this files is directly serviceable.
9  * Documentation is up to date though.
10  */
11 
12 #ifndef NUTOOLS_RANDOMUTILS_PROVIDERS_PEREVENTPOLICY_H
13 #define NUTOOLS_RANDOMUTILS_PROVIDERS_PEREVENTPOLICY_H 1
14 
15 // C/C++ standard libraries
16 #include <string>
17 #include <sstream>
18 #include <ostream> // std::endl
19 #include <type_traits> // std::make_signed<>
20 
21 // From art and its tool chain
23 #include "fhiclcpp/ParameterSet.h"
25 
26 // Some helper classes
27 #include "nutools/RandomUtils/Providers/RandomSeedPolicyBase.h"
28 #include "nutools/RandomUtils/Providers/EngineId.h"
29 #include "nutools/RandomUtils/Providers/EventSeedInputData.h"
30 
31 
32 namespace rndm {
33 
34  namespace details {
35 
36  /** ************************************************************************
37  * @brief Implementation of the "perEvent" policy
38  *
39  * This policy extracts seeds depending on contextual information from the
40  * event.
41  * The information that enters the seed is the event ID
42  * (run, subrun, event), the process name, and the engine ID.
43  */
44  template <typename SEED>
45  class PerEventPolicy: public RandomSeedPolicyBase<SEED> {
46  public:
49  using seed_t = typename base_t::seed_t;
50 
51  /// type for contextual event information
53 
54  typedef enum {
55  saEventTimestamp_v1, ///< event timestamp algorithm (v1)
56  NAlgos, ///< total number of seed algorithms
57  saUndefined, ///< algorithm not defined
58  saDefault = saEventTimestamp_v1 ///< default algorithm
59  } SeedAlgo_t; ///< seed algorithms; see reseed() documentation for details
60 
61  /// Configures from a parameter set
62  /// @see configure()
63  PerEventPolicy(fhicl::ParameterSet const& pset): base_t("perEvent")
64  { this_t::configure(pset); }
65 
66  /// Returns whether the returned seed should be unique: for us it "no".
67  virtual bool yieldsUniqueSeeds() const override { return false; }
68 
69 
70  /**
71  * @brief Configure this policy
72  * @param pset the parameter set for the configuration
73  *
74  * Parameters:
75  * - *algorithm* (string, default: "EventTimestamp_v1"): the name of the
76  * algorithm to get the seed
77  * - *offset* (integer, optional): if specified, all the final seeds are
78  * incremented by this value; the resulting seed is not checked, it
79  * might even be invalid. This is considered an emergency hack when
80  * one absolutely needs to have a different seed than the one assigned
81  * to the event. This also defies the purpose of the policy, since after
82  * this, to reproduce the random sequences the additional knowledge of
83  * which offset was used is necessary.
84  */
85  virtual void configure(fhicl::ParameterSet const& pset) override;
86 
87  /// Prints the details of the configuration of the random generator
88  virtual void print(std::ostream& out) const override;
89 
90 
91  /// Default algorithm version
92  static constexpr const char* DefaultVersion = "v1";
93 
94 
95  /// Converts some information into a valid seed by means of hash values
96  template <typename Hashable>
97  static seed_t SeedFromHash(Hashable const& info)
98  { return makeValid(std::hash<Hashable>()(info)); }
99 
100  /// Converts run, subrun and event numbers into a string
102 
103  /// Converts event ID and timestamp information into a string
104  static std::string UniqueEventString(EventData_t const& info);
105 
106 
107  private:
108  /// type for seed offset
110 
111  SeedAlgo_t algo; ///< the algorithm to extract the seed
112 
113  SeedOffset_t offset; ///< offset added to all the seeds
114 
115  /// Per-job seed: invalid seeds are returned
117  { return base_t::InvalidSeed; }
118 
119  /**
120  * @brief Returns a seed proper for the specified event information
121  * @param id random number engine ID (moule label and instance name)
122  * @param info event information
123  * @return a seed specific to the information provided
124  *
125  * The algorithm used to combine the provided information into a seed is
126  * defined by the configuration. The following algorithms are supported:
127  * - *EventTimestamp_v1*: includes event ID (run, subrun and event
128  * numbers), event timestamp, process name and engine ID into a hash
129  * value, used for the seed
130  */
131  virtual seed_t createEventSeed
132  (SeedMasterHelper::EngineId const& id, EventData_t const& info)
133  override;
134 
135  /// Renders a seed valid
136  template <typename T>
138 
139  /// Implementation of the EventTimestamp_v1 algorithm
141  (SeedMasterHelper::EngineId const& id, EventData_t const& info);
142 
143 
144  //@{
145  /// Algorithm name (manual) handling
146  static const std::vector<std::string> algoNames;
147 
148  static std::vector<std::string> InitAlgoNames();
149  //@}
150  }; // class PerEventPolicy<>
151 
152 
153 
154  //--------------------------------------------------------------------------
155  //--- PerEventPolicy template implementation
156  //---
157  template <typename SEED>
158  std::vector<std::string> PerEventPolicy<SEED>::InitAlgoNames() {
159 
160  std::vector<std::string> names((size_t) NAlgos);
161 
162  names[saEventTimestamp_v1] = "EventTimestamp_v1";
163 
164  return names;
165  } // PerEventPolicy<SEED>::InitAlgoNames()
166 
167 
168  template <typename SEED>
169  const std::vector<std::string> PerEventPolicy<SEED>::algoNames
171 
172 
173  //--------------------------------------------------------------------------
174  template <typename SEED>
176  (EventData_t const& info)
177  {
178  std::ostringstream sstr;
179  sstr << "Run: " << info.runNumber << " Subrun: " << info.subRunNumber
180  << " Event: " << info.eventNumber;
181  return sstr.str();
182  } // PerEventPolicy<SEED>::UniqueEventIDString()
183 
184 
185  template <typename SEED>
187  (EventData_t const& info)
188  {
189  std::ostringstream sstr;
190  sstr << " Timestamp: " << info.time;
191  return UniqueEventIDString(info) + sstr.str();
192  } // PerEventPolicy<SEED>::UniqueEventString()
193 
194 
195  template <typename SEED>
197  (SeedMasterHelper::EngineId const& id, EventData_t const& info)
198  -> seed_t
199  {
200  if (!info.isTimeValid) {
202  << "Input event has an invalid timestamp,"
203  " random seed per-event policy EventTimestamp_v1 can't be used.\n";
204  }
206  + " Process: " + info.processName
207  + " Module: " + id.moduleLabel;
208  if (!id.instanceName.empty())
209  s.append(" Instance: ").append(id.instanceName);
210  seed_t seed = SeedFromHash(s);
211  MF_LOG_DEBUG("PerEventPolicy") << "Seed from: '" << s << "': " << seed;
212  return seed;
213  } // PerEventPolicy<SEED>::EventTimestamp_v1()
214 
215 
216  //--------------------------------------------------------------------------
217  template <typename SEED>
219  // set the algorithm
220  algo = saUndefined;
221  std::string algorithm_name
222  = pset.get<std::string>("algorithm", "default");
223 
224  if (algorithm_name == "default") algo = saDefault;
225  else {
226  for (size_t iAlgo = 0; iAlgo < (size_t) NAlgos; ++iAlgo) {
227  if (algorithm_name != algoNames[iAlgo]) continue;
228  algo = (SeedAlgo_t) iAlgo;
229  break;
230  } // for
231  }
232  if (algo == saUndefined) {
234  << "No valid event random seed algorithm specified!\n";
235  }
236 
237  // read an optional overall offset
238  offset = pset.get<SeedOffset_t>("offset", 0);
239 
240  // EventTimestamp_v1 does not require specific configuration
241 
242  } // PerEventPolicy<SEED>::configure()
243 
244 
245  //--------------------------------------------------------------------------
246  /// Prints the details of the configuration of the random generator
247  template <typename SEED>
248  void PerEventPolicy<SEED>::print(std::ostream& out) const {
249  base_t::print(out);
250  out
251  << "\n algorithm version: " << algoNames[algo];
252  if (offset != 0)
253  out << "\n constant offset: " << offset;
254  } // PerEventPolicy<SEED>::print()
255 
256 
257  //--------------------------------------------------------------------------
258  template <typename SEED>
260  (SeedMasterHelper::EngineId const& id, EventData_t const& info)
261  {
263  switch (algo) {
264  case saEventTimestamp_v1:
265  seed = EventTimestamp_v1(id, info);
266  break;
267  case saUndefined:
269  << "Per-event random number seeder not configured!\n";
270  default:
272  << "Unsupported per-event random number seeder (#"
273  << ((int) algo) << ")\n";
274  } // switch
275  return seed + offset;
276  } // PerEventPolicy<SEED>::createEventSeed()
277 
278 
279  } // namespace details
280 
281 } // namespace rndm
282 
283 
284 #endif // NUTOOLS_RANDOMUTILS_PROVIDERS_PEREVENTPOLICY_H
virtual void print(std::ostream &out) const override
Prints the details of the configuration of the random generator.
virtual seed_t createEventSeed(SeedMasterHelper::EngineId const &id, EventData_t const &info) override
Returns a seed proper for the specified event information.
static std::string UniqueEventIDString(EventData_t const &info)
Converts run, subrun and event numbers into a string.
SEED seed_t
type of the random seed
Definition: BasePolicies.h:45
static seed_t EventTimestamp_v1(SeedMasterHelper::EngineId const &id, EventData_t const &info)
Implementation of the EventTimestamp_v1 algorithm.
std::string string
Definition: nybbler.cc:12
SeedOffset_t offset
offset added to all the seeds
Simple data structure with data needed to extract a seed from a event.
virtual seed_t createSeed(SeedMasterHelper::EngineId const &) override
Per-job seed: invalid seeds are returned.
total number of seed algorithms
typename std::make_signed< seed_t >::type SeedOffset_t
type for seed offset
virtual void print(std::ostream &out) const
Prints information on the configuration of this policy.
Definition: BasePolicies.h:76
std::string processName
name of the running process
virtual void configure(fhicl::ParameterSet const &pset) override
Configure this policy.
static seed_t SeedFromHash(Hashable const &info)
Converts some information into a valid seed by means of hash values.
typename base_t::seed_t seed_t
static std::vector< std::string > InitAlgoNames()
Interface for a policy implementation.
Definition: BasePolicies.h:43
T get(std::string const &key) const
Definition: ParameterSet.h:231
static const std::vector< std::string > algoNames
Algorithm name (manual) handling.
Identifier for a engine, made of module name and optional instance name.
Definition: EngineId.h:22
SeedAlgo_t algo
the algorithm to extract the seed
static seed_t makeValid(T value)
Renders a seed valid.
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
Implementation of the "perEvent" policy.
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1225
Class storing a seed in the valid range.
static QCString type
Definition: declinfo.cpp:672
#define MF_LOG_DEBUG(id)
static constexpr seed_t InvalidSeed
An invalid seed.
Definition: BasePolicies.h:51
PerEventPolicy(fhicl::ParameterSet const &pset)
static constexpr const char * DefaultVersion
Default algorithm version.
static QCString * s
Definition: config.cpp:1042
static std::string UniqueEventString(EventData_t const &info)
Converts event ID and timestamp information into a string.
virtual bool yieldsUniqueSeeds() const override
Returns whether the returned seed should be unique: for us it "no".