Skip to content

packages/engine/scram-node/src/expression/random_deviate.h

A collection of deviate expressions with random distributions sampled at run-time.

Namespaces

Name
scram
scram::mef

Classes

Name
classscram::mef::RandomDeviate <br>Abstract base class for all deviate expressions.
classscram::mef::UniformDeviate <br>Uniform distribution.
classscram::mef::NormalDeviate <br>Normal distribution.
classscram::mef::LognormalDeviate <br>Log-normal distribution.
classscram::mef::GammaDeviate <br>Gamma distribution.
classscram::mef::BetaDeviate <br>Beta distribution.
classscram::mef::Histogram <br>Histogram distribution.

Source code

cpp
/*
 * Copyright (C) 2014-2018 Olzhas Rakhimov
 * Copyright (C) 2023 OpenPRA ORG Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */


#pragma once

#include <memory>
#include <random>
#include <vector>

#include <boost/range/iterator_range.hpp>

#include "src/expression.h"

namespace scram::mef {

class RandomDeviate : public Expression {
 public:
  using Expression::Expression;

  bool IsDeviate() noexcept override { return true; }

  static void seed(unsigned seed) noexcept { rng_.seed(seed); }

 protected:
  std::mt19937& rng() { return rng_; }

 private:
  static std::mt19937 rng_;  
};

class UniformDeviate : public RandomDeviate {
 public:
  UniformDeviate(Expression* min, Expression* max);

  void Validate() const override;

  double value() noexcept override { return (min_.value() + max_.value()) / 2; }
  Interval interval() noexcept override {
    return Interval::closed(min_.value(), max_.value());
  }

 private:
  double DoSample() noexcept override;

  Expression& min_;  
  Expression& max_;  
};

class NormalDeviate : public RandomDeviate {
 public:
  NormalDeviate(Expression* mean, Expression* sigma);

  void Validate() const override;

  double value() noexcept override { return mean_.value(); }
  Interval interval() noexcept override {
    double mean = mean_.value();
    double delta = 6 * sigma_.value();
    return Interval::closed(mean - delta, mean + delta);
  }

 private:
  double DoSample() noexcept override;

  Expression& mean_;  
  Expression& sigma_;  
};

class LognormalDeviate : public RandomDeviate {
 public:
  LognormalDeviate(Expression* mean, Expression* ef, Expression* level);

  LognormalDeviate(Expression* mu, Expression* sigma);

  void Validate() const override { flavor_->Validate(); };
  double value() noexcept override { return flavor_->mean(); }
  Interval interval() noexcept override;

 private:
  double DoSample() noexcept override;

  struct Flavor {
    virtual ~Flavor() = default;
    virtual double scale() noexcept = 0;
    virtual double location() noexcept = 0;
    virtual double mean() noexcept = 0;
    virtual void Validate() const = 0;
  };

  class Logarithmic final : public Flavor {
   public:
    Logarithmic(Expression* mean, Expression* ef, Expression* level)
        : mean_(*mean), ef_(*ef), level_(*level) {}
    double scale() noexcept override;
    double location() noexcept override;
    double mean() noexcept override { return mean_.value(); }
    void Validate() const override;

   private:
    Expression& mean_;  
    Expression& ef_;  
    Expression& level_;  
  };

  class Normal final : public Flavor {
   public:
    Normal(Expression* mu, Expression* sigma) : mu_(*mu), sigma_(*sigma) {}
    double scale() noexcept override { return sigma_.value(); }
    double location() noexcept override { return mu_.value(); }
    double mean() noexcept override;
    void Validate() const override;

   private:
    Expression& mu_;  
    Expression& sigma_;  
  };

  std::unique_ptr<Flavor> flavor_;  
};

class GammaDeviate : public RandomDeviate {
 public:
  GammaDeviate(Expression* k, Expression* theta);

  void Validate() const override;

  double value() noexcept override { return k_.value() * theta_.value(); }
  Interval interval() noexcept override;

 private:
  double DoSample() noexcept override;

  Expression& k_;  
  Expression& theta_;  
};

class BetaDeviate : public RandomDeviate {
 public:
  BetaDeviate(Expression* alpha, Expression* beta);

  void Validate() const override;

  double value() noexcept override {
    double alpha_mean = alpha_.value();
    return alpha_mean / (alpha_mean + beta_.value());
  }

  Interval interval() noexcept override;

 private:
  double DoSample() noexcept override;

  Expression& alpha_;  
  Expression& beta_;  
};

class Histogram : public RandomDeviate {
 public:
  Histogram(std::vector<Expression*> boundaries,
            std::vector<Expression*> weights);

  void Validate() const override;

  double value() noexcept override;
  Interval interval() noexcept override {
    return Interval::closed((*boundaries_.begin())->value(),
                            (*std::prev(boundaries_.end()))->value());
  }

 private:
  using IteratorRange =
      boost::iterator_range<std::vector<Expression*>::const_iterator>;

  double DoSample() noexcept override;

  IteratorRange boundaries_;  
  IteratorRange weights_;  
};

}  // namespace scram::mef

Updated on 2025-11-11 at 16:51:08 +0000