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