6 changed files with 520 additions and 62 deletions
			
			
		- 
					387src/storm/modelchecker/multiobjective/deterministicScheds/DetSchedsSimplexChecker.h
 - 
					1src/storm/modelchecker/multiobjective/deterministicScheds/DetSchedsWeightVectorChecker.cpp
 - 
					157src/storm/modelchecker/multiobjective/deterministicScheds/DeterministicParetoExplorer.cpp
 - 
					25src/storm/modelchecker/multiobjective/deterministicScheds/DeterministicParetoExplorer.h
 - 
					11src/storm/modelchecker/multiobjective/deterministicScheds/MultiObjectiveSchedulerEvaluator.cpp
 - 
					1src/storm/modelchecker/multiobjective/deterministicScheds/MultiObjectiveSchedulerEvaluator.h
 
@ -0,0 +1,387 @@ | 
				
			|||
#pragma once | 
				
			|||
 | 
				
			|||
#include <vector> | 
				
			|||
 | 
				
			|||
#include "storm/storage/geometry/Polytope.h" | 
				
			|||
#include "storm/modelchecker/multiobjective/deterministicScheds/MultiObjectiveSchedulerEvaluator.h" | 
				
			|||
#include "storm/storage/expressions/Expressions.h" | 
				
			|||
#include "storm/utility/solver.h" | 
				
			|||
#include "storm/solver/LpSolver.h" | 
				
			|||
#include "storm/modelchecker/results/ExplicitQuantitativeCheckResult.h" | 
				
			|||
#include "storm/modelchecker/results/ExplicitQualitativeCheckResult.h" | 
				
			|||
#include "storm/modelchecker/propositional/SparsePropositionalModelChecker.h" | 
				
			|||
#include "storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.h" | 
				
			|||
#include "storm/modelchecker/csl/SparseCtmcCslModelChecker.h" | 
				
			|||
#include "storm/storage/BitVector.h" | 
				
			|||
#include "storm/utility/graph.h" | 
				
			|||
#include "storm/utility/vector.h" | 
				
			|||
#include "storm/utility/Stopwatch.h" | 
				
			|||
 | 
				
			|||
namespace storm { | 
				
			|||
     | 
				
			|||
    class Environment; | 
				
			|||
     | 
				
			|||
    namespace modelchecker { | 
				
			|||
        namespace multiobjective { | 
				
			|||
             | 
				
			|||
            /*! | 
				
			|||
             * Represents a set of points in euclidean space. | 
				
			|||
             * The set is defined as the union of the polytopes at the leafs of the tree. | 
				
			|||
             * The polytope at inner nodes is always the convex union of its children. | 
				
			|||
             * The sets described by the children of a node are disjoint. | 
				
			|||
             * A child is always non-empty, i.e., isEmpty() should only hold for the root node. | 
				
			|||
             * @tparam GeometryValueType | 
				
			|||
             */ | 
				
			|||
            template <typename GeometryValueType> | 
				
			|||
            class PolytopeTree { | 
				
			|||
                typedef typename std::shared_ptr<storm::storage::geometry::Polytope<GeometryValueType>> Polytope; | 
				
			|||
                typedef typename std::vector<GeometryValueType> Point; | 
				
			|||
 | 
				
			|||
            public: | 
				
			|||
                PolytopeTree(Polytope const& polytope) : polytope(polytope) {} | 
				
			|||
                 | 
				
			|||
                /*! | 
				
			|||
                 * Substracts the given rhs from this polytope. | 
				
			|||
                 */ | 
				
			|||
                void setMinus(Polytope const& rhs) { | 
				
			|||
                    // This operation only has an effect if the intersection of this and rhs is non-empty. | 
				
			|||
                    if (!isEmpty() && !polytope->intersection(rhs)->isEmpty()) { | 
				
			|||
                        if (children.empty()) { | 
				
			|||
                            // This is a leaf node. | 
				
			|||
                            // Apply splitting. | 
				
			|||
                            auto newChildren = polytope->setMinus(rhs); | 
				
			|||
                            if (newChildren.empty()) { | 
				
			|||
                                // Delete this node. | 
				
			|||
                                polytope = nullptr; | 
				
			|||
                            } else if (newChildren.size() == 1) { | 
				
			|||
                                // Replace this node with its only child | 
				
			|||
                                polytope = newChildren.front()->clean(); | 
				
			|||
                            } else { | 
				
			|||
                                // Add the new children to this node. There is no need to traverse them. | 
				
			|||
                                for (auto& c : newChildren) { | 
				
			|||
                                    children.push_back(c->clean()); | 
				
			|||
                                } | 
				
			|||
                            } | 
				
			|||
                        } else { | 
				
			|||
                            // This is an inner node. Traverse the children and set this to the convex union of its children. | 
				
			|||
                            std::vector<PolytopeTree<GeometryValueType>> newChildren; | 
				
			|||
                            Polytope newPolytope = nullptr; | 
				
			|||
                            for (auto& c : children) { | 
				
			|||
                                c.setMinus(rhs); | 
				
			|||
                                if (c.polytope != nullptr) { | 
				
			|||
                                    newChildren.push_back(c); | 
				
			|||
                                    if (newPolytope) { | 
				
			|||
                                        newPolytope->convexUnion(c.polytope); | 
				
			|||
                                    } else { | 
				
			|||
                                        newPolytope = c.polytope; | 
				
			|||
                                    } | 
				
			|||
                                } | 
				
			|||
                            } | 
				
			|||
                            polytope = newPolytope; // nullptr, if no children left | 
				
			|||
                            children = std::move(newChildren); | 
				
			|||
                        } | 
				
			|||
                    } | 
				
			|||
                } | 
				
			|||
                 | 
				
			|||
                void substractDownwardClosure(Point const& point, GeometryValueType const& eps) { | 
				
			|||
                    std::vector<GeometryValueType>(pointPlusEps); | 
				
			|||
                    for (auto const& coordinate : point) { | 
				
			|||
                        pointPlusEps.push_back(coordinate + eps); | 
				
			|||
                    } | 
				
			|||
                    auto downwardOfPoint = storm::storage::geometry::Polytope<GeometryValueType>::createDownwardClosure({pointPlusEps}); | 
				
			|||
                    setMinus(downwardOfPoint); | 
				
			|||
                } | 
				
			|||
 | 
				
			|||
                bool isEmpty() const { | 
				
			|||
                    return polytope == nullptr; | 
				
			|||
                } | 
				
			|||
                 | 
				
			|||
                void clear() { | 
				
			|||
                    children.clear(); | 
				
			|||
                    polytope = nullptr; | 
				
			|||
                } | 
				
			|||
                 | 
				
			|||
                Polytope getPolytope() const { | 
				
			|||
                    return polytope; | 
				
			|||
                } | 
				
			|||
                 | 
				
			|||
                std::vector<PolytopeTree>& getChildren() { | 
				
			|||
                    return children; | 
				
			|||
                } | 
				
			|||
                 | 
				
			|||
                std::string toString() { | 
				
			|||
                    std::stringstream s; | 
				
			|||
                    s << "PolytopeTree node with " << getChildren().size() << " children: " << getPolytope()->toString(true) << std::endl << "Vertices: "; | 
				
			|||
                    auto vertices = getPolytope()->getVertices(); | 
				
			|||
                    for (auto const& v : vertices) { | 
				
			|||
                        s << "["; | 
				
			|||
                        for (auto const& vi : v) { | 
				
			|||
                            s << storm::utility::convertNumber<double>(vi) << ","; | 
				
			|||
                        } | 
				
			|||
                        s << "]\t"; | 
				
			|||
                    } | 
				
			|||
                    s << std::endl; | 
				
			|||
                    return s.str(); | 
				
			|||
                } | 
				
			|||
                 | 
				
			|||
            private: | 
				
			|||
                 | 
				
			|||
                 | 
				
			|||
                 | 
				
			|||
                Polytope polytope; | 
				
			|||
                std::vector<PolytopeTree<GeometryValueType>> children; | 
				
			|||
            }; | 
				
			|||
             | 
				
			|||
            template <typename ModelType, typename GeometryValueType> | 
				
			|||
            class DetSchedsSimplexChecker { | 
				
			|||
            public: | 
				
			|||
                 | 
				
			|||
                typedef typename ModelType::ValueType ValueType; | 
				
			|||
                typedef typename std::shared_ptr<storm::storage::geometry::Polytope<GeometryValueType>> Polytope; | 
				
			|||
                typedef typename std::vector<GeometryValueType> Point; | 
				
			|||
                 | 
				
			|||
                DetSchedsSimplexChecker(std::shared_ptr<MultiObjectiveSchedulerEvaluator<ModelType>> const& schedulerEvaluator) : schedulerEvaluator(schedulerEvaluator) { | 
				
			|||
                    init(); | 
				
			|||
                } | 
				
			|||
                 | 
				
			|||
                ~DetSchedsSimplexChecker() { | 
				
			|||
                    std::cout << "SIMPLEX CHECKER: " << swInit << " seconds for initialization" << std::endl; | 
				
			|||
                    std::cout << "SIMPLEX CHECKER: " << swCheck << " seconds for checking, including" << std::endl; | 
				
			|||
                    std::cout << "\t " << swLpBuild << " seconds for LP building" << std::endl; | 
				
			|||
                    std::cout << "\t " << swLpSolve << " seconds for LP solving" << std::endl; | 
				
			|||
                    std::cout << "SIMPLEX CHECKER: " << swAux << " seconds for aux stuff" << std::endl; | 
				
			|||
                } | 
				
			|||
                 | 
				
			|||
                std::pair<std::vector<Point>, std::vector<Polytope>> check(storm::Environment const& env, std::vector<GeometryValueType> const& weightVector, PolytopeTree<GeometryValueType>& polytopeTree, GeometryValueType const& eps) { | 
				
			|||
                    std::cout << "Checking a Simplex with weight vector " << storm::utility::vector::toString(weightVector) << std::endl << " and root " << polytopeTree.toString() << std::endl << "\t"; | 
				
			|||
                    if (polytopeTree.isEmpty()) { | 
				
			|||
                        return {{}, {}}; | 
				
			|||
                    } | 
				
			|||
                    swCheck.start(); | 
				
			|||
                     | 
				
			|||
                    swLpBuild.start(); | 
				
			|||
                    lpModel->push(); | 
				
			|||
                    currentObjectiveVariables.clear(); | 
				
			|||
                     | 
				
			|||
                    // set up objective function for the given weight vector | 
				
			|||
                    for (uint64_t objIndex = 0; objIndex < initialStateResults.size(); ++objIndex) { | 
				
			|||
                        currentObjectiveVariables.push_back(lpModel->addUnboundedContinuousVariable("w_" + std::to_string(objIndex), storm::utility::convertNumber<ValueType>(weightVector[objIndex]))); | 
				
			|||
                        lpModel->addConstraint("", currentObjectiveVariables.back().getExpression() == initialStateResults[objIndex]); | 
				
			|||
                    } | 
				
			|||
                    lpModel->update(); | 
				
			|||
                    swLpBuild.stop(); | 
				
			|||
 | 
				
			|||
                    auto result = checkRecursive(weightVector, polytopeTree, eps); | 
				
			|||
                     | 
				
			|||
                    swLpBuild.start(); | 
				
			|||
                    lpModel->pop(); | 
				
			|||
                    lpModel->update(); | 
				
			|||
                    swLpBuild.stop(); | 
				
			|||
                    swCheck.stop(); | 
				
			|||
                    std::cout << " done!" << std::endl; | 
				
			|||
                    return result; | 
				
			|||
                } | 
				
			|||
                 | 
				
			|||
            private: | 
				
			|||
                 | 
				
			|||
                std::pair<std::vector<Point>, std::vector<Polytope>> checkRecursive(std::vector<GeometryValueType> const& weightVector, PolytopeTree<GeometryValueType>& polytopeTree, GeometryValueType const& eps) { | 
				
			|||
                    std::cout << "."; | 
				
			|||
                    std::cout.flush(); | 
				
			|||
                    STORM_LOG_ASSERT(!polytopeTree.isEmpty(), "Tree node is empty"); | 
				
			|||
                    STORM_LOG_ASSERT(!polytopeTree.getPolytope()->isEmpty(), "Tree node is empty."); | 
				
			|||
                    STORM_LOG_TRACE("Checking " << polytopeTree.toString()); | 
				
			|||
                     | 
				
			|||
                    auto vertices = polytopeTree.getPolytope()->getVertices(); | 
				
			|||
                     | 
				
			|||
                    std::vector<Point> foundPoints; | 
				
			|||
                    std::vector<Polytope> infeasableAreas; | 
				
			|||
                     | 
				
			|||
                    swLpBuild.start(); | 
				
			|||
                    lpModel->push(); | 
				
			|||
                    // Assert the constraints of the current polytope | 
				
			|||
                    auto nodeConstraints = polytopeTree.getPolytope()->getConstraints(lpModel->getManager(), currentObjectiveVariables); | 
				
			|||
                    for (auto const& constr : nodeConstraints) { | 
				
			|||
                        lpModel->addConstraint("", constr); | 
				
			|||
                    } | 
				
			|||
                    lpModel->update(); | 
				
			|||
                    swLpBuild.stop(); | 
				
			|||
                     | 
				
			|||
                    if (polytopeTree.getChildren().empty()) { | 
				
			|||
                        // At leaf nodes we need to perform the actual check. | 
				
			|||
                        swLpSolve.start(); | 
				
			|||
                        lpModel->optimize(); | 
				
			|||
                        swLpSolve.stop(); | 
				
			|||
                         | 
				
			|||
                        if (lpModel->isInfeasible()) { | 
				
			|||
                            infeasableAreas.push_back(polytopeTree.getPolytope()); | 
				
			|||
                            polytopeTree.clear(); | 
				
			|||
                        } else { | 
				
			|||
                            STORM_LOG_ASSERT(!lpModel->isUnbounded(), "LP result is unbounded."); | 
				
			|||
                            Point newPoint; | 
				
			|||
                            for (auto const& objVar : currentObjectiveVariables) { | 
				
			|||
                                newPoint.push_back(storm::utility::convertNumber<GeometryValueType>(lpModel->getContinuousValue(objVar))); | 
				
			|||
                            } | 
				
			|||
                            auto halfspace = storm::storage::geometry::Halfspace<GeometryValueType>(weightVector, storm::utility::vector::dotProduct(weightVector, newPoint)).invert(); | 
				
			|||
                            infeasableAreas.push_back(polytopeTree.getPolytope()->intersection(halfspace)); | 
				
			|||
                            if (infeasableAreas.back()->isEmpty()) { | 
				
			|||
                                infeasableAreas.pop_back(); | 
				
			|||
                            } | 
				
			|||
                            swAux.start(); | 
				
			|||
                            polytopeTree.setMinus(storm::storage::geometry::Polytope<GeometryValueType>::create({halfspace})); | 
				
			|||
                            foundPoints.push_back(newPoint); | 
				
			|||
                            polytopeTree.substractDownwardClosure(newPoint, eps); | 
				
			|||
                            swAux.stop(); | 
				
			|||
                            if (!polytopeTree.isEmpty()) { | 
				
			|||
                                auto childRes = checkRecursive(weightVector, polytopeTree, eps); | 
				
			|||
                                foundPoints.insert(foundPoints.end(), childRes.first.begin(), childRes.first.end()); | 
				
			|||
                                infeasableAreas.insert(infeasableAreas.end(), childRes.second.begin(), childRes.second.end()); | 
				
			|||
                            } | 
				
			|||
                        } | 
				
			|||
                    } else { | 
				
			|||
                        // Traverse all the children. | 
				
			|||
                        for (uint64_t childId = 0; childId < polytopeTree.getChildren().size(); ++childId) { | 
				
			|||
                            auto childRes = checkRecursive(weightVector, polytopeTree.getChildren()[childId], eps); | 
				
			|||
                            STORM_LOG_ASSERT(polytopeTree.getChildren()[childId].isEmpty(), "expected empty children."); | 
				
			|||
                            // Make the results known to the right siblings | 
				
			|||
                            for (auto const& newPoint : childRes.first) { | 
				
			|||
                                for (uint64_t siblingId = childId + 1; siblingId < polytopeTree.getChildren().size(); ++siblingId) { | 
				
			|||
                                    polytopeTree.getChildren()[siblingId].substractDownwardClosure(newPoint, eps); | 
				
			|||
                                } | 
				
			|||
                            } | 
				
			|||
                            foundPoints.insert(foundPoints.end(), childRes.first.begin(), childRes.first.end()); | 
				
			|||
                            infeasableAreas.insert(infeasableAreas.end(), childRes.second.begin(), childRes.second.end()); | 
				
			|||
                        } | 
				
			|||
                        // All children are empty now, so this becomes empty. | 
				
			|||
                        polytopeTree.clear(); | 
				
			|||
                    } | 
				
			|||
                    swLpBuild.start(); | 
				
			|||
                    lpModel->pop(); | 
				
			|||
                    swLpBuild.stop(); | 
				
			|||
                    return {foundPoints, infeasableAreas}; | 
				
			|||
                } | 
				
			|||
 | 
				
			|||
                /* Todo | 
				
			|||
                ValueType getChoiceValueSummand(Objective<ValueType> const& objective, uint64_t choiceIndex) { | 
				
			|||
                    auto const& model = schedulerEvaluator->getModel(); | 
				
			|||
                    storm::modelchecker::SparsePropositionalModelChecker<ModelType> mc(model); | 
				
			|||
                    auto const& formula = *objective.formula; | 
				
			|||
                    if (formula.isProbabilityOperatorFormula() && formula.getSubformula().isUntilFormula()) { | 
				
			|||
                        return storm::utility::zero<ValueType>(); | 
				
			|||
                    } else if (formula.getSubformula().isEventuallyFormula() && (formula.isRewardOperatorFormula() || formula.isTimeOperatorFormula())) { | 
				
			|||
                         | 
				
			|||
                        storm::storage::BitVector rew0States = mc.check(formula.getSubformula().asEventuallyFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); | 
				
			|||
                        if (formula.isRewardOperatorFormula()) { | 
				
			|||
                            auto const& rewModel = formula.asRewardOperatorFormula().hasRewardModelName() ? model.getRewardModel(formula.asRewardOperatorFormula().getRewardModelName()) : model.getUniqueRewardModel(); | 
				
			|||
                            storm::storage::BitVector statesWithoutReward = rewModel.getStatesWithZeroReward(model.getTransitionMatrix()); | 
				
			|||
                            rew0States = storm::utility::graph::performProb1A(model.getTransitionMatrix(), model.getNondeterministicChoiceIndices(), model.getBackwardTransitions(), statesWithoutReward, rew0States); | 
				
			|||
                        } | 
				
			|||
                        storm::utility::vector::setVectorValues(results[objIndex], rew0States, storm::utility::zero<ValueType>()); | 
				
			|||
                        schedulerIndependentStates.push_back(std::move(rew0States)); | 
				
			|||
                    } else if (formula.isRewardOperatorFormula() && formula.getSubformula().isTotalRewardFormula()) { | 
				
			|||
                        auto const& rewModel = formula.asRewardOperatorFormula().hasRewardModelName() ? model.getRewardModel(formula.asRewardOperatorFormula().getRewardModelName()) : model.getUniqueRewardModel(); | 
				
			|||
                        storm::storage::BitVector statesWithoutReward = rewModel.getStatesWithZeroReward(model.getTransitionMatrix()); | 
				
			|||
                        storm::storage::BitVector rew0States = storm::utility::graph::performProbGreater0E(model.getBackwardTransitions(), statesWithoutReward, ~statesWithoutReward); | 
				
			|||
                        rew0States.complement(); | 
				
			|||
                        storm::utility::vector::setVectorValues(results[objIndex], rew0States, storm::utility::zero<ValueType>()); | 
				
			|||
                        schedulerIndependentStates.push_back(std::move(rew0States)); | 
				
			|||
                    } else { | 
				
			|||
                        STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "The given formula " << formula << " is not supported."); | 
				
			|||
                    } | 
				
			|||
                }*/ | 
				
			|||
                 | 
				
			|||
                void init() { | 
				
			|||
                    swInit.start(); | 
				
			|||
                    auto const& model = schedulerEvaluator->getModel(); | 
				
			|||
                    auto const& objectives = schedulerEvaluator->getObjectives(); | 
				
			|||
                    uint64_t numStates = model.getNumberOfStates(); | 
				
			|||
                    lpModel = storm::utility::solver::getLpSolver<ValueType>("model"); | 
				
			|||
                    lpModel->setOptimizationDirection(storm::solver::OptimizationDirection::Maximize); | 
				
			|||
                    initialStateResults.clear(); | 
				
			|||
                     | 
				
			|||
                    auto one = lpModel->getConstant(storm::utility::one<ValueType>()); | 
				
			|||
                     | 
				
			|||
                    // Create choice variables and assert that at least one choice is taken at each state. | 
				
			|||
                    std::vector<storm::expressions::Expression> choiceVars; | 
				
			|||
                    choiceVars.reserve(model.getNumberOfChoices()); | 
				
			|||
                    for (uint64_t state = 0; state < numStates; ++state) { | 
				
			|||
                        uint64_t numChoices = model.getNumberOfChoices(state); | 
				
			|||
                        if (numChoices == 1) { | 
				
			|||
                            choiceVars.emplace_back(); | 
				
			|||
                        } else { | 
				
			|||
                            std::vector<storm::expressions::Expression> localChoices; | 
				
			|||
                            for (uint64_t choice = 0; choice < numChoices; ++choice) { | 
				
			|||
                                localChoices.push_back(lpModel->addBoundedIntegerVariable("c" + std::to_string(state) + "_" + std::to_string(choice), 0, 1).getExpression()); | 
				
			|||
                            } | 
				
			|||
                            lpModel->addConstraint("", storm::expressions::sum(localChoices).reduceNesting() >= one); | 
				
			|||
                            choiceVars.insert(choiceVars.end(), localChoices.begin(), localChoices.end()); | 
				
			|||
                        } | 
				
			|||
                    } | 
				
			|||
                     | 
				
			|||
                    for (uint64_t objIndex = 0; objIndex < objectives.size(); ++objIndex) { | 
				
			|||
                        Objective<ValueType> const& objective = objectives[objIndex]; | 
				
			|||
                        storm::storage::BitVector const& schedulerIndependentStates = schedulerEvaluator->getSchedulerIndependentStates(objIndex); | 
				
			|||
                        // Create state variables | 
				
			|||
                        std::vector<storm::expressions::Expression> stateVars; | 
				
			|||
                        stateVars.reserve(numStates); | 
				
			|||
                        for (uint64_t state = 0; state < numStates; ++state) { | 
				
			|||
                            if (schedulerIndependentStates.get(state)) { | 
				
			|||
                                stateVars.push_back(lpModel->getConstant(schedulerEvaluator->getSchedulerIndependentStateResult(objIndex, state))); | 
				
			|||
                            } else { | 
				
			|||
                                stateVars.push_back(lpModel->addContinuousVariable("x" + std::to_string(objIndex) + "_" + std::to_string(state), objective.lowerResultBound, objective.upperResultBound).getExpression()); | 
				
			|||
                            } | 
				
			|||
                            if (state == *model.getInitialStates().begin()) { | 
				
			|||
                                initialStateResults.push_back(stateVars.back()); | 
				
			|||
                            } | 
				
			|||
                        } | 
				
			|||
                         | 
				
			|||
                        // Create and assert choice values | 
				
			|||
                        for (uint64_t state = 0; state < numStates; ++state) { | 
				
			|||
                            if (schedulerIndependentStates.get(state)) { | 
				
			|||
                                continue; | 
				
			|||
                            } | 
				
			|||
                            storm::expressions::Expression stateValue; | 
				
			|||
                            uint64_t numChoices = model.getNumberOfChoices(state); | 
				
			|||
                            for (uint64_t choice = 0; choice < numChoices; ++choice) { | 
				
			|||
                                storm::expressions::Expression choiceValue; | 
				
			|||
                                if (objective.formula) | 
				
			|||
                                for (auto const& transition : model.getTransitionMatrix().getRow(state, choice)) { | 
				
			|||
                                    storm::expressions::Expression transitionValue = lpModel->getConstant(transition.getValue()) * stateVars[transition.getColumn()]; | 
				
			|||
                                    if (choiceValue.isInitialized()) { | 
				
			|||
                                        choiceValue = choiceValue + transitionValue; | 
				
			|||
                                    } else { | 
				
			|||
                                        choiceValue = transitionValue; | 
				
			|||
                                    } | 
				
			|||
                                } | 
				
			|||
                                choiceValue = choiceValue.simplify().reduceNesting(); | 
				
			|||
                                if (numChoices == 1) { | 
				
			|||
                                    lpModel->addConstraint("", stateVars[state] == choiceValue); | 
				
			|||
                                } else { | 
				
			|||
                                    uint64_t globalChoiceIndex = model.getTransitionMatrix().getRowGroupIndices()[state] + choice; | 
				
			|||
                                    storm::expressions::Expression maxDiff = lpModel->getConstant(objective.upperResultBound.get()) * (one - choiceVars[globalChoiceIndex]); | 
				
			|||
                                    lpModel->addConstraint("", stateVars[state] - choiceValue <= maxDiff); | 
				
			|||
                                    lpModel->addConstraint("", choiceValue - stateVars[state] <= maxDiff); | 
				
			|||
                                } | 
				
			|||
                            } | 
				
			|||
                        } | 
				
			|||
                    } | 
				
			|||
                    lpModel->update(); | 
				
			|||
                    swInit.stop(); | 
				
			|||
                } | 
				
			|||
                 | 
				
			|||
                std::shared_ptr<MultiObjectiveSchedulerEvaluator<ModelType>> schedulerEvaluator; | 
				
			|||
 | 
				
			|||
                std::unique_ptr<storm::solver::LpSolver<ValueType>> lpModel; | 
				
			|||
                std::vector<storm::expressions::Expression> initialStateResults; | 
				
			|||
                std::vector<storm::expressions::Variable> currentObjectiveVariables; | 
				
			|||
 | 
				
			|||
                 | 
				
			|||
                storm::utility::Stopwatch swInit; | 
				
			|||
                storm::utility::Stopwatch swCheck; | 
				
			|||
                storm::utility::Stopwatch swLpSolve; | 
				
			|||
                storm::utility::Stopwatch swLpBuild; | 
				
			|||
                storm::utility::Stopwatch swAux; | 
				
			|||
            }; | 
				
			|||
             | 
				
			|||
        } | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
						Write
						Preview
					
					
					Loading…
					
					Cancel
						Save
					
		Reference in new issue