You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

98 lines
6.7 KiB

#include "storm/modelchecker/multiobjective/pcaa/SparsePcaaParetoQuery.h"
#include "storm/adapters/RationalFunctionAdapter.h"
#include "storm/models/sparse/Mdp.h"
#include "storm/models/sparse/MarkovAutomaton.h"
#include "storm/models/sparse/StandardRewardModel.h"
#include "storm/modelchecker/results/ExplicitParetoCurveCheckResult.h"
#include "storm/utility/constants.h"
#include "storm/utility/vector.h"
#include "storm/environment/modelchecker/MultiObjectiveModelCheckerEnvironment.h"
namespace storm {
namespace modelchecker {
namespace multiobjective {
template <class SparseModelType, typename GeometryValueType>
SparsePcaaParetoQuery<SparseModelType, GeometryValueType>::SparsePcaaParetoQuery(SparseMultiObjectivePreprocessorResult<SparseModelType>& preprocessorResult) : SparsePcaaQuery<SparseModelType, GeometryValueType>(preprocessorResult) {
STORM_LOG_ASSERT(preprocessorResult.queryType==SparseMultiObjectivePreprocessorResult<SparseModelType>::QueryType::Pareto, "Invalid query Type");
}
template <class SparseModelType, typename GeometryValueType>
std::unique_ptr<CheckResult> SparsePcaaParetoQuery<SparseModelType, GeometryValueType>::check(Environment const& env) {
// Set the precision of the weight vector checker
typename SparseModelType::ValueType weightedPrecision = storm::utility::convertNumber<typename SparseModelType::ValueType>(env.modelchecker().multi().getPrecision());
weightedPrecision /= storm::utility::sqrt(storm::utility::convertNumber<typename SparseModelType::ValueType, uint_fast64_t>(this->objectives.size()));
// multiobjPrecision / sqrt(numObjectives) is the largest possible value for which termination is guaranteed.
// Lets be a little bit more precise to reduce the number of required iterations.
weightedPrecision *= storm::utility::convertNumber<typename SparseModelType::ValueType>(0.9);
this->weightVectorChecker->setWeightedPrecision(weightedPrecision);
// refine the approximation
exploreSetOfAchievablePoints(env);
// obtain the data for the checkresult
std::vector<std::vector<typename SparseModelType::ValueType>> paretoOptimalPoints;
std::vector<Point> vertices = this->underApproximation->getVertices();
paretoOptimalPoints.reserve(vertices.size());
for(auto const& vertex : vertices) {
paretoOptimalPoints.push_back(storm::utility::vector::convertNumericVector<typename SparseModelType::ValueType>(this->transformPointToOriginalModel(vertex)));
}
return std::unique_ptr<CheckResult>(new ExplicitParetoCurveCheckResult<typename SparseModelType::ValueType>(this->originalModel.getInitialStates().getNextSetIndex(0),
std::move(paretoOptimalPoints),
this->transformPolytopeToOriginalModel(this->underApproximation)->template convertNumberRepresentation<typename SparseModelType::ValueType>(),
this->transformPolytopeToOriginalModel(this->overApproximation)->template convertNumberRepresentation<typename SparseModelType::ValueType>()));
}
template <class SparseModelType, typename GeometryValueType>
void SparsePcaaParetoQuery<SparseModelType, GeometryValueType>::exploreSetOfAchievablePoints(Environment const& env) {
//First consider the objectives individually
for(uint_fast64_t objIndex = 0; objIndex<this->objectives.size() && !this->maxStepsPerformed(env); ++objIndex) {
WeightVector direction(this->objectives.size(), storm::utility::zero<GeometryValueType>());
direction[objIndex] = storm::utility::one<GeometryValueType>();
this->performRefinementStep(env, std::move(direction));
}
while(!this->maxStepsPerformed(env)) {
// Get the halfspace of the underApproximation with maximal distance to a vertex of the overApproximation
std::vector<storm::storage::geometry::Halfspace<GeometryValueType>> underApproxHalfspaces = this->underApproximation->getHalfspaces();
std::vector<Point> overApproxVertices = this->overApproximation->getVertices();
uint_fast64_t farestHalfspaceIndex = underApproxHalfspaces.size();
GeometryValueType farestDistance = storm::utility::zero<GeometryValueType>();
for(uint_fast64_t halfspaceIndex = 0; halfspaceIndex < underApproxHalfspaces.size(); ++halfspaceIndex) {
for(auto const& vertex : overApproxVertices) {
GeometryValueType distance = underApproxHalfspaces[halfspaceIndex].euclideanDistance(vertex);
if(distance > farestDistance) {
farestHalfspaceIndex = halfspaceIndex;
farestDistance = distance;
}
}
}
if(farestDistance < storm::utility::convertNumber<GeometryValueType>(env.modelchecker().multi().getPrecision())) {
// Goal precision reached!
return;
}
STORM_LOG_INFO("Current precision of the approximation of the pareto curve is ~" << storm::utility::convertNumber<double>(farestDistance));
WeightVector direction = underApproxHalfspaces[farestHalfspaceIndex].normalVector();
this->performRefinementStep(env, std::move(direction));
}
STORM_LOG_ERROR("Could not reach the desired precision: Exceeded maximum number of refinement steps");
}
#ifdef STORM_HAVE_CARL
template class SparsePcaaParetoQuery<storm::models::sparse::Mdp<double>, storm::RationalNumber>;
template class SparsePcaaParetoQuery<storm::models::sparse::MarkovAutomaton<double>, storm::RationalNumber>;
template class SparsePcaaParetoQuery<storm::models::sparse::Mdp<storm::RationalNumber>, storm::RationalNumber>;
template class SparsePcaaParetoQuery<storm::models::sparse::MarkovAutomaton<storm::RationalNumber>, storm::RationalNumber>;
#endif
}
}
}