Storm
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
SparseModelMemoryProduct.cpp
Go to the documentation of this file.
2
3#include <boost/optional.hpp>
4
16
18
19namespace storm {
20namespace storage {
21
22template<typename ValueType, typename RewardModelType>
24 storm::storage::MemoryStructure const& memoryStructure)
25 : isInitialized(false), memoryStateCount(memoryStructure.getNumberOfStates()), model(sparseModel), memory(memoryStructure), scheduler(boost::none) {
26 reachableStates = storm::storage::BitVector(model.getNumberOfStates() * memoryStateCount, false);
27}
28
29template<typename ValueType, typename RewardModelType>
32 : isInitialized(false),
33 memoryStateCount(scheduler.getNumberOfMemoryStates()),
34 model(sparseModel),
35 localMemory(scheduler.getMemoryStructure() ? boost::optional<MemoryStructure>()
36 : boost::optional<MemoryStructure>(
37 storm::storage::MemoryStructureBuilder<ValueType, RewardModelType>::buildTrivialMemoryStructure(model))),
38 memory(scheduler.getMemoryStructure() ? scheduler.getMemoryStructure().get() : localMemory.get()),
39 scheduler(scheduler) {
40 reachableStates = storm::storage::BitVector(model.getNumberOfStates() * memoryStateCount, false);
41}
42
43template<typename ValueType, typename RewardModelType>
45 if (!isInitialized) {
46 uint64_t modelStateCount = model.getNumberOfStates();
47
48 computeMemorySuccessors();
49
50 // Get the initial states and reachable states. A stateIndex s corresponds to the model state (s / memoryStateCount) and memory state (s %
51 // memoryStateCount)
52 storm::storage::BitVector initialStates(modelStateCount * memoryStateCount, false);
53 auto memoryInitIt = memory.getInitialMemoryStates().begin();
54 if (memory.isOnlyInitialStatesRelevantSet()) {
55 for (auto modelInit : model.getInitialStates()) {
56 initialStates.set(modelInit * memoryStateCount + *memoryInitIt, true);
57 ++memoryInitIt;
58 }
59 } else {
60 // Build Product from all model states
61 for (uint_fast64_t modelState = 0; modelState < model.getNumberOfStates(); ++modelState) {
62 initialStates.set(modelState * memoryStateCount + *memoryInitIt, true);
63 ++memoryInitIt;
64 }
65 }
66 STORM_LOG_ASSERT(memoryInitIt == memory.getInitialMemoryStates().end(), "Unexpected number of initial states.");
67
68 computeReachableStates(initialStates);
69
70 // Compute the mapping to the states of the result
71 uint64_t reachableStateCount = 0;
72 toResultStateMapping = std::vector<uint64_t>(model.getNumberOfStates() * memoryStateCount, std::numeric_limits<uint64_t>::max());
73 for (auto reachableState : reachableStates) {
74 toResultStateMapping[reachableState] = reachableStateCount;
75 ++reachableStateCount;
76 }
77
78 isInitialized = true;
79 }
80}
81
82template<typename ValueType, typename RewardModelType>
83void SparseModelMemoryProduct<ValueType, RewardModelType>::addReachableState(uint64_t const& modelState, uint64_t const& memoryState) {
84 isInitialized = false;
85 reachableStates.set(modelState * memoryStateCount + memoryState, true);
86}
87
88template<typename ValueType, typename RewardModelType>
90 isInitialized = false;
91 reachableStates.fill();
92}
93
94template<typename ValueType, typename RewardModelType>
95std::shared_ptr<storm::models::sparse::Model<ValueType, RewardModelType>> SparseModelMemoryProduct<ValueType, RewardModelType>::build() {
96 initialize();
97
98 // Build the model components
100 if (scheduler) {
101 transitionMatrix = buildTransitionMatrixForScheduler();
102 } else if (model.getTransitionMatrix().hasTrivialRowGrouping()) {
103 transitionMatrix = buildDeterministicTransitionMatrix();
104 } else {
105 transitionMatrix = buildNondeterministicTransitionMatrix();
106 }
107 storm::models::sparse::StateLabeling labeling = buildStateLabeling(transitionMatrix);
108 std::unordered_map<std::string, RewardModelType> rewardModels = buildRewardModels(transitionMatrix);
109
110 return buildResult(std::move(transitionMatrix), std::move(labeling), std::move(rewardModels));
111}
112
113template<typename ValueType, typename RewardModelType>
114bool SparseModelMemoryProduct<ValueType, RewardModelType>::isStateReachable(uint64_t const& modelState, uint64_t const& memoryState) {
115 STORM_LOG_ASSERT(modelState < getOriginalModel().getNumberOfStates(), "Invalid model state: " << modelState << ".");
116 STORM_LOG_ASSERT(memoryState < memoryStateCount, "Invalid memory state: " << memoryState << ".");
117 initialize();
118 return reachableStates.get(modelState * memoryStateCount + memoryState);
119}
120
121template<typename ValueType, typename RewardModelType>
122uint64_t const& SparseModelMemoryProduct<ValueType, RewardModelType>::getResultState(uint64_t const& modelState, uint64_t const& memoryState) {
123 initialize();
124 STORM_LOG_ASSERT(isStateReachable(modelState, memoryState), "Tried to get unreachable product state (" << modelState << "," << memoryState << ")");
125 return toResultStateMapping[modelState * memoryStateCount + memoryState];
126}
127
128template<typename ValueType, typename RewardModelType>
130 uint64_t modelTransitionCount = model.getTransitionMatrix().getEntryCount();
131 memorySuccessors = std::vector<uint64_t>(modelTransitionCount * memoryStateCount, std::numeric_limits<uint64_t>::max());
132
133 for (uint64_t memoryState = 0; memoryState < memoryStateCount; ++memoryState) {
134 for (uint64_t transitionGoal = 0; transitionGoal < memoryStateCount; ++transitionGoal) {
135 auto const& memoryTransition = memory.getTransitionMatrix()[memoryState][transitionGoal];
136 if (memoryTransition) {
137 for (auto modelTransitionIndex : memoryTransition.get()) {
138 memorySuccessors[modelTransitionIndex * memoryStateCount + memoryState] = transitionGoal;
139 }
140 }
141 }
142 }
143}
144
145template<typename ValueType, typename RewardModelType>
146void SparseModelMemoryProduct<ValueType, RewardModelType>::computeReachableStates(storm::storage::BitVector const& initialStates) {
147 // Explore the reachable states via DFS.
148 // A state s on the stack corresponds to the model state (s / memoryStateCount) and memory state (s % memoryStateCount)
149 reachableStates |= initialStates;
150 if (!reachableStates.full()) {
151 std::vector<uint64_t> stack(reachableStates.begin(), reachableStates.end());
152 while (!stack.empty()) {
153 uint64_t stateIndex = stack.back();
154 stack.pop_back();
155 uint64_t modelState = stateIndex / memoryStateCount;
156 uint64_t memoryState = stateIndex % memoryStateCount;
157
158 if (scheduler) {
159 auto choices = scheduler->getChoice(modelState, memoryState).getChoiceAsDistribution();
160 uint64_t groupStart = model.getTransitionMatrix().getRowGroupIndices()[modelState];
161 for (auto const& choice : choices) {
162 STORM_LOG_ASSERT(groupStart + choice.first < model.getTransitionMatrix().getRowGroupIndices()[modelState + 1],
163 "Invalid choice " << choice.first << " at model state " << modelState << ".");
164 auto const& row = model.getTransitionMatrix().getRow(groupStart + choice.first);
165 for (auto modelTransitionIt = row.begin(); modelTransitionIt != row.end(); ++modelTransitionIt) {
166 if (!storm::utility::isZero(modelTransitionIt->getValue())) {
167 uint64_t successorModelState = modelTransitionIt->getColumn();
168 uint64_t modelTransitionId = modelTransitionIt - model.getTransitionMatrix().begin();
169 uint64_t successorMemoryState = memorySuccessors[modelTransitionId * memoryStateCount + memoryState];
170 uint64_t successorStateIndex = successorModelState * memoryStateCount + successorMemoryState;
171 if (!reachableStates.get(successorStateIndex)) {
172 reachableStates.set(successorStateIndex, true);
173 stack.push_back(successorStateIndex);
174 }
175 }
176 }
177 }
178 } else {
179 auto const& rowGroup = model.getTransitionMatrix().getRowGroup(modelState);
180 for (auto modelTransitionIt = rowGroup.begin(); modelTransitionIt != rowGroup.end(); ++modelTransitionIt) {
181 if (!storm::utility::isZero(modelTransitionIt->getValue())) {
182 uint64_t successorModelState = modelTransitionIt->getColumn();
183 uint64_t modelTransitionId = modelTransitionIt - model.getTransitionMatrix().begin();
184 uint64_t successorMemoryState = memorySuccessors[modelTransitionId * memoryStateCount + memoryState];
185 uint64_t successorStateIndex = successorModelState * memoryStateCount + successorMemoryState;
186 if (!reachableStates.get(successorStateIndex)) {
187 reachableStates.set(successorStateIndex, true);
188 stack.push_back(successorStateIndex);
189 }
190 }
191 }
192 }
193 }
194 }
195}
196
197template<typename ValueType, typename RewardModelType>
198storm::storage::SparseMatrix<ValueType> SparseModelMemoryProduct<ValueType, RewardModelType>::buildDeterministicTransitionMatrix() {
199 uint64_t numResStates = reachableStates.getNumberOfSetBits();
200 uint64_t numResTransitions = 0;
201 for (auto stateIndex : reachableStates) {
202 numResTransitions += model.getTransitionMatrix().getRow(stateIndex / memoryStateCount).getNumberOfEntries();
203 }
204
205 storm::storage::SparseMatrixBuilder<ValueType> builder(numResStates, numResStates, numResTransitions, true);
206 uint64_t currentRow = 0;
207 for (auto stateIndex : reachableStates) {
208 uint64_t modelState = stateIndex / memoryStateCount;
209 uint64_t memoryState = stateIndex % memoryStateCount;
210 auto const& modelRow = model.getTransitionMatrix().getRow(modelState);
211 for (auto entryIt = modelRow.begin(); entryIt != modelRow.end(); ++entryIt) {
212 uint64_t transitionId = entryIt - model.getTransitionMatrix().begin();
213 uint64_t successorMemoryState = memorySuccessors[transitionId * memoryStateCount + memoryState];
214 builder.addNextValue(currentRow, getResultState(entryIt->getColumn(), successorMemoryState), entryIt->getValue());
215 }
216 ++currentRow;
217 }
218
219 return builder.build();
220}
221
222template<typename ValueType, typename RewardModelType>
223storm::storage::SparseMatrix<ValueType> SparseModelMemoryProduct<ValueType, RewardModelType>::buildNondeterministicTransitionMatrix() {
224 uint64_t numResStates = reachableStates.getNumberOfSetBits();
225 uint64_t numResChoices = 0;
226 uint64_t numResTransitions = 0;
227 for (auto stateIndex : reachableStates) {
228 uint64_t modelState = stateIndex / memoryStateCount;
229 for (uint64_t modelRow = model.getTransitionMatrix().getRowGroupIndices()[modelState];
230 modelRow < model.getTransitionMatrix().getRowGroupIndices()[modelState + 1]; ++modelRow) {
231 ++numResChoices;
232 numResTransitions += model.getTransitionMatrix().getRow(modelRow).getNumberOfEntries();
233 }
234 }
235
236 storm::storage::SparseMatrixBuilder<ValueType> builder(numResChoices, numResStates, numResTransitions, true, true, numResStates);
237 uint64_t currentRow = 0;
238 for (auto stateIndex : reachableStates) {
239 uint64_t modelState = stateIndex / memoryStateCount;
240 uint64_t memoryState = stateIndex % memoryStateCount;
241 builder.newRowGroup(currentRow);
242 for (uint64_t modelRowIndex = model.getTransitionMatrix().getRowGroupIndices()[modelState];
243 modelRowIndex < model.getTransitionMatrix().getRowGroupIndices()[modelState + 1]; ++modelRowIndex) {
244 auto const& modelRow = model.getTransitionMatrix().getRow(modelRowIndex);
245 for (auto entryIt = modelRow.begin(); entryIt != modelRow.end(); ++entryIt) {
246 uint64_t transitionId = entryIt - model.getTransitionMatrix().begin();
247 uint64_t successorMemoryState = memorySuccessors[transitionId * memoryStateCount + memoryState];
248 builder.addNextValue(currentRow, getResultState(entryIt->getColumn(), successorMemoryState), entryIt->getValue());
249 }
250 ++currentRow;
251 }
252 }
253
254 return builder.build();
255}
256
257template<typename ValueType, typename RewardModelType>
258storm::storage::SparseMatrix<ValueType> SparseModelMemoryProduct<ValueType, RewardModelType>::buildTransitionMatrixForScheduler() {
259 uint64_t numResStates = reachableStates.getNumberOfSetBits();
260 uint64_t numResChoices = 0;
261 uint64_t numResTransitions = 0;
262 bool hasTrivialNondeterminism = true;
263 for (auto stateIndex : reachableStates) {
264 uint64_t modelState = stateIndex / memoryStateCount;
265 uint64_t memoryState = stateIndex % memoryStateCount;
266 storm::storage::SchedulerChoice<ValueType> choice = scheduler->getChoice(modelState, memoryState);
267 if (choice.isDefined()) {
268 ++numResChoices;
269 if (choice.isDeterministic()) {
270 uint64_t modelRow = model.getTransitionMatrix().getRowGroupIndices()[modelState] + choice.getDeterministicChoice();
271 numResTransitions += model.getTransitionMatrix().getRow(modelRow).getNumberOfEntries();
272 } else {
273 std::set<uint64_t> successors;
274 for (auto const& choiceIndex : choice.getChoiceAsDistribution()) {
275 if (!storm::utility::isZero(choiceIndex.second)) {
276 uint64_t modelRow = model.getTransitionMatrix().getRowGroupIndices()[modelState] + choiceIndex.first;
277 for (auto const& entry : model.getTransitionMatrix().getRow(modelRow)) {
278 successors.insert(entry.getColumn());
279 }
280 }
281 }
282 numResTransitions += successors.size();
283 }
284 } else {
285 uint64_t modelRow = model.getTransitionMatrix().getRowGroupIndices()[modelState];
286 uint64_t groupEnd = model.getTransitionMatrix().getRowGroupIndices()[modelState + 1];
287 hasTrivialNondeterminism = hasTrivialNondeterminism && (groupEnd == modelRow + 1);
288 for (; modelRow < groupEnd; ++modelRow) {
289 ++numResChoices;
290 numResTransitions += model.getTransitionMatrix().getRow(modelRow).getNumberOfEntries();
291 }
292 }
293 }
294
295 storm::storage::SparseMatrixBuilder<ValueType> builder(numResChoices, numResStates, numResTransitions, true, !hasTrivialNondeterminism,
296 hasTrivialNondeterminism ? 0 : numResStates);
297 uint64_t currentRow = 0;
298 for (auto stateIndex : reachableStates) {
299 uint64_t modelState = stateIndex / memoryStateCount;
300 uint64_t memoryState = stateIndex % memoryStateCount;
301 if (!hasTrivialNondeterminism) {
302 builder.newRowGroup(currentRow);
303 }
304 storm::storage::SchedulerChoice<ValueType> choice = scheduler->getChoice(modelState, memoryState);
305 if (choice.isDefined()) {
306 if (choice.isDeterministic()) {
307 uint64_t modelRowIndex = model.getTransitionMatrix().getRowGroupIndices()[modelState] + choice.getDeterministicChoice();
308 auto const& modelRow = model.getTransitionMatrix().getRow(modelRowIndex);
309 for (auto entryIt = modelRow.begin(); entryIt != modelRow.end(); ++entryIt) {
310 uint64_t transitionId = entryIt - model.getTransitionMatrix().begin();
311 uint64_t successorMemoryState = memorySuccessors[transitionId * memoryStateCount + memoryState];
312 builder.addNextValue(currentRow, getResultState(entryIt->getColumn(), successorMemoryState), entryIt->getValue());
313 }
314 } else {
315 std::map<uint64_t, ValueType> transitions;
316 for (auto const& choiceIndex : choice.getChoiceAsDistribution()) {
317 if (!storm::utility::isZero(choiceIndex.second)) {
318 uint64_t modelRowIndex = model.getTransitionMatrix().getRowGroupIndices()[modelState] + choiceIndex.first;
319 auto const& modelRow = model.getTransitionMatrix().getRow(modelRowIndex);
320 for (auto entryIt = modelRow.begin(); entryIt != modelRow.end(); ++entryIt) {
321 uint64_t transitionId = entryIt - model.getTransitionMatrix().begin();
322 uint64_t successorMemoryState = memorySuccessors[transitionId * memoryStateCount + memoryState];
323 ValueType transitionValue = choiceIndex.second * entryIt->getValue();
324 auto insertionRes = transitions.insert(std::make_pair(getResultState(entryIt->getColumn(), successorMemoryState), transitionValue));
325 if (!insertionRes.second) {
326 insertionRes.first->second += transitionValue;
327 }
328 }
329 }
330 }
331 for (auto const& transition : transitions) {
332 builder.addNextValue(currentRow, transition.first, transition.second);
333 }
334 }
335 ++currentRow;
336 } else {
337 for (uint64_t modelRowIndex = model.getTransitionMatrix().getRowGroupIndices()[modelState];
338 modelRowIndex < model.getTransitionMatrix().getRowGroupIndices()[modelState + 1]; ++modelRowIndex) {
339 auto const& modelRow = model.getTransitionMatrix().getRow(modelRowIndex);
340 for (auto entryIt = modelRow.begin(); entryIt != modelRow.end(); ++entryIt) {
341 uint64_t transitionId = entryIt - model.getTransitionMatrix().begin();
342 uint64_t successorMemoryState = memorySuccessors[transitionId * memoryStateCount + memoryState];
343 builder.addNextValue(currentRow, getResultState(entryIt->getColumn(), successorMemoryState), entryIt->getValue());
344 }
345 ++currentRow;
346 }
347 }
348 }
349
350 return builder.build();
351}
352
353template<typename ValueType, typename RewardModelType>
354storm::models::sparse::StateLabeling SparseModelMemoryProduct<ValueType, RewardModelType>::buildStateLabeling(
355 storm::storage::SparseMatrix<ValueType> const& resultTransitionMatrix) {
356 uint64_t modelStateCount = model.getNumberOfStates();
357
358 uint64_t numResStates = resultTransitionMatrix.getRowGroupCount();
359 storm::models::sparse::StateLabeling resultLabeling(numResStates);
360
361 for (std::string modelLabel : model.getStateLabeling().getLabels()) {
362 if (modelLabel != "init") {
363 storm::storage::BitVector resLabeledStates(numResStates, false);
364 for (auto modelState : model.getStateLabeling().getStates(modelLabel)) {
365 for (uint64_t memoryState = 0; memoryState < memoryStateCount; ++memoryState) {
366 if (isStateReachable(modelState, memoryState)) {
367 resLabeledStates.set(getResultState(modelState, memoryState), true);
368 }
369 }
370 }
371 resultLabeling.addLabel(modelLabel, std::move(resLabeledStates));
372 }
373 }
374 for (std::string memoryLabel : memory.getStateLabeling().getLabels()) {
375 STORM_LOG_THROW(!resultLabeling.containsLabel(memoryLabel), storm::exceptions::InvalidOperationException,
376 "Failed to build the product of model and memory structure: State labelings are not disjoint as both structures contain the label "
377 << memoryLabel << ".");
378 storm::storage::BitVector resLabeledStates(numResStates, false);
379 for (auto memoryState : memory.getStateLabeling().getStates(memoryLabel)) {
380 for (uint64_t modelState = 0; modelState < modelStateCount; ++modelState) {
381 if (isStateReachable(modelState, memoryState)) {
382 resLabeledStates.set(getResultState(modelState, memoryState), true);
383 }
384 }
385 }
386 resultLabeling.addLabel(memoryLabel, std::move(resLabeledStates));
387 }
388
389 storm::storage::BitVector initialStates(numResStates, false);
390 auto memoryInitIt = memory.getInitialMemoryStates().begin();
391 for (auto modelInit : model.getInitialStates()) {
392 initialStates.set(getResultState(modelInit, *memoryInitIt), true);
393 ++memoryInitIt;
394 }
395 resultLabeling.addLabel("init", std::move(initialStates));
396
397 return resultLabeling;
398}
399
400template<typename ValueType, typename RewardModelType>
401std::unordered_map<std::string, RewardModelType> SparseModelMemoryProduct<ValueType, RewardModelType>::buildRewardModels(
402 storm::storage::SparseMatrix<ValueType> const& resultTransitionMatrix) {
403 typedef typename RewardModelType::ValueType RewardValueType;
404
405 std::unordered_map<std::string, RewardModelType> result;
406 uint64_t numResStates = resultTransitionMatrix.getRowGroupCount();
407
408 for (auto const& rewardModel : model.getRewardModels()) {
409 std::optional<std::vector<RewardValueType>> stateRewards;
410 if (rewardModel.second.hasStateRewards()) {
411 stateRewards = std::vector<RewardValueType>(numResStates, storm::utility::zero<RewardValueType>());
412 uint64_t modelState = 0;
413 for (auto const& modelStateReward : rewardModel.second.getStateRewardVector()) {
414 if (!storm::utility::isZero(modelStateReward)) {
415 for (uint64_t memoryState = 0; memoryState < memoryStateCount; ++memoryState) {
416 if (isStateReachable(modelState, memoryState)) {
417 stateRewards.value()[getResultState(modelState, memoryState)] = modelStateReward;
418 }
419 }
420 }
421 ++modelState;
422 }
423 }
424 std::optional<std::vector<RewardValueType>> stateActionRewards;
425 if (rewardModel.second.hasStateActionRewards()) {
426 stateActionRewards = std::vector<RewardValueType>(resultTransitionMatrix.getRowCount(), storm::utility::zero<RewardValueType>());
427 uint64_t modelState = 0;
428 uint64_t modelRow = 0;
429 for (auto const& modelStateActionReward : rewardModel.second.getStateActionRewardVector()) {
430 if (!storm::utility::isZero(modelStateActionReward)) {
431 while (modelRow >= model.getTransitionMatrix().getRowGroupIndices()[modelState + 1]) {
432 ++modelState;
433 }
434 uint64_t rowOffset = modelRow - model.getTransitionMatrix().getRowGroupIndices()[modelState];
435 for (uint64_t memoryState = 0; memoryState < memoryStateCount; ++memoryState) {
436 if (isStateReachable(modelState, memoryState)) {
437 if (scheduler && scheduler->getChoice(modelState, memoryState).isDefined()) {
438 ValueType factor = scheduler->getChoice(modelState, memoryState).getChoiceAsDistribution().getProbability(rowOffset);
439 stateActionRewards.value()[resultTransitionMatrix.getRowGroupIndices()[getResultState(modelState, memoryState)]] +=
440 factor * modelStateActionReward;
441 } else {
442 stateActionRewards.value()[resultTransitionMatrix.getRowGroupIndices()[getResultState(modelState, memoryState)] + rowOffset] =
443 modelStateActionReward;
444 }
445 }
446 }
447 }
448 ++modelRow;
449 }
450 }
451 std::optional<storm::storage::SparseMatrix<RewardValueType>> transitionRewards;
452 if (rewardModel.second.hasTransitionRewards()) {
453 bool const useRowGrouping = !resultTransitionMatrix.hasTrivialRowGrouping();
454 storm::storage::SparseMatrixBuilder<RewardValueType> builder(resultTransitionMatrix.getRowCount(), resultTransitionMatrix.getColumnCount(), 0ull,
455 true, useRowGrouping,
456 useRowGrouping ? resultTransitionMatrix.getRowGroupCount() : 0ull);
457 uint64_t stateIndex = 0;
458 for (auto const& resState : toResultStateMapping) {
459 if (resState < numResStates) {
460 uint64_t modelState = stateIndex / memoryStateCount;
461 uint64_t memoryState = stateIndex % memoryStateCount;
462 uint64_t rowGroupSize = resultTransitionMatrix.getRowGroupSize(resState);
463 if (useRowGrouping) {
464 builder.newRowGroup(resultTransitionMatrix.getRowGroupIndices()[resState]);
465 }
466 if (scheduler && scheduler->getChoice(modelState, memoryState).isDefined()) {
467 std::map<uint64_t, RewardValueType> rewards;
468 for (uint64_t rowOffset = 0; rowOffset < rowGroupSize; ++rowOffset) {
469 uint64_t modelRowIndex = model.getTransitionMatrix().getRowGroupIndices()[modelState] + rowOffset;
470 auto transitionEntryIt = model.getTransitionMatrix().getRow(modelRowIndex).begin();
471 for (auto const& rewardEntry : rewardModel.second.getTransitionRewardMatrix().getRow(modelRowIndex)) {
472 while (transitionEntryIt->getColumn() != rewardEntry.getColumn()) {
473 STORM_LOG_ASSERT(transitionEntryIt != model.getTransitionMatrix().getRow(modelRowIndex).end(),
474 "The reward transition matrix is not a submatrix of the model transition matrix.");
475 ++transitionEntryIt;
476 }
477 uint64_t transitionId = transitionEntryIt - model.getTransitionMatrix().begin();
478 uint64_t successorMemoryState = memorySuccessors[transitionId * memoryStateCount + memoryState];
479 auto insertionRes =
480 rewards.insert(std::make_pair(getResultState(rewardEntry.getColumn(), successorMemoryState), rewardEntry.getValue()));
481 if (!insertionRes.second) {
482 insertionRes.first->second += rewardEntry.getValue();
483 }
484 }
485 }
486 uint64_t resRowIndex = resultTransitionMatrix.getRowGroupIndices()[resState];
487 for (auto& reward : rewards) {
488 builder.addNextValue(resRowIndex, reward.first, reward.second);
489 }
490 } else {
491 for (uint64_t rowOffset = 0; rowOffset < rowGroupSize; ++rowOffset) {
492 uint64_t resRowIndex = resultTransitionMatrix.getRowGroupIndices()[resState] + rowOffset;
493 uint64_t modelRowIndex = model.getTransitionMatrix().getRowGroupIndices()[modelState] + rowOffset;
494 auto transitionEntryIt = model.getTransitionMatrix().getRow(modelRowIndex).begin();
495 for (auto const& rewardEntry : rewardModel.second.getTransitionRewardMatrix().getRow(modelRowIndex)) {
496 while (transitionEntryIt->getColumn() != rewardEntry.getColumn()) {
497 STORM_LOG_ASSERT(transitionEntryIt != model.getTransitionMatrix().getRow(modelRowIndex).end(),
498 "The reward transition matrix is not a submatrix of the model transition matrix.");
499 ++transitionEntryIt;
500 }
501 uint64_t transitionId = transitionEntryIt - model.getTransitionMatrix().begin();
502 uint64_t successorMemoryState = memorySuccessors[transitionId * memoryStateCount + memoryState];
503 builder.addNextValue(resRowIndex, getResultState(rewardEntry.getColumn(), successorMemoryState), rewardEntry.getValue());
504 }
505 }
506 }
507 }
508 ++stateIndex;
509 }
510 transitionRewards = builder.build();
511 }
512 result.insert(std::make_pair(rewardModel.first, RewardModelType(std::move(stateRewards), std::move(stateActionRewards), std::move(transitionRewards))));
513 }
514 return result;
515}
516
517template<typename ValueType, typename RewardModelType>
518std::shared_ptr<storm::models::sparse::Model<ValueType, RewardModelType>> SparseModelMemoryProduct<ValueType, RewardModelType>::buildResult(
520 std::unordered_map<std::string, RewardModelType>&& rewardModels) {
521 storm::storage::sparse::ModelComponents<ValueType, RewardModelType> components(std::move(matrix), std::move(labeling), std::move(rewardModels));
522
523 if (model.isOfType(storm::models::ModelType::Ctmc)) {
524 components.rateTransitions = true;
525 } else if (model.isOfType(storm::models::ModelType::MarkovAutomaton)) {
526 // We also need to translate the exit rates and the Markovian states
527 uint64_t numResStates = components.transitionMatrix.getRowGroupCount();
528 std::vector<ValueType> resultExitRates;
529 resultExitRates.reserve(components.transitionMatrix.getRowGroupCount());
530 storm::storage::BitVector resultMarkovianStates(numResStates, false);
531 auto const& modelExitRates = dynamic_cast<storm::models::sparse::MarkovAutomaton<ValueType, RewardModelType> const&>(model).getExitRates();
532 auto const& modelMarkovianStates = dynamic_cast<storm::models::sparse::MarkovAutomaton<ValueType, RewardModelType> const&>(model).getMarkovianStates();
533
534 uint64_t stateIndex = 0;
535 for (auto const& resState : toResultStateMapping) {
536 if (resState < numResStates) {
537 assert(resState == resultExitRates.size());
538 uint64_t modelState = stateIndex / memoryStateCount;
539 resultExitRates.push_back(modelExitRates[modelState]);
540 if (modelMarkovianStates.get(modelState)) {
541 resultMarkovianStates.set(resState, true);
542 }
543 }
544 ++stateIndex;
545 }
546 components.markovianStates = std::move(resultMarkovianStates);
547 components.exitRates = std::move(resultExitRates);
548 }
549
550 return storm::utility::builder::buildModelFromComponents(model.getType(), std::move(components));
551}
552
553template<typename ValueType, typename RewardModelType>
557
558template<typename ValueType, typename RewardModelType>
562
568
569} // namespace storage
570} // namespace storm
This class represents a Markov automaton.
Base class for all sparse models.
Definition Model.h:33
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.
Definition BitVector.h:18
void set(uint_fast64_t index, bool value=true)
Sets the given truth value at the given index.
This class represents a (deterministic) memory structure that can be used to encode certain events (s...
uint_fast64_t getDeterministicChoice() const
If this choice is deterministic, this function returns the selected (local) choice index.
bool isDeterministic() const
Returns true iff this scheduler choice is deterministic (i.e., not randomized)
bool isDefined() const
Returns true iff this scheduler choice is defined.
This class defines which action is chosen in a particular state of a non-deterministic model.
Definition Scheduler.h:18
index_type getNumberOfEntries() const
Retrieves the number of entries in the rows.
A class that can be used to build a sparse matrix by adding value by value.
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 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)
A class that holds a possibly non-square matrix in the compressed row storage format.
const_rows getRow(index_type row) const
Returns an object representing the given row.
index_type getRowGroupCount() const
Returns the number of row groups in the matrix.
index_type getColumnCount() const
Returns the number of columns of the matrix.
bool hasTrivialRowGrouping() const
Retrieves whether the matrix has a trivial row grouping.
std::vector< index_type > const & getRowGroupIndices() const
Returns the grouping of rows of this matrix.
index_type getRowGroupSize(index_type group) const
Returns the size of the given row group.
index_type getRowCount() const
Returns the number of rows of the matrix.
This class builds the product of the given sparse model and the given memory structure.
storm::storage::MemoryStructure const & getMemory() const
std::shared_ptr< storm::models::sparse::Model< ValueType, RewardModelType > > build()
void addReachableState(uint64_t const &modelState, uint64_t const &memoryState)
SparseModelMemoryProduct(storm::models::sparse::Model< ValueType, RewardModelType > const &sparseModel, storm::storage::MemoryStructure const &memoryStructure)
storm::models::sparse::Model< ValueType, RewardModelType > const & getOriginalModel() const
bool isStateReachable(uint64_t const &modelState, uint64_t const &memoryState)
uint64_t const & getResultState(uint64_t const &modelState, uint64_t const &memoryState)
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:11
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
SFTBDDChecker::ValueType ValueType
storm::storage::BitVector getStates(storm::logic::Formula const &propositionalFormula, bool formulaInverted, PomdpType const &pomdp)
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
std::pair< storm::dd::Bdd< Type >, uint64_t > computeReachableStates(storm::dd::Bdd< Type > const &initialStates, storm::dd::Bdd< Type > const &transitions, std::set< storm::expressions::Variable > const &rowMetaVariables, std::set< storm::expressions::Variable > const &columnMetaVariables)
Definition dd.cpp:16
bool isZero(ValueType const &a)
Definition constants.cpp:41
LabParser.cpp.
Definition cli.cpp:18