Skip to content

Commit

Permalink
Add event tree Sequence and Instruction
Browse files Browse the repository at this point in the history
Only 'collect-expression' instruction is implemented
for use by Sequence.

Issue #150
  • Loading branch information
rakhimov committed Mar 31, 2017
1 parent c4b8954 commit 786ec4e
Show file tree
Hide file tree
Showing 9 changed files with 132 additions and 7 deletions.
18 changes: 17 additions & 1 deletion src/event_tree.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@

#include "event_tree.h"

#include "error.h"

namespace scram {
namespace mef {

Expand All @@ -28,7 +30,21 @@ Instruction::~Instruction() = default;
CollectExpression::CollectExpression(const ExpressionPtr& expression)
: expression_(expression) {}

EventTree::EventTree(std::string name) : Element(std::move(name)) {}
void Sequence::instructions(InstructionContainer instructions) {
if (instructions.empty()) {
throw LogicError("Sequence " + Element::name() +
" requires at least one instruction");
}
instructions_ = std::move(instructions);
}

void EventTree::Add(SequencePtr sequence) {
if (sequences_.count(sequence->name())) {
throw ValidationError("Duplicate sequence " + sequence->name() +
" in event tree " + Element::name());
}
sequences_.insert(std::move(sequence));
}

} // namespace mef
} // namespace scram
37 changes: 34 additions & 3 deletions src/event_tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

#include <memory>
#include <string>
#include <vector>

#include <boost/noncopyable.hpp>

Expand All @@ -38,6 +39,12 @@ class Instruction : private boost::noncopyable {
virtual ~Instruction() = 0;
};

/// Instructions are assumed not to be shared.
using InstructionPtr = std::unique_ptr<Instruction>;

/// A collection of instructions.
using InstructionContainer = std::vector<InstructionPtr>;

/// The operation of collecting expressions for event tree sequences.
class CollectExpression : public Instruction {
public:
Expand All @@ -49,13 +56,37 @@ class CollectExpression : public Instruction {
ExpressionPtr expression_; ///< The probability expression to multiply.
};

/// Representation of sequences in event trees.
class Sequence : public Element {
public:
using Element::Element;

/// @param[in] instructions One or more instructions for the sequence.
///
/// @throws LogicError The instructions are empty.
void instructions(InstructionContainer instructions);

private:
/// Instructions to execute with the sequence.
InstructionContainer instructions_;
};

/// Sequences are defined in event trees but referenced in other constructs.
using SequencePtr = std::shared_ptr<Sequence>;

/// Event Tree representation with MEF constructs.
class EventTree : public Element, private boost::noncopyable {
public:
/// @param[in] name A unique name for the event tree within the model.
using Element::Element;

/// @param[in] sequence A unique sequence defined in this event tree.
///
/// @throws InvalidArgument The name is malformed.
explicit EventTree(std::string name);
/// @throws ValidationError The sequence is already defined.
void Add(SequencePtr sequence);

private:
/// Unique sequences defined in this event tree.
ElementTable<SequencePtr> sequences_;
};

using EventTreePtr = std::unique_ptr<EventTree>; ///< Unique trees in models.
Expand Down
32 changes: 32 additions & 0 deletions src/initializer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,16 @@ CcfGroupPtr Initializer::Register(const xmlpp::Element* ccf_node,
tbd_.emplace_back(ccf_group.get(), ccf_node);
return ccf_group;
}

template <>
SequencePtr Initializer::Register(const xmlpp::Element* xml_node,
const std::string& /*base_path*/,
RoleSpecifier /*container_role*/) {
SequencePtr sequence = ConstructElement<Sequence>(xml_node);
Register(sequence, xml_node);
tbd_.emplace_back(sequence.get(), xml_node);
return sequence;
}
/// @}

void Initializer::ProcessInputFile(const std::string& xml_file) {
Expand Down Expand Up @@ -414,6 +424,17 @@ void Initializer::Define(const xmlpp::Element* ccf_node, CcfGroup* ccf_group) {
}
}
}

template <>
void Initializer::Define(const xmlpp::Element* xml_node, Sequence* sequence) {
xmlpp::NodeSet xml_instructions =
xml_node->find("./*[name() != 'attributes' and name() != 'label']");
InstructionContainer instructions;
for (const xmlpp::Node* xml_instruction : xml_instructions) {
instructions.emplace_back(GetInstruction(XmlElement(xml_instruction)));
}
sequence->instructions(std::move(instructions));
}
/// @}

void Initializer::ProcessTbdElements() {
Expand All @@ -436,6 +457,10 @@ void Initializer::ProcessTbdElements() {

void Initializer::DefineEventTree(const xmlpp::Element* et_node) {
EventTreePtr event_tree = ConstructElement<EventTree>(et_node);
for (const xmlpp::Node* node : et_node->find("./define-sequence")) {
event_tree->Add(Register<Sequence>(XmlElement(node), event_tree->name(),
RoleSpecifier::kPublic));
}
Register(std::move(event_tree), et_node);
}

Expand Down Expand Up @@ -578,6 +603,13 @@ void Initializer::ProcessFormula(const xmlpp::Element* formula_node,
}
}

InstructionPtr Initializer::GetInstruction(const xmlpp::Element* xml_element) {
assert(xml_element->get_name() == "collect-expression");
const xmlpp::Element* arg_element =
XmlElement(xml_element->find("./*").front());
return std::make_unique<CollectExpression>(GetExpression(arg_element, ""));
}

template <class T, int N>
struct Initializer::Extractor {
/// Extracts and accumulates expressions
Expand Down
13 changes: 11 additions & 2 deletions src/initializer.h
Original file line number Diff line number Diff line change
Expand Up @@ -264,12 +264,21 @@ class Initializer : private boost::noncopyable {
const std::string& base_path,
Formula* formula);

/// Processes Instruction definitions.
///
/// @param[in] xml_element The XML element with instruction definitions.
///
/// @returns The newly defined instruction.
///
/// @throws ValidationError Errors in instruction definitions.
InstructionPtr GetInstruction(const xmlpp::Element* xml_element);

/// Processes Expression definitions in input file.
///
/// @param[in] expr_element XML expression element containing the definition.
/// @param[in] base_path Series of ancestor containers in the path with dots.
///
/// @returns Pointer to the newly defined or registered expression.
/// @returns The newly defined or registered expression.
///
/// @throws ValidationError There are problems with getting the expression.
ExpressionPtr GetExpression(const xmlpp::Element* expr_element,
Expand Down Expand Up @@ -363,7 +372,7 @@ class Initializer : private boost::noncopyable {
/// CCF groups rely on both parameter and basic event registrations.
///
/// Elements are assumed to be unique.
TbdContainer<Parameter, BasicEvent, Gate, CcfGroup> tbd_;
TbdContainer<Parameter, BasicEvent, Gate, CcfGroup, Sequence> tbd_;

/// Container of defined expressions for later validation due to cycles.
std::vector<std::pair<Expression*, const xmlpp::Element*>> expressions_;
Expand Down
7 changes: 7 additions & 0 deletions src/model.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ void Model::Add(EventTreePtr event_tree) {
event_trees_.insert(std::move(event_tree));
}

void Model::Add(const SequencePtr& sequence) {
if (sequences_.count(sequence->name())) {
throw RedefinitionError("Redefinition of sequence " + sequence->name());
}
sequences_.insert(std::move(sequence));
}

void Model::Add(FaultTreePtr fault_tree) {
if (fault_trees_.count(fault_tree->name())) {
throw RedefinitionError("Redefinition of fault tree " + fault_tree->name());
Expand Down
3 changes: 3 additions & 0 deletions src/model.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ class Model : public Element, private boost::noncopyable {
/// @returns Defined constructs in the model.
/// @{
const ElementTable<EventTreePtr>& event_trees() const { return event_trees_; }
const ElementTable<SequencePtr>& sequences() const { return sequences_; }
const ElementTable<FaultTreePtr>& fault_trees() const { return fault_trees_; }
const IdTable<ParameterPtr>& parameters() const {
return parameters_.entities_by_id;
Expand All @@ -85,6 +86,7 @@ class Model : public Element, private boost::noncopyable {
///
/// @{
void Add(EventTreePtr element);
void Add(const SequencePtr& element);
void Add(FaultTreePtr element);
void Add(const ParameterPtr& element);
void Add(const HouseEventPtr& element);
Expand Down Expand Up @@ -182,6 +184,7 @@ class Model : public Element, private boost::noncopyable {
/// A collection of defined constructs in the model.
/// @{
ElementTable<EventTreePtr> event_trees_;
ElementTable<SequencePtr> sequences_;
ElementTable<FaultTreePtr> fault_trees_;
LookupTable<Gate> gates_;
LookupTable<HouseEvent> house_events_;
Expand Down
1 change: 1 addition & 0 deletions src/reporter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ void Reporter::ReportModelFeatures(const mef::Model& model,
feature("house-events", model.house_events());
feature("ccf-groups", model.ccf_groups());
feature("fault-trees", model.fault_trees());
feature("event-trees", model.event_trees());
}

void Reporter::ReportPerformance(const core::RiskAnalysis& risk_an,
Expand Down
4 changes: 3 additions & 1 deletion tests/initializer_tests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,9 @@ TEST(InitializerTest, CorrectEtaInputs) {

TEST(InitializerTest, IncorrectEtaInputs) {
std::string dir = "./share/scram/input/eta/";
const char* incorrect_inputs[] = {"doubly_defined_event_tree.xml"};
const char* incorrect_inputs[] = {
"doubly_defined_event_tree.xml", "doubly_defined_sequence.xml",
};
for (const auto& input : incorrect_inputs) {
EXPECT_THROW(Initializer({dir + input}, core::Settings()), ValidationError)
<< " Filename: " << input;
Expand Down
24 changes: 24 additions & 0 deletions tests/input/eta/doubly_defined_sequence.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?xml version="1.0"?>

<opsa-mef>
<define-event-tree name="first">
<define-sequence name="S">
<collect-expression>
<bool value="true"/>
</collect-expression>
</define-sequence>
<initial-state>
<sequence name="S"/>
</initial-state>
</define-event-tree>
<define-event-tree name="second">
<define-sequence name="S">
<collect-expression>
<bool value="true"/>
</collect-expression>
</define-sequence>
<initial-state>
<sequence name="S"/>
</initial-state>
</define-event-tree>
</opsa-mef>

0 comments on commit 786ec4e

Please sign in to comment.