Storm 1.14.0.1
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
15#include "storm/io/export.h"
17
21
22namespace storm {
23namespace modelchecker {
24namespace multiobjective {
25
26template<class SparseModelType, typename GeometryValueType>
28 : coordinates(coordinates), onFacet(false), paretoOptimal(false) {
29 STORM_LOG_ASSERT(!this->coordinates.empty(), "Points with dimension 0 are not supported.");
30}
31
32template<class SparseModelType, typename GeometryValueType>
34 : coordinates(std::move(coordinates)), onFacet(false), paretoOptimal(false) {
35 STORM_LOG_ASSERT(!this->coordinates.empty(), "Points with dimension 0 are not supported.");
36}
37
38template<class SparseModelType, typename GeometryValueType>
40 return coordinates;
41}
42
43template<class SparseModelType, typename GeometryValueType>
45 return coordinates;
46}
47
48template<class SparseModelType, typename GeometryValueType>
50 STORM_LOG_ASSERT(!coordinates.empty(), "Points with dimension 0 are not supported.");
51 return coordinates.size();
52}
53
54template<class SparseModelType, typename GeometryValueType>
57 STORM_LOG_ASSERT(this->dimension() == other.dimension(), "Non-Equal dimensions of points: [" << this->toString() << "] vs. [" << other.toString() << "]");
58 auto thisIt = this->get().begin();
59 auto otherIt = other.get().begin();
60 auto thisItE = this->get().end();
61
62 // Find the first entry where the points differ
63 while (*thisIt == *otherIt) {
64 ++thisIt;
65 ++otherIt;
66 if (thisIt == thisItE) {
68 }
69 }
70
71 if (*thisIt > *otherIt) {
72 // *this might dominate other
73 for (++thisIt, ++otherIt; thisIt != thisItE; ++thisIt, ++otherIt) {
74 if (*thisIt < *otherIt) {
76 }
77 }
79 } else {
80 STORM_LOG_ASSERT(*thisIt < *otherIt, "Expected iterator value less than other.");
81 // *this might be dominated by other
82 for (++thisIt, ++otherIt; thisIt != thisItE; ++thisIt, ++otherIt) {
83 if (*thisIt > *otherIt) {
85 }
86 }
88 }
89}
90
91template<class SparseModelType, typename GeometryValueType>
95
96template<class SparseModelType, typename GeometryValueType>
100
101template<class SparseModelType, typename GeometryValueType>
105
106template<class SparseModelType, typename GeometryValueType>
110
111template<class SparseModelType, typename GeometryValueType>
113 std::stringstream out;
114 bool first = true;
115 for (auto const& pi : this->get()) {
116 if (first) {
117 first = false;
118 } else {
119 out << ", ";
120 }
121 if (convertToDouble) {
122 out << storm::utility::convertNumber<double>(pi);
123 } else {
124 out << pi;
125 }
126 }
127 return out.str();
128}
129
130template<class SparseModelType, typename GeometryValueType>
134
135template<class SparseModelType, typename GeometryValueType>
136boost::optional<typename DeterministicSchedsParetoExplorer<SparseModelType, GeometryValueType>::PointId>
138 // Find dominated and dominating points
139 auto pointsIt = points.begin();
140 while (pointsIt != points.end()) {
141 switch (point.getDominance(pointsIt->second)) {
143 // Nothing to be done for this point
144 ++pointsIt;
145 break;
147 if (pointsIt->second.liesOnFacet()) {
148 // Do not erase points that lie on a facet. But flag it as non-optimal.
149 pointsIt->second.setParetoOptimal(false);
150 ++pointsIt;
151 } else {
152 pointsIt = points.erase(pointsIt);
153 }
154 break;
156 // The new point is dominated by another point.
157 return boost::none;
159 if (point.liesOnFacet()) {
160 pointsIt->second.setOnFacet();
161 }
162 return pointsIt->first;
163 }
164 }
165 // This point is not dominated by some other (known) point.
166 point.setParetoOptimal(true);
167
168 if (env.modelchecker().multi().isPrintResultsSet()) {
169 std::cout << "## achievable point: [" << point.toString(true) << "]\n";
170 }
171 points.emplace_hint(points.end(), currId, std::move(point));
172 return currId++;
173}
174
175template<class SparseModelType, typename GeometryValueType>
180
181template<class SparseModelType, typename GeometryValueType>
186
187template<class SparseModelType, typename GeometryValueType>
192
193template<class SparseModelType, typename GeometryValueType>
197
198template<class SparseModelType, typename GeometryValueType>
201 std::vector<std::vector<GeometryValueType>> pointsAsVector;
202 pointsAsVector.reserve(size());
203 for (auto const& p : points) {
204 pointsAsVector.push_back(p.second.get());
205 }
207}
208
209template<class SparseModelType, typename GeometryValueType>
211 Polytope const& polytope) {
212 for (auto const& p : points) {
213 if (polytope->contains(p.second.get())) {
214 collectedPoints.insert(p.first);
215 }
216 }
217}
218
219template<class SparseModelType, typename GeometryValueType>
221 for (auto const& p : this->points) {
222 if (includeIDs) {
223 out << p.first << ": [" << p.second.toString(convertToDouble) << "]\n";
224 } else {
225 out << p.second.toString(convertToDouble) << '\n';
226 }
227 }
228}
229
230template<class SparseModelType, typename GeometryValueType>
235
236template<class SparseModelType, typename GeometryValueType>
241
242template<class SparseModelType, typename GeometryValueType>
247
248template<class SparseModelType, typename GeometryValueType>
250 GeometryValueType product = storm::utility::vector::dotProduct(getHalfspace().normalVector(), point.get());
251 if (product != getHalfspace().offset()) {
252 if (product < getHalfspace().offset()) {
253 STORM_LOG_DEBUG("The point on the facet actually has distance "
254 << storm::utility::convertNumber<double>(getHalfspace().euclideanDistance(point.get())));
255 } else {
256 STORM_LOG_DEBUG("Halfspace of facet is shifted by " << storm::utility::convertNumber<double>(getHalfspace().euclideanDistance(point.get()))
257 << " to capture all points that are supposed to lie on the facet.");
258 halfspace.offset() = product;
259 }
260 }
261 pointsOnFacet.push_back(pointId);
262}
263
264template<class SparseModelType, typename GeometryValueType>
265std::vector<typename DeterministicSchedsParetoExplorer<SparseModelType, GeometryValueType>::PointId> const&
269
270template<class SparseModelType, typename GeometryValueType>
274
275template<class SparseModelType, typename GeometryValueType>
278 std::vector<GeometryValueType> const& referenceCoordinates) {
279 std::vector<std::vector<GeometryValueType>> vertices = {referenceCoordinates};
280 for (auto const& pId : pointsOnFacet) {
281 vertices.push_back(pointset.getPoint(pId).get());
282 }
283 // This facet might lie at the 'border', which means that the downward closure has to be taken in some directions
284 storm::storage::BitVector dimensionsForDownwardClosure = storm::utility::vector::filterZero(this->halfspace.normalVector());
285 STORM_LOG_ASSERT(dimensionsForDownwardClosure.getNumberOfSetBits() + vertices.size() >= halfspace.normalVector().size() + 1,
286 "The number of points on the facet is insufficient.");
287 if (dimensionsForDownwardClosure.empty()) {
289 } else {
291 }
292}
293
294template<class SparseModelType, typename GeometryValueType>
297 : model(preprocessorResult.preprocessedModel), objectives(preprocessorResult.objectives) {
298 originalModelInitialState = *preprocessorResult.originalModel.getInitialStates().begin();
299 objectiveHelper.reserve(objectives.size());
300 for (auto const& obj : objectives) {
301 objectiveHelper.emplace_back(*model, obj);
302 STORM_LOG_ASSERT(!objectiveHelper.back().hasThreshold(), "Unexpected input: got a Pareto query with a thresholded objective.");
303 }
304 lpChecker = std::make_shared<DeterministicSchedsLpChecker<SparseModelType, GeometryValueType>>(*model, objectiveHelper);
305 if (preprocessorResult.containsOnlyTotalRewardFormulas()) {
306 wvChecker = storm::modelchecker::multiobjective::createWeightVectorChecker(preprocessorResult);
307 } else {
308 wvChecker = nullptr;
309 }
310}
311
312template<class SparseModelType, typename GeometryValueType>
314 clean();
315 for (auto& obj : objectiveHelper) {
316 obj.computeLowerUpperBounds(env);
317 }
318 initializeFacets(env);
319
320 // Compute the relative precision in each dimension.
322 std::vector<GeometryValueType> pmax, pmin;
323 for (auto const& point : pointset) {
324 auto const& coordinates = point.second.get();
325 if (pmax.empty() && pmin.empty()) {
326 pmax = coordinates;
327 pmin = coordinates;
328 } else {
329 for (uint64_t i = 0; i < pmax.size(); ++i) {
330 pmax[i] = std::max(pmax[i], coordinates[i]);
331 pmin[i] = std::min(pmin[i], coordinates[i]);
332 }
333 }
334 }
335 GeometryValueType epsScalingFactor = storm::utility::convertNumber<GeometryValueType>(env.modelchecker().multi().getPrecision());
336 epsScalingFactor += epsScalingFactor;
337 eps.clear();
338 for (uint64_t i = 0; i < pmax.size(); ++i) {
339 eps.push_back((pmax[i] - pmin[i]) * epsScalingFactor);
341 STORM_LOG_WARN("Changing relative precision of objective "
342 << i << " to 1e-8 since the difference between the highest and lowest value is below 1e-8.");
344 }
345 }
346 STORM_LOG_INFO("Relative precision for deterministic scheduler Pareto explorer is "
348 } else {
350 storm::exceptions::IllegalArgumentException, "Unknown multiobjective precision type.");
352 ei += ei;
353 eps = std::vector<GeometryValueType>(objectives.size(), ei);
354 }
355 while (!unprocessedFacets.empty()) {
356 Facet f = std::move(unprocessedFacets.front());
357 unprocessedFacets.pop();
358 processFacet(env, f);
359 }
360
361 std::vector<std::vector<ModelValueType>> paretoPoints;
362 paretoPoints.reserve(pointset.size());
363 for (auto const& p : pointset) {
364 if (p.second.isParetoOptimal()) {
365 paretoPoints.push_back(
367 }
368 }
369 return std::make_unique<storm::modelchecker::ExplicitParetoCurveCheckResult<ModelValueType>>(originalModelInitialState, std::move(paretoPoints), nullptr,
370 nullptr);
371}
372
373template<class SparseModelType, typename GeometryValueType>
374void DeterministicSchedsParetoExplorer<SparseModelType, GeometryValueType>::clean() {
375 pointset = Pointset();
376 unprocessedFacets = std::queue<Facet>();
378 unachievableAreas.clear();
379}
380
381template<class SparseModelType, typename GeometryValueType>
382void DeterministicSchedsParetoExplorer<SparseModelType, GeometryValueType>::addHalfspaceToOverApproximation(Environment const& env,
383 std::vector<GeometryValueType> const& normalVector,
384 GeometryValueType const& offset) {
385 if (env.modelchecker().multi().isPrintResultsSet()) {
386 std::cout << "## overapproximation halfspace: [";
387 bool first = true;
388 for (auto const& xi : normalVector) {
389 if (first) {
390 first = false;
391 } else {
392 std::cout << ",";
393 }
394 std::cout << storm::utility::convertNumber<double>(xi);
395 }
396 std::cout << "];[" << storm::utility::convertNumber<double>(offset) << "]\n";
397 }
398 storm::storage::geometry::Halfspace<GeometryValueType> overApproxHalfspace(normalVector, offset);
399 overApproximation = overApproximation->intersection(overApproxHalfspace);
400}
401
402template<class SparseModelType, typename GeometryValueType>
403void DeterministicSchedsParetoExplorer<SparseModelType, GeometryValueType>::addUnachievableArea(Environment const& env, Polytope const& area) {
404 if (env.modelchecker().multi().isPrintResultsSet()) {
405 std::vector<std::vector<GeometryValueType>> vertices;
406 if (objectives.size() == 2) {
407 vertices = area->getVerticesInClockwiseOrder();
408 } else {
409 vertices = area->getVertices();
410 }
411 std::cout << "## unachievable polytope: ";
412 bool firstVertex = true;
413 for (auto const& v : vertices) {
414 if (firstVertex) {
415 firstVertex = false;
416 } else {
417 std::cout << ";";
418 }
419 std::cout << "[";
420 bool firstEntry = true;
421 for (auto const& vi : v) {
422 if (firstEntry) {
423 firstEntry = false;
424 } else {
425 std::cout << ",";
426 }
427 std::cout << storm::utility::convertNumber<double>(vi);
428 }
429 std::cout << "]";
430 }
431 std::cout << '\n';
432 }
433 unachievableAreas.push_back(area);
434}
435
436template<class SparseModelType, typename GeometryValueType>
438DeterministicSchedsParetoExplorer<SparseModelType, GeometryValueType>::negateMinObjectives(Polytope const& polytope) const {
439 std::vector<GeometryValueType> zeroRow(objectives.size(), storm::utility::zero<GeometryValueType>());
440 std::vector<std::vector<GeometryValueType>> transformationMatrix(objectives.size(), zeroRow);
441 for (uint64_t objIndex = 0; objIndex < objectives.size(); ++objIndex) {
442 if (objectiveHelper[objIndex].minimizing()) {
443 transformationMatrix[objIndex][objIndex] = -storm::utility::one<GeometryValueType>();
444 } else {
445 transformationMatrix[objIndex][objIndex] = storm::utility::one<GeometryValueType>();
446 }
447 }
448 return polytope->affineTransformation(transformationMatrix, zeroRow);
449}
450
451template<class SparseModelType, typename GeometryValueType>
452void DeterministicSchedsParetoExplorer<SparseModelType, GeometryValueType>::negateMinObjectives(std::vector<GeometryValueType>& vector) const {
453 for (uint64_t objIndex = 0; objIndex < this->objectives.size(); ++objIndex) {
454 if (objectiveHelper[objIndex].minimizing()) {
455 vector[objIndex] *= -storm::utility::one<GeometryValueType>();
456 }
457 }
458}
459
460template<class SparseModelType, typename GeometryValueType>
461void DeterministicSchedsParetoExplorer<SparseModelType, GeometryValueType>::initializeFacets(Environment const& env) {
462 for (uint64_t objIndex = 0; objIndex < objectives.size(); ++objIndex) {
463 std::vector<GeometryValueType> weightVector(objectives.size(), storm::utility::zero<GeometryValueType>());
464 weightVector[objIndex] = storm::utility::one<GeometryValueType>();
465 std::vector<GeometryValueType> pointCoord;
466 GeometryValueType offset;
467 if (wvChecker) {
468 wvChecker->setWeightedPrecision(storm::utility::convertNumber<ModelValueType>(env.solver().minMax().getPrecision()));
469 wvChecker->check(env, storm::utility::vector::convertNumericVector<ModelValueType>(weightVector));
470 pointCoord = storm::utility::vector::convertNumericVector<GeometryValueType>(wvChecker->getAchievablePoint());
471 negateMinObjectives(pointCoord);
472 offset = storm::utility::convertNumber<GeometryValueType>(wvChecker->getOptimalWeightedSum());
473 } else {
474 lpChecker->setCurrentWeightVector(env, weightVector);
475 auto optionalPoint = lpChecker->check(env, overApproximation);
476 STORM_LOG_THROW(optionalPoint.has_value(), storm::exceptions::UnexpectedException, "Unable to find a point in the current overapproximation.");
477 pointCoord = std::move(optionalPoint->first);
478 offset = std::move(optionalPoint->second);
479 }
480 Point p(pointCoord);
481 p.setOnFacet();
482 // Adapt the overapproximation
483 addHalfspaceToOverApproximation(env, weightVector, offset);
484 pointset.addPoint(env, std::move(p));
485 }
486
487 auto initialHalfspaces = pointset.downwardClosure()->getHalfspaces();
488 for (auto& h : initialHalfspaces) {
489 Facet f(std::move(h));
490 for (auto const& p : pointset) {
491 if (f.getHalfspace().isPointOnBoundary(p.second.get())) {
492 f.addPoint(p.first, p.second);
493 }
494 }
495 STORM_LOG_ASSERT(std::count(f.getHalfspace().normalVector().begin(), f.getHalfspace().normalVector().end(), storm::utility::zero<GeometryValueType>()) +
496 f.getNumberOfPoints() >=
497 objectives.size(),
498 "Not enough points on facet.");
499
500 unprocessedFacets.push(std::move(f));
501 }
502}
503
504template<class SparseModelType, typename GeometryValueType>
505std::vector<GeometryValueType> DeterministicSchedsParetoExplorer<SparseModelType, GeometryValueType>::getReferenceCoordinates(Environment const& env) const {
506 std::vector<GeometryValueType> result;
507 for (uint64_t objIndex = 0; objIndex < objectives.size(); ++objIndex) {
508 result.push_back(
509 storm::utility::convertNumber<GeometryValueType>(objectiveHelper[objIndex].getLowerValueBoundAtState(*model->getInitialStates().begin())));
510 }
511 return result;
512}
513
514template<class SparseModelType, typename GeometryValueType>
515void DeterministicSchedsParetoExplorer<SparseModelType, GeometryValueType>::processFacet(Environment const& env, Facet& f) {
516 if (!wvChecker) {
517 lpChecker->setCurrentWeightVector(env, f.getHalfspace().normalVector());
518 }
519
520 if (optimizeAndSplitFacet(env, f)) {
521 return;
522 }
523
524 storm::storage::geometry::PolytopeTree<GeometryValueType> polytopeTree(f.getInducedPolytope(pointset, getReferenceCoordinates(env)));
525 for (auto const& point : pointset) {
526 polytopeTree.substractDownwardClosure(point.second.get(), eps);
527 if (polytopeTree.isEmpty()) {
528 break;
529 }
530 }
531 if (!polytopeTree.isEmpty()) {
532 if (wvChecker) {
533 lpChecker->setCurrentWeightVector(env, f.getHalfspace().normalVector());
534 }
535 auto res = lpChecker->check(env, polytopeTree, eps);
536 for (auto const& infeasableArea : res.second) {
537 addUnachievableArea(env, infeasableArea);
538 }
539 for (auto& achievablePoint : res.first) {
540 pointset.addPoint(env, Point(std::move(achievablePoint)));
541 }
542 }
543}
544
545template<typename GeometryValueType>
546bool closePoints(std::vector<GeometryValueType> const& first, std::vector<GeometryValueType> const& second, GeometryValueType const& maxDistance) {
547 for (uint64_t i = 0; i < first.size(); ++i) {
548 if (storm::utility::abs<GeometryValueType>(first[i] - second[i]) > maxDistance) {
549 return false;
550 }
551 }
552 return true;
553}
554
555template<class SparseModelType, typename GeometryValueType>
556bool DeterministicSchedsParetoExplorer<SparseModelType, GeometryValueType>::optimizeAndSplitFacet(Environment const& env, Facet& f) {
557 // Invoke optimization and insert the explored points
558 boost::optional<PointId> optPointId;
559 std::vector<GeometryValueType> pointCoord;
560 GeometryValueType offset;
561 if (wvChecker) {
562 wvChecker->setWeightedPrecision(storm::utility::convertNumber<ModelValueType>(env.solver().minMax().getPrecision()));
563 wvChecker->check(env, storm::utility::vector::convertNumericVector<ModelValueType>(f.getHalfspace().normalVector()));
564 pointCoord = storm::utility::vector::convertNumericVector<GeometryValueType>(wvChecker->getAchievablePoint());
565 negateMinObjectives(pointCoord);
566 offset = storm::utility::convertNumber<GeometryValueType>(wvChecker->getOptimalWeightedSum());
567 } else {
568 auto currentArea = overApproximation->intersection(f.getHalfspace().invert());
569 auto optionalPoint = lpChecker->check(env, overApproximation, eps);
570 if (optionalPoint.has_value()) {
571 pointCoord = std::move(optionalPoint->first);
572 } else {
573 // As we did not find any feasable solution in the given area, we take a point that lies on the facet
574 pointCoord = pointset.getPoint(f.getPoints().front()).get();
575 }
576 offset = std::move(optionalPoint->second);
577 }
578
579 Point p(pointCoord);
580 p.setOnFacet();
581 addHalfspaceToOverApproximation(env, f.getHalfspace().normalVector(), offset);
582 optPointId = pointset.addPoint(env, std::move(p));
583
584 // Potentially generate new facets
585 if (optPointId) {
586 auto const& optPoint = pointset.getPoint(*optPointId);
587 if (f.getHalfspace().contains(optPoint.get())) {
588 // The point is contained in the halfspace which means that no more splitting is possible.
589 return false;
590 } else {
591 // Collect the new point with its neighbors.
592 // Also check whether the remamining area is already sufficiently small.
593 storm::storage::geometry::PolytopeTree<GeometryValueType> remainingArea(overApproximation->intersection(f.getHalfspace().invert()));
594 std::vector<std::vector<GeometryValueType>> vertices;
595 vertices.push_back(optPoint.get());
597 minmaxPrec += minmaxPrec;
598 for (auto const& pId : f.getPoints()) {
599 vertices.push_back(pointset.getPoint(pId).get());
600 remainingArea.substractDownwardClosure(vertices.back(), eps);
601 STORM_LOG_WARN_COND((std::is_same<ModelValueType, storm::RationalNumber>::value) || !closePoints(vertices.front(), vertices.back(), minmaxPrec),
602 "Found Pareto optimal points that are close to each other. This can be due to numerical issues. Maybe try exact mode?");
603 }
604 if (remainingArea.isEmpty()) {
605 return false;
606 }
607
608 // We need to generate new facets
610 vertices, storm::utility::vector::filterZero(f.getHalfspace().normalVector()))
611 ->getHalfspaces();
612 for (auto& h : newHalfspaceCandidates) {
613 if (!storm::utility::vector::hasNegativeEntry(h.normalVector())) {
614 STORM_LOG_ASSERT(h.isPointOnBoundary(optPoint.get()), "Unexpected facet found while splitting.");
615 Facet fNew(std::move(h));
616 fNew.addPoint(optPointId.get(), optPoint);
617 auto vertexIt = vertices.begin();
618 ++vertexIt;
619 for (auto const& pId : f.getPoints()) {
620 STORM_LOG_ASSERT(pointset.getPoint(pId).get() == *vertexIt, "Vertex mismatch.");
621 if (fNew.getHalfspace().isPointOnBoundary(*vertexIt)) {
622 fNew.addPoint(pId, pointset.getPoint(pId));
623 }
624 ++vertexIt;
625 }
626 STORM_LOG_ASSERT(vertexIt == vertices.end(), "Vertex iterator not at end.");
627 unprocessedFacets.push(std::move(fNew));
628 }
629 }
630 return true;
631 }
632 } else {
633 // If the 'optimal point' was dominated by an existing point, we can not split the facet any further.
634 return false;
635 }
636}
637
638template<class SparseModelType, typename GeometryValueType>
640 /*
641 STORM_LOG_ERROR_COND(objectives.size()==2, "Exporting plot requested but this is only implemented for the two-dimensional case.");
642
643 auto transformedUnderApprox = transformPolytopeToOriginalModel(underApproximation);
644 auto transformedOverApprox = transformPolytopeToOriginalModel(overApproximation);
645
646 // Get pareto points as well as a hyperrectangle that is used to guarantee that the resulting polytopes are bounded.
647 storm::storage::geometry::Hyperrectangle<GeometryValueType> boundaries(std::vector<GeometryValueType>(objectives.size(),
648storm::utility::zero<GeometryValueType>()), std::vector<GeometryValueType>(objectives.size(), storm::utility::zero<GeometryValueType>()));
649 std::vector<std::vector<GeometryValueType>> paretoPoints;
650 paretoPoints.reserve(refinementSteps.size());
651 for(auto const& step : refinementSteps) {
652 paretoPoints.push_back(transformPointToOriginalModel(step.lowerBoundPoint));
653 boundaries.enlarge(paretoPoints.back());
654 }
655 auto underApproxVertices = transformedUnderApprox->getVertices();
656 for(auto const& v : underApproxVertices) {
657 boundaries.enlarge(v);
658 }
659 auto overApproxVertices = transformedOverApprox->getVertices();
660 for(auto const& v : overApproxVertices) {
661 boundaries.enlarge(v);
662 }
663
664 //Further enlarge the boundaries a little
665 storm::utility::vector::scaleVectorInPlace(boundaries.lowerBounds(), GeometryValueType(15) / GeometryValueType(10));
666 storm::utility::vector::scaleVectorInPlace(boundaries.upperBounds(), GeometryValueType(15) / GeometryValueType(10));
667
668 auto boundariesAsPolytope = boundaries.asPolytope();
669 std::vector<std::string> columnHeaders = {"x", "y"};
670
671 std::vector<std::vector<double>> pointsForPlotting;
672 if (env.modelchecker().multi().getPlotPathUnderApproximation()) {
673 underApproxVertices = transformedUnderApprox->intersection(boundariesAsPolytope)->getVerticesInClockwiseOrder();
674 pointsForPlotting.reserve(underApproxVertices.size());
675 for(auto const& v : underApproxVertices) {
676 pointsForPlotting.push_back(storm::utility::vector::convertNumericVector<double>(v));
677 }
678 storm::io::exportDataToCSVFile<double, std::string>(env.modelchecker().multi().getPlotPathUnderApproximation().get(), pointsForPlotting,
679columnHeaders);
680 }
681
682 if (env.modelchecker().multi().getPlotPathOverApproximation()) {
683 pointsForPlotting.clear();
684 overApproxVertices = transformedOverApprox->intersection(boundariesAsPolytope)->getVerticesInClockwiseOrder();
685 pointsForPlotting.reserve(overApproxVertices.size());
686 for(auto const& v : overApproxVertices) {
687 pointsForPlotting.push_back(storm::utility::vector::convertNumericVector<double>(v));
688 }
689 storm::io::exportDataToCSVFile<double, std::string>(env.modelchecker().multi().getPlotPathOverApproximation().get(), pointsForPlotting,
690columnHeaders);
691 }
692
693 if (env.modelchecker().multi().getPlotPathParetoPoints()) {
694 pointsForPlotting.clear();
695 pointsForPlotting.reserve(paretoPoints.size());
696 for(auto const& v : paretoPoints) {
697 pointsForPlotting.push_back(storm::utility::vector::convertNumericVector<double>(v));
698 }
699 storm::io::exportDataToCSVFile<double, std::string>(env.modelchecker().multi().getPlotPathParetoPoints().get(), pointsForPlotting, columnHeaders);
700 }
701};
702 */
703}
704
709} // namespace multiobjective
710} // namespace modelchecker
711} // 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
A bit vector that is internally represented as a vector of 64-bit values.
Definition BitVector.h:16
bool empty() const
Retrieves whether no bits are set to true in this bit vector.
uint64_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:40
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:24
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:51
#define STORM_LOG_INFO(message)
Definition logging.h:27
#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
bool closePoints(std::vector< GeometryValueType > const &first, std::vector< GeometryValueType > const &second, GeometryValueType const &maxDistance)
std::vector< GeometryValueType > transformObjectiveValuesToOriginal(std::vector< Objective< ValueType > > const &objectives, std::vector< GeometryValueType > const &point)
std::vector< TargetType > convertNumericVector(std::vector< SourceType > const &oldVector)
Converts the given vector to the given ValueType Assumes that both, TargetType and SourceType are num...
Definition vector.h:966
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:473
std::string toString(std::vector< ValueType > const &vector)
Output vector as string.
Definition vector.h:1179
bool hasNegativeEntry(std::vector< T > const &v)
Definition vector.h:1123
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:519
ValueType abs(ValueType const &number)
ValueType zero()
Definition constants.cpp:24
ValueType one()
Definition constants.cpp:19
TargetType convertNumber(SourceType const &number)