Skip to content

packages/engine/scram/src/probability_analysis.h

Contains functionality to do numerical analysis of probabilities.

Namespaces

Name
scram
scram::mef
scram::core

Classes

Name
structscram::core::Sil <br>Safety Integrity Level metrics.
classscram::core::ProbabilityAnalysis <br>Main quantitative analysis class.
classscram::core::CutSetProbabilityCalculator <br>Quantitative calculator of a probability value of a single cut set.
classscram::core::RareEventCalculator <br>Quantitative calculator of probability values with the Rare-Event approximation.
classscram::core::McubCalculator <br>Quantitative calculator of probability values with the Min-Cut-Upper Bound approximation.
classscram::core::ProbabilityAnalyzerBase <br>Base class for Probability analyzers.
classscram::core::ProbabilityAnalyzer <br>Fault-tree-analysis-aware probability analyzer.
classscram::core::ProbabilityAnalyzer< Bdd > <br>Specialization of probability analyzer with Binary Decision Diagrams.

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 <utility>
#include <vector>
#include <memory>

#include "analysis.h"
#include "bdd.h"
#include "fault_tree_analysis.h"
#include "logger.h"
#include "pdag.h"

namespace scram::mef {
class MissionTime;
} // namespace scram::mef

namespace scram::core {

    struct Sil {
        double pfd_avg = 0;
        double pfh_avg = 0;

        std::array<std::pair<const double, double>, 6> pfd_fractions{
                {{1e-5, 0}, {1e-4, 0}, {1e-3, 0}, {1e-2, 0}, {1e-1, 0}, {1, 0}}};
        std::array<std::pair<const double, double>, 6> pfh_fractions{
                {{1e-9, 0}, {1e-8, 0}, {1e-7, 0}, {1e-6, 0}, {1e-5, 0}, {1, 0}}};
    };

    class ProbabilityAnalysis : public Analysis {
    public:
        ProbabilityAnalysis(const FaultTreeAnalysis *fta, mef::MissionTime *mission_time);

        virtual ~ProbabilityAnalysis() = default;

        void Analyze() ;

        double p_total() const { return p_total_; }

        const std::vector<std::pair<double, double>> &p_time() const {
            return p_time_;
        }

        const Sil &sil() const {
            assert(sil_ && "The SIL is not done!");
            return *sil_;
        }

    protected:
        mef::MissionTime &mission_time() { return *mission_time_; }

    private:
        virtual double CalculateTotalProbability()  = 0;

        virtual std::vector<std::pair<double, double>>
        CalculateProbabilityOverTime()  = 0;

        void ComputeSil() ;

        double p_total_;                               
        mef::MissionTime *mission_time_;               
        std::vector<std::pair<double, double>> p_time_;
        std::unique_ptr<Sil> sil_;                     
    };

    class CutSetProbabilityCalculator {
    public:
        double Calculate(const std::vector<int> &cut_set,
                         const Pdag::IndexMap<double> &p_vars) ;
    };

    class Zbdd;// The container of analysis products for computations.

    class RareEventCalculator : private CutSetProbabilityCalculator {
    public:
        double Calculate(const Zbdd &cut_sets,
                         const Pdag::IndexMap<double> &p_vars) ;

        double Calculate(const ProductSummary::ProductList &cut_sets,
                 const Pdag::IndexMap<double> &p_vars) ;

    };

    class McubCalculator : private CutSetProbabilityCalculator {
    public:
        double Calculate(const Zbdd &cut_sets,
                         const Pdag::IndexMap<double> &p_vars) ;

        double Calculate(const ProductSummary::ProductList &cut_sets,
                 const Pdag::IndexMap<double> &p_vars) ;

    };

    class ProbabilityAnalyzerBase : public ProbabilityAnalysis {
    public:
        template<class Algorithm>
                ProbabilityAnalyzerBase(const FaultTreeAnalyzer<Algorithm> *fta,
                                        mef::MissionTime *mission_time)
                    : ProbabilityAnalysis(fta, mission_time),
                      graph_(fta->graph()),
                      fta_(fta) {
                    if (!settings().skip_products() && settings().requires_products()) {
                        const Zbdd& zbdd = (fta->algorithm()->products());
                        products_ = &zbdd;
                    }
                    ExtractVariableProbabilities();
                }

        [[nodiscard]] Pdag *graph() const { return graph_; }

        [[nodiscard]] const Zbdd &products() const { return *products_; }

        [[nodiscard]] const Pdag::IndexMap<double> &p_vars() const { return p_vars_; }

        [[nodiscard]] const FaultTreeAnalysis *fault_tree_analysis() const { return fta_; }

    protected:
        ~ProbabilityAnalyzerBase() override = default;

    private:
        virtual double
        CalculateTotalProbability(const Pdag::IndexMap<double> &p_vars) = 0;

        double CalculateTotalProbability()  override {
            return ApplyInitiatingEventFrequency(
                this->CalculateTotalProbability(p_vars_));
        }

        std::vector<std::pair<double, double>>
        CalculateProbabilityOverTime()  override;

        void ExtractVariableProbabilities();

    public:
        double ApplyInitiatingEventFrequency(double probability) const {
            return graph_->initiating_event_frequency() * probability;
        }

        double initiating_event_frequency() const {
            return graph_->initiating_event_frequency();
        }

    protected:
        Pdag *graph_;            
        const Zbdd *products_;  
        Pdag::IndexMap<double> p_vars_;
        const FaultTreeAnalysis *fta_ = nullptr; 
    };

    template<class Calculator>
    class ProbabilityAnalyzer : public ProbabilityAnalyzerBase {
    public:
        using ProbabilityAnalyzerBase::ProbabilityAnalyzerBase;

        double CalculateTotalProbability(
                const Pdag::IndexMap<double> &p_vars)  final;

    private:
        Calculator calc_;
    };

    template<>
    class ProbabilityAnalyzer<Bdd> : public ProbabilityAnalyzerBase {
    public:
        template<class Algorithm>
        ProbabilityAnalyzer(const FaultTreeAnalyzer<Algorithm> *fta,
                            mef::MissionTime *mission_time)
            : ProbabilityAnalyzerBase(fta, mission_time),
              current_mark_(false),
              owner_(true) {
            CreateBdd(*fta);
        }

        ProbabilityAnalyzer(FaultTreeAnalyzer<Bdd> *fta,
                            mef::MissionTime *mission_time);

        ~ProbabilityAnalyzer() ;

        Bdd *bdd_graph() { return bdd_graph_; }

        double CalculateTotalProbability(
                const Pdag::IndexMap<double> &p_vars)  final;

    private:
        void CreateBdd(const FaultTreeAnalysis &fta) ;

        double CalculateProbability(const Bdd::VertexPtr &vertex, bool mark,
                                    const Pdag::IndexMap<double> &p_vars) ;

        Bdd *bdd_graph_;   
        bool current_mark_;
        bool owner_;       
    };

}// namespace scram::core

Updated on 2026-01-09 at 21:59:13 +0000