27template<
typename StateType>
31 if (!stateToId.contains(cs)) {
32 return static_cast<StateType
>(this->size());
34 return this->stateToId.getValue(cs);
37template<
typename StateType>
39 return this->stateToId.size();
42template<
typename ValueType,
typename RewardModelType,
typename StateType>
44 auto const& buildSettings = storm::settings::getModule<storm::settings::modules::BuildSettings>();
47 if (buildSettings.isExplorationStateLimitSet()) {
52template<
typename ValueType,
typename RewardModelType,
typename StateType>
55 : generator(generator), options(options), stateStorage(generator->getStateSize()) {
59template<
typename ValueType,
typename RewardModelType,
typename StateType>
67template<
typename ValueType,
typename RewardModelType,
typename StateType>
71 requires(!storm::IsIntervalType<ValueType>)
76template<
typename ValueType,
typename RewardModelType,
typename StateType>
80 switch (generator->getModelType()) {
94 STORM_LOG_THROW(
false, storm::exceptions::WrongFormatException,
"Error while creating model: cannot handle this model type.");
100template<
typename ValueType,
typename RewardModelType,
typename StateType>
102 StateType newIndex =
static_cast<StateType
>(stateStorage.getNumberOfStates());
105 std::pair<StateType, std::size_t> actualIndexBucketPair = stateStorage.stateToId.findOrAddAndGetBucket(state, newIndex);
107 StateType actualIndex = actualIndexBucketPair.first;
109 if (actualIndex == newIndex) {
111 statesToExplore.emplace_front(state, actualIndex);
114 stateRemapping.get().push_back(storm::utility::zero<StateType>());
116 statesToExplore.emplace_back(state, actualIndex);
125template<
typename ValueType,
typename RewardModelType,
typename StateType>
130template<
typename ValueType,
typename RewardModelType,
typename StateType>
137 stateAndChoiceInformationBuilder.
stateValuationsBuilder() = generator->initializeStateValuationsBuilder();
142 std::bind(&ExplicitModelBuilder<ValueType, RewardModelType, StateType>::getOrAddStateIndex,
this, std::placeholders::_1);
148 stateRemapping = std::vector<uint_fast64_t>();
152 this->stateStorage.initialStateIndices = generator->getInitialStates(stateToIdCallback);
153 STORM_LOG_THROW(!this->stateStorage.initialStateIndices.empty(), storm::exceptions::WrongFormatException,
154 "The model does not have a single initial state.");
157 uint_fast64_t currentRowGroup = 0;
158 uint_fast64_t currentRow = 0;
160 auto timeOfStart = std::chrono::high_resolution_clock::now();
161 auto timeOfLastMessage = std::chrono::high_resolution_clock::now();
162 uint64_t numberOfExploredStates = 0;
163 uint64_t numberOfExploredStatesSinceLastMessage = 0;
166 while (!statesToExplore.empty()) {
169 StateType currentIndex = statesToExplore.front().second;
170 statesToExplore.pop_front();
175 stateRemapping.
get()[currentIndex] = currentRowGroup;
178 if (currentIndex % 100000 == 0) {
182 generator->load(currentState);
189 bool const stateLimitExceeded = options.explorationStateLimit.has_value() && stateStorage.getNumberOfStates() >= options.explorationStateLimit.value();
190 if (!stateLimitExceeded) {
191 behavior = generator->expand(stateToIdCallback);
194 if (behavior.
empty()) {
198 STORM_LOG_THROW(options.fixDeadlocks, storm::exceptions::WrongFormatException,
199 "Error while creating sparse matrix from probabilistic program: found deadlock state ("
200 << generator->stateToString(currentState) <<
"). For fixing these, please provide the appropriate option.");
201 this->stateStorage.deadlockStateIndices.push_back(currentIndex);
203 if (stateLimitExceeded) {
205 this->stateStorage.unexploredStateIndices.push_back(currentIndex);
212 if (!generator->isDeterministicModel()) {
216 transitionMatrixBuilder.
addNextValue(currentRow, currentIndex, storm::utility::one<ValueType>());
218 for (
auto& rewardModelBuilder : rewardModelBuilders) {
219 if (rewardModelBuilder.hasStateRewards()) {
220 rewardModelBuilder.addStateReward(storm::utility::zero<ValueType>());
223 if (rewardModelBuilder.hasStateActionRewards()) {
224 rewardModelBuilder.addStateActionReward(storm::utility::zero<ValueType>());
241 for (
auto& rewardModelBuilder : rewardModelBuilders) {
242 if (rewardModelBuilder.hasStateRewards()) {
243 rewardModelBuilder.addStateReward(*stateRewardIt);
249 if (!generator->isDeterministicModel()) {
254 bool firstChoiceOfState =
true;
255 for (
auto const& choice : behavior) {
258 for (
auto const& label : choice.getLabels()) {
259 stateAndChoiceInformationBuilder.
addChoiceLabel(label, currentRow);
268 "There is a state where different players have an enabled choice.");
269 if (firstChoiceOfState) {
278 for (
auto const& stateProbabilityPair : choice) {
279 transitionMatrixBuilder.
addNextValue(currentRow, stateProbabilityPair.first, stateProbabilityPair.second);
283 auto choiceRewardIt = choice.getRewards().begin();
284 for (
auto& rewardModelBuilder : rewardModelBuilders) {
285 if (rewardModelBuilder.hasStateActionRewards()) {
286 rewardModelBuilder.addStateActionReward(*choiceRewardIt);
291 firstChoiceOfState =
false;
297 ++numberOfExploredStates;
298 if (generator->getOptions().isShowProgressSet()) {
299 ++numberOfExploredStatesSinceLastMessage;
301 auto now = std::chrono::high_resolution_clock::now();
302 auto durationSinceLastMessage = std::chrono::duration_cast<std::chrono::seconds>(now - timeOfLastMessage).count();
303 if (
static_cast<uint64_t
>(durationSinceLastMessage) >= generator->getOptions().getShowProgressDelay()) {
304 auto statesPerSecond = numberOfExploredStatesSinceLastMessage / durationSinceLastMessage;
305 auto durationSinceStart = std::chrono::duration_cast<std::chrono::seconds>(now - timeOfStart).count();
306 std::cout <<
"Explored " << numberOfExploredStates <<
" states in " << durationSinceStart <<
" seconds (currently " << statesPerSecond
307 <<
" states per second).\n";
308 timeOfLastMessage = std::chrono::high_resolution_clock::now();
309 numberOfExploredStatesSinceLastMessage = 0;
314 auto durationSinceStart = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::high_resolution_clock::now() - timeOfStart).count();
315 std::cout <<
"Explored " << numberOfExploredStates <<
" states in " << durationSinceStart <<
" seconds before abort.\n";
316 STORM_LOG_THROW(
false, storm::exceptions::AbortException,
"Aborted in state space exploration.");
325 std::vector<uint_fast64_t>
const& remapping = stateRemapping.get();
337 std::vector<StateType> newInitialStateIndices(this->stateStorage.initialStateIndices.size());
338 std::transform(this->stateStorage.initialStateIndices.begin(), this->stateStorage.initialStateIndices.end(), newInitialStateIndices.begin(),
339 [&remapping](StateType
const& state) { return remapping[state]; });
340 std::sort(newInitialStateIndices.begin(), newInitialStateIndices.end());
341 this->stateStorage.initialStateIndices = std::move(newInitialStateIndices);
344 this->stateStorage.stateToId.remap([&remapping](StateType
const& state) {
return remapping[state]; });
346 this->generator->remapStateIds([&remapping](StateType
const& state) {
return remapping[state]; });
350template<
typename ValueType,
typename RewardModelType,
typename StateType>
354 bool deterministicModel = generator->isDeterministicModel();
358 std::vector<RewardModelBuilder<typename RewardModelType::ValueType>> rewardModelBuilders;
359 for (uint64_t i = 0;
i < generator->getNumberOfRewardModels(); ++
i) {
360 rewardModelBuilders.emplace_back(generator->getRewardModelInformation(i));
362 StateAndChoiceInformationBuilder stateAndChoiceInformationBuilder;
363 stateAndChoiceInformationBuilder.
setBuildChoiceLabels(generator->getOptions().isBuildChoiceLabelsSet());
364 stateAndChoiceInformationBuilder.setBuildChoiceOrigins(generator->getOptions().isBuildChoiceOriginsSet());
367 stateAndChoiceInformationBuilder.setBuildStateValuations(generator->getOptions().isBuildStateValuationsSet());
369 buildMatrices(transitionMatrixBuilder, rewardModelBuilders, stateAndChoiceInformationBuilder);
374 std::unordered_map<std::string, RewardModelType>(), !generator->isDiscreteTimeModel());
376 uint_fast64_t numStates = modelComponents.transitionMatrix.getColumnCount();
377 uint_fast64_t numChoices = modelComponents.transitionMatrix.getRowCount();
380 for (
auto& rewardModelBuilder : rewardModelBuilders) {
381 modelComponents.rewardModels.emplace(rewardModelBuilder.getName(),
382 rewardModelBuilder.build(numChoices, modelComponents.transitionMatrix.getColumnCount(), numStates));
385 if (stateAndChoiceInformationBuilder.isBuildStatePlayerIndications()) {
386 modelComponents.statePlayerIndications = stateAndChoiceInformationBuilder.buildStatePlayerIndications(numStates);
387 modelComponents.playerNameToIndexMap = generator->getPlayerNameToIndexMap();
390 if (stateAndChoiceInformationBuilder.isBuildMarkovianStates()) {
391 modelComponents.markovianStates = stateAndChoiceInformationBuilder.buildMarkovianStates(numStates);
394 if (stateAndChoiceInformationBuilder.isBuildChoiceLabels()) {
395 modelComponents.choiceLabeling = stateAndChoiceInformationBuilder.buildChoiceLabeling(numChoices);
398 if (stateAndChoiceInformationBuilder.isBuildStateValuations()) {
399 modelComponents.stateValuations = stateAndChoiceInformationBuilder.stateValuationsBuilder().build();
401 if (stateAndChoiceInformationBuilder.isBuildChoiceOrigins()) {
402 auto originData = stateAndChoiceInformationBuilder.buildDataOfChoiceOrigins(numChoices);
403 modelComponents.choiceOrigins = generator->generateChoiceOrigins(originData);
405 if (generator->isPartiallyObservable()) {
406 std::vector<uint32_t> classes(stateStorage.getNumberOfStates());
407 std::unordered_map<uint32_t, std::vector<std::pair<std::vector<std::string>, uint32_t>>> observationActions;
408 for (
auto const& bitVectorIndexPair : stateStorage.stateToId) {
409 uint32_t varObservation = generator->observabilityClass(bitVectorIndexPair.first);
410 classes[bitVectorIndexPair.second] = varObservation;
413 modelComponents.observabilityClasses = classes;
414 if (generator->getOptions().isBuildObservationValuationsSet()) {
415 modelComponents.observationValuations = generator->makeObservationValuation();
418 return modelComponents;
421template<
typename ValueType,
typename RewardModelType,
typename StateType>
423 return generator->label(stateStorage, stateStorage.initialStateIndices, stateStorage.deadlockStateIndices, stateStorage.unexploredStateIndices);
427template class ExplicitModelBuilder<double, storm::models::sparse::StandardRewardModel<double>, uint32_t>;
428template class ExplicitStateLookup<uint32_t>;
430template class ExplicitModelBuilder<RationalNumber, storm::models::sparse::StandardRewardModel<RationalNumber>, uint32_t>;
431template class ExplicitModelBuilder<RationalFunction, storm::models::sparse::StandardRewardModel<RationalFunction>, uint32_t>;
432template class ExplicitModelBuilder<double, storm::models::sparse::StandardRewardModel<storm::Interval>, uint32_t>;
433template class ExplicitModelBuilder<storm::Interval, 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(uint64_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
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