Skip to content

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

Fault Tree Analysis.

Namespaces

Name
scram
scram::mef
scram::core

Classes

Name
structscram::core::Literal <br>Event or its complement that may appear in products.
classscram::core::Product <br>Collection of unique literals.
classscram::core::ProductContainer <br>A container of analysis result products with Literals.
classscram::core::FaultTreeAnalysis <br>Fault tree analysis functionality.
classscram::core::FaultTreeAnalyzer <br>Fault tree analysis facility with specific algorithms.

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

#include <memory>
#include <unordered_set>
#include <vector>

#include <boost/iterator/iterator_facade.hpp>
#include <boost/iterator/transform_iterator.hpp>

#include "analysis.h"
#include "pdag.h"
#include "preprocessor.h"
#include "settings.h"
#include "zbdd.h"

namespace scram::mef {  // Decouple from the analysis code.
class Model;  // Provider of substitutions.
class Gate;
class BasicEvent;
}  // namespace scram::mef

namespace scram::core {

struct Literal {
  bool complement;  
  const mef::BasicEvent& event;  
};

class Product {
  struct LiteralExtractor {
    Literal operator()(int index) const {
      return {index < 0, *graph.basic_events()[std::abs(index)]};
    }
    const Pdag& graph;  
  };

 public:
  Product(const std::vector<int>& data, const Pdag& graph) noexcept
      : data_(data), graph_(graph) {}

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

  int size() const { return data_.size(); }

  int order() const { return empty() ? 1 : size(); }

  double p() const;

  auto begin() const {
    return boost::make_transform_iterator(data_.begin(),
                                          LiteralExtractor{graph_});
  }

  auto end() const {
    return boost::make_transform_iterator(data_.end(),
                                          LiteralExtractor{graph_});
  }

 private:
  const std::vector<int>& data_;  
  const Pdag& graph_;  
};

class ProductContainer {
  struct ProductExtractor {
    Product operator()(const std::vector<int>& product) const {
      return Product(product, graph);
    }
    const Pdag& graph;  
  };

 public:
  ProductContainer(const Zbdd& products, const Pdag& graph) noexcept;

  const std::unordered_set<const mef::BasicEvent*>& product_events() const {
    return product_events_;
  }

  auto begin() const {
    return boost::make_transform_iterator(products_.begin(),
                                          ProductExtractor{graph_});
  }
  auto end() const {
    return boost::make_transform_iterator(products_.end(),
                                          ProductExtractor{graph_});
  }

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

  int size() const { return size_; }

  const std::vector<int>& distribution() const { return distribution_; }

 private:
  const Zbdd& products_;  
  const Pdag& graph_;  
  int size_;  
  std::vector<int> distribution_;  
  std::unordered_set<const mef::BasicEvent*> product_events_;
};

void Print(const ProductContainer& products);

class FaultTreeAnalysis : public Analysis {
 public:
  FaultTreeAnalysis(const mef::Gate& root, const Settings& settings,
                    const mef::Model* model = nullptr);

  virtual ~FaultTreeAnalysis() = default;

  const mef::Gate& top_event() const { return top_event_; }

  void Analyze() noexcept;

  const ProductContainer& products() const {
    assert(products_ && "The analysis is not done!");
    return *products_;
  }

 protected:
  const Pdag* graph() const { return graph_.get(); }

 private:
  virtual void Preprocess(Pdag* graph) noexcept = 0;

  virtual const Zbdd& GenerateProducts(const Pdag* graph) noexcept = 0;

  void Store(const Zbdd& products, const Pdag& graph) noexcept;

  const mef::Gate& top_event_;  
  const mef::Model* model_;  
  std::unique_ptr<Pdag> graph_;  
  std::unique_ptr<const ProductContainer> products_;  
};

template <class Algorithm>
class FaultTreeAnalyzer : public FaultTreeAnalysis {
 public:
  using FaultTreeAnalysis::FaultTreeAnalysis;
  using FaultTreeAnalysis::graph;  // Provide access to other analyses.

  const Algorithm* algorithm() const { return algorithm_.get(); }
  Algorithm* algorithm() { return algorithm_.get(); }

 private:
  void Preprocess(Pdag* graph) noexcept override {
    CustomPreprocessor<Algorithm>{graph}();
  }

  const Zbdd& GenerateProducts(const Pdag* graph) noexcept override {
    algorithm_ = std::make_unique<Algorithm>(graph, Analysis::settings());
    algorithm_->Analyze(graph);
    return algorithm_->products();
  }

  std::unique_ptr<Algorithm> algorithm_;  
};

}  // namespace scram::core

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