SeedMaster.h
Go to the documentation of this file.
1 /**
2  * @file SeedMaster.h
3  * @brief A class to assist in the distribution of guaranteed unique seeds
4  * @author Gianluca Petrillo (petrillo@fnal.gov)
5  * @date 20141111
6  * @see NuRandomService.h SeedMaster.cc
7  */
8 
9 #ifndef NUTOOLS_RANDOMUTILS_PROVIDERS_SEEDMASTER_H
10 #define NUTOOLS_RANDOMUTILS_PROVIDERS_SEEDMASTER_H 1
11 
12 // C/C++ standard libraries
13 #include <vector>
14 #include <string>
15 #include <map>
16 #include <memory> // std::unique_ptr<>
17 #include <utility> // std::forward()
18 
19 // From art and its tool chain
20 #include "fhiclcpp/ParameterSet.h"
22 
23 // Some helper classes
24 #include "nutools/RandomUtils/Providers/MapKeyIterator.h"
25 #include "nutools/RandomUtils/Providers/EngineId.h"
26 #include "nutools/RandomUtils/Providers/Policies.h"
27 #include "nutools/RandomUtils/Providers/EventSeedInputData.h"
28 
29 // more headers included in the implementation section below
30 
31 
32 // The master list of all the policies
33 #define SEED_SERVICE_POLICIES \
34  SEED_SERVICE_POLICY(unDefined) \
35  SEED_SERVICE_POLICY(autoIncrement) \
36  SEED_SERVICE_POLICY(linearMapping) \
37  SEED_SERVICE_POLICY(preDefinedOffset) \
38  SEED_SERVICE_POLICY(preDefinedSeed) \
39  SEED_SERVICE_POLICY(random) \
40  SEED_SERVICE_POLICY(perEvent) \
41  /**/
42 
43 
44 namespace rndm {
45 
46  /**
47  * @brief A class to assist in the distribution of guaranteed unique seeds to all engine IDs.
48  * @tparam SEED type of random engine seed
49  * @see NuRandomService
50  *
51  * @attention direct use of this class is limited to art-less contexts;
52  * within art, use `rndm::NuRandomService` instead.
53  *
54  * This class is configured from a FHiCL parameter set.
55  * The complete configuration depends on the policy chosen; the following
56  * parameters are common to all the policies:
57  *
58  * NuRandomService : {
59  * policy : "autoIncrement" // Required: Other legal value are listed in SEED_SERVICE_POLICIES
60  * verbosity : 0 // Optional: default=0, no informational printout
61  * endOfJobSummary : false // Optional: print list of all managed seeds at end of job.
62  * }
63  *
64  * The policy parameter tells the service to which algorithm to use.
65  * If the value of the policy parameter is not one of the known policies, the code will
66  * throw an exception.
67  *
68  * Code instanciating a SeedMaster can request a seed by making one of the
69  * following two calls:
70  *
71  * SeedMasterInstance.getSeed("moduleLabel");
72  * SeedMasterInstance.getSeed("moduleLabel", "instanceName");
73  *
74  * art module code requests a seed directly to NuRandomService service.
75  *
76  * It is the callers responsibility to use the appropriate form.
77  *
78  * When `getSeed` is called with a particular module label and instance name, it computes
79  * a seed value, saves it and returns it. If there is a subsequent call to `getSeed` with
80  * the same module label and instance name, the class will return the saved value of
81  * the seed. The following text will use the phrase "unique calls to `getSeed`"; two
82  * calls with the same module label and instance names are not considered unique.
83  *
84  * If the policy is defined as `autoIncrement`, the additional configurable
85  * items are:
86  *
87  * NuRandomService : {
88  * policy : "autoIncrement"
89  * // ... and all the common ones, plus:
90  * baseSeed : 0 // Required: An integer >= 0.
91  * checkRange : true // Optional: legal values true (default) or false
92  * maxUniqueEngines : 20 // Required iff checkRange is true.
93  * }
94  *
95  * In this policy, the seed is set to `baseSeed`+`offset`, where
96  * on the first unique call to `getSeed` the `offset` is set to 0; on the
97  * second unique call to `getSeed` it is set to 1, and so on.
98  *
99  * If the policy is defined as `linearMapping`, the additional configurable
100  * items are:
101  *
102  * NuRandomService : {
103  * policy : "linearMapping"
104  * // ... and all the common ones, plus:
105  * nJob : 0 // Required: An integer >= 0.
106  * checkRange : true // Optional: legal values true (default) or false
107  * maxUniqueEngines : 20 // Required iff checkRange is true.
108  * }
109  *
110  * In this policy, the seed is set to
111  * `maxUniqueEngines`*`nJob`+`offset`, where on the first unique call to `getSeed`
112  * the `offset` is set to 0; on the second unique call to `getSeed` it is set to 1,
113  * and so on.
114  *
115  * If the policy is defined as `preDefinedOffset`, the additional configurable
116  * items are:
117  *
118  * NuRandomService : {
119  * policy : "preDefinedOffset"
120  * // ... and all the common ones, plus:
121  * baseSeed : 0 // Required: An integer >= 0.
122  * checkRange : true // Optional: legal values true (default) or false
123  * maxUniqueEngines : 20 // Required iff checkRange is true
124  *
125  * module_label1: offset1 // for each module with a nameless engine
126  * module_label2: { // for each module with nemed engine instances
127  * instance_name1: offset21 // ... one entry for each instance name
128  * instance_name2: offset22
129  * }
130  * }
131  *
132  * In this policy, when `getSeed` is called, the class will look
133  * into the parameter set to find a defined offset for the specified module label
134  * and instance name. The returned value of the seed will be `baseSeed`+`offset`.
135  *
136  * If the policy is defined as `preDefinedSeed`, the additional configurable
137  * items are:
138  *
139  * NuRandomService : {
140  * policy : "preDefinedSeed"
141  * // ... and all the common ones, plus:
142  *
143  * module_label1: seed1 // for each module with a nameless engine
144  * module_label2: { // for each module with nemed engine instances
145  * instance_name1: seed21 // ... one entry for each instance name
146  * instance_name2: seed22
147  * }
148  * }
149  *
150  * This policy allows to specify the actual seed to be used.
151  * Note that the policy
152  * does not impose any constraint on the user-provided set of seeds.
153  * In particular, the uniqueness of the seeds is not
154  * enforced. Intended for debugging and special tests, use with care.
155  *
156  * If the policy is defined as `random`, the additional configurable
157  * items are:
158  *
159  * NuRandomService : {
160  * policy : "random"
161  * // ... and all the common ones, plus:
162  * masterSeed: master_seed // optional: an integer >= 0
163  * }
164  *
165  * With this policy, the seed is extracted from a local random number
166  * generator.
167  * The seed used to initialize this additional random number generatot is
168  * taken from the clock, unless the `masterSeed` parameter is set to specify
169  * the actual seed.
170  * This policy is meant as a quick way to disentangle the code from the
171  * random seed policy used, and it's meant for special needs only and
172  * definitely not for production.
173  * You can enable this policy instead of whatever is already in your
174  * configuration by adding at the end of your configuration:
175  *
176  * services.NuRandomService.policy: "random"
177  *
178  * (this assumes that the configuration of the SeedMaster is read from
179  * `services.NuRandomService`, that is the case in the art framework).
180  *
181  * The FHiCL grammar to specify the offsets takes two forms. If no instance name
182  * is given, the offset is given by:
183  *
184  * moduleLabel : offset
185  *
186  * When a module has multiple instances, the offsets are given by:
187  *
188  * moduleLabel : {
189  * instanceName1 : offset1
190  * instanceName2 : offset2
191  * }
192  *
193  * `SeedMaster` does several additional checks, except for the `preDefinedSeed` policy.
194  *
195  * If one (module label, instance name) has the same seed as another (module label, instance name),
196  * the class will throw an exception.
197  *
198  * If the `checkRange` parameter is set to `true`, and if an offset is generated with a value outside
199  * the allowed range (typically `0<= offset < maxUniqueEngines-1`) then the class will also throw an exception.
200  *
201  * It is the responsibility of the user to ensure that the parameters
202  * (e.g. `nJob` and `maxUniqueEngines`) are chosen
203  * it a way that ensures the required level of uniqueness of seeds. The example grid jobs have
204  * a single point of maintenance to achieve this: the user must specify the starting job number
205  * for each grid submission.
206  */
207  template <typename SEED>
208  class SeedMaster {
209  public:
210  using seed_t = SEED; ///< type of served seeds
211  using SeedMaster_t = SeedMaster<SEED>; ///< type of this class
212 
213  using EngineId = SeedMasterHelper::EngineId; ///< type of engine ID
214 
215  /// type of a function setting a seed
216  using Seeder_t = std::function<void(EngineId const&, seed_t)>;
217 
218  private:
219  /// Type of abstract class for policy implementation
221 
222  /// Type for seed data base
223  using map_type = std::map<EngineId, seed_t>;
224 
225  /// Information for each engine
226  struct EngineInfo_t {
227  public:
228  bool hasSeeder() const { return bool(seeder); }
229  bool isFrozen() const { return !autoseed; }
230 
231  void freeze(bool doFreeze = true) { autoseed = !doFreeze; }
232  void setSeeder(Seeder_t new_seeder) { seeder = new_seeder; }
233 
234  /// Execute the seeder (whatever arguments it has...)
235  template <typename... Args>
236  void applySeed(Args... args) const
237  { if (hasSeeder()) seeder(std::forward<Args>(args)...); }
238 
239  /// Applies the seed unless frozen
240  template <typename... Args>
241  void autoApplySeed(Args... args) const
242  { if (!isFrozen()) applySeed(std::forward<Args>(args)...); }
243 
244  private:
245  Seeder_t seeder; ///< engine seeder
246  bool autoseed = true; ///< whether seeding can be automatic
247 
248  }; // EngineInfo_t
249 
250  /// type of map of seeders associated with the engines
251  using EngineData_t = std::map<EngineId, EngineInfo_t>;
252 
253  public:
254  /// type of data used for event seeds
256 
257  /// An invalid seed
259 
260  enum Policy {
261 #define SEED_SERVICE_POLICY(x) x,
263 #undef SEED_SERVICE_POLICY
264  };
265 
266  static const std::vector<std::string>& policyNames();
267 
268  /// An iterator to the configured engine IDs
271 
273 
274  // Accept compiler written c'tors, assignments and d'tor.
275 
276  /// Returns whether the specified engine is already registered
277  bool hasEngine(EngineId const& id) const
278  { return engineData.count(id) > 0; }
279 
280  /// Returns whether the specified engine has a valid seeder
281  bool hasSeeder(EngineId const& id) const
282  {
283  auto iEngineInfo = engineData.find(id);
284  return
285  (iEngineInfo != engineData.end()) && iEngineInfo->second.hasSeeder();
286  }
287 
288  /// Returns the seed value for this module label
289  seed_t getSeed(std::string moduleLabel);
290 
291  /// Returns the seed value for this module label and instance name
292  seed_t getSeed(std::string moduleLabel, std::string instanceName);
293 
294  /// Returns the seed value for the engine with the specified ID
295  seed_t getSeed(EngineId const&);
296 
297  //@{
298  /// Returns the seed value for the event with specified data
300  (EventData_t const& data, std::string instanceName);
301  seed_t getEventSeed(EventData_t const& data, EngineId const& id);
302  //@}
303 
304  /// Returns the last computed seed value for the specified engine ID
305  seed_t getCurrentSeed(EngineId const& id) const
306  { return getSeedFromMap(currentSeeds, id); }
307 
308 
309  /**
310  * @brief Register the specified function to reseed the engine id
311  * @param id ID of the engine to be associated to the seeder
312  * @param seeder function to be used for seeding the engine
313  *
314  * SeedMaster keeps a list of functions that can be used to reseed an
315  * existing engine.
316  * When reseedEvent() (or reseed()) is called, these functions are invoked
317  * to set the seed to the engine.
318  */
319  void registerSeeder(EngineId const& id, Seeder_t seeder);
320 
321 
322  /**
323  * @brief Register the specified function to reseed the engine id
324  * @param id ID of the engine to be associated to the seeder
325  * @param seeder function to be used for seeding the engine
326  * @throw art::Exception (art::errors::LogicError) if already registered
327  * @see registerSeeder()
328  *
329  * This method registers a seeder for a given engine ID, just as
330  * registerSeeder() does, except that it throws an exception if a seeder has
331  * already been registered for it.
332  */
333  void registerNewSeeder(EngineId const& id, Seeder_t seeder);
334 
335 
336  /// Forces SeedMaster not to change the seed of a registered engine
337  void freezeSeed(EngineId const& id, seed_t seed);
338 
339 
340  /**
341  * @brief Reseeds the specified engine with a global seed (if any)
342  * @param id ID of the engine to be reseeded
343  * @return the seed used to reseed, InvalidSeed if no reseeding happened
344  *
345  * Reseeding does not happen if either there is no seeder registered with
346  * that engine, or if that engine is already frozen.
347  */
348  seed_t reseed(EngineId const& id);
349 
350  /**
351  * @brief Reseeds the specified engine with an event seed (if any)
352  * @param id ID of the engine to be reseeded
353  * @param data event data to extract the seed from
354  * @return the seed used to reseed, InvalidSeed if no reseeding happened
355  *
356  * Reseeding does not happen if either there is no seeder registered with
357  * that engine, or if that engine is already frozen.
358  */
359  seed_t reseedEvent(EngineId const& id, EventData_t const& data);
360 
361  /// Prints known (EngineId,seed) pairs
362  template<typename Stream> void print(Stream&&) const;
363 
364  /// Returns an object to iterate in range-for through configured engine IDs
366 
367  /// Prepares for a new event
368  void onNewEvent();
369 
370  /// Prints to the framework Info logger
371  void print() const { print(mf::LogVerbatim("SEEDS")); }
372 
373  private:
374  /// Control the level of information messages
376 
377  /// Which of the supported policies to use?
379 
380  /// List of seeds computed from configuration information.
382 
383  /// List of event seeds already computed.
385 
386  /// List of seeds already computed.
388 
389  EngineData_t engineData; ///< list of all engine information
390 
391  /// Helper function to parse the policy name
392  void setPolicy(std::string policyName);
393 
394  /// @{
395  /// @brief Throws if the seed has already been used
396  ///
397  /// It does not take into account per-event seeds, but only configured ones.
398  void ensureUnique
399  (EngineId const& id, seed_t seed, map_type const& map) const;
400  void ensureUnique(EngineId const& id, seed_t seed) const
401  { return ensureUnique(id, seed, configuredSeeds); }
402  /// @}
403 
404  /// the instance of the random policy
405  std::unique_ptr<PolicyImpl_t> policy_impl;
406 
407 
408  /// Returns a seed from the specified map, or InvalidSeed if not present
409  static seed_t getSeedFromMap(map_type const& seeds, EngineId const& id)
410  {
411  auto iSeed = seeds.find(id);
412  return (iSeed == seeds.end())? InvalidSeed: iSeed->second;
413  }
414 
415  }; // class SeedMaster
416 
417 } // namespace rndm
418 
419 
420 //==============================================================================
421 //=== Template implementation
422 //===
423 
424 
425 // C++ include files
426 #include <ostream>
427 #include <iomanip> // std::setw()
428 #include <ostream> // std::endl
429 #include <algorithm> // std::find(), std::copy()
430 #include <iterator> // std::ostream_iterator<>, std::distance()
431 
432 // Supporting library include files
434 
435 // Art include files
437 
438 
439 //----------------------------------------------------------------------------
440 template <typename SEED>
441 std::vector<std::string> const& rndm::SeedMaster<SEED>::policyNames() {
442  static std::vector<std::string> names;
443  if(names.empty()) {
444  const char *cnames[] = {
445 #define SEED_SERVICE_POLICY(x) #x,
447 #undef SEED_SERVICE_POLICY
448  };
449  names = std::vector<std::string>
450  (cnames, cnames + sizeof(cnames)/sizeof(cnames[0]));
451  }
452 
453  return names;
454 } // SeedMaster<SEED>::policyNames()
455 
456 
457 
458 //----------------------------------------------------------------------------
459 template <typename SEED>
461  verbosity(pSet.get<int>("verbosity",0)),
462  policy(unDefined),
463  configuredSeeds(),
464  knownEventSeeds(),
465  currentSeeds(),
466  engineData()
467 {
468 
469  // Throw if policy is not recognized.
470  const std::string strPolicy = pSet.get<std::string>("policy");
471  setPolicy(strPolicy);
472 
473  // Finish parsing the parameter set, as required by the selected policy
474  switch(policy) {
475  case autoIncrement:
477  break;
478  case linearMapping:
480  break;
481  case preDefinedOffset:
483  break;
484  case preDefinedSeed:
486  break;
487  case random:
489  break;
490  case perEvent:
492  break;
493  default:
495  << "SeedMaster(): Internal error: unknown policy_ value";
496  } // switch
497 
498  if ( verbosity > 0 )
499  print(mf::LogVerbatim("SeedMaster"));
500 
501 } // SeedMaster<SEED>::SeedMaster()
502 
503 
504 
505 //----------------------------------------------------------------------------
506 template <typename SEED>
507 inline typename rndm::SeedMaster<SEED>::seed_t
509  (std::string moduleLabel)
510 {
511  return getSeed(EngineId(moduleLabel));
512 } // SeedMaster<SEED>::getSeed(string)
513 
514 
515 //----------------------------------------------------------------------------
516 template <typename SEED>
518  (std::string moduleLabel, std::string instanceName)
519 {
520  return getSeed(EngineId(moduleLabel,instanceName));
521 } // SeedMaster<SEED>::getSeed(string, string)
522 
523 
524 //----------------------------------------------------------------------------
525 template <typename SEED>
527  (EngineId const& id, Seeder_t seeder)
528 {
529  engineData[id].setSeeder(seeder); // creates anew and sets
530 } // SeedMaster<SEED>::registerSeeder()
531 
532 
533 //----------------------------------------------------------------------------
534 template <typename SEED>
536  (EngineId const& id, Seeder_t seeder)
537 {
538  if (hasEngine(id)) {
540  << "SeedMaster(): Engine with ID='" << id << "' already registered";
541  }
542  registerSeeder(id, seeder);
543 } // SeedMaster<SEED>::registerNewSeeder()
544 
545 
546 //----------------------------------------------------------------------------
547 template <typename SEED>
549  engineData.at(id).freeze();
550  configuredSeeds[id] = seed;
551  currentSeeds[id] = seed;
552 } // SeedMaster<>::freezeSeed()
553 
554 
555 //----------------------------------------------------------------------------
556 template <typename SEED>
558  (EngineId const& id)
559 {
560  auto const& engineInfo = engineData.at(id);
561  if (engineInfo.isFrozen()) return InvalidSeed;
562  seed_t seed = getSeed(id);
563  if (seed != InvalidSeed) { // reseed
564  engineInfo.applySeed(id, seed);
565  }
566  return seed;
567 } // SeedMaster<SEED>::reseed()
568 
569 
570 template <typename SEED>
572  (EngineId const& id, EventData_t const& data)
573 {
574  auto const& engineInfo = engineData.at(id);
575  if (engineInfo.isFrozen()) return InvalidSeed;
576  seed_t seed = getEventSeed(data, id);
577  if (seed != InvalidSeed) { // reseed
578  engineInfo.autoApplySeed(id, seed);
579  }
580  return seed;
581 } // SeedMaster<SEED>::reseedEvent()
582 
583 
584 
585 //----------------------------------------------------------------------------
586 template <typename SEED> template <typename Stream>
587 void rndm::SeedMaster<SEED>::print(Stream&& log) const {
588  log << "\nSummary of seeds computed by the NuRandomService";
589 
590  // allow the policy implementation to print whatever it feels to
591  std::ostringstream sstr;
592  policy_impl->print(sstr);
593  if (!sstr.str().empty()) log << '\n' << sstr.str();
594 
595  if ( !currentSeeds.empty() ) {
596 
597  constexpr unsigned int ConfSeedWidth = 18;
598  constexpr unsigned int SepWidth1 = 2;
599  constexpr unsigned int LastSeedWidth = 18;
600  constexpr unsigned int SepWidth2 = SepWidth1 + 1;
601 
602  log << "\n "
603  << std::setw(ConfSeedWidth) << "Configured value"
604  << std::setw(SepWidth1) << ""
605  << std::setw(LastSeedWidth) << "Last value"
606  << std::setw(SepWidth2) << ""
607  << "ModuleLabel.InstanceName";
608 
609  for (auto const& p: currentSeeds) {
610  EngineId const& ID = p.first;
611  seed_t configuredSeed = getSeedFromMap(configuredSeeds, ID);
612  seed_t currentSeed = p.second;
613 
614  if (configuredSeed == InvalidSeed) {
615  if (currentSeed == InvalidSeed) {
616  log << "\n "
617  << std::setw(ConfSeedWidth) << "INVALID!!!"
618  << std::setw(SepWidth1) << ""
619  << std::setw(LastSeedWidth) << ""
620  << std::setw(SepWidth2) << ""
621  << ID;
622  }
623  else { // if seed was configured, it should be that one all the way!!
624  log << "\n "
625  << std::setw(ConfSeedWidth) << "(per event)"
626  << std::setw(SepWidth1) << ""
627  << std::setw(LastSeedWidth) << currentSeed
628  << std::setw(SepWidth2) << ""
629  << ID;
630  }
631  }
632  else {
633  if (configuredSeed == currentSeed) {
634  log << "\n "
635  << std::setw(ConfSeedWidth) << configuredSeed
636  << std::setw(SepWidth1) << ""
637  << std::setw(LastSeedWidth) << "(same)"
638  << std::setw(SepWidth2) << ""
639  << ID;
640  }
641  else { // if seed was configured, it should be that one all the way!!
642  log << "\n "
643  << std::setw(ConfSeedWidth) << configuredSeed
644  << std::setw(SepWidth1) << ""
645  << std::setw(LastSeedWidth) << currentSeed
646  << std::setw(SepWidth2) << ""
647  << ID << " [[ERROR!!!]]";
648  }
649  } // if per job
650  if (ID.isGlobal()) log << " (global)";
651  if (hasEngine(ID) && engineData.at(ID).isFrozen()) log << " [overridden]";
652  } // for all seeds
653  } // if any seed
654  log << '\n' << std::endl;
655 } // SeedMaster<SEED>::print(Stream)
656 
657 
658 //----------------------------------------------------------------------------
659 template <typename SEED>
661  (EngineId const& id)
662 {
663  // Check for an already computed seed.
664  typename map_type::const_iterator iSeed = configuredSeeds.find(id);
665  seed_t seed = InvalidSeed;
666  if (iSeed != configuredSeeds.end()) return iSeed->second;
667 
668  // Compute the seed.
669  seed = policy_impl->getSeed(id);
670  if (policy_impl->yieldsUniqueSeeds()) ensureUnique(id, seed);
671 
672  // Save the result.
673  configuredSeeds[id] = seed;
674 
675  // for per-event policies, configured seed is invalid;
676  // in that case we don't expect to change the seed,
677  // and we should not record it as current; this should not matter anyway
678  // we still store it if there is nothing (emplace does not overwrite)
679  if (seed != InvalidSeed) currentSeeds[id] = seed;
680  else currentSeeds.emplace(id, seed);
681 
682  return seed;
683 } // SeedMaster<SEED>::getSeed()
684 
685 
686 //----------------------------------------------------------------------------
687 template <typename SEED>
689  (EventData_t const& data, EngineId const& id)
690 {
691  // Check for an already computed seed.
692  typename map_type::iterator iSeed = knownEventSeeds.find(id);
693  seed_t seed = InvalidSeed;
694  if (iSeed != knownEventSeeds.end()) return iSeed->second;
695 
696  // Compute the seed.
697  seed = policy_impl->getEventSeed(id, data);
698  if ((seed != InvalidSeed) && policy_impl->yieldsUniqueSeeds())
699  ensureUnique(id, seed, knownEventSeeds);
700 
701  // Save the result.
702  knownEventSeeds[id] = seed;
703 
704  // for configured-seed policies, per-event seed is invalid;
705  // in that case we don't expect to change the seed,
706  // and we should not record it as current
707  // we still store it if there is nothing (emplace does not overwrite)
708  if (seed != InvalidSeed) currentSeeds[id] = seed;
709  else currentSeeds.emplace(id, seed);
710 
711  return seed;
712 } // SeedMaster<SEED>::getEventSeed(EngineId)
713 
714 
715 template <typename SEED>
717  (EventData_t const& data, std::string instanceName)
718 {
719  return getEventSeed(data, EngineId(data.moduleLabel, instanceName));
720 } // SeedMaster<SEED>::getEventSeed(string)
721 
722 
723 
724 //----------------------------------------------------------------------------
725 template <typename SEED>
727  // forget all we know about the current event
728  knownEventSeeds.clear();
729 } // SeedMaster<SEED>::onNewEvent()
730 
731 
732 //----------------------------------------------------------------------------
733 template <typename SEED>
735 
737  = std::find(policyNames().begin(), policyNames().end(), policyName);
738  if (iter != policyNames().end()) {
739  policy = Policy(std::distance(policyNames().begin(), iter));
740  }
741 
742  if (policy == unDefined) {
743  std::ostringstream os;
744  os<< "NuRandomService::setPolicy(): Unrecognized policy: "
745  << policyName
746  << "\n Known policies are: ";
747 
749  std::ostream_iterator<std::string>(os, ", "));
750 
751  throw art::Exception(art::errors::Configuration) << os.str();
752  }
753 } // SeedMaster<SEED>::setPolicy()
754 
755 
756 //----------------------------------------------------------------------------
757 template <typename SEED>
759  (EngineId const& id, seed_t seed, map_type const& seeds) const
760 {
761 
762  for (auto const& p: seeds) {
763 
764  // Do not compare to self
765  if ( p.first == id ) continue;
766 
767  if ( p.second == seed ){
769  << "NuRandomService::ensureUnique() seed: "<<seed
770  << " already used by module.instance: " << p.first << "\n"
771  << "May not be reused by module.instance: " << id;
772  }
773  } // for
774 } // SeedMaster<SEED>::ensureUnique()
775 
776 
777 #endif // NUTOOLS_RANDOMUTILS_PROVIDERS_SEEDMASTER_H
void setPolicy(std::string policyName)
Helper function to parse the policy name.
Definition: SeedMaster.h:734
A class to assist in the distribution of guaranteed unique seeds to all engine IDs.
Definition: SeedMaster.h:208
intermediate_table::iterator iterator
void applySeed(Args...args) const
Execute the seeder (whatever arguments it has...)
Definition: SeedMaster.h:236
NuRandomServiceHelper::EventSeedInputData EventData_t
type of data used for event seeds
Definition: BasePolicies.h:48
bool autoseed
whether seeding can be automatic
Definition: SeedMaster.h:246
std::map< EngineId, EngineInfo_t > EngineData_t
type of map of seeders associated with the engines
Definition: SeedMaster.h:251
void print() const
Prints to the framework Info logger.
Definition: SeedMaster.h:371
std::string string
Definition: nybbler.cc:12
unsigned int ID
bool hasSeeder(EngineId const &id) const
Returns whether the specified engine has a valid seeder.
Definition: SeedMaster.h:281
map_type knownEventSeeds
List of event seeds already computed.
Definition: SeedMaster.h:384
int verbosity
Control the level of information messages.
Definition: SeedMaster.h:375
static constexpr seed_t InvalidSeed
An invalid seed.
Definition: SeedMaster.h:258
intermediate_table::const_iterator const_iterator
std::map< EngineId, seed_t > map_type
Type for seed data base.
Definition: SeedMaster.h:223
Implementation of the "preDefinedOffset" policy.
Definition: BasePolicies.h:693
static QCString args
Definition: declinfo.cpp:674
seed_t getEventSeed(EventData_t const &data, std::string instanceName)
Returns the seed value for the event with specified data.
Definition: SeedMaster.h:717
map_type currentSeeds
List of seeds already computed.
Definition: SeedMaster.h:387
bool hasEngine(EngineId const &id) const
Returns whether the specified engine is already registered.
Definition: SeedMaster.h:277
Implementation of the "random" policy.
Definition: BasePolicies.h:781
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
static seed_t getSeedFromMap(map_type const &seeds, EngineId const &id)
Returns a seed from the specified map, or InvalidSeed if not present.
Definition: SeedMaster.h:409
seed_t seed_t
type of served seeds
Definition: SeedMaster.h:210
SeedMasterHelper::EngineId EngineId
type of engine ID
Definition: SeedMaster.h:213
void registerNewSeeder(EngineId const &id, Seeder_t seeder)
Register the specified function to reseed the engine id.
Definition: SeedMaster.h:536
Interface for a policy implementation.
Definition: BasePolicies.h:43
std::function< void(EngineId const &, seed_t)> Seeder_t
type of a function setting a seed
Definition: SeedMaster.h:216
Implementation of the "autoIncrement" policy.
Definition: BasePolicies.h:343
typename PolicyImpl_t::EventData_t EventData_t
type of data used for event seeds
Definition: SeedMaster.h:255
T get(std::string const &key) const
Definition: ParameterSet.h:231
void freezeSeed(EngineId const &id, seed_t seed)
Forces SeedMaster not to change the seed of a registered engine.
Definition: SeedMaster.h:548
Implementation of the "preDefinedSeed" policy.
Definition: BasePolicies.h:625
Identifier for a engine, made of module name and optional instance name.
Definition: EngineId.h:22
static const std::vector< std::string > & policyNames()
Definition: SeedMaster.h:441
Q_EXPORT QTSManip setw(int w)
Definition: qtextstream.h:331
void freeze(bool doFreeze=true)
Definition: SeedMaster.h:231
p
Definition: test.py:223
Implementation of the "linearMapping" policy.
Definition: BasePolicies.h:415
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
std::vector< TrajPoint > seeds
Definition: DataStructs.cxx:13
Policy policy
Which of the supported policies to use?
Definition: SeedMaster.h:378
SeedMaster(const fhicl::ParameterSet &)
Definition: SeedMaster.h:460
Implementation of the "perEvent" policy.
seed_t reseedEvent(EngineId const &id, EventData_t const &data)
Reseeds the specified engine with an event seed (if any)
Definition: SeedMaster.h:572
seed_t getSeed(std::string moduleLabel)
Returns the seed value for this module label.
Definition: SeedMaster.h:509
void onNewEvent()
Prepares for a new event.
Definition: SeedMaster.h:726
void ensureUnique(EngineId const &id, seed_t seed, map_type const &map) const
Throws if the seed has already been used.
Definition: SeedMaster.h:759
bool isGlobal() const
Returns whether the label is "global" (no module context)
Definition: EngineId.h:45
static constexpr seed_t InvalidSeed
An invalid seed.
Definition: BasePolicies.h:51
T copy(T const &v)
Seeder_t seeder
engine seeder
Definition: SeedMaster.h:245
map_type configuredSeeds
List of seeds computed from configuration information.
Definition: SeedMaster.h:381
void setSeeder(Seeder_t new_seeder)
Definition: SeedMaster.h:232
std::unique_ptr< PolicyImpl_t > policy_impl
the instance of the random policy
Definition: SeedMaster.h:405
EngineInfoIteratorBox engineIDsRange() const
Returns an object to iterate in range-for through configured engine IDs.
Definition: SeedMaster.h:365
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
Definition: StdUtils.h:72
EngineData_t engineData
list of all engine information
Definition: SeedMaster.h:389
void registerSeeder(EngineId const &id, Seeder_t seeder)
Register the specified function to reseed the engine id.
Definition: SeedMaster.h:527
seed_t reseed(EngineId const &id)
Reseeds the specified engine with a global seed (if any)
Definition: SeedMaster.h:558
auto const & get(AssnsNode< L, R, D > const &r)
Definition: AssnsNode.h:115
seed_t getCurrentSeed(EngineId const &id) const
Returns the last computed seed value for the specified engine ID.
Definition: SeedMaster.h:305
void autoApplySeed(Args...args) const
Applies the seed unless frozen.
Definition: SeedMaster.h:241
void ensureUnique(EngineId const &id, seed_t seed) const
Definition: SeedMaster.h:400
Provides iterators for std::begin() and std::end()
int bool
Definition: qglobal.h:345
QTextStream & endl(QTextStream &s)
Information for each engine.
Definition: SeedMaster.h:226