Skip to content

Commit

Permalink
Collect non-declarative Substitutions in PDAG
Browse files Browse the repository at this point in the history
These substitutions cannot be applied by PDAG at construction.
The analysis must handle non-declarative substitutions with sets.

Issue #154
  • Loading branch information
rakhimov committed Nov 18, 2017
1 parent 053c143 commit 2551dea
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 3 deletions.
57 changes: 54 additions & 3 deletions src/pdag.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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<Gate>(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_);
Expand Down Expand Up @@ -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<mef::BasicEvent*>(&substitution.target()))
GatherVariables(**target, ccf, nodes);
}
Expand Down Expand Up @@ -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<mef::BasicEvent*>(&substitution.target()))
return nodes->variables.find(*event)->second->index();

assert(*boost::get<bool>(&substitution.target()) && "Invalid delete term");
return 0;
}();

std::vector<int> 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<int> args;
for (const mef::Formula::EventArg& arg :
substitution.hypothesis().event_args()) {
auto* event = boost::get<mef::BasicEvent*>(&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<mef::BasicEvent*>(&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!
Expand Down
31 changes: 31 additions & 0 deletions src/pdag.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<int> hypothesis;
/// The non-empty unique source event IDs to remove.
const std::vector<int> 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!).
Expand Down Expand Up @@ -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.),
Expand All @@ -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<Substitution>& substitutions() const {
return substitutions_;
}

/// @returns true if the fault tree is coherent.
bool coherent() const { return coherent_; }

Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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<GateWeakPtr> null_gates_;
std::vector<Substitution> substitutions_; ///< Non-declarative substitutions.
};

/// Traverses and visits gates and nodes in the graph.
Expand Down

0 comments on commit 2551dea

Please sign in to comment.