113 createMetaVariablesAndIdentities();
117 parameterCreator.create(this->program, *this->rowExpressionAdapter);
118 if (std::is_same<ValueType, storm::RationalFunction>::value) {
119 this->parameters = parameterCreator.getParameters();
127 std::shared_ptr<storm::dd::DdManager<Type>>
manager;
173 void createMetaVariablesAndIdentities() {
176 std::pair<storm::expressions::Variable, storm::expressions::Variable> variablePair = manager->addMetaVariable(program.
getActionName(actionIndex));
177 synchronizationMetaVariables.push_back(variablePair.first);
178 allSynchronizationMetaVariables.insert(variablePair.first);
179 allNondeterminismVariables.insert(variablePair.first);
183 uint_fast64_t numberOfNondeterminismVariables = program.
getModules().size();
184 for (
auto const& module : program.
getModules()) {
185 numberOfNondeterminismVariables +=
module.getNumberOfCommands();
187 for (uint_fast64_t i = 0; i < numberOfNondeterminismVariables; ++i) {
188 std::pair<storm::expressions::Variable, storm::expressions::Variable> variablePair = manager->addMetaVariable(
"nondet" + std::to_string(i));
189 nondeterminismMetaVariables.push_back(variablePair.first);
190 allNondeterminismVariables.insert(variablePair.first);
195 int_fast64_t low = integerVariable.getLowerBoundExpression().evaluateAsInt();
196 int_fast64_t high = integerVariable.getUpperBoundExpression().evaluateAsInt();
197 std::pair<storm::expressions::Variable, storm::expressions::Variable> variablePair = manager->addMetaVariable(integerVariable.getName(), low, high);
199 STORM_LOG_TRACE(
"Created meta variables for global integer variable: " << variablePair.first.getName() <<
"[" << variablePair.first.getIndex()
200 <<
"] and " << variablePair.second.getName() <<
"["
201 << variablePair.second.getIndex() <<
"]");
203 rowMetaVariables.insert(variablePair.first);
204 variableToRowMetaVariableMap->emplace(integerVariable.getExpressionVariable(), variablePair.first);
206 columnMetaVariables.insert(variablePair.second);
207 variableToColumnMetaVariableMap->emplace(integerVariable.getExpressionVariable(), variablePair.second);
209 storm::dd::Bdd<Type> variableIdentity = manager->getIdentity(variablePair.first, variablePair.second);
210 variableToIdentityMap.emplace(integerVariable.getExpressionVariable(), variableIdentity.template toAdd<ValueType>());
211 rowColumnMetaVariablePairs.push_back(variablePair);
213 allGlobalVariables.insert(integerVariable.getExpressionVariable());
216 std::pair<storm::expressions::Variable, storm::expressions::Variable> variablePair = manager->addMetaVariable(booleanVariable.getName());
218 STORM_LOG_TRACE(
"Created meta variables for global boolean variable: " << variablePair.first.getName() <<
"[" << variablePair.first.getIndex()
219 <<
"] and " << variablePair.second.getName() <<
"["
220 << variablePair.second.getIndex() <<
"]");
222 rowMetaVariables.insert(variablePair.first);
223 variableToRowMetaVariableMap->emplace(booleanVariable.getExpressionVariable(), variablePair.first);
225 columnMetaVariables.insert(variablePair.second);
226 variableToColumnMetaVariableMap->emplace(booleanVariable.getExpressionVariable(), variablePair.second);
228 storm::dd::Bdd<Type> variableIdentity = manager->getIdentity(variablePair.first, variablePair.second);
229 variableToIdentityMap.emplace(booleanVariable.getExpressionVariable(), variableIdentity.template toAdd<ValueType>());
231 rowColumnMetaVariablePairs.push_back(variablePair);
232 allGlobalVariables.insert(booleanVariable.getExpressionVariable());
241 int_fast64_t low = integerVariable.getLowerBoundExpression().evaluateAsInt();
242 int_fast64_t high = integerVariable.getUpperBoundExpression().evaluateAsInt();
243 std::pair<storm::expressions::Variable, storm::expressions::Variable> variablePair =
244 manager->addMetaVariable(integerVariable.getName(), low, high);
245 STORM_LOG_TRACE(
"Created meta variables for integer variable: " << variablePair.first.getName() <<
"[" << variablePair.first.getIndex()
246 <<
"] and " << variablePair.second.getName() <<
"["
247 << variablePair.second.getIndex() <<
"]");
249 rowMetaVariables.insert(variablePair.first);
250 variableToRowMetaVariableMap->emplace(integerVariable.getExpressionVariable(), variablePair.first);
252 columnMetaVariables.insert(variablePair.second);
253 variableToColumnMetaVariableMap->emplace(integerVariable.getExpressionVariable(), variablePair.second);
255 storm::dd::Bdd<Type> variableIdentity = manager->getIdentity(variablePair.first, variablePair.second);
256 variableToIdentityMap.emplace(integerVariable.getExpressionVariable(), variableIdentity.template toAdd<ValueType>());
257 moduleIdentity &= variableIdentity;
258 moduleRange &= manager->getRange(variablePair.first);
260 rowColumnMetaVariablePairs.push_back(variablePair);
263 std::pair<storm::expressions::Variable, storm::expressions::Variable> variablePair = manager->addMetaVariable(booleanVariable.getName());
264 STORM_LOG_TRACE(
"Created meta variables for boolean variable: " << variablePair.first.getName() <<
"[" << variablePair.first.getIndex()
265 <<
"] and " << variablePair.second.getName() <<
"["
266 << variablePair.second.getIndex() <<
"]");
268 rowMetaVariables.insert(variablePair.first);
269 variableToRowMetaVariableMap->emplace(booleanVariable.getExpressionVariable(), variablePair.first);
271 columnMetaVariables.insert(variablePair.second);
272 variableToColumnMetaVariableMap->emplace(booleanVariable.getExpressionVariable(), variablePair.second);
274 storm::dd::Bdd<Type> variableIdentity = manager->getIdentity(variablePair.first, variablePair.second);
275 variableToIdentityMap.emplace(booleanVariable.getExpressionVariable(), variableIdentity.template toAdd<ValueType>());
276 moduleIdentity &= variableIdentity;
277 moduleRange &= manager->getRange(variablePair.first);
279 rowColumnMetaVariablePairs.push_back(variablePair);
281 moduleToIdentityMap[
module.getName()] = moduleIdentity.template toAdd<ValueType>();
282 moduleToRangeMap[
module.getName()] = moduleRange.template toAdd<ValueType>();
287template<storm::dd::DdType Type,
typename ValueType>
295 return boost::any_cast<typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram>(
296 composition.
accept(*
this, newSynchronizingActionToOffsetMap()));
300 std::map<uint_fast64_t, uint_fast64_t> result;
301 for (
auto const& actionIndex : generationInfo.program.getSynchronizingActionIndices()) {
302 result[actionIndex] = 0;
308 std::map<uint_fast64_t, uint_fast64_t>
const& oldMapping)
const {
309 std::map<uint_fast64_t, uint_fast64_t> result = oldMapping;
310 for (
auto const& action : sub.synchronizingActionToDecisionDiagramMap) {
311 result[action.first] = action.second.numberOfUsedNondeterminismVariables;
318 std::map<uint_fast64_t, uint_fast64_t>
const& synchronizingActionToOffsetMap = boost::any_cast<std::map<uint_fast64_t, uint_fast64_t>
const&>(data);
321 generationInfo, generationInfo.program.getModule(composition.
getModuleName()), synchronizingActionToOffsetMap);
328 std::map<uint_fast64_t, uint_fast64_t> renaming;
330 STORM_LOG_THROW(generationInfo.program.hasAction(namePair.first), storm::exceptions::InvalidArgumentException,
331 "Composition refers to unknown action '" << namePair.first <<
"'.");
332 STORM_LOG_THROW(generationInfo.program.hasAction(namePair.second), storm::exceptions::InvalidArgumentException,
333 "Composition refers to unknown action '" << namePair.second <<
"'.");
334 renaming.emplace(generationInfo.program.getActionIndex(namePair.first), generationInfo.program.getActionIndex(namePair.second));
338 std::map<uint_fast64_t, uint_fast64_t>
const& synchronizingActionToOffsetMap = boost::any_cast<std::map<uint_fast64_t, uint_fast64_t>
const&>(data);
339 std::map<uint_fast64_t, uint_fast64_t> newSynchronizingActionToOffsetMap = synchronizingActionToOffsetMap;
340 for (
auto const& indexPair : renaming) {
341 auto it = synchronizingActionToOffsetMap.find(indexPair.second);
342 STORM_LOG_THROW(it != synchronizingActionToOffsetMap.end(), storm::exceptions::InvalidArgumentException,
343 "Invalid action index " << indexPair.second <<
".");
344 newSynchronizingActionToOffsetMap[indexPair.first] = it->second;
349 boost::any_cast<typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram>(
353 return rename(sub, renaming);
358 std::set<uint_fast64_t> actionIndicesToHide;
360 STORM_LOG_THROW(generationInfo.program.hasAction(action), storm::exceptions::InvalidArgumentException,
361 "Composition refers to unknown action '" << action <<
"'.");
362 actionIndicesToHide.insert(generationInfo.program.getActionIndex(action));
366 std::map<uint_fast64_t, uint_fast64_t>
const& synchronizingActionToOffsetMap = boost::any_cast<std::map<uint_fast64_t, uint_fast64_t>
const&>(data);
367 std::map<uint_fast64_t, uint_fast64_t> newSynchronizingActionToOffsetMap = synchronizingActionToOffsetMap;
368 for (
auto const& index : actionIndicesToHide) {
369 newSynchronizingActionToOffsetMap[index] = 0;
374 boost::any_cast<typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram>(
378 hide(sub, actionIndicesToHide);
385 boost::any_cast<typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram>(composition.
getLeftSubcomposition().
accept(*
this, data));
388 std::map<uint_fast64_t, uint_fast64_t>
const& synchronizingActionToOffsetMap = boost::any_cast<std::map<uint_fast64_t, uint_fast64_t>
const&>(data);
389 std::map<uint_fast64_t, uint_fast64_t> newSynchronizingActionToOffsetMap = synchronizingActionToOffsetMap;
390 for (
auto const& action : left.synchronizingActionToDecisionDiagramMap) {
391 newSynchronizingActionToOffsetMap[action.first] = action.second.numberOfUsedNondeterminismVariables;
395 boost::any_cast<typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram>(
399 std::set<uint_fast64_t> leftSynchronizationActionIndices = left.getSynchronizingActionIndices();
400 std::set<uint_fast64_t> rightSynchronizationActionIndices = right.getSynchronizingActionIndices();
401 std::set<uint_fast64_t> synchronizationActionIndices;
402 std::set_intersection(leftSynchronizationActionIndices.begin(), leftSynchronizationActionIndices.end(), rightSynchronizationActionIndices.begin(),
403 rightSynchronizationActionIndices.end(), std::inserter(synchronizationActionIndices, synchronizationActionIndices.begin()));
406 composeInParallel(left, right, synchronizationActionIndices);
413 boost::any_cast<typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram>(composition.
getLeftSubcomposition().
accept(*
this, data));
416 boost::any_cast<typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram>(composition.
getRightSubcomposition().
accept(*
this, data));
419 composeInParallel(left, right, std::set<uint_fast64_t>());
425 std::set<uint_fast64_t> synchronizingActionIndices;
427 synchronizingActionIndices.insert(generationInfo.program.getActionIndex(action));
432 boost::any_cast<typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram>(composition.
getLeftSubcomposition().
accept(*
this, data));
435 std::map<uint_fast64_t, uint_fast64_t>
const& synchronizingActionToOffsetMap = boost::any_cast<std::map<uint_fast64_t, uint_fast64_t>
const&>(data);
436 std::map<uint_fast64_t, uint_fast64_t> newSynchronizingActionToOffsetMap = synchronizingActionToOffsetMap;
437 for (
auto const& actionIndex : synchronizingActionIndices) {
438 auto it = left.synchronizingActionToDecisionDiagramMap.find(actionIndex);
439 if (it != left.synchronizingActionToDecisionDiagramMap.end()) {
440 newSynchronizingActionToOffsetMap[actionIndex] = it->second.numberOfUsedNondeterminismVariables;
445 boost::any_cast<typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram>(
448 std::set<uint_fast64_t> leftSynchronizationActionIndices = left.getSynchronizingActionIndices();
449 bool isContainedInLeft = std::includes(leftSynchronizationActionIndices.begin(), leftSynchronizationActionIndices.end(),
450 synchronizingActionIndices.begin(), synchronizingActionIndices.end());
452 "Left subcomposition of composition '" << composition <<
"' does not include all actions over which to synchronize.");
454 std::set<uint_fast64_t> rightSynchronizationActionIndices = right.getSynchronizingActionIndices();
455 bool isContainedInRight = std::includes(rightSynchronizationActionIndices.begin(), rightSynchronizationActionIndices.end(),
456 synchronizingActionIndices.begin(), synchronizingActionIndices.end());
458 "Right subcomposition of composition '" << composition <<
"' does not include all actions over which to synchronize.");
461 composeInParallel(left, right, synchronizingActionIndices);
473 for (
auto const& actionIndex : actionIndicesToHide) {
474 auto it = sub.synchronizingActionToDecisionDiagramMap.find(actionIndex);
475 if (it != sub.synchronizingActionToDecisionDiagramMap.end()) {
477 sub.numberOfUsedNondeterminismVariables =
478 std::max(sub.numberOfUsedNondeterminismVariables, sub.independentAction.numberOfUsedNondeterminismVariables);
479 sub.synchronizingActionToDecisionDiagramMap.erase(it);
487 typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram rename(
typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram& sub,
488 std::map<uint_fast64_t, uint_fast64_t>
const& renaming)
const {
490 std::map<uint_fast64_t, typename DdPrismModelBuilder<Type, ValueType>::ActionDecisionDiagram> actionIndexToDdMap;
493 for (
auto& action : sub.synchronizingActionToDecisionDiagramMap) {
494 auto renamingIt = renaming.find(action.first);
495 if (renamingIt != renaming.end()) {
498 auto itNewActions = actionIndexToDdMap.find(renamingIt->second);
499 if (itNewActions != actionIndexToDdMap.end()) {
500 actionIndexToDdMap[renamingIt->second] =
501 DdPrismModelBuilder<Type, ValueType>::combineUnsynchronizedActions(generationInfo, action.second, itNewActions->second);
505 actionIndexToDdMap[renamingIt->second] = action.second;
510 auto itNewActions = actionIndexToDdMap.find(action.first);
511 if (itNewActions != actionIndexToDdMap.end()) {
512 actionIndexToDdMap[action.first] =
513 DdPrismModelBuilder<Type, ValueType>::combineUnsynchronizedActions(generationInfo, action.second, itNewActions->second);
516 actionIndexToDdMap[action.first] = action.second;
521 return typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram(sub.independentAction, actionIndexToDdMap, sub.identity,
522 sub.numberOfUsedNondeterminismVariables);
529 void composeInParallel(
typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram& left,
530 typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram& right,
531 std::set<uint_fast64_t>
const& synchronizationActionIndices)
const {
535 uint_fast64_t numberOfUsedNondeterminismVariables = right.independentAction.numberOfUsedNondeterminismVariables;
536 left.independentAction = DdPrismModelBuilder<Type, ValueType>::combineUnsynchronizedActions(generationInfo, left.independentAction,
537 right.independentAction, left.identity, right.identity);
538 numberOfUsedNondeterminismVariables = std::max(numberOfUsedNondeterminismVariables, left.independentAction.numberOfUsedNondeterminismVariables);
541 typename DdPrismModelBuilder<Type, ValueType>::ActionDecisionDiagram emptyAction(*generationInfo.manager);
544 for (
auto& action : left.synchronizingActionToDecisionDiagramMap) {
546 if (synchronizationActionIndices.find(action.first) != synchronizationActionIndices.end()) {
549 if (!right.hasSynchronizingAction(action.first)) {
550 action.second = emptyAction;
553 action.second = DdPrismModelBuilder<Type, ValueType>::combineSynchronizingActions(
554 action.second, right.synchronizingActionToDecisionDiagramMap[action.first]);
560 if (right.hasSynchronizingAction(action.first)) {
561 action.second = DdPrismModelBuilder<Type, ValueType>::combineUnsynchronizedActions(
562 generationInfo, action.second, right.synchronizingActionToDecisionDiagramMap[action.first], left.identity, right.identity);
566 action.second = DdPrismModelBuilder<Type, ValueType>::combineUnsynchronizedActions(generationInfo, action.second, emptyAction,
567 left.identity, right.identity);
570 numberOfUsedNondeterminismVariables = std::max(numberOfUsedNondeterminismVariables, action.second.numberOfUsedNondeterminismVariables);
574 for (
auto const& actionIndex : right.getSynchronizingActionIndices()) {
577 if (!left.hasSynchronizingAction(actionIndex)) {
578 if (synchronizationActionIndices.find(actionIndex) != synchronizationActionIndices.end()) {
581 left.synchronizingActionToDecisionDiagramMap[actionIndex] = emptyAction;
585 left.synchronizingActionToDecisionDiagramMap[actionIndex] = DdPrismModelBuilder<Type, ValueType>::combineUnsynchronizedActions(
586 generationInfo, emptyAction, right.synchronizingActionToDecisionDiagramMap[actionIndex], left.identity, right.identity);
589 numberOfUsedNondeterminismVariables =
590 std::max(numberOfUsedNondeterminismVariables, left.synchronizingActionToDecisionDiagramMap[actionIndex].numberOfUsedNondeterminismVariables);
594 left.identity = left.identity * right.identity;
597 left.numberOfUsedNondeterminismVariables = std::max(left.numberOfUsedNondeterminismVariables, numberOfUsedNondeterminismVariables);
600 typename DdPrismModelBuilder<Type, ValueType>::GenerationInformation& generationInfo;
603template<storm::dd::DdType Type,
typename ValueType>
608template<storm::dd::DdType Type,
typename ValueType>
610 : buildAllRewardModels(false), rewardModelsToBuild(), buildAllLabels(false), labelsToBuild(), terminalStates() {
614template<storm::dd::DdType Type,
typename ValueType>
616 : buildAllRewardModels(false), rewardModelsToBuild(), buildAllLabels(false), labelsToBuild(
std::set<
std::string>()) {
621template<storm::dd::DdType Type,
typename ValueType>
623 : buildAllRewardModels(false), rewardModelsToBuild(), buildAllLabels(false), labelsToBuild() {
624 for (
auto const& formula : formulas) {
627 if (formulas.size() == 1) {
632template<storm::dd::DdType Type,
typename ValueType>
635 terminalStates.clear();
638 if (!buildAllRewardModels) {
640 rewardModelsToBuild.insert(referencedRewardModels.begin(), referencedRewardModels.end());
644 std::vector<std::shared_ptr<storm::logic::AtomicLabelFormula const>> atomicLabelFormulas = formula.
getAtomicLabelFormulas();
645 for (
auto const& formula : atomicLabelFormulas) {
646 if (!labelsToBuild) {
647 labelsToBuild = std::set<std::string>();
649 labelsToBuild.get().insert(formula.get()->getLabel());
653template<storm::dd::DdType Type,
typename ValueType>
658template<storm::dd::DdType Type,
typename ValueType>
662 : allTransitionsDd(allTransitionsDd), globalModule(globalModule), stateActionDd(stateActionDd) {
671template<storm::dd::DdType Type,
typename ValueType>
680 std::vector<storm::prism::Assignment> assignments = update.
getAssignments();
681 std::set<storm::expressions::Variable> assignedVariables;
682 for (
auto const& assignment : assignments) {
685 assignedVariables.insert(assignment.getVariable());
699 result = result.
equals(writtenVariable).template toAdd<ValueType>();
703 result = result * generationInfo.
manager->getRange(primedMetaVariable).template toAdd<ValueType>();
709 std::set<storm::expressions::Variable> assignedGlobalVariables;
710 std::set_intersection(assignedVariables.begin(), assignedVariables.end(), generationInfo.
allGlobalVariables.begin(),
711 generationInfo.
allGlobalVariables.end(), std::inserter(assignedGlobalVariables, assignedGlobalVariables.begin()));
715 if (assignedVariables.find(booleanVariable.getExpressionVariable()) == assignedVariables.end()) {
716 STORM_LOG_TRACE(
"Multiplying identity of variable " << booleanVariable.getName());
723 if (assignedVariables.find(integerVariable.getExpressionVariable()) == assignedVariables.end()) {
724 STORM_LOG_TRACE(
"Multiplying identity of variable " << integerVariable.getName());
729 return UpdateDecisionDiagram(updateDd, assignedGlobalVariables);
732template<storm::dd::DdType Type,
typename ValueType>
733typename DdPrismModelBuilder<Type, ValueType>::ActionDecisionDiagram DdPrismModelBuilder<Type, ValueType>::createCommandDecisionDiagram(
737 generationInfo.moduleToRangeMap[
module.getName()].notZero();
742 std::vector<UpdateDecisionDiagram> updateResults;
744 updateResults.push_back(createUpdateDecisionDiagram(generationInfo, module, guard.template toAdd<ValueType>(), update));
746 STORM_LOG_WARN_COND(!updateResults.back().updateDd.isZero(),
"Update '" << update <<
"' does not have any effect.");
750 std::set<storm::expressions::Variable> globalVariablesInSomeUpdate;
756 std::for_each(updateResults.begin(), updateResults.end(), [&globalVariablesInSomeUpdate](UpdateDecisionDiagram
const& update) {
757 globalVariablesInSomeUpdate.insert(update.assignedGlobalVariables.begin(), update.assignedGlobalVariables.end());
760 globalVariablesInSomeUpdate = generationInfo.allGlobalVariables;
764 for (
auto& updateResult : updateResults) {
765 std::set<storm::expressions::Variable> missingIdentities;
766 std::set_difference(globalVariablesInSomeUpdate.begin(), globalVariablesInSomeUpdate.end(), updateResult.assignedGlobalVariables.begin(),
767 updateResult.assignedGlobalVariables.end(), std::inserter(missingIdentities, missingIdentities.begin()));
769 for (
auto const& variable : missingIdentities) {
770 STORM_LOG_TRACE(
"Multiplying identity for variable " << variable.getName() <<
"[" << variable.getIndex() <<
"] to update.");
771 updateResult.updateDd *= generationInfo.variableToIdentityMap.at(variable);
777 auto updateResultsIt = updateResults.begin();
778 for (
auto updateIt = command.
getUpdates().begin(), updateIte = command.
getUpdates().end(); updateIt != updateIte; ++updateIt, ++updateResultsIt) {
780 commandDd += updateResultsIt->updateDd * probabilityDd;
783 return ActionDecisionDiagram(guard, guard.template toAdd<ValueType>() * commandDd, globalVariablesInSomeUpdate);
785 return ActionDecisionDiagram(*generationInfo.manager);
789template<storm::dd::DdType Type,
typename ValueType>
790typename DdPrismModelBuilder<Type, ValueType>::ActionDecisionDiagram DdPrismModelBuilder<Type, ValueType>::createActionDecisionDiagram(
791 GenerationInformation& generationInfo,
storm::prism::Module const& module, uint_fast64_t synchronizationActionIndex,
792 uint_fast64_t nondeterminismVariableOffset) {
793 std::vector<ActionDecisionDiagram> commandDds;
796 bool relevant = (synchronizationActionIndex == 0 && !command.
isLabeled()) ||
806 commandDds.push_back(createCommandDecisionDiagram(generationInfo, module, command));
809 ActionDecisionDiagram result(*generationInfo.manager);
810 if (!commandDds.empty()) {
811 switch (generationInfo.program.getModelType()) {
814 result = combineCommandsToActionMarkovChain(generationInfo, commandDds);
817 result = combineCommandsToActionMDP(generationInfo, commandDds, nondeterminismVariableOffset);
820 STORM_LOG_THROW(
false, storm::exceptions::InvalidArgumentException,
"Cannot translate model of this type.");
827template<storm::dd::DdType Type,
typename ValueType>
828std::set<storm::expressions::Variable> DdPrismModelBuilder<Type, ValueType>::equalizeAssignedGlobalVariables(GenerationInformation
const& generationInfo,
829 ActionDecisionDiagram& action1,
830 ActionDecisionDiagram& action2) {
832 std::set<storm::expressions::Variable> globalVariablesInActionDd;
833 std::set_union(action1.assignedGlobalVariables.begin(), action1.assignedGlobalVariables.end(), action2.assignedGlobalVariables.begin(),
834 action2.assignedGlobalVariables.end(), std::inserter(globalVariablesInActionDd, globalVariablesInActionDd.begin()));
836 std::set<storm::expressions::Variable> missingIdentitiesInAction1;
837 std::set_difference(globalVariablesInActionDd.begin(), globalVariablesInActionDd.end(), action1.assignedGlobalVariables.begin(),
838 action1.assignedGlobalVariables.end(), std::inserter(missingIdentitiesInAction1, missingIdentitiesInAction1.begin()));
839 for (
auto const& variable : missingIdentitiesInAction1) {
840 action1.transitionsDd *= generationInfo.variableToIdentityMap.at(variable);
843 std::set<storm::expressions::Variable> missingIdentitiesInAction2;
844 std::set_difference(globalVariablesInActionDd.begin(), globalVariablesInActionDd.end(), action1.assignedGlobalVariables.begin(),
845 action1.assignedGlobalVariables.end(), std::inserter(missingIdentitiesInAction2, missingIdentitiesInAction2.begin()));
846 for (
auto const& variable : missingIdentitiesInAction2) {
847 action2.transitionsDd *= generationInfo.variableToIdentityMap.at(variable);
850 return globalVariablesInActionDd;
853template<storm::dd::DdType Type,
typename ValueType>
854std::set<storm::expressions::Variable> DdPrismModelBuilder<Type, ValueType>::equalizeAssignedGlobalVariables(GenerationInformation
const& generationInfo,
855 std::vector<ActionDecisionDiagram>& actionDds) {
857 std::set<storm::expressions::Variable> globalVariablesInActionDd;
858 for (
auto const& commandDd : actionDds) {
859 globalVariablesInActionDd.insert(commandDd.assignedGlobalVariables.
begin(), commandDd.assignedGlobalVariables.
end());
865 for (
auto& actionDd : actionDds) {
867 std::set<storm::expressions::Variable> missingIdentities;
868 std::set_difference(globalVariablesInActionDd.begin(), globalVariablesInActionDd.end(), actionDd.assignedGlobalVariables.begin(),
869 actionDd.assignedGlobalVariables.end(), std::inserter(missingIdentities, missingIdentities.begin()));
870 for (
auto const& variable : missingIdentities) {
871 STORM_LOG_TRACE(
"Multiplying identity of variable " << variable.getName() <<
".");
872 actionDd.transitionsDd *= generationInfo.variableToIdentityMap.at(variable);
875 return globalVariablesInActionDd;
878template<storm::dd::DdType Type,
typename ValueType>
879typename DdPrismModelBuilder<Type, ValueType>::ActionDecisionDiagram DdPrismModelBuilder<Type, ValueType>::combineCommandsToActionMarkovChain(
880 GenerationInformation& generationInfo, std::vector<ActionDecisionDiagram>& commandDds) {
886 std::set<storm::expressions::Variable> assignedGlobalVariables = equalizeAssignedGlobalVariables(generationInfo, commandDds);
889 for (
auto& commandDd : commandDds) {
891 temporary = commandDd.guardDd && allGuards;
895 "Guard of a command overlaps with previous guards.");
897 allGuards |= commandDd.guardDd;
898 allCommands += commandDd.transitionsDd;
901 return ActionDecisionDiagram(allGuards, allCommands, assignedGlobalVariables);
904template<storm::dd::DdType Type,
typename ValueType>
906 uint_fast64_t nondeterminismVariableOffset,
907 uint_fast64_t numberOfBinaryVariables, int_fast64_t value) {
910 STORM_LOG_TRACE(
"Encoding " << value <<
" with " << numberOfBinaryVariables <<
" binary variable(s) starting from offset " << nondeterminismVariableOffset
913 std::map<storm::expressions::Variable, int_fast64_t> metaVariableNameToValueMap;
914 for (uint_fast64_t i = 0;
i < numberOfBinaryVariables; ++
i) {
915 if (value & (1ull << (numberOfBinaryVariables - i - 1))) {
916 metaVariableNameToValueMap.emplace(generationInfo.nondeterminismMetaVariables[nondeterminismVariableOffset + i], 1);
918 metaVariableNameToValueMap.emplace(generationInfo.nondeterminismMetaVariables[nondeterminismVariableOffset + i], 0);
922 result.
setValue(metaVariableNameToValueMap, storm::utility::one<ValueType>());
926template<storm::dd::DdType Type,
typename ValueType>
927typename DdPrismModelBuilder<Type, ValueType>::ActionDecisionDiagram DdPrismModelBuilder<Type, ValueType>::combineCommandsToActionMDP(
928 GenerationInformation& generationInfo, std::vector<ActionDecisionDiagram>& commandDds, uint_fast64_t nondeterminismVariableOffset) {
933 std::set<storm::expressions::Variable> assignedGlobalVariables = equalizeAssignedGlobalVariables(generationInfo, commandDds);
937 for (
auto const& commandDd : commandDds) {
938 sumOfGuards += commandDd.guardDd.template toAdd<uint_fast64_t>();
939 allGuards |= commandDd.guardDd;
941 uint_fast64_t maxChoices = sumOfGuards.
getMax();
946 if (maxChoices == 0) {
947 return ActionDecisionDiagram(*generationInfo.manager);
948 }
else if (maxChoices == 1) {
950 for (
auto const& commandDd : commandDds) {
951 allCommands += commandDd.transitionsDd;
953 return ActionDecisionDiagram(allGuards, allCommands, assignedGlobalVariables);
959 std::vector<storm::dd::Add<Type, ValueType>> choiceDds(maxChoices, generationInfo.manager->template getAddZero<ValueType>());
960 std::vector<storm::dd::Bdd<Type>> remainingDds(maxChoices, generationInfo.manager->getBddZero());
962 for (uint_fast64_t currentChoices = 1; currentChoices <= maxChoices; ++currentChoices) {
964 equalsNumberOfChoicesDd = sumOfGuards.
equals(generationInfo.manager->getConstant(currentChoices));
967 if (equalsNumberOfChoicesDd.
isZero()) {
972 for (uint_fast64_t j = 0; j < currentChoices; ++j) {
973 choiceDds[j] = generationInfo.manager->template getAddZero<ValueType>();
974 remainingDds[j] = equalsNumberOfChoicesDd;
977 for (std::size_t j = 0; j < commandDds.size(); ++j) {
980 storm::dd::Bdd<Type> guardChoicesIntersection = commandDds[j].guardDd && equalsNumberOfChoicesDd;
983 if (guardChoicesIntersection.
isZero()) {
988 for (uint_fast64_t k = 0; k < currentChoices; ++k) {
990 storm::dd::Bdd<Type> remainingGuardChoicesIntersection = guardChoicesIntersection && remainingDds[k];
993 if (!remainingGuardChoicesIntersection.
isZero()) {
995 remainingDds[k] = remainingDds[k] && !remainingGuardChoicesIntersection;
998 choiceDds[k] += remainingGuardChoicesIntersection.template toAdd<ValueType>() * commandDds[j].transitionsDd;
1002 guardChoicesIntersection = guardChoicesIntersection && !remainingGuardChoicesIntersection;
1005 if (guardChoicesIntersection.
isZero()) {
1012 for (uint_fast64_t j = 0; j < currentChoices; ++j) {
1013 allCommands += encodeChoice(generationInfo, nondeterminismVariableOffset, numberOfBinaryVariables, j) * choiceDds[j];
1017 sumOfGuards = sumOfGuards * (!equalsNumberOfChoicesDd).
template toAdd<uint_fast64_t>();
1020 return ActionDecisionDiagram(allGuards, allCommands, assignedGlobalVariables, nondeterminismVariableOffset + numberOfBinaryVariables);
1024template<storm::dd::DdType Type,
typename ValueType>
1025typename DdPrismModelBuilder<Type, ValueType>::ActionDecisionDiagram DdPrismModelBuilder<Type, ValueType>::combineSynchronizingActions(
1026 ActionDecisionDiagram
const& action1, ActionDecisionDiagram
const& action2) {
1027 std::set<storm::expressions::Variable> assignedGlobalVariables;
1028 std::set_union(action1.assignedGlobalVariables.begin(), action1.assignedGlobalVariables.end(), action2.assignedGlobalVariables.begin(),
1029 action2.assignedGlobalVariables.end(), std::inserter(assignedGlobalVariables, assignedGlobalVariables.begin()));
1030 return ActionDecisionDiagram(action1.guardDd && action2.guardDd, action1.transitionsDd * action2.transitionsDd, assignedGlobalVariables,
1031 std::max(action1.numberOfUsedNondeterminismVariables, action2.numberOfUsedNondeterminismVariables));
1034template<storm::dd::DdType Type,
typename ValueType>
1035typename DdPrismModelBuilder<Type, ValueType>::ActionDecisionDiagram DdPrismModelBuilder<Type, ValueType>::combineUnsynchronizedActions(
1036 GenerationInformation
const& generationInfo, ActionDecisionDiagram& action1, ActionDecisionDiagram& action2,
1039 STORM_LOG_TRACE(
"Multiplying identities to combine unsynchronized actions.");
1040 action1.transitionsDd = action1.transitionsDd * identityDd2;
1041 action2.transitionsDd = action2.transitionsDd * identityDd1;
1044 return combineUnsynchronizedActions(generationInfo, action1, action2);
1047template<storm::dd::DdType Type,
typename ValueType>
1048typename DdPrismModelBuilder<Type, ValueType>::ActionDecisionDiagram DdPrismModelBuilder<Type, ValueType>::combineUnsynchronizedActions(
1049 GenerationInformation
const& generationInfo, ActionDecisionDiagram& action1, ActionDecisionDiagram& action2) {
1053 std::set<storm::expressions::Variable> assignedGlobalVariables = equalizeAssignedGlobalVariables(generationInfo, action1, action2);
1057 return ActionDecisionDiagram(action1.guardDd || action2.guardDd, action1.transitionsDd + action2.transitionsDd, assignedGlobalVariables, 0);
1059 if (action1.transitionsDd.isZero()) {
1060 return ActionDecisionDiagram(action2.guardDd, action2.transitionsDd, assignedGlobalVariables, action2.numberOfUsedNondeterminismVariables);
1061 }
else if (action2.transitionsDd.isZero()) {
1062 return ActionDecisionDiagram(action1.guardDd, action1.transitionsDd, assignedGlobalVariables, action1.numberOfUsedNondeterminismVariables);
1066 uint_fast64_t numberOfUsedNondeterminismVariables = std::max(action1.numberOfUsedNondeterminismVariables, action2.numberOfUsedNondeterminismVariables);
1067 if (action1.numberOfUsedNondeterminismVariables > action2.numberOfUsedNondeterminismVariables) {
1070 for (uint_fast64_t i = action2.numberOfUsedNondeterminismVariables;
i < action1.numberOfUsedNondeterminismVariables; ++
i) {
1071 nondeterminismEncoding *= generationInfo.manager->getEncoding(generationInfo.nondeterminismMetaVariables[i], 0).template toAdd<ValueType>();
1073 action2.transitionsDd *= nondeterminismEncoding;
1074 }
else if (action2.numberOfUsedNondeterminismVariables > action1.numberOfUsedNondeterminismVariables) {
1077 for (uint_fast64_t i = action1.numberOfUsedNondeterminismVariables;
i < action2.numberOfUsedNondeterminismVariables; ++
i) {
1078 nondeterminismEncoding *= generationInfo.manager->getEncoding(generationInfo.nondeterminismMetaVariables[i], 0).template toAdd<ValueType>();
1080 action1.transitionsDd *= nondeterminismEncoding;
1085 generationInfo.manager->getEncoding(generationInfo.nondeterminismMetaVariables[numberOfUsedNondeterminismVariables], 1)
1086 .ite(action2.transitionsDd, action1.transitionsDd);
1088 return ActionDecisionDiagram(action1.guardDd || action2.guardDd, combinedTransitions, assignedGlobalVariables, numberOfUsedNondeterminismVariables + 1);
1090 STORM_LOG_THROW(
false, storm::exceptions::InvalidStateException,
"Illegal model type.");
1094template<storm::dd::DdType Type,
typename ValueType>
1095typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram DdPrismModelBuilder<Type, ValueType>::createModuleDecisionDiagram(
1096 GenerationInformation& generationInfo,
storm::prism::Module const& module, std::map<uint_fast64_t, uint_fast64_t>
const& synchronizingActionToOffsetMap) {
1098 ActionDecisionDiagram independentActionDd = createActionDecisionDiagram(generationInfo, module, 0, 0);
1099 uint_fast64_t numberOfUsedNondeterminismVariables = independentActionDd.numberOfUsedNondeterminismVariables;
1102 std::map<uint_fast64_t, ActionDecisionDiagram> actionIndexToDdMap;
1103 for (
auto const& actionIndex : module.getSynchronizingActionIndices()) {
1105 ActionDecisionDiagram tmp = createActionDecisionDiagram(generationInfo, module, actionIndex, synchronizingActionToOffsetMap.at(actionIndex));
1106 numberOfUsedNondeterminismVariables = std::max(numberOfUsedNondeterminismVariables, tmp.numberOfUsedNondeterminismVariables);
1107 actionIndexToDdMap.emplace(actionIndex, tmp);
1110 return ModuleDecisionDiagram(independentActionDd, actionIndexToDdMap, generationInfo.moduleToIdentityMap.at(module.
getName()),
1111 numberOfUsedNondeterminismVariables);
1114template<storm::dd::DdType Type,
typename ValueType>
1116 uint_fast64_t actionIndex) {
1118 if (actionIndex != 0) {
1119 for (uint_fast64_t i = 0;
i < generationInfo.synchronizationMetaVariables.size(); ++
i) {
1120 if ((actionIndex - 1) == i) {
1121 synchronization *= generationInfo.manager->getEncoding(generationInfo.synchronizationMetaVariables[i], 1).template toAdd<ValueType>();
1123 synchronization *= generationInfo.manager->getEncoding(generationInfo.synchronizationMetaVariables[i], 0).template toAdd<ValueType>();
1127 for (uint_fast64_t i = 0;
i < generationInfo.synchronizationMetaVariables.size(); ++
i) {
1128 synchronization *= generationInfo.manager->getEncoding(generationInfo.synchronizationMetaVariables[i], 0).template toAdd<ValueType>();
1131 return synchronization;
1134template<storm::dd::DdType Type,
typename ValueType>
1136 ModuleDecisionDiagram& module) {
1140 module.independentAction.ensureContainsVariables(generationInfo.rowMetaVariables, generationInfo.columnMetaVariables);
1141 for (
auto& synchronizingAction : module.synchronizingActionToDecisionDiagramMap) {
1142 synchronizingAction.second.ensureContainsVariables(generationInfo.rowMetaVariables, generationInfo.columnMetaVariables);
1147 result = generationInfo.manager->template getAddZero<ValueType>();
1151 uint_fast64_t numberOfUsedNondeterminismVariables =
module.numberOfUsedNondeterminismVariables;
1154 std::set<storm::expressions::Variable> missingIdentities;
1155 std::set_difference(generationInfo.allGlobalVariables.begin(), generationInfo.allGlobalVariables.end(),
1156 module.independentAction.assignedGlobalVariables.begin(), module.independentAction.assignedGlobalVariables.end(),
1157 std::inserter(missingIdentities, missingIdentities.begin()));
1159 for (
auto const& variable : missingIdentities) {
1160 STORM_LOG_TRACE(
"Multiplying identity of global variable " << variable.getName() <<
" to independent action.");
1161 identityEncoding *= generationInfo.variableToIdentityMap.at(variable);
1166 for (uint_fast64_t i = module.independentAction.numberOfUsedNondeterminismVariables;
i < numberOfUsedNondeterminismVariables; ++
i) {
1167 nondeterminismEncoding *= generationInfo.manager->getEncoding(generationInfo.nondeterminismMetaVariables[i], 0).template toAdd<ValueType>();
1170 result = identityEncoding *
module.independentAction.transitionsDd * nondeterminismEncoding;
1173 std::map<uint_fast64_t, storm::dd::Add<Type, ValueType>> synchronizingActionToDdMap;
1174 for (
auto const& synchronizingAction : module.synchronizingActionToDecisionDiagramMap) {
1176 missingIdentities = std::set<storm::expressions::Variable>();
1177 std::set_difference(generationInfo.allGlobalVariables.begin(), generationInfo.allGlobalVariables.end(),
1178 synchronizingAction.second.assignedGlobalVariables.begin(), synchronizingAction.second.assignedGlobalVariables.end(),
1179 std::inserter(missingIdentities, missingIdentities.begin()));
1180 identityEncoding = generationInfo.manager->template getAddOne<ValueType>();
1181 for (
auto const& variable : missingIdentities) {
1182 STORM_LOG_TRACE(
"Multiplying identity of global variable " << variable.getName() <<
" to synchronizing action '" << synchronizingAction.first
1184 identityEncoding *= generationInfo.variableToIdentityMap.at(variable);
1187 nondeterminismEncoding = generationInfo.manager->template getAddOne<ValueType>();
1188 for (uint_fast64_t i = synchronizingAction.second.numberOfUsedNondeterminismVariables;
i < numberOfUsedNondeterminismVariables; ++
i) {
1189 nondeterminismEncoding *= generationInfo.manager->getEncoding(generationInfo.nondeterminismMetaVariables[i], 0).template toAdd<ValueType>();
1191 synchronizingActionToDdMap.emplace(synchronizingAction.first, identityEncoding * synchronizingAction.second.transitionsDd * nondeterminismEncoding);
1195 result *= getSynchronizationDecisionDiagram(generationInfo);
1197 for (
auto& synchronizingAction : synchronizingActionToDdMap) {
1198 synchronizingAction.second *= getSynchronizationDecisionDiagram(generationInfo, synchronizingAction.first);
1202 for (
auto const& synchronizingAction : synchronizingActionToDdMap) {
1203 result += synchronizingAction.second;
1210 std::set<storm::expressions::Variable> missingIdentities;
1211 std::set_difference(generationInfo.allGlobalVariables.begin(), generationInfo.allGlobalVariables.end(),
1212 module.independentAction.assignedGlobalVariables.begin(), module.independentAction.assignedGlobalVariables.end(),
1213 std::inserter(missingIdentities, missingIdentities.begin()));
1215 for (
auto const& variable : missingIdentities) {
1216 STORM_LOG_TRACE(
"Multiplying identity of global variable " << variable.getName() <<
" to independent action.");
1217 identityEncoding *= generationInfo.variableToIdentityMap.at(variable);
1220 result = identityEncoding *
module.independentAction.transitionsDd;
1221 for (
auto const& synchronizingAction : module.synchronizingActionToDecisionDiagramMap) {
1223 missingIdentities = std::set<storm::expressions::Variable>();
1224 std::set_difference(generationInfo.allGlobalVariables.begin(), generationInfo.allGlobalVariables.end(),
1225 synchronizingAction.second.assignedGlobalVariables.begin(), synchronizingAction.second.assignedGlobalVariables.end(),
1226 std::inserter(missingIdentities, missingIdentities.begin()));
1227 identityEncoding = generationInfo.manager->template getAddOne<ValueType>();
1228 for (
auto const& variable : missingIdentities) {
1229 STORM_LOG_TRACE(
"Multiplying identity of global variable " << variable.getName() <<
" to synchronizing action '" << synchronizingAction.first
1231 identityEncoding *= generationInfo.variableToIdentityMap.at(variable);
1234 result += identityEncoding * synchronizingAction.second.transitionsDd;
1237 STORM_LOG_THROW(
false, storm::exceptions::InvalidArgumentException,
"Illegal model type.");
1242template<storm::dd::DdType Type,
typename ValueType>
1243typename DdPrismModelBuilder<Type, ValueType>::SystemResult DdPrismModelBuilder<Type, ValueType>::createSystemDecisionDiagram(
1244 GenerationInformation& generationInfo) {
1245 ModuleComposer<Type, ValueType> composer(generationInfo);
1246 ModuleDecisionDiagram system =
1247 composer.compose(generationInfo.program.specifiesSystemComposition() ? generationInfo.program.getSystemCompositionConstruct().getSystemComposition()
1248 : *generationInfo.program.getDefaultSystemComposition());
1253 boost::optional<storm::dd::Add<Type, ValueType>> stateActionDd;
1257 stateActionDd = result.
sumAbstract(generationInfo.columnMetaVariables);
1258 result = result / stateActionDd.get();
1262 for (uint_fast64_t index = system.numberOfUsedNondeterminismVariables; index < generationInfo.nondeterminismMetaVariables.size(); ++index) {
1263 generationInfo.allNondeterminismVariables.erase(generationInfo.nondeterminismMetaVariables[index]);
1265 generationInfo.nondeterminismMetaVariables.resize(system.numberOfUsedNondeterminismVariables);
1268 return SystemResult(result, system, stateActionDd);
1271template<storm::dd::DdType Type,
typename ValueType>
1272std::unordered_map<std::string, storm::models::symbolic::StandardRewardModel<Type, ValueType>>
1273DdPrismModelBuilder<Type, ValueType>::createRewardModelDecisionDiagrams(
1274 std::vector<std::reference_wrapper<storm::prism::RewardModel const>>
const& selectedRewardModels, SystemResult& system,
1277 std::unordered_map<std::string, storm::models::symbolic::StandardRewardModel<Type, ValueType>> rewardModels;
1278 for (
auto const& rewardModel : selectedRewardModels) {
1279 rewardModels.emplace(rewardModel.get().getName(), createRewardModelDecisionDiagrams(generationInfo, rewardModel.get(), globalModule, reachableStatesAdd,
1280 transitionMatrix, system.stateActionDd));
1282 return rewardModels;
1285template<storm::dd::DdType Type,
typename ValueType>
1288 STORM_LOG_WARN_COND(!rewards.
isZero(),
"The reward model declares " << rewardType <<
" but does not assign any non-zero values.");
1291template<storm::dd::DdType Type>
1293 STORM_LOG_WARN_COND(!rewards.
isZero(),
"The reward model declares " << rewardType <<
" but does not assign any non-zero values.");
1296template<storm::dd::DdType Type,
typename ValueType>
1298 GenerationInformation& generationInfo,
storm::prism::RewardModel const& rewardModel, ModuleDecisionDiagram
const& globalModule,
1302 boost::optional<storm::dd::Add<Type, ValueType>> stateRewards;
1304 stateRewards = generationInfo.manager->template getAddZero<ValueType>();
1306 for (
auto const& stateReward : rewardModel.getStateRewards()) {
1311 rewards = reachableStatesAdd * states * rewards;
1314 stateRewards.get() += rewards;
1321 boost::optional<storm::dd::Add<Type, ValueType>> stateActionRewards;
1323 stateActionRewards = generationInfo.manager->template getAddZero<ValueType>();
1325 for (
auto const& stateActionReward : rewardModel.getStateActionRewards()) {
1331 synchronization = getSynchronizationDecisionDiagram(generationInfo, stateActionReward.getActionIndex());
1333 ActionDecisionDiagram
const& actionDd = stateActionReward.isLabeled()
1334 ? globalModule.synchronizingActionToDecisionDiagramMap.at(stateActionReward.getActionIndex())
1335 : globalModule.independentAction;
1336 states *= actionDd.guardDd.template toAdd<ValueType>() * reachableStatesAdd;
1342 if (!stateActionDd) {
1343 stateActionDd = transitionMatrix.
notZero().existsAbstract(generationInfo.columnMetaVariables).template toAdd<ValueType>();
1345 stateActionRewardDd *= stateActionDd.get();
1349 stateActionRewardDd *= actionDd.transitionsDd.
sumAbstract(generationInfo.columnMetaVariables);
1353 stateActionRewards.get() += stateActionRewardDd;
1359 if (!stateActionDd) {
1360 stateActionDd = transitionMatrix.
sumAbstract(generationInfo.columnMetaVariables);
1363 stateActionRewards.get() /= stateActionDd.get();
1367 checkRewards(stateActionRewards.get(),
"action rewards");
1371 boost::optional<storm::dd::Add<Type, ValueType>> transitionRewards;
1373 transitionRewards = generationInfo.manager->template getAddZero<ValueType>();
1375 for (
auto const& transitionReward : rewardModel.getTransitionRewards()) {
1377 generationInfo.rowExpressionAdapter->translateExpression(transitionReward.getSourceStatePredicateExpression());
1379 generationInfo.rowExpressionAdapter->translateExpression(transitionReward.getTargetStatePredicateExpression());
1385 if (transitionReward.isLabeled()) {
1387 synchronization = getSynchronizationDecisionDiagram(generationInfo, transitionReward.getActionIndex());
1389 transitions = globalModule.synchronizingActionToDecisionDiagramMap.at(transitionReward.getActionIndex()).transitionsDd;
1392 synchronization = getSynchronizationDecisionDiagram(generationInfo);
1394 transitions = globalModule.independentAction.transitionsDd;
1400 transitionRewardDd = transitions * transitionRewardDd;
1403 transitionRewardDd = transitions.
notZero().template toAdd<ValueType>() * transitionRewardDd;
1407 transitionRewards.get() += transitionRewardDd;
1411 checkRewards(transitionRewards.get(),
"transition rewards");
1415 transitionRewards.get() /= stateActionDd.get();
1422template<storm::dd::DdType Type,
typename ValueType>
1423std::shared_ptr<storm::models::symbolic::Model<Type, ValueType>> DdPrismModelBuilder<Type, ValueType>::buildInternal(
1427 GenerationInformation generationInfo(program, manager);
1429 SystemResult system = createSystemDecisionDiagram(generationInfo);
1432 ModuleDecisionDiagram
const& globalModule = system.globalModule;
1436 if (!options.terminalStates.empty()) {
1439 return program.getLabelExpression(labelName);
1441 STORM_LOG_THROW(labelName ==
"init" || labelName ==
"deadlock", storm::exceptions::InvalidArgumentException,
1442 "Terminal states refer to illegal label '" << labelName <<
"'.");
1444 return program.getManager().boolean(labelName ==
"init");
1448 terminalStatesBdd = generationInfo.rowExpressionAdapter->translateExpression(terminalExpression).toBdd();
1449 transitionMatrix *= (!terminalStatesBdd).
template toAdd<ValueType>();
1457 transitionMatrixBdd = transitionMatrixBdd.
existsAbstract(generationInfo.allNondeterminismVariables);
1460 storm::dd::Bdd<Type> reachableStates = storm::utility::dd::computeReachableStates<Type>(initialStates, transitionMatrixBdd, generationInfo.rowMetaVariables,
1461 generationInfo.columnMetaVariables)
1464 transitionMatrix *= reachableStatesAdd;
1465 if (system.stateActionDd) {
1466 system.stateActionDd.get() *= reachableStatesAdd;
1474 if (!deadlockStates.
isZero()) {
1480 uint_fast64_t
count = 0;
1481 for (
auto it = deadlockStatesAdd.
begin(), ite = deadlockStatesAdd.
end(); it !=
ite &&
count < 3; ++it, ++
count) {
1482 STORM_LOG_INFO((*it).first.toPrettyString(generationInfo.rowMetaVariables) <<
'\n');
1489 for (
auto const& var : generationInfo.allGlobalVariables) {
1490 identity *= generationInfo.variableToIdentityMap.at(var);
1494 transitionMatrix += deadlockStatesAdd * identity;
1499 for (
auto const& metaVariable : generationInfo.allNondeterminismVariables) {
1500 action *= generationInfo.manager->template getIdentity<ValueType>(metaVariable);
1503 for (
auto const& var : generationInfo.allGlobalVariables) {
1504 action *= generationInfo.variableToIdentityMap.at(var);
1506 transitionMatrix += deadlockStatesAdd * globalModule.identity * action;
1511 <<
" deadlock states. Please unset the option to not fix deadlocks, if you want to fix them automatically.");
1516 deadlockStates = deadlockStates && !terminalStatesBdd;
1519 std::vector<std::reference_wrapper<storm::prism::RewardModel const>> selectedRewardModels;
1522 for (
auto const& rewardModelName : options.rewardModelsToBuild) {
1524 "Model does not possess a reward model with the name '" << rewardModelName <<
"'.");
1527 for (
auto const& rewardModel : program.getRewardModels()) {
1528 if (options.buildAllRewardModels || options.rewardModelsToBuild.find(rewardModel.
getName()) != options.rewardModelsToBuild.end()) {
1529 selectedRewardModels.push_back(rewardModel);
1534 if (selectedRewardModels.empty() && program.
getNumberOfRewardModels() == 1 && options.rewardModelsToBuild.size() == 1 &&
1535 *options.rewardModelsToBuild.begin() ==
"") {
1539 std::unordered_map<std::string, storm::models::symbolic::StandardRewardModel<Type, ValueType>> rewardModels =
1540 createRewardModelDecisionDiagrams(selectedRewardModels, system, generationInfo, globalModule, reachableStatesAdd, transitionMatrix);
1543 std::map<std::string, storm::expressions::Expression> labelToExpressionMapping;
1544 for (
auto const& label : program.getLabels()) {
1545 labelToExpressionMapping.emplace(label.getName(), label.getStatePredicateExpression());
1548 std::shared_ptr<storm::models::symbolic::Model<Type, ValueType>> result;
1551 generationInfo.manager, reachableStates, initialStates, deadlockStates, transitionMatrix, generationInfo.rowMetaVariables,
1552 generationInfo.rowExpressionAdapter, generationInfo.columnMetaVariables, generationInfo.rowColumnMetaVariablePairs, labelToExpressionMapping,
1556 generationInfo.manager, reachableStates, initialStates, deadlockStates, transitionMatrix, system.stateActionDd, generationInfo.rowMetaVariables,
1557 generationInfo.rowExpressionAdapter, generationInfo.columnMetaVariables, generationInfo.rowColumnMetaVariablePairs, labelToExpressionMapping,
1561 generationInfo.manager, reachableStates, initialStates, deadlockStates, transitionMatrix, generationInfo.rowMetaVariables,
1562 generationInfo.rowExpressionAdapter, generationInfo.columnMetaVariables, generationInfo.rowColumnMetaVariablePairs,
1563 generationInfo.allNondeterminismVariables, labelToExpressionMapping, rewardModels));
1565 STORM_LOG_THROW(
false, storm::exceptions::InvalidArgumentException,
"Invalid model type.");
1568 if (std::is_same<ValueType, storm::RationalFunction>::value) {
1569 result->addParameters(generationInfo.parameters);
1575template<storm::dd::DdType Type,
typename ValueType>
1579 std::vector<std::reference_wrapper<storm::prism::Constant const>> undefinedConstants = program.
getUndefinedConstants();
1580 std::stringstream stream;
1581 bool printComma =
false;
1582 for (
auto const& constant : undefinedConstants) {
1588 stream << constant.get().getName() <<
" (" << constant.get().getType() <<
")";
1591 STORM_LOG_THROW(
false, storm::exceptions::InvalidArgumentException,
"Program still contains these undefined constants: " + stream.str());
1594 "Program contains unbounded variables which is not supported by the DD engine.");
1596 STORM_LOG_TRACE(
"Building representation of program:\n" << program <<
'\n');
1598 auto manager = std::make_shared<storm::dd::DdManager<Type>>();
1599 std::shared_ptr<storm::models::symbolic::Model<Type, ValueType>> result;
1600 manager->execute([&program, &options, &manager, &result,
this]() { result = this->buildInternal(program, options, manager); });