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