3#include <boost/optional.hpp>
22template<
typename ValueType,
typename RewardModelType>
25 : isInitialized(false), memoryStateCount(memoryStructure.getNumberOfStates()), model(sparseModel), memory(memoryStructure), scheduler(
boost::none) {
29template<
typename ValueType,
typename RewardModelType>
32 : isInitialized(false),
33 memoryStateCount(scheduler.getNumberOfMemoryStates()),
38 memory(scheduler.getMemoryStructure() ? scheduler.getMemoryStructure().get() : localMemory.get()),
39 scheduler(scheduler) {
43template<
typename ValueType,
typename RewardModelType>
46 uint64_t modelStateCount = model.getNumberOfStates();
48 computeMemorySuccessors();
53 auto memoryInitIt = memory.getInitialMemoryStates().begin();
54 if (memory.isOnlyInitialStatesRelevantSet()) {
55 for (
auto modelInit : model.getInitialStates()) {
56 initialStates.set(modelInit * memoryStateCount + *memoryInitIt,
true);
61 for (uint_fast64_t modelState = 0; modelState < model.getNumberOfStates(); ++modelState) {
62 initialStates.set(modelState * memoryStateCount + *memoryInitIt,
true);
66 STORM_LOG_ASSERT(memoryInitIt == memory.getInitialMemoryStates().end(),
"Unexpected number of initial states.");
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;
82template<
typename ValueType,
typename RewardModelType>
84 isInitialized =
false;
85 reachableStates.set(modelState * memoryStateCount + memoryState,
true);
88template<
typename ValueType,
typename RewardModelType>
90 isInitialized =
false;
91 reachableStates.fill();
94template<
typename ValueType,
typename RewardModelType>
101 transitionMatrix = buildTransitionMatrixForScheduler();
102 }
else if (model.getTransitionMatrix().hasTrivialRowGrouping()) {
103 transitionMatrix = buildDeterministicTransitionMatrix();
105 transitionMatrix = buildNondeterministicTransitionMatrix();
108 std::unordered_map<std::string, RewardModelType> rewardModels = buildRewardModels(transitionMatrix);
110 return buildResult(std::move(transitionMatrix), std::move(labeling), std::move(rewardModels));
113template<
typename ValueType,
typename RewardModelType>
115 STORM_LOG_ASSERT(modelState < getOriginalModel().getNumberOfStates(),
"Invalid model state: " << modelState <<
".");
116 STORM_LOG_ASSERT(memoryState < memoryStateCount,
"Invalid memory state: " << memoryState <<
".");
118 return reachableStates.get(modelState * memoryStateCount + memoryState);
121template<
typename ValueType,
typename RewardModelType>
124 STORM_LOG_ASSERT(isStateReachable(modelState, memoryState),
"Tried to get unreachable product state (" << modelState <<
"," << memoryState <<
")");
125 return toResultStateMapping[modelState * memoryStateCount + memoryState];
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());
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;
145template<
typename ValueType,
typename RewardModelType>
146void SparseModelMemoryProduct<ValueType, RewardModelType>::computeReachableStates(
storm::storage::BitVector const& initialStates) {
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();
155 uint64_t modelState = stateIndex / memoryStateCount;
156 uint64_t memoryState = stateIndex % memoryStateCount;
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) {
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);
179 auto const& rowGroup = model.getTransitionMatrix().getRowGroup(modelState);
180 for (
auto modelTransitionIt = rowGroup.begin(); modelTransitionIt != rowGroup.end(); ++modelTransitionIt) {
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);
197template<
typename ValueType,
typename RewardModelType>
199 uint64_t numResStates = reachableStates.getNumberOfSetBits();
200 uint64_t numResTransitions = 0;
201 for (
auto stateIndex : reachableStates) {
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());
219 return builder.build();
222template<
typename ValueType,
typename RewardModelType>
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) {
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());
254 return builder.build();
257template<
typename ValueType,
typename RewardModelType>
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;
270 uint64_t modelRow = model.getTransitionMatrix().getRowGroupIndices()[modelState] + choice.
getDeterministicChoice();
271 numResTransitions += model.getTransitionMatrix().getRow(modelRow).getNumberOfEntries();
273 std::set<uint64_t> successors;
274 for (
auto const& choiceIndex : choice.getChoiceAsDistribution()) {
276 uint64_t modelRow = model.getTransitionMatrix().getRowGroupIndices()[modelState] + choiceIndex.first;
277 for (
auto const& entry : model.getTransitionMatrix().getRow(modelRow)) {
278 successors.insert(entry.getColumn());
282 numResTransitions += successors.size();
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) {
290 numResTransitions += model.getTransitionMatrix().getRow(modelRow).getNumberOfEntries();
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) {
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());
315 std::map<uint64_t, ValueType> transitions;
316 for (
auto const& choiceIndex : choice.getChoiceAsDistribution()) {
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;
331 for (
auto const& transition : transitions) {
332 builder.
addNextValue(currentRow, transition.first, transition.second);
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());
350 return builder.
build();
353template<
typename ValueType,
typename RewardModelType>
356 uint64_t modelStateCount = model.getNumberOfStates();
361 for (std::string modelLabel : model.getStateLabeling().getLabels()) {
362 if (modelLabel !=
"init") {
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);
371 resultLabeling.addLabel(modelLabel, std::move(resLabeledStates));
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 <<
".");
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);
386 resultLabeling.addLabel(memoryLabel, std::move(resLabeledStates));
390 auto memoryInitIt = memory.getInitialMemoryStates().begin();
391 for (
auto modelInit : model.getInitialStates()) {
392 initialStates.
set(getResultState(modelInit, *memoryInitIt),
true);
395 resultLabeling.addLabel(
"init", std::move(initialStates));
397 return resultLabeling;
400template<
typename ValueType,
typename RewardModelType>
401std::unordered_map<std::string, RewardModelType> SparseModelMemoryProduct<ValueType, RewardModelType>::buildRewardModels(
403 typedef typename RewardModelType::ValueType RewardValueType;
405 std::unordered_map<std::string, RewardModelType> result;
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()) {
415 for (uint64_t memoryState = 0; memoryState < memoryStateCount; ++memoryState) {
416 if (isStateReachable(modelState, memoryState)) {
417 stateRewards.value()[getResultState(modelState, memoryState)] = modelStateReward;
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()) {
431 while (modelRow >= model.getTransitionMatrix().getRowGroupIndices()[modelState + 1]) {
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;
442 stateActionRewards.value()[resultTransitionMatrix.
getRowGroupIndices()[getResultState(modelState, memoryState)] + rowOffset] =
443 modelStateActionReward;
451 std::optional<storm::storage::SparseMatrix<RewardValueType>> transitionRewards;
452 if (rewardModel.second.hasTransitionRewards()) {
455 true, useRowGrouping,
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) {
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.");
477 uint64_t transitionId = transitionEntryIt - model.getTransitionMatrix().begin();
478 uint64_t successorMemoryState = memorySuccessors[transitionId * memoryStateCount + memoryState];
480 rewards.insert(std::make_pair(getResultState(rewardEntry.getColumn(), successorMemoryState), rewardEntry.getValue()));
481 if (!insertionRes.second) {
482 insertionRes.first->second += rewardEntry.getValue();
487 for (
auto& reward : rewards) {
488 builder.
addNextValue(resRowIndex, reward.first, reward.second);
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.");
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());
510 transitionRewards = builder.
build();
512 result.insert(std::make_pair(rewardModel.first, RewardModelType(std::move(stateRewards), std::move(stateActionRewards), std::move(transitionRewards))));
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) {
524 components.rateTransitions =
true;
527 uint64_t numResStates = components.transitionMatrix.getRowGroupCount();
528 std::vector<ValueType> resultExitRates;
529 resultExitRates.reserve(components.transitionMatrix.getRowGroupCount());
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);
546 components.markovianStates = std::move(resultMarkovianStates);
547 components.exitRates = std::move(resultExitRates);
553template<
typename ValueType,
typename RewardModelType>
558template<
typename ValueType,
typename RewardModelType>
This class represents a Markov automaton.
Base class for all sparse 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.
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.
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)
void setBuildFullProduct()
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)
#define STORM_LOG_THROW(cond, exception, message)
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)
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)
bool isZero(ValueType const &a)