Storm
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
storm-dft.cpp
Go to the documentation of this file.
15
19template<typename ValueType>
26
27 // Build DFT from given file
28 std::shared_ptr<storm::dft::storage::DFT<ValueType>> dft;
29 if (dftIOSettings.isDftFileSet()) {
30 STORM_LOG_DEBUG("Loading DFT from Galileo file " << dftIOSettings.getDftFilename());
31 dft = storm::dft::api::loadDFTGalileoFile<ValueType>(dftIOSettings.getDftFilename());
32 } else if (dftIOSettings.isDftJsonFileSet()) {
33 STORM_LOG_DEBUG("Loading DFT from Json file " << dftIOSettings.getDftJsonFilename());
34 dft = storm::dft::api::loadDFTJsonFile<ValueType>(dftIOSettings.getDftJsonFilename());
35 } else {
36 STORM_LOG_THROW(false, storm::exceptions::InvalidSettingsException, "No input model given.");
37 }
38
39 // Show statistics about DFT (number of gates, etc.)
40 if (dftIOSettings.isShowDftStatisticsSet()) {
41 dft->writeStatsToStream(std::cout);
42 std::cout << '\n';
43 }
44
45 // Export to json
46 if (dftIOSettings.isExportToJson()) {
47 storm::dft::api::exportDFTToJsonFile<ValueType>(*dft, dftIOSettings.getExportJsonFilename());
48 }
49
50 // Check well-formedness of DFT
51 auto wellFormedResult = storm::dft::api::isWellFormed(*dft, false);
52 STORM_LOG_THROW(wellFormedResult.first, storm::exceptions::UnmetRequirementException, "DFT is not well-formed: " << wellFormedResult.second);
53 // Warn about potential modeling issues
54 auto modelingIssues = storm::dft::api::hasPotentialModelingIssues(*dft);
55 STORM_LOG_WARN_COND(!modelingIssues.first, modelingIssues.second);
56
57 // Transformation to GSPN
58 if (dftGspnSettings.isTransformToGspn()) {
59 std::pair<std::shared_ptr<storm::gspn::GSPN>, uint64_t> pair = storm::dft::api::transformToGSPN(*dft);
60 std::shared_ptr<storm::gspn::GSPN> gspn = pair.first;
61 uint64_t toplevelFailedPlace = pair.second;
62
63 // Export
65
66 // Transform to Jani
67 // TODO analyse Jani model
68 std::shared_ptr<storm::jani::Model> model = storm::dft::api::transformToJani(*gspn, toplevelFailedPlace);
69 return;
70 }
71
72 // Export to SMT
73 if (dftIOSettings.isExportToSmt()) {
74 storm::dft::api::exportDFTToSMT<ValueType>(*dft, dftIOSettings.getExportSmtFilename());
75 return;
76 }
77
78 bool useSMT = false;
79 uint64_t solverTimeout = 10;
80#ifdef STORM_HAVE_Z3
81 if (faultTreeSettings.solveWithSMT()) {
82 useSMT = true;
83 STORM_LOG_DEBUG("Use SMT for preprocessing");
84 }
85#endif
86
87 // Apply transformations
88 // TODO transform later before actual analysis
89 dft = storm::dft::api::applyTransformations(*dft, faultTreeSettings.isUniqueFailedBE(), true, false);
90 STORM_LOG_DEBUG(dft->getElementsString());
91
92 // Compute minimal number of BE failures leading to system failure and
93 // maximal number of BE failures not leading to system failure yet.
94 // TODO: always needed?
95 auto bounds = storm::dft::api::computeBEFailureBounds(*dft, useSMT, solverTimeout);
96 STORM_LOG_DEBUG("BE failure bounds: lower bound: " << bounds.first << ", upper bound: " << bounds.second << ".");
97
98#ifdef STORM_HAVE_Z3
99 if (useSMT) {
100 // Solve with SMT
101 STORM_LOG_DEBUG("Running DFT analysis with use of SMT.");
102 // Set dynamic behavior vector
104 }
105#endif
106
107 // BDD Analysis
108 if (dftIOSettings.isExportToBddDot() || dftIOSettings.isAnalyzeWithBdds() || dftIOSettings.isMinimalCutSets() || dftIOSettings.isImportanceMeasureSet()) {
109 bool const isImportanceMeasureSet{dftIOSettings.isImportanceMeasureSet()};
110 bool const isMinimalCutSets{dftIOSettings.isMinimalCutSets()};
111 bool const isMTTF{dftIOSettings.usePropExpectedTime()};
112 double const mttfPrecision{faultTreeSettings.getMttfPrecision()};
113 double const mttfStepsize{faultTreeSettings.getMttfStepsize()};
114 std::string const mttfAlgorithm{faultTreeSettings.getMttfAlgorithm()};
115 bool const isExportToBddDot{dftIOSettings.isExportToBddDot()};
116 bool const isTimebound{dftIOSettings.usePropTimebound()};
117 bool const isTimepoints{dftIOSettings.usePropTimepoints()};
118
119 bool const probabilityAnalysis{ioSettings.isPropertySet() || !isImportanceMeasureSet};
120 size_t const chunksize{faultTreeSettings.getChunksize()};
121 bool const isModularisation{faultTreeSettings.useModularisation()};
122
123 std::vector<double> timepoints{};
124 if (isTimepoints) {
125 timepoints = dftIOSettings.getPropTimepoints();
126 }
127 if (isTimebound) {
128 timepoints.push_back(dftIOSettings.getPropTimebound());
129 }
130
131 std::string filename{""};
132 if (isExportToBddDot) {
133 filename = dftIOSettings.getExportBddDotFilename();
134 }
135
136 // gather manually inputted properties
137 std::vector<std::shared_ptr<storm::logic::Formula const>> manuallyInputtedProperties;
138 if (ioSettings.isPropertySet()) {
139 manuallyInputtedProperties = storm::api::extractFormulasFromProperties(storm::api::parseProperties(ioSettings.getProperty()));
140 }
141
142 std::string importanceMeasureName{""};
143 if (isImportanceMeasureSet) {
144 importanceMeasureName = dftIOSettings.getImportanceMeasure();
145 }
146
147 // Set variable ordering
148 if (dftIOSettings.isVariableOrderingFileSet()) {
149 auto beOrder = storm::dft::parser::BEOrderParser<ValueType>::parseBEOrder(dftIOSettings.getVariableOrderingFilename(), *dft);
150 dft->setBEOrder(beOrder);
151 }
152
153 auto const additionalRelevantEventNames{faultTreeSettings.getRelevantEvents()};
154 storm::dft::api::analyzeDFTBdd<ValueType>(dft, isExportToBddDot, filename, isMTTF, mttfPrecision, mttfStepsize, mttfAlgorithm, isMinimalCutSets,
155 probabilityAnalysis, isModularisation, importanceMeasureName, timepoints, manuallyInputtedProperties,
156 additionalRelevantEventNames, chunksize);
157
158 // don't perform other analysis if analyzeWithBdds is set
159 if (dftIOSettings.isAnalyzeWithBdds()) {
160 return;
161 }
162 }
163
164 // From now on we analyse the DFT via model checking
165
166 // Set min or max
167 std::string optimizationDirection = "min";
168 if (dftIOSettings.isComputeMaximalValue()) {
169 optimizationDirection = "max";
170 }
171
172 // Construct properties to analyse.
173 // We allow multiple properties to be checked at once.
174 std::vector<std::string> properties;
175 if (ioSettings.isPropertySet()) {
176 properties.push_back(ioSettings.getProperty());
177 }
178 if (dftIOSettings.usePropExpectedTime()) {
179 properties.push_back("T" + optimizationDirection + "=? [F \"failed\"]");
180 }
181 if (dftIOSettings.usePropProbability()) {
182 properties.push_back("P" + optimizationDirection + "=? [F \"failed\"]");
183 }
184 if (dftIOSettings.usePropTimebound()) {
185 std::stringstream stream;
186 stream << "P" << optimizationDirection << "=? [F<=" << dftIOSettings.getPropTimebound() << " \"failed\"]";
187 properties.push_back(stream.str());
188 }
189 if (dftIOSettings.usePropTimepoints()) {
190 for (double timepoint : dftIOSettings.getPropTimepoints()) {
191 std::stringstream stream;
192 stream << "P" << optimizationDirection << "=? [F<=" << timepoint << " \"failed\"]";
193 properties.push_back(stream.str());
194 }
195 }
196
197 // Build properties
198 std::vector<std::shared_ptr<storm::logic::Formula const>> props;
199 if (!properties.empty()) {
200 std::string propString;
201 for (size_t i = 0; i < properties.size(); ++i) {
202 propString += properties[i];
203 if (i + 1 < properties.size()) {
204 propString += ";";
205 }
206 }
208 }
209
210 // Set relevant event names
211 std::vector<std::string> additionalRelevantEventNames;
212 if (faultTreeSettings.areRelevantEventsSet()) {
213 // Possible clash of relevantEvents and disableDC was already considered in FaultTreeSettings::check().
214 additionalRelevantEventNames = faultTreeSettings.getRelevantEvents();
215 } else if (faultTreeSettings.isDisableDC()) {
216 // All events are relevant
217 additionalRelevantEventNames = {"all"};
218 }
219 storm::dft::utility::RelevantEvents relevantEvents = storm::dft::api::computeRelevantEvents(props, additionalRelevantEventNames);
220
221 // Analyze DFT by translation to CTMC/MA
222 dft = storm::dft::api::prepareForMarkovAnalysis<ValueType>(*dft);
223 STORM_LOG_DEBUG("DFT after preparation for Markov analysis:\n" << dft->getElementsString());
224
225 // Check which FDEPs actually introduce conflicts which need non-deterministic resolution
226 bool hasConflicts = storm::dft::api::computeDependencyConflicts(*dft, useSMT, solverTimeout);
227 if (hasConflicts) {
228 STORM_LOG_DEBUG("FDEP conflicts found.");
229 } else {
230 STORM_LOG_DEBUG("No FDEP conflicts found.");
231 }
232
233 // TODO allow building of state space even without properties
234 if (props.empty()) {
235 STORM_LOG_WARN("No property given. No analysis will be performed.");
236 } else {
237 double approximationError = 0.0;
238 if (faultTreeSettings.isApproximationErrorSet()) {
239 approximationError = faultTreeSettings.getApproximationError();
240 }
241 storm::dft::api::analyzeDFT<ValueType>(*dft, props, faultTreeSettings.useSymmetryReduction(), faultTreeSettings.useModularisation(), relevantEvents,
242 faultTreeSettings.isAllowDCForRelevantEvents(), approximationError,
243 faultTreeSettings.getApproximationHeuristic(), transformationSettings.isChainEliminationSet(),
244 transformationSettings.getLabelBehavior(), true);
245 }
246}
247
248void process() {
250 if (generalSettings.isParametricSet()) {
251 processOptions<storm::RationalFunction>();
252 } else if (generalSettings.isExactSet()) {
253 STORM_LOG_WARN("Exact solving over rational numbers is not implemented. Performing exact solving using rational functions instead.");
254 processOptions<storm::RationalFunction>();
255 } else {
256 processOptions<double>();
257 }
258}
259
267int main(const int argc, const char** argv) {
268 try {
269 return storm::cli::process("Storm-dft", "storm-dft", storm::dft::settings::initializeDftSettings, process, argc, argv);
270 } catch (storm::exceptions::BaseException const& exception) {
271 STORM_LOG_ERROR("An exception caused Storm-DFT to terminate. The message of the exception is: " << exception.what());
272 return 1;
273 } catch (std::exception const& exception) {
274 STORM_LOG_ERROR("An unexpected exception occurred and caused Storm-DFT to terminate. The message of this exception is: " << exception.what());
275 return 2;
276 }
277}
static std::vector< size_t > parseBEOrder(std::string const &filename, storm::dft::storage::DFT< ValueType > const &dft)
Parse BE order from given file.
This class represents the base class of all exception classes.
virtual const char * what() const NOEXCEPT override
Retrieves the message associated with this exception.
This class represents the general settings.
bool isExactSet() const
Retrieves whether the option enabling exact model checking is set and we should use infinite precisio...
bool isParametricSet() const
Retrieves whether the option enabling parametric model checking is set.
#define STORM_LOG_WARN(message)
Definition logging.h:30
#define STORM_LOG_DEBUG(message)
Definition logging.h:23
#define STORM_LOG_ERROR(message)
Definition logging.h:31
#define STORM_LOG_WARN_COND(cond, message)
Definition macros.h:38
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
std::vector< storm::jani::Property > parseProperties(storm::parser::FormulaParser &formulaParser, std::string const &inputString, boost::optional< std::set< std::string > > const &propertyFilter)
void handleGSPNExportSettings(storm::gspn::GSPN const &gspn, std::function< std::vector< storm::jani::Property >(storm::builder::JaniGSPNBuilder const &)> const &janiProperyGetter)
std::vector< std::shared_ptr< storm::logic::Formula const > > extractFormulasFromProperties(std::vector< storm::jani::Property > const &properties)
int process(std::string const &name, std::string const &executableName, std::function< void(std::string const &, std::string const &)> initSettingsFunc, std::function< void(void)> processOptionsFunc, const int argc, const char **argv)
Processes the options and returns the exit code.
Definition cli.cpp:81
std::pair< uint64_t, uint64_t > computeBEFailureBounds(storm::dft::storage::DFT< ValueType > const &dft, bool useSMT, double solverTimeout)
Definition storm-dft.h:125
std::shared_ptr< storm::jani::Model > transformToJani(storm::gspn::GSPN const &gspn, uint64_t toplevelFailedPlace)
Transform GSPN to Jani model.
std::pair< bool, std::string > isWellFormed(storm::dft::storage::DFT< ValueType > const &dft, bool validForMarkovianAnalysis=true)
Check whether the DFT is well-formed.
Definition storm-dft.h:64
std::pair< std::shared_ptr< storm::gspn::GSPN >, uint64_t > transformToGSPN(storm::dft::storage::DFT< double > const &dft)
storm::dft::utility::RelevantEvents computeRelevantEvents(std::vector< std::shared_ptr< storm::logic::Formula const > > const &properties, std::vector< std::string > const &additionalRelevantEventNames)
Get relevant event ids from given relevant event names and labels in properties.
std::pair< bool, std::string > hasPotentialModelingIssues(storm::dft::storage::DFT< ValueType > const &dft)
Check whether the DFT has potential modeling issues.
Definition storm-dft.h:82
void analyzeDFTSMT(storm::dft::storage::DFT< double > const &dft, bool printOutput)
std::shared_ptr< storm::dft::storage::DFT< ValueType > > applyTransformations(storm::dft::storage::DFT< ValueType > const &dft, bool uniqueBE, bool binaryFDEP, bool exponentialDistributions)
Apply transformations for DFT.
Definition storm-dft.h:98
bool computeDependencyConflicts(storm::dft::storage::DFT< ValueType > &dft, bool useSMT, double solverTimeout)
Definition storm-dft.h:132
void initializeDftSettings(std::string const &name, std::string const &executableName)
SettingsType const & getModule()
Get module.
void processOptions()
Process commandline options and start computations.
Definition storm-dft.cpp:20
void process()
int main(const int argc, const char **argv)
Entry point for Storm-DFT.