12 #include "ThirdParty/parallelstl/include/pstl/algorithm" 13 #include "ThirdParty/parallelstl/include/pstl/execution" 18 inline double uniform(
double random,
double min,
double max) {
19 return random * (max - min) + min;
22 std::tuple<EventCollection, double>
26 double generationMaxValue,
27 std::vector<ComPWA::Event>::const_iterator PhspStartIterator,
28 std::vector<ComPWA::Event>::const_iterator PhspTrueStartIterator,
29 bool InverseIntensityWeighting =
false) {
35 {PhspTrueStartIterator, PhspTrueStartIterator + EventBunchSize}};
36 auto TempDataSet = Kinematics.
convert(NewEvents);
39 auto Intensities = Intensity.
evaluate(TempDataSet.Data);
43 std::vector<double> WeightedIntensities(Intensities.size());
44 std::transform(pstl::execution::par_unseq, Intensities.begin(),
45 Intensities.end(), TempDataSet.Weights.begin(),
46 WeightedIntensities.begin(),
47 [](
double intensity,
double weight) {
48 if (std::isfinite(intensity)) {
49 return intensity * weight;
56 double BunchMax(*std::max_element(pstl::execution::par_unseq,
57 WeightedIntensities.begin(),
58 WeightedIntensities.end()));
61 if (BunchMax > generationMaxValue) {
62 return std::make_tuple(SelectedEvents, BunchMax);
68 std::vector<double> RandomNumbers;
69 RandomNumbers.reserve(WeightedIntensities.size());
70 std::generate_n(std::back_inserter(RandomNumbers), WeightedIntensities.size(),
71 [&RandomGenerator, generationMaxValue]() {
72 return uniform(RandomGenerator(), 0, generationMaxValue);
75 if (InverseIntensityWeighting) {
76 for (
unsigned int i = 0; i < WeightedIntensities.size(); ++i) {
77 if (RandomNumbers[i] < WeightedIntensities[i]) {
78 SelectedEvents.Events.push_back(
79 {PhspStartIterator->FourMomenta, 1.0 / Intensities[i]});
84 for (
unsigned int i = 0; i < WeightedIntensities.size(); ++i) {
85 if (RandomNumbers[i] < WeightedIntensities[i]) {
86 SelectedEvents.Events.push_back({PhspStartIterator->FourMomenta, 1.0});
92 return std::make_tuple(SelectedEvents, BunchMax);
101 if (NumberOfEvents <= 0)
102 return GeneratedEvents;
105 unsigned int EventBunchSize(5000);
106 GeneratedEvents.Events.reserve(NumberOfEvents);
107 unsigned int TotalGeneratedEvents(0);
109 double SafetyMargin(0.05);
110 double generationMaxValue(0.0);
111 unsigned int initialSeed = RandomGenerator.
getSeed();
113 LOG(INFO) <<
"Generating hit-and-miss sample: [" << NumberOfEvents
118 Generator.
generate(EventBunchSize, RandomGenerator);
120 TotalGeneratedEvents += EventBunchSize;
123 generateBunch(EventBunchSize, Kinematics, Intensity, RandomGenerator,
124 generationMaxValue, TempEvents.
Events.begin(),
125 TempEvents.
Events.begin());
128 double MaximumWeight = std::get<1>(Bunch);
131 if (MaximumWeight > generationMaxValue) {
132 generationMaxValue = (1.0 + SafetyMargin) * MaximumWeight;
134 if (GeneratedEvents.Events.size() > 0) {
135 GeneratedEvents.
Events.clear();
136 RandomGenerator.
setSeed(initialSeed);
138 LOG(INFO) <<
"Tools::generate() | Error in HitMiss " 139 "procedure: Maximum value of random number generation " 140 "smaller then amplitude maximum! We raise the maximum " 142 << generationMaxValue <<
" value and restart generation!";
147 size_t AmountToAppend(BunchEvents.Events.size());
148 if (GeneratedEvents.Events.size() + BunchEvents.Events.size() >
150 AmountToAppend = NumberOfEvents - GeneratedEvents.Events.size();
153 GeneratedEvents.Events.insert(
154 GeneratedEvents.Events.end(),
155 std::make_move_iterator(BunchEvents.Events.begin()),
156 std::make_move_iterator(BunchEvents.Events.begin() + AmountToAppend));
157 bar.
next(AmountToAppend);
159 if (GeneratedEvents.Events.size() == NumberOfEvents)
162 LOG(INFO) <<
"Successfully generated " << NumberOfEvents
163 <<
" with an efficiency of " 164 << 1.0 * NumberOfEvents / TotalGeneratedEvents;
166 return GeneratedEvents;
176 if (NumberOfEvents <= 0)
177 throw std::runtime_error(
"Tools::generate() negative number of events: " +
178 std::to_string(NumberOfEvents));
180 if (PhspSampleTrue.
Events.size() != PhspSample.
Events.size())
181 throw std::runtime_error(
182 "Tools::generate() | We have a sample of true " 183 "phsp events, but the sample size doesn't match that one of " 187 GeneratedEvents.Events.resize(NumberOfEvents);
189 double SafetyMargin(0.05);
192 if (PhspSampleTrue.
Events.size()) {
194 if (temp_maxweight > maxSampleWeight)
195 maxSampleWeight = temp_maxweight;
198 if (maxSampleWeight <= 0.0)
199 throw std::runtime_error(
"Tools::generate() Sample maximum value is zero!");
200 double generationMaxValue(maxSampleWeight * (1.0 + SafetyMargin));
201 unsigned int initialSeed = RandomGenerator.
getSeed();
203 LOG(INFO) <<
"Tools::generate() | Using " << generationMaxValue
204 <<
" as maximum value of the intensity.";
206 auto const &PhspEvents = PhspSample;
207 unsigned int LastIndex(PhspEvents.Events.size() - 1);
209 unsigned int EventBunchSize(5000);
210 if (PhspEvents.Events.size() < EventBunchSize)
211 EventBunchSize = PhspEvents.Events.size();
213 auto CurrentStartIterator = PhspEvents.Events.begin();
214 auto CurrentTrueStartIterator = PhspEvents.Events.begin();
215 if (PhspSampleTrue.
Events.size())
216 CurrentTrueStartIterator = PhspSampleTrue.
Events.begin();
217 unsigned int CurrentStartIndex(0);
218 LOG(INFO) <<
"Generating hit-and-miss sample: [" << NumberOfEvents
222 if (CurrentStartIndex + EventBunchSize > LastIndex)
223 EventBunchSize = LastIndex - CurrentStartIndex;
225 auto Bunch =
generateBunch(EventBunchSize, Kinematics, Intensity,
226 RandomGenerator, generationMaxValue,
227 CurrentStartIterator, CurrentTrueStartIterator);
230 double MaximumWeight = std::get<1>(Bunch);
233 if (MaximumWeight > generationMaxValue) {
234 generationMaxValue = (1.0 + SafetyMargin) * MaximumWeight;
235 LOG(INFO) <<
"We raise the maximum to " << generationMaxValue;
236 if (GeneratedEvents.Events.size() > 0) {
237 GeneratedEvents.
Events.clear();
238 RandomGenerator.
setSeed(initialSeed);
239 CurrentStartIterator = PhspEvents.Events.begin();
240 CurrentTrueStartIterator = PhspEvents.Events.begin();
241 if (PhspSampleTrue.
Events.size())
242 CurrentTrueStartIterator = PhspSampleTrue.
Events.begin();
243 CurrentStartIndex = 0;
245 LOG(INFO) <<
"Tools::generate() | Error in HitMiss " 246 "procedure: Maximum value of random number generation " 247 "smaller then amplitude maximum! Restarting generation!";
252 size_t AmountToAppend(BunchEvents.
Events.size());
253 if (GeneratedEvents.Events.size() + BunchEvents.
Events.size() >
255 AmountToAppend = NumberOfEvents - GeneratedEvents.Events.size();
257 GeneratedEvents.Events.insert(
258 GeneratedEvents.Events.end(),
259 std::make_move_iterator(BunchEvents.
Events.begin()),
260 std::make_move_iterator(BunchEvents.
Events.begin() + AmountToAppend));
262 bar.
next(AmountToAppend);
264 if (GeneratedEvents.Events.size() == NumberOfEvents)
268 std::advance(CurrentTrueStartIterator, EventBunchSize);
269 std::advance(CurrentStartIterator, EventBunchSize);
270 CurrentStartIndex += EventBunchSize;
272 if (CurrentStartIndex >= LastIndex)
275 double gen_eff = (double)GeneratedEvents.Events.size() / NumberOfEvents;
276 if (CurrentStartIndex > NumberOfEvents) {
277 gen_eff = (double)GeneratedEvents.Events.size() / CurrentStartIndex;
279 LOG(INFO) <<
"Efficiency of toy MC generation: " << gen_eff;
281 return GeneratedEvents;
289 unsigned int EventBunchSize(5000);
291 LOG(INFO) <<
"Generating phase-space MC: [" << NumberOfEvents <<
" events] ";
296 Generator.
generate(EventBunchSize, RandomGenerator);
297 std::vector<double> RandomNumbers;
298 RandomNumbers.reserve(EventBunchSize);
299 std::generate_n(std::back_inserter(RandomNumbers), EventBunchSize,
300 [&RandomGenerator]() {
return RandomGenerator(); });
301 for (
size_t i = 0; i < RandomNumbers.size(); ++i) {
302 if (GeneratedPhsp.
Events.size() == NumberOfEvents)
304 if (RandomNumbers[i] > TmpEvents.
Events[i].Weight) {
310 GeneratedPhsp.
Events.push_back(
314 if (GeneratedPhsp.
Events.size() == NumberOfEvents)
317 return GeneratedPhsp;
326 if (NumberOfEvents <= 0)
327 return GeneratedEventList;
329 unsigned int EventBunchSize(5000);
330 GeneratedEventList.Events.reserve(NumberOfEvents);
332 double SafetyMargin(0.05);
333 double generationMaxValue(0.0);
334 unsigned int initialSeed = RandomGenerator.
getSeed();
337 <<
"Generating phase space sample (hit-and-miss importance sampled): [" 338 << NumberOfEvents <<
" events] ";
342 Generator.
generate(EventBunchSize, RandomGenerator);
345 double MaximumWeight;
347 std::tie(BunchEvents, MaximumWeight) =
348 generateBunch(EventBunchSize, Kinematics, Intensity, RandomGenerator,
349 generationMaxValue, TempEventList.
Events.begin(),
350 TempEventList.
Events.begin(),
true);
353 if (MaximumWeight > generationMaxValue) {
354 generationMaxValue = (1.0 + SafetyMargin) * MaximumWeight;
355 if (GeneratedEventList.Events.size() > 0) {
356 GeneratedEventList.Events.clear();
357 RandomGenerator.
setSeed(initialSeed);
360 <<
"Tools::generateImportanceSampledPhsp() | Error in HitMiss " 361 "procedure: Maximum value of random number generation " 362 "smaller then amplitude maximum! We raise the maximum " 364 << generationMaxValue <<
" value and restart generation!";
369 size_t AmountToAppend(BunchEvents.Events.size());
370 if (GeneratedEventList.Events.size() + BunchEvents.Events.size() >
372 AmountToAppend = NumberOfEvents - GeneratedEventList.Events.size();
375 GeneratedEventList.Events.insert(
376 GeneratedEventList.Events.end(), BunchEvents.Events.begin(),
377 BunchEvents.Events.begin() + AmountToAppend);
379 bar.
next(AmountToAppend);
381 if (GeneratedEventList.Events.size() == NumberOfEvents)
385 double WeightSum(0.0);
386 for (
auto const &
Event : GeneratedEventList.Events) {
391 double rescale_factor(NumberOfEvents / WeightSum);
392 for (
auto &
Event : GeneratedEventList.Events) {
396 return GeneratedEventList;
Interface class for PHSP event generators.
virtual const std::vector< pid > & getFinalStatePIDs() const =0
Get a vector of PIDs of the final state.
EventCollection generatePhsp(unsigned int NumberOfEvents, const ComPWA::PhaseSpaceEventGenerator &Generator, ComPWA::UniformRealNumberGenerator &RandomGenerator)
virtual ComPWA::Data::DataSet convert(const EventCollection &Events) const =0
double uniform(double random, double min, double max)
virtual EventCollection generate(unsigned int NumberOfEvents, UniformRealNumberGenerator &RandomGenerator) const =0
Some useful functions for Monte-Carlo event generation.
EventCollection generateImportanceSampledPhsp(unsigned int NumberOfEvents, const ComPWA::Kinematics &Kinematics, const ComPWA::PhaseSpaceEventGenerator &Generator, ComPWA::Intensity &Intensity, ComPWA::UniformRealNumberGenerator &RandomGenerator)
std::vector< Event > Events
virtual OutputType evaluate(const InputTypes &... args) noexcept=0
std::tuple< EventCollection, double > generateBunch(unsigned int EventBunchSize, const ComPWA::Kinematics &Kinematics, ComPWA::Intensity &Intensity, ComPWA::UniformRealNumberGenerator &RandomGenerator, double generationMaxValue, std::vector< ComPWA::Event >::const_iterator PhspStartIterator, std::vector< ComPWA::Event >::const_iterator PhspTrueStartIterator, bool InverseIntensityWeighting=false)
The Kinematics interface defines the conversion of Events to a DataSet.
EventCollection generate(unsigned int NumberOfEvents, const ComPWA::Kinematics &Kinematics, const ComPWA::PhaseSpaceEventGenerator &Generator, ComPWA::Intensity &Intensity, ComPWA::UniformRealNumberGenerator &RandomGenerator)
void next(size_t increment=1)
indicate the next step in process
Data structure containing all kinematic information of a physics event.
double getMaximumSampleWeight(const EventCollection &Sample)
Interface template for a general Function of the form OutputType Function(InputTypes) The concept clo...