Storm
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
DeterministicSchedsParetoExplorer.cpp
Go to the documentation of this file.
1#include <algorithm>
2#include <sstream>
3
14
17
18#include "storm/io/export.h"
20
24
25namespace storm {
26namespace modelchecker {
27namespace multiobjective {
28
29template<class SparseModelType, typename GeometryValueType>
31 : coordinates(coordinates), onFacet(false), paretoOptimal(false) {
32 STORM_LOG_ASSERT(!this->coordinates.empty(), "Points with dimension 0 are not supported");
33}
34
35template<class SparseModelType, typename GeometryValueType>
37 : coordinates(std::move(coordinates)), onFacet(false), paretoOptimal(false) {
38 STORM_LOG_ASSERT(!this->coordinates.empty(), "Points with dimension 0 are not supported");
39}
40
41template<class SparseModelType, typename GeometryValueType>
43 return coordinates;
44}
45
46template<class SparseModelType, typename GeometryValueType>
48 return coordinates;
49}
50
51template<class SparseModelType, typename GeometryValueType>
53 STORM_LOG_ASSERT(!coordinates.empty(), "Points with dimension 0 are not supported");
54 return coordinates.size();
55}
56
57template<class SparseModelType, typename GeometryValueType>
60 STORM_LOG_ASSERT(this->dimension() == other.dimension(), "Non-Equal dimensions of points: [" << this->toString() << "] vs. [" << other.toString() << "]");
61 auto thisIt = this->get().begin();
62 auto otherIt = other.get().begin();
63 auto thisItE = this->get().end();
64
65 // Find the first entry where the points differ
66 while (*thisIt == *otherIt) {
67 ++thisIt;
68 ++otherIt;
69 if (thisIt == thisItE) {
70 return DominanceResult::Equal;
71 }
72 }
73
74 if (*thisIt > *otherIt) {
75 // *this might dominate other
76 for (++thisIt, ++otherIt; thisIt != thisItE; ++thisIt, ++otherIt) {
77 if (*thisIt < *otherIt) {
78 return DominanceResult::Incomparable;
79 }
80 }
81 return DominanceResult::Dominates;
82 } else {
83 assert(*thisIt < *otherIt);
84 // *this might be dominated by other
85 for (++thisIt, ++otherIt; thisIt != thisItE; ++thisIt, ++otherIt) {
86 if (*thisIt > *otherIt) {
87 return DominanceResult::Incomparable;
88 }
89 }
90 return DominanceResult::Dominated;
91 }
92}
93
94template<class SparseModelType, typename GeometryValueType>
98
99template<class SparseModelType, typename GeometryValueType>
103
104template<class SparseModelType, typename GeometryValueType>
108
109template<class SparseModelType, typename GeometryValueType>
113
114template<class SparseModelType, typename GeometryValueType>
116 std::stringstream out;
117 bool first = true;
118 for (auto const& pi : this->get()) {
119 if (first) {
120 first = false;
121 } else {
122 out << ", ";
123 }
124 if (convertToDouble) {
125 out << storm::utility::convertNumber<double>(pi);
126 } else {
127 out << pi;
128 }
129 }
130 return out.str();
131}
132
133template<class SparseModelType, typename GeometryValueType>
137
138template<class SparseModelType, typename GeometryValueType>
139boost::optional<typename DeterministicSchedsParetoExplorer<SparseModelType, GeometryValueType>::PointId>
141 // Find dominated and dominating points
142 auto pointsIt = points.begin();
143 while (pointsIt != points.end()) {
144 switch (point.getDominance(pointsIt->second)) {
146 // Nothing to be done for this point
147 ++pointsIt;
148 break;
150 if (pointsIt->second.liesOnFacet()) {
151 // Do not erase points that lie on a facet. But flag it as non-optimal.
152 pointsIt->second.setParetoOptimal(false);
153 ++pointsIt;
154 } else {
155 pointsIt = points.erase(pointsIt);
156 }
157 break;
159 // The new point is dominated by another point.
160 return boost::none;
162 if (point.liesOnFacet()) {
163 pointsIt->second.setOnFacet();
164 }
165 return pointsIt->first;
166 }
167 }
168 // This point is not dominated by some other (known) point.
169 point.setParetoOptimal(true);
170
171 if (env.modelchecker().multi().isPrintResultsSet()) {
172 std::cout << "## achievable point: [" << point.toString(true) << "]\n";
173 }
174 points.emplace_hint(points.end(), currId, std::move(point));
175 return currId++;
176}
177
178template<class SparseModelType, typename GeometryValueType>
183
184template<class SparseModelType, typename GeometryValueType>
189
190template<class SparseModelType, typename GeometryValueType>
195
196template<class SparseModelType, typename GeometryValueType>
200
201template<class SparseModelType, typename GeometryValueType>
204 std::vector<std::vector<GeometryValueType>> pointsAsVector;
205 pointsAsVector.reserve(size());
206 for (auto const& p : points) {
207 pointsAsVector.push_back(p.second.get());
208 }
210}
211
212template<class SparseModelType, typename GeometryValueType>
214 Polytope const& polytope) {
215 for (auto const& p : points) {
216 if (polytope->contains(p.second.get())) {
217 collectedPoints.insert(p.first);
218 }
219 }
220}
221
222template<class SparseModelType, typename GeometryValueType>
224 for (auto const& p : this->points) {
225 if (includeIDs) {
226 out << p.first << ": [" << p.second.toString(convertToDouble) << "]\n";
227 } else {
228 out << p.second.toString(convertToDouble) << '\n';
229 }
230 }
231}
232
233template<class SparseModelType, typename GeometryValueType>
238
239template<class SparseModelType, typename GeometryValueType>
244
245template<class SparseModelType, typename GeometryValueType>
250
251template<class SparseModelType, typename GeometryValueType>
253 GeometryValueType product = storm::utility::vector::dotProduct(getHalfspace().normalVector(), point.get());
254 if (product != getHalfspace().offset()) {
255 if (product < getHalfspace().offset()) {
256 STORM_LOG_DEBUG("The point on the facet actually has distance "
257 << storm::utility::convertNumber<double>(getHalfspace().euclideanDistance(point.get())));
258 } else {
259 STORM_LOG_DEBUG("Halfspace of facet is shifted by " << storm::utility::convertNumber<double>(getHalfspace().euclideanDistance(point.get()))
260 << " to capture all points that are supposed to lie on the facet.");
261 halfspace.offset() = product;
262 }
263 }
264 pointsOnFacet.push_back(pointId);
265}
266
267template<class SparseModelType, typename GeometryValueType>
268std::vector<typename DeterministicSchedsParetoExplorer<SparseModelType, GeometryValueType>::PointId> const&
272
273template<class SparseModelType, typename GeometryValueType>
277
278template<class SparseModelType, typename GeometryValueType>
281 std::vector<GeometryValueType> const& referenceCoordinates) {
282 std::vector<std::vector<GeometryValueType>> vertices = {referenceCoordinates};
283 for (auto const& pId : pointsOnFacet) {
284 vertices.push_back(pointset.getPoint(pId).get());
285 }
286 // This facet might lie at the 'border', which means that the downward closure has to be taken in some directions
287 storm::storage::BitVector dimensionsForDownwardClosure = storm::utility::vector::filterZero(this->halfspace.normalVector());
288 STORM_LOG_ASSERT(dimensionsForDownwardClosure.getNumberOfSetBits() + vertices.size() >= halfspace.normalVector().size() + 1,
289 "The number of points on the facet is insufficient");
290 if (dimensionsForDownwardClosure.empty()) {
292 } else {
294 }
295}
296
297template<class SparseModelType, typename GeometryValueType>
300 : model(preprocessorResult.preprocessedModel), objectives(preprocessorResult.objectives) {
301 originalModelInitialState = *preprocessorResult.originalModel.getInitialStates().begin();
302 objectiveHelper.reserve(objectives.size());
303 for (auto const& obj : objectives) {
304 objectiveHelper.emplace_back(*model, obj);
305 STORM_LOG_ASSERT(!objectiveHelper.back().hasThreshold(), "Unexpected input: got a Pareto query with a thresholded objective.");
306 }
307 lpChecker = std::make_shared<DeterministicSchedsLpChecker<SparseModelType, GeometryValueType>>(*model, objectiveHelper);
308 if (preprocessorResult.containsOnlyTotalRewardFormulas()) {
310 } else {
311 wvChecker = nullptr;
312 }
313}
314
315template<class SparseModelType, typename GeometryValueType>
317 clean();
318 for (auto& obj : objectiveHelper) {
319 obj.computeLowerUpperBounds(env);
320 }
321 initializeFacets(env);
322
323 // Compute the relative precision in each dimension.
325 std::vector<GeometryValueType> pmax, pmin;
326 for (auto const& point : pointset) {
327 auto const& coordinates = point.second.get();
328 if (pmax.empty() && pmin.empty()) {
329 pmax = coordinates;
330 pmin = coordinates;
331 } else {
332 for (uint64_t i = 0; i < pmax.size(); ++i) {
333 pmax[i] = std::max(pmax[i], coordinates[i]);
334 pmin[i] = std::min(pmin[i], coordinates[i]);
335 }
336 }
337 }
338 GeometryValueType epsScalingFactor = storm::utility::convertNumber<GeometryValueType>(env.modelchecker().multi().getPrecision());
339 epsScalingFactor += epsScalingFactor;
340 eps.clear();
341 for (uint64_t i = 0; i < pmax.size(); ++i) {
342 eps.push_back((pmax[i] - pmin[i]) * epsScalingFactor);
343 if (eps.back() < storm::utility::convertNumber<GeometryValueType>(1e-8)) {
344 STORM_LOG_WARN("Changing relative precision of objective "
345 << i << " to 1e-8 since the difference between the highest and lowest value is below 1e-8.");
346 eps.back() = storm::utility::convertNumber<GeometryValueType>(1e-8);
347 }
348 }
349 STORM_LOG_INFO("Relative precision for deterministic scheduler Pareto explorer is "
350 << storm::utility::vector::toString(storm::utility::vector::convertNumericVector<double>(eps)) << '\n');
351 } else {
353 storm::exceptions::IllegalArgumentException, "Unknown multiobjective precision type.");
354 auto ei = storm::utility::convertNumber<GeometryValueType>(env.modelchecker().multi().getPrecision());
355 ei += ei;
356 eps = std::vector<GeometryValueType>(objectives.size(), ei);
357 }
358 while (!unprocessedFacets.empty()) {
359 Facet f = std::move(unprocessedFacets.front());
360 unprocessedFacets.pop();
361 processFacet(env, f);
362 }
363
364 std::vector<std::vector<ModelValueType>> paretoPoints;
365 paretoPoints.reserve(pointset.size());
366 for (auto const& p : pointset) {
367 if (p.second.isParetoOptimal()) {
368 paretoPoints.push_back(
369 storm::utility::vector::convertNumericVector<ModelValueType>(transformObjectiveValuesToOriginal(objectives, p.second.get())));
370 }
371 }
372 return std::make_unique<storm::modelchecker::ExplicitParetoCurveCheckResult<ModelValueType>>(originalModelInitialState, std::move(paretoPoints), nullptr,
373 nullptr);
374}
375
376template<class SparseModelType, typename GeometryValueType>
378 pointset = Pointset();
379 unprocessedFacets = std::queue<Facet>();
381 unachievableAreas.clear();
382}
383
384template<class SparseModelType, typename GeometryValueType>
385void DeterministicSchedsParetoExplorer<SparseModelType, GeometryValueType>::addHalfspaceToOverApproximation(Environment const& env,
386 std::vector<GeometryValueType> const& normalVector,
387 GeometryValueType const& offset) {
388 if (env.modelchecker().multi().isPrintResultsSet()) {
389 std::cout << "## overapproximation halfspace: [";
390 bool first = true;
391 for (auto const& xi : normalVector) {
392 if (first) {
393 first = false;
394 } else {
395 std::cout << ",";
396 }
397 std::cout << storm::utility::convertNumber<double>(xi);
398 }
399 std::cout << "];[" << storm::utility::convertNumber<double>(offset) << "]\n";
400 }
401 storm::storage::geometry::Halfspace<GeometryValueType> overApproxHalfspace(normalVector, offset);
402 overApproximation = overApproximation->intersection(overApproxHalfspace);
403}
404
405template<class SparseModelType, typename GeometryValueType>
406void DeterministicSchedsParetoExplorer<SparseModelType, GeometryValueType>::addUnachievableArea(Environment const& env, Polytope const& area) {
407 if (env.modelchecker().multi().isPrintResultsSet()) {
408 std::vector<std::vector<GeometryValueType>> vertices;
409 if (objectives.size() == 2) {
410 vertices = area->getVerticesInClockwiseOrder();
411 } else {
412 vertices = area->getVertices();
413 }
414 std::cout << "## unachievable polytope: ";
415 bool firstVertex = true;
416 for (auto const& v : vertices) {
417 if (firstVertex) {
418 firstVertex = false;
419 } else {
420 std::cout << ";";
421 }
422 std::cout << "[";
423 bool firstEntry = true;
424 for (auto const& vi : v) {
425 if (firstEntry) {
426 firstEntry = false;
427 } else {
428 std::cout << ",";
429 }
430 std::cout << storm::utility::convertNumber<double>(vi);
431 }
432 std::cout << "]";
433 }
434 std::cout << '\n';
435 }
436 unachievableAreas.push_back(area);
437}
438
439template<class SparseModelType, typename GeometryValueType>
441DeterministicSchedsParetoExplorer<SparseModelType, GeometryValueType>::negateMinObjectives(Polytope const& polytope) const {
442 std::vector<GeometryValueType> zeroRow(objectives.size(), storm::utility::zero<GeometryValueType>());
443 std::vector<std::vector<GeometryValueType>> transformationMatrix(objectives.size(), zeroRow);
444 for (uint64_t objIndex = 0; objIndex < objectives.size(); ++objIndex) {
445 if (objectiveHelper[objIndex].minimizing()) {
446 transformationMatrix[objIndex][objIndex] = -storm::utility::one<GeometryValueType>();
447 } else {
448 transformationMatrix[objIndex][objIndex] = storm::utility::one<GeometryValueType>();
449 }
450 }
451 return polytope->affineTransformation(transformationMatrix, zeroRow);
452}
453
454template<class SparseModelType, typename GeometryValueType>
455void DeterministicSchedsParetoExplorer<SparseModelType, GeometryValueType>::negateMinObjectives(std::vector<GeometryValueType>& vector) const {
456 for (uint64_t objIndex = 0; objIndex < this->objectives.size(); ++objIndex) {
457 if (objectiveHelper[objIndex].minimizing()) {
458 vector[objIndex] *= -storm::utility::one<GeometryValueType>();
459 }
460 }
461}
462
463template<class SparseModelType, typename GeometryValueType>
464void DeterministicSchedsParetoExplorer<SparseModelType, GeometryValueType>::initializeFacets(Environment const& env) {
465 for (uint64_t objIndex = 0; objIndex < objectives.size(); ++objIndex) {
466 std::vector<GeometryValueType> weightVector(objectives.size(), storm::utility::zero<GeometryValueType>());
467 weightVector[objIndex] = storm::utility::one<GeometryValueType>();
468 std::vector<GeometryValueType> pointCoord;
469 GeometryValueType offset;
470 if (wvChecker) {
471 wvChecker->check(env, storm::utility::vector::convertNumericVector<ModelValueType>(weightVector));
472 pointCoord = storm::utility::vector::convertNumericVector<GeometryValueType>(wvChecker->getUnderApproximationOfInitialStateResults());
473 negateMinObjectives(pointCoord);
474 auto upperBoundPoint = storm::utility::vector::convertNumericVector<GeometryValueType>(wvChecker->getOverApproximationOfInitialStateResults());
475 negateMinObjectives(upperBoundPoint);
476 offset = storm::utility::vector::dotProduct(weightVector, upperBoundPoint);
477 } else {
478 lpChecker->setCurrentWeightVector(env, weightVector);
479 auto optionalPoint = lpChecker->check(env, overApproximation);
480 STORM_LOG_THROW(optionalPoint.has_value(), storm::exceptions::UnexpectedException, "Unable to find a point in the current overapproximation.");
481 pointCoord = std::move(optionalPoint->first);
482 offset = std::move(optionalPoint->second);
483 }
484 Point p(pointCoord);
485 p.setOnFacet();
486 // Adapt the overapproximation
487 addHalfspaceToOverApproximation(env, weightVector, offset);
488 pointset.addPoint(env, std::move(p));
489 }
490
491 auto initialHalfspaces = pointset.downwardClosure()->getHalfspaces();
492 for (auto& h : initialHalfspaces) {
493 Facet f(std::move(h));
494 for (auto const& p : pointset) {
495 if (f.getHalfspace().isPointOnBoundary(p.second.get())) {
496 f.addPoint(p.first, p.second);
497 }
498 }
499 STORM_LOG_ASSERT(std::count(f.getHalfspace().normalVector().begin(), f.getHalfspace().normalVector().end(), storm::utility::zero<GeometryValueType>()) +
500 f.getNumberOfPoints() >=
501 objectives.size(),
502 "Not enough points on facet.");
503
504 unprocessedFacets.push(std::move(f));
505 }
506}
507
508template<class SparseModelType, typename GeometryValueType>
509std::vector<GeometryValueType> DeterministicSchedsParetoExplorer<SparseModelType, GeometryValueType>::getReferenceCoordinates(Environment const& env) const {
510 std::vector<GeometryValueType> result;
511 for (uint64_t objIndex = 0; objIndex < objectives.size(); ++objIndex) {
512 result.push_back(
513 storm::utility::convertNumber<GeometryValueType>(objectiveHelper[objIndex].getLowerValueBoundAtState(*model->getInitialStates().begin())));
514 }
515 return result;
516}
517
518template<class SparseModelType, typename GeometryValueType>
519void DeterministicSchedsParetoExplorer<SparseModelType, GeometryValueType>::processFacet(Environment const& env, Facet& f) {
520 if (!wvChecker) {
521 lpChecker->setCurrentWeightVector(env, f.getHalfspace().normalVector());
522 }
523
524 if (optimizeAndSplitFacet(env, f)) {
525 return;
526 }
527
528 storm::storage::geometry::PolytopeTree<GeometryValueType> polytopeTree(f.getInducedPolytope(pointset, getReferenceCoordinates(env)));
529 for (auto const& point : pointset) {
530 polytopeTree.substractDownwardClosure(point.second.get(), eps);
531 if (polytopeTree.isEmpty()) {
532 break;
533 }
534 }
535 if (!polytopeTree.isEmpty()) {
536 if (wvChecker) {
537 lpChecker->setCurrentWeightVector(env, f.getHalfspace().normalVector());
538 }
539 auto res = lpChecker->check(env, polytopeTree, eps);
540 for (auto const& infeasableArea : res.second) {
541 addUnachievableArea(env, infeasableArea);
542 }
543 for (auto& achievablePoint : res.first) {
544 pointset.addPoint(env, Point(std::move(achievablePoint)));
545 }
546 }
547}
548
549template<typename GeometryValueType>
550bool closePoints(std::vector<GeometryValueType> const& first, std::vector<GeometryValueType> const& second, GeometryValueType const& maxDistance) {
551 for (uint64_t i = 0; i < first.size(); ++i) {
552 if (storm::utility::abs<GeometryValueType>(first[i] - second[i]) > maxDistance) {
553 return false;
554 }
555 }
556 return true;
557}
558
559template<class SparseModelType, typename GeometryValueType>
560bool DeterministicSchedsParetoExplorer<SparseModelType, GeometryValueType>::optimizeAndSplitFacet(Environment const& env, Facet& f) {
561 // Invoke optimization and insert the explored points
562 boost::optional<PointId> optPointId;
563 std::vector<GeometryValueType> pointCoord;
564 GeometryValueType offset;
565 if (wvChecker) {
566 wvChecker->check(env, storm::utility::vector::convertNumericVector<ModelValueType>(f.getHalfspace().normalVector()));
567 pointCoord = storm::utility::vector::convertNumericVector<GeometryValueType>(wvChecker->getUnderApproximationOfInitialStateResults());
568 negateMinObjectives(pointCoord);
569 auto upperBoundPoint = storm::utility::vector::convertNumericVector<GeometryValueType>(wvChecker->getOverApproximationOfInitialStateResults());
570 negateMinObjectives(upperBoundPoint);
571 offset = storm::utility::vector::dotProduct(f.getHalfspace().normalVector(), upperBoundPoint);
572 } else {
573 auto currentArea = overApproximation->intersection(f.getHalfspace().invert());
574 auto optionalPoint = lpChecker->check(env, overApproximation, eps);
575 if (optionalPoint.has_value()) {
576 pointCoord = std::move(optionalPoint->first);
577 } else {
578 // As we did not find any feasable solution in the given area, we take a point that lies on the facet
579 pointCoord = pointset.getPoint(f.getPoints().front()).get();
580 }
581 offset = std::move(optionalPoint->second);
582 }
583
584 Point p(pointCoord);
585 p.setOnFacet();
586 addHalfspaceToOverApproximation(env, f.getHalfspace().normalVector(), offset);
587 optPointId = pointset.addPoint(env, std::move(p));
588
589 // Potentially generate new facets
590 if (optPointId) {
591 auto const& optPoint = pointset.getPoint(*optPointId);
592 if (f.getHalfspace().contains(optPoint.get())) {
593 // The point is contained in the halfspace which means that no more splitting is possible.
594 return false;
595 } else {
596 // Collect the new point with its neighbors.
597 // Also check whether the remamining area is already sufficiently small.
598 storm::storage::geometry::PolytopeTree<GeometryValueType> remainingArea(overApproximation->intersection(f.getHalfspace().invert()));
599 std::vector<std::vector<GeometryValueType>> vertices;
600 vertices.push_back(optPoint.get());
601 auto minmaxPrec = storm::utility::convertNumber<GeometryValueType>(env.solver().minMax().getPrecision());
602 minmaxPrec += minmaxPrec;
603 for (auto const& pId : f.getPoints()) {
604 vertices.push_back(pointset.getPoint(pId).get());
605 remainingArea.substractDownwardClosure(vertices.back(), eps);
606 STORM_LOG_WARN_COND((std::is_same<ModelValueType, storm::RationalNumber>::value) || !closePoints(vertices.front(), vertices.back(), minmaxPrec),
607 "Found Pareto optimal points that are close to each other. This can be due to numerical issues. Maybe try exact mode?");
608 }
609 if (remainingArea.isEmpty()) {
610 return false;
611 }
612
613 // We need to generate new facets
615 vertices, storm::utility::vector::filterZero(f.getHalfspace().normalVector()))
616 ->getHalfspaces();
617 for (auto& h : newHalfspaceCandidates) {
618 if (!storm::utility::vector::hasNegativeEntry(h.normalVector())) {
619 STORM_LOG_ASSERT(h.isPointOnBoundary(optPoint.get()), "Unexpected facet found while splitting.");
620 Facet fNew(std::move(h));
621 fNew.addPoint(optPointId.get(), optPoint);
622 auto vertexIt = vertices.begin();
623 ++vertexIt;
624 for (auto const& pId : f.getPoints()) {
625 assert(pointset.getPoint(pId).get() == *vertexIt);
626 if (fNew.getHalfspace().isPointOnBoundary(*vertexIt)) {
627 fNew.addPoint(pId, pointset.getPoint(pId));
628 }
629 ++vertexIt;
630 }
631 assert(vertexIt == vertices.end());
632 unprocessedFacets.push(std::move(fNew));
633 }
634 }
635 return true;
636 }
637 } else {
638 // If the 'optimal point' was dominated by an existing point, we can not split the facet any further.
639 return false;
640 }
641}
642
643template<class SparseModelType, typename GeometryValueType>
645 /*
646 STORM_LOG_ERROR_COND(objectives.size()==2, "Exporting plot requested but this is only implemented for the two-dimensional case.");
647
648 auto transformedUnderApprox = transformPolytopeToOriginalModel(underApproximation);
649 auto transformedOverApprox = transformPolytopeToOriginalModel(overApproximation);
650
651 // Get pareto points as well as a hyperrectangle that is used to guarantee that the resulting polytopes are bounded.
652 storm::storage::geometry::Hyperrectangle<GeometryValueType> boundaries(std::vector<GeometryValueType>(objectives.size(),
653storm::utility::zero<GeometryValueType>()), std::vector<GeometryValueType>(objectives.size(), storm::utility::zero<GeometryValueType>()));
654 std::vector<std::vector<GeometryValueType>> paretoPoints;
655 paretoPoints.reserve(refinementSteps.size());
656 for(auto const& step : refinementSteps) {
657 paretoPoints.push_back(transformPointToOriginalModel(step.lowerBoundPoint));
658 boundaries.enlarge(paretoPoints.back());
659 }
660 auto underApproxVertices = transformedUnderApprox->getVertices();
661 for(auto const& v : underApproxVertices) {
662 boundaries.enlarge(v);
663 }
664 auto overApproxVertices = transformedOverApprox->getVertices();
665 for(auto const& v : overApproxVertices) {
666 boundaries.enlarge(v);
667 }
668
669 //Further enlarge the boundaries a little
670 storm::utility::vector::scaleVectorInPlace(boundaries.lowerBounds(), GeometryValueType(15) / GeometryValueType(10));
671 storm::utility::vector::scaleVectorInPlace(boundaries.upperBounds(), GeometryValueType(15) / GeometryValueType(10));
672
673 auto boundariesAsPolytope = boundaries.asPolytope();
674 std::vector<std::string> columnHeaders = {"x", "y"};
675
676 std::vector<std::vector<double>> pointsForPlotting;
677 if (env.modelchecker().multi().getPlotPathUnderApproximation()) {
678 underApproxVertices = transformedUnderApprox->intersection(boundariesAsPolytope)->getVerticesInClockwiseOrder();
679 pointsForPlotting.reserve(underApproxVertices.size());
680 for(auto const& v : underApproxVertices) {
681 pointsForPlotting.push_back(storm::utility::vector::convertNumericVector<double>(v));
682 }
683 storm::io::exportDataToCSVFile<double, std::string>(env.modelchecker().multi().getPlotPathUnderApproximation().get(), pointsForPlotting,
684columnHeaders);
685 }
686
687 if (env.modelchecker().multi().getPlotPathOverApproximation()) {
688 pointsForPlotting.clear();
689 overApproxVertices = transformedOverApprox->intersection(boundariesAsPolytope)->getVerticesInClockwiseOrder();
690 pointsForPlotting.reserve(overApproxVertices.size());
691 for(auto const& v : overApproxVertices) {
692 pointsForPlotting.push_back(storm::utility::vector::convertNumericVector<double>(v));
693 }
694 storm::io::exportDataToCSVFile<double, std::string>(env.modelchecker().multi().getPlotPathOverApproximation().get(), pointsForPlotting,
695columnHeaders);
696 }
697
698 if (env.modelchecker().multi().getPlotPathParetoPoints()) {
699 pointsForPlotting.clear();
700 pointsForPlotting.reserve(paretoPoints.size());
701 for(auto const& v : paretoPoints) {
702 pointsForPlotting.push_back(storm::utility::vector::convertNumericVector<double>(v));
703 }
704 storm::io::exportDataToCSVFile<double, std::string>(env.modelchecker().multi().getPlotPathParetoPoints().get(), pointsForPlotting, columnHeaders);
705 }
706};
707 */
708}
709
714} // namespace multiobjective
715} // namespace modelchecker
716} // namespace storm
SolverEnvironment & solver()
ModelCheckerEnvironment & modelchecker()
storm::RationalNumber const & getPrecision() const
MultiObjectiveModelCheckerEnvironment & multi()
MinMaxSolverEnvironment & minMax()
storm::storage::geometry::Halfspace< GeometryValueType > const & getHalfspace() const
Polytope getInducedPolytope(Pointset const &pointset, std::vector< GeometryValueType > const &referenceCoordinates)
Creates a polytope that captures all points that lie 'under' the facet.
Facet(storm::storage::geometry::Halfspace< GeometryValueType > const &halfspace)
void printToStream(std::ostream &out, bool includeIDs=true, bool convertToDouble=false)
Polytope downwardClosure() const
Returns the downward closure of the contained points.
Point const & getPoint(PointId const &id) const
Returns the point with the given ID.
void collectPointsInPolytope(std::set< PointId > &collectedPoints, Polytope const &polytope)
uint64_t size() const
Returns the number of points currently contained in the set.
boost::optional< PointId > addPoint(Environment const &env, Point &&point)
If the given point is not dominated by another point in the set, it is added to the set and its ID is...
virtual std::unique_ptr< CheckResult > check(Environment const &env)
DeterministicSchedsParetoExplorer(preprocessing::SparseMultiObjectivePreprocessorResult< SparseModelType > &preprocessorResult)
std::shared_ptr< storm::storage::geometry::Polytope< GeometryValueType > > Polytope
static std::unique_ptr< PcaaWeightVectorChecker< ModelType > > create(preprocessing::SparseMultiObjectivePreprocessorResult< ModelType > const &preprocessorResult)
A bit vector that is internally represented as a vector of 64-bit values.
Definition BitVector.h:18
bool empty() const
Retrieves whether no bits are set to true in this bit vector.
uint_fast64_t getNumberOfSetBits() const
Returns the number of bits that are set to true in this bit vector.
static std::shared_ptr< Polytope< ValueType > > createDownwardClosure(std::vector< Point > const &points)
Creates the downward closure of the given points (i.e., the set { x | ex.
Definition Polytope.cpp:43
static std::shared_ptr< Polytope< ValueType > > create(std::vector< Halfspace< ValueType > > const &halfspaces)
Creates a polytope from the given halfspaces.
static std::shared_ptr< Polytope< ValueType > > createUniversalPolytope()
Creates the universal polytope (i.e., the set R^n)
Definition Polytope.cpp:27
static std::shared_ptr< Polytope< ValueType > > createSelectiveDownwardClosure(std::vector< Point > const &points, storm::storage::BitVector const &selectedDimensions)
Creates the downward closure of the given points but only with respect to the selected dimensions,...
Definition Polytope.cpp:54
Represents a set of points in Euclidean space.
#define STORM_LOG_INFO(message)
Definition logging.h:29
#define STORM_LOG_WARN(message)
Definition logging.h:30
#define STORM_LOG_DEBUG(message)
Definition logging.h:23
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:11
#define STORM_LOG_WARN_COND(cond, message)
Definition macros.h:38
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
std::vector< GeometryValueType > transformObjectiveValuesToOriginal(std::vector< Objective< ValueType > > objectives, std::vector< GeometryValueType > const &point)
bool closePoints(std::vector< GeometryValueType > const &first, std::vector< GeometryValueType > const &second, GeometryValueType const &maxDistance)
T dotProduct(std::vector< T > const &firstOperand, std::vector< T > const &secondOperand)
Computes the dot product (aka scalar product) and returns the result.
Definition vector.h:517
std::string toString(std::vector< ValueType > const &vector)
Output vector as string.
Definition vector.h:1298
bool hasNegativeEntry(std::vector< T > const &v)
Definition vector.h:1242
storm::storage::BitVector filterZero(std::vector< T > const &values)
Retrieves a bit vector containing all the indices for which the value at this position is equal to ze...
Definition vector.h:563
LabParser.cpp.
Definition cli.cpp:18