Storm 1.10.0.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
SparsePcaaParetoQuery.cpp
Go to the documentation of this file.
2
12
13namespace storm {
14namespace modelchecker {
15namespace multiobjective {
16
17template<class SparseModelType, typename GeometryValueType>
24
25template<class SparseModelType, typename GeometryValueType>
26std::unique_ptr<CheckResult> SparsePcaaParetoQuery<SparseModelType, GeometryValueType>::check(Environment const& env, bool produceScheduler) {
28 storm::exceptions::IllegalArgumentException, "Unhandled multiobjective precision type.");
29
30 // Set the precision of the weight vector checker
31 typename SparseModelType::ValueType weightedPrecision =
32 storm::utility::convertNumber<typename SparseModelType::ValueType>(env.modelchecker().multi().getPrecision());
33 weightedPrecision /= storm::utility::sqrt(storm::utility::convertNumber<typename SparseModelType::ValueType, uint_fast64_t>(this->objectives.size()));
34 // multiobjPrecision / sqrt(numObjectives) is the largest possible value for which termination is guaranteed.
35 // To see this, assume that for both weight vectors <1,0> and <0,1> we get the same point <a,b> for the under-approximation and <a+weightedPrecision,b>
36 // resp. <a,b+weightedPrecision> for the over-approximation. Then, the over-approx. point <a+weightedPrecision,b+weightedPrecision> has a distance to the
37 // under-approximation of weightedPrecision * sqrt(numObjectives). Lets be a little bit more precise to reduce the number of required iterations.
38 weightedPrecision *= storm::utility::convertNumber<typename SparseModelType::ValueType>(0.9);
39 this->weightVectorChecker->setWeightedPrecision(weightedPrecision);
40
41 // refine the approximation
42 exploreSetOfAchievablePoints(env, produceScheduler);
43
44 // obtain the data for the checkresult
45 std::vector<std::vector<typename SparseModelType::ValueType>> paretoOptimalPoints;
46 std::vector<storm::storage::Scheduler<typename SparseModelType::ValueType>> paretoOptimalSchedulers;
47 std::vector<Point> vertices = this->underApproximation->getVertices();
48 paretoOptimalPoints.reserve(vertices.size());
49 for (auto const& vertex : vertices) {
50 paretoOptimalPoints.push_back(
51 storm::utility::vector::convertNumericVector<typename SparseModelType::ValueType>(transformObjectiveValuesToOriginal(this->objectives, vertex)));
52 if (produceScheduler) {
53 // Find the refinement step in which we found the vertex
54 // TODO: Handle this in a safer way. Associating the found schedulers with the found points is quite implicit and error prone right now.
55 auto stepIt = std::find_if(this->refinementSteps.begin(), this->refinementSteps.end(),
56 [&vertex](auto const& step) { return step.lowerBoundPoint == vertex; });
57 STORM_LOG_THROW(stepIt != this->refinementSteps.end(), storm::exceptions::UnexpectedException,
58 "Scheduler for point " << storm::utility::vector::toString(paretoOptimalPoints.back()) << " not found.");
59 STORM_LOG_ASSERT(stepIt->scheduler.has_value(),
60 "Scheduler for point " << storm::utility::vector::toString(paretoOptimalPoints.back()) << " not generated.");
61 paretoOptimalSchedulers.push_back(std::move(stepIt->scheduler.value()));
62 }
63 }
64 return std::unique_ptr<CheckResult>(new ExplicitParetoCurveCheckResult<typename SparseModelType::ValueType>(
65 this->originalModel.getInitialStates().getNextSetIndex(0), std::move(paretoOptimalPoints), std::move(paretoOptimalSchedulers),
66 transformObjectivePolytopeToOriginal(this->objectives, this->underApproximation)
67 ->template convertNumberRepresentation<typename SparseModelType::ValueType>(),
68 transformObjectivePolytopeToOriginal(this->objectives, this->overApproximation)
69 ->template convertNumberRepresentation<typename SparseModelType::ValueType>()));
70}
71
72template<class SparseModelType, typename GeometryValueType>
75 storm::exceptions::IllegalArgumentException, "Unhandled multiobjective precision type.");
76
77 // First consider the objectives individually
78 for (uint_fast64_t objIndex = 0; objIndex < this->objectives.size() && !this->maxStepsPerformed(env); ++objIndex) {
79 WeightVector direction(this->objectives.size(), storm::utility::zero<GeometryValueType>());
80 direction[objIndex] = storm::utility::one<GeometryValueType>();
81 this->performRefinementStep(env, std::move(direction), produceScheduler);
83 break;
84 }
85 }
86
87 while (!this->maxStepsPerformed(env) && !storm::utility::resources::isTerminate()) {
88 // Get the halfspace of the underApproximation with maximal distance to a vertex of the overApproximation
89 std::vector<storm::storage::geometry::Halfspace<GeometryValueType>> underApproxHalfspaces = this->underApproximation->getHalfspaces();
90 std::vector<Point> overApproxVertices = this->overApproximation->getVertices();
91 uint_fast64_t farestHalfspaceIndex = underApproxHalfspaces.size();
92 GeometryValueType farestDistance = storm::utility::zero<GeometryValueType>();
93 for (uint_fast64_t halfspaceIndex = 0; halfspaceIndex < underApproxHalfspaces.size(); ++halfspaceIndex) {
94 for (auto const& vertex : overApproxVertices) {
95 GeometryValueType distance = underApproxHalfspaces[halfspaceIndex].euclideanDistance(vertex);
96 if (distance > farestDistance) {
97 farestHalfspaceIndex = halfspaceIndex;
98 farestDistance = distance;
99 }
100 }
101 }
102 if (farestDistance < storm::utility::convertNumber<GeometryValueType>(env.modelchecker().multi().getPrecision())) {
103 // Goal precision reached!
104 return;
105 }
106 STORM_LOG_INFO("Current precision of the approximation of the pareto curve is ~" << storm::utility::convertNumber<double>(farestDistance));
107 WeightVector direction = underApproxHalfspaces[farestHalfspaceIndex].normalVector();
108 this->performRefinementStep(env, std::move(direction), produceScheduler);
109 }
110 STORM_LOG_ERROR("Could not reach the desired precision: Termination requested or maximum number of refinement steps exceeded.");
111}
112
113#ifdef STORM_HAVE_CARL
114template class SparsePcaaParetoQuery<storm::models::sparse::Mdp<double>, storm::RationalNumber>;
115template class SparsePcaaParetoQuery<storm::models::sparse::MarkovAutomaton<double>, storm::RationalNumber>;
116
117template class SparsePcaaParetoQuery<storm::models::sparse::Mdp<storm::RationalNumber>, storm::RationalNumber>;
118template class SparsePcaaParetoQuery<storm::models::sparse::MarkovAutomaton<storm::RationalNumber>, storm::RationalNumber>;
119#endif
120} // namespace multiobjective
121} // namespace modelchecker
122} // namespace storm
ModelCheckerEnvironment & modelchecker()
MultiObjectiveModelCheckerEnvironment & multi()
virtual std::unique_ptr< CheckResult > check(Environment const &env, bool produceScheduler) override
SparsePcaaParetoQuery(preprocessing::SparseMultiObjectivePreprocessorResult< SparseModelType > &preprocessorResult)
#define STORM_LOG_INFO(message)
Definition logging.h:24
#define STORM_LOG_ERROR(message)
Definition logging.h:26
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:11
#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)
std::shared_ptr< storm::storage::geometry::Polytope< GeometryValueType > > transformObjectivePolytopeToOriginal(std::vector< Objective< ValueType > > objectives, std::shared_ptr< storm::storage::geometry::Polytope< GeometryValueType > > const &polytope)
bool isTerminate()
Check whether the program should terminate (due to some abort signal).
std::string toString(std::vector< ValueType > const &vector)
Output vector as string.
Definition vector.h:1149
ValueType sqrt(ValueType const &number)
LabParser.cpp.