parameter_distributions.h Source File

CPP API: parameter_distributions.h Source File
parameter_distributions.h
Go to the documentation of this file.
1 /*
2 * Copyright (C) 2020-2026 MEmilio
3 *
4 * Authors: Martin J. Kuehn, Daniel Abele, Julia Bicker
5 *
6 * Contact: Martin J. Kuehn <Martin.Kuehn@DLR.de>
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20 #ifndef MIO_UTILS_PARAMETER_DISTRIBUTIONS_H
21 #define MIO_UTILS_PARAMETER_DISTRIBUTIONS_H
22 
23 #include "memilio/utils/logging.h"
24 #include "memilio/utils/visitor.h"
27 #include "memilio/io/io.h"
28 
29 #include <limits>
30 #include <memory>
31 #include <vector>
32 #include <random>
33 
34 namespace mio
35 {
36 
49 
50 template <class Derived>
53 
54 namespace details
55 {
56 template <class IOObj>
59  : obj(o)
60  {
61  }
62  virtual void visit(const ParameterDistributionNormal& normal_dist) final;
63  virtual void visit(const ParameterDistributionUniform& uniform_dist) final;
64  virtual void visit(const ParameterDistributionLogNormal& lognormal_dist) final;
65  virtual void visit(const ParameterDistributionExponential& lognormal_dist) final;
66  virtual void visit(const ParameterDistributionConstant& lognormal_dist) final;
67  IOObj& obj;
68 };
69 } // namespace details
70 
71 /*
72  * Parameter Distribution class representing a generic distribution and contains predefined samples
73  */
75 {
76 public:
78  {
79  }
80 
81  virtual ~ParameterDistribution() = default;
82 
84  {
85  m_predefined_samples.push_back(sample);
86  }
87 
89  {
90  m_predefined_samples.resize(0);
91  }
92 
93  const std::vector<ScalarType>& get_predefined_samples() const
94  {
95  return m_predefined_samples;
96  }
97 
98  /*
99  * @brief returns a value for the given parameter distribution
100  * in case some predefined samples are set, these values are taken
101  * first, in case the vector of predefined values is empty, a 'real'
102  * random sample is taken
103  */
104  template <class RNG>
106  {
107  if (m_predefined_samples.size() > 0) {
108  ScalarType rnumb = m_predefined_samples[0];
110  return rnumb;
111  }
112  else {
113  return get_rand_sample(rng);
114  }
115  }
116 
121  template <class IOContext>
122  void serialize(IOContext& io) const
123  {
124  auto obj = io.create_object("ParameterDistribution");
125  auto visitor = details::SerializationVisitor<decltype(obj)>{obj};
126  this->accept(visitor);
127  }
128 
129  virtual bool smaller_impl(const ParameterDistribution& other) const = 0;
130 
134  virtual std::vector<ScalarType> params() const = 0;
135 
136  virtual ScalarType get_rand_sample(RandomNumberGenerator& rng) = 0;
138 
139  virtual ParameterDistribution* clone() const = 0;
140 
147  virtual void accept(ParameterDistributionVisitor& visitor) = 0;
148  virtual void accept(ConstParameterDistributionVisitor& visitor) const = 0;
149 
150 protected:
151  std::vector<ScalarType>
152  m_predefined_samples; // if these values are set; no real sample will occur but these values will be taken
153 };
154 
155 /*
156  * Child class of Parameter Distribution class which additionally contains
157  * the mean value and the standard deviation for a normal distribution
158  */
159 class ParameterDistributionNormal : public VisitableParameterDistribution<ParameterDistributionNormal>
160 {
161 public:
164  , m_mean(0)
165  , m_standard_dev(1)
166  , m_distribution(0, 1)
167  {
168  }
169 
172  , m_mean(mean)
173  , m_standard_dev(standard_dev)
174  , m_distribution(mean, standard_dev)
175  {
176  m_mean = mean;
177  m_standard_dev = standard_dev;
178  }
179 
180  ParameterDistributionNormal(ScalarType lower_bound, ScalarType upper_bound, ScalarType mean, ScalarType quantile)
182  , m_mean(mean)
183  , m_upper_bound(upper_bound)
184  , m_lower_bound(lower_bound)
185  , m_quantile(quantile)
186  {
187  // if upper and lower bound are given, the standard deviation is calculated such that [lower_bound, upper_bound] represent the 0.995 quartile]
188  m_standard_dev = upper_bound; // set as to high and adapt then
189  adapt_standard_dev(m_standard_dev, upper_bound, lower_bound);
190  m_distribution = mio::NormalDistribution<ScalarType>::ParamType(m_mean, m_standard_dev);
191  }
192 
194  ScalarType standard_dev, ScalarType quantile)
196  , m_mean(mean)
197  , m_standard_dev(standard_dev)
198  , m_upper_bound(upper_bound)
199  , m_lower_bound(lower_bound)
200  , m_quantile(quantile)
201  {
203  m_distribution = mio::NormalDistribution<ScalarType>::ParamType(m_mean, m_standard_dev);
204  }
205 
206  void set_mean(ScalarType mean)
207  {
208  m_mean = mean;
209  }
210 
212  {
214  }
215 
216  /*
217  * @brief verification that at least 99% of the density
218  * function lie in the interval defined by the boundaries
219  */
220  bool check_quantiles(ScalarType& mean, ScalarType& standard_dev)
221  {
222  bool changed = false;
223  if (adapt_mean(mean)) {
224  changed = true;
225  log_warning("Mean adapted to lie within [lowerbound,upperbound].");
226  }
227 
228  if (adapt_standard_dev(standard_dev, m_upper_bound, m_lower_bound)) {
229  changed = true;
230  log_warning("Standard deviation reduced to fit 99% of the distribution within [lowerbound,upperbound].");
231  }
232 
233  return changed;
234  }
235 
236  bool adapt_mean(ScalarType& mean)
237  {
238  bool changed = false;
239  if (mean < m_lower_bound || mean > m_upper_bound) {
240  mean = 0.5 * (m_upper_bound - m_lower_bound);
241  changed = true;
242  }
243  return changed;
244  }
245 
246  // ensure that 0.99 % of the distribution are within lower bound and upper bound
247  bool adapt_standard_dev(ScalarType& standard_dev, ScalarType upper_bound, ScalarType lower_bound)
248  {
249  bool changed = false;
250  if (m_mean + standard_dev * m_quantile > upper_bound) {
251  standard_dev = (upper_bound - m_mean) / m_quantile;
252  changed = true;
253  }
254  if (m_mean - standard_dev * m_quantile < lower_bound) {
255  standard_dev = (m_mean - lower_bound) / m_quantile;
256  changed = true;
257  }
258 
259  return changed;
260  }
261 
262  void set_standard_dev(ScalarType standard_dev)
263  {
264  m_standard_dev = standard_dev;
265  }
266 
268  {
269  return m_mean;
270  }
271 
273  {
274  return m_standard_dev;
275  }
276 
277  void set_lower_bound(ScalarType lower_bound)
278  {
279  m_lower_bound = lower_bound;
280  }
281 
282  void set_upper_bound(ScalarType upper_bound)
283  {
284  m_upper_bound = upper_bound;
285  }
286 
288  {
289  return m_lower_bound;
290  }
291 
293  {
294  return m_upper_bound;
295  }
296 
297  bool smaller_impl(const ParameterDistribution& other) const override
298  {
299  const ParameterDistributionNormal* PDNormal = dynamic_cast<const ParameterDistributionNormal*>(&other);
300  if (PDNormal) {
301  return m_mean < PDNormal->m_mean;
302  }
303  else {
304  return false;
305  }
306  }
307 
308  std::vector<ScalarType> params() const override
309  {
310  return {m_mean, m_standard_dev};
311  }
312 
313  /*
314  * @brief gets a sample of a normally distributed variable
315  * before sampling, it is verified that at least 99% of the
316  * density function lie in the interval defined by the boundaries
317  * otherwise the normal distribution is adapted
318  */
319  template <class RNG>
320  ScalarType sample(RNG& rng)
321  {
322  //If ub = lb, sampling can only be succesful if mean = lb and dev = 0.
323  //But this degenerate normal distribution is not allowed by the c++ standard.
324  if (m_upper_bound == m_lower_bound) {
325  return m_lower_bound;
326  }
327 
328  if (check_quantiles(m_mean, m_standard_dev) || m_distribution.params.mean() != m_mean ||
329  m_distribution.params.stddev() != m_standard_dev) {
330  m_distribution = NormalDistribution<ScalarType>::ParamType{m_mean, m_standard_dev};
331  }
332 
333  int i = 0;
334  int retries = 10;
335  ScalarType rnumb = m_distribution.get_distribution_instance()(rng, m_distribution.params);
336  while ((rnumb > m_upper_bound || rnumb < m_lower_bound) && i < retries) {
337  rnumb = m_distribution.get_distribution_instance()(rng, m_distribution.params);
338  i++;
339  if (i == retries) {
340  log_warning("Not successfully sampled within [min,max].");
341  if (rnumb > m_upper_bound) {
342  rnumb = m_upper_bound;
343  }
344  else {
345  rnumb = m_lower_bound;
346  }
347  }
348  }
349  return rnumb;
350  }
351 
352  ScalarType get_rand_sample(RandomNumberGenerator& rng) override
353  {
354  return sample(rng);
355  }
356 
358  {
359  return sample(rng);
360  }
361 
362  template <class IOObject>
363  void serialize_elements(IOObject& obj) const
364  {
365  obj.add_element("Mean", m_mean);
366  obj.add_element("StandardDev", m_standard_dev);
367  obj.add_element("LowerBound", m_lower_bound);
368  obj.add_element("UpperBound", m_upper_bound);
369  obj.add_element("Quantile", m_quantile);
370  obj.add_list("PredefinedSamples", m_predefined_samples.begin(), m_predefined_samples.end());
371  }
372 
373  template <class IOContext>
374  void serialize(IOContext& io) const
375  {
376  auto obj = io.create_object("ParameterDistributionNormal");
377  serialize_elements(obj);
378  }
379 
380  template <class IOContext, class IOObject>
381  static IOResult<ParameterDistributionNormal> deserialize_elements(IOContext& io, IOObject& obj)
382  {
383  auto m = obj.expect_element("Mean", Tag<ScalarType>{});
384  auto s = obj.expect_element("StandardDev", Tag<ScalarType>{});
385  auto lb = obj.expect_element("LowerBound", Tag<ScalarType>{});
386  auto ub = obj.expect_element("UpperBound", Tag<ScalarType>{});
387  auto qu = obj.expect_element("Quantile", Tag<ScalarType>{});
388  auto predef = obj.expect_list("PredefinedSamples", Tag<ScalarType>{});
389  auto p = apply(
390  io,
391  [](auto&& lb_, auto&& ub_, auto&& m_, auto&& s_, auto&& qu_, auto&& predef_) {
392  auto distr = ParameterDistributionNormal(lb_, ub_, m_, s_, qu_);
393  for (auto&& e : predef_) {
394  distr.add_predefined_sample(e);
395  }
396  return distr;
397  },
398  lb, ub, m, s, qu, predef);
399  if (p) {
400  return success(p.value());
401  }
402  else {
403  return p.as_failure();
404  }
405  }
406 
407  template <class IOContext>
409  {
410  auto obj = io.expect_object("ParameterDistributionNormal");
411  return deserialize_elements(io, obj);
412  }
413 
414  ParameterDistribution* clone() const override
415  {
416  return new ParameterDistributionNormal(*this);
417  }
418 
419 private:
420  ScalarType m_mean; // the mean value of the normal distribution
421  ScalarType m_standard_dev; // the standard deviation of the normal distribution
422  ScalarType m_upper_bound = std::numeric_limits<
423  ScalarType>::max(); // upper bound and lower bound can be given to the constructor instead of stddev
425  ScalarType m_quantile = 2.5758; // default is 0.995 quartile
426  NormalDistribution<ScalarType>::ParamType m_distribution;
427 };
428 
429 template <class IOObj>
431 {
432  obj.add_element("Type", std::string("Normal"));
433  normal_dist.serialize_elements(obj);
434 }
435 
436 /*
437  * Child class of Parameter Distribution class which represents an uniform distribution
438  */
439 class ParameterDistributionUniform : public VisitableParameterDistribution<ParameterDistributionUniform>
440 {
441 public:
444  , m_upper_bound(upper_bound)
445  , m_lower_bound(lower_bound)
446  , m_distribution(lower_bound, upper_bound)
447  {
448  }
449 
450  bool smaller_impl(const ParameterDistribution& other) const override
451  {
452  const ParameterDistributionUniform* PDUniform = dynamic_cast<const ParameterDistributionUniform*>(&other);
453  if (PDUniform) {
454  return (m_lower_bound < PDUniform->m_lower_bound) && (m_upper_bound < PDUniform->m_upper_bound);
455  }
456  else {
457  return false;
458  }
459  }
460 
461  std::vector<ScalarType> params() const override
462  {
463  return {m_lower_bound, m_upper_bound};
464  }
465 
467  {
468  return m_lower_bound;
469  }
470 
472  {
473  return m_upper_bound;
474  }
475 
476  /*
477  * @brief gets a sample of a uniformly distributed variable
478  */
479  template <class RNG>
480  ScalarType sample(RNG& rng)
481  {
482  if (m_distribution.params.b() != m_upper_bound || m_distribution.params.a() != m_lower_bound) {
483  m_distribution = UniformDistribution<ScalarType>::ParamType{m_lower_bound, m_upper_bound};
484  }
485 
486  return m_distribution.get_distribution_instance()(rng, m_distribution.params);
487  }
488 
489  ScalarType get_rand_sample(RandomNumberGenerator& rng) override
490  {
491  return sample(rng);
492  }
493 
495  {
496  return sample(rng);
497  }
498 
499  ParameterDistribution* clone() const override
500  {
501  return new ParameterDistributionUniform(*this);
502  }
503 
504  template <class IOObject>
505  void serialize_elements(IOObject& obj) const
506  {
507  obj.add_element("LowerBound", m_lower_bound);
508  obj.add_element("UpperBound", m_upper_bound);
509  obj.add_list("PredefinedSamples", m_predefined_samples.begin(), m_predefined_samples.end());
510  }
511 
512  template <class IOContext>
513  void serialize(IOContext& io) const
514  {
515  auto obj = io.create_object("ParameterDistributionUniform");
516  serialize_elements(obj);
517  }
518 
519  template <class IOContext, class IOObject>
521  {
522  auto lb = obj.expect_element("LowerBound", Tag<ScalarType>{});
523  auto ub = obj.expect_element("UpperBound", Tag<ScalarType>{});
524  auto predef = obj.expect_list("PredefinedSamples", Tag<ScalarType>{});
525  auto p = apply(
526  io,
527  [](auto&& lb_, auto&& ub_, auto&& predef_) {
528  auto distr = ParameterDistributionUniform(lb_, ub_);
529  for (auto&& e : predef_) {
530  distr.add_predefined_sample(e);
531  }
532  return distr;
533  },
534  lb, ub, predef);
535  if (p) {
536  return success(p.value());
537  }
538  else {
539  return p.as_failure();
540  }
541  }
542 
543  template <class IOContext>
545  {
546  auto obj = io.expect_object("ParameterDistributionUniform");
547  return deserialize_elements(io, obj);
548  }
549 
550 private:
553  UniformDistribution<ScalarType>::ParamType m_distribution;
554 };
555 
556 template <class IOObj>
558 {
559  obj.add_element("Type", std::string("Uniform"));
560  uniform_dist.serialize_elements(obj);
561 }
562 
563 /*
564  * Child class of Parameter Distribution class which represents an lognormal distribution
565  */
566 class ParameterDistributionLogNormal : public VisitableParameterDistribution<ParameterDistributionLogNormal>
567 {
568 public:
571  , m_log_mean(log_mean)
572  , m_log_stddev(log_stddev)
573  , m_distribution(log_mean, log_stddev)
574  {
575  }
576 
577  bool smaller_impl(const ParameterDistribution& other) const override
578  {
579  const ParameterDistributionLogNormal* PDLogNorm = dynamic_cast<const ParameterDistributionLogNormal*>(&other);
580  if (PDLogNorm) {
581  return m_log_mean < PDLogNorm->m_log_mean;
582  }
583  else {
584  return false;
585  }
586  }
587 
588  std::vector<ScalarType> params() const override
589  {
590  return {m_log_mean, m_log_stddev};
591  }
592 
594  {
595  return m_log_mean;
596  }
597 
599  {
600  return m_log_stddev;
601  }
602 
603  /*
604  * @brief gets a sample of a lognormally distributed variable
605  */
606  template <class RNG>
607  ScalarType sample(RNG& rng)
608  {
609  if (m_distribution.params.m() != m_log_mean || m_distribution.params.s() != m_log_stddev) {
610  m_distribution = LogNormalDistribution<ScalarType>::ParamType{m_log_mean, m_log_stddev};
611  }
612 
613  return m_distribution.get_distribution_instance()(rng, m_distribution.params);
614  }
615 
616  ScalarType get_rand_sample(RandomNumberGenerator& rng) override
617  {
618  return sample(rng);
619  }
620 
622  {
623  return sample(rng);
624  }
625 
626  ParameterDistribution* clone() const override
627  {
628  return new ParameterDistributionLogNormal(*this);
629  }
630 
631  template <class IOObject>
632  void serialize_elements(IOObject& obj) const
633  {
634  obj.add_element("LogMean", m_log_mean);
635  obj.add_element("LogStddev", m_log_stddev);
636  obj.add_list("PredefinedSamples", m_predefined_samples.begin(), m_predefined_samples.end());
637  }
638 
639  template <class IOContext>
640  void serialize(IOContext& io) const
641  {
642  auto obj = io.create_object("ParameterDistributionLogNormal");
643  serialize_elements(obj);
644  }
645 
646  template <class IOContext, class IOObject>
648  {
649  auto lm = obj.expect_element("LogMean", Tag<ScalarType>{});
650  auto ls = obj.expect_element("LogStddev", Tag<ScalarType>{});
651  auto predef = obj.expect_list("PredefinedSamples", Tag<ScalarType>{});
652  auto p = apply(
653  io,
654  [](auto&& lm_, auto&& ls_, auto&& predef_) {
655  auto distr = ParameterDistributionLogNormal(lm_, ls_);
656  for (auto&& e : predef_) {
657  distr.add_predefined_sample(e);
658  }
659  return distr;
660  },
661  lm, ls, predef);
662  if (p) {
663  return success(p.value());
664  }
665  else {
666  return p.as_failure();
667  }
668  }
669 
670  template <class IOContext>
672  {
673  auto obj = io.expect_object("ParameterDistributionLogNormal");
674  return deserialize_elements(io, obj);
675  }
676 
677 private:
680  LogNormalDistribution<ScalarType>::ParamType m_distribution;
681 };
682 
683 template <class IOObj>
685 {
686  obj.add_element("Type", std::string("LogNormal"));
687  uniform_dist.serialize_elements(obj);
688 }
689 
690 /*
691  * Child class of Parameter Distribution class which represents an exponential distribution
692  */
693 class ParameterDistributionExponential : public VisitableParameterDistribution<ParameterDistributionExponential>
694 {
695 public:
698  , m_rate(rate)
699  , m_distribution(rate)
700  {
701  }
702 
703  bool smaller_impl(const ParameterDistribution& other) const override
704  {
705  const ParameterDistributionExponential* PDExponential =
706  dynamic_cast<const ParameterDistributionExponential*>(&other);
707  if (PDExponential) {
708  return m_rate < PDExponential->m_rate;
709  }
710  else {
711  return false;
712  }
713  }
714 
715  std::vector<ScalarType> params() const override
716  {
717  return {m_rate};
718  }
719 
721  {
722  return m_rate;
723  }
724 
725  /*
726  * @brief gets a sample of a exponentially distributed variable
727  */
728  template <class RNG>
729  ScalarType sample(RNG& rng)
730  {
731  if (m_distribution.params.lambda() != m_rate) {
732  m_distribution = ExponentialDistribution<ScalarType>::ParamType{m_rate};
733  }
734 
735  return m_distribution.get_distribution_instance()(rng, m_distribution.params);
736  }
737 
738  ScalarType get_rand_sample(RandomNumberGenerator& rng) override
739  {
740  return sample(rng);
741  }
742 
744  {
745  return sample(rng);
746  }
747 
748  ParameterDistribution* clone() const override
749  {
750  return new ParameterDistributionExponential(*this);
751  }
752 
753  template <class IOObject>
754  void serialize_elements(IOObject& obj) const
755  {
756  obj.add_element("Rate", m_rate);
757  obj.add_list("PredefinedSamples", m_predefined_samples.begin(), m_predefined_samples.end());
758  }
759 
760  template <class IOContext>
761  void serialize(IOContext& io) const
762  {
763  auto obj = io.create_object("ParameterDistributionExponential");
764  serialize_elements(obj);
765  }
766 
767  template <class IOContext, class IOObject>
769  {
770  auto r = obj.expect_element("Rate", Tag<ScalarType>{});
771  auto predef = obj.expect_list("PredefinedSamples", Tag<ScalarType>{});
772  auto p = apply(
773  io,
774  [](auto&& r_, auto&& predef_) {
775  auto distr = ParameterDistributionExponential(r_);
776  for (auto&& e : predef_) {
777  distr.add_predefined_sample(e);
778  }
779  return distr;
780  },
781  r, predef);
782  if (p) {
783  return success(p.value());
784  }
785  else {
786  return p.as_failure();
787  }
788  }
789 
790  template <class IOContext>
792  {
793  auto obj = io.expect_object("ParameterDistributionExponential");
794  return deserialize_elements(io, obj);
795  }
796 
797 private:
799  ExponentialDistribution<ScalarType>::ParamType m_distribution;
800 };
801 
802 template <class IOObj>
804 {
805  obj.add_element("Type", std::string("Exponential"));
806  uniform_dist.serialize_elements(obj);
807 }
808 
809 /*
810  * Child class of Parameter Distribution class which represents a constant distribution/value
811  */
812 class ParameterDistributionConstant : public VisitableParameterDistribution<ParameterDistributionConstant>
813 {
814 public:
817  , m_constant(constant)
818  {
819  }
820 
821  bool smaller_impl(const ParameterDistribution& other) const override
822  {
823  const ParameterDistributionConstant* PDConstantl = dynamic_cast<const ParameterDistributionConstant*>(&other);
824  if (PDConstantl) {
825  return m_constant < PDConstantl->m_constant;
826  }
827  else {
828  return false;
829  }
830  }
831 
832  std::vector<ScalarType> params() const override
833  {
834  return {m_constant};
835  }
836 
838  {
839  return m_constant;
840  }
841 
842  /*
843  * @brief gets a constant
844  */
845  template <class RNG>
846  ScalarType sample(RNG& /*rng*/)
847  {
848  return m_constant;
849  }
850 
851  ScalarType get_rand_sample(RandomNumberGenerator& rng) override
852  {
853  return sample(rng);
854  }
855 
857  {
858  return sample(rng);
859  }
860 
861  ParameterDistribution* clone() const override
862  {
863  return new ParameterDistributionConstant(*this);
864  }
865 
866  template <class IOObject>
867  void serialize_elements(IOObject& obj) const
868  {
869  obj.add_element("Constant", m_constant);
870  obj.add_list("PredefinedSamples", m_predefined_samples.begin(), m_predefined_samples.end());
871  }
872 
873  template <class IOContext>
874  void serialize(IOContext& io) const
875  {
876  auto obj = io.create_object("ParameterDistributionConstant");
877  serialize_elements(obj);
878  }
879 
880  template <class IOContext, class IOObject>
882  {
883  auto c = obj.expect_element("Constant", Tag<ScalarType>{});
884  auto predef = obj.expect_list("PredefinedSamples", Tag<ScalarType>{});
885  auto p = apply(
886  io,
887  [](auto&& c_, auto&& predef_) {
888  auto distr = ParameterDistributionConstant(c_);
889  for (auto&& e : predef_) {
890  distr.add_predefined_sample(e);
891  }
892  return distr;
893  },
894  c, predef);
895  if (p) {
896  return success(p.value());
897  }
898  else {
899  return p.as_failure();
900  }
901  }
902 
903  template <class IOContext>
905  {
906  auto obj = io.expect_object("ParameterDistributionConstant");
907  return deserialize_elements(io, obj);
908  }
909 
910 private:
912 };
913 
914 template <class IOObj>
916 {
917  obj.add_element("Type", std::string("Constant"));
918  uniform_dist.serialize_elements(obj);
919 }
920 
925 template <class IOContext>
927  Tag<std::shared_ptr<ParameterDistribution>>)
928 {
929  auto obj = io.expect_object("ParameterDistribution");
930  auto type = obj.expect_element("Type", Tag<std::string>{});
931  if (type) {
932  if (type.value() == "Uniform") {
933  BOOST_OUTCOME_TRY(auto&& r, ParameterDistributionUniform::deserialize_elements(io, obj));
934  return std::make_shared<ParameterDistributionUniform>(r);
935  }
936  else if (type.value() == "Normal") {
937  BOOST_OUTCOME_TRY(auto&& r, ParameterDistributionNormal::deserialize_elements(io, obj));
938  return std::make_shared<ParameterDistributionNormal>(r);
939  }
940  else if (type.value() == "LogNormal") {
941  BOOST_OUTCOME_TRY(auto&& r, ParameterDistributionLogNormal::deserialize_elements(io, obj));
942  return std::make_shared<ParameterDistributionLogNormal>(r);
943  }
944  else if (type.value() == "Exponential") {
945  BOOST_OUTCOME_TRY(auto&& r, ParameterDistributionExponential::deserialize_elements(io, obj));
946  return std::make_shared<ParameterDistributionExponential>(r);
947  }
948  else if (type.value() == "Constant") {
949  BOOST_OUTCOME_TRY(auto&& r, ParameterDistributionConstant::deserialize_elements(io, obj));
950  return std::make_shared<ParameterDistributionConstant>(r);
951  }
952  else {
953  return failure(StatusCode::InvalidValue, "Type of ParameterDistribution " + type.value() + " not valid.");
954  }
955  }
956  return failure(type.error());
957 }
958 
959 } // namespace mio
960 
961 #endif // MIO_UTILS_PARAMETER_DISTRIBUTIONS_H
Definition: parameter_distributions.h:813
ScalarType sample(RNG &)
Definition: parameter_distributions.h:846
ScalarType get_rand_sample(RandomNumberGenerator &rng) override
Definition: parameter_distributions.h:851
void serialize_elements(IOObject &obj) const
Definition: parameter_distributions.h:867
std::vector< ScalarType > params() const override
Definition: parameter_distributions.h:832
ScalarType get_rand_sample(abm::PersonalRandomNumberGenerator &rng) override
Definition: parameter_distributions.h:856
void serialize(IOContext &io) const
Definition: parameter_distributions.h:874
ParameterDistribution * clone() const override
Definition: parameter_distributions.h:861
static IOResult< ParameterDistributionConstant > deserialize(IOContext &io)
Definition: parameter_distributions.h:904
static IOResult< ParameterDistributionConstant > deserialize_elements(IOContext &io, IOObject &obj)
Definition: parameter_distributions.h:881
ScalarType get_constant() const
Definition: parameter_distributions.h:837
ParameterDistributionConstant(ScalarType constant)
Definition: parameter_distributions.h:815
bool smaller_impl(const ParameterDistribution &other) const override
Definition: parameter_distributions.h:821
ScalarType m_constant
Definition: parameter_distributions.h:911
Definition: parameter_distributions.h:694
ExponentialDistribution< ScalarType >::ParamType m_distribution
Definition: parameter_distributions.h:799
std::vector< ScalarType > params() const override
Definition: parameter_distributions.h:715
ScalarType get_rate() const
Definition: parameter_distributions.h:720
ParameterDistribution * clone() const override
Definition: parameter_distributions.h:748
ScalarType m_rate
Definition: parameter_distributions.h:798
ParameterDistributionExponential(ScalarType rate)
Definition: parameter_distributions.h:696
ScalarType sample(RNG &rng)
Definition: parameter_distributions.h:729
static IOResult< ParameterDistributionExponential > deserialize_elements(IOContext &io, IOObject &obj)
Definition: parameter_distributions.h:768
void serialize(IOContext &io) const
Definition: parameter_distributions.h:761
bool smaller_impl(const ParameterDistribution &other) const override
Definition: parameter_distributions.h:703
static IOResult< ParameterDistributionExponential > deserialize(IOContext &io)
Definition: parameter_distributions.h:791
ScalarType get_rand_sample(abm::PersonalRandomNumberGenerator &rng) override
Definition: parameter_distributions.h:743
ScalarType get_rand_sample(RandomNumberGenerator &rng) override
Definition: parameter_distributions.h:738
void serialize_elements(IOObject &obj) const
Definition: parameter_distributions.h:754
Definition: parameter_distributions.h:567
ParameterDistribution * clone() const override
Definition: parameter_distributions.h:626
void serialize(IOContext &io) const
Definition: parameter_distributions.h:640
ScalarType get_rand_sample(RandomNumberGenerator &rng) override
Definition: parameter_distributions.h:616
std::vector< ScalarType > params() const override
Definition: parameter_distributions.h:588
bool smaller_impl(const ParameterDistribution &other) const override
Definition: parameter_distributions.h:577
LogNormalDistribution< ScalarType >::ParamType m_distribution
Definition: parameter_distributions.h:680
ScalarType get_log_stddev() const
Definition: parameter_distributions.h:598
ScalarType get_rand_sample(abm::PersonalRandomNumberGenerator &rng) override
Definition: parameter_distributions.h:621
void serialize_elements(IOObject &obj) const
Definition: parameter_distributions.h:632
ScalarType m_log_mean
Definition: parameter_distributions.h:678
ParameterDistributionLogNormal(ScalarType log_mean, ScalarType log_stddev)
Definition: parameter_distributions.h:569
ScalarType sample(RNG &rng)
Definition: parameter_distributions.h:607
static IOResult< ParameterDistributionLogNormal > deserialize_elements(IOContext &io, IOObject &obj)
Definition: parameter_distributions.h:647
ScalarType m_log_stddev
Definition: parameter_distributions.h:679
ScalarType get_log_mean() const
Definition: parameter_distributions.h:593
static IOResult< ParameterDistributionLogNormal > deserialize(IOContext &io)
Definition: parameter_distributions.h:671
Definition: parameter_distributions.h:160
bool smaller_impl(const ParameterDistribution &other) const override
Definition: parameter_distributions.h:297
ScalarType get_rand_sample(RandomNumberGenerator &rng) override
Definition: parameter_distributions.h:352
ScalarType get_mean() const
Definition: parameter_distributions.h:267
void serialize_elements(IOObject &obj) const
Definition: parameter_distributions.h:363
ScalarType m_standard_dev
Definition: parameter_distributions.h:421
ParameterDistributionNormal(ScalarType mean, ScalarType standard_dev)
Definition: parameter_distributions.h:170
ScalarType m_upper_bound
Definition: parameter_distributions.h:422
ScalarType get_rand_sample(abm::PersonalRandomNumberGenerator &rng) override
Definition: parameter_distributions.h:357
ScalarType sample(RNG &rng)
Definition: parameter_distributions.h:320
NormalDistribution< ScalarType >::ParamType m_distribution
Definition: parameter_distributions.h:426
static IOResult< ParameterDistributionNormal > deserialize_elements(IOContext &io, IOObject &obj)
Definition: parameter_distributions.h:381
ScalarType m_lower_bound
Definition: parameter_distributions.h:424
ScalarType m_quantile
Definition: parameter_distributions.h:425
ParameterDistributionNormal()
Definition: parameter_distributions.h:162
ScalarType m_mean
Definition: parameter_distributions.h:420
ScalarType get_lower_bound() const
Definition: parameter_distributions.h:287
ParameterDistributionNormal(ScalarType lower_bound, ScalarType upper_bound, ScalarType mean, ScalarType quantile)
Definition: parameter_distributions.h:180
bool adapt_mean(ScalarType &mean)
Definition: parameter_distributions.h:236
static IOResult< ParameterDistributionNormal > deserialize(IOContext &io)
Definition: parameter_distributions.h:408
void set_upper_bound(ScalarType upper_bound)
Definition: parameter_distributions.h:282
void set_lower_bound(ScalarType lower_bound)
Definition: parameter_distributions.h:277
void serialize(IOContext &io) const
Definition: parameter_distributions.h:374
ParameterDistribution * clone() const override
Definition: parameter_distributions.h:414
void set_mean(ScalarType mean)
Definition: parameter_distributions.h:206
void set_standard_dev(ScalarType standard_dev)
Definition: parameter_distributions.h:262
bool check_quantiles(ScalarType &mean, ScalarType &standard_dev)
Definition: parameter_distributions.h:220
bool adapt_standard_dev(ScalarType &standard_dev, ScalarType upper_bound, ScalarType lower_bound)
Definition: parameter_distributions.h:247
ScalarType get_upper_bound() const
Definition: parameter_distributions.h:292
std::vector< ScalarType > params() const override
Definition: parameter_distributions.h:308
bool check_quantiles()
Definition: parameter_distributions.h:211
ScalarType get_standard_dev() const
Definition: parameter_distributions.h:272
ParameterDistributionNormal(ScalarType lower_bound, ScalarType upper_bound, ScalarType mean, ScalarType standard_dev, ScalarType quantile)
Definition: parameter_distributions.h:193
Definition: parameter_distributions.h:440
void serialize(IOContext &io) const
Definition: parameter_distributions.h:513
static IOResult< ParameterDistributionUniform > deserialize(IOContext &io)
Definition: parameter_distributions.h:544
bool smaller_impl(const ParameterDistribution &other) const override
Definition: parameter_distributions.h:450
ScalarType sample(RNG &rng)
Definition: parameter_distributions.h:480
ScalarType get_rand_sample(abm::PersonalRandomNumberGenerator &rng) override
Definition: parameter_distributions.h:494
ScalarType m_upper_bound
Definition: parameter_distributions.h:551
ScalarType get_rand_sample(RandomNumberGenerator &rng) override
Definition: parameter_distributions.h:489
std::vector< ScalarType > params() const override
Definition: parameter_distributions.h:461
UniformDistribution< ScalarType >::ParamType m_distribution
Definition: parameter_distributions.h:553
ScalarType get_upper_bound() const
Definition: parameter_distributions.h:471
static IOResult< ParameterDistributionUniform > deserialize_elements(IOContext &io, IOObject &obj)
Definition: parameter_distributions.h:520
ScalarType m_lower_bound
Definition: parameter_distributions.h:552
void serialize_elements(IOObject &obj) const
Definition: parameter_distributions.h:505
ParameterDistribution * clone() const override
Definition: parameter_distributions.h:499
ScalarType get_lower_bound() const
Definition: parameter_distributions.h:466
ParameterDistributionUniform(ScalarType lower_bound, ScalarType upper_bound)
Definition: parameter_distributions.h:442
Definition: parameter_distributions.h:75
virtual void accept(ConstParameterDistributionVisitor &visitor) const =0
void remove_predefined_samples()
Definition: parameter_distributions.h:88
const std::vector< ScalarType > & get_predefined_samples() const
Definition: parameter_distributions.h:93
virtual ParameterDistribution * clone() const =0
void serialize(IOContext &io) const
serialize this.
Definition: parameter_distributions.h:122
ParameterDistribution()
Definition: parameter_distributions.h:77
std::vector< ScalarType > m_predefined_samples
Definition: parameter_distributions.h:152
virtual void accept(ParameterDistributionVisitor &visitor)=0
This function implements the visit interface of the visitor pattern.
virtual ScalarType get_rand_sample(RandomNumberGenerator &rng)=0
virtual std::vector< ScalarType > params() const =0
Returns the distribution parameters as vector.
virtual bool smaller_impl(const ParameterDistribution &other) const =0
virtual ScalarType get_rand_sample(abm::PersonalRandomNumberGenerator &)=0
void add_predefined_sample(ScalarType sample)
Definition: parameter_distributions.h:83
virtual ~ParameterDistribution()=default
ScalarType get_sample(RNG &rng)
Definition: parameter_distributions.h:105
Random number generator of individual persons.
Definition: personal_rng.h:50
double ScalarType
Configuration of memilio library.
Definition: memilio/config.h:30
static min_max_return_type< ad::internal::active_type< AD_TAPE_REAL, DATA_HANDLER_1 >, ad::internal::active_type< AD_TAPE_REAL, DATA_HANDLER_1 > >::type min(const ad::internal::active_type< AD_TAPE_REAL, DATA_HANDLER_1 > &a, const ad::internal::active_type< AD_TAPE_REAL, DATA_HANDLER_1 > &b)
Definition: ad.hpp:2599
A collection of classes to simplify handling of matrix shapes in meta programming.
Definition: models/abm/analyze_result.h:30
auto failure(const IOStatus &s)
Create an object that is implicitly convertible to an error IOResult<T>.
Definition: io.h:380
boost::outcome_v2::in_place_type_t< T > Tag
Type that is used for overload resolution.
Definition: io.h:407
auto i
Definition: io.h:809
void log_warning(spdlog::string_view_t fmt, const Args &... args)
Definition: logging.h:112
details::ApplyResultT< F, T... > apply(IOContext &io, F f, const IOResult< T > &... rs)
Evaluate a function with zero or more unpacked IOResults as arguments.
Definition: io.h:481
auto success()
Create an object that is implicitly convertible to a succesful IOResult<void>.
Definition: io.h:359
auto max(const Eigen::MatrixBase< A > &a, B &&b)
coefficient wise maximum of two matrices.
Definition: eigen_util.h:171
boost::outcome_v2::unchecked< T, IOStatus > IOResult
Value-or-error type for operations that return a value but can fail.
Definition: io.h:353
IOResult< T > deserialize_internal(IOContext &io, Tag< T > tag)
Deserialization implementation for the default serialization feature.
Definition: default_serialize.h:236
Definition: visitor.h:71
Definition: visitor.h:90
A generic visitor inspired by Fedor Pikus.
Definition: visitor.h:52
Definition: parameter_distributions.h:57
virtual void visit(const ParameterDistributionNormal &normal_dist) final
Definition: parameter_distributions.h:430
IOObj & obj
Definition: parameter_distributions.h:67
SerializationVisitor(IOObj &o)
Definition: parameter_distributions.h:58