Storm 1.14.0.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 std::optional<TimeBound> const& lowerBound, std::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<std::optional<TimeBound>> const& lowerBounds, std::vector<std::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 STORM_LOG_ASSERT(timeBoundReferences.size() == upperBound.size(), "Time bound reference/upper bound size mismatch.");
38 STORM_LOG_ASSERT(timeBoundReferences.size() == lowerBound.size(), "Time bound reference/lower bound size mismatch.");
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<std::optional<TimeBound>> const& lowerBounds, std::vector<std::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 STORM_LOG_ASSERT(leftSubformula.size() == rightSubformula.size(), "Left/right subformula size mismatch.");
52 STORM_LOG_ASSERT(rightSubformula.size() == timeBoundReference.size(), "Subformula/time bound reference size mismatch.");
53 STORM_LOG_ASSERT(timeBoundReference.size() == lowerBound.size(), "Time bound reference/lower bound size mismatch.");
54 STORM_LOG_ASSERT(lowerBound.size() == upperBound.size(), "Lower/upper bound size mismatch.");
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()) {
101 if (!this->getTimeBoundReference(i).hasRewardModelName()) {
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 STORM_LOG_ASSERT(timeBoundReference.size() != 0, "Time bound reference is empty.");
153 return timeBoundReference.size() > 1;
154}
155
157 STORM_LOG_ASSERT(leftSubformula.size() != 0, "Left subformula is empty.");
158 STORM_LOG_ASSERT(leftSubformula.size() == rightSubformula.size(), "Left/right subformula size mismatch.");
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 STORM_LOG_ASSERT(i < timeBoundReference.size(), "Time bound reference index out of range.");
194 return timeBoundReference.at(i);
195}
196
198 STORM_LOG_ASSERT(i < lowerBound.size(), "Lower bound index out of range.");
199 if (!hasLowerBound(i)) {
200 return false;
201 }
202 return lowerBound.at(i).value().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).value().getBound().hasIntegerType();
223}
224
226 return upperBound.at(i).value().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).value().getBound().hasIntegerType();
244}
245
247 return lowerBound.at(i).value().getBound();
248}
249
251 return upperBound.at(i).value().getBound();
252}
253
254std::optional<TimeBound> BoundedUntilFormula::getLowerBoundAsOptionalTimeBound(unsigned i) const {
255 return lowerBound.at(i);
256}
257
258std::optional<TimeBound> BoundedUntilFormula::getUpperBoundAsOptionalTimeBound(unsigned i) const {
259 return upperBound.at(i);
260}
261
262template<>
263double BoundedUntilFormula::getLowerBound(unsigned i) const {
264 if (!hasLowerBound(i)) {
265 return 0.0;
266 }
267 checkNoVariablesInBound(this->getLowerBound());
268 double bound = this->getLowerBound(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<>
274double BoundedUntilFormula::getUpperBound(unsigned i) const {
275 checkNoVariablesInBound(this->getUpperBound());
276 double bound = this->getUpperBound(i).evaluateAsDouble();
277 STORM_LOG_THROW(bound >= 0, storm::exceptions::InvalidPropertyException, "Time-bound must not evaluate to negative number.");
278 return bound;
279}
280
281template<>
282storm::RationalNumber BoundedUntilFormula::getLowerBound(unsigned i) const {
283 if (!hasLowerBound(i)) {
285 }
286 checkNoVariablesInBound(this->getLowerBound(i));
287 storm::RationalNumber bound = this->getLowerBound(i).evaluateAsRational();
288 STORM_LOG_THROW(bound >= storm::utility::zero<storm::RationalNumber>(), storm::exceptions::InvalidPropertyException,
289 "Time-bound must not evaluate to negative number.");
290 return bound;
291}
292
293template<>
294storm::RationalNumber BoundedUntilFormula::getUpperBound(unsigned i) const {
295 checkNoVariablesInBound(this->getUpperBound(i));
296 storm::RationalNumber bound = this->getUpperBound(i).evaluateAsRational();
297 STORM_LOG_THROW(bound >= storm::utility::zero<storm::RationalNumber>(), storm::exceptions::InvalidPropertyException,
298 "Time-bound must not evaluate to negative number.");
299 return bound;
300}
301
302template<>
303uint64_t BoundedUntilFormula::getLowerBound(unsigned i) const {
304 if (!hasLowerBound(i)) {
305 return 0;
306 }
307 checkNoVariablesInBound(this->getLowerBound(i));
308 int_fast64_t bound = this->getLowerBound(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<>
314uint64_t BoundedUntilFormula::getUpperBound(unsigned i) const {
315 checkNoVariablesInBound(this->getUpperBound(i));
316 int_fast64_t bound = this->getUpperBound(i).evaluateAsInt();
317 STORM_LOG_THROW(bound >= 0, storm::exceptions::InvalidPropertyException, "Time-bound must not evaluate to negative number.");
318 return static_cast<uint64_t>(bound);
319}
320
321template<>
323 double bound = getUpperBound<double>(i);
324 STORM_LOG_THROW(!isUpperBoundStrict(i) || bound > 0, storm::exceptions::InvalidPropertyException,
325 "Cannot retrieve non-strict bound from strict zero-bound.");
326 return bound;
327}
328
329template<>
331 int_fast64_t bound = getUpperBound<uint64_t>(i);
332 if (isUpperBoundStrict(i)) {
333 STORM_LOG_THROW(bound > 0, storm::exceptions::InvalidPropertyException, "Cannot retrieve non-strict bound from strict zero-bound.");
334 return bound - 1;
335 } else {
336 return bound;
337 }
338}
339
340template<>
342 double bound = getLowerBound<double>(i);
343 STORM_LOG_THROW(!isLowerBoundStrict(i), storm::exceptions::InvalidPropertyException, "Cannot retrieve non-strict lower bound from strict lower-bound.");
344 return bound;
345}
346
347template<>
349 int_fast64_t bound = getLowerBound<uint64_t>(i);
350 if (isLowerBoundStrict(i)) {
351 return bound + 1;
352 } else {
353 return bound;
354 }
355}
356
357void BoundedUntilFormula::checkNoVariablesInBound(storm::expressions::Expression const& bound) {
358 STORM_LOG_THROW(!bound.containsVariables(), storm::exceptions::InvalidOperationException,
359 "Cannot evaluate time-bound '" << bound << "' as it contains undefined constants.");
360}
361
362std::shared_ptr<BoundedUntilFormula const> BoundedUntilFormula::restrictToDimension(unsigned i) const {
363 return std::make_shared<BoundedUntilFormula const>(getLeftSubformula(i).asSharedPointer(), getRightSubformula(i).asSharedPointer(), lowerBound.at(i),
364 upperBound.at(i), getTimeBoundReference(i));
365}
366
367std::ostream& BoundedUntilFormula::writeToStream(std::ostream& out, bool allowParentheses) const {
369 out << "multi(";
370 restrictToDimension(0)->writeToStream(out);
371 for (unsigned i = 1; i < this->getDimension(); ++i) {
372 out << ", ";
373 restrictToDimension(i)->writeToStream(out);
374 }
375 out << ")";
376 } else {
377 if (allowParentheses) {
378 out << "(";
379 }
380 this->getLeftSubformula().writeToStream(out, true);
381
382 out << " U";
383 if (this->isMultiDimensional()) {
384 out << "^{";
385 }
386 for (unsigned i = 0; i < this->getDimension(); ++i) {
387 if (i > 0) {
388 out << ", ";
389 }
390 if (this->getTimeBoundReference(i).isRewardBound()) {
391 out << "rew";
392 if (this->getTimeBoundReference(i).hasRewardAccumulation()) {
393 out << "[" << this->getTimeBoundReference(i).getRewardAccumulation() << "]";
394 }
395 if (this->getTimeBoundReference(i).hasRewardModelName()) {
396 out << "{\"" << this->getTimeBoundReference(i).getRewardName() << "\"}";
397 }
398 } else if (this->getTimeBoundReference(i).isStepBound()) {
399 out << "steps";
400 //} else if (this->getTimeBoundReference(i).isStepBound())
401 // Note: the 'time' keyword is optional.
402 // out << "time";
403 }
404 if (this->hasLowerBound(i)) {
405 if (this->hasUpperBound(i)) {
406 if (this->isLowerBoundStrict(i)) {
407 out << "(";
408 } else {
409 out << "[";
410 }
411 out << this->getLowerBound(i);
412 out << ", ";
413 out << this->getUpperBound(i);
414 if (this->isUpperBoundStrict(i)) {
415 out << ")";
416 } else {
417 out << "]";
418 }
419 } else {
420 if (this->isLowerBoundStrict(i)) {
421 out << ">";
422 } else {
423 out << ">=";
424 }
425 out << getLowerBound(i);
426 }
427 } else {
428 if (this->isUpperBoundStrict(i)) {
429 out << "<";
430 } else {
431 out << "<=";
432 }
433 out << this->getUpperBound(i);
434 }
435 out << " ";
436 }
437 if (this->isMultiDimensional()) {
438 out << "}";
439 }
440
441 this->getRightSubformula().writeToStream(out, true);
442 if (allowParentheses) {
443 out << ")";
444 }
445 }
446
447 return out;
448}
449} // namespace logic
450} // 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.
std::optional< TimeBound > getLowerBoundAsOptionalTimeBound(unsigned i=0) const
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
BoundedUntilFormula(std::shared_ptr< Formula const > const &leftSubformula, std::shared_ptr< Formula const > const &rightSubformula, std::optional< TimeBound > const &lowerBound, std::optional< TimeBound > const &upperBound, TimeBoundReference const &timeBoundReference)
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
virtual bool hasQuantitativeResult() const override
virtual void gatherUsedVariables(std::set< storm::expressions::Variable > &usedVariables) const override
std::optional< TimeBound > getUpperBoundAsOptionalTimeBound(unsigned i=0) const
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:613
virtual void gatherAtomicLabelFormulas(std::vector< std::shared_ptr< AtomicLabelFormula const > > &atomicLabelFormulas) const
Definition Formula.cpp:611
virtual void gatherUsedVariables(std::set< storm::expressions::Variable > &usedVariables) const
Definition Formula.cpp:615
virtual void gatherAtomicExpressionFormulas(std::vector< std::shared_ptr< AtomicExpressionFormula const > > &atomicExpressionFormulas) const
Definition Formula.cpp:609
std::shared_ptr< Formula const > asSharedPointer()
Definition Formula.cpp:601
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:9
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:39
ValueType zero()
Definition constants.cpp:26