#pragma once #include #include #include "storm/modelchecker/multiobjective/preprocessing/SparseMultiObjectivePreprocessorResult.h" #include "storm/modelchecker/multiobjective/deterministicScheds/DeterministicSchedsLpChecker.h" #include "storm/modelchecker/multiobjective/deterministicScheds/DeterministicSchedsObjectiveHelper.h" #include "storm/storage/geometry/Polytope.h" #include "storm/storage/geometry/Halfspace.h" #include "storm/modelchecker/results/CheckResult.h" #include "storm/storage/expressions/ExpressionManager.h" #include "storm/solver/SmtSolver.h" namespace storm { class Environment; namespace modelchecker { namespace multiobjective { template class DeterministicSchedsParetoExplorer { public: typedef uint64_t PointId; typedef typename std::shared_ptr> Polytope; typedef typename SparseModelType::ValueType ModelValueType; class Point { public: Point(std::vector const& coordinates); Point(std::vector&& coordinates); std::vector const& get() const; std::vector& get(); uint64_t dimension() const; enum class DominanceResult { Incomparable, Dominates, Dominated, Equal }; DominanceResult getDominance(Point const& other) const; void setOnFacet(bool value = true); bool liesOnFacet() const; std::string toString(bool convertToDouble = false) const; private: std::vector coordinates; bool onFacet; }; class Pointset { public: typedef typename std::map::const_iterator iterator_type; Pointset(); /*! * If the given point is not dominated by another point in the set, it is added * to the set and its ID is returned. * If the point is dominated by another point, boost::none is returned. * Erases all points in the set, that are dominated by the given point. * If the same point is already contained in the set, its id is returned */ boost::optional addPoint(Environment const& env, Point&& point); /*! * Returns the point with the given ID */ Point const& getPoint(PointId const& id) const; iterator_type begin() const; iterator_type end() const; /*! * Returns the number of points currently contained in the set */ uint64_t size() const; /*! * Returns the downward closure of the contained points. */ Polytope downwardClosure() const; void collectPointsInPolytope(std::set& collectedPoints, Polytope const& polytope); void printToStream(std::ostream& out, bool includeIDs = true, bool convertToDouble = false); private: std::map points; PointId currId; }; class Facet { public: Facet(storm::storage::geometry::Halfspace const& halfspace); Facet(storm::storage::geometry::Halfspace&& halfspace); storm::storage::geometry::Halfspace const& getHalfspace() const; void addPoint(PointId const& pointId, Point const& point); std::vector const& getPoints() const; uint64_t getNumberOfPoints() const; /*! * Creates a polytope that captures all points that lie 'under' the facet */ Polytope getInducedPolytope(Pointset const& pointset, std::vector const& referenceCoordinates); private: storm::storage::geometry::Halfspace halfspace; std::vector pointsOnFacet; }; DeterministicSchedsParetoExplorer(Environment const& env, preprocessing::SparseMultiObjectivePreprocessorResult& preprocessorResult); virtual std::unique_ptr check(Environment const& env); void exportPlotOfCurrentApproximation(Environment const& env); private: /*! * Cleans up all cached results from a previous check call */ void clean(); /*! * Intersects the overapproximation with the given halfspace */ void addHalfspaceToOverApproximation(Environment const& env, std::vector const& normalVector, GeometryValueType const& offset); /*! * Adds a polytope which consists of unachievable points */ void addUnachievableArea(Environment const& env, Polytope const& area); /*! * Builds the initial facets by optimizing the objectives individually. * Adds the facets that need further processing to unprocessedFacets */ void initializeFacets(Environment const& env); /*! * Gets reference coordinates used to subdividing the downwardclosure */ std::vector getReferenceCoordinates(Environment const& env) const; /*! * Processes the given facet */ void processFacet(Environment const& env, Facet& f); /*! * Optimizes in the facet direction. If this results in a point that does not lie on the facet, * 1. The new Pareto optimal point is added * 2. New facets are generated and (if not already precise enough) added to unprocessedFacets * 3. true is returned */ bool optimizeAndSplitFacet(Environment const& env, Facet& f); Polytope negateMinObjectives(Polytope const& polytope) const; void negateMinObjectives(std::vector& vector) const; Pointset pointset; std::queue unprocessedFacets; Polytope overApproximation; std::vector unachievableAreas; std::shared_ptr> lpChecker; std::vector> objectiveHelper; std::shared_ptr const& model; uint64_t originalModelInitialState; std::vector> const& objectives; }; } } }