42template<
typename StateType>
46 if (!stateToId.contains(cs)) {
47 return static_cast<StateType
>(this->size());
49 return this->stateToId.getValue(cs);
52template<
typename StateType>
54 return this->stateToId.size();
57template<
typename ValueType,
typename RewardModelType,
typename StateType>
62 if (buildSettings.isExplorationStateLimitSet()) {
67template<
typename ValueType,
typename RewardModelType,
typename StateType>
70 : generator(generator), options(options), stateStorage(generator->getStateSize()) {
74template<
typename ValueType,
typename RewardModelType,
typename StateType>
82template<
typename ValueType,
typename RewardModelType,
typename StateType>
90template<
typename ValueType,
typename RewardModelType,
typename StateType>
94 switch (generator->getModelType()) {
108 STORM_LOG_THROW(
false, storm::exceptions::WrongFormatException,
"Error while creating model: cannot handle this model type.");
114template<
typename ValueType,
typename RewardModelType,
typename StateType>
116 StateType newIndex =
static_cast<StateType
>(stateStorage.getNumberOfStates());
119 std::pair<StateType, std::size_t> actualIndexBucketPair = stateStorage.stateToId.findOrAddAndGetBucket(state, newIndex);
121 StateType actualIndex = actualIndexBucketPair.first;
123 if (actualIndex == newIndex) {
125 statesToExplore.emplace_front(state, actualIndex);
128 stateRemapping.get().push_back(storm::utility::zero<StateType>());
130 statesToExplore.emplace_back(state, actualIndex);
139template<
typename ValueType,
typename RewardModelType,
typename StateType>
144template<
typename ValueType,
typename RewardModelType,
typename StateType>
151 stateAndChoiceInformationBuilder.
stateValuationsBuilder() = generator->initializeStateValuationsBuilder();
156 std::bind(&ExplicitModelBuilder<ValueType, RewardModelType, StateType>::getOrAddStateIndex,
this, std::placeholders::_1);
162 stateRemapping = std::vector<uint_fast64_t>();
166 this->stateStorage.initialStateIndices = generator->getInitialStates(stateToIdCallback);
167 STORM_LOG_THROW(!this->stateStorage.initialStateIndices.empty(), storm::exceptions::WrongFormatException,
168 "The model does not have a single initial state.");
171 uint_fast64_t currentRowGroup = 0;
172 uint_fast64_t currentRow = 0;
174 auto timeOfStart = std::chrono::high_resolution_clock::now();
175 auto timeOfLastMessage = std::chrono::high_resolution_clock::now();
176 uint64_t numberOfExploredStates = 0;
177 uint64_t numberOfExploredStatesSinceLastMessage = 0;
180 while (!statesToExplore.empty()) {
183 StateType currentIndex = statesToExplore.front().second;
184 statesToExplore.pop_front();
189 stateRemapping.
get()[currentIndex] = currentRowGroup;
192 if (currentIndex % 100000 == 0) {
196 generator->load(currentState);
203 bool const stateLimitExceeded = options.explorationStateLimit.has_value() && stateStorage.getNumberOfStates() >= options.explorationStateLimit.value();
204 if (!stateLimitExceeded) {
205 behavior = generator->expand(stateToIdCallback);
208 if (behavior.
empty()) {
212 STORM_LOG_THROW(options.fixDeadlocks, storm::exceptions::WrongFormatException,
213 "Error while creating sparse matrix from probabilistic program: found deadlock state ("
214 << generator->stateToString(currentState) <<
"). For fixing these, please provide the appropriate option.");
215 this->stateStorage.deadlockStateIndices.push_back(currentIndex);
217 if (stateLimitExceeded) {
219 this->stateStorage.unexploredStateIndices.push_back(currentIndex);
226 if (!generator->isDeterministicModel()) {
230 transitionMatrixBuilder.
addNextValue(currentRow, currentIndex, storm::utility::one<ValueType>());
232 for (
auto& rewardModelBuilder : rewardModelBuilders) {
233 if (rewardModelBuilder.hasStateRewards()) {
234 rewardModelBuilder.addStateReward(storm::utility::zero<ValueType>());
237 if (rewardModelBuilder.hasStateActionRewards()) {
238 rewardModelBuilder.addStateActionReward(storm::utility::zero<ValueType>());
255 for (
auto& rewardModelBuilder : rewardModelBuilders) {
256 if (rewardModelBuilder.hasStateRewards()) {
257 rewardModelBuilder.addStateReward(*stateRewardIt);
263 if (!generator->isDeterministicModel()) {
268 bool firstChoiceOfState =
true;
269 for (
auto const& choice : behavior) {
272 for (
auto const& label : choice.getLabels()) {
273 stateAndChoiceInformationBuilder.
addChoiceLabel(label, currentRow);
282 "There is a state where different players have an enabled choice.");
283 if (firstChoiceOfState) {
292 for (
auto const& stateProbabilityPair : choice) {
293 transitionMatrixBuilder.
addNextValue(currentRow, stateProbabilityPair.first, stateProbabilityPair.second);
297 auto choiceRewardIt = choice.getRewards().begin();
298 for (
auto& rewardModelBuilder : rewardModelBuilders) {
299 if (rewardModelBuilder.hasStateActionRewards()) {
300 rewardModelBuilder.addStateActionReward(*choiceRewardIt);
305 firstChoiceOfState =
false;
311 ++numberOfExploredStates;
312 if (generator->getOptions().isShowProgressSet()) {
313 ++numberOfExploredStatesSinceLastMessage;
315 auto now = std::chrono::high_resolution_clock::now();
316 auto durationSinceLastMessage = std::chrono::duration_cast<std::chrono::seconds>(now - timeOfLastMessage).count();
317 if (
static_cast<uint64_t
>(durationSinceLastMessage) >= generator->getOptions().getShowProgressDelay()) {
318 auto statesPerSecond = numberOfExploredStatesSinceLastMessage / durationSinceLastMessage;
319 auto durationSinceStart = std::chrono::duration_cast<std::chrono::seconds>(now - timeOfStart).count();
320 std::cout <<
"Explored " << numberOfExploredStates <<
" states in " << durationSinceStart <<
" seconds (currently " << statesPerSecond
321 <<
" states per second).\n";
322 timeOfLastMessage = std::chrono::high_resolution_clock::now();
323 numberOfExploredStatesSinceLastMessage = 0;
328 auto durationSinceStart = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::high_resolution_clock::now() - timeOfStart).count();
329 std::cout <<
"Explored " << numberOfExploredStates <<
" states in " << durationSinceStart <<
" seconds before abort.\n";
330 STORM_LOG_THROW(
false, storm::exceptions::AbortException,
"Aborted in state space exploration.");
339 std::vector<uint_fast64_t>
const& remapping = stateRemapping.get();
351 std::vector<StateType> newInitialStateIndices(this->stateStorage.initialStateIndices.size());
352 std::transform(this->stateStorage.initialStateIndices.begin(), this->stateStorage.initialStateIndices.end(), newInitialStateIndices.begin(),
353 [&remapping](StateType
const& state) { return remapping[state]; });
354 std::sort(newInitialStateIndices.begin(), newInitialStateIndices.end());
355 this->stateStorage.initialStateIndices = std::move(newInitialStateIndices);
358 this->stateStorage.stateToId.remap([&remapping](StateType
const& state) {
return remapping[state]; });
360 this->generator->remapStateIds([&remapping](StateType
const& state) {
return remapping[state]; });
364template<
typename ValueType,
typename RewardModelType,
typename StateType>
368 bool deterministicModel = generator->isDeterministicModel();
372 std::vector<RewardModelBuilder<typename RewardModelType::ValueType>> rewardModelBuilders;
373 for (uint64_t i = 0;
i < generator->getNumberOfRewardModels(); ++
i) {
374 rewardModelBuilders.emplace_back(generator->getRewardModelInformation(i));
376 StateAndChoiceInformationBuilder stateAndChoiceInformationBuilder;
377 stateAndChoiceInformationBuilder.
setBuildChoiceLabels(generator->getOptions().isBuildChoiceLabelsSet());
378 stateAndChoiceInformationBuilder.setBuildChoiceOrigins(generator->getOptions().isBuildChoiceOriginsSet());
381 stateAndChoiceInformationBuilder.setBuildStateValuations(generator->getOptions().isBuildStateValuationsSet());
383 buildMatrices(transitionMatrixBuilder, rewardModelBuilders, stateAndChoiceInformationBuilder);
388 std::unordered_map<std::string, RewardModelType>(), !generator->isDiscreteTimeModel());
390 uint_fast64_t numStates = modelComponents.transitionMatrix.getColumnCount();
391 uint_fast64_t numChoices = modelComponents.transitionMatrix.getRowCount();
394 for (
auto& rewardModelBuilder : rewardModelBuilders) {
395 modelComponents.rewardModels.emplace(rewardModelBuilder.getName(),
396 rewardModelBuilder.build(numChoices, modelComponents.transitionMatrix.getColumnCount(), numStates));
399 if (stateAndChoiceInformationBuilder.isBuildStatePlayerIndications()) {
400 modelComponents.statePlayerIndications = stateAndChoiceInformationBuilder.buildStatePlayerIndications(numStates);
401 modelComponents.playerNameToIndexMap = generator->getPlayerNameToIndexMap();
404 if (stateAndChoiceInformationBuilder.isBuildMarkovianStates()) {
405 modelComponents.markovianStates = stateAndChoiceInformationBuilder.buildMarkovianStates(numStates);
408 if (stateAndChoiceInformationBuilder.isBuildChoiceLabels()) {
409 modelComponents.choiceLabeling = stateAndChoiceInformationBuilder.buildChoiceLabeling(numChoices);
412 if (stateAndChoiceInformationBuilder.isBuildStateValuations()) {
413 modelComponents.stateValuations = stateAndChoiceInformationBuilder.stateValuationsBuilder().build();
415 if (stateAndChoiceInformationBuilder.isBuildChoiceOrigins()) {
416 auto originData = stateAndChoiceInformationBuilder.buildDataOfChoiceOrigins(numChoices);
417 modelComponents.choiceOrigins = generator->generateChoiceOrigins(originData);
419 if (generator->isPartiallyObservable()) {
420 std::vector<uint32_t> classes(stateStorage.getNumberOfStates());
421 std::unordered_map<uint32_t, std::vector<std::pair<std::vector<std::string>, uint32_t>>> observationActions;
422 for (
auto const& bitVectorIndexPair : stateStorage.stateToId) {
423 uint32_t varObservation = generator->observabilityClass(bitVectorIndexPair.first);
424 classes[bitVectorIndexPair.second] = varObservation;
427 modelComponents.observabilityClasses = classes;
428 if (generator->getOptions().isBuildObservationValuationsSet()) {
429 modelComponents.observationValuations = generator->makeObservationValuation();
432 return modelComponents;
435template<
typename ValueType,
typename RewardModelType,
typename StateType>
437 return generator->label(stateStorage, stateStorage.initialStateIndices, stateStorage.deadlockStateIndices, stateStorage.unexploredStateIndices);
441template class ExplicitModelBuilder<double, storm::models::sparse::StandardRewardModel<double>, uint32_t>;
442template class ExplicitStateLookup<uint32_t>;
444#ifdef STORM_HAVE_CARL
445template class ExplicitModelBuilder<RationalNumber, storm::models::sparse::StandardRewardModel<RationalNumber>, uint32_t>;
446template class ExplicitModelBuilder<RationalFunction, storm::models::sparse::StandardRewardModel<RationalFunction>, uint32_t>;
447template class ExplicitModelBuilder<double, storm::models::sparse::StandardRewardModel<storm::Interval>, uint32_t>;
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.
This class manages the labeling of the state space with a number of (atomic) labels.
A bit vector that is internally represented as a vector of 64-bit values.
bool get(uint_fast64_t index) const
Retrieves the truth value of the bit at the given index and performs a bound check.
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
SettingsType const & getModule()
Get module.
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).
Options()
Creates an object representing the default building options.
std::optional< StateType > explorationStateLimit
ExplorationOrder explorationOrder