Skip to content

packages/engine/scram-node/src/event.h

Contains event classes for fault trees.

Namespaces

Name
scram
scram::mef

Classes

Name
classscram::mef::Event <br>Abstract base class for general fault tree events.
classscram::mef::HouseEvent <br>Representation of a house event in a fault tree.
classscram::mef::BasicEvent <br>Representation of a basic event in a fault tree.
classscram::mef::Gate <br>A representation of a gate in a fault tree.
classscram::mef::Formula <br>Boolean formula with connectives and arguments.
structscram::mef::Formula::Arg <br>Formula argument with a complement flag.
classscram::mef::Formula::ArgSet <br>The set of formula arguments.

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 <cstdint>

#include <initializer_list>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <variant>
#include <vector>

#include "element.h"
#include "expression.h"

namespace scram::mef {

class Event : public Id, public Usage {
 public:
  static constexpr const char* kTypeString = "event";  

  using Id::Id;

  virtual ~Event() = 0;  
};

class HouseEvent : public Event {
 public:
  static constexpr const char* kTypeString = "house event";  

  static HouseEvent kTrue;  
  static HouseEvent kFalse;  

  using Event::Event;

  HouseEvent(HouseEvent&&);  

  void state(bool constant) { state_ = constant; }

  bool state() const { return state_; }

 private:
  bool state_ = false;
};

class Gate;

class BasicEvent : public Event {
 public:
  static constexpr const char* kTypeString = "basic event";  

  using Event::Event;

  virtual ~BasicEvent() = default;

  bool HasExpression() const { return expression_ != nullptr; }

  void expression(Expression* expression) { expression_ = expression; }

  Expression& expression() const {
    assert(expression_ && "The basic event's expression is not set.");
    return *expression_;
  }

  double p() const noexcept {
    assert(expression_ && "The basic event's expression is not set.");
    return expression_->value();
  }

  void Validate() const;

  bool HasCcf() const { return ccf_gate_ != nullptr; }

  const Gate& ccf_gate() const {
    assert(ccf_gate_);
    return *ccf_gate_;
  }

  void ccf_gate(std::unique_ptr<Gate> gate) {
    assert(!ccf_gate_);
    ccf_gate_ = std::move(gate);
  }

 private:
  Expression* expression_ = nullptr;

  std::unique_ptr<Gate> ccf_gate_;
};

class Formula;  // To describe a gate's formula.

class Gate : public Event, public NodeMark {
 public:
  static constexpr const char* kTypeString = "gate";  

  using Event::Event;

  bool HasFormula() const { return formula_ != nullptr; }

  const Formula& formula() const {
    assert(formula_ && "Gate formula is not set.");
    return *formula_;
  }
  Formula& formula() {
    return const_cast<Formula&>(std::as_const(*this).formula());
  }

  std::unique_ptr<Formula> formula(std::unique_ptr<Formula> formula) {
    assert(formula && "Cannot unset formula.");
    formula_.swap(formula);
    return formula;
  }

 private:
  std::unique_ptr<Formula> formula_;  
};

enum Connective : std::uint8_t {
  kAnd = 0,
  kOr,
  kAtleast,  
  kXor,  
  kNot,  
  kNand,  
  kNor,  
  kNull,  

  // Rarely used connectives specific to the MEF.
  kIff,  
  kImply,  
  kCardinality  
};

const int kNumConnectives = 11;

const char* const kConnectiveToString[] = {"and", "or",    "atleast",    "xor",
                                           "not", "nand",  "nor",        "null",
                                           "iff", "imply", "cardinality"};

class Formula {
 public:
  using ArgEvent = std::variant<Gate*, BasicEvent*, HouseEvent*>;

  struct Arg {
    bool complement;  
    ArgEvent event;  
  };

  class ArgSet {
   public:
    ArgSet() = default;

    ArgSet(std::initializer_list<Arg> init_list)
        : ArgSet(init_list.begin(), init_list.end()) {}

    ArgSet(std::initializer_list<ArgEvent> init_list)
        : ArgSet(init_list.begin(), init_list.end()) {}

    template <typename Iterator>
    ArgSet(Iterator first1, Iterator last1) {
      for (; first1 != last1; ++first1)
        Add(*first1);
    }

    void Add(ArgEvent event, bool complement = false);

    void Add(Arg arg) { Add(arg.event, arg.complement); }

    void Remove(ArgEvent event);

    const std::vector<Arg>& data() const { return args_; }
    std::vector<Arg>& data() { return args_; }

    std::size_t size() const { return args_.size(); }

    bool empty() const { return args_.empty(); }

   private:
    std::vector<Arg> args_;  
  };

  Formula(Connective connective, ArgSet args,
          std::optional<int> min_number = {},
          std::optional<int> max_number = {});

  Formula(const Formula&) = default;
  Formula& operator=(const Formula&) = default;

  Connective connective() const { return connective_; }

  std::optional<int> min_number() const;

  std::optional<int> max_number() const;

  const std::vector<Arg>& args() const { return args_.data(); }

  void Swap(ArgEvent current, ArgEvent other);

 private:
  void ValidateMinMaxNumber(std::optional<int> min_number,
                            std::optional<int> max_number);

  void ValidateConnective(std::optional<int> min_number,
                          std::optional<int> max_number);

  void ValidateNesting(const Arg& arg);

  Connective connective_;  
  std::uint16_t min_number_;  
  std::uint16_t max_number_;  
  ArgSet args_;  
};

using FormulaPtr = std::unique_ptr<Formula>;  

inline bool operator==(const Formula::Arg& lhs,
                       const Formula::Arg& rhs) noexcept {
  return lhs.complement == rhs.complement && lhs.event == rhs.event;
}

}  // namespace scram::mef

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