25template<
typename StateType>
29 if (!stateToId.contains(cs)) {
30 return static_cast<StateType
>(this->
size());
32 return this->stateToId.getValue(cs);
35template<
typename StateType>
37 return this->stateToId.size();
40template<
typename ValueType,
typename RewardModelType,
typename StateType>
46template<
typename ValueType,
typename RewardModelType,
typename StateType>
49 : generator(generator), options(options), stateStorage(generator->getStateSize()) {
53template<
typename ValueType,
typename RewardModelType,
typename StateType>
61template<
typename ValueType,
typename RewardModelType,
typename StateType>
70template<
typename ValueType,
typename RewardModelType,
typename StateType>
74 switch (generator->getModelType()) {
88 STORM_LOG_THROW(
false, storm::exceptions::WrongFormatException,
"Error while creating model: cannot handle this model type.");
94template<
typename ValueType,
typename RewardModelType,
typename StateType>
95StateType ExplicitModelBuilder<ValueType, RewardModelType, StateType>::getOrAddStateIndex(
CompressedState const& state) {
96 StateType newIndex =
static_cast<StateType
>(stateStorage.getNumberOfStates());
99 std::pair<StateType, std::size_t> actualIndexBucketPair = stateStorage.stateToId.findOrAddAndGetBucket(state, newIndex);
101 StateType actualIndex = actualIndexBucketPair.first;
103 if (actualIndex == newIndex) {
105 statesToExplore.emplace_front(state, actualIndex);
110 statesToExplore.emplace_back(state, actualIndex);
119template<
typename ValueType,
typename RewardModelType,
typename StateType>
124template<
typename ValueType,
typename RewardModelType,
typename StateType>
125void ExplicitModelBuilder<ValueType, RewardModelType, StateType>::buildMatrices(
136 std::bind(&ExplicitModelBuilder<ValueType, RewardModelType, StateType>::getOrAddStateIndex,
this, std::placeholders::_1);
142 stateRemapping = std::vector<uint_fast64_t>();
146 this->stateStorage.initialStateIndices = generator->getInitialStates(stateToIdCallback);
147 STORM_LOG_THROW(!this->stateStorage.initialStateIndices.empty(), storm::exceptions::WrongFormatException,
148 "The model does not have a single initial state.");
151 uint_fast64_t currentRowGroup = 0;
152 uint_fast64_t currentRow = 0;
154 auto timeOfStart = std::chrono::high_resolution_clock::now();
155 auto timeOfLastMessage = std::chrono::high_resolution_clock::now();
156 uint64_t numberOfExploredStates = 0;
157 uint64_t numberOfExploredStatesSinceLastMessage = 0;
160 while (!statesToExplore.empty()) {
163 StateType currentIndex = statesToExplore.front().second;
164 statesToExplore.pop_front();
169 stateRemapping.get()[currentIndex] = currentRowGroup;
172 if (currentIndex % 100000 == 0) {
176 generator->
load(currentState);
178 generator->addStateValuation(currentIndex, stateAndChoiceInformationBuilder.
stateValuations());
181 storm::generator::StateBehavior<ValueType, StateType> behavior;
183 bool const stateLimitExceeded = options.explorationStateLimit.has_value() && stateStorage.getNumberOfStates() >= options.explorationStateLimit.value();
184 if (!stateLimitExceeded) {
185 behavior = generator->expand(stateToIdCallback);
188 if (behavior.
empty()) {
192 STORM_LOG_THROW(options.fixDeadlocks, storm::exceptions::WrongFormatException,
193 "Error while creating sparse matrix from probabilistic program: found deadlock state ("
194 << generator->stateToString(currentState) <<
"). For fixing these, please provide the appropriate option.");
195 this->stateStorage.deadlockStateIndices.push_back(currentIndex);
197 if (stateLimitExceeded) {
199 this->stateStorage.unexploredStateIndices.push_back(currentIndex);
206 if (!generator->isDeterministicModel()) {
212 for (
auto& rewardModelBuilder : rewardModelBuilders) {
213 if (rewardModelBuilder.hasStateRewards()) {
217 if (rewardModelBuilder.hasStateActionRewards()) {
235 for (
auto& rewardModelBuilder : rewardModelBuilders) {
236 if (rewardModelBuilder.hasStateRewards()) {
237 rewardModelBuilder.addStateReward(*stateRewardIt);
243 if (!generator->isDeterministicModel()) {
248 bool firstChoiceOfState =
true;
249 for (
auto const& choice : behavior) {
252 for (
auto const& label : choice.getLabels()) {
253 stateAndChoiceInformationBuilder.
addChoiceLabel(label, currentRow);
262 "There is a state where different players have an enabled choice.");
263 if (firstChoiceOfState) {
272 for (
auto const& stateProbabilityPair : choice) {
273 transitionMatrixBuilder.
addNextValue(currentRow, stateProbabilityPair.first, stateProbabilityPair.second);
277 auto choiceRewardIt = choice.getRewards().begin();
278 for (
auto& rewardModelBuilder : rewardModelBuilders) {
279 if (rewardModelBuilder.hasStateActionRewards()) {
280 rewardModelBuilder.addStateActionReward(*choiceRewardIt);
285 firstChoiceOfState =
false;
291 ++numberOfExploredStates;
292 if (generator->getOptions().isShowProgressSet()) {
293 ++numberOfExploredStatesSinceLastMessage;
295 auto now = std::chrono::high_resolution_clock::now();
296 auto durationSinceLastMessage = std::chrono::duration_cast<std::chrono::seconds>(now - timeOfLastMessage).count();
297 if (
static_cast<uint64_t
>(durationSinceLastMessage) >= generator->getOptions().getShowProgressDelay()) {
298 auto statesPerSecond = numberOfExploredStatesSinceLastMessage / durationSinceLastMessage;
299 auto durationSinceStart = std::chrono::duration_cast<std::chrono::seconds>(now - timeOfStart).count();
300 std::cout <<
"Explored " << numberOfExploredStates <<
" states in " << durationSinceStart <<
" seconds (currently " << statesPerSecond
301 <<
" states per second).\n";
302 timeOfLastMessage = std::chrono::high_resolution_clock::now();
303 numberOfExploredStatesSinceLastMessage = 0;
308 auto durationSinceStart = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::high_resolution_clock::now() - timeOfStart).count();
309 std::cout <<
"Explored " << numberOfExploredStates <<
" states in " << durationSinceStart <<
" seconds before abort.\n";
310 STORM_LOG_THROW(
false, storm::exceptions::AbortException,
"Aborted in state space exploration.");
319 std::vector<uint_fast64_t>
const& remapping = stateRemapping.get();
331 std::vector<StateType> newInitialStateIndices(this->stateStorage.initialStateIndices.size());
332 std::transform(this->stateStorage.initialStateIndices.begin(), this->stateStorage.initialStateIndices.end(), newInitialStateIndices.begin(),
333 [&remapping](StateType
const& state) { return remapping[state]; });
334 std::sort(newInitialStateIndices.begin(), newInitialStateIndices.end());
335 this->stateStorage.initialStateIndices = std::move(newInitialStateIndices);
338 this->stateStorage.stateToId.remap([&remapping](StateType
const& state) {
return remapping[state]; });
340 this->generator->remapStateIds([&remapping](StateType
const& state) {
return remapping[state]; });
344template<
typename ValueType,
typename RewardModelType,
typename StateType>
345storm::storage::sparse::ModelComponents<ValueType, RewardModelType> ExplicitModelBuilder<ValueType, RewardModelType, StateType>::buildModelComponents() {
348 bool deterministicModel = generator->isDeterministicModel();
351 storm::storage::SparseMatrixBuilder<ValueType> transitionMatrixBuilder(0, 0, 0,
false, !deterministicModel, 0);
352 std::vector<RewardModelBuilder<typename RewardModelType::ValueType>> rewardModelBuilders;
353 for (uint64_t i = 0;
i < generator->getNumberOfRewardModels(); ++
i) {
354 rewardModelBuilders.emplace_back(generator->getRewardModelInformation(i));
357 stateAndChoiceInformationBuilder.
setBuildChoiceLabels(generator->getOptions().isBuildChoiceLabelsSet());
358 stateAndChoiceInformationBuilder.setBuildChoiceOrigins(generator->getOptions().isBuildChoiceOriginsSet());
361 stateAndChoiceInformationBuilder.setBuildStateValuations(generator->getOptions().isBuildStateValuationsSet());
363 buildMatrices(transitionMatrixBuilder, rewardModelBuilders, stateAndChoiceInformationBuilder);
366 storm::storage::sparse::ModelComponents<ValueType, RewardModelType> modelComponents(
368 std::unordered_map<std::string, RewardModelType>(), !generator->isDiscreteTimeModel());
370 uint_fast64_t numStates = modelComponents.transitionMatrix.getColumnCount();
371 uint_fast64_t numChoices = modelComponents.transitionMatrix.getRowCount();
374 for (
auto& rewardModelBuilder : rewardModelBuilders) {
375 modelComponents.rewardModels.emplace(rewardModelBuilder.getName(),
376 rewardModelBuilder.build(numChoices, modelComponents.transitionMatrix.getColumnCount(), numStates));
379 if (stateAndChoiceInformationBuilder.isBuildStatePlayerIndications()) {
380 modelComponents.statePlayerIndications = stateAndChoiceInformationBuilder.buildStatePlayerIndications(numStates);
381 modelComponents.playerNameToIndexMap = generator->getPlayerNameToIndexMap();
384 if (stateAndChoiceInformationBuilder.isBuildMarkovianStates()) {
385 modelComponents.markovianStates = stateAndChoiceInformationBuilder.buildMarkovianStates(numStates);
388 if (stateAndChoiceInformationBuilder.isBuildChoiceLabels()) {
389 modelComponents.choiceLabeling = stateAndChoiceInformationBuilder.buildChoiceLabeling(numChoices);
392 if (stateAndChoiceInformationBuilder.isBuildStateValuations()) {
393 modelComponents.stateValuations = std::move(stateAndChoiceInformationBuilder.stateValuations());
395 if (stateAndChoiceInformationBuilder.isBuildChoiceOrigins()) {
396 auto originData = stateAndChoiceInformationBuilder.buildDataOfChoiceOrigins(numChoices);
397 modelComponents.choiceOrigins = generator->generateChoiceOrigins(originData);
399 if (generator->isPartiallyObservable()) {
400 std::vector<uint32_t> classes(stateStorage.getNumberOfStates());
401 std::unordered_map<uint32_t, std::vector<std::pair<std::vector<std::string>, uint32_t>>> observationActions;
402 for (
auto const& bitVectorIndexPair : stateStorage.stateToId) {
403 uint32_t varObservation = generator->observabilityClass(bitVectorIndexPair.first);
404 classes[bitVectorIndexPair.second] = varObservation;
407 modelComponents.observabilityClasses = classes;
408 if (generator->getOptions().isBuildObservationValuationsSet()) {
409 modelComponents.observationValuations = generator->makeObservationValuation();
412 return modelComponents;
415template<
typename ValueType,
typename RewardModelType,
typename StateType>
416storm::models::sparse::StateLabeling ExplicitModelBuilder<ValueType, RewardModelType, StateType>::buildStateLabeling() {
417 return generator->label(stateStorage, stateStorage.initialStateIndices, stateStorage.deadlockStateIndices, stateStorage.unexploredStateIndices);
ExplicitStateLookup< StateType > exportExplicitStateLookup() const
Export a wrapper that contains (a copy of) the internal information that maps states to ids.
ExplicitModelBuilder(std::shared_ptr< storm::generator::NextStateGenerator< ValueType, StateType > > const &generator, Options const &options=Options())
Creates an explicit model builder that uses the provided generator.
std::shared_ptr< storm::models::sparse::Model< ValueType, RewardModelType > > build()
Convert the program given at construction time to an abstract model.
StateType lookup(std::map< storm::expressions::Variable, storm::expressions::Expression > const &stateDescription) const
Lookup state.
uint64_t size() const
How many states have been stored?
A structure that is used to keep track of a reward model currently being built.
bool empty() const
Retrieves whether the behavior is empty in the sense that there are no available choices.
bool wasExpanded() const
Retrieves whether the state was expanded.
std::vector< ValueType > const & getStateRewards() const
Retrieves the list of state rewards under selected reward models.
static BitVector load(std::string const &description)
A class that can be used to build a sparse matrix by adding value by value.
index_type getCurrentRowGroupCount() const
Retrieves the current row group count.
void addNextValue(index_type row, index_type column, value_type const &value)
Sets the matrix entry at the given row and column to the given value.
void replaceColumns(std::vector< index_type > const &replacements, index_type offset)
Replaces all columns with id > offset according to replacements.
void newRowGroup(index_type startingRow)
Starts a new row group in the matrix.
SparseMatrix< value_type > build(index_type overriddenRowCount=0, index_type overriddenColumnCount=0, index_type overriddenRowGroupCount=0)
#define STORM_LOG_DEBUG(message)
#define STORM_LOG_TRACE(message)
#define STORM_LOG_ASSERT(cond, message)
#define STORM_LOG_THROW(cond, exception, message)
CompressedState createCompressedState(VariableInformation const &varInfo, std::map< storm::expressions::Variable, storm::expressions::Expression > const &stateDescription, bool checkOutOfBounds)
storm::storage::BitVector CompressedState
storm::builder::BuilderOptions NextStateGeneratorOptions
std::shared_ptr< storm::models::sparse::Model< ValueType, RewardModelType > > buildModelFromComponents(storm::models::ModelType modelType, storm::storage::sparse::ModelComponents< ValueType, RewardModelType > &&components)
bool isTerminate()
Check whether the program should terminate (due to some abort signal).
constexpr bool IsIntervalType
Helper to check if a type is an interval.
Options()
Creates an object representing the default building options.
std::optional< StateType > explorationStateLimit
ExplorationOrder explorationOrder