Storm 1.11.1.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
FailureBoundFinder.cpp
Go to the documentation of this file.
2
3namespace storm::dft {
4namespace utility {
5
6uint64_t FailureBoundFinder::correctLowerBound(std::shared_ptr<storm::dft::modelchecker::DFTASFChecker> smtchecker, uint64_t bound, uint_fast64_t timeout) {
7 STORM_LOG_DEBUG("Lower bound correction - try to correct bound " << std::to_string(bound));
8 uint64_t boundCandidate = bound;
9 uint64_t nrDepEvents = 0;
10 uint64_t nrNonMarkovian = 0;
11 auto dft = smtchecker->getDFT();
12
13 // Count dependent events
14 for (size_t i = 0; i < dft.nrElements(); ++i) {
15 std::shared_ptr<storm::dft::storage::elements::DFTElement<double> const> element = dft.getElement(i);
16 if (element->isBasicElement()) {
17 auto be = std::static_pointer_cast<storm::dft::storage::elements::DFTBE<double> const>(element);
18 if (be->hasIngoingDependencies()) {
19 ++nrDepEvents;
20 }
21 }
22 }
23
24 // Only need to check as long as bound candidate + nr of non-Markovians to check is smaller than number of dependent events
25 // Check boundCandidate == 0 is later performed in the switch case
26 while (nrNonMarkovian <= nrDepEvents) {
27 if (nrNonMarkovian == 0 and boundCandidate == 0) {
28 nrNonMarkovian = 1;
29 }
30 STORM_LOG_TRACE("Lower bound correction - check possible bound " << std::to_string(boundCandidate) << " with " << std::to_string(nrNonMarkovian)
31 << " non-Markovian states");
32 // The uniqueness transformation for constantly failed BEs guarantees that a DFT never fails
33 // in step 0 without intermediate non-Markovians, thus forcibly set nrNonMarkovian
34 smtchecker->setSolverTimeout(timeout * 1000);
35 storm::solver::SmtSolver::CheckResult tmp_res = smtchecker->checkFailsLeqWithEqNonMarkovianState(boundCandidate + nrNonMarkovian, nrNonMarkovian);
36 smtchecker->unsetSolverTimeout();
37 switch (tmp_res) {
39 /* If SAT, there is a sequence where only boundCandidate-many BEs fail directly and rest is nonMarkovian.
40 * Bound candidate is vaild, therefore check the next one */
41 STORM_LOG_TRACE("Lower bound correction - SAT");
42 // Prevent integer underflow
43 if (boundCandidate == 0) {
44 STORM_LOG_DEBUG("Lower bound correction - corrected bound to 0");
45 return 0;
46 }
47 --boundCandidate;
48 break;
50 // If any query returns unknown, we cannot be sure about the bound and fall back to the naive one
51 STORM_LOG_DEBUG("Lower bound correction - Solver returned 'Unknown', corrected to 1");
52 return 1;
53 default:
54 // if query is UNSAT, increase number of non-Markovian states and try again
55 STORM_LOG_TRACE("Lower bound correction - UNSAT");
56 ++nrNonMarkovian;
57 break;
58 }
59 }
60 // if for one candidate all queries are UNSAT, it is not valid. Return last valid candidate
61 STORM_LOG_DEBUG("Lower bound correction - corrected bound to " << std::to_string(boundCandidate + 1));
62 return boundCandidate + 1;
63}
64
65uint64_t FailureBoundFinder::correctUpperBound(std::shared_ptr<storm::dft::modelchecker::DFTASFChecker> smtchecker, uint64_t bound, uint_fast64_t timeout) {
66 STORM_LOG_DEBUG("Upper bound correction - try to correct bound " << std::to_string(bound));
67 uint64_t boundCandidate = bound;
68 uint64_t nrNonMarkovian = 0;
69 uint64_t currentTimepoint = 0;
70 auto dft = smtchecker->getDFT();
71
72 while (boundCandidate > 0) {
73 currentTimepoint = bound + 1;
74 while (currentTimepoint - boundCandidate > 0) {
75 --currentTimepoint;
76 nrNonMarkovian = currentTimepoint - boundCandidate;
77 STORM_LOG_TRACE("Upper bound correction - candidate " << std::to_string(boundCandidate) << " check split " << std::to_string(currentTimepoint)
78 << "|" << std::to_string(nrNonMarkovian));
79 smtchecker->setSolverTimeout(timeout * 1000);
80 storm::solver::SmtSolver::CheckResult tmp_res = smtchecker->checkFailsAtTimepointWithEqNonMarkovianState(currentTimepoint, nrNonMarkovian);
81 smtchecker->unsetSolverTimeout();
82 switch (tmp_res) {
84 STORM_LOG_TRACE("Upper bound correction - SAT");
85 STORM_LOG_DEBUG("Upper bound correction - corrected to bound " << boundCandidate << " (TLE can fail at sequence point "
86 << std::to_string(currentTimepoint) << " with "
87 << std::to_string(nrNonMarkovian) << " non-Markovian states)");
88 return boundCandidate;
90 // If any query returns unknown, we cannot be sure about the bound and fall back to the naive one
91 STORM_LOG_DEBUG("Upper bound correction - Solver returned 'Unknown', corrected to bound " << bound);
92 return bound;
93 default:
94 // if query is UNSAT, increase number of non-Markovian states and try again
95 STORM_LOG_TRACE("Lower bound correction - UNSAT");
96 break;
97 }
98 }
99 --boundCandidate;
100 }
101
102 // if for one candidate all queries are UNSAT, it is not valid. Return last valid candidate
103 STORM_LOG_DEBUG("Upper bound correction - corrected bound to " << std::to_string(boundCandidate));
104 return boundCandidate;
105}
106
107uint64_t FailureBoundFinder::getLeastFailureBound(storm::dft::storage::DFT<double> const &dft, bool useSMT, uint_fast64_t timeout) {
108 if (useSMT) {
109 STORM_LOG_TRACE("Compute lower bound for number of BE failures necessary for the DFT to fail");
110
112 smtchecker.toSolver();
113
114 uint64_t bound = 0;
115 while (bound < dft.nrBasicElements() + 1) {
116 smtchecker.setSolverTimeout(timeout * 1000);
118 smtchecker.unsetSolverTimeout();
119 switch (tmp_res) {
121 if (!dft.getDependencies().empty()) {
122 return correctLowerBound(std::make_shared<storm::dft::modelchecker::DFTASFChecker>(smtchecker), bound, timeout);
123 } else {
124 return bound;
125 }
127 STORM_LOG_DEBUG("Lower bound: Solver returned 'Unknown'");
128 return bound;
129 default:
130 ++bound;
131 break;
132 }
133 }
134
135 return bound;
136 } else {
137 // naive bound
138 return 1;
139 }
140}
141
142uint64_t FailureBoundFinder::getLeastFailureBound(storm::dft::storage::DFT<RationalFunction> const &dft, bool useSMT, uint_fast64_t timeout) {
143 if (useSMT) {
144 STORM_LOG_WARN("SMT encoding does not support rational functions");
145 }
146 return 1;
147}
148
149uint64_t FailureBoundFinder::getAlwaysFailedBound(storm::dft::storage::DFT<double> const &dft, bool useSMT, uint_fast64_t timeout) {
150 STORM_LOG_TRACE("Compute bound for number of BE failures such that the DFT always fails");
151 if (useSMT) {
153 smtchecker.toSolver();
154
156 return dft.nrBasicElements() + 1;
157 }
158 uint64_t bound = dft.nrBasicElements();
159 while (bound > 0) {
160 smtchecker.setSolverTimeout(timeout * 1000);
162 smtchecker.unsetSolverTimeout();
163 switch (tmp_res) {
165 if (!dft.getDependencies().empty()) {
166 return correctUpperBound(std::make_shared<storm::dft::modelchecker::DFTASFChecker>(smtchecker), bound, timeout);
167 } else {
168 return bound;
169 }
171 STORM_LOG_DEBUG("Upper bound: Solver returned 'Unknown'");
172 return bound;
173 default:
174 --bound;
175 break;
176 }
177 }
178 return bound;
179 } else {
180 // naive bound
181 return dft.nrBasicElements() + 1;
182 }
183}
184
185uint64_t FailureBoundFinder::getAlwaysFailedBound(storm::dft::storage::DFT<RationalFunction> const &dft, bool useSMT, uint_fast64_t timeout) {
186 if (useSMT) {
187 STORM_LOG_WARN("SMT encoding does not support rational functions");
188 }
189 return dft.nrBasicElements() + 1;
190}
191
193
194} // namespace utility
195} // namespace storm::dft
storm::solver::SmtSolver::CheckResult checkTleFailsWithLeq(uint64_t bound)
Check if there exists a sequence of BE failures of at least given length such that the TLE of the DFT...
void setSolverTimeout(uint_fast64_t milliseconds)
Set the timeout of the solver.
void toSolver()
Generates a new solver instance and prepares it for SMT checking of the DFT.
void unsetSolverTimeout()
Unset the timeout for the solver.
storm::solver::SmtSolver::CheckResult checkTleNeverFailed()
Check if the TLE of the DFT never fails.
storm::solver::SmtSolver::CheckResult checkTleFailsWithEq(uint64_t bound)
Check if there exists a sequence of BE failures of exactly given length such that the TLE of the DFT ...
Represents a Dynamic Fault Tree.
Definition DFT.h:52
size_t nrBasicElements() const
Definition DFT.h:99
std::vector< size_t > const & getDependencies() const
Definition DFT.h:154
static uint64_t getLeastFailureBound(storm::dft::storage::DFT< double > const &dft, bool useSMT=false, uint_fast64_t timeout=10)
Get the minimal number of BEs necessary for the TLE to fail (lower bound for number of failures to ch...
static uint64_t getAlwaysFailedBound(storm::dft::storage::DFT< double > const &dft, bool useSMT=false, uint_fast64_t timeout=10)
Get the number of BE failures for which the TLE always fails (upper bound for number of failures to c...
CheckResult
possible check results
Definition SmtSolver.h:25
#define STORM_LOG_WARN(message)
Definition logging.h:25
#define STORM_LOG_DEBUG(message)
Definition logging.h:18
#define STORM_LOG_TRACE(message)
Definition logging.h:12