3#include <boost/algorithm/string.hpp>
18template<
typename ValueType>
25 return parseJson(jsonInput);
28template<
typename ValueType>
30 Json jsonInput = Json::parse(jsonString);
31 return parseJson(jsonInput);
34template<
typename ValueType>
39 std::string toplevelName =
"";
42 std::string currentLocation;
45 currentLocation =
"parameters";
46 if (jsonInput.count(
"parameters") > 0) {
47 Json parameters = jsonInput.at(
"parameters");
48 STORM_LOG_THROW(parameters.empty() || (std::is_same<ValueType, storm::RationalFunction>::value), storm::exceptions::NotSupportedException,
49 "Parameters are only allowed when using rational functions.");
50 for (
auto const& parameter : parameters) {
55 currentLocation =
"nodes";
56 Json
const& nodes = jsonInput.at(
"nodes");
58 std::map<std::string, std::string> nameMapping;
59 std::set<std::string> names;
60 for (
auto const& element : nodes) {
61 Json data = element.at(
"data");
62 std::string
id = data.at(
"id");
63 std::string name = parseName(data.at(
"name"));
64 STORM_LOG_THROW(names.find(name) == names.end(), storm::exceptions::WrongFormatException,
"Element '" << name <<
"' was already declared.");
66 nameMapping[id] = name;
70 for (
auto const& element : nodes) {
71 currentLocation = parseValue(element);
72 Json
const& data = element.at(
"data");
73 std::string name = parseName(data.at(
"name"));
75 if (data.count(
"relevant") > 0) {
76 bool isRelevant = data.at(
"relevant");
78 relevantEvents.
insert(name);
82 std::vector<std::string> childNames;
84 if (data.count(
"children") > 0) {
85 for (
auto const& child : data.at(
"children")) {
86 STORM_LOG_THROW(nameMapping.find(child) != nameMapping.end(), storm::exceptions::WrongFormatException,
87 "Child '" << child <<
"' for element '" << name <<
"' was not defined.");
88 childNames.push_back(nameMapping.at(child));
92 std::string type = data.at(
"type");
95 }
else if (type ==
"or") {
97 }
else if (type ==
"vot") {
98 STORM_LOG_THROW(data.count(
"voting") > 0, storm::exceptions::WrongFormatException,
"Voting gate '" << name <<
"' requires parameter 'voting'.");
99 std::string votThreshold = parseValue(data.at(
"voting"));
100 builder.
addVotingGate(name, storm::parser::parseNumber<size_t>(votThreshold), childNames);
101 }
else if (type ==
"pand") {
102 if (data.count(
"inclusive") > 0) {
103 bool inclusive = data.at(
"inclusive");
108 }
else if (type ==
"por") {
109 if (data.count(
"inclusive") > 0) {
110 bool inclusive = data.at(
"inclusive");
111 builder.
addPorGate(name, childNames, inclusive);
115 }
else if (type ==
"spare") {
117 }
else if (type ==
"seq") {
119 }
else if (type ==
"mutex") {
121 }
else if (type ==
"fdep") {
122 builder.
addPdep(name, childNames, storm::utility::one<ValueType>());
123 }
else if (type ==
"pdep") {
124 STORM_LOG_THROW(data.count(
"probability") > 0, storm::exceptions::WrongFormatException,
125 "PDEP '" << name <<
"' requires parameter 'probability'.");
127 if (storm::utility::isZero<ValueType>(probability)) {
129 STORM_LOG_WARN(
"Dependency " << name <<
" with probability 0 is superfluous and will not be added.");
132 builder.
addPdep(name, childNames, probability);
133 }
else if (boost::starts_with(type,
"be")) {
134 parseBasicElement(name, type, data, builder, valueParser);
135 }
else if (type ==
"compound") {
138 STORM_LOG_THROW(
false, storm::exceptions::NotSupportedException,
"Type name '" << type <<
"' not recognized.");
141 if (element.find(
"position") != element.end()) {
143 Json position = element.at(
"position");
144 double x = position.at(
"x");
145 double y = position.at(
"y");
150 STORM_LOG_THROW(jsonInput.count(
"toplevel") > 0, storm::exceptions::WrongFormatException,
151 "Top level element must be specified via parameter 'toplevel'.");
152 std::string topLevelId = parseValue(jsonInput.at(
"toplevel"));
153 STORM_LOG_THROW(nameMapping.find(topLevelId) != nameMapping.end(), storm::exceptions::WrongFormatException,
154 "Top level element with id '" << topLevelId <<
"' was not defined.");
158 STORM_LOG_THROW(
false, storm::exceptions::FileIoException,
"A parsing exception occurred in " << currentLocation <<
": " << exception.
what());
159 }
catch (std::exception
const& exception) {
160 STORM_LOG_THROW(
false, storm::exceptions::FileIoException,
"An exception occurred during parsing in " << currentLocation <<
": " << exception.what());
171template<
typename ValueType>
172std::string DFTJsonParser<ValueType>::parseName(std::string
const& name) {
173 std::string newName = name;
174 std::replace(newName.begin(), newName.end(),
' ',
'_');
175 std::replace(newName.begin(), newName.end(),
'-',
'_');
179template<
typename ValueType>
180std::string DFTJsonParser<ValueType>::parseValue(Json value) {
181 if (value.is_string()) {
182 return value.get<std::string>();
184 std::stringstream stream;
190template<
typename ValueType>
191void DFTJsonParser<ValueType>::parseBasicElement(std::string
const& name, std::string
const& type, Json input,
193 std::string distribution =
"exponential";
194 if (input.count(
"distribution") > 0) {
195 distribution = input.at(
"distribution");
197 if (distribution ==
"exp") {
198 distribution =
"exponential";
201 STORM_LOG_THROW(type ==
"be" || (type ==
"be_exp" && distribution ==
"exponential"), storm::exceptions::WrongFormatException,
202 "BE type '" << type <<
"' and distribution '" << distribution <<
" do not agree.");
204 if (distribution ==
"const") {
206 STORM_LOG_THROW(input.count(
"failed") > 0, storm::exceptions::WrongFormatException,
"Constant BE '" << name <<
"' requires parameter 'failed'.");
207 bool failed = input.at(
"failed");
209 }
else if (distribution ==
"probability") {
211 STORM_LOG_THROW(input.count(
"prob") > 0, storm::exceptions::WrongFormatException,
212 "BE '" << name <<
"' with probability distribution requires parameter 'prob'.");
214 ValueType dormancy = storm::utility::one<ValueType>();
215 if (input.count(
"dorm") > 0) {
216 dormancy = valueParser.
parseValue(parseValue(input.at(
"dorm")));
218 STORM_LOG_WARN(
"No dormancy factor was provided for basic element '" << name <<
"'. Assuming dormancy factor of 1.");
221 }
else if (distribution ==
"exponential") {
223 STORM_LOG_THROW(input.count(
"rate") > 0, storm::exceptions::WrongFormatException,
224 "BE '" << name <<
"' with exponential distribution requires parameter 'rate'.");
226 ValueType dormancy = storm::utility::one<ValueType>();
227 if (input.count(
"dorm") > 0) {
228 dormancy = valueParser.
parseValue(parseValue(input.at(
"dorm")));
230 STORM_LOG_WARN(
"No dormancy factor was provided for basic element '" << name <<
"'. Assuming dormancy factor of 1.");
232 bool transient =
false;
233 if (input.count(
"transient") > 0) {
234 transient = input.at(
"transient");
237 }
else if (distribution ==
"erlang") {
239 STORM_LOG_THROW(input.count(
"rate") > 0, storm::exceptions::WrongFormatException,
240 "BE '" << name <<
"' with Erlang distribution requires parameter 'rate'.");
242 STORM_LOG_THROW(input.count(
"phases") > 0, storm::exceptions::WrongFormatException,
243 "BE '" << name <<
"' with Erlang distribution requires parameter 'phases'.");
244 size_t phases = storm::parser::parseNumber<size_t>(parseValue(input.at(
"phases")));
245 ValueType dormancy = storm::utility::one<ValueType>();
246 if (input.count(
"dorm") > 0) {
247 dormancy = valueParser.
parseValue(parseValue(input.at(
"dorm")));
249 STORM_LOG_WARN(
"No dormancy factor was provided for basic element '" << name <<
"'. Assuming dormancy factor of 1.");
252 }
else if (distribution ==
"weibull") {
254 STORM_LOG_THROW(input.count(
"shape") > 0, storm::exceptions::WrongFormatException,
255 "BE '" << name <<
"' with Weibull distribution requires parameter 'shape'.");
257 STORM_LOG_THROW(input.count(
"rate") > 0, storm::exceptions::WrongFormatException,
258 "BE '" << name <<
"' with Weibull distribution requires parameter 'rate'.");
261 }
else if (distribution ==
"lognormal") {
263 STORM_LOG_THROW(input.count(
"mean") > 0, storm::exceptions::WrongFormatException,
264 "BE '" << name <<
"' with Log-normal distribution requires parameter 'mean'.");
266 STORM_LOG_THROW(input.count(
"stddev") > 0, storm::exceptions::WrongFormatException,
267 "BE '" << name <<
"' with Log-normal distribution requires parameter 'stddev'.");
271 STORM_LOG_THROW(
false, storm::exceptions::WrongFormatException,
"Distribution " << distribution <<
" not known.");
276template class DFTJsonParser<double>;
277template class DFTJsonParser<RationalFunction>;
void addPdep(std::string const &name, std::vector< std::string > const &children, ValueType probability)
Create (probabilistic) dependency (PDEP) and add it to DFT.
void addOrGate(std::string const &name, std::vector< std::string > const &children)
Create OR-gate and add it to DFT.
void addVotingGate(std::string const &name, unsigned threshold, std::vector< std::string > const &children)
Create VOTing-gate and add it to DFT.
void addBasicElementErlang(std::string const &name, ValueType rate, unsigned phases, ValueType dormancyFactor)
Create BE with Erlang distribution and add it to DFT.
void addLayoutInfo(std::string const &name, double x, double y)
Add layout information for DFT element.
void addSpareGate(std::string const &name, std::vector< std::string > const &children)
Create SPARE-gate and add it to DFT.
void addBasicElementConst(std::string const &name, bool failed)
Create BE which is constant failed or constant failsafe and add it to DFT.
storm::dft::storage::DFT< ValueType > build()
Create DFT.
void addAndGate(std::string const &name, std::vector< std::string > const &children)
Create AND-gate and add it to DFT.
void addBasicElementProbability(std::string const &name, ValueType probability, ValueType dormancyFactor)
Create BE with constant (Bernoulli) distribution and add it to DFT.
void setTopLevel(std::string const &tle)
Set top level element.
void addBasicElementExponential(std::string const &name, ValueType rate, ValueType dormancyFactor, bool transient=false)
Create BE with exponential distribution and add it to DFT.
void addPorGate(std::string const &name, std::vector< std::string > const &children, bool inclusive=true)
Create POR-gate and add it to DFT.
void addSequenceEnforcer(std::string const &name, std::vector< std::string > const &children)
Create sequence enforcer (SEQ) and add it to DFT.
void addPandGate(std::string const &name, std::vector< std::string > const &children, bool inclusive=true)
Create PAND-gate and add it to DFT.
void addBasicElementWeibull(std::string const &name, ValueType shape, ValueType rate)
Create BE with Weibull distribution and add it to DFT.
void addBasicElementLogNormal(std::string const &name, ValueType mean, ValueType standardDeviation)
Create BE with log-normal distribution and add it to DFT.
void addMutex(std::string const &name, std::vector< std::string > const &children)
Create mutual exclusion-gate (MUTEX) and add it to DFT.
Parser for DFT in custom JSON format.
static storm::dft::storage::DFT< ValueType > parseJsonFromFile(std::string const &filename)
Parse DFT from JSON format given as file and build DFT.
static storm::dft::storage::DFT< ValueType > parseJsonFromString(std::string const &jsonString)
Parse DFT from JSON format given as a string and build DFT.
Represents a Dynamic Fault Tree.
std::string getRelevantEventsString() const
Get a string containing the list of all relevant events.
void setRelevantEvents(storm::dft::utility::RelevantEvents const &relevantEvents, bool const allowDCForRelevant) const
Set the relevance flag for all elements according to the given relevant events.
void insert(std::string const &name)
Add relevant event.
This class represents the base class of all exception classes.
virtual const char * what() const NOEXCEPT override
Retrieves the message associated with this exception.
Parser for values according to their ValueType.
void addParameter(std::string const ¶meter)
Add declaration of parameter.
ValueType parseValue(std::string const &value) const
Parse ValueType from string.
#define STORM_LOG_WARN(message)
#define STORM_LOG_DEBUG(message)
#define STORM_LOG_TRACE(message)
#define STORM_LOG_THROW(cond, exception, message)
SFTBDDChecker::ValueType ValueType
void closeFile(std::ofstream &stream)
Close the given file after writing.
void openFile(std::string const &filepath, std::ofstream &filestream, bool append=false, bool silent=false)
Open the given file for writing.