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.