Storm 1.11.1.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
SubsystemBuilder.cpp
Go to the documentation of this file.
2
3#include <boost/optional.hpp>
4
16#include "storm/utility/graph.h"
19
20namespace storm {
21namespace transformer {
22
23template<typename ValueType, typename RewardModelType>
27 auto const& ma = *originalModel.template as<storm::models::sparse::MarkovAutomaton<ValueType, RewardModelType>>();
28 components.markovianStates = ma.getMarkovianStates() % subsystem;
29 components.exitRates = storm::utility::vector::filterVector(ma.getExitRates(), subsystem);
30 components.rateTransitions = false; // Note that originalModel.getTransitionMatrix() contains probabilities
31 } else if (originalModel.isOfType(storm::models::ModelType::Ctmc)) {
32 auto const& ctmc = *originalModel.template as<storm::models::sparse::Ctmc<ValueType, RewardModelType>>();
33 components.exitRates = storm::utility::vector::filterVector(ctmc.getExitRateVector(), subsystem);
34 components.rateTransitions = true;
35 } else {
37 storm::exceptions::UnexpectedException, "Unexpected model type.");
38 }
39 // Nothing to be done if the model has deadlock States
40}
41
42template<typename RewardModelType>
43RewardModelType transformRewardModel(RewardModelType const& originalRewardModel, storm::storage::BitVector const& subsystem,
44 storm::storage::BitVector const& subsystemActions, bool makeRowGroupingTrivial) {
45 std::optional<std::vector<typename RewardModelType::ValueType>> stateRewardVector;
46 std::optional<std::vector<typename RewardModelType::ValueType>> stateActionRewardVector;
47 std::optional<storm::storage::SparseMatrix<typename RewardModelType::ValueType>> transitionRewardMatrix;
48 if (originalRewardModel.hasStateRewards()) {
49 stateRewardVector = storm::utility::vector::filterVector(originalRewardModel.getStateRewardVector(), subsystem);
50 }
51 if (originalRewardModel.hasStateActionRewards()) {
52 stateActionRewardVector = storm::utility::vector::filterVector(originalRewardModel.getStateActionRewardVector(), subsystemActions);
53 }
54 if (originalRewardModel.hasTransitionRewards()) {
55 transitionRewardMatrix = originalRewardModel.getTransitionRewardMatrix().getSubmatrix(false, subsystemActions, subsystem);
56 if (makeRowGroupingTrivial) {
57 STORM_LOG_ASSERT(transitionRewardMatrix.value().getColumnCount() == transitionRewardMatrix.value().getRowCount(), "Matrix should be square");
58 transitionRewardMatrix.value().makeRowGroupingTrivial();
59 }
60 }
61 return RewardModelType(std::move(stateRewardVector), std::move(stateActionRewardVector), std::move(transitionRewardMatrix));
62}
63
64template<typename ValueType, typename RewardModelType>
66 storm::storage::BitVector const& subsystemStates,
67 storm::storage::BitVector const& subsystemActions,
68 SubsystemBuilderOptions const& options) {
69 auto const& groupIndices = originalModel.getTransitionMatrix().getRowGroupIndices();
71 uint_fast64_t subsystemStateCount = subsystemStates.getNumberOfSetBits();
72 if (options.buildStateMapping) {
73 result.newToOldStateIndexMapping.reserve(subsystemStateCount);
74 }
75 if (options.buildActionMapping) {
76 result.newToOldActionIndexMapping.reserve(subsystemActions.getNumberOfSetBits());
77 }
78 storm::storage::BitVector deadlockStates;
79 if (options.fixDeadlocks) {
80 deadlockStates.resize(subsystemStates.size(), false);
81 }
82 // Get the set of actions that stay in the subsystem.
83 // Also establish the mappings if requested.
84 storm::storage::BitVector keptActions(originalModel.getTransitionMatrix().getRowCount(), false);
85 for (auto subsysState : subsystemStates) {
86 if (options.buildStateMapping) {
87 result.newToOldStateIndexMapping.push_back(subsysState);
88 }
89 bool hasDeadlock = true;
90 for (uint_fast64_t row = subsystemActions.getNextSetIndex(groupIndices[subsysState]); row < groupIndices[subsysState + 1];
91 row = subsystemActions.getNextSetIndex(row + 1)) {
92 bool allRowEntriesStayInSubsys = true;
93 if (options.checkTransitionsOutside) {
94 for (auto const& entry : originalModel.getTransitionMatrix().getRow(row)) {
95 if (!subsystemStates.get(entry.getColumn())) {
96 allRowEntriesStayInSubsys = false;
97 break;
98 }
99 }
100 }
101 if (allRowEntriesStayInSubsys) {
102 if (options.buildActionMapping) {
103 result.newToOldActionIndexMapping.push_back(row);
104 }
105 keptActions.set(row, true);
106 hasDeadlock = false;
107 }
108 }
109 if (hasDeadlock) {
110 STORM_LOG_THROW(options.fixDeadlocks, storm::exceptions::InvalidOperationException,
111 "Expected that in each state, at least one action is selected. Got a deadlock state instead. (violated at " << subsysState << ")");
112 if (options.buildActionMapping) {
113 result.newToOldActionIndexMapping.push_back(std::numeric_limits<uint64_t>::max());
114 }
115 deadlockStates.set(subsysState);
116 }
117 }
118 // If we have deadlock states we keep an action in each rowgroup of a deadlock states.
119 bool hasDeadlockStates = !deadlockStates.empty();
120 if (options.buildKeptActions) {
121 // store them now, before changing them.
122 result.keptActions = keptActions;
123 }
124 for (auto deadlockState : deadlockStates) {
125 keptActions.set(groupIndices[deadlockState], true);
126 }
127
128 // Transform the components of the model
130 if (hasDeadlockStates) {
131 // make deadlock choices a selfloop
132 components.transitionMatrix = originalModel.getTransitionMatrix();
133 components.transitionMatrix.makeRowGroupsAbsorbing(deadlockStates);
134 components.transitionMatrix.dropZeroEntries();
135 components.transitionMatrix = components.transitionMatrix.getSubmatrix(false, keptActions, subsystemStates);
136 } else {
137 components.transitionMatrix = originalModel.getTransitionMatrix().getSubmatrix(false, keptActions, subsystemStates);
138 }
139 if (options.makeRowGroupingTrivial) {
140 STORM_LOG_ASSERT(components.transitionMatrix.getColumnCount() == components.transitionMatrix.getRowCount(), "Matrix should be square");
141 components.transitionMatrix.makeRowGroupingTrivial();
142 }
143
144 components.stateLabeling = originalModel.getStateLabeling().getSubLabeling(subsystemStates);
145 for (auto const& rewardModel : originalModel.getRewardModels()) {
146 components.rewardModels.insert(
147 std::make_pair(rewardModel.first, transformRewardModel(rewardModel.second, subsystemStates, keptActions, options.makeRowGroupingTrivial)));
148 }
149 if (originalModel.hasChoiceLabeling()) {
150 components.choiceLabeling = originalModel.getChoiceLabeling().getSubLabeling(keptActions);
151 }
152 if (originalModel.hasStateValuations()) {
153 components.stateValuations = originalModel.getStateValuations().selectStates(subsystemStates);
154 }
155 if (originalModel.hasChoiceOrigins()) {
156 components.choiceOrigins = originalModel.getChoiceOrigins()->selectChoices(keptActions);
157 }
158
159 if (hasDeadlockStates) {
160 auto subDeadlockStates = deadlockStates % subsystemStates;
161 assert(deadlockStates.getNumberOfSetBits() == subDeadlockStates.getNumberOfSetBits());
162 // erase rewards, choice labels, choice origins
163 for (auto& rewModel : components.rewardModels) {
164 for (auto state : subDeadlockStates) {
165 rewModel.second.clearRewardAtState(state, components.transitionMatrix);
166 }
167 }
168 if (components.choiceLabeling) {
169 storm::storage::BitVector nonDeadlockChoices(components.transitionMatrix.getRowCount(), true);
170 for (auto state : subDeadlockStates) {
171 auto const& choice = components.transitionMatrix.getRowGroupIndices()[state];
172 nonDeadlockChoices.set(choice, false);
173 }
174 for (auto const& label : components.choiceLabeling.value().getLabels()) {
175 components.choiceLabeling->setChoices(label, components.choiceLabeling->getChoices(label) & nonDeadlockChoices);
176 }
177 }
178 if (components.choiceOrigins) {
179 for (auto state : subDeadlockStates) {
180 auto const& choice = components.transitionMatrix.getRowGroupIndices()[state];
181 components.choiceOrigins.value()->clearOriginOfChoice(choice);
182 }
183 }
184 // get a unique label for the deadlock states
185 result.deadlockLabel = "deadl";
186 while (components.stateLabeling.containsLabel(result.deadlockLabel.get())) {
187 result.deadlockLabel->push_back('_');
188 }
189 components.stateLabeling.addLabel(result.deadlockLabel.get(), std::move(subDeadlockStates));
190 }
191
192 transformModelSpecificComponents<ValueType, RewardModelType>(originalModel, subsystemStates, components);
193 models::ModelType newModelType = originalModel.getType();
194 if (components.transitionMatrix.hasTrivialRowGrouping() && originalModel.getType() == models::ModelType::Mdp) {
195 newModelType = models::ModelType::Dtmc;
196 }
197 result.model = storm::utility::builder::buildModelFromComponents(newModelType, std::move(components));
198 STORM_LOG_DEBUG("Subsystem Builder is done. Resulting model has " << result.model->getNumberOfStates() << " states.");
199 return result;
200}
201
202template<typename ValueType, typename RewardModelType>
204 storm::storage::BitVector const& subsystemStates,
205 storm::storage::BitVector const& subsystemActions, bool keepUnreachableStates,
206 SubsystemBuilderOptions options) {
207 STORM_LOG_DEBUG("Invoked subsystem builder on model with " << originalModel.getNumberOfStates() << " states.");
208 storm::storage::BitVector initialStates = originalModel.getInitialStates() & subsystemStates;
209 STORM_LOG_THROW(!initialStates.empty(), storm::exceptions::InvalidArgumentException, "The subsystem would not contain any initial states");
210
211 STORM_LOG_THROW(!subsystemStates.empty(), storm::exceptions::InvalidArgumentException, "Invoked SubsystemBuilder for an empty subsystem.");
212 if (keepUnreachableStates) {
213 return internalBuildSubsystem(originalModel, subsystemStates, subsystemActions, options);
214 } else {
215 auto actualSubsystem = storm::utility::graph::getReachableStates(originalModel.getTransitionMatrix(), initialStates, subsystemStates,
216 storm::storage::BitVector(subsystemStates.size(), false), false, 0, subsystemActions);
217 return internalBuildSubsystem(originalModel, actualSubsystem, subsystemActions, options);
218 }
219}
220
222 storm::storage::BitVector const& subsystemStates, storm::storage::BitVector const& subsystemActions,
223 bool keepUnreachableStates = true, SubsystemBuilderOptions options = SubsystemBuilderOptions());
226 storm::storage::BitVector const& subsystemStates, storm::storage::BitVector const& subsystemActions, bool keepUnreachableStates = true,
229 storm::storage::BitVector const& subsystemStates,
230 storm::storage::BitVector const& subsystemActions, bool keepUnreachableStates = true,
233 storm::storage::BitVector const& subsystemStates,
234 storm::storage::BitVector const& subsystemActions,
235 bool keepUnreachableStates = true,
238 storm::storage::BitVector const& subsystemStates,
239 storm::storage::BitVector const& subsystemActions, bool keepUnreachableStates = true,
241
242} // namespace transformer
243} // namespace storm
virtual ModelType getType() const
Return the actual type of the model.
Definition ModelBase.cpp:7
bool isOfType(storm::models::ModelType const &modelType) const
Checks whether the model is of the given type.
Definition ModelBase.cpp:27
ChoiceLabeling getSubLabeling(storm::storage::BitVector const &choices) const
Retrieves the sub labeling that represents the same labeling as the current one for all selected choi...
void addLabel(std::string const &label)
Adds a new label to the labelings.
bool containsLabel(std::string const &label) const
Checks whether a label is registered within this labeling.
Base class for all sparse models.
Definition Model.h:32
storm::models::sparse::ChoiceLabeling const & getChoiceLabeling() const
Retrieves the labels for the choices of the model.
Definition Model.cpp:336
storm::storage::SparseMatrix< ValueType > const & getTransitionMatrix() const
Retrieves the matrix representing the transitions of the model.
Definition Model.cpp:199
std::unordered_map< std::string, RewardModelType > const & getRewardModels() const
Retrieves the reward models.
Definition Model.cpp:691
bool hasStateValuations() const
Retrieves whether this model was build with state valuations.
Definition Model.cpp:351
storm::storage::sparse::StateValuations const & getStateValuations() const
Retrieves the valuations of the states of the model.
Definition Model.cpp:356
std::shared_ptr< storm::storage::sparse::ChoiceOrigins > const & getChoiceOrigins() const
Retrieves the origins of the choices of the model.
Definition Model.cpp:376
bool hasChoiceLabeling() const
Retrieves whether this model has a labeling of the choices.
Definition Model.cpp:331
storm::models::sparse::StateLabeling const & getStateLabeling() const
Returns the state labeling associated with this model.
Definition Model.cpp:321
bool hasChoiceOrigins() const
Retrieves whether this model was build with choice origins.
Definition Model.cpp:371
virtual uint_fast64_t getNumberOfStates() const override
Returns the number of states of the model.
Definition Model.cpp:164
storm::storage::BitVector const & getInitialStates() const
Retrieves the initial states of the model.
Definition Model.cpp:179
StateLabeling getSubLabeling(storm::storage::BitVector const &states) const
Retrieves the sub labeling that represents the same labeling as the current one for all selected stat...
A bit vector that is internally represented as a vector of 64-bit values.
Definition BitVector.h:16
uint64_t getNextSetIndex(uint64_t startingIndex) const
Retrieves the index of the bit that is the next bit set to true in the bit vector.
bool empty() const
Retrieves whether no bits are set to true in this bit vector.
uint64_t getNumberOfSetBits() const
Returns the number of bits that are set to true in this bit vector.
void set(uint64_t index, bool value=true)
Sets the given truth value at the given index.
size_t size() const
Retrieves the number of bits this bit vector can store.
void resize(uint64_t newLength, bool init=false)
Resizes the bit vector to hold the given new number of bits.
bool get(uint64_t index) const
Retrieves the truth value of the bit at the given index and performs a bound check.
StateValuations selectStates(storm::storage::BitVector const &selectedStates) const
#define STORM_LOG_DEBUG(message)
Definition logging.h:18
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:11
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
SubsystemBuilderReturnType< ValueType, RewardModelType > internalBuildSubsystem(storm::models::sparse::Model< ValueType, RewardModelType > const &originalModel, storm::storage::BitVector const &subsystemStates, storm::storage::BitVector const &subsystemActions, SubsystemBuilderOptions const &options)
void transformModelSpecificComponents(storm::models::sparse::Model< ValueType, RewardModelType > const &originalModel, storm::storage::BitVector const &subsystem, storm::storage::sparse::ModelComponents< ValueType, RewardModelType > &components)
RewardModelType transformRewardModel(RewardModelType const &originalRewardModel, storm::storage::BitVector const &subsystem, storm::storage::BitVector const &subsystemActions, bool makeRowGroupingTrivial)
SubsystemBuilderReturnType< ValueType, RewardModelType > buildSubsystem(storm::models::sparse::Model< ValueType, RewardModelType > const &originalModel, storm::storage::BitVector const &subsystemStates, storm::storage::BitVector const &subsystemActions, bool keepUnreachableStates, SubsystemBuilderOptions options)
std::shared_ptr< storm::models::sparse::Model< ValueType, RewardModelType > > buildModelFromComponents(storm::models::ModelType modelType, storm::storage::sparse::ModelComponents< ValueType, RewardModelType > &&components)
Definition builder.cpp:20
storm::storage::BitVector getReachableStates(storm::storage::SparseMatrix< T > const &transitionMatrix, storm::storage::BitVector const &initialStates, storm::storage::BitVector const &constraintStates, storm::storage::BitVector const &targetStates, bool useStepBound, uint_fast64_t maximalSteps, boost::optional< storm::storage::BitVector > const &choiceFilter)
Performs a forward depth-first search through the underlying graph structure to identify the states t...
Definition graph.cpp:41
std::vector< Type > filterVector(std::vector< Type > const &in, storm::storage::BitVector const &filter)
Definition vector.h:1060
std::optional< storm::storage::sparse::StateValuations > stateValuations
std::unordered_map< std::string, RewardModelType > rewardModels
storm::storage::SparseMatrix< ValueType > transitionMatrix
boost::optional< storm::storage::BitVector > markovianStates
std::optional< std::shared_ptr< storm::storage::sparse::ChoiceOrigins > > choiceOrigins
std::optional< storm::models::sparse::ChoiceLabeling > choiceLabeling
storm::models::sparse::StateLabeling stateLabeling
boost::optional< std::vector< ValueType > > exitRates
std::vector< uint_fast64_t > newToOldStateIndexMapping
std::shared_ptr< storm::models::sparse::Model< ValueType, RewardModelType > > model
boost::optional< std::string > deadlockLabel