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