162 void createMetaVariablesAndIdentities() {
164 for (
auto const& actionIndex :
program.getSynchronizingActionIndices()) {
165 std::pair<storm::expressions::Variable, storm::expressions::Variable> variablePair =
manager->addMetaVariable(
program.getActionName(actionIndex));
172 uint_fast64_t numberOfNondeterminismVariables =
program.getModules().size();
173 for (
auto const& module :
program.getModules()) {
174 numberOfNondeterminismVariables +=
module.getNumberOfCommands();
176 for (uint_fast64_t i = 0; i < numberOfNondeterminismVariables; ++i) {
177 std::pair<storm::expressions::Variable, storm::expressions::Variable> variablePair =
manager->addMetaVariable(
"nondet" + std::to_string(i));
184 int_fast64_t low = integerVariable.getLowerBoundExpression().evaluateAsInt();
185 int_fast64_t high = integerVariable.getUpperBoundExpression().evaluateAsInt();
186 std::pair<storm::expressions::Variable, storm::expressions::Variable> variablePair =
manager->addMetaVariable(integerVariable.getName(), low, high);
188 STORM_LOG_TRACE(
"Created meta variables for global integer variable: " << variablePair.first.getName() <<
"[" << variablePair.first.getIndex()
189 <<
"] and " << variablePair.second.getName() <<
"["
190 << variablePair.second.getIndex() <<
"]");
199 variableToIdentityMap.emplace(integerVariable.getExpressionVariable(), variableIdentity.template toAdd<ValueType>());
205 std::pair<storm::expressions::Variable, storm::expressions::Variable> variablePair =
manager->addMetaVariable(booleanVariable.getName());
207 STORM_LOG_TRACE(
"Created meta variables for global boolean variable: " << variablePair.first.getName() <<
"[" << variablePair.first.getIndex()
208 <<
"] and " << variablePair.second.getName() <<
"["
209 << variablePair.second.getIndex() <<
"]");
218 variableToIdentityMap.emplace(booleanVariable.getExpressionVariable(), variableIdentity.template toAdd<ValueType>());
230 int_fast64_t low = integerVariable.getLowerBoundExpression().evaluateAsInt();
231 int_fast64_t high = integerVariable.getUpperBoundExpression().evaluateAsInt();
232 std::pair<storm::expressions::Variable, storm::expressions::Variable> variablePair =
233 manager->addMetaVariable(integerVariable.getName(), low, high);
234 STORM_LOG_TRACE(
"Created meta variables for integer variable: " << variablePair.first.getName() <<
"[" << variablePair.first.getIndex()
235 <<
"] and " << variablePair.second.getName() <<
"["
236 << variablePair.second.getIndex() <<
"]");
245 variableToIdentityMap.emplace(integerVariable.getExpressionVariable(), variableIdentity.template toAdd<ValueType>());
246 moduleIdentity &= variableIdentity;
247 moduleRange &=
manager->getRange(variablePair.first);
252 std::pair<storm::expressions::Variable, storm::expressions::Variable> variablePair =
manager->addMetaVariable(booleanVariable.getName());
253 STORM_LOG_TRACE(
"Created meta variables for boolean variable: " << variablePair.first.getName() <<
"[" << variablePair.first.getIndex()
254 <<
"] and " << variablePair.second.getName() <<
"["
255 << variablePair.second.getIndex() <<
"]");
264 variableToIdentityMap.emplace(booleanVariable.getExpressionVariable(), variableIdentity.template toAdd<ValueType>());
265 moduleIdentity &= variableIdentity;
266 moduleRange &=
manager->getRange(variablePair.first);
271 moduleToRangeMap[module.getName()] = moduleRange.template toAdd<ValueType>();
276template<storm::dd::DdType Type,
typename ValueType>
284 return boost::any_cast<typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram>(
289 std::map<uint_fast64_t, uint_fast64_t> result;
290 for (
auto const& actionIndex : generationInfo.program.getSynchronizingActionIndices()) {
291 result[actionIndex] = 0;
297 std::map<uint_fast64_t, uint_fast64_t>
const& oldMapping)
const {
298 std::map<uint_fast64_t, uint_fast64_t> result = oldMapping;
299 for (
auto const& action : sub.synchronizingActionToDecisionDiagramMap) {
300 result[action.first] = action.second.numberOfUsedNondeterminismVariables;
307 std::map<uint_fast64_t, uint_fast64_t>
const& synchronizingActionToOffsetMap = boost::any_cast<std::map<uint_fast64_t, uint_fast64_t>
const&>(data);
309 typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram result = DdPrismModelBuilder<Type, ValueType>::createModuleDecisionDiagram(
310 generationInfo, generationInfo.program.getModule(composition.
getModuleName()), synchronizingActionToOffsetMap);
317 std::map<uint_fast64_t, uint_fast64_t> renaming;
319 STORM_LOG_THROW(generationInfo.program.hasAction(namePair.first), storm::exceptions::InvalidArgumentException,
320 "Composition refers to unknown action '" << namePair.first <<
"'.");
321 STORM_LOG_THROW(generationInfo.program.hasAction(namePair.second), storm::exceptions::InvalidArgumentException,
322 "Composition refers to unknown action '" << namePair.second <<
"'.");
323 renaming.emplace(generationInfo.program.getActionIndex(namePair.first), generationInfo.program.getActionIndex(namePair.second));
327 std::map<uint_fast64_t, uint_fast64_t>
const& synchronizingActionToOffsetMap = boost::any_cast<std::map<uint_fast64_t, uint_fast64_t>
const&>(data);
329 for (
auto const& indexPair : renaming) {
330 auto it = synchronizingActionToOffsetMap.find(indexPair.second);
331 STORM_LOG_THROW(it != synchronizingActionToOffsetMap.end(), storm::exceptions::InvalidArgumentException,
332 "Invalid action index " << indexPair.second <<
".");
337 typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram sub =
338 boost::any_cast<typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram>(
342 return rename(sub, renaming);
347 std::set<uint_fast64_t> actionIndicesToHide;
349 STORM_LOG_THROW(generationInfo.program.hasAction(action), storm::exceptions::InvalidArgumentException,
350 "Composition refers to unknown action '" << action <<
"'.");
351 actionIndicesToHide.insert(generationInfo.program.getActionIndex(action));
355 std::map<uint_fast64_t, uint_fast64_t>
const& synchronizingActionToOffsetMap = boost::any_cast<std::map<uint_fast64_t, uint_fast64_t>
const&>(data);
357 for (
auto const& index : actionIndicesToHide) {
362 typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram sub =
363 boost::any_cast<typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram>(
367 hide(sub, actionIndicesToHide);
373 typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram left =
374 boost::any_cast<typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram>(composition.
getLeftSubcomposition().accept(*
this, data));
377 std::map<uint_fast64_t, uint_fast64_t>
const& synchronizingActionToOffsetMap = boost::any_cast<std::map<uint_fast64_t, uint_fast64_t>
const&>(data);
379 for (
auto const& action : left.synchronizingActionToDecisionDiagramMap) {
383 typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram right =
384 boost::any_cast<typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram>(
388 std::set<uint_fast64_t> leftSynchronizationActionIndices = left.getSynchronizingActionIndices();
389 std::set<uint_fast64_t> rightSynchronizationActionIndices = right.getSynchronizingActionIndices();
390 std::set<uint_fast64_t> synchronizationActionIndices;
391 std::set_intersection(leftSynchronizationActionIndices.begin(), leftSynchronizationActionIndices.end(), rightSynchronizationActionIndices.begin(),
392 rightSynchronizationActionIndices.end(), std::inserter(synchronizationActionIndices, synchronizationActionIndices.begin()));
395 composeInParallel(left, right, synchronizationActionIndices);
401 typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram left =
402 boost::any_cast<typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram>(composition.
getLeftSubcomposition().accept(*
this, data));
404 typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram right =
405 boost::any_cast<typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram>(composition.
getRightSubcomposition().accept(*
this, data));
408 composeInParallel(left, right, std::set<uint_fast64_t>());
414 std::set<uint_fast64_t> synchronizingActionIndices;
416 synchronizingActionIndices.insert(generationInfo.program.getActionIndex(action));
420 typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram left =
421 boost::any_cast<typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram>(composition.
getLeftSubcomposition().accept(*
this, data));
424 std::map<uint_fast64_t, uint_fast64_t>
const& synchronizingActionToOffsetMap = boost::any_cast<std::map<uint_fast64_t, uint_fast64_t>
const&>(data);
426 for (
auto const& actionIndex : synchronizingActionIndices) {
427 auto it = left.synchronizingActionToDecisionDiagramMap.find(actionIndex);
428 if (it != left.synchronizingActionToDecisionDiagramMap.end()) {
433 typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram right =
434 boost::any_cast<typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram>(
437 std::set<uint_fast64_t> leftSynchronizationActionIndices = left.getSynchronizingActionIndices();
438 bool isContainedInLeft = std::includes(leftSynchronizationActionIndices.begin(), leftSynchronizationActionIndices.end(),
439 synchronizingActionIndices.begin(), synchronizingActionIndices.end());
441 "Left subcomposition of composition '" << composition <<
"' does not include all actions over which to synchronize.");
443 std::set<uint_fast64_t> rightSynchronizationActionIndices = right.getSynchronizingActionIndices();
444 bool isContainedInRight = std::includes(rightSynchronizationActionIndices.begin(), rightSynchronizationActionIndices.end(),
445 synchronizingActionIndices.begin(), synchronizingActionIndices.end());
447 "Right subcomposition of composition '" << composition <<
"' does not include all actions over which to synchronize.");
450 composeInParallel(left, right, synchronizingActionIndices);
459 void hide(
typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram& sub, std::set<uint_fast64_t>
const& actionIndicesToHide)
const {
462 for (
auto const& actionIndex : actionIndicesToHide) {
463 auto it = sub.synchronizingActionToDecisionDiagramMap.find(actionIndex);
464 if (it != sub.synchronizingActionToDecisionDiagramMap.end()) {
465 sub.independentAction = DdPrismModelBuilder<Type, ValueType>::combineUnsynchronizedActions(generationInfo, sub.independentAction, it->second);
466 sub.numberOfUsedNondeterminismVariables =
467 std::max(sub.numberOfUsedNondeterminismVariables, sub.independentAction.numberOfUsedNondeterminismVariables);
468 sub.synchronizingActionToDecisionDiagramMap.erase(it);
476 typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram rename(
typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram& sub,
477 std::map<uint_fast64_t, uint_fast64_t>
const& renaming)
const {
479 std::map<uint_fast64_t, typename DdPrismModelBuilder<Type, ValueType>::ActionDecisionDiagram> actionIndexToDdMap;
482 for (
auto& action : sub.synchronizingActionToDecisionDiagramMap) {
483 auto renamingIt = renaming.find(action.first);
484 if (renamingIt != renaming.end()) {
487 auto itNewActions = actionIndexToDdMap.find(renamingIt->second);
488 if (itNewActions != actionIndexToDdMap.end()) {
489 actionIndexToDdMap[renamingIt->second] =
490 DdPrismModelBuilder<Type, ValueType>::combineUnsynchronizedActions(generationInfo, action.second, itNewActions->second);
494 actionIndexToDdMap[renamingIt->second] = action.second;
499 auto itNewActions = actionIndexToDdMap.find(action.first);
500 if (itNewActions != actionIndexToDdMap.end()) {
501 actionIndexToDdMap[action.first] =
502 DdPrismModelBuilder<Type, ValueType>::combineUnsynchronizedActions(generationInfo, action.second, itNewActions->second);
505 actionIndexToDdMap[action.first] = action.second;
510 return typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram(sub.independentAction, actionIndexToDdMap, sub.identity,
511 sub.numberOfUsedNondeterminismVariables);
518 void composeInParallel(
typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram& left,
519 typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram& right,
520 std::set<uint_fast64_t>
const& synchronizationActionIndices)
const {
524 uint_fast64_t numberOfUsedNondeterminismVariables = right.independentAction.numberOfUsedNondeterminismVariables;
525 left.independentAction = DdPrismModelBuilder<Type, ValueType>::combineUnsynchronizedActions(generationInfo, left.independentAction,
526 right.independentAction, left.identity, right.identity);
527 numberOfUsedNondeterminismVariables = std::max(numberOfUsedNondeterminismVariables, left.independentAction.numberOfUsedNondeterminismVariables);
530 typename DdPrismModelBuilder<Type, ValueType>::ActionDecisionDiagram emptyAction(*generationInfo.manager);
533 for (
auto& action : left.synchronizingActionToDecisionDiagramMap) {
535 if (synchronizationActionIndices.find(action.first) != synchronizationActionIndices.end()) {
538 if (!right.hasSynchronizingAction(action.first)) {
539 action.second = emptyAction;
542 action.second = DdPrismModelBuilder<Type, ValueType>::combineSynchronizingActions(
543 action.second, right.synchronizingActionToDecisionDiagramMap[action.first]);
549 if (right.hasSynchronizingAction(action.first)) {
550 action.second = DdPrismModelBuilder<Type, ValueType>::combineUnsynchronizedActions(
551 generationInfo, action.second, right.synchronizingActionToDecisionDiagramMap[action.first], left.identity, right.identity);
555 action.second = DdPrismModelBuilder<Type, ValueType>::combineUnsynchronizedActions(generationInfo, action.second, emptyAction,
556 left.identity, right.identity);
559 numberOfUsedNondeterminismVariables = std::max(numberOfUsedNondeterminismVariables, action.second.numberOfUsedNondeterminismVariables);
563 for (
auto const& actionIndex : right.getSynchronizingActionIndices()) {
566 if (!left.hasSynchronizingAction(actionIndex)) {
567 if (synchronizationActionIndices.find(actionIndex) != synchronizationActionIndices.end()) {
570 left.synchronizingActionToDecisionDiagramMap[actionIndex] = emptyAction;
574 left.synchronizingActionToDecisionDiagramMap[actionIndex] = DdPrismModelBuilder<Type, ValueType>::combineUnsynchronizedActions(
575 generationInfo, emptyAction, right.synchronizingActionToDecisionDiagramMap[actionIndex], left.identity, right.identity);
578 numberOfUsedNondeterminismVariables =
579 std::max(numberOfUsedNondeterminismVariables, left.synchronizingActionToDecisionDiagramMap[actionIndex].numberOfUsedNondeterminismVariables);
583 left.identity = left.identity * right.identity;
586 left.numberOfUsedNondeterminismVariables = std::max(left.numberOfUsedNondeterminismVariables, numberOfUsedNondeterminismVariables);
589 typename DdPrismModelBuilder<Type, ValueType>::GenerationInformation& generationInfo;
592template<storm::dd::DdType Type,
typename ValueType>
597template<storm::dd::DdType Type,
typename ValueType>
603template<storm::dd::DdType Type,
typename ValueType>
610template<storm::dd::DdType Type,
typename ValueType>
613 for (
auto const& formula : formulas) {
616 if (formulas.size() == 1) {
617 this->setTerminalStatesFromFormula(*formulas.front());
621template<storm::dd::DdType Type,
typename ValueType>
633 std::vector<std::shared_ptr<storm::logic::AtomicLabelFormula const>> atomicLabelFormulas = formula.
getAtomicLabelFormulas();
634 for (
auto const& formula : atomicLabelFormulas) {
642template<storm::dd::DdType Type,
typename ValueType>
647template<storm::dd::DdType Type,
typename ValueType>
656 typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram
globalModule;
660template<storm::dd::DdType Type,
typename ValueType>
661typename DdPrismModelBuilder<Type, ValueType>::UpdateDecisionDiagram DdPrismModelBuilder<Type, ValueType>::createUpdateDecisionDiagram(
669 std::vector<storm::prism::Assignment> assignments = update.
getAssignments();
670 std::set<storm::expressions::Variable> assignedVariables;
671 for (
auto const& assignment : assignments) {
674 assignedVariables.insert(assignment.getVariable());
688 result = result.
equals(writtenVariable).template toAdd<ValueType>();
692 result = result * generationInfo.
manager->getRange(primedMetaVariable).template toAdd<ValueType>();
698 std::set<storm::expressions::Variable> assignedGlobalVariables;
699 std::set_intersection(assignedVariables.begin(), assignedVariables.end(), generationInfo.
allGlobalVariables.begin(),
700 generationInfo.
allGlobalVariables.end(), std::inserter(assignedGlobalVariables, assignedGlobalVariables.begin()));
704 if (assignedVariables.find(booleanVariable.getExpressionVariable()) == assignedVariables.end()) {
705 STORM_LOG_TRACE(
"Multiplying identity of variable " << booleanVariable.getName());
712 if (assignedVariables.find(integerVariable.getExpressionVariable()) == assignedVariables.end()) {
713 STORM_LOG_TRACE(
"Multiplying identity of variable " << integerVariable.getName());
718 return UpdateDecisionDiagram(updateDd, assignedGlobalVariables);
721template<storm::dd::DdType Type,
typename ValueType>
722typename DdPrismModelBuilder<Type, ValueType>::ActionDecisionDiagram DdPrismModelBuilder<Type, ValueType>::createCommandDecisionDiagram(
723 GenerationInformation& generationInfo, storm::prism::Module
const& module, storm::prism::Command
const& command) {
725 storm::dd::Bdd<Type> guard = generationInfo.rowExpressionAdapter->translateBooleanExpression(command.
getGuardExpression()) &&
726 generationInfo.moduleToRangeMap[
module.getName()].notZero();
731 std::vector<UpdateDecisionDiagram> updateResults;
732 for (storm::prism::Update
const& update : command.
getUpdates()) {
733 updateResults.push_back(createUpdateDecisionDiagram(generationInfo, module, guard.template toAdd<ValueType>(), update));
735 STORM_LOG_WARN_COND(!updateResults.back().updateDd.isZero(),
"Update '" << update <<
"' does not have any effect.");
739 std::set<storm::expressions::Variable> globalVariablesInSomeUpdate;
745 std::for_each(updateResults.begin(), updateResults.end(), [&globalVariablesInSomeUpdate](UpdateDecisionDiagram
const& update) {
746 globalVariablesInSomeUpdate.insert(update.assignedGlobalVariables.begin(), update.assignedGlobalVariables.end());
749 globalVariablesInSomeUpdate = generationInfo.allGlobalVariables;
753 for (
auto& updateResult : updateResults) {
754 std::set<storm::expressions::Variable> missingIdentities;
755 std::set_difference(globalVariablesInSomeUpdate.begin(), globalVariablesInSomeUpdate.end(), updateResult.assignedGlobalVariables.begin(),
756 updateResult.assignedGlobalVariables.end(), std::inserter(missingIdentities, missingIdentities.begin()));
758 for (
auto const& variable : missingIdentities) {
759 STORM_LOG_TRACE(
"Multiplying identity for variable " << variable.getName() <<
"[" << variable.getIndex() <<
"] to update.");
760 updateResult.updateDd *= generationInfo.variableToIdentityMap.at(variable);
765 storm::dd::Add<Type, ValueType> commandDd = generationInfo.manager->template getAddZero<ValueType>();
766 auto updateResultsIt = updateResults.begin();
767 for (
auto updateIt = command.
getUpdates().begin(), updateIte = command.
getUpdates().end(); updateIt != updateIte; ++updateIt, ++updateResultsIt) {
768 storm::dd::Add<Type, ValueType> probabilityDd = generationInfo.rowExpressionAdapter->translateExpression(updateIt->getLikelihoodExpression());
769 commandDd += updateResultsIt->updateDd * probabilityDd;
772 return ActionDecisionDiagram(guard, guard.template toAdd<ValueType>() * commandDd, globalVariablesInSomeUpdate);
774 return ActionDecisionDiagram(*generationInfo.manager);
778template<storm::dd::DdType Type,
typename ValueType>
779typename DdPrismModelBuilder<Type, ValueType>::ActionDecisionDiagram DdPrismModelBuilder<Type, ValueType>::createActionDecisionDiagram(
780 GenerationInformation& generationInfo, storm::prism::Module
const& module, uint_fast64_t synchronizationActionIndex,
781 uint_fast64_t nondeterminismVariableOffset) {
782 std::vector<ActionDecisionDiagram> commandDds;
783 for (storm::prism::Command
const& command : module.
getCommands()) {
785 bool relevant = (synchronizationActionIndex == 0 && !command.
isLabeled()) ||
795 commandDds.push_back(createCommandDecisionDiagram(generationInfo, module, command));
798 ActionDecisionDiagram result(*generationInfo.manager);
799 if (!commandDds.empty()) {
800 switch (generationInfo.program.getModelType()) {
803 result = combineCommandsToActionMarkovChain(generationInfo, commandDds);
806 result = combineCommandsToActionMDP(generationInfo, commandDds, nondeterminismVariableOffset);
809 STORM_LOG_THROW(
false, storm::exceptions::InvalidArgumentException,
"Cannot translate model of this type.");
816template<storm::dd::DdType Type,
typename ValueType>
817std::set<storm::expressions::Variable> DdPrismModelBuilder<Type, ValueType>::equalizeAssignedGlobalVariables(
GenerationInformation const& generationInfo,
818 ActionDecisionDiagram& action1,
819 ActionDecisionDiagram& action2) {
821 std::set<storm::expressions::Variable> globalVariablesInActionDd;
822 std::set_union(action1.assignedGlobalVariables.begin(), action1.assignedGlobalVariables.end(), action2.assignedGlobalVariables.begin(),
823 action2.assignedGlobalVariables.end(), std::inserter(globalVariablesInActionDd, globalVariablesInActionDd.begin()));
825 std::set<storm::expressions::Variable> missingIdentitiesInAction1;
826 std::set_difference(globalVariablesInActionDd.begin(), globalVariablesInActionDd.end(), action1.assignedGlobalVariables.begin(),
827 action1.assignedGlobalVariables.end(), std::inserter(missingIdentitiesInAction1, missingIdentitiesInAction1.begin()));
828 for (
auto const& variable : missingIdentitiesInAction1) {
829 action1.transitionsDd *= generationInfo.variableToIdentityMap.at(variable);
832 std::set<storm::expressions::Variable> missingIdentitiesInAction2;
833 std::set_difference(globalVariablesInActionDd.begin(), globalVariablesInActionDd.end(), action1.assignedGlobalVariables.begin(),
834 action1.assignedGlobalVariables.end(), std::inserter(missingIdentitiesInAction2, missingIdentitiesInAction2.begin()));
835 for (
auto const& variable : missingIdentitiesInAction2) {
836 action2.transitionsDd *= generationInfo.variableToIdentityMap.at(variable);
839 return globalVariablesInActionDd;
842template<storm::dd::DdType Type,
typename ValueType>
843std::set<storm::expressions::Variable> DdPrismModelBuilder<Type, ValueType>::equalizeAssignedGlobalVariables(
GenerationInformation const& generationInfo,
844 std::vector<ActionDecisionDiagram>& actionDds) {
846 std::set<storm::expressions::Variable> globalVariablesInActionDd;
847 for (
auto const& commandDd : actionDds) {
848 globalVariablesInActionDd.insert(commandDd.assignedGlobalVariables.
begin(), commandDd.assignedGlobalVariables.
end());
854 for (
auto& actionDd : actionDds) {
856 std::set<storm::expressions::Variable> missingIdentities;
857 std::set_difference(globalVariablesInActionDd.begin(), globalVariablesInActionDd.end(), actionDd.assignedGlobalVariables.begin(),
858 actionDd.assignedGlobalVariables.end(), std::inserter(missingIdentities, missingIdentities.begin()));
859 for (
auto const& variable : missingIdentities) {
860 STORM_LOG_TRACE(
"Multiplying identity of variable " << variable.getName() <<
".");
861 actionDd.transitionsDd *= generationInfo.variableToIdentityMap.at(variable);
864 return globalVariablesInActionDd;
867template<storm::dd::DdType Type,
typename ValueType>
868typename DdPrismModelBuilder<Type, ValueType>::ActionDecisionDiagram DdPrismModelBuilder<Type, ValueType>::combineCommandsToActionMarkovChain(
870 storm::dd::Bdd<Type> allGuards = generationInfo.manager->getBddZero();
871 storm::dd::Add<Type, ValueType> allCommands = generationInfo.manager->template getAddZero<ValueType>();
872 storm::dd::Bdd<Type> temporary;
875 std::set<storm::expressions::Variable> assignedGlobalVariables = equalizeAssignedGlobalVariables(generationInfo, commandDds);
878 for (
auto& commandDd : commandDds) {
880 temporary = commandDd.guardDd && allGuards;
884 "Guard of a command overlaps with previous guards.");
886 allGuards |= commandDd.guardDd;
887 allCommands += commandDd.transitionsDd;
890 return ActionDecisionDiagram(allGuards, allCommands, assignedGlobalVariables);
893template<storm::dd::DdType Type,
typename ValueType>
894storm::dd::Add<Type, ValueType> DdPrismModelBuilder<Type, ValueType>::encodeChoice(
GenerationInformation& generationInfo,
895 uint_fast64_t nondeterminismVariableOffset,
896 uint_fast64_t numberOfBinaryVariables, int_fast64_t value) {
897 storm::dd::Add<Type, ValueType> result = generationInfo.manager->template getAddZero<ValueType>();
899 STORM_LOG_TRACE(
"Encoding " << value <<
" with " << numberOfBinaryVariables <<
" binary variable(s) starting from offset " << nondeterminismVariableOffset
902 std::map<storm::expressions::Variable, int_fast64_t> metaVariableNameToValueMap;
903 for (uint_fast64_t i = 0;
i < numberOfBinaryVariables; ++
i) {
904 if (value & (1ull << (numberOfBinaryVariables - i - 1))) {
905 metaVariableNameToValueMap.emplace(generationInfo.nondeterminismMetaVariables[nondeterminismVariableOffset + i], 1);
907 metaVariableNameToValueMap.emplace(generationInfo.nondeterminismMetaVariables[nondeterminismVariableOffset + i], 0);
915template<storm::dd::DdType Type,
typename ValueType>
916typename DdPrismModelBuilder<Type, ValueType>::ActionDecisionDiagram DdPrismModelBuilder<Type, ValueType>::combineCommandsToActionMDP(
917 GenerationInformation& generationInfo, std::vector<ActionDecisionDiagram>& commandDds, uint_fast64_t nondeterminismVariableOffset) {
918 storm::dd::Bdd<Type> allGuards = generationInfo.manager->getBddZero();
919 storm::dd::Add<Type, ValueType> allCommands = generationInfo.manager->template getAddZero<ValueType>();
922 std::set<storm::expressions::Variable> assignedGlobalVariables = equalizeAssignedGlobalVariables(generationInfo, commandDds);
925 storm::dd::Add<Type, uint_fast64_t> sumOfGuards = generationInfo.manager->template getAddZero<uint_fast64_t>();
926 for (
auto const& commandDd : commandDds) {
927 sumOfGuards += commandDd.guardDd.template toAdd<uint_fast64_t>();
928 allGuards |= commandDd.guardDd;
930 uint_fast64_t maxChoices = sumOfGuards.
getMax();
935 if (maxChoices == 0) {
936 return ActionDecisionDiagram(*generationInfo.manager);
937 }
else if (maxChoices == 1) {
939 for (
auto const& commandDd : commandDds) {
940 allCommands += commandDd.transitionsDd;
942 return ActionDecisionDiagram(allGuards, allCommands, assignedGlobalVariables);
945 uint_fast64_t numberOfBinaryVariables =
static_cast<uint_fast64_t
>(std::ceil(std::log2(maxChoices)));
947 storm::dd::Bdd<Type> equalsNumberOfChoicesDd;
948 std::vector<storm::dd::Add<Type, ValueType>> choiceDds(maxChoices, generationInfo.manager->template getAddZero<ValueType>());
949 std::vector<storm::dd::Bdd<Type>> remainingDds(maxChoices, generationInfo.manager->getBddZero());
951 for (uint_fast64_t currentChoices = 1; currentChoices <= maxChoices; ++currentChoices) {
953 equalsNumberOfChoicesDd = sumOfGuards.
equals(generationInfo.manager->getConstant(currentChoices));
956 if (equalsNumberOfChoicesDd.
isZero()) {
961 for (uint_fast64_t j = 0; j < currentChoices; ++j) {
962 choiceDds[j] = generationInfo.manager->template getAddZero<ValueType>();
963 remainingDds[j] = equalsNumberOfChoicesDd;
966 for (std::size_t j = 0; j < commandDds.size(); ++j) {
969 storm::dd::Bdd<Type> guardChoicesIntersection = commandDds[j].guardDd && equalsNumberOfChoicesDd;
972 if (guardChoicesIntersection.
isZero()) {
977 for (uint_fast64_t k = 0; k < currentChoices; ++k) {
979 storm::dd::Bdd<Type> remainingGuardChoicesIntersection = guardChoicesIntersection && remainingDds[k];
982 if (!remainingGuardChoicesIntersection.
isZero()) {
984 remainingDds[k] = remainingDds[k] && !remainingGuardChoicesIntersection;
987 choiceDds[k] += remainingGuardChoicesIntersection.template toAdd<ValueType>() * commandDds[j].transitionsDd;
991 guardChoicesIntersection = guardChoicesIntersection && !remainingGuardChoicesIntersection;
994 if (guardChoicesIntersection.
isZero()) {
1001 for (uint_fast64_t j = 0; j < currentChoices; ++j) {
1002 allCommands += encodeChoice(generationInfo, nondeterminismVariableOffset, numberOfBinaryVariables, j) * choiceDds[j];
1006 sumOfGuards = sumOfGuards * (!equalsNumberOfChoicesDd).
template toAdd<uint_fast64_t>();
1009 return ActionDecisionDiagram(allGuards, allCommands, assignedGlobalVariables, nondeterminismVariableOffset + numberOfBinaryVariables);
1013template<storm::dd::DdType Type,
typename ValueType>
1014typename DdPrismModelBuilder<Type, ValueType>::ActionDecisionDiagram DdPrismModelBuilder<Type, ValueType>::combineSynchronizingActions(
1015 ActionDecisionDiagram
const& action1, ActionDecisionDiagram
const& action2) {
1016 std::set<storm::expressions::Variable> assignedGlobalVariables;
1017 std::set_union(action1.assignedGlobalVariables.begin(), action1.assignedGlobalVariables.end(), action2.assignedGlobalVariables.begin(),
1018 action2.assignedGlobalVariables.end(), std::inserter(assignedGlobalVariables, assignedGlobalVariables.begin()));
1019 return ActionDecisionDiagram(action1.guardDd && action2.guardDd, action1.transitionsDd * action2.transitionsDd, assignedGlobalVariables,
1020 std::max(action1.numberOfUsedNondeterminismVariables, action2.numberOfUsedNondeterminismVariables));
1023template<storm::dd::DdType Type,
typename ValueType>
1024typename DdPrismModelBuilder<Type, ValueType>::ActionDecisionDiagram DdPrismModelBuilder<Type, ValueType>::combineUnsynchronizedActions(
1025 GenerationInformation const& generationInfo, ActionDecisionDiagram& action1, ActionDecisionDiagram& action2,
1026 storm::dd::Add<Type, ValueType>
const& identityDd1, storm::dd::Add<Type, ValueType>
const& identityDd2) {
1028 STORM_LOG_TRACE(
"Multiplying identities to combine unsynchronized actions.");
1029 action1.transitionsDd = action1.transitionsDd * identityDd2;
1030 action2.transitionsDd = action2.transitionsDd * identityDd1;
1033 return combineUnsynchronizedActions(generationInfo, action1, action2);
1036template<storm::dd::DdType Type,
typename ValueType>
1037typename DdPrismModelBuilder<Type, ValueType>::ActionDecisionDiagram DdPrismModelBuilder<Type, ValueType>::combineUnsynchronizedActions(
1038 GenerationInformation const& generationInfo, ActionDecisionDiagram& action1, ActionDecisionDiagram& action2) {
1042 std::set<storm::expressions::Variable> assignedGlobalVariables = equalizeAssignedGlobalVariables(generationInfo, action1, action2);
1046 return ActionDecisionDiagram(action1.guardDd || action2.guardDd, action1.transitionsDd + action2.transitionsDd, assignedGlobalVariables, 0);
1048 if (action1.transitionsDd.isZero()) {
1049 return ActionDecisionDiagram(action2.guardDd, action2.transitionsDd, assignedGlobalVariables, action2.numberOfUsedNondeterminismVariables);
1050 }
else if (action2.transitionsDd.isZero()) {
1051 return ActionDecisionDiagram(action1.guardDd, action1.transitionsDd, assignedGlobalVariables, action1.numberOfUsedNondeterminismVariables);
1055 uint_fast64_t numberOfUsedNondeterminismVariables = std::max(action1.numberOfUsedNondeterminismVariables, action2.numberOfUsedNondeterminismVariables);
1056 if (action1.numberOfUsedNondeterminismVariables > action2.numberOfUsedNondeterminismVariables) {
1057 storm::dd::Add<Type, ValueType> nondeterminismEncoding = generationInfo.manager->template getAddOne<ValueType>();
1059 for (uint_fast64_t i = action2.numberOfUsedNondeterminismVariables; i < action1.numberOfUsedNondeterminismVariables; ++i) {
1060 nondeterminismEncoding *= generationInfo.manager->getEncoding(generationInfo.nondeterminismMetaVariables[i], 0).template toAdd<ValueType>();
1062 action2.transitionsDd *= nondeterminismEncoding;
1063 }
else if (action2.numberOfUsedNondeterminismVariables > action1.numberOfUsedNondeterminismVariables) {
1064 storm::dd::Add<Type, ValueType> nondeterminismEncoding = generationInfo.manager->template getAddOne<ValueType>();
1066 for (uint_fast64_t i = action1.numberOfUsedNondeterminismVariables; i < action2.numberOfUsedNondeterminismVariables; ++i) {
1067 nondeterminismEncoding *= generationInfo.manager->getEncoding(generationInfo.nondeterminismMetaVariables[i], 0).template toAdd<ValueType>();
1069 action1.transitionsDd *= nondeterminismEncoding;
1073 storm::dd::Add<Type, ValueType> combinedTransitions =
1074 generationInfo.manager->getEncoding(generationInfo.nondeterminismMetaVariables[numberOfUsedNondeterminismVariables], 1)
1075 .ite(action2.transitionsDd, action1.transitionsDd);
1077 return ActionDecisionDiagram(action1.guardDd || action2.guardDd, combinedTransitions, assignedGlobalVariables, numberOfUsedNondeterminismVariables + 1);
1079 STORM_LOG_THROW(
false, storm::exceptions::InvalidStateException,
"Illegal model type.");
1083template<storm::dd::DdType Type,
typename ValueType>
1084typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram DdPrismModelBuilder<Type, ValueType>::createModuleDecisionDiagram(
1085 GenerationInformation& generationInfo, storm::prism::Module
const& module, std::map<uint_fast64_t, uint_fast64_t>
const& synchronizingActionToOffsetMap) {
1087 ActionDecisionDiagram independentActionDd = createActionDecisionDiagram(generationInfo, module, 0, 0);
1088 uint_fast64_t numberOfUsedNondeterminismVariables = independentActionDd.numberOfUsedNondeterminismVariables;
1091 std::map<uint_fast64_t, ActionDecisionDiagram> actionIndexToDdMap;
1094 ActionDecisionDiagram tmp = createActionDecisionDiagram(generationInfo, module, actionIndex, synchronizingActionToOffsetMap.at(actionIndex));
1095 numberOfUsedNondeterminismVariables = std::max(numberOfUsedNondeterminismVariables, tmp.numberOfUsedNondeterminismVariables);
1096 actionIndexToDdMap.emplace(actionIndex, tmp);
1099 return ModuleDecisionDiagram(independentActionDd, actionIndexToDdMap, generationInfo.moduleToIdentityMap.at(module.
getName()),
1100 numberOfUsedNondeterminismVariables);
1103template<storm::dd::DdType Type,
typename ValueType>
1104storm::dd::Add<Type, ValueType> DdPrismModelBuilder<Type, ValueType>::getSynchronizationDecisionDiagram(
GenerationInformation& generationInfo,
1105 uint_fast64_t actionIndex) {
1106 storm::dd::Add<Type, ValueType> synchronization = generationInfo.manager->template getAddOne<ValueType>();
1107 if (actionIndex != 0) {
1108 for (uint_fast64_t i = 0;
i < generationInfo.synchronizationMetaVariables.size(); ++
i) {
1109 if ((actionIndex - 1) == i) {
1110 synchronization *= generationInfo.manager->getEncoding(generationInfo.synchronizationMetaVariables[i], 1).template toAdd<ValueType>();
1112 synchronization *= generationInfo.manager->getEncoding(generationInfo.synchronizationMetaVariables[i], 0).template toAdd<ValueType>();
1116 for (uint_fast64_t i = 0;
i < generationInfo.synchronizationMetaVariables.size(); ++
i) {
1117 synchronization *= generationInfo.manager->getEncoding(generationInfo.synchronizationMetaVariables[i], 0).template toAdd<ValueType>();
1120 return synchronization;
1123template<storm::dd::DdType Type,
typename ValueType>
1124storm::dd::Add<Type, ValueType> DdPrismModelBuilder<Type, ValueType>::createSystemFromModule(
GenerationInformation& generationInfo,
1125 ModuleDecisionDiagram& module) {
1126 storm::dd::Add<Type, ValueType> result;
1129 module.independentAction.ensureContainsVariables(generationInfo.rowMetaVariables, generationInfo.columnMetaVariables);
1130 for (
auto& synchronizingAction : module.synchronizingActionToDecisionDiagramMap) {
1131 synchronizingAction.second.ensureContainsVariables(generationInfo.rowMetaVariables, generationInfo.columnMetaVariables);
1136 result = generationInfo.manager->template getAddZero<ValueType>();
1140 uint_fast64_t numberOfUsedNondeterminismVariables =
module.numberOfUsedNondeterminismVariables;
1143 std::set<storm::expressions::Variable> missingIdentities;
1144 std::set_difference(generationInfo.allGlobalVariables.begin(), generationInfo.allGlobalVariables.end(),
1145 module.independentAction.assignedGlobalVariables.begin(), module.independentAction.assignedGlobalVariables.end(),
1146 std::inserter(missingIdentities, missingIdentities.begin()));
1147 storm::dd::Add<Type, ValueType> identityEncoding = generationInfo.manager->template getAddOne<ValueType>();
1148 for (
auto const& variable : missingIdentities) {
1149 STORM_LOG_TRACE(
"Multiplying identity of global variable " << variable.getName() <<
" to independent action.");
1150 identityEncoding *= generationInfo.variableToIdentityMap.at(variable);
1154 storm::dd::Add<Type, ValueType> nondeterminismEncoding = generationInfo.manager->template getAddOne<ValueType>();
1155 for (uint_fast64_t i = module.independentAction.numberOfUsedNondeterminismVariables; i < numberOfUsedNondeterminismVariables; ++i) {
1156 nondeterminismEncoding *= generationInfo.manager->getEncoding(generationInfo.nondeterminismMetaVariables[i], 0).template toAdd<ValueType>();
1159 result = identityEncoding * module.independentAction.transitionsDd * nondeterminismEncoding;
1162 std::map<uint_fast64_t, storm::dd::Add<Type, ValueType>> synchronizingActionToDdMap;
1163 for (
auto const& synchronizingAction : module.synchronizingActionToDecisionDiagramMap) {
1165 missingIdentities = std::set<storm::expressions::Variable>();
1166 std::set_difference(generationInfo.allGlobalVariables.begin(), generationInfo.allGlobalVariables.end(),
1167 synchronizingAction.second.assignedGlobalVariables.begin(), synchronizingAction.second.assignedGlobalVariables.end(),
1168 std::inserter(missingIdentities, missingIdentities.begin()));
1169 identityEncoding = generationInfo.manager->template getAddOne<ValueType>();
1170 for (
auto const& variable : missingIdentities) {
1171 STORM_LOG_TRACE(
"Multiplying identity of global variable " << variable.getName() <<
" to synchronizing action '" << synchronizingAction.first
1173 identityEncoding *= generationInfo.variableToIdentityMap.at(variable);
1176 nondeterminismEncoding = generationInfo.manager->template getAddOne<ValueType>();
1177 for (uint_fast64_t i = synchronizingAction.second.numberOfUsedNondeterminismVariables; i < numberOfUsedNondeterminismVariables; ++i) {
1178 nondeterminismEncoding *= generationInfo.manager->getEncoding(generationInfo.nondeterminismMetaVariables[i], 0).template toAdd<ValueType>();
1180 synchronizingActionToDdMap.emplace(synchronizingAction.first, identityEncoding * synchronizingAction.second.transitionsDd * nondeterminismEncoding);
1184 result *= getSynchronizationDecisionDiagram(generationInfo);
1186 for (
auto& synchronizingAction : synchronizingActionToDdMap) {
1187 synchronizingAction.second *= getSynchronizationDecisionDiagram(generationInfo, synchronizingAction.first);
1191 for (
auto const& synchronizingAction : synchronizingActionToDdMap) {
1192 result += synchronizingAction.second;
1199 std::set<storm::expressions::Variable> missingIdentities;
1200 std::set_difference(generationInfo.allGlobalVariables.begin(), generationInfo.allGlobalVariables.end(),
1201 module.independentAction.assignedGlobalVariables.begin(), module.independentAction.assignedGlobalVariables.end(),
1202 std::inserter(missingIdentities, missingIdentities.begin()));
1203 storm::dd::Add<Type, ValueType> identityEncoding = generationInfo.manager->template getAddOne<ValueType>();
1204 for (
auto const& variable : missingIdentities) {
1205 STORM_LOG_TRACE(
"Multiplying identity of global variable " << variable.getName() <<
" to independent action.");
1206 identityEncoding *= generationInfo.variableToIdentityMap.at(variable);
1209 result = identityEncoding * module.independentAction.transitionsDd;
1210 for (
auto const& synchronizingAction : module.synchronizingActionToDecisionDiagramMap) {
1212 missingIdentities = std::set<storm::expressions::Variable>();
1213 std::set_difference(generationInfo.allGlobalVariables.begin(), generationInfo.allGlobalVariables.end(),
1214 synchronizingAction.second.assignedGlobalVariables.begin(), synchronizingAction.second.assignedGlobalVariables.end(),
1215 std::inserter(missingIdentities, missingIdentities.begin()));
1216 identityEncoding = generationInfo.manager->template getAddOne<ValueType>();
1217 for (
auto const& variable : missingIdentities) {
1218 STORM_LOG_TRACE(
"Multiplying identity of global variable " << variable.getName() <<
" to synchronizing action '" << synchronizingAction.first
1220 identityEncoding *= generationInfo.variableToIdentityMap.at(variable);
1223 result += identityEncoding * synchronizingAction.second.transitionsDd;
1226 STORM_LOG_THROW(
false, storm::exceptions::InvalidArgumentException,
"Illegal model type.");
1231template<storm::dd::DdType Type,
typename ValueType>
1232typename DdPrismModelBuilder<Type, ValueType>::SystemResult DdPrismModelBuilder<Type, ValueType>::createSystemDecisionDiagram(
1235 ModuleDecisionDiagram system =
1236 composer.compose(generationInfo.program.specifiesSystemComposition() ? generationInfo.program.getSystemCompositionConstruct().getSystemComposition()
1237 : *generationInfo.program.getDefaultSystemComposition());
1239 storm::dd::Add<Type, ValueType> result = createSystemFromModule(generationInfo, system);
1242 boost::optional<storm::dd::Add<Type, ValueType>> stateActionDd;
1246 stateActionDd = result.
sumAbstract(generationInfo.columnMetaVariables);
1247 result = result / stateActionDd.get();
1251 for (uint_fast64_t index = system.numberOfUsedNondeterminismVariables; index < generationInfo.nondeterminismMetaVariables.size(); ++index) {
1252 generationInfo.allNondeterminismVariables.erase(generationInfo.nondeterminismMetaVariables[index]);
1254 generationInfo.nondeterminismMetaVariables.resize(system.numberOfUsedNondeterminismVariables);
1260template<storm::dd::DdType Type,
typename ValueType>
1261std::unordered_map<std::string, storm::models::symbolic::StandardRewardModel<Type, ValueType>>
1262DdPrismModelBuilder<Type, ValueType>::createRewardModelDecisionDiagrams(
1263 std::vector<std::reference_wrapper<storm::prism::RewardModel const>>
const& selectedRewardModels,
SystemResult& system,
1264 GenerationInformation& generationInfo, ModuleDecisionDiagram
const& globalModule, storm::dd::Add<Type, ValueType>
const& reachableStatesAdd,
1265 storm::dd::Add<Type, ValueType>
const& transitionMatrix) {
1266 std::unordered_map<std::string, storm::models::symbolic::StandardRewardModel<Type, ValueType>> rewardModels;
1267 for (
auto const& rewardModel : selectedRewardModels) {
1268 rewardModels.emplace(rewardModel.get().getName(), createRewardModelDecisionDiagrams(generationInfo, rewardModel.get(), globalModule, reachableStatesAdd,
1269 transitionMatrix, system.stateActionDd));
1271 return rewardModels;
1274template<storm::dd::DdType Type,
typename ValueType>
1277 STORM_LOG_WARN_COND(!rewards.
isZero(),
"The reward model declares " << rewardType <<
" but does not assign any non-zero values.");
1280template<storm::dd::DdType Type>
1282 STORM_LOG_WARN_COND(!rewards.
isZero(),
"The reward model declares " << rewardType <<
" but does not assign any non-zero values.");
1285template<storm::dd::DdType Type,
typename ValueType>
1287 GenerationInformation& generationInfo,
storm::prism::RewardModel const& rewardModel, ModuleDecisionDiagram
const& globalModule,
1291 boost::optional<storm::dd::Add<Type, ValueType>> stateRewards;
1293 stateRewards = generationInfo.manager->template getAddZero<ValueType>();
1300 rewards = reachableStatesAdd * states * rewards;
1303 stateRewards.get() += rewards;
1310 boost::optional<storm::dd::Add<Type, ValueType>> stateActionRewards;
1312 stateActionRewards = generationInfo.manager->template getAddZero<ValueType>();
1315 storm::dd::Add<Type, ValueType> states = generationInfo.rowExpressionAdapter->translateExpression(stateActionReward.getStatePredicateExpression());
1316 storm::dd::Add<Type, ValueType> rewards = generationInfo.rowExpressionAdapter->translateExpression(stateActionReward.getRewardValueExpression());
1317 storm::dd::Add<Type, ValueType> synchronization = generationInfo.manager->template getAddOne<ValueType>();
1320 synchronization = getSynchronizationDecisionDiagram(generationInfo, stateActionReward.getActionIndex());
1322 ActionDecisionDiagram
const& actionDd = stateActionReward.isLabeled()
1323 ? globalModule.synchronizingActionToDecisionDiagramMap.at(stateActionReward.getActionIndex())
1324 : globalModule.independentAction;
1325 states *= actionDd.guardDd.template toAdd<ValueType>() * reachableStatesAdd;
1326 storm::dd::Add<Type, ValueType> stateActionRewardDd = synchronization * states * rewards;
1331 if (!stateActionDd) {
1332 stateActionDd = transitionMatrix.
notZero().existsAbstract(generationInfo.columnMetaVariables).template toAdd<ValueType>();
1334 stateActionRewardDd *= stateActionDd.get();
1338 stateActionRewardDd *= actionDd.transitionsDd.
sumAbstract(generationInfo.columnMetaVariables);
1342 stateActionRewards.get() += stateActionRewardDd;
1348 if (!stateActionDd) {
1349 stateActionDd = transitionMatrix.
sumAbstract(generationInfo.columnMetaVariables);
1352 stateActionRewards.get() /= stateActionDd.get();
1356 checkRewards(stateActionRewards.get(),
"action rewards");
1360 boost::optional<storm::dd::Add<Type, ValueType>> transitionRewards;
1362 transitionRewards = generationInfo.manager->template getAddZero<ValueType>();
1365 storm::dd::Add<Type, ValueType> sourceStates =
1366 generationInfo.rowExpressionAdapter->translateExpression(transitionReward.getSourceStatePredicateExpression());
1367 storm::dd::Add<Type, ValueType> targetStates =
1368 generationInfo.rowExpressionAdapter->translateExpression(transitionReward.getTargetStatePredicateExpression());
1369 storm::dd::Add<Type, ValueType> rewards = generationInfo.rowExpressionAdapter->translateExpression(transitionReward.getRewardValueExpression());
1371 storm::dd::Add<Type, ValueType> synchronization = generationInfo.manager->template getAddOne<ValueType>();
1373 storm::dd::Add<Type, ValueType> transitions;
1374 if (transitionReward.isLabeled()) {
1376 synchronization = getSynchronizationDecisionDiagram(generationInfo, transitionReward.getActionIndex());
1378 transitions = globalModule.synchronizingActionToDecisionDiagramMap.at(transitionReward.getActionIndex()).transitionsDd;
1381 synchronization = getSynchronizationDecisionDiagram(generationInfo);
1383 transitions = globalModule.independentAction.transitionsDd;
1386 storm::dd::Add<Type, ValueType> transitionRewardDd = synchronization * sourceStates * targetStates * rewards;
1389 transitionRewardDd = transitions * transitionRewardDd;
1392 transitionRewardDd = transitions.
notZero().template toAdd<ValueType>() * transitionRewardDd;
1396 transitionRewards.get() += transitionRewardDd;
1400 checkRewards(transitionRewards.get(),
"transition rewards");
1404 transitionRewards.get() /= stateActionDd.get();
1408 return storm::models::symbolic::StandardRewardModel<Type, ValueType>(stateRewards, stateActionRewards, transitionRewards);
1411template<storm::dd::DdType Type,
typename ValueType>
1412std::shared_ptr<storm::models::symbolic::Model<Type, ValueType>> DdPrismModelBuilder<Type, ValueType>::buildInternal(
1413 storm::prism::Program
const& program,
Options const& options, std::shared_ptr<storm::dd::DdManager<Type>>
const& manager) {
1418 SystemResult system = createSystemDecisionDiagram(generationInfo);
1419 storm::dd::Add<Type, ValueType> transitionMatrix = system.allTransitionsDd;
1421 ModuleDecisionDiagram
const& globalModule = system.globalModule;
1424 storm::dd::Bdd<Type> terminalStatesBdd = generationInfo.manager->getBddZero();
1425 if (!options.terminalStates.empty()) {
1426 storm::expressions::Expression terminalExpression = options.terminalStates.asExpression([&program](std::string
const& labelName) {
1430 STORM_LOG_THROW(labelName ==
"init" || labelName ==
"deadlock", storm::exceptions::InvalidArgumentException,
1431 "Terminal states refer to illegal label '" << labelName <<
"'.");
1437 terminalStatesBdd = generationInfo.rowExpressionAdapter->translateExpression(terminalExpression).toBdd();
1438 transitionMatrix *= (!terminalStatesBdd).
template toAdd<ValueType>();
1442 storm::dd::Bdd<Type> initialStates = createInitialStatesDecisionDiagram(generationInfo);
1444 storm::dd::Bdd<Type> transitionMatrixBdd = transitionMatrix.
notZero();
1446 transitionMatrixBdd = transitionMatrixBdd.
existsAbstract(generationInfo.allNondeterminismVariables);
1450 generationInfo.columnMetaVariables)
1452 storm::dd::Add<Type, ValueType> reachableStatesAdd = reachableStates.template toAdd<ValueType>();
1453 transitionMatrix *= reachableStatesAdd;
1454 if (system.stateActionDd) {
1455 system.stateActionDd.get() *= reachableStatesAdd;
1459 storm::dd::Bdd<Type> statesWithTransition = transitionMatrixBdd.
existsAbstract(generationInfo.columnMetaVariables);
1460 storm::dd::Bdd<Type> deadlockStates = reachableStates && !statesWithTransition;
1463 if (!deadlockStates.
isZero()) {
1465 if (options.fixDeadlocks) {
1468 storm::dd::Add<Type, ValueType> deadlockStatesAdd = deadlockStates.template toAdd<ValueType>();
1469 uint_fast64_t
count = 0;
1470 for (
auto it = deadlockStatesAdd.
begin(), ite = deadlockStatesAdd.
end(); it != ite && count < 3; ++it, ++count) {
1471 STORM_LOG_INFO((*it).first.toPrettyString(generationInfo.rowMetaVariables) <<
'\n');
1475 storm::dd::Add<Type, ValueType> identity = globalModule.identity;
1478 for (
auto const& var : generationInfo.allGlobalVariables) {
1479 identity *= generationInfo.variableToIdentityMap.at(var);
1483 transitionMatrix += deadlockStatesAdd * identity;
1487 storm::dd::Add<Type, ValueType> action = generationInfo.manager->template getAddOne<ValueType>();
1488 for (
auto const& metaVariable : generationInfo.allNondeterminismVariables) {
1489 action *= generationInfo.manager->template getIdentity<ValueType>(metaVariable);
1492 for (
auto const& var : generationInfo.allGlobalVariables) {
1493 action *= generationInfo.variableToIdentityMap.at(var);
1495 transitionMatrix += deadlockStatesAdd * globalModule.identity * action;
1500 <<
" deadlock states. Please unset the option to not fix deadlocks, if you want to fix them automatically.");
1505 deadlockStates = deadlockStates && !terminalStatesBdd;
1508 std::vector<std::reference_wrapper<storm::prism::RewardModel const>> selectedRewardModels;
1511 for (
auto const& rewardModelName : options.rewardModelsToBuild) {
1513 "Model does not possess a reward model with the name '" << rewardModelName <<
"'.");
1517 if (options.buildAllRewardModels || options.rewardModelsToBuild.find(rewardModel.
getName()) != options.rewardModelsToBuild.end()) {
1518 selectedRewardModels.push_back(rewardModel);
1523 if (selectedRewardModels.empty() && program.
getNumberOfRewardModels() == 1 && options.rewardModelsToBuild.size() == 1 &&
1524 *options.rewardModelsToBuild.begin() ==
"") {
1528 std::unordered_map<std::string, storm::models::symbolic::StandardRewardModel<Type, ValueType>> rewardModels =
1529 createRewardModelDecisionDiagrams(selectedRewardModels, system, generationInfo, globalModule, reachableStatesAdd, transitionMatrix);
1532 std::map<std::string, storm::expressions::Expression> labelToExpressionMapping;
1533 for (
auto const& label : program.
getLabels()) {
1534 labelToExpressionMapping.emplace(label.getName(), label.getStatePredicateExpression());
1537 std::shared_ptr<storm::models::symbolic::Model<Type, ValueType>> result;
1539 result = std::shared_ptr<storm::models::symbolic::Model<Type, ValueType>>(
new storm::models::symbolic::Dtmc<Type, ValueType>(
1540 generationInfo.manager, reachableStates, initialStates, deadlockStates, transitionMatrix, generationInfo.rowMetaVariables,
1541 generationInfo.rowExpressionAdapter, generationInfo.columnMetaVariables, generationInfo.rowColumnMetaVariablePairs, labelToExpressionMapping,
1544 result = std::shared_ptr<storm::models::symbolic::Model<Type, ValueType>>(
new storm::models::symbolic::Ctmc<Type, ValueType>(
1545 generationInfo.manager, reachableStates, initialStates, deadlockStates, transitionMatrix, system.stateActionDd, generationInfo.rowMetaVariables,
1546 generationInfo.rowExpressionAdapter, generationInfo.columnMetaVariables, generationInfo.rowColumnMetaVariablePairs, labelToExpressionMapping,
1549 result = std::shared_ptr<storm::models::symbolic::Model<Type, ValueType>>(
new storm::models::symbolic::Mdp<Type, ValueType>(
1550 generationInfo.manager, reachableStates, initialStates, deadlockStates, transitionMatrix, generationInfo.rowMetaVariables,
1551 generationInfo.rowExpressionAdapter, generationInfo.columnMetaVariables, generationInfo.rowColumnMetaVariablePairs,
1552 generationInfo.allNondeterminismVariables, labelToExpressionMapping, rewardModels));
1554 STORM_LOG_THROW(
false, storm::exceptions::InvalidArgumentException,
"Invalid model type.");
1557 if (std::is_same<ValueType, storm::RationalFunction>::value) {
1558 result->addParameters(generationInfo.parameters);
1564template<storm::dd::DdType Type,
typename ValueType>
1569 std::vector<std::reference_wrapper<storm::prism::Constant const>> undefinedConstants = program.
getUndefinedConstants();
1570 std::stringstream stream;
1571 bool printComma =
false;
1572 for (
auto const& constant : undefinedConstants) {
1578 stream << constant.get().getName() <<
" (" << constant.get().getType() <<
")";
1581 STORM_LOG_THROW(
false, storm::exceptions::InvalidArgumentException,
"Program still contains these undefined constants: " + stream.str() +
".");
1584 "Program contains unbounded variables which is not supported by the DD engine.");
1586 "Program contains interval updates which are not supported by the DD engnie.");
1588 STORM_LOG_TRACE(
"Building representation of program:\n" << program <<
'\n');
1590 auto manager = std::make_shared<storm::dd::DdManager<Type>>(env);
1591 std::shared_ptr<storm::models::symbolic::Model<Type, ValueType>> result;
1592 manager->execute([&program, &options, &manager, &result,
this]() { result = this->buildInternal(program, options, manager); });