From 2551deae9b2efdf83bbfc2ec3f425ea5e533da5e Mon Sep 17 00:00:00 2001 From: rakhimov Date: Fri, 17 Nov 2017 00:26:33 -0800 Subject: [PATCH] Collect non-declarative Substitutions in PDAG These substitutions cannot be applied by PDAG at construction. The analysis must handle non-declarative substitutions with sets. Issue #154 --- src/pdag.cc | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++--- src/pdag.h | 31 +++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 3 deletions(-) diff --git a/src/pdag.cc b/src/pdag.cc index 4516e98963..2a6bbd90b2 100644 --- a/src/pdag.cc +++ b/src/pdag.cc @@ -467,11 +467,14 @@ Pdag::Pdag(const mef::Gate& root, bool ccf, const mef::Model* model) noexcept root_ = ConstructGate(root.formula(), ccf, &nodes); - if (model) { // Apply declarative substitutions. + if (model) { // Process substitution application. auto application = std::make_shared(kAnd, this); for (const mef::SubstitutionPtr& substitution : model->substitutions()) { - if (substitution->declarative()) + if (substitution->declarative()) { // Apply declarative substitutions. application->AddArg(ConstructSubstitution(*substitution, ccf, &nodes)); + } else { // Gather non-declarative substitutions for analysis. + CollectSubstitution(*substitution, &nodes); + } } if (!application->args().empty()) { application->AddArg(root_); @@ -543,8 +546,13 @@ void Pdag::GatherVariables(const mef::BasicEvent& basic_event, bool ccf, void Pdag::GatherVariables(const mef::Substitution& substitution, bool ccf, ProcessedNodes* nodes) noexcept { - assert(substitution.declarative() && "Non-declarative is not implemented."); GatherVariables(substitution.hypothesis(), ccf, nodes); + + for (const mef::BasicEvent* event : substitution.source()) { + assert(!event->HasCcf() && "Non declarative substitutions w/ CCF groups."); + GatherVariables(*event, ccf, nodes); + } + if (auto* target = boost::get(&substitution.target())) GatherVariables(**target, ccf, nodes); } @@ -640,6 +648,49 @@ GatePtr Pdag::ConstructSubstitution(const mef::Substitution& substitution, return implication; } +void Pdag::CollectSubstitution(const mef::Substitution& substitution, + ProcessedNodes* nodes) noexcept { + assert(!substitution.declarative() && "Only non-declarative substitutions."); + int target = [&substitution, &nodes] { + if (auto* event = boost::get(&substitution.target())) + return nodes->variables.find(*event)->second->index(); + + assert(*boost::get(&substitution.target()) && "Invalid delete term"); + return 0; + }(); + + std::vector source; + for (const mef::BasicEvent* event : substitution.source()) + source.push_back(nodes->variables.find(event)->second->index()); + + switch (substitution.hypothesis().type()) { + case mef::kNull: + case mef::kAnd: { + std::vector args; + for (const mef::Formula::EventArg& arg : + substitution.hypothesis().event_args()) { + auto* event = boost::get(&arg); + assert(event); + args.push_back(nodes->variables.find(*event)->second->index()); + } + substitutions_.push_back({std::move(args), std::move(source), target}); + break; + } + case mef::kOr: { + for (const mef::Formula::EventArg& arg : + substitution.hypothesis().event_args()) { + auto* event = boost::get(&arg); + assert(event); + substitutions_.push_back( + {{nodes->variables.find(*event)->second->index()}, source, target}); + } + break; + } + default: + assert(false && "Only simple formulas for non-declarative substitutions"); + } +} + bool Pdag::IsTrivial() noexcept { assert(root_.use_count() == 1 && "Graph gate pointers outside of the graph!"); /// @todo Enable the code by decouple the order assignment! diff --git a/src/pdag.h b/src/pdag.h index e52fbe4b4c..5e328c01d8 100644 --- a/src/pdag.h +++ b/src/pdag.h @@ -807,6 +807,17 @@ class Pdag : private boost::noncopyable { } }; + /// Non-declarative substitutions. + struct Substitution { + /// The non-empty unique hypothesis set event IDs. + const std::vector hypothesis; + /// The non-empty unique source event IDs to remove. + const std::vector source; + /// The target event ID. + /// 0 indicates absence of a target (i.e., constant True). + const int target; + }; + /// Various kinds of marks applied to the nodes. enum NodeMark { kGateMark, ///< General graph traversal (dirty upon traversal end!). @@ -834,6 +845,9 @@ class Pdag : private boost::noncopyable { /// /// @pre No new Variable nodes are introduced after the construction. /// + /// @post All declarative substitutions are applied, + /// and all non-declarative substitutions are collected for application. + /// /// @post The PDAG is stable as long as /// the argument fault tree and its underlying containers are stable. /// If the fault tree has been manipulated (event addition, etc.), @@ -849,6 +863,11 @@ class Pdag : private boost::noncopyable { explicit Pdag(const mef::Gate& root, bool ccf = false, const mef::Model* model = nullptr) noexcept; + /// @returns Non-declarative substitutions to be applied by analysis. + const std::vector& substitutions() const { + return substitutions_; + } + /// @returns true if the fault tree is coherent. bool coherent() const { return coherent_; } @@ -1046,6 +1065,17 @@ class Pdag : private boost::noncopyable { GatePtr ConstructSubstitution(const mef::Substitution& substitution, bool ccf, ProcessedNodes* nodes) noexcept; + /// Collects non-declarative substitutions for later analysis. + /// + /// @param[in] substitution The non-declarative substitution. + /// @param[in,out] nodes The mapping of gathered Variables. + /// + /// @pre The substitution is non-declarative. + /// @pre Non-declarative substitution events are not in CCF groups. + /// @pre All the substitution variables have been gathered. + void CollectSubstitution(const mef::Substitution& substitution, + ProcessedNodes* nodes) noexcept; + /// Processes a Boolean formula's argument events /// into arguments of an indexed gate in the PDAG. /// Basic events are saved for reference in analysis. @@ -1081,6 +1111,7 @@ class Pdag : private boost::noncopyable { /// Container for NULL type gates to be tracked and cleaned by algorithms. /// NULL type gates are created by gates with only one argument. std::vector null_gates_; + std::vector substitutions_; ///< Non-declarative substitutions. }; /// Traverses and visits gates and nodes in the graph.