Storm 1.11.1.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
BoundedUntilFormula.cpp
Go to the documentation of this file.
2
3#include <boost/any.hpp>
4#include <ostream>
5
13
14namespace storm {
15namespace logic {
16BoundedUntilFormula::BoundedUntilFormula(std::shared_ptr<Formula const> const& leftSubformula, std::shared_ptr<Formula const> const& rightSubformula,
17 boost::optional<TimeBound> const& lowerBound, boost::optional<TimeBound> const& upperBound,
18 TimeBoundReference const& timeBoundReference)
19 : PathFormula(),
20 leftSubformula({leftSubformula}),
21 rightSubformula({rightSubformula}),
22 timeBoundReference({timeBoundReference}),
23 lowerBound({lowerBound}),
24 upperBound({upperBound}) {
25 STORM_LOG_THROW(lowerBound || upperBound, storm::exceptions::InvalidArgumentException, "Bounded until formula requires at least one bound.");
26}
27
28BoundedUntilFormula::BoundedUntilFormula(std::shared_ptr<Formula const> const& leftSubformula, std::shared_ptr<Formula const> const& rightSubformula,
29 std::vector<boost::optional<TimeBound>> const& lowerBounds, std::vector<boost::optional<TimeBound>> const& upperBounds,
30 std::vector<TimeBoundReference> const& timeBoundReferences)
31 : PathFormula(),
32 leftSubformula({leftSubformula}),
33 rightSubformula({rightSubformula}),
34 timeBoundReference(timeBoundReferences),
35 lowerBound(lowerBounds),
36 upperBound(upperBounds) {
37 assert(timeBoundReferences.size() == upperBound.size());
38 assert(timeBoundReferences.size() == lowerBound.size());
39}
40
41BoundedUntilFormula::BoundedUntilFormula(std::vector<std::shared_ptr<Formula const>> const& leftSubformulas,
42 std::vector<std::shared_ptr<Formula const>> const& rightSubformulas,
43 std::vector<boost::optional<TimeBound>> const& lowerBounds, std::vector<boost::optional<TimeBound>> const& upperBounds,
44 std::vector<TimeBoundReference> const& timeBoundReferences)
45 : PathFormula(),
46 leftSubformula(leftSubformulas),
47 rightSubformula(rightSubformulas),
48 timeBoundReference(timeBoundReferences),
49 lowerBound(lowerBounds),
50 upperBound(upperBounds) {
51 assert(leftSubformula.size() == rightSubformula.size());
52 assert(rightSubformula.size() == timeBoundReference.size());
53 assert(timeBoundReference.size() == lowerBound.size());
54 assert(lowerBound.size() == upperBound.size());
55 STORM_LOG_THROW(this->getDimension() != 0, storm::exceptions::InvalidArgumentException, "Bounded until formula requires at least one dimension.");
56 for (unsigned i = 0; i < timeBoundReferences.size(); ++i) {
57 STORM_LOG_THROW(hasLowerBound(i) || hasUpperBound(i), storm::exceptions::InvalidArgumentException,
58 "Bounded until formula requires at least one bound in each dimension.");
59 }
60}
61
63 return true;
64}
65
67 return true;
68}
69
70boost::any BoundedUntilFormula::accept(FormulaVisitor const& visitor, boost::any const& data) const {
71 return visitor.visit(*this, data);
72}
73
74void BoundedUntilFormula::gatherAtomicExpressionFormulas(std::vector<std::shared_ptr<AtomicExpressionFormula const>>& atomicExpressionFormulas) const {
76 for (unsigned i = 0; i < this->getDimension(); ++i) {
77 this->getLeftSubformula(i).gatherAtomicExpressionFormulas(atomicExpressionFormulas);
78 this->getRightSubformula(i).gatherAtomicExpressionFormulas(atomicExpressionFormulas);
79 }
80 } else {
81 this->getLeftSubformula().gatherAtomicExpressionFormulas(atomicExpressionFormulas);
82 this->getRightSubformula().gatherAtomicExpressionFormulas(atomicExpressionFormulas);
83 }
84}
85
86void BoundedUntilFormula::gatherAtomicLabelFormulas(std::vector<std::shared_ptr<AtomicLabelFormula const>>& atomicLabelFormulas) const {
88 for (unsigned i = 0; i < this->getDimension(); ++i) {
89 this->getLeftSubformula(i).gatherAtomicLabelFormulas(atomicLabelFormulas);
90 this->getRightSubformula(i).gatherAtomicLabelFormulas(atomicLabelFormulas);
91 }
92 } else {
93 this->getLeftSubformula().gatherAtomicLabelFormulas(atomicLabelFormulas);
94 this->getRightSubformula().gatherAtomicLabelFormulas(atomicLabelFormulas);
95 }
96}
97
98void BoundedUntilFormula::gatherReferencedRewardModels(std::set<std::string>& referencedRewardModels) const {
99 for (unsigned i = 0; i < this->getDimension(); ++i) {
100 if (this->getTimeBoundReference(i).isRewardBound()) {
102 referencedRewardModels.insert("");
103 } else {
104 referencedRewardModels.insert(this->getTimeBoundReference(i).getRewardName());
105 }
106 }
107 }
109 for (unsigned i = 0; i < this->getDimension(); ++i) {
110 this->getLeftSubformula(i).gatherReferencedRewardModels(referencedRewardModels);
111 this->getRightSubformula(i).gatherReferencedRewardModels(referencedRewardModels);
112 }
113 } else {
114 this->getLeftSubformula().gatherReferencedRewardModels(referencedRewardModels);
115 this->getRightSubformula().gatherReferencedRewardModels(referencedRewardModels);
116 }
117}
118
119void BoundedUntilFormula::gatherUsedVariables(std::set<storm::expressions::Variable>& usedVariables) const {
121 for (unsigned i = 0; i < this->getDimension(); ++i) {
122 this->getLeftSubformula(i).gatherUsedVariables(usedVariables);
123 this->getRightSubformula(i).gatherUsedVariables(usedVariables);
124 if (this->hasLowerBound(i)) {
125 this->getLowerBound(i).gatherVariables(usedVariables);
126 }
127 if (this->hasUpperBound(i)) {
128 this->getUpperBound(i).gatherVariables(usedVariables);
129 }
130 }
131 } else {
132 this->getLeftSubformula().gatherUsedVariables(usedVariables);
133 this->getRightSubformula().gatherUsedVariables(usedVariables);
134 if (this->hasLowerBound(0)) {
135 this->getLowerBound().gatherVariables(usedVariables);
136 }
137 if (this->hasUpperBound(0)) {
138 this->getUpperBound().gatherVariables(usedVariables);
139 }
140 }
141}
142
144 return false;
145}
146
148 return true;
149}
150
152 assert(timeBoundReference.size() != 0);
153 return timeBoundReference.size() > 1;
154}
155
157 assert(leftSubformula.size() != 0);
158 assert(leftSubformula.size() == rightSubformula.size());
159 return leftSubformula.size() > 1;
160}
161
163 return timeBoundReference.size();
164}
165
167 STORM_LOG_ASSERT(leftSubformula.size() == 1, "The left subformula is not unique.");
168 return *leftSubformula.at(0);
169}
170
172 if (leftSubformula.size() == 1 && i < getDimension()) {
173 return getLeftSubformula();
174 } else {
175 return *leftSubformula.at(i);
176 }
177}
178
180 STORM_LOG_ASSERT(rightSubformula.size() == 1, "The right subformula is not unique.");
181 return *rightSubformula.at(0);
182}
183
185 if (rightSubformula.size() == 1 && i < getDimension()) {
186 return getRightSubformula();
187 } else {
188 return *rightSubformula.at(i);
189 }
190}
191
193 assert(i < timeBoundReference.size());
194 return timeBoundReference.at(i);
195}
196
198 assert(i < lowerBound.size());
199 if (!hasLowerBound(i)) {
200 return false;
201 }
202 return lowerBound.at(i).get().isStrict();
203}
204
206 for (auto const& lb : lowerBound) {
207 if (static_cast<bool>(lb)) {
208 return true;
209 }
210 }
211 return false;
212}
213
215 return static_cast<bool>(lowerBound.at(i));
216}
217
219 if (!hasLowerBound(i)) {
220 return true;
221 }
222 return lowerBound.at(i).get().getBound().hasIntegerType();
223}
224
226 return upperBound.at(i).get().isStrict();
227}
228
230 for (auto const& ub : upperBound) {
231 if (static_cast<bool>(ub)) {
232 return true;
233 }
234 }
235 return false;
236}
237
239 return static_cast<bool>(upperBound.at(i));
240}
241
243 return upperBound.at(i).get().getBound().hasIntegerType();
244}
245
247 return lowerBound.at(i).get().getBound();
248}
249
251 return upperBound.at(i).get().getBound();
252}
253
254template<>
255double BoundedUntilFormula::getLowerBound(unsigned i) const {
256 if (!hasLowerBound(i)) {
257 return 0.0;
258 }
259 checkNoVariablesInBound(this->getLowerBound());
260 double bound = this->getLowerBound(i).evaluateAsDouble();
261 STORM_LOG_THROW(bound >= 0, storm::exceptions::InvalidPropertyException, "Time-bound must not evaluate to negative number.");
262 return bound;
263}
264
265template<>
266double BoundedUntilFormula::getUpperBound(unsigned i) const {
267 checkNoVariablesInBound(this->getUpperBound());
268 double bound = this->getUpperBound(i).evaluateAsDouble();
269 STORM_LOG_THROW(bound >= 0, storm::exceptions::InvalidPropertyException, "Time-bound must not evaluate to negative number.");
270 return bound;
271}
272
273template<>
274storm::RationalNumber BoundedUntilFormula::getLowerBound(unsigned i) const {
275 if (!hasLowerBound(i)) {
276 return storm::utility::zero<storm::RationalNumber>();
277 }
278 checkNoVariablesInBound(this->getLowerBound(i));
279 storm::RationalNumber bound = this->getLowerBound(i).evaluateAsRational();
280 STORM_LOG_THROW(bound >= storm::utility::zero<storm::RationalNumber>(), storm::exceptions::InvalidPropertyException,
281 "Time-bound must not evaluate to negative number.");
282 return bound;
283}
284
285template<>
286storm::RationalNumber BoundedUntilFormula::getUpperBound(unsigned i) const {
287 checkNoVariablesInBound(this->getUpperBound(i));
288 storm::RationalNumber bound = this->getUpperBound(i).evaluateAsRational();
289 STORM_LOG_THROW(bound >= storm::utility::zero<storm::RationalNumber>(), storm::exceptions::InvalidPropertyException,
290 "Time-bound must not evaluate to negative number.");
291 return bound;
292}
293
294template<>
295uint64_t BoundedUntilFormula::getLowerBound(unsigned i) const {
296 if (!hasLowerBound(i)) {
297 return 0;
298 }
299 checkNoVariablesInBound(this->getLowerBound(i));
300 int_fast64_t bound = this->getLowerBound(i).evaluateAsInt();
301 STORM_LOG_THROW(bound >= 0, storm::exceptions::InvalidPropertyException, "Time-bound must not evaluate to negative number.");
302 return static_cast<uint64_t>(bound);
303}
304
305template<>
306uint64_t BoundedUntilFormula::getUpperBound(unsigned i) const {
307 checkNoVariablesInBound(this->getUpperBound(i));
308 int_fast64_t bound = this->getUpperBound(i).evaluateAsInt();
309 STORM_LOG_THROW(bound >= 0, storm::exceptions::InvalidPropertyException, "Time-bound must not evaluate to negative number.");
310 return static_cast<uint64_t>(bound);
311}
312
313template<>
315 double bound = getUpperBound<double>(i);
316 STORM_LOG_THROW(!isUpperBoundStrict(i) || bound > 0, storm::exceptions::InvalidPropertyException,
317 "Cannot retrieve non-strict bound from strict zero-bound.");
318 return bound;
319}
320
321template<>
323 int_fast64_t bound = getUpperBound<uint64_t>(i);
324 if (isUpperBoundStrict(i)) {
325 STORM_LOG_THROW(bound > 0, storm::exceptions::InvalidPropertyException, "Cannot retrieve non-strict bound from strict zero-bound.");
326 return bound - 1;
327 } else {
328 return bound;
329 }
330}
331
332template<>
334 double bound = getLowerBound<double>(i);
335 STORM_LOG_THROW(!isLowerBoundStrict(i), storm::exceptions::InvalidPropertyException, "Cannot retrieve non-strict lower bound from strict lower-bound.");
336 return bound;
337}
338
339template<>
341 int_fast64_t bound = getLowerBound<uint64_t>(i);
342 if (isLowerBoundStrict(i)) {
343 return bound + 1;
344 } else {
345 return bound;
346 }
347}
348
349void BoundedUntilFormula::checkNoVariablesInBound(storm::expressions::Expression const& bound) {
350 STORM_LOG_THROW(!bound.containsVariables(), storm::exceptions::InvalidOperationException,
351 "Cannot evaluate time-bound '" << bound << "' as it contains undefined constants.");
352}
353
354std::shared_ptr<BoundedUntilFormula const> BoundedUntilFormula::restrictToDimension(unsigned i) const {
355 return std::make_shared<BoundedUntilFormula const>(getLeftSubformula(i).asSharedPointer(), getRightSubformula(i).asSharedPointer(), lowerBound.at(i),
356 upperBound.at(i), getTimeBoundReference(i));
357}
358
359std::ostream& BoundedUntilFormula::writeToStream(std::ostream& out, bool allowParentheses) const {
361 out << "multi(";
362 restrictToDimension(0)->writeToStream(out);
363 for (unsigned i = 1; i < this->getDimension(); ++i) {
364 out << ", ";
365 restrictToDimension(i)->writeToStream(out);
366 }
367 out << ")";
368 } else {
369 if (allowParentheses) {
370 out << "(";
371 }
372 this->getLeftSubformula().writeToStream(out, true);
373
374 out << " U";
375 if (this->isMultiDimensional()) {
376 out << "^{";
377 }
378 for (unsigned i = 0; i < this->getDimension(); ++i) {
379 if (i > 0) {
380 out << ", ";
381 }
382 if (this->getTimeBoundReference(i).isRewardBound()) {
383 out << "rew";
385 out << "[" << this->getTimeBoundReference(i).getRewardAccumulation() << "]";
386 }
387 if (this->getTimeBoundReference(i).hasRewardModelName()) {
388 out << "{\"" << this->getTimeBoundReference(i).getRewardName() << "\"}";
389 }
390 } else if (this->getTimeBoundReference(i).isStepBound()) {
391 out << "steps";
392 //} else if (this->getTimeBoundReference(i).isStepBound())
393 // Note: the 'time' keyword is optional.
394 // out << "time";
395 }
396 if (this->hasLowerBound(i)) {
397 if (this->hasUpperBound(i)) {
398 if (this->isLowerBoundStrict(i)) {
399 out << "(";
400 } else {
401 out << "[";
402 }
403 out << this->getLowerBound(i);
404 out << ", ";
405 out << this->getUpperBound(i);
406 if (this->isUpperBoundStrict(i)) {
407 out << ")";
408 } else {
409 out << "]";
410 }
411 } else {
412 if (this->isLowerBoundStrict(i)) {
413 out << ">";
414 } else {
415 out << ">=";
416 }
417 out << getLowerBound(i);
418 }
419 } else {
420 if (this->isUpperBoundStrict(i)) {
421 out << "<";
422 } else {
423 out << "<=";
424 }
425 out << this->getUpperBound(i);
426 }
427 out << " ";
428 }
429 if (this->isMultiDimensional()) {
430 out << "}";
431 }
432
433 this->getRightSubformula().writeToStream(out, true);
434 if (allowParentheses) {
435 out << ")";
436 }
437 }
438
439 return out;
440}
441} // namespace logic
442} // namespace storm
int_fast64_t evaluateAsInt(Valuation const *valuation=nullptr) const
Evaluates the expression under the valuation of variables given by the valuation and returns the resu...
double evaluateAsDouble(Valuation const *valuation=nullptr) const
Evaluates the expression under the valuation of variables given by the valuation and returns the resu...
storm::RationalNumber evaluateAsRational() const
Evaluates the expression and returns the resulting rational number.
bool containsVariables() const
Retrieves whether the expression contains a variable.
void gatherVariables(std::set< storm::expressions::Variable > &variables) const
Retrieves the set of all variables that appear in the expression.
ValueType getNonStrictLowerBound(unsigned i=0) const
virtual std::ostream & writeToStream(std::ostream &out, bool allowParentheses=false) const override
Writes the forumla to the given output stream.
std::shared_ptr< BoundedUntilFormula const > restrictToDimension(unsigned i) const
TimeBoundReference const & getTimeBoundReference(unsigned i=0) const
virtual void gatherAtomicLabelFormulas(std::vector< std::shared_ptr< AtomicLabelFormula const > > &atomicLabelFormulas) const override
ValueType getNonStrictUpperBound(unsigned i=0) const
bool isLowerBoundStrict(unsigned i=0) const
virtual bool hasQualitativeResult() const override
virtual bool isProbabilityPathFormula() const override
virtual void gatherAtomicExpressionFormulas(std::vector< std::shared_ptr< AtomicExpressionFormula const > > &atomicExpressionFormulas) const override
storm::expressions::Expression const & getUpperBound(unsigned i=0) const
virtual boost::any accept(FormulaVisitor const &visitor, boost::any const &data) const override
storm::expressions::Expression const & getLowerBound(unsigned i=0) const
virtual void gatherReferencedRewardModels(std::set< std::string > &referencedRewardModels) const override
virtual bool isBoundedUntilFormula() const override
bool hasIntegerUpperBound(unsigned i=0) const
BoundedUntilFormula(std::shared_ptr< Formula const > const &leftSubformula, std::shared_ptr< Formula const > const &rightSubformula, boost::optional< TimeBound > const &lowerBound, boost::optional< TimeBound > const &upperBound, TimeBoundReference const &timeBoundReference)
virtual bool hasQuantitativeResult() const override
virtual void gatherUsedVariables(std::set< storm::expressions::Variable > &usedVariables) const override
bool hasIntegerLowerBound(unsigned i=0) const
bool isUpperBoundStrict(unsigned i=0) const
virtual std::ostream & writeToStream(std::ostream &out, bool allowParentheses=false) const =0
Writes the forumla to the given output stream.
virtual void gatherReferencedRewardModels(std::set< std::string > &referencedRewardModels) const
Definition Formula.cpp:587
virtual void gatherAtomicLabelFormulas(std::vector< std::shared_ptr< AtomicLabelFormula const > > &atomicLabelFormulas) const
Definition Formula.cpp:583
virtual void gatherUsedVariables(std::set< storm::expressions::Variable > &usedVariables) const
Definition Formula.cpp:591
virtual void gatherAtomicExpressionFormulas(std::vector< std::shared_ptr< AtomicExpressionFormula const > > &atomicExpressionFormulas) const
Definition Formula.cpp:579
std::shared_ptr< Formula const > asSharedPointer()
Definition Formula.cpp:571
virtual boost::any visit(AtomicExpressionFormula const &f, boost::any const &data) const =0
std::string const & getRewardName() const
RewardAccumulation const & getRewardAccumulation() const
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:11
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30