Storm 1.14.0.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
QuantileHelper.cpp
Go to the documentation of this file.
2
3#include <boost/optional.hpp>
4#include <memory>
5#include <optional>
6#include <set>
7#include <vector>
8
10
19
22
25
26namespace storm {
27namespace modelchecker {
28namespace helper {
29namespace rewardbounded {
30
31template<typename ModelType>
32QuantileHelper<ModelType>::QuantileHelper(ModelType const& model, storm::logic::QuantileFormula const& quantileFormula)
33 : model(model), quantileFormula(quantileFormula) {
34 // Do all kinds of sanity check.
35 std::set<storm::expressions::Variable> quantileVariables;
36 for (auto const& quantileVariable : quantileFormula.getBoundVariables()) {
37 STORM_LOG_THROW(quantileVariables.count(quantileVariable) == 0, storm::exceptions::NotSupportedException,
38 "Quantile formula considers the same bound variable twice.");
39 quantileVariables.insert(quantileVariable);
40 }
41 STORM_LOG_THROW(quantileFormula.getSubformula().isProbabilityOperatorFormula(), storm::exceptions::NotSupportedException,
42 "Quantile formula needs probability operator inside. The formula " << quantileFormula << " is not supported.");
43 auto const& probOpFormula = quantileFormula.getSubformula().asProbabilityOperatorFormula();
44 STORM_LOG_THROW(probOpFormula.hasBound(), storm::exceptions::InvalidOperationException,
45 "Probability operator inside quantile formula needs to have a bound.");
46 STORM_LOG_THROW(!model.isNondeterministicModel() || probOpFormula.hasOptimalityType(), storm::exceptions::InvalidOperationException,
47 "Probability operator inside quantile formula needs to have an optimality type.");
48 STORM_LOG_WARN_COND(probOpFormula.getBound().comparisonType == storm::logic::ComparisonType::Greater ||
49 probOpFormula.getBound().comparisonType == storm::logic::ComparisonType::LessEqual,
50 "Probability operator inside quantile formula needs to have bound > or <=. The specified comparison type might lead to "
51 "non-termination."); // This has to do with letting bound variables approach infinity, e.g., Pr>0.7 [F "goal"] holds iff Pr>0.7 [F<=B
52 // "goal"] holds for some B.
53 STORM_LOG_THROW(probOpFormula.getSubformula().isBoundedUntilFormula(), storm::exceptions::NotSupportedException,
54 "Quantile formula needs bounded until probability operator formula as subformula. The formula " << quantileFormula << " is not supported.");
55 auto const& boundedUntilFormula = probOpFormula.getSubformula().asBoundedUntilFormula();
56 std::set<storm::expressions::Variable> boundVariables;
57 for (uint64_t dim = 0; dim < boundedUntilFormula.getDimension(); ++dim) {
58 storm::expressions::Expression boundExpression;
59 if (boundedUntilFormula.hasUpperBound(dim)) {
60 STORM_LOG_THROW(!boundedUntilFormula.hasLowerBound(dim), storm::exceptions::NotSupportedException,
61 "Interval bounds are not supported within quantile formulas.");
62 STORM_LOG_THROW(!boundedUntilFormula.isUpperBoundStrict(dim), storm::exceptions::NotSupportedException,
63 "Only non-strict upper reward bounds are supported for quantiles.");
64 boundExpression = boundedUntilFormula.getUpperBound(dim);
65 } else if (boundedUntilFormula.hasLowerBound(dim)) {
66 STORM_LOG_THROW(!boundedUntilFormula.isLowerBoundStrict(dim), storm::exceptions::NotSupportedException,
67 "Only non-strict lower reward bounds are supported for quantiles.");
68 boundExpression = boundedUntilFormula.getLowerBound(dim);
69 }
70 if (boundExpression.isInitialized() && boundExpression.containsVariables()) {
72 boundExpression.isVariable(), storm::exceptions::NotSupportedException,
73 "Non-trivial bound expressions such as '" << boundExpression << "' are not supported. Either specify a constant or a quantile variable.");
74 storm::expressions::Variable const& boundVariable = boundExpression.getBaseExpression().asVariableExpression().getVariable();
75 STORM_LOG_THROW(boundVariables.count(boundVariable) == 0, storm::exceptions::NotSupportedException,
76 "Variable " << boundExpression << " occurs at multiple reward bounds.");
77 boundVariables.insert(boundVariable);
78 STORM_LOG_THROW(quantileVariables.count(boundVariable) == 1, storm::exceptions::NotSupportedException,
79 "The formula contains undefined constant '" << boundExpression << "'.");
80 }
81 }
82}
83
85std::shared_ptr<storm::logic::ProbabilityOperatorFormula> transformBoundedUntilOperator(storm::logic::ProbabilityOperatorFormula const& boundedUntilOperator,
86 std::vector<BoundTransformation> const& transformations,
87 bool complementQuery = false) {
88 auto const& origBoundedUntil = boundedUntilOperator.getSubformula().asBoundedUntilFormula();
89 STORM_LOG_ASSERT(transformations.size() == origBoundedUntil.getDimension(),
90 "Tried to replace the bound of a dimension that is higher than the number of dimensions of the formula.");
91 std::vector<std::shared_ptr<storm::logic::Formula const>> leftSubformulas, rightSubformulas;
92 std::vector<std::optional<storm::logic::TimeBound>> lowerBounds, upperBounds;
93 std::vector<storm::logic::TimeBoundReference> timeBoundReferences;
94
95 for (uint64_t dim = 0; dim < origBoundedUntil.getDimension(); ++dim) {
96 if (origBoundedUntil.hasMultiDimensionalSubformulas()) {
97 leftSubformulas.push_back(origBoundedUntil.getLeftSubformula(dim).asSharedPointer());
98 rightSubformulas.push_back(origBoundedUntil.getRightSubformula(dim).asSharedPointer());
99 }
100 timeBoundReferences.push_back(origBoundedUntil.getTimeBoundReference(dim));
101 if (transformations[dim] == BoundTransformation::None) {
102 if (origBoundedUntil.hasLowerBound(dim)) {
103 lowerBounds.push_back(storm::logic::TimeBound(origBoundedUntil.isLowerBoundStrict(dim), origBoundedUntil.getLowerBound(dim)));
104 } else {
105 lowerBounds.push_back(std::nullopt);
106 }
107 if (origBoundedUntil.hasUpperBound(dim)) {
108 upperBounds.push_back(storm::logic::TimeBound(origBoundedUntil.isUpperBoundStrict(dim), origBoundedUntil.getUpperBound(dim)));
109 } else {
110 upperBounds.push_back(std::nullopt);
111 }
112 } else {
113 // We need a zero expression in all other cases
115 if (origBoundedUntil.hasLowerBound(dim)) {
116 zero = origBoundedUntil.getLowerBound(dim).getManager().rational(0.0);
117 } else {
118 STORM_LOG_THROW(origBoundedUntil.hasUpperBound(dim), storm::exceptions::InvalidOperationException,
119 "The given bounded until formula has no cost-bound for one dimension.");
120 zero = origBoundedUntil.getUpperBound(dim).getManager().rational(0.0);
121 }
122 if (transformations[dim] == BoundTransformation::LessEqualZero) {
123 lowerBounds.push_back(std::nullopt);
124 upperBounds.push_back(storm::logic::TimeBound(false, zero));
125 } else {
126 STORM_LOG_ASSERT(transformations[dim] == BoundTransformation::GreaterZero || transformations[dim] == BoundTransformation::GreaterEqualZero,
127 "Unhandled bound transformation.");
128 lowerBounds.push_back(storm::logic::TimeBound(transformations[dim] == BoundTransformation::GreaterZero, zero));
129 upperBounds.push_back(std::nullopt);
130 }
131 }
132 }
133 std::shared_ptr<storm::logic::Formula> newBoundedUntil;
134 if (origBoundedUntil.hasMultiDimensionalSubformulas()) {
135 newBoundedUntil = std::make_shared<storm::logic::BoundedUntilFormula>(leftSubformulas, rightSubformulas, lowerBounds, upperBounds, timeBoundReferences);
136 } else {
137 newBoundedUntil = std::make_shared<storm::logic::BoundedUntilFormula>(origBoundedUntil.getLeftSubformula().asSharedPointer(),
138 origBoundedUntil.getRightSubformula().asSharedPointer(), lowerBounds, upperBounds,
139 timeBoundReferences);
140 }
141 storm::logic::OperatorInformation newOpInfo(boundedUntilOperator.getOperatorInformation().optimalityType, boundedUntilOperator.getBound());
142 if (complementQuery) {
143 newOpInfo.bound->comparisonType = storm::logic::invert(newOpInfo.bound->comparisonType);
144 }
145 return std::make_shared<storm::logic::ProbabilityOperatorFormula>(newBoundedUntil, newOpInfo);
146}
147
150 STORM_LOG_DEBUG("Increasing precision of underlying solver.");
153 static_cast<storm::RationalNumber>(env.solver().getPrecisionOfLinearEquationSolver(env.solver().getLinearEquationSolverType()).first.get() * factor));
154 env.solver().minMax().setPrecision(env.solver().minMax().getPrecision() * factor);
155}
156
161template<typename ValueType>
162std::pair<ValueType, ValueType> getLowerUpperBound(storm::Environment const& env, ValueType const& factor, ValueType const& value, bool minMax = true) {
163 ValueType prec;
164 bool relative;
165 if (minMax) {
167 relative = env.solver().minMax().getRelativeTerminationCriterion();
168 } else {
169 prec =
172 }
173 prec *= factor;
174 if (relative) {
175 ValueType one = storm::utility::one<ValueType>();
176 ValueType lower = value * (one / (prec + one));
177 ValueType upper = value * (one + prec / (prec + one));
178 return std::make_pair(lower, upper);
179 } else {
180 return std::pair<ValueType, ValueType>(value - prec, value + prec);
181 }
182}
183
184template<typename ModelType>
185uint64_t QuantileHelper<ModelType>::getDimension() const {
186 return quantileFormula.getSubformula().asProbabilityOperatorFormula().getSubformula().asBoundedUntilFormula().getDimension();
187}
188
189template<typename ModelType>
190storm::storage::BitVector QuantileHelper<ModelType>::getOpenDimensions() const {
191 auto const& boundedUntil = quantileFormula.getSubformula().asProbabilityOperatorFormula().getSubformula().asBoundedUntilFormula();
192 storm::storage::BitVector res(getDimension(), false);
193 for (uint64_t dim = 0; dim < getDimension(); ++dim) {
194 auto const& bound = boundedUntil.hasLowerBound(dim) ? boundedUntil.getLowerBound(dim) : boundedUntil.getUpperBound(dim);
195 if (bound.containsVariables()) {
196 res.set(dim, true);
197 }
198 }
199 return res;
200}
201
202template<typename ModelType>
203storm::expressions::Variable const& QuantileHelper<ModelType>::getVariableForDimension(uint64_t const& dim) const {
204 auto const& boundedUntil = quantileFormula.getSubformula().asProbabilityOperatorFormula().getSubformula().asBoundedUntilFormula();
205 return (boundedUntil.hasLowerBound(dim) ? boundedUntil.getLowerBound(dim) : boundedUntil.getUpperBound(dim))
206 .getBaseExpression()
207 .asVariableExpression()
208 .getVariable();
209}
210
211template<typename ModelType>
212std::vector<std::vector<storm::utility::ExtendedValueType<typename ModelType::ValueType>>> QuantileHelper<ModelType>::computeQuantile(Environment const& env) {
213 numCheckedEpochs = 0;
214 numPrecisionRefinements = 0;
215 swEpochAnalysis.reset();
216 swExploration.reset();
217 cachedSubQueryResults.clear();
218
219 std::vector<std::vector<storm::utility::ExtendedValueType<ValueType>>> result;
220 Environment envCpy = env; // It might be necessary to increase the precision during the computation
221 // Call the internal recursive function
222 auto internalResult = computeQuantile(envCpy, getOpenDimensions(), false);
223
224 // Translate the result by applying the scaling factors and permutation.
225 std::vector<uint64_t> permutation;
226 for (auto const& v : quantileFormula.getBoundVariables()) {
227 uint64_t openDim = 0;
228 for (auto dim : getOpenDimensions()) {
229 if (getVariableForDimension(dim) == v) {
230 permutation.push_back(openDim);
231 break;
232 }
233 ++openDim;
234 }
235 }
236 STORM_LOG_ASSERT(permutation.size() == getOpenDimensions().getNumberOfSetBits(), "Permutation size mismatch.");
237 for (auto const& costLimits : internalResult.first.getGenerator()) {
238 std::vector<storm::utility::ExtendedValueType<ValueType>> resultPoint;
239 for (auto const& dim : permutation) {
240 CostLimit const& cl = costLimits[dim];
241 resultPoint.push_back(cl.isInfinity() ? storm::utility::positiveInfinity<ValueType>()
243 internalResult.second[dim]));
244 }
245 result.push_back(resultPoint);
246 }
247 STORM_LOG_STATISTICS("Number of checked epochs: " << numCheckedEpochs);
248 STORM_LOG_STATISTICS("Number of required precision refinements: " << numPrecisionRefinements);
249 STORM_LOG_STATISTICS("Time for epoch exploration: " << swExploration << " seconds.");
250 STORM_LOG_STATISTICS("\tTime for epoch model analysis: " << swEpochAnalysis << " seconds.");
251 return result;
252}
253
254template<typename ModelType>
255std::pair<CostLimitClosure, std::vector<typename QuantileHelper<ModelType>::ValueType>> QuantileHelper<ModelType>::computeQuantile(
256 Environment& env, storm::storage::BitVector const& consideredDimensions, bool complementaryQuery) {
257 STORM_LOG_ASSERT(consideredDimensions.isSubsetOf(getOpenDimensions()),
258 "Considered dimensions for a quantile query should be a subset of the set of dimensions without a fixed bound.");
259
260 storm::storage::BitVector cacheKey = consideredDimensions;
261 cacheKey.resize(cacheKey.size() + 1, complementaryQuery);
262 auto cacheIt = cachedSubQueryResults.find(cacheKey);
263 if (cacheIt != cachedSubQueryResults.end()) {
264 return cacheIt->second;
265 }
266
267 auto boundedUntilOp = transformBoundedUntilOperator(quantileFormula.getSubformula().asProbabilityOperatorFormula(),
268 std::vector<BoundTransformation>(getDimension(), BoundTransformation::None), complementaryQuery);
269 std::set<storm::expressions::Variable> infinityVariables;
270 storm::storage::BitVector lowerBoundedDimensions(getDimension());
271 storm::storage::BitVector downwardClosedDimensions(getDimension());
272 bool hasLowerValueBound = storm::logic::isLowerBound(boundedUntilOp->getComparisonType());
273 for (auto d : getOpenDimensions()) {
274 if (consideredDimensions.get(d)) {
275 bool hasLowerCostBound = boundedUntilOp->getSubformula().asBoundedUntilFormula().hasLowerBound(d);
276 lowerBoundedDimensions.set(d, hasLowerCostBound);
277 downwardClosedDimensions.set(d, hasLowerCostBound == hasLowerValueBound);
278 } else {
279 infinityVariables.insert(getVariableForDimension(d));
280 }
281 }
282 downwardClosedDimensions = downwardClosedDimensions % consideredDimensions;
283 CostLimitClosure satCostLimits(downwardClosedDimensions), unsatCostLimits(~downwardClosedDimensions);
284
285 // Initialize the (un)sat cost limits to guarantee termination
286 bool onlyUpperCostBounds = lowerBoundedDimensions.empty();
287 bool onlyLowerCostBounds = lowerBoundedDimensions == consideredDimensions;
288 if (onlyUpperCostBounds || onlyLowerCostBounds) {
289 for (uint64_t k : consideredDimensions) {
290 storm::storage::BitVector subQueryDimensions = consideredDimensions;
291 subQueryDimensions.set(k, false);
292 bool subQueryComplement = complementaryQuery != ((onlyUpperCostBounds && hasLowerValueBound) || (onlyLowerCostBounds && !hasLowerValueBound));
293 auto subQueryResult = computeQuantile(env, subQueryDimensions, subQueryComplement);
294 for (auto const& subQueryCostLimit : subQueryResult.first.getGenerator()) {
295 CostLimits initPoint;
296 uint64_t i = 0;
297 for (uint64_t dim : consideredDimensions) {
298 if (dim == k) {
299 initPoint.push_back(CostLimit::infinity());
300 } else {
301 initPoint.push_back(subQueryCostLimit[i]);
302 ++i;
303 }
304 }
305 if (subQueryComplement == complementaryQuery) {
306 satCostLimits.insert(initPoint);
307 } else {
308 unsatCostLimits.insert(initPoint);
309 }
310 }
311 }
312 } else {
313 STORM_LOG_WARN("Quantile formula considers mixtures of upper and lower reward-bounds. Termination is not guaranteed.");
314 }
315
316 // Loop until the goal precision is reached.
317 STORM_LOG_DEBUG("Computing quantile for dimensions: " << consideredDimensions);
318 while (true) {
319 // initialize reward unfolding and data that will be needed for each epoch
320 MultiDimensionalRewardUnfolding<ValueType, true> rewardUnfolding(model, boundedUntilOp, infinityVariables);
321 if (computeQuantile(env, consideredDimensions, *boundedUntilOp, lowerBoundedDimensions, satCostLimits, unsatCostLimits, rewardUnfolding)) {
322 std::vector<ValueType> scalingFactors;
323 for (uint64_t dim : consideredDimensions) {
324 scalingFactors.push_back(rewardUnfolding.getDimension(dim).scalingFactor);
325 }
326 std::pair<CostLimitClosure, std::vector<ValueType>> result(satCostLimits, scalingFactors);
327 cachedSubQueryResults.emplace(cacheKey, result);
328 return result;
329 }
330 STORM_LOG_WARN("Restarting quantile computation after " << swExploration << " seconds due to insufficient precision.");
331 ++numPrecisionRefinements;
333 }
334}
335
336bool getNextCandidateCostLimit(CostLimit const& candidateCostLimitSum, CostLimits& current) {
337 if (current.size() == 0) {
338 return false;
339 }
340 uint64_t iSum = current.front().get();
341 if (iSum == candidateCostLimitSum.get()) {
342 return false;
343 }
344 for (uint64_t i = 1; i < current.size(); ++i) {
345 iSum += current[i].get();
346 if (iSum == candidateCostLimitSum.get()) {
347 ++current[i - 1].get();
348 uint64_t newVal = current[i].get() - 1;
349 current[i].get() = 0;
350 current.back().get() = newVal;
351 return true;
352 }
353 }
354 STORM_LOG_THROW(false, storm::exceptions::UnexpectedException,
355 "The entries of the current cost limit candidate do not sum up to the current candidate sum.");
356 return false;
357}
358
359bool translateEpochToCostLimits(EpochManager::Epoch const& epoch, EpochManager::Epoch const& startEpoch, storm::storage::BitVector const& consideredDimensions,
360 storm::storage::BitVector const& lowerBoundedDimensions, EpochManager const& epochManager, CostLimits& epochAsCostLimits) {
361 for (uint64_t dim = 0; dim < consideredDimensions.size(); ++dim) {
362 if (consideredDimensions.get(dim)) {
363 if (lowerBoundedDimensions.get(dim)) {
364 if (epochManager.isBottomDimension(epoch, dim)) {
365 epochAsCostLimits.push_back(CostLimit(0));
366 } else {
367 epochAsCostLimits.push_back(CostLimit(epochManager.getDimensionOfEpoch(epoch, dim) + 1));
368 }
369 } else {
370 if (epochManager.isBottomDimension(epoch, dim)) {
371 return false;
372 } else {
373 epochAsCostLimits.push_back(CostLimit(epochManager.getDimensionOfEpoch(epoch, dim)));
374 }
375 }
376 } else {
377 if (epochManager.isBottomDimension(epoch, dim)) {
378 if (!epochManager.isBottomDimension(startEpoch, dim)) {
379 return false;
380 }
381 } else if (epochManager.getDimensionOfEpoch(epoch, dim) != epochManager.getDimensionOfEpoch(startEpoch, dim)) {
382 return false;
383 }
384 }
385 }
386 return true;
387}
388
389template<typename ModelType>
391 storm::logic::ProbabilityOperatorFormula const& boundedUntilOperator,
392 storm::storage::BitVector const& lowerBoundedDimensions, CostLimitClosure& satCostLimits,
393 CostLimitClosure& unsatCostLimits, MultiDimensionalRewardUnfolding<ValueType, true>& rewardUnfolding) {
394 auto lowerBound = rewardUnfolding.getLowerObjectiveBound();
395 auto upperBound = rewardUnfolding.getUpperObjectiveBound();
396 std::vector<ValueType> x, b;
397 std::unique_ptr<storm::solver::MinMaxLinearEquationSolver<ValueType>> minMaxSolver; // Needed for MDP
398 std::unique_ptr<storm::solver::LinearEquationSolver<ValueType>> linEqSolver; // Needed for DTMC
399 if (!model.isNondeterministicModel()) {
400 rewardUnfolding.setEquationSystemFormatForEpochModel(storm::solver::GeneralLinearEquationSolverFactory<ValueType>().getEquationProblemFormat(env));
401 }
402
403 swExploration.start();
404 bool progress = true;
405 for (CostLimit candidateCostLimitSum(0); progress; ++candidateCostLimitSum.get()) {
406 CostLimits currentCandidate(satCostLimits.dimension(), CostLimit(0));
407 if (!currentCandidate.empty()) {
408 currentCandidate.back() = candidateCostLimitSum;
409 }
410 // We can still have progress if one of the closures is empty and the other is not full.
411 // This ensures that we do not terminate too early in case that the (un)satCostLimits are initially non-empty.
412 progress = (satCostLimits.empty() && !unsatCostLimits.full()) || (unsatCostLimits.empty() && !satCostLimits.full());
413 do {
414 if (!satCostLimits.contains(currentCandidate) && !unsatCostLimits.contains(currentCandidate)) {
415 progress = true;
416 // Transform candidate cost limits to an appropriate start epoch
417 auto startEpoch = rewardUnfolding.getStartEpoch(true);
418 auto costLimitIt = currentCandidate.begin();
419 for (uint64_t dim : consideredDimensions) {
420 if (lowerBoundedDimensions.get(dim)) {
421 if (costLimitIt->get() > 0) {
422 rewardUnfolding.getEpochManager().setDimensionOfEpoch(startEpoch, dim, costLimitIt->get() - 1);
423 } else {
424 rewardUnfolding.getEpochManager().setBottomDimension(startEpoch, dim);
425 }
426 } else {
427 rewardUnfolding.getEpochManager().setDimensionOfEpoch(startEpoch, dim, costLimitIt->get());
428 }
429 ++costLimitIt;
430 }
431 STORM_LOG_DEBUG("Checking start epoch " << rewardUnfolding.getEpochManager().toString(startEpoch) << ".");
432 auto epochSequence = rewardUnfolding.getEpochComputationOrder(startEpoch, true);
433 for (auto const& epoch : epochSequence) {
434 ++numCheckedEpochs;
435 swEpochAnalysis.start();
436 auto& epochModel = rewardUnfolding.setCurrentEpoch(epoch);
437 if (model.isNondeterministicModel()) {
438 rewardUnfolding.setSolutionForCurrentEpoch(
439 epochModel.analyzeSingleObjective(env, boundedUntilOperator.getOptimalityType(), x, b, minMaxSolver, lowerBound, upperBound));
440 } else {
441 rewardUnfolding.setSolutionForCurrentEpoch(epochModel.analyzeSingleObjective(env, x, b, linEqSolver, lowerBound, upperBound));
442 }
443 swEpochAnalysis.stop();
444
445 CostLimits epochAsCostLimits;
446 if (translateEpochToCostLimits(epoch, startEpoch, consideredDimensions, lowerBoundedDimensions, rewardUnfolding.getEpochManager(),
447 epochAsCostLimits)) {
448 ValueType currValue = rewardUnfolding.getInitialStateResult(epoch);
449 bool propertySatisfied;
450 if (env.solver().isForceSoundness()) {
451 ValueType sumOfEpochDimensions =
452 storm::utility::convertNumber<ValueType>(rewardUnfolding.getEpochManager().getSumOfDimensions(epoch) + 1);
453 auto lowerUpperValue = getLowerUpperBound(env, sumOfEpochDimensions, currValue);
454 propertySatisfied = boundedUntilOperator.getBound().isSatisfied(lowerUpperValue.first);
455 if (propertySatisfied != boundedUntilOperator.getBound().isSatisfied(lowerUpperValue.second)) {
456 // unclear result due to insufficient precision.
457 swExploration.stop();
458 return false;
459 }
460 } else {
461 propertySatisfied = boundedUntilOperator.getBound().isSatisfied(currValue);
462 }
463 if (propertySatisfied) {
464 satCostLimits.insert(epochAsCostLimits);
465 } else {
466 unsatCostLimits.insert(epochAsCostLimits);
467 }
468 }
469 }
470 }
471 } while (getNextCandidateCostLimit(candidateCostLimitSum, currentCandidate));
472 if (!progress) {
473 progress = !CostLimitClosure::unionFull(satCostLimits, unsatCostLimits);
474 }
475 }
476 swExploration.stop();
477 return true;
478}
479
484
485} // namespace rewardbounded
486} // namespace helper
487} // namespace modelchecker
488} // namespace storm
SolverEnvironment & solver()
storm::RationalNumber const & getPrecision() const
void setPrecision(storm::RationalNumber value)
bool const & getRelativeTerminationCriterion() const
MinMaxSolverEnvironment & minMax()
storm::solver::EquationSolverType const & getLinearEquationSolverType() const
void setLinearEquationSolverPrecision(boost::optional< storm::RationalNumber > const &newPrecision, boost::optional< bool > const &relativePrecision=boost::none)
std::pair< boost::optional< storm::RationalNumber >, boost::optional< bool > > getPrecisionOfLinearEquationSolver(storm::solver::EquationSolverType const &solverType) const
VariableExpression const & asVariableExpression() const
bool isVariable() const
Retrieves whether the expression is a variable.
bool containsVariables() const
Retrieves whether the expression contains a variable.
BaseExpression const & getBaseExpression() const
Retrieves the base expression underlying this expression object.
bool isInitialized() const
Checks whether the object encapsulates a base-expression.
Variable const & getVariable() const
Retrieves the variable associated with this expression.
BoundedUntilFormula & asBoundedUntilFormula()
Definition Formula.cpp:363
Bound const & getBound() const
OperatorInformation const & getOperatorInformation() const
storm::solver::OptimizationDirection const & getOptimalityType() const
Formula const & getSubformula() const
static bool unionFull(CostLimitClosure const &first, CostLimitClosure const &second)
Returns true if the union of the two closures is full, i.e., contains every point.
bool isBottomDimension(Epoch const &epoch, uint64_t const &dimension) const
uint64_t getDimensionOfEpoch(Epoch const &epoch, uint64_t const &dimension) const
QuantileHelper(ModelType const &model, storm::logic::QuantileFormula const &quantileFormula)
std::vector< std::vector< storm::utility::ExtendedValueType< ValueType > > > computeQuantile(Environment const &env)
A bit vector that is internally represented as a vector of 64-bit values.
Definition BitVector.h:16
bool isSubsetOf(BitVector const &other) const
Checks whether all bits that are set in the current bit vector are also set in the given bit vector.
void set(uint64_t index, bool value=true)
Sets the given truth value at the given index.
size_t size() const
Retrieves the number of bits this bit vector can store.
void resize(uint64_t newLength, bool init=false)
Resizes the bit vector to hold the given new number of bits.
bool get(uint64_t index) const
Retrieves the truth value of the bit at the given index and performs a bound check.
#define STORM_LOG_WARN(message)
Definition logging.h:35
#define STORM_LOG_DEBUG(message)
Definition logging.h:28
#define STORM_LOG_STATISTICS(message)
Definition logging.h:48
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:9
#define STORM_LOG_WARN_COND(cond, message)
Definition macros.h:54
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:39
SFTBDDChecker::ValueType ValueType
bool isLowerBound(ComparisonType t)
ComparisonType invert(ComparisonType t)
std::pair< ValueType, ValueType > getLowerUpperBound(storm::Environment const &env, ValueType const &factor, ValueType const &value, bool minMax=true)
Computes a lower / upper bound on the actual result of a sound minmax or linear equation solver.
void increasePrecision(storm::Environment &env)
Increases the precision of solver results.
bool translateEpochToCostLimits(EpochManager::Epoch const &epoch, EpochManager::Epoch const &startEpoch, storm::storage::BitVector const &consideredDimensions, storm::storage::BitVector const &lowerBoundedDimensions, EpochManager const &epochManager, CostLimits &epochAsCostLimits)
std::shared_ptr< storm::logic::ProbabilityOperatorFormula > transformBoundedUntilOperator(storm::logic::ProbabilityOperatorFormula const &boundedUntilOperator, std::vector< BoundTransformation > const &transformations, bool complementQuery=false)
bool getNextCandidateCostLimit(CostLimit const &candidateCostLimitSum, CostLimits &current)
ExtendedValueType< ValueType > positiveInfinity()
std::conditional_t< storm::NumberTraits< ValueType >::HasInfinity, ValueType, ExtendedNumber< ValueType > > ExtendedValueType
The type to use for values that may be infinite.
ValueType one()
Definition constants.cpp:21
TargetType convertNumber(SourceType const &number)
bool isSatisfied(ValueType const &compareValue) const
Definition Bound.cpp:9
boost::optional< Bound > bound
boost::optional< storm::solver::OptimizationDirection > optimalityType