diff --git a/CMakeLists.txt b/CMakeLists.txt index 6bdaa29a2..1fc3d1d1a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -383,6 +383,7 @@ file(GLOB_RECURSE STORM_MODELCHECKER_REACHABILITY_FILES ${PROJECT_SOURCE_DIR}/sr file(GLOB_RECURSE STORM_MODELCHECKER_PROPOSITIONAL_FILES ${PROJECT_SOURCE_DIR}/src/modelchecker/propositional/*.h ${PROJECT_SOURCE_DIR}/src/modelchecker/propositional/*.cpp) file(GLOB_RECURSE STORM_MODELCHECKER_RESULTS_FILES ${PROJECT_SOURCE_DIR}/src/modelchecker/results/*.h ${PROJECT_SOURCE_DIR}/src/modelchecker/results/*.cpp) file(GLOB_RECURSE STORM_COUNTEREXAMPLES_FILES ${PROJECT_SOURCE_DIR}/src/counterexamples/*.h ${PROJECT_SOURCE_DIR}/src/counterexamples/*.cpp) +file(GLOB_RECURSE STORM_PERMISSIVESCHEDULER_FILES ${PROJECT_SOURCE_DIR}/src/permissivesched/*.h ${PROJECT_SOURCE_DIR}/src/permissivesched/*.cpp) file(GLOB STORM_MODELS_FILES ${PROJECT_SOURCE_DIR}/src/models/*.h ${PROJECT_SOURCE_DIR}/src/models/*.cpp) file(GLOB_RECURSE STORM_MODELS_SPARSE_FILES ${PROJECT_SOURCE_DIR}/src/models/sparse/*.h ${PROJECT_SOURCE_DIR}/src/models/sparse/*.cpp) file(GLOB_RECURSE STORM_MODELS_SYMBOLIC_FILES ${PROJECT_SOURCE_DIR}/src/models/symbolic/*.h ${PROJECT_SOURCE_DIR}/src/models/symbolic/*.cpp) @@ -421,6 +422,7 @@ source_group(modelchecker\\reachability FILES ${STORM_MODELCHECKER_REACHABILITY_ source_group(modelchecker\\propositional FILES ${STORM_MODELCHECKER_PROPOSITIONAL_FILES}) source_group(modelchecker\\results FILES ${STORM_MODELCHECKER_RESULTS_FILES}) source_group(counterexamples FILES ${STORM_COUNTEREXAMPLES_FILES}) +source_group(permissiveschedulers FILES ${STORM_PERMISSIVESCHEDULER_FILES}) source_group(models FILES ${STORM_MODELS_FILES}) source_group(models\\sparse FILES ${STORM_MODELS_SPARSE_FILES}) source_group(models\\symbolic FILES ${STORM_MODELS_SYMBOLIC_FILES}) diff --git a/src/permissivesched/MILPPermissiveSchedulers.h b/src/permissivesched/MILPPermissiveSchedulers.h new file mode 100644 index 000000000..abfbf2274 --- /dev/null +++ b/src/permissivesched/MILPPermissiveSchedulers.h @@ -0,0 +1,196 @@ +#ifndef MILPPERMISSIVESCHEDULERS_H +#define MILPPERMISSIVESCHEDULERS_H + + +#include +#include + +#include "PermissiveSchedulerComputation.h" + +#include "../storage/BitVector.h" +#include "../storage/StateActionPair.h" +#include "../storage/StateActionTargetTuple.h" +#include "../storage/expressions/Variable.h" +#include "../solver/LpSolver.h" + + + +namespace storm { + namespace ps { + +class MilpPermissiveSchedulerComputation : public PermissiveSchedulerComputation { + private: + + bool mCalledOptimizer = false; + storm::solver::LpSolver& solver; + std::unordered_map multistrategyVariables; + std::unordered_map mProbVariables; + std::unordered_map mAlphaVariables; + std::unordered_map mBetaVariables; + std::unordered_map mGammaVariables; + + public: + + MilpPermissiveSchedulerComputation(storm::solver::LpSolver& milpsolver, std::shared_ptr> mdp, storm::storage::BitVector const& goalstates, storm::storage::BitVector const& sinkstates) + : PermissiveSchedulerComputation(mdp, goalstates, sinkstates), solver(milpsolver) + { + + } + + + void calculatePermissiveScheduler(double boundary) override { + createMILP(boundary, mPenalties); + solver.optimize(); + mCalledOptimizer = true; + } + + + bool foundSolution() const override { + assert(mCalledOptimizer); + return !solver.isInfeasible(); + } + + MemorylessDeterministicPermissiveScheduler && getScheduler() const override { + storm::storage::BitVector result(mdp->getNumberOfChoices(), true); + for(auto const& entry : multistrategyVariables) { + if(!solver.getBinaryValue(entry.second)) { + result.set(mdp->getNondeterministicChoiceIndices()[entry.first.getState()]+entry.first.getAction(), false); + } + } + return std::move(result); + } + + + private: + + /** + * + */ + void createVariables(PermissiveSchedulerPenalties const& penalties, storm::storage::BitVector const& relevantStates) { + // We need the unique initial state later, so we get that one before looping. + assert(mdp->getInitialStates().getNumberOfSetBits() == 1); + uint_fast64_t initialStateIndex = mdp->getInitialStates().getNextSetIndex(0); + + storm::expressions::Variable var; + for(uint_fast64_t s : relevantStates) { + // Create x_s variables + // Notice that only the initial probability appears in the objective. + if(s == initialStateIndex) { + var = solver.addLowerBoundedContinuousVariable("x_" + std::to_string(s), 0.0, -1.0); + } else { + var = solver.addLowerBoundedContinuousVariable("x_" + std::to_string(s), 0.0); + } + mProbVariables[s] = var; + // Create alpha_s variables + var = solver.addBinaryVariable("alp_" + std::to_string(s)); + mAlphaVariables[s] = var; + // Create gamma_s variables + var = solver.addBoundedContinuousVariable("gam_" + std::to_string(s), 0.0, 1.0); + mGammaVariables[s] = var; + for(uint_fast64_t a = 0; a < mdp->getNumberOfChoices(s); ++a) { + auto stateAndAction = storage::StateActionPair(s,a); + + // Create y_(s,a) variables + double penalty = penalties.get(stateAndAction); + var = solver.addBinaryVariable("y_" + std::to_string(s) + "_" + std::to_string(a), -penalty); + multistrategyVariables[stateAndAction] = var; + + // Create beta_(s,a,t) variables + // Iterate over successors of s via a. + for(auto const& entry : mdp->getTransitionMatrix().getRow(mdp->getNondeterministicChoiceIndices()[s]+a)) { + if(entry.getValue() != 0) { + storage::StateActionTarget sat = {s,a,entry.getColumn()}; + var = solver.addBinaryVariable("beta_" + to_string(sat)); + mBetaVariables[sat] = var; + } + } + + } + } + } + + + + void createConstraints(double boundary, storm::storage::BitVector const& relevantStates) { + // (5) and (7) are omitted on purpose (-- we currenty do not support controllability of actions -- ) + + // (1) + assert(mdp->getInitialStates().getNumberOfSetBits() == 1); + uint_fast64_t initialStateIndex = mdp->getInitialStates().getNextSetIndex(0); + solver.addConstraint("c1", mProbVariables[initialStateIndex] >= solver.getConstant(boundary)); + for(uint_fast64_t s : relevantStates) { + std::string stateString = std::to_string(s); + storm::expressions::Expression expr = solver.getConstant(0.0); + // (2) + for(uint_fast64_t a = 0; a < mdp->getNumberOfChoices(s); ++a) { + expr = expr + multistrategyVariables[storage::StateActionPair(s,a)]; + } + solver.addConstraint("c2-" + stateString, solver.getConstant(1) <= expr); + // (5) + solver.addConstraint("c5-" + std::to_string(s), mProbVariables[s] <= mAlphaVariables[s]); + + // (3) For the relevant states. + for(uint_fast64_t a = 0; a < mdp->getNumberOfChoices(s); ++a) { + std::string sastring(stateString + "_" + std::to_string(a)); + expr = solver.getConstant(0.0); + for(auto const& entry : mdp->getTransitionMatrix().getRow(mdp->getNondeterministicChoiceIndices()[s]+a)) { + if(entry.getValue() != 0 && relevantStates.get(entry.getColumn())) { + expr = expr + solver.getConstant(entry.getValue()) * mProbVariables[entry.getColumn()]; + } else if (entry.getValue() != 0 && mGoals.get(entry.getColumn())) { + expr = expr + solver.getConstant(entry.getValue()); + } + } + solver.addConstraint("c3-" + sastring, mProbVariables[s] < (solver.getConstant(1) - multistrategyVariables[storage::StateActionPair(s,a)]) + expr); + } + + for(uint_fast64_t a = 0; a < mdp->getNumberOfChoices(s); ++a) { + // (6) + std::string sastring(stateString + "_" + std::to_string(a)); + expr = solver.getConstant(0.0); + for(auto const& entry : mdp->getTransitionMatrix().getRow(mdp->getNondeterministicChoiceIndices()[s]+a)) { + if(entry.getValue() != 0) { + storage::StateActionTarget sat = {s,a,entry.getColumn()}; + expr = expr + mBetaVariables[sat]; + } + } + solver.addConstraint("c6-" + sastring, multistrategyVariables[storage::StateActionPair(s,a)] == (solver.getConstant(1) - mAlphaVariables[s]) + expr); + + for(auto const& entry : mdp->getTransitionMatrix().getRow(mdp->getNondeterministicChoiceIndices()[s]+a)) { + if(entry.getValue() != 0) { + storage::StateActionTarget sat = {s,a,entry.getColumn()}; + std::string satstring = to_string(sat); + // (8) + assert(mGammaVariables.count(entry.getColumn()) > 0); + assert(mGammaVariables.count(s) > 0); + assert(mBetaVariables.count(sat) > 0); + solver.addConstraint("c8-" + satstring, mGammaVariables[entry.getColumn()] < mGammaVariables[s] + (solver.getConstant(1) - mBetaVariables[sat]) + mProbVariables[s]); // With rewards, we have to change this. + } + } + + } + } + } + + + /** + * + */ + void createMILP(double boundary, PermissiveSchedulerPenalties const& penalties) { + storm::storage::BitVector irrelevant = mGoals | mSinks; + storm::storage::BitVector relevantStates = ~irrelevant; + // Notice that the separated construction of variables and + // constraints slows down the construction of the MILP. + // In the future, we might want to merge this. + createVariables(penalties, relevantStates); + createConstraints(boundary, relevantStates); + + + solver.setModelSense(storm::solver::LpSolver::ModelSense::Minimize); + + } + }; + } +} + +#endif /* MILPPERMISSIVESCHEDULERS_H */ + diff --git a/src/permissivesched/PermissiveSchedulerComputation.h b/src/permissivesched/PermissiveSchedulerComputation.h new file mode 100644 index 000000000..5582ffc36 --- /dev/null +++ b/src/permissivesched/PermissiveSchedulerComputation.h @@ -0,0 +1,55 @@ +#ifndef PERMISSIVESCHEDULERCOMPUTATION_H +#define PERMISSIVESCHEDULERCOMPUTATION_H + +#include + +#include "../storage/BitVector.h" +#include "../models/sparse/Mdp.h" +#include "PermissiveSchedulerPenalty.h" +#include "PermissiveSchedulers.h" + +namespace storm { + namespace ps { + class PermissiveSchedulerComputation { + protected: + std::shared_ptr> mdp; + storm::storage::BitVector const& mGoals; + storm::storage::BitVector const& mSinks; + PermissiveSchedulerPenalties mPenalties; + + public: + + PermissiveSchedulerComputation(std::shared_ptr> mdp, storm::storage::BitVector const& goalstates, storm::storage::BitVector const& sinkstates) + : mdp(mdp), mGoals(goalstates), mSinks(sinkstates) + { + + } + + + virtual void calculatePermissiveScheduler(double boundary) = 0; + + void setPenalties(PermissiveSchedulerPenalties penalties) { + mPenalties = penalties; + } + + PermissiveSchedulerPenalties const& getPenalties() const { + return mPenalties; + } + + PermissiveSchedulerPenalties & getPenalties() { + return mPenalties; + } + + virtual bool foundSolution() const = 0; + + virtual MemorylessDeterministicPermissiveScheduler&& getScheduler() const = 0; + + + }; + + } +} + + +#endif /* PERMISSIVESCHEDULERCOMPUTATION_H */ + diff --git a/src/permissivesched/PermissiveSchedulerPenalty.h b/src/permissivesched/PermissiveSchedulerPenalty.h new file mode 100644 index 000000000..bb680defa --- /dev/null +++ b/src/permissivesched/PermissiveSchedulerPenalty.h @@ -0,0 +1,53 @@ +#ifndef PERMISSIVESCHEDULERPENALTY_H +#define PERMISSIVESCHEDULERPENALTY_H + +#include + +#include "../storage/StateActionPair.h" + +namespace storm { + namespace ps { + + class PermissiveSchedulerPenalties { + + std::unordered_map mPenalties; + + public: + double get(uint_fast64_t state, uint_fast64_t action) const { + return get(storage::StateActionPair(state, action)); + + } + + + double get(storage::StateActionPair const& sap) const { + auto it = mPenalties.find(sap); + if(it == mPenalties.end()) { + return 1.0; + } + else { + return it->second; + } + } + + void set(uint_fast64_t state, uint_fast64_t action, double penalty) { + assert(penalty >= 1.0); + if(penalty == 1.0) { + auto it = mPenalties.find(std::make_pair(state, action)); + if(it != mPenalties.end()) { + mPenalties.erase(it); + } + } else { + mPenalties.emplace(std::make_pair(state, action), penalty); + } + } + + void clear() { + mPenalties.clear(); + } + }; + } +} + + +#endif /* PERMISSIVESCHEDULERPENALTY_H */ + diff --git a/src/permissivesched/PermissiveSchedulers.cpp b/src/permissivesched/PermissiveSchedulers.cpp new file mode 100644 index 000000000..89665859e --- /dev/null +++ b/src/permissivesched/PermissiveSchedulers.cpp @@ -0,0 +1,31 @@ +#include "PermissiveSchedulers.h" +#include "../storage/BitVector.h" +#include "../utility/solver.h" +#include "../utility/graph.h" +#include "../modelchecker/propositional/SparsePropositionalModelChecker.h" +#include "../modelchecker/results/ExplicitQualitativeCheckResult.h" +#include "MILPPermissiveSchedulers.h" + + +namespace storm { + namespace ps { + + boost::optional computePermissiveSchedulerViaMILP(std::shared_ptr> mdp, storm::logic::ProbabilityOperatorFormula const& safeProp) { + storm::modelchecker::SparsePropositionalModelChecker propMC(*mdp); + assert(safeProp.getSubformula().isEventuallyFormula()); + auto backwardTransitions = mdp->getBackwardTransitions(); + storm::storage::BitVector goalstates = propMC.check(safeProp.getSubformula().asEventuallyFormula().getSubformula())->asExplicitQualitativeCheckResult().getTruthValuesVector(); + goalstates = storm::utility::graph::performProb1E(*mdp, backwardTransitions, storm::storage::BitVector(goalstates.size(), true), goalstates); + storm::storage::BitVector sinkstates = storm::utility::graph::performProb0A(*mdp,backwardTransitions, storm::storage::BitVector(goalstates.size(), true), goalstates); + + auto solver = storm::utility::solver::getLpSolver("Gurobi"); + MilpPermissiveSchedulerComputation comp(*solver, mdp, goalstates, sinkstates); + comp.calculatePermissiveScheduler(safeProp.getBound()); + if(comp.foundSolution()) { + return boost::optional(comp.getScheduler()); + } else { + return boost::optional(comp.getScheduler()); + } + } + } +} diff --git a/src/permissivesched/PermissiveSchedulers.h b/src/permissivesched/PermissiveSchedulers.h index a5d8b5574..d9bbd4e74 100644 --- a/src/permissivesched/PermissiveSchedulers.h +++ b/src/permissivesched/PermissiveSchedulers.h @@ -2,228 +2,24 @@ #ifndef PERMISSIVESCHEDULERS_H #define PERMISSIVESCHEDULERS_H -#include -#include "expressions/Variable.h" -#include "StateActionPair.h" -#include "StateActionTargetTuple.h" +#include "../logic/ProbabilityOperatorFormula.h" +#include "../models/sparse/Mdp.h" + namespace storm { - namespace storage { - class PermissiveSchedulerPenalties { - std::unordered_map mPenalties; - - public: - double get(uint_fast64_t state, uint_fast64_t action) const { - return get(StateActionPair(state, action)); - - } - - - double get(StateActionPair const& sap) const { - auto it = mPenalties.find(sap); - if(it == mPenalties.end()) { - return 1.0; - } - else { - return it->second; - } - } - - void set(uint_fast64_t state, uint_fast64_t action, double penalty) { - assert(penalty >= 1.0); - if(penalty == 1.0) { - auto it = mPenalties.find(std::make_pair(state, action)); - if(it != mPenalties.end()) { - mPenalties.erase(it); - } - } else { - mPenalties.emplace(std::make_pair(state, action), penalty); - } - } - - void clear() { - mPenalties.clear(); - } + namespace ps { + + class PermissiveScheduler { }; - class MilpPermissiveSchedulerComputation { - private: - - bool mCalledOptimizer = false; - storm::solver::LpSolver& solver; - std::shared_ptr> mdp; - std::unordered_map multistrategyVariables; - std::unordered_map mProbVariables; - std::unordered_map mAlphaVariables; - std::unordered_map mBetaVariables; - std::unordered_map mGammaVariables; - BitVector const& mGoals; - BitVector const& mSinks; - + class MemorylessDeterministicPermissiveScheduler : public PermissiveScheduler { + storm::storage::BitVector memdetschedulers; public: - - MilpPermissiveSchedulerComputation(storm::solver::LpSolver& milpsolver, std::shared_ptr> mdp, BitVector const& goalstates, BitVector const& sinkstates) - : solver(milpsolver), mdp(mdp), mGoals(goalstates), mSinks(sinkstates) - { - - } - - - void calculatePermissiveScheduler(double boundary, PermissiveSchedulerPenalties const& penalties, BitVector const& irrelevantStates = BitVector()) { - createMILP(boundary, penalties, irrelevantStates); - solver.optimize(); - mCalledOptimizer = true; - } - - bool foundSolution() { - assert(mCalledOptimizer); - return !solver.isInfeasible(); - } - - BitVector getAllowedStateActionPairs() const { - BitVector result(mdp->getNumberOfChoices(), true); - for(auto const& entry : multistrategyVariables) { - if(!solver.getBinaryValue(entry.second)) { - result.set(mdp->getNondeterministicChoiceIndices()[entry.first.getState()]+entry.first.getAction(), false); - } - } - return result; - } - - - private: - - /** - * - */ - void createVariables(PermissiveSchedulerPenalties const& penalties, BitVector const& relevantStates) { - // We need the unique initial state later, so we get that one before looping. - assert(mdp->getInitialStates().getNumberOfSetBits() == 1); - uint_fast64_t initialStateIndex = mdp->getInitialStates().getNextSetIndex(0); - - storm::expressions::Variable var; - for(uint_fast64_t s : relevantStates) { - // Create x_s variables - // Notice that only the initial probability appears in the objective. - if(s == initialStateIndex) { - var = solver.addLowerBoundedContinuousVariable("x_" + std::to_string(s), 0.0, -1.0); - } else { - var = solver.addLowerBoundedContinuousVariable("x_" + std::to_string(s), 0.0); - } - mProbVariables[s] = var; - // Create alpha_s variables - var = solver.addBinaryVariable("alp_" + std::to_string(s)); - mAlphaVariables[s] = var; - // Create gamma_s variables - var = solver.addBoundedContinuousVariable("gam_" + std::to_string(s), 0.0, 1.0); - mGammaVariables[s] = var; - for(uint_fast64_t a = 0; a < mdp->getNumberOfChoices(s); ++a) { - auto stateAndAction = StateActionPair(s,a); - // Create y_(s,a) variables - - double penalty = penalties.get(stateAndAction); - var = solver.addBinaryVariable("y_" + std::to_string(s) + "_" + std::to_string(a), -penalty); - multistrategyVariables[stateAndAction] = var; - - // Create beta_(s,a,t) variables - // Iterate over successors of s via a. - for(auto const& entry : mdp->getTransitionMatrix().getRow(mdp->getNondeterministicChoiceIndices()[s]+a)) { - if(entry.getValue() != 0) { - StateActionTarget sat = {s,a,entry.getColumn()}; - var = solver.addBinaryVariable("beta_" + to_string(sat)); - mBetaVariables[sat] = var; - } - } - - } - } - } - - - - void createConstraints(double boundary, storm::storage::BitVector const& relevantStates) { - // (5) and (7) are omitted on purpose (-- we currenty do not support controllability of actions -- ) - - // (1) - assert(mdp->getInitialStates().getNumberOfSetBits() == 1); - uint_fast64_t initialStateIndex = mdp->getInitialStates().getNextSetIndex(0); - solver.addConstraint("c1", mProbVariables[initialStateIndex] >= solver.getConstant(boundary)); - for(uint_fast64_t s : relevantStates) { - std::string stateString = std::to_string(s); - storm::expressions::Expression expr; - // (2) - for(uint_fast64_t a = 0; a < mdp->getNumberOfChoices(s); ++a) { - expr = expr + multistrategyVariables[StateActionPair(s,a)]; - } - solver.addConstraint("c2-" + stateString, solver.getConstant(1) <= expr); - // (5) - solver.addConstraint("c5-" + std::to_string(s), mProbVariables[s] <= mAlphaVariables[s]); - - // (3) For the relevant states. - for(uint_fast64_t a = 0; a < mdp->getNumberOfChoices(s); ++a) { - std::string sastring(stateString + "_" + std::to_string(a)); - expr = storm::expressions::Expression(); - for(auto const& entry : mdp->getTransitionMatrix().getRow(mdp->getNondeterministicChoiceIndices()[s]+a)) { - if(entry.getValue() != 0 && relevantStates.get(entry.getColumn())) { - expr = expr + solver.getConstant(entry.getValue()) * mProbVariables[entry.getColumn()]; - } else if (entry.getValue() != 0 && mGoals.get(entry.getColumn())) { - expr = expr + solver.getConstant(entry.getValue()); - } - } - solver.addConstraint("c3-" + sastring, mProbVariables[s] < (solver.getConstant(1) - multistrategyVariables[StateActionPair(s,a)]) + expr); - } - - for(uint_fast64_t a = 0; a < mdp->getNumberOfChoices(s); ++a) { - // (6) - std::string sastring(stateString + "_" + std::to_string(a)); - expr = storm::expressions::Expression(); - for(auto const& entry : mdp->getTransitionMatrix().getRow(mdp->getNondeterministicChoiceIndices()[s]+a)) { - if(entry.getValue() != 0) { - StateActionTarget sat = {s,a,entry.getColumn()}; - expr = expr + mBetaVariables[sat]; - } - } - solver.addConstraint("c6-" + sastring, multistrategyVariables[StateActionPair(s,a)] == (solver.getConstant(1) - mAlphaVariables[s]) + expr); - - for(auto const& entry : mdp->getTransitionMatrix().getRow(mdp->getNondeterministicChoiceIndices()[s]+a)) { - if(entry.getValue() != 0) { - StateActionTarget sat = {s,a,entry.getColumn()}; - std::string satstring = to_string(sat); - // (8) - solver.addConstraint("c8-" + satstring, mGammaVariables[entry.getColumn()] < mGammaVariables[s] + (solver.getConstant(1) - mBetaVariables[sat])); // With rewards, we have to change this. - } - } - - } - } - } - - - /** - * - */ - void createMILP(double boundary, PermissiveSchedulerPenalties const& penalties, BitVector const& dontCareStates ) { - BitVector irrelevant = mGoals | mSinks; - BitVector relevantStates = ~irrelevant; - // Notice that the separated construction of variables and - // constraints slows down the construction of the MILP. - // In the future, we might want to merge this. - createVariables(penalties, relevantStates); - createConstraints(boundary, relevantStates); - - - solver.setModelSense(storm::solver::LpSolver::ModelSense::Minimize); - - - } - - - - - + MemorylessDeterministicPermissiveScheduler(storm::storage::BitVector const& allowedPairs) : memdetschedulers(allowedPairs) {} }; + boost::optional computePermissiveSchedulerViaMILP(std::shared_ptr> mdp, storm::logic::ProbabilityOperatorFormula const& safeProp); } } diff --git a/src/permissivesched/SmtBasedPermissiveSchedulers.h b/src/permissivesched/SmtBasedPermissiveSchedulers.h new file mode 100644 index 000000000..9af6882ad --- /dev/null +++ b/src/permissivesched/SmtBasedPermissiveSchedulers.h @@ -0,0 +1,7 @@ +#ifndef SMTBASEDPERMISSIVESCHEDULERS_H +#define SMTBASEDPERMISSIVESCHEDULERS_H + + + +#endif /* SMTBASEDPERMISSIVESCHEDULERS_H */ + diff --git a/test/functional/builder/die_selection.nm b/test/functional/builder/die_selection.nm new file mode 100644 index 000000000..819472268 --- /dev/null +++ b/test/functional/builder/die_selection.nm @@ -0,0 +1,45 @@ +// Knuth's model of a fair die using only fair coins +mdp + +module die + + // local state + s : [0..7] init 0; + // value of the dice + d : [0..6] init 0; + + [fair] s=0 -> 0.5 : (s'=1) + 0.5 : (s'=2); + [ufair1] s=0 -> 0.6 : (s'=1) + 0.4 : (s'=2); + [ufair2] s=0 -> 0.7 : (s'=1) + 0.3 : (s'=2); + [fair] s=1 -> 0.5 : (s'=3) + 0.5 : (s'=4); + [ufair1] s=1 -> 0.6 : (s'=3) + 0.4 : (s'=4); + [ufair2] s=1 -> 0.7 : (s'=3) + 0.3 : (s'=4); + [fair] s=2 -> 0.5 : (s'=5) + 0.5 : (s'=6); + [ufair1] s=2 -> 0.6 : (s'=5) + 0.4 : (s'=6); + [ufair2] s=2 -> 0.7 : (s'=5) + 0.3 : (s'=6); + [fair] s=3 -> 0.5 : (s'=1) + 0.5 : (s'=7) & (d'=1); + [ufair1] s=3 -> 0.6 : (s'=1) + 0.4 : (s'=7) & (d'=1); + [ufair2] s=3 -> 0.7 : (s'=1) + 0.3 : (s'=7) & (d'=1); + [fair] s=4 -> 0.5 : (s'=7) & (d'=2) + 0.5 : (s'=7) & (d'=3); + [ufair1] s=4 -> 0.6 : (s'=7) & (d'=2) + 0.4 : (s'=7) & (d'=3); + [ufair2] s=4 -> 0.7 : (s'=7) & (d'=2) + 0.3 : (s'=7) & (d'=3); + [fair] s=5 -> 0.5 : (s'=7) & (d'=4) + 0.5 : (s'=7) & (d'=5); + [ufair1] s=5 -> 0.6 : (s'=2) + 0.4 : (s'=7) & (d'=6); + [ufair2] s=5 -> 0.7 : (s'=2) + 0.3 : (s'=7) & (d'=6); + [] s=7 -> 1: (s'=7); + +endmodule + +rewards "coin_flips" + [fair] s<7 : 1; + [ufair1] s<7 : 1; + [ufair2] s<7 : 1; +endrewards + +label "one" = s=7&d=1; +label "two" = s=7&d=2; +label "three" = s=7&d=3; +label "four" = s=7&d=4; +label "five" = s=7&d=5; +label "six" = s=7&d=6; +label "done" = s=7; diff --git a/test/functional/permissiveschedulers/MilpPermissiveSchedulerTest.cpp b/test/functional/permissiveschedulers/MilpPermissiveSchedulerTest.cpp new file mode 100644 index 000000000..a66a6f693 --- /dev/null +++ b/test/functional/permissiveschedulers/MilpPermissiveSchedulerTest.cpp @@ -0,0 +1,31 @@ +#include "gtest/gtest.h" +#include "storm-config.h" +#include "src/parser/PrismParser.h" +#include "src/parser/FormulaParser.h" +#include "src/logic/Formulas.h" +#include "src/permissivesched/PermissiveSchedulers.h" +#include "src/builder/ExplicitPrismModelBuilder.h" + + +TEST(MilpPermissiveSchedulerTest, DieSelection) { + storm::prism::Program program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/die_selection.nm"); + storm::parser::FormulaParser formulaParser(program.getManager().getSharedPointer()); + std::cout << " We are now here " << std::endl; + auto formula = formulaParser.parseFromString("P<=0.2 [ F \"one\"]")->asProbabilityOperatorFormula(); + std::cout << formula << std::endl; + + // Customize and perform model-building. + typename storm::builder::ExplicitPrismModelBuilder::Options options; + + options = typename storm::builder::ExplicitPrismModelBuilder::Options(formula); + options.addConstantDefinitionsFromString(program, ""); + options.buildRewards = false; + options.buildCommandLabels = true; + + std::shared_ptr> mdp = storm::builder::ExplicitPrismModelBuilder::translateProgram(program, options)->as>(); + + storm::ps::computePermissiveSchedulerViaMILP(mdp, formula); + + // + +}