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