Browse Source
introduced PostScheduler
introduced PostScheduler
this allows for different choice mappings per state, in the sense of 'what should I schedule if another scheduler has already picked a different action'tempestpy_adaptions
Stefan Pranger
4 years ago
3 changed files with 283 additions and 16 deletions
-
167src/storm/storage/PostScheduler.cpp
-
100src/storm/storage/PostScheduler.h
-
32src/storm/storage/Scheduler.h
@ -0,0 +1,167 @@ |
|||||
|
#include "storm/utility/vector.h"
|
||||
|
#include "storm/storage/PostScheduler.h"
|
||||
|
|
||||
|
#include "storm/utility/macros.h"
|
||||
|
#include "storm/exceptions/NotImplementedException.h"
|
||||
|
#include <boost/algorithm/string/join.hpp>
|
||||
|
|
||||
|
namespace storm { |
||||
|
namespace storage { |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
PostScheduler<ValueType>::PostScheduler(uint_fast64_t numberOfModelStates, std::vector<uint_fast64_t> numberOfChoicesPerState, boost::optional<storm::storage::MemoryStructure> const& memoryStructure) : Scheduler<ValueType>(numberOfModelStates, memoryStructure) { |
||||
|
STORM_LOG_DEBUG(numberOfChoicesPerState.size() << " " << numberOfModelStates); |
||||
|
STORM_LOG_ASSERT(numberOfChoicesPerState.size() == numberOfModelStates, "Need to know amount of choices per model state"); |
||||
|
uint_fast64_t numOfMemoryStates = memoryStructure ? memoryStructure->getNumberOfStates() : 1; |
||||
|
schedulerChoiceMapping = std::vector<std::vector<std::vector<SchedulerChoice<ValueType>>>>(numOfMemoryStates, std::vector<std::vector<SchedulerChoice<ValueType>>>(numberOfModelStates)); |
||||
|
for(uint state = 0; state < numberOfModelStates; state++) { |
||||
|
schedulerChoiceMapping[0][state].resize(numberOfChoicesPerState[state]); |
||||
|
} |
||||
|
numberOfChoices = 0; |
||||
|
for(std::vector<uint_fast64_t>::iterator it = numberOfChoicesPerState.begin(); it != numberOfChoicesPerState.end(); ++it) |
||||
|
numberOfChoices += *it; |
||||
|
this->numOfUndefinedChoices = numOfMemoryStates * numberOfChoices; |
||||
|
this->numOfDeterministicChoices = 0; |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
PostScheduler<ValueType>::PostScheduler(uint_fast64_t numberOfModelStates, std::vector<uint_fast64_t> numberOfChoicesPerState, boost::optional<storm::storage::MemoryStructure>&& memoryStructure) : Scheduler<ValueType>(numberOfModelStates, std::move(memoryStructure)) { |
||||
|
STORM_LOG_ASSERT(numberOfChoicesPerState.size() == numberOfModelStates, "Need to know amount of choices per model state"); |
||||
|
uint_fast64_t numOfMemoryStates = memoryStructure ? memoryStructure->getNumberOfStates() : 1; |
||||
|
schedulerChoiceMapping = std::vector<std::vector<std::vector<SchedulerChoice<ValueType>>>>(numOfMemoryStates, std::vector<std::vector<SchedulerChoice<ValueType>>>(numberOfModelStates)); |
||||
|
for(uint state = 0; state < numberOfModelStates; state++) { |
||||
|
schedulerChoiceMapping[0][state].resize(numberOfChoicesPerState[state]); |
||||
|
} |
||||
|
numberOfChoices = 0; |
||||
|
for(std::vector<uint_fast64_t>::iterator it = numberOfChoicesPerState.begin(); it != numberOfChoicesPerState.end(); ++it) |
||||
|
numberOfChoices += *it; |
||||
|
this->numOfUndefinedChoices = numOfMemoryStates * numberOfChoices; |
||||
|
this->numOfDeterministicChoices = 0; |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
void PostScheduler<ValueType>::setChoice(OldChoice const& oldChoice, SchedulerChoice<ValueType> const& newChoice, uint_fast64_t modelState, uint_fast64_t memoryState) { |
||||
|
STORM_LOG_ASSERT(memoryState == 0, "Currently we do not support PostScheduler with memory"); |
||||
|
STORM_LOG_ASSERT(modelState < schedulerChoiceMapping[memoryState].size(), "Illegal model state index"); |
||||
|
|
||||
|
//auto& schedulerChoice = schedulerChoiceMapping[memoryState][modelState];
|
||||
|
//if (schedulerChoice.isDefined()) {
|
||||
|
// if (!choice.isDefined()) {
|
||||
|
// ++numOfUndefinedChoices;
|
||||
|
// }
|
||||
|
//} else {
|
||||
|
// if (choice.isDefined()) {
|
||||
|
// assert(numOfUndefinedChoices > 0);
|
||||
|
// --numOfUndefinedChoices;
|
||||
|
// }
|
||||
|
//}
|
||||
|
//if (schedulerChoice.isDeterministic()) {
|
||||
|
// if (!choice.isDeterministic()) {
|
||||
|
// assert(numOfDeterministicChoices > 0);
|
||||
|
// --numOfDeterministicChoices;
|
||||
|
// }
|
||||
|
//} else {
|
||||
|
// if (choice.isDeterministic()) {
|
||||
|
// ++numOfDeterministicChoices;
|
||||
|
// }
|
||||
|
//}
|
||||
|
schedulerChoiceMapping[memoryState][modelState][oldChoice] = newChoice; |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
SchedulerChoice<ValueType> const& PostScheduler<ValueType>::getChoice(uint_fast64_t modelState, OldChoice oldChoice, uint_fast64_t memoryState) { |
||||
|
STORM_LOG_ASSERT(memoryState < this->getNumberOfMemoryStates(), "Illegal memory state index"); |
||||
|
STORM_LOG_ASSERT(modelState < schedulerChoiceMapping[memoryState].size(), "Illegal model state index"); |
||||
|
return schedulerChoiceMapping[memoryState][modelState][oldChoice]; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
template <typename ValueType> |
||||
|
bool PostScheduler<ValueType>::isDeterministicScheduler() const { |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
bool PostScheduler<ValueType>::isMemorylessScheduler() const { |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
template <typename ValueType> |
||||
|
void PostScheduler<ValueType>::printToStream(std::ostream& out, std::shared_ptr<storm::models::sparse::Model<ValueType>> model, bool skipUniqueChoices) const { |
||||
|
|
||||
|
bool const stateValuationsGiven = model != nullptr && model->hasStateValuations(); |
||||
|
bool const choiceLabelsGiven = model != nullptr && model->hasChoiceLabeling(); |
||||
|
bool const choiceOriginsGiven = model != nullptr && model->hasChoiceOrigins(); |
||||
|
uint_fast64_t widthOfStates = std::to_string(schedulerChoiceMapping.front().size()).length(); |
||||
|
if (stateValuationsGiven) { |
||||
|
widthOfStates += model->getStateValuations().getStateInfo(schedulerChoiceMapping.front().size() - 1).length() + 5; |
||||
|
} |
||||
|
widthOfStates = std::max(widthOfStates, (uint_fast64_t)12); |
||||
|
uint_fast64_t numOfSkippedStatesWithUniqueChoice = 0; |
||||
|
out << std::setw(widthOfStates) << "model state:" << " " << (isMemorylessScheduler() ? "" : " memory: ") << "choice(s)" << std::endl; |
||||
|
for (uint_fast64_t state = 0; state < schedulerChoiceMapping.front().size(); ++state) { |
||||
|
// Print the state info
|
||||
|
if (stateValuationsGiven) { |
||||
|
out << std::setw(widthOfStates) << (std::to_string(state) + ": " + model->getStateValuations().getStateInfo(state)); |
||||
|
} else { |
||||
|
out << std::setw(widthOfStates) << state; |
||||
|
} |
||||
|
out << " "; |
||||
|
|
||||
|
bool firstChoiceIndex = true; |
||||
|
for(uint choiceIndex = 0; choiceIndex < schedulerChoiceMapping[0][state].size(); choiceIndex++) { |
||||
|
SchedulerChoice<ValueType> const& choice = schedulerChoiceMapping[0][state][choiceIndex]; |
||||
|
if(firstChoiceIndex) { |
||||
|
firstChoiceIndex = false; |
||||
|
out << std::to_string(choiceIndex) << ": "; |
||||
|
} else { |
||||
|
out << std::setw(widthOfStates + 5) << std::to_string(choiceIndex) << ": "; |
||||
|
} |
||||
|
if (choice.isDefined()) { |
||||
|
if (choice.isDeterministic()) { |
||||
|
if (choiceOriginsGiven) { |
||||
|
out << model->getChoiceOrigins()->getChoiceInfo(model->getTransitionMatrix().getRowGroupIndices()[state] + choice.getDeterministicChoice()); |
||||
|
} else { |
||||
|
out << choice.getDeterministicChoice(); |
||||
|
} |
||||
|
if (choiceLabelsGiven) { |
||||
|
auto choiceLabels = model->getChoiceLabeling().getLabelsOfChoice(model->getTransitionMatrix().getRowGroupIndices()[state] + choice.getDeterministicChoice()); |
||||
|
out << " {" << boost::join(choiceLabels, ", ") << "}"; |
||||
|
} |
||||
|
} else { |
||||
|
bool firstChoice = true; |
||||
|
for (auto const& choiceProbPair : choice.getChoiceAsDistribution()) { |
||||
|
if (firstChoice) { |
||||
|
firstChoice = false; |
||||
|
} else { |
||||
|
out << " + "; |
||||
|
} |
||||
|
out << choiceProbPair.second << ": ("; |
||||
|
if (choiceOriginsGiven) { |
||||
|
out << model->getChoiceOrigins()->getChoiceInfo(model->getTransitionMatrix().getRowGroupIndices()[state] + choiceProbPair.first); |
||||
|
} else { |
||||
|
out << choiceProbPair.first; |
||||
|
} |
||||
|
if (choiceLabelsGiven) { |
||||
|
auto choiceLabels = model->getChoiceLabeling().getLabelsOfChoice(model->getTransitionMatrix().getRowGroupIndices()[state] + choice.getDeterministicChoice()); |
||||
|
out << " {" << boost::join(choiceLabels, ", ") << "}"; |
||||
|
} |
||||
|
out << ")"; |
||||
|
} |
||||
|
} |
||||
|
} else { |
||||
|
out << "undefined."; |
||||
|
} |
||||
|
|
||||
|
// Todo: print memory updates
|
||||
|
out << std::endl; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
template class PostScheduler<double>; |
||||
|
#ifdef STORM_HAVE_CARL
|
||||
|
template class PostScheduler<storm::RationalNumber>; |
||||
|
#endif
|
||||
|
} |
||||
|
} |
@ -0,0 +1,100 @@ |
|||||
|
#pragma once |
||||
|
|
||||
|
#include <cstdint> |
||||
|
#include <map> |
||||
|
#include "storm/storage/SchedulerChoice.h" |
||||
|
#include "storm/storage/Scheduler.h" |
||||
|
|
||||
|
namespace storm { |
||||
|
namespace storage { |
||||
|
|
||||
|
/* |
||||
|
* TODO needs obvious changes in all comment blocks |
||||
|
* This class defines which action is chosen in a particular state of a non-deterministic model. More concretely, a scheduler maps a state s to i |
||||
|
* if the scheduler takes the i-th action available in s (i.e. the choices are relative to the states). |
||||
|
* A Choice can be undefined, deterministic |
||||
|
*/ |
||||
|
template <typename ValueType> |
||||
|
class PostScheduler : public Scheduler<ValueType> { |
||||
|
public: |
||||
|
typedef uint_fast64_t OldChoice; |
||||
|
/*! |
||||
|
* Initializes a scheduler for the given number of model states. |
||||
|
* |
||||
|
* @param numberOfModelStates number of model states |
||||
|
* @param memoryStructure the considered memory structure. If not given, the scheduler is considered as memoryless. |
||||
|
*/ |
||||
|
PostScheduler(uint_fast64_t numberOfModelStates, std::vector<uint_fast64_t> numberOfChoicesPerState, boost::optional<storm::storage::MemoryStructure> const& memoryStructure = boost::none); |
||||
|
PostScheduler(uint_fast64_t numberOfModelStates, std::vector<uint_fast64_t> numberOfChoicesPerState, boost::optional<storm::storage::MemoryStructure>&& memoryStructure); |
||||
|
|
||||
|
/*! |
||||
|
* Sets the choice defined by the scheduler for the given state. |
||||
|
* |
||||
|
* @param choice The choice to set for the given state. |
||||
|
* @param modelState The state of the model for which to set the choice. |
||||
|
* @param memoryState The state of the memoryStructure for which to set the choice. |
||||
|
*/ |
||||
|
void setChoice(OldChoice const& oldChoice, SchedulerChoice<ValueType> const& newChoice, uint_fast64_t modelState, uint_fast64_t memoryState = 0); |
||||
|
|
||||
|
/*! |
||||
|
* Is the scheduler defined on the states indicated by the selected-states bitvector? |
||||
|
*/ |
||||
|
bool isChoiceSelected(BitVector const& selectedStates, uint64_t memoryState = 0) const; |
||||
|
|
||||
|
/*! |
||||
|
* Clears the choice defined by the scheduler for the given state. |
||||
|
* |
||||
|
* @param modelState The state of the model for which to clear the choice. |
||||
|
* @param memoryState The state of the memoryStructure for which to clear the choice. |
||||
|
*/ |
||||
|
void clearChoice(uint_fast64_t modelState, uint_fast64_t memoryState = 0); |
||||
|
|
||||
|
/*! |
||||
|
* Gets the choice defined by the scheduler for the given model and memory state. |
||||
|
* |
||||
|
* @param state The state for which to get the choice. |
||||
|
* @param memoryState the memory state which we consider. |
||||
|
*/ |
||||
|
SchedulerChoice<ValueType> const& getChoice(uint_fast64_t modelState, OldChoice oldChoice, uint_fast64_t memoryState = 0) ; |
||||
|
|
||||
|
/*! |
||||
|
* Compute the Action Support: A bit vector that indicates all actions that are selected with positive probability in some memory state |
||||
|
*/ |
||||
|
//storm::storage::BitVector computeActionSupport(std::vector<uint64_t> const& nondeterministicChoiceIndicies) const; |
||||
|
|
||||
|
/*! |
||||
|
* Retrieves whether all defined choices are deterministic |
||||
|
*/ |
||||
|
bool isDeterministicScheduler() const; |
||||
|
|
||||
|
/*! |
||||
|
* Retrieves whether the scheduler considers a trivial memory structure (i.e., a memory structure with just a single state) |
||||
|
*/ |
||||
|
bool isMemorylessScheduler() const; |
||||
|
|
||||
|
/*! |
||||
|
* Retrieves the number of memory states this scheduler considers. |
||||
|
*/ |
||||
|
//uint_fast64_t getNumberOfMemoryStates() const; |
||||
|
|
||||
|
/*! |
||||
|
* Retrieves the memory structure associated with this scheduler |
||||
|
*/ |
||||
|
//boost::optional<storm::storage::MemoryStructure> const& getMemoryStructure() const; |
||||
|
|
||||
|
/*! |
||||
|
* Prints the scheduler to the given output stream. |
||||
|
* @param out The output stream |
||||
|
* @param model If given, provides additional information for printing (e.g., displaying the state valuations instead of state indices) |
||||
|
* @param skipUniqueChoices If true, the (unique) choice for deterministic states (i.e., states with only one enabled choice) is not printed explicitly. |
||||
|
* Requires a model to be given. |
||||
|
*/ |
||||
|
void printToStream(std::ostream& out, std::shared_ptr<storm::models::sparse::Model<ValueType>> model = nullptr, bool skipUniqueChoices = false) const; |
||||
|
private: |
||||
|
std::vector<std::vector<std::vector<SchedulerChoice<ValueType>>>> schedulerChoiceMapping; |
||||
|
|
||||
|
std::vector<uint_fast64_t> numberOfChoicesPerState; |
||||
|
uint_fast64_t numberOfChoices; |
||||
|
}; |
||||
|
} |
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue