114 parameterCreator.create(this->program, *this->rowExpressionAdapter);
115 if (std::is_same<ValueType, storm::RationalFunction>::value) {
116 this->parameters = parameterCreator.getParameters();
124 std::shared_ptr<storm::dd::DdManager<Type>>
manager;
170 void createMetaVariablesAndIdentities() {
172 for (
auto const& actionIndex :
program.getSynchronizingActionIndices()) {
173 std::pair<storm::expressions::Variable, storm::expressions::Variable> variablePair =
manager->addMetaVariable(
program.getActionName(actionIndex));
180 uint_fast64_t numberOfNondeterminismVariables =
program.getModules().size();
181 for (
auto const& module :
program.getModules()) {
182 numberOfNondeterminismVariables +=
module.getNumberOfCommands();
184 for (uint_fast64_t i = 0; i < numberOfNondeterminismVariables; ++i) {
185 std::pair<storm::expressions::Variable, storm::expressions::Variable> variablePair =
manager->addMetaVariable(
"nondet" + std::to_string(i));
192 int_fast64_t low = integerVariable.getLowerBoundExpression().evaluateAsInt();
193 int_fast64_t high = integerVariable.getUpperBoundExpression().evaluateAsInt();
194 std::pair<storm::expressions::Variable, storm::expressions::Variable> variablePair =
manager->addMetaVariable(integerVariable.getName(), low, high);
196 STORM_LOG_TRACE(
"Created meta variables for global integer variable: " << variablePair.first.getName() <<
"[" << variablePair.first.getIndex()
197 <<
"] and " << variablePair.second.getName() <<
"["
198 << variablePair.second.getIndex() <<
"]");
207 variableToIdentityMap.emplace(integerVariable.getExpressionVariable(), variableIdentity.template toAdd<ValueType>());
213 std::pair<storm::expressions::Variable, storm::expressions::Variable> variablePair =
manager->addMetaVariable(booleanVariable.getName());
215 STORM_LOG_TRACE(
"Created meta variables for global boolean variable: " << variablePair.first.getName() <<
"[" << variablePair.first.getIndex()
216 <<
"] and " << variablePair.second.getName() <<
"["
217 << variablePair.second.getIndex() <<
"]");
226 variableToIdentityMap.emplace(booleanVariable.getExpressionVariable(), variableIdentity.template toAdd<ValueType>());
238 int_fast64_t low = integerVariable.getLowerBoundExpression().evaluateAsInt();
239 int_fast64_t high = integerVariable.getUpperBoundExpression().evaluateAsInt();
240 std::pair<storm::expressions::Variable, storm::expressions::Variable> variablePair =
241 manager->addMetaVariable(integerVariable.getName(), low, high);
242 STORM_LOG_TRACE(
"Created meta variables for integer variable: " << variablePair.first.getName() <<
"[" << variablePair.first.getIndex()
243 <<
"] and " << variablePair.second.getName() <<
"["
244 << variablePair.second.getIndex() <<
"]");
253 variableToIdentityMap.emplace(integerVariable.getExpressionVariable(), variableIdentity.template toAdd<ValueType>());
254 moduleIdentity &= variableIdentity;
255 moduleRange &=
manager->getRange(variablePair.first);
260 std::pair<storm::expressions::Variable, storm::expressions::Variable> variablePair =
manager->addMetaVariable(booleanVariable.getName());
261 STORM_LOG_TRACE(
"Created meta variables for boolean variable: " << variablePair.first.getName() <<
"[" << variablePair.first.getIndex()
262 <<
"] and " << variablePair.second.getName() <<
"["
263 << variablePair.second.getIndex() <<
"]");
272 variableToIdentityMap.emplace(booleanVariable.getExpressionVariable(), variableIdentity.template toAdd<ValueType>());
273 moduleIdentity &= variableIdentity;
274 moduleRange &=
manager->getRange(variablePair.first);
279 moduleToRangeMap[module.getName()] = moduleRange.template toAdd<ValueType>();
284template<storm::dd::DdType Type,
typename ValueType>
292 return boost::any_cast<typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram>(
297 std::map<uint_fast64_t, uint_fast64_t> result;
298 for (
auto const& actionIndex : generationInfo.program.getSynchronizingActionIndices()) {
299 result[actionIndex] = 0;
305 std::map<uint_fast64_t, uint_fast64_t>
const& oldMapping)
const {
306 std::map<uint_fast64_t, uint_fast64_t> result = oldMapping;
307 for (
auto const& action : sub.synchronizingActionToDecisionDiagramMap) {
308 result[action.first] = action.second.numberOfUsedNondeterminismVariables;
315 std::map<uint_fast64_t, uint_fast64_t>
const& synchronizingActionToOffsetMap = boost::any_cast<std::map<uint_fast64_t, uint_fast64_t>
const&>(data);
317 typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram result = DdPrismModelBuilder<Type, ValueType>::createModuleDecisionDiagram(
318 generationInfo, generationInfo.program.getModule(composition.
getModuleName()), synchronizingActionToOffsetMap);
325 std::map<uint_fast64_t, uint_fast64_t> renaming;
327 STORM_LOG_THROW(generationInfo.program.hasAction(namePair.first), storm::exceptions::InvalidArgumentException,
328 "Composition refers to unknown action '" << namePair.first <<
"'.");
329 STORM_LOG_THROW(generationInfo.program.hasAction(namePair.second), storm::exceptions::InvalidArgumentException,
330 "Composition refers to unknown action '" << namePair.second <<
"'.");
331 renaming.emplace(generationInfo.program.getActionIndex(namePair.first), generationInfo.program.getActionIndex(namePair.second));
335 std::map<uint_fast64_t, uint_fast64_t>
const& synchronizingActionToOffsetMap = boost::any_cast<std::map<uint_fast64_t, uint_fast64_t>
const&>(data);
337 for (
auto const& indexPair : renaming) {
338 auto it = synchronizingActionToOffsetMap.find(indexPair.second);
339 STORM_LOG_THROW(it != synchronizingActionToOffsetMap.end(), storm::exceptions::InvalidArgumentException,
340 "Invalid action index " << indexPair.second <<
".");
345 typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram sub =
346 boost::any_cast<typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram>(
350 return rename(sub, renaming);
355 std::set<uint_fast64_t> actionIndicesToHide;
357 STORM_LOG_THROW(generationInfo.program.hasAction(action), storm::exceptions::InvalidArgumentException,
358 "Composition refers to unknown action '" << action <<
"'.");
359 actionIndicesToHide.insert(generationInfo.program.getActionIndex(action));
363 std::map<uint_fast64_t, uint_fast64_t>
const& synchronizingActionToOffsetMap = boost::any_cast<std::map<uint_fast64_t, uint_fast64_t>
const&>(data);
365 for (
auto const& index : actionIndicesToHide) {
370 typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram sub =
371 boost::any_cast<typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram>(
375 hide(sub, actionIndicesToHide);
381 typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram left =
382 boost::any_cast<typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram>(composition.
getLeftSubcomposition().accept(*
this, data));
385 std::map<uint_fast64_t, uint_fast64_t>
const& synchronizingActionToOffsetMap = boost::any_cast<std::map<uint_fast64_t, uint_fast64_t>
const&>(data);
387 for (
auto const& action : left.synchronizingActionToDecisionDiagramMap) {
391 typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram right =
392 boost::any_cast<typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram>(
396 std::set<uint_fast64_t> leftSynchronizationActionIndices = left.getSynchronizingActionIndices();
397 std::set<uint_fast64_t> rightSynchronizationActionIndices = right.getSynchronizingActionIndices();
398 std::set<uint_fast64_t> synchronizationActionIndices;
399 std::set_intersection(leftSynchronizationActionIndices.begin(), leftSynchronizationActionIndices.end(), rightSynchronizationActionIndices.begin(),
400 rightSynchronizationActionIndices.end(), std::inserter(synchronizationActionIndices, synchronizationActionIndices.begin()));
403 composeInParallel(left, right, synchronizationActionIndices);
409 typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram left =
410 boost::any_cast<typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram>(composition.
getLeftSubcomposition().accept(*
this, data));
412 typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram right =
413 boost::any_cast<typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram>(composition.
getRightSubcomposition().accept(*
this, data));
416 composeInParallel(left, right, std::set<uint_fast64_t>());
422 std::set<uint_fast64_t> synchronizingActionIndices;
424 synchronizingActionIndices.insert(generationInfo.program.getActionIndex(action));
428 typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram left =
429 boost::any_cast<typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram>(composition.
getLeftSubcomposition().accept(*
this, data));
432 std::map<uint_fast64_t, uint_fast64_t>
const& synchronizingActionToOffsetMap = boost::any_cast<std::map<uint_fast64_t, uint_fast64_t>
const&>(data);
434 for (
auto const& actionIndex : synchronizingActionIndices) {
435 auto it = left.synchronizingActionToDecisionDiagramMap.find(actionIndex);
436 if (it != left.synchronizingActionToDecisionDiagramMap.end()) {
441 typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram right =
442 boost::any_cast<typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram>(
445 std::set<uint_fast64_t> leftSynchronizationActionIndices = left.getSynchronizingActionIndices();
446 bool isContainedInLeft = std::includes(leftSynchronizationActionIndices.begin(), leftSynchronizationActionIndices.end(),
447 synchronizingActionIndices.begin(), synchronizingActionIndices.end());
449 "Left subcomposition of composition '" << composition <<
"' does not include all actions over which to synchronize.");
451 std::set<uint_fast64_t> rightSynchronizationActionIndices = right.getSynchronizingActionIndices();
452 bool isContainedInRight = std::includes(rightSynchronizationActionIndices.begin(), rightSynchronizationActionIndices.end(),
453 synchronizingActionIndices.begin(), synchronizingActionIndices.end());
455 "Right subcomposition of composition '" << composition <<
"' does not include all actions over which to synchronize.");
458 composeInParallel(left, right, synchronizingActionIndices);
467 void hide(
typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram& sub, std::set<uint_fast64_t>
const& actionIndicesToHide)
const {
470 for (
auto const& actionIndex : actionIndicesToHide) {
471 auto it = sub.synchronizingActionToDecisionDiagramMap.find(actionIndex);
472 if (it != sub.synchronizingActionToDecisionDiagramMap.end()) {
473 sub.independentAction = DdPrismModelBuilder<Type, ValueType>::combineUnsynchronizedActions(generationInfo, sub.independentAction, it->second);
474 sub.numberOfUsedNondeterminismVariables =
475 std::max(sub.numberOfUsedNondeterminismVariables, sub.independentAction.numberOfUsedNondeterminismVariables);
476 sub.synchronizingActionToDecisionDiagramMap.erase(it);
484 typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram rename(
typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram& sub,
485 std::map<uint_fast64_t, uint_fast64_t>
const& renaming)
const {
487 std::map<uint_fast64_t, typename DdPrismModelBuilder<Type, ValueType>::ActionDecisionDiagram> actionIndexToDdMap;
490 for (
auto& action : sub.synchronizingActionToDecisionDiagramMap) {
491 auto renamingIt = renaming.find(action.first);
492 if (renamingIt != renaming.end()) {
495 auto itNewActions = actionIndexToDdMap.find(renamingIt->second);
496 if (itNewActions != actionIndexToDdMap.end()) {
497 actionIndexToDdMap[renamingIt->second] =
498 DdPrismModelBuilder<Type, ValueType>::combineUnsynchronizedActions(generationInfo, action.second, itNewActions->second);
502 actionIndexToDdMap[renamingIt->second] = action.second;
507 auto itNewActions = actionIndexToDdMap.find(action.first);
508 if (itNewActions != actionIndexToDdMap.end()) {
509 actionIndexToDdMap[action.first] =
510 DdPrismModelBuilder<Type, ValueType>::combineUnsynchronizedActions(generationInfo, action.second, itNewActions->second);
513 actionIndexToDdMap[action.first] = action.second;
518 return typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram(sub.independentAction, actionIndexToDdMap, sub.identity,
519 sub.numberOfUsedNondeterminismVariables);
526 void composeInParallel(
typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram& left,
527 typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram& right,
528 std::set<uint_fast64_t>
const& synchronizationActionIndices)
const {
532 uint_fast64_t numberOfUsedNondeterminismVariables = right.independentAction.numberOfUsedNondeterminismVariables;
533 left.independentAction = DdPrismModelBuilder<Type, ValueType>::combineUnsynchronizedActions(generationInfo, left.independentAction,
534 right.independentAction, left.identity, right.identity);
535 numberOfUsedNondeterminismVariables = std::max(numberOfUsedNondeterminismVariables, left.independentAction.numberOfUsedNondeterminismVariables);
538 typename DdPrismModelBuilder<Type, ValueType>::ActionDecisionDiagram emptyAction(*generationInfo.manager);
541 for (
auto& action : left.synchronizingActionToDecisionDiagramMap) {
543 if (synchronizationActionIndices.find(action.first) != synchronizationActionIndices.end()) {
546 if (!right.hasSynchronizingAction(action.first)) {
547 action.second = emptyAction;
550 action.second = DdPrismModelBuilder<Type, ValueType>::combineSynchronizingActions(
551 action.second, right.synchronizingActionToDecisionDiagramMap[action.first]);
557 if (right.hasSynchronizingAction(action.first)) {
558 action.second = DdPrismModelBuilder<Type, ValueType>::combineUnsynchronizedActions(
559 generationInfo, action.second, right.synchronizingActionToDecisionDiagramMap[action.first], left.identity, right.identity);
563 action.second = DdPrismModelBuilder<Type, ValueType>::combineUnsynchronizedActions(generationInfo, action.second, emptyAction,
564 left.identity, right.identity);
567 numberOfUsedNondeterminismVariables = std::max(numberOfUsedNondeterminismVariables, action.second.numberOfUsedNondeterminismVariables);
571 for (
auto const& actionIndex : right.getSynchronizingActionIndices()) {
574 if (!left.hasSynchronizingAction(actionIndex)) {
575 if (synchronizationActionIndices.find(actionIndex) != synchronizationActionIndices.end()) {
578 left.synchronizingActionToDecisionDiagramMap[actionIndex] = emptyAction;
582 left.synchronizingActionToDecisionDiagramMap[actionIndex] = DdPrismModelBuilder<Type, ValueType>::combineUnsynchronizedActions(
583 generationInfo, emptyAction, right.synchronizingActionToDecisionDiagramMap[actionIndex], left.identity, right.identity);
586 numberOfUsedNondeterminismVariables =
587 std::max(numberOfUsedNondeterminismVariables, left.synchronizingActionToDecisionDiagramMap[actionIndex].numberOfUsedNondeterminismVariables);
591 left.identity = left.identity * right.identity;
594 left.numberOfUsedNondeterminismVariables = std::max(left.numberOfUsedNondeterminismVariables, numberOfUsedNondeterminismVariables);
597 typename DdPrismModelBuilder<Type, ValueType>::GenerationInformation& generationInfo;
600template<storm::dd::DdType Type,
typename ValueType>
605template<storm::dd::DdType Type,
typename ValueType>
611template<storm::dd::DdType Type,
typename ValueType>
618template<storm::dd::DdType Type,
typename ValueType>
621 for (
auto const& formula : formulas) {
624 if (formulas.size() == 1) {
625 this->setTerminalStatesFromFormula(*formulas.front());
629template<storm::dd::DdType Type,
typename ValueType>
641 std::vector<std::shared_ptr<storm::logic::AtomicLabelFormula const>> atomicLabelFormulas = formula.
getAtomicLabelFormulas();
642 for (
auto const& formula : atomicLabelFormulas) {
650template<storm::dd::DdType Type,
typename ValueType>
655template<storm::dd::DdType Type,
typename ValueType>
664 typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram
globalModule;
668template<storm::dd::DdType Type,
typename ValueType>
669typename DdPrismModelBuilder<Type, ValueType>::UpdateDecisionDiagram DdPrismModelBuilder<Type, ValueType>::createUpdateDecisionDiagram(
677 std::vector<storm::prism::Assignment> assignments = update.
getAssignments();
678 std::set<storm::expressions::Variable> assignedVariables;
679 for (
auto const& assignment : assignments) {
682 assignedVariables.insert(assignment.getVariable());
696 result = result.
equals(writtenVariable).template toAdd<ValueType>();
700 result = result * generationInfo.
manager->getRange(primedMetaVariable).template toAdd<ValueType>();
706 std::set<storm::expressions::Variable> assignedGlobalVariables;
707 std::set_intersection(assignedVariables.begin(), assignedVariables.end(), generationInfo.
allGlobalVariables.begin(),
708 generationInfo.
allGlobalVariables.end(), std::inserter(assignedGlobalVariables, assignedGlobalVariables.begin()));
712 if (assignedVariables.find(booleanVariable.getExpressionVariable()) == assignedVariables.end()) {
713 STORM_LOG_TRACE(
"Multiplying identity of variable " << booleanVariable.getName());
720 if (assignedVariables.find(integerVariable.getExpressionVariable()) == assignedVariables.end()) {
721 STORM_LOG_TRACE(
"Multiplying identity of variable " << integerVariable.getName());
726 return UpdateDecisionDiagram(updateDd, assignedGlobalVariables);
729template<storm::dd::DdType Type,
typename ValueType>
730typename DdPrismModelBuilder<Type, ValueType>::ActionDecisionDiagram DdPrismModelBuilder<Type, ValueType>::createCommandDecisionDiagram(
731 GenerationInformation& generationInfo, storm::prism::Module
const& module, storm::prism::Command
const& command) {
733 storm::dd::Bdd<Type> guard = generationInfo.rowExpressionAdapter->translateBooleanExpression(command.
getGuardExpression()) &&
734 generationInfo.moduleToRangeMap[
module.getName()].notZero();
739 std::vector<UpdateDecisionDiagram> updateResults;
740 for (storm::prism::Update
const& update : command.
getUpdates()) {
741 updateResults.push_back(createUpdateDecisionDiagram(generationInfo, module, guard.template toAdd<ValueType>(), update));
743 STORM_LOG_WARN_COND(!updateResults.back().updateDd.isZero(),
"Update '" << update <<
"' does not have any effect.");
747 std::set<storm::expressions::Variable> globalVariablesInSomeUpdate;
753 std::for_each(updateResults.begin(), updateResults.end(), [&globalVariablesInSomeUpdate](UpdateDecisionDiagram
const& update) {
754 globalVariablesInSomeUpdate.insert(update.assignedGlobalVariables.begin(), update.assignedGlobalVariables.end());
757 globalVariablesInSomeUpdate = generationInfo.allGlobalVariables;
761 for (
auto& updateResult : updateResults) {
762 std::set<storm::expressions::Variable> missingIdentities;
763 std::set_difference(globalVariablesInSomeUpdate.begin(), globalVariablesInSomeUpdate.end(), updateResult.assignedGlobalVariables.begin(),
764 updateResult.assignedGlobalVariables.end(), std::inserter(missingIdentities, missingIdentities.begin()));
766 for (
auto const& variable : missingIdentities) {
767 STORM_LOG_TRACE(
"Multiplying identity for variable " << variable.getName() <<
"[" << variable.getIndex() <<
"] to update.");
768 updateResult.updateDd *= generationInfo.variableToIdentityMap.at(variable);
773 storm::dd::Add<Type, ValueType> commandDd = generationInfo.manager->template getAddZero<ValueType>();
774 auto updateResultsIt = updateResults.begin();
775 for (
auto updateIt = command.
getUpdates().begin(), updateIte = command.
getUpdates().end(); updateIt != updateIte; ++updateIt, ++updateResultsIt) {
776 storm::dd::Add<Type, ValueType> probabilityDd = generationInfo.rowExpressionAdapter->translateExpression(updateIt->getLikelihoodExpression());
777 commandDd += updateResultsIt->updateDd * probabilityDd;
780 return ActionDecisionDiagram(guard, guard.template toAdd<ValueType>() * commandDd, globalVariablesInSomeUpdate);
782 return ActionDecisionDiagram(*generationInfo.manager);
786template<storm::dd::DdType Type,
typename ValueType>
787typename DdPrismModelBuilder<Type, ValueType>::ActionDecisionDiagram DdPrismModelBuilder<Type, ValueType>::createActionDecisionDiagram(
788 GenerationInformation& generationInfo, storm::prism::Module
const& module, uint_fast64_t synchronizationActionIndex,
789 uint_fast64_t nondeterminismVariableOffset) {
790 std::vector<ActionDecisionDiagram> commandDds;
791 for (storm::prism::Command
const& command : module.
getCommands()) {
793 bool relevant = (synchronizationActionIndex == 0 && !command.
isLabeled()) ||
803 commandDds.push_back(createCommandDecisionDiagram(generationInfo, module, command));
806 ActionDecisionDiagram result(*generationInfo.manager);
807 if (!commandDds.empty()) {
808 switch (generationInfo.program.getModelType()) {
811 result = combineCommandsToActionMarkovChain(generationInfo, commandDds);
814 result = combineCommandsToActionMDP(generationInfo, commandDds, nondeterminismVariableOffset);
817 STORM_LOG_THROW(
false, storm::exceptions::InvalidArgumentException,
"Cannot translate model of this type.");
824template<storm::dd::DdType Type,
typename ValueType>
825std::set<storm::expressions::Variable> DdPrismModelBuilder<Type, ValueType>::equalizeAssignedGlobalVariables(
GenerationInformation const& generationInfo,
826 ActionDecisionDiagram& action1,
827 ActionDecisionDiagram& action2) {
829 std::set<storm::expressions::Variable> globalVariablesInActionDd;
830 std::set_union(action1.assignedGlobalVariables.begin(), action1.assignedGlobalVariables.end(), action2.assignedGlobalVariables.begin(),
831 action2.assignedGlobalVariables.end(), std::inserter(globalVariablesInActionDd, globalVariablesInActionDd.begin()));
833 std::set<storm::expressions::Variable> missingIdentitiesInAction1;
834 std::set_difference(globalVariablesInActionDd.begin(), globalVariablesInActionDd.end(), action1.assignedGlobalVariables.begin(),
835 action1.assignedGlobalVariables.end(), std::inserter(missingIdentitiesInAction1, missingIdentitiesInAction1.begin()));
836 for (
auto const& variable : missingIdentitiesInAction1) {
837 action1.transitionsDd *= generationInfo.variableToIdentityMap.at(variable);
840 std::set<storm::expressions::Variable> missingIdentitiesInAction2;
841 std::set_difference(globalVariablesInActionDd.begin(), globalVariablesInActionDd.end(), action1.assignedGlobalVariables.begin(),
842 action1.assignedGlobalVariables.end(), std::inserter(missingIdentitiesInAction2, missingIdentitiesInAction2.begin()));
843 for (
auto const& variable : missingIdentitiesInAction2) {
844 action2.transitionsDd *= generationInfo.variableToIdentityMap.at(variable);
847 return globalVariablesInActionDd;
850template<storm::dd::DdType Type,
typename ValueType>
851std::set<storm::expressions::Variable> DdPrismModelBuilder<Type, ValueType>::equalizeAssignedGlobalVariables(
GenerationInformation const& generationInfo,
852 std::vector<ActionDecisionDiagram>& actionDds) {
854 std::set<storm::expressions::Variable> globalVariablesInActionDd;
855 for (
auto const& commandDd : actionDds) {
856 globalVariablesInActionDd.insert(commandDd.assignedGlobalVariables.
begin(), commandDd.assignedGlobalVariables.
end());
862 for (
auto& actionDd : actionDds) {
864 std::set<storm::expressions::Variable> missingIdentities;
865 std::set_difference(globalVariablesInActionDd.begin(), globalVariablesInActionDd.end(), actionDd.assignedGlobalVariables.begin(),
866 actionDd.assignedGlobalVariables.end(), std::inserter(missingIdentities, missingIdentities.begin()));
867 for (
auto const& variable : missingIdentities) {
868 STORM_LOG_TRACE(
"Multiplying identity of variable " << variable.getName() <<
".");
869 actionDd.transitionsDd *= generationInfo.variableToIdentityMap.at(variable);
872 return globalVariablesInActionDd;
875template<storm::dd::DdType Type,
typename ValueType>
876typename DdPrismModelBuilder<Type, ValueType>::ActionDecisionDiagram DdPrismModelBuilder<Type, ValueType>::combineCommandsToActionMarkovChain(
878 storm::dd::Bdd<Type> allGuards = generationInfo.manager->getBddZero();
879 storm::dd::Add<Type, ValueType> allCommands = generationInfo.manager->template getAddZero<ValueType>();
880 storm::dd::Bdd<Type> temporary;
883 std::set<storm::expressions::Variable> assignedGlobalVariables = equalizeAssignedGlobalVariables(generationInfo, commandDds);
886 for (
auto& commandDd : commandDds) {
888 temporary = commandDd.guardDd && allGuards;
892 "Guard of a command overlaps with previous guards.");
894 allGuards |= commandDd.guardDd;
895 allCommands += commandDd.transitionsDd;
898 return ActionDecisionDiagram(allGuards, allCommands, assignedGlobalVariables);
901template<storm::dd::DdType Type,
typename ValueType>
902storm::dd::Add<Type, ValueType> DdPrismModelBuilder<Type, ValueType>::encodeChoice(
GenerationInformation& generationInfo,
903 uint_fast64_t nondeterminismVariableOffset,
904 uint_fast64_t numberOfBinaryVariables, int_fast64_t value) {
905 storm::dd::Add<Type, ValueType> result = generationInfo.manager->template getAddZero<ValueType>();
907 STORM_LOG_TRACE(
"Encoding " << value <<
" with " << numberOfBinaryVariables <<
" binary variable(s) starting from offset " << nondeterminismVariableOffset
910 std::map<storm::expressions::Variable, int_fast64_t> metaVariableNameToValueMap;
911 for (uint_fast64_t i = 0;
i < numberOfBinaryVariables; ++
i) {
912 if (value & (1ull << (numberOfBinaryVariables - i - 1))) {
913 metaVariableNameToValueMap.emplace(generationInfo.nondeterminismMetaVariables[nondeterminismVariableOffset + i], 1);
915 metaVariableNameToValueMap.emplace(generationInfo.nondeterminismMetaVariables[nondeterminismVariableOffset + i], 0);
923template<storm::dd::DdType Type,
typename ValueType>
924typename DdPrismModelBuilder<Type, ValueType>::ActionDecisionDiagram DdPrismModelBuilder<Type, ValueType>::combineCommandsToActionMDP(
925 GenerationInformation& generationInfo, std::vector<ActionDecisionDiagram>& commandDds, uint_fast64_t nondeterminismVariableOffset) {
926 storm::dd::Bdd<Type> allGuards = generationInfo.manager->getBddZero();
927 storm::dd::Add<Type, ValueType> allCommands = generationInfo.manager->template getAddZero<ValueType>();
930 std::set<storm::expressions::Variable> assignedGlobalVariables = equalizeAssignedGlobalVariables(generationInfo, commandDds);
933 storm::dd::Add<Type, uint_fast64_t> sumOfGuards = generationInfo.manager->template getAddZero<uint_fast64_t>();
934 for (
auto const& commandDd : commandDds) {
935 sumOfGuards += commandDd.guardDd.template toAdd<uint_fast64_t>();
936 allGuards |= commandDd.guardDd;
938 uint_fast64_t maxChoices = sumOfGuards.
getMax();
943 if (maxChoices == 0) {
944 return ActionDecisionDiagram(*generationInfo.manager);
945 }
else if (maxChoices == 1) {
947 for (
auto const& commandDd : commandDds) {
948 allCommands += commandDd.transitionsDd;
950 return ActionDecisionDiagram(allGuards, allCommands, assignedGlobalVariables);
953 uint_fast64_t numberOfBinaryVariables =
static_cast<uint_fast64_t
>(std::ceil(std::log2(maxChoices)));
955 storm::dd::Bdd<Type> equalsNumberOfChoicesDd;
956 std::vector<storm::dd::Add<Type, ValueType>> choiceDds(maxChoices, generationInfo.manager->template getAddZero<ValueType>());
957 std::vector<storm::dd::Bdd<Type>> remainingDds(maxChoices, generationInfo.manager->getBddZero());
959 for (uint_fast64_t currentChoices = 1; currentChoices <= maxChoices; ++currentChoices) {
961 equalsNumberOfChoicesDd = sumOfGuards.
equals(generationInfo.manager->getConstant(currentChoices));
964 if (equalsNumberOfChoicesDd.
isZero()) {
969 for (uint_fast64_t j = 0; j < currentChoices; ++j) {
970 choiceDds[j] = generationInfo.manager->template getAddZero<ValueType>();
971 remainingDds[j] = equalsNumberOfChoicesDd;
974 for (std::size_t j = 0; j < commandDds.size(); ++j) {
977 storm::dd::Bdd<Type> guardChoicesIntersection = commandDds[j].guardDd && equalsNumberOfChoicesDd;
980 if (guardChoicesIntersection.
isZero()) {
985 for (uint_fast64_t k = 0; k < currentChoices; ++k) {
987 storm::dd::Bdd<Type> remainingGuardChoicesIntersection = guardChoicesIntersection && remainingDds[k];
990 if (!remainingGuardChoicesIntersection.
isZero()) {
992 remainingDds[k] = remainingDds[k] && !remainingGuardChoicesIntersection;
995 choiceDds[k] += remainingGuardChoicesIntersection.template toAdd<ValueType>() * commandDds[j].transitionsDd;
999 guardChoicesIntersection = guardChoicesIntersection && !remainingGuardChoicesIntersection;
1002 if (guardChoicesIntersection.
isZero()) {
1009 for (uint_fast64_t j = 0; j < currentChoices; ++j) {
1010 allCommands += encodeChoice(generationInfo, nondeterminismVariableOffset, numberOfBinaryVariables, j) * choiceDds[j];
1014 sumOfGuards = sumOfGuards * (!equalsNumberOfChoicesDd).
template toAdd<uint_fast64_t>();
1017 return ActionDecisionDiagram(allGuards, allCommands, assignedGlobalVariables, nondeterminismVariableOffset + numberOfBinaryVariables);
1021template<storm::dd::DdType Type,
typename ValueType>
1022typename DdPrismModelBuilder<Type, ValueType>::ActionDecisionDiagram DdPrismModelBuilder<Type, ValueType>::combineSynchronizingActions(
1023 ActionDecisionDiagram
const& action1, ActionDecisionDiagram
const& action2) {
1024 std::set<storm::expressions::Variable> assignedGlobalVariables;
1025 std::set_union(action1.assignedGlobalVariables.begin(), action1.assignedGlobalVariables.end(), action2.assignedGlobalVariables.begin(),
1026 action2.assignedGlobalVariables.end(), std::inserter(assignedGlobalVariables, assignedGlobalVariables.begin()));
1027 return ActionDecisionDiagram(action1.guardDd && action2.guardDd, action1.transitionsDd * action2.transitionsDd, assignedGlobalVariables,
1028 std::max(action1.numberOfUsedNondeterminismVariables, action2.numberOfUsedNondeterminismVariables));
1031template<storm::dd::DdType Type,
typename ValueType>
1032typename DdPrismModelBuilder<Type, ValueType>::ActionDecisionDiagram DdPrismModelBuilder<Type, ValueType>::combineUnsynchronizedActions(
1033 GenerationInformation const& generationInfo, ActionDecisionDiagram& action1, ActionDecisionDiagram& action2,
1034 storm::dd::Add<Type, ValueType>
const& identityDd1, storm::dd::Add<Type, ValueType>
const& identityDd2) {
1036 STORM_LOG_TRACE(
"Multiplying identities to combine unsynchronized actions.");
1037 action1.transitionsDd = action1.transitionsDd * identityDd2;
1038 action2.transitionsDd = action2.transitionsDd * identityDd1;
1041 return combineUnsynchronizedActions(generationInfo, action1, action2);
1044template<storm::dd::DdType Type,
typename ValueType>
1045typename DdPrismModelBuilder<Type, ValueType>::ActionDecisionDiagram DdPrismModelBuilder<Type, ValueType>::combineUnsynchronizedActions(
1046 GenerationInformation const& generationInfo, ActionDecisionDiagram& action1, ActionDecisionDiagram& action2) {
1050 std::set<storm::expressions::Variable> assignedGlobalVariables = equalizeAssignedGlobalVariables(generationInfo, action1, action2);
1054 return ActionDecisionDiagram(action1.guardDd || action2.guardDd, action1.transitionsDd + action2.transitionsDd, assignedGlobalVariables, 0);
1056 if (action1.transitionsDd.isZero()) {
1057 return ActionDecisionDiagram(action2.guardDd, action2.transitionsDd, assignedGlobalVariables, action2.numberOfUsedNondeterminismVariables);
1058 }
else if (action2.transitionsDd.isZero()) {
1059 return ActionDecisionDiagram(action1.guardDd, action1.transitionsDd, assignedGlobalVariables, action1.numberOfUsedNondeterminismVariables);
1063 uint_fast64_t numberOfUsedNondeterminismVariables = std::max(action1.numberOfUsedNondeterminismVariables, action2.numberOfUsedNondeterminismVariables);
1064 if (action1.numberOfUsedNondeterminismVariables > action2.numberOfUsedNondeterminismVariables) {
1065 storm::dd::Add<Type, ValueType> nondeterminismEncoding = generationInfo.manager->template getAddOne<ValueType>();
1067 for (uint_fast64_t i = action2.numberOfUsedNondeterminismVariables; i < action1.numberOfUsedNondeterminismVariables; ++i) {
1068 nondeterminismEncoding *= generationInfo.manager->getEncoding(generationInfo.nondeterminismMetaVariables[i], 0).template toAdd<ValueType>();
1070 action2.transitionsDd *= nondeterminismEncoding;
1071 }
else if (action2.numberOfUsedNondeterminismVariables > action1.numberOfUsedNondeterminismVariables) {
1072 storm::dd::Add<Type, ValueType> nondeterminismEncoding = generationInfo.manager->template getAddOne<ValueType>();
1074 for (uint_fast64_t i = action1.numberOfUsedNondeterminismVariables; i < action2.numberOfUsedNondeterminismVariables; ++i) {
1075 nondeterminismEncoding *= generationInfo.manager->getEncoding(generationInfo.nondeterminismMetaVariables[i], 0).template toAdd<ValueType>();
1077 action1.transitionsDd *= nondeterminismEncoding;
1081 storm::dd::Add<Type, ValueType> combinedTransitions =
1082 generationInfo.manager->getEncoding(generationInfo.nondeterminismMetaVariables[numberOfUsedNondeterminismVariables], 1)
1083 .ite(action2.transitionsDd, action1.transitionsDd);
1085 return ActionDecisionDiagram(action1.guardDd || action2.guardDd, combinedTransitions, assignedGlobalVariables, numberOfUsedNondeterminismVariables + 1);
1087 STORM_LOG_THROW(
false, storm::exceptions::InvalidStateException,
"Illegal model type.");
1091template<storm::dd::DdType Type,
typename ValueType>
1092typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram DdPrismModelBuilder<Type, ValueType>::createModuleDecisionDiagram(
1093 GenerationInformation& generationInfo, storm::prism::Module
const& module, std::map<uint_fast64_t, uint_fast64_t>
const& synchronizingActionToOffsetMap) {
1095 ActionDecisionDiagram independentActionDd = createActionDecisionDiagram(generationInfo, module, 0, 0);
1096 uint_fast64_t numberOfUsedNondeterminismVariables = independentActionDd.numberOfUsedNondeterminismVariables;
1099 std::map<uint_fast64_t, ActionDecisionDiagram> actionIndexToDdMap;
1102 ActionDecisionDiagram tmp = createActionDecisionDiagram(generationInfo, module, actionIndex, synchronizingActionToOffsetMap.at(actionIndex));
1103 numberOfUsedNondeterminismVariables = std::max(numberOfUsedNondeterminismVariables, tmp.numberOfUsedNondeterminismVariables);
1104 actionIndexToDdMap.emplace(actionIndex, tmp);
1107 return ModuleDecisionDiagram(independentActionDd, actionIndexToDdMap, generationInfo.moduleToIdentityMap.at(module.
getName()),
1108 numberOfUsedNondeterminismVariables);
1111template<storm::dd::DdType Type,
typename ValueType>
1112storm::dd::Add<Type, ValueType> DdPrismModelBuilder<Type, ValueType>::getSynchronizationDecisionDiagram(
GenerationInformation& generationInfo,
1113 uint_fast64_t actionIndex) {
1114 storm::dd::Add<Type, ValueType> synchronization = generationInfo.manager->template getAddOne<ValueType>();
1115 if (actionIndex != 0) {
1116 for (uint_fast64_t i = 0;
i < generationInfo.synchronizationMetaVariables.size(); ++
i) {
1117 if ((actionIndex - 1) == i) {
1118 synchronization *= generationInfo.manager->getEncoding(generationInfo.synchronizationMetaVariables[i], 1).template toAdd<ValueType>();
1120 synchronization *= generationInfo.manager->getEncoding(generationInfo.synchronizationMetaVariables[i], 0).template toAdd<ValueType>();
1124 for (uint_fast64_t i = 0;
i < generationInfo.synchronizationMetaVariables.size(); ++
i) {
1125 synchronization *= generationInfo.manager->getEncoding(generationInfo.synchronizationMetaVariables[i], 0).template toAdd<ValueType>();
1128 return synchronization;
1131template<storm::dd::DdType Type,
typename ValueType>
1132storm::dd::Add<Type, ValueType> DdPrismModelBuilder<Type, ValueType>::createSystemFromModule(
GenerationInformation& generationInfo,
1133 ModuleDecisionDiagram& module) {
1134 storm::dd::Add<Type, ValueType> result;
1137 module.independentAction.ensureContainsVariables(generationInfo.rowMetaVariables, generationInfo.columnMetaVariables);
1138 for (
auto& synchronizingAction : module.synchronizingActionToDecisionDiagramMap) {
1139 synchronizingAction.second.ensureContainsVariables(generationInfo.rowMetaVariables, generationInfo.columnMetaVariables);
1144 result = generationInfo.manager->template getAddZero<ValueType>();
1148 uint_fast64_t numberOfUsedNondeterminismVariables =
module.numberOfUsedNondeterminismVariables;
1151 std::set<storm::expressions::Variable> missingIdentities;
1152 std::set_difference(generationInfo.allGlobalVariables.begin(), generationInfo.allGlobalVariables.end(),
1153 module.independentAction.assignedGlobalVariables.begin(), module.independentAction.assignedGlobalVariables.end(),
1154 std::inserter(missingIdentities, missingIdentities.begin()));
1155 storm::dd::Add<Type, ValueType> identityEncoding = generationInfo.manager->template getAddOne<ValueType>();
1156 for (
auto const& variable : missingIdentities) {
1157 STORM_LOG_TRACE(
"Multiplying identity of global variable " << variable.getName() <<
" to independent action.");
1158 identityEncoding *= generationInfo.variableToIdentityMap.at(variable);
1162 storm::dd::Add<Type, ValueType> nondeterminismEncoding = generationInfo.manager->template getAddOne<ValueType>();
1163 for (uint_fast64_t i = module.independentAction.numberOfUsedNondeterminismVariables; i < numberOfUsedNondeterminismVariables; ++i) {
1164 nondeterminismEncoding *= generationInfo.manager->getEncoding(generationInfo.nondeterminismMetaVariables[i], 0).template toAdd<ValueType>();
1167 result = identityEncoding * module.independentAction.transitionsDd * nondeterminismEncoding;
1170 std::map<uint_fast64_t, storm::dd::Add<Type, ValueType>> synchronizingActionToDdMap;
1171 for (
auto const& synchronizingAction : module.synchronizingActionToDecisionDiagramMap) {
1173 missingIdentities = std::set<storm::expressions::Variable>();
1174 std::set_difference(generationInfo.allGlobalVariables.begin(), generationInfo.allGlobalVariables.end(),
1175 synchronizingAction.second.assignedGlobalVariables.begin(), synchronizingAction.second.assignedGlobalVariables.end(),
1176 std::inserter(missingIdentities, missingIdentities.begin()));
1177 identityEncoding = generationInfo.manager->template getAddOne<ValueType>();
1178 for (
auto const& variable : missingIdentities) {
1179 STORM_LOG_TRACE(
"Multiplying identity of global variable " << variable.getName() <<
" to synchronizing action '" << synchronizingAction.first
1181 identityEncoding *= generationInfo.variableToIdentityMap.at(variable);
1184 nondeterminismEncoding = generationInfo.manager->template getAddOne<ValueType>();
1185 for (uint_fast64_t i = synchronizingAction.second.numberOfUsedNondeterminismVariables; i < numberOfUsedNondeterminismVariables; ++i) {
1186 nondeterminismEncoding *= generationInfo.manager->getEncoding(generationInfo.nondeterminismMetaVariables[i], 0).template toAdd<ValueType>();
1188 synchronizingActionToDdMap.emplace(synchronizingAction.first, identityEncoding * synchronizingAction.second.transitionsDd * nondeterminismEncoding);
1192 result *= getSynchronizationDecisionDiagram(generationInfo);
1194 for (
auto& synchronizingAction : synchronizingActionToDdMap) {
1195 synchronizingAction.second *= getSynchronizationDecisionDiagram(generationInfo, synchronizingAction.first);
1199 for (
auto const& synchronizingAction : synchronizingActionToDdMap) {
1200 result += synchronizingAction.second;
1207 std::set<storm::expressions::Variable> missingIdentities;
1208 std::set_difference(generationInfo.allGlobalVariables.begin(), generationInfo.allGlobalVariables.end(),
1209 module.independentAction.assignedGlobalVariables.begin(), module.independentAction.assignedGlobalVariables.end(),
1210 std::inserter(missingIdentities, missingIdentities.begin()));
1211 storm::dd::Add<Type, ValueType> identityEncoding = generationInfo.manager->template getAddOne<ValueType>();
1212 for (
auto const& variable : missingIdentities) {
1213 STORM_LOG_TRACE(
"Multiplying identity of global variable " << variable.getName() <<
" to independent action.");
1214 identityEncoding *= generationInfo.variableToIdentityMap.at(variable);
1217 result = identityEncoding * module.independentAction.transitionsDd;
1218 for (
auto const& synchronizingAction : module.synchronizingActionToDecisionDiagramMap) {
1220 missingIdentities = std::set<storm::expressions::Variable>();
1221 std::set_difference(generationInfo.allGlobalVariables.begin(), generationInfo.allGlobalVariables.end(),
1222 synchronizingAction.second.assignedGlobalVariables.begin(), synchronizingAction.second.assignedGlobalVariables.end(),
1223 std::inserter(missingIdentities, missingIdentities.begin()));
1224 identityEncoding = generationInfo.manager->template getAddOne<ValueType>();
1225 for (
auto const& variable : missingIdentities) {
1226 STORM_LOG_TRACE(
"Multiplying identity of global variable " << variable.getName() <<
" to synchronizing action '" << synchronizingAction.first
1228 identityEncoding *= generationInfo.variableToIdentityMap.at(variable);
1231 result += identityEncoding * synchronizingAction.second.transitionsDd;
1234 STORM_LOG_THROW(
false, storm::exceptions::InvalidArgumentException,
"Illegal model type.");
1239template<storm::dd::DdType Type,
typename ValueType>
1240typename DdPrismModelBuilder<Type, ValueType>::SystemResult DdPrismModelBuilder<Type, ValueType>::createSystemDecisionDiagram(
1243 ModuleDecisionDiagram system =
1244 composer.compose(generationInfo.program.specifiesSystemComposition() ? generationInfo.program.getSystemCompositionConstruct().getSystemComposition()
1245 : *generationInfo.program.getDefaultSystemComposition());
1247 storm::dd::Add<Type, ValueType> result = createSystemFromModule(generationInfo, system);
1250 boost::optional<storm::dd::Add<Type, ValueType>> stateActionDd;
1254 stateActionDd = result.
sumAbstract(generationInfo.columnMetaVariables);
1255 result = result / stateActionDd.get();
1259 for (uint_fast64_t index = system.numberOfUsedNondeterminismVariables; index < generationInfo.nondeterminismMetaVariables.size(); ++index) {
1260 generationInfo.allNondeterminismVariables.erase(generationInfo.nondeterminismMetaVariables[index]);
1262 generationInfo.nondeterminismMetaVariables.resize(system.numberOfUsedNondeterminismVariables);
1268template<storm::dd::DdType Type,
typename ValueType>
1269std::unordered_map<std::string, storm::models::symbolic::StandardRewardModel<Type, ValueType>>
1270DdPrismModelBuilder<Type, ValueType>::createRewardModelDecisionDiagrams(
1271 std::vector<std::reference_wrapper<storm::prism::RewardModel const>>
const& selectedRewardModels,
SystemResult& system,
1272 GenerationInformation& generationInfo, ModuleDecisionDiagram
const& globalModule, storm::dd::Add<Type, ValueType>
const& reachableStatesAdd,
1273 storm::dd::Add<Type, ValueType>
const& transitionMatrix) {
1274 std::unordered_map<std::string, storm::models::symbolic::StandardRewardModel<Type, ValueType>> rewardModels;
1275 for (
auto const& rewardModel : selectedRewardModels) {
1276 rewardModels.emplace(rewardModel.get().getName(), createRewardModelDecisionDiagrams(generationInfo, rewardModel.get(), globalModule, reachableStatesAdd,
1277 transitionMatrix, system.stateActionDd));
1279 return rewardModels;
1282template<storm::dd::DdType Type,
typename ValueType>
1285 STORM_LOG_WARN_COND(!rewards.
isZero(),
"The reward model declares " << rewardType <<
" but does not assign any non-zero values.");
1288template<storm::dd::DdType Type>
1290 STORM_LOG_WARN_COND(!rewards.
isZero(),
"The reward model declares " << rewardType <<
" but does not assign any non-zero values.");
1293template<storm::dd::DdType Type,
typename ValueType>
1295 GenerationInformation& generationInfo,
storm::prism::RewardModel const& rewardModel, ModuleDecisionDiagram
const& globalModule,
1299 boost::optional<storm::dd::Add<Type, ValueType>> stateRewards;
1301 stateRewards = generationInfo.manager->template getAddZero<ValueType>();
1308 rewards = reachableStatesAdd * states * rewards;
1311 stateRewards.get() += rewards;
1318 boost::optional<storm::dd::Add<Type, ValueType>> stateActionRewards;
1320 stateActionRewards = generationInfo.manager->template getAddZero<ValueType>();
1323 storm::dd::Add<Type, ValueType> states = generationInfo.rowExpressionAdapter->translateExpression(stateActionReward.getStatePredicateExpression());
1324 storm::dd::Add<Type, ValueType> rewards = generationInfo.rowExpressionAdapter->translateExpression(stateActionReward.getRewardValueExpression());
1325 storm::dd::Add<Type, ValueType> synchronization = generationInfo.manager->template getAddOne<ValueType>();
1328 synchronization = getSynchronizationDecisionDiagram(generationInfo, stateActionReward.getActionIndex());
1330 ActionDecisionDiagram
const& actionDd = stateActionReward.isLabeled()
1331 ? globalModule.synchronizingActionToDecisionDiagramMap.at(stateActionReward.getActionIndex())
1332 : globalModule.independentAction;
1333 states *= actionDd.guardDd.template toAdd<ValueType>() * reachableStatesAdd;
1334 storm::dd::Add<Type, ValueType> stateActionRewardDd = synchronization * states * rewards;
1339 if (!stateActionDd) {
1340 stateActionDd = transitionMatrix.
notZero().existsAbstract(generationInfo.columnMetaVariables).template toAdd<ValueType>();
1342 stateActionRewardDd *= stateActionDd.get();
1346 stateActionRewardDd *= actionDd.transitionsDd.
sumAbstract(generationInfo.columnMetaVariables);
1350 stateActionRewards.get() += stateActionRewardDd;
1356 if (!stateActionDd) {
1357 stateActionDd = transitionMatrix.
sumAbstract(generationInfo.columnMetaVariables);
1360 stateActionRewards.get() /= stateActionDd.get();
1364 checkRewards(stateActionRewards.get(),
"action rewards");
1368 boost::optional<storm::dd::Add<Type, ValueType>> transitionRewards;
1370 transitionRewards = generationInfo.manager->template getAddZero<ValueType>();
1373 storm::dd::Add<Type, ValueType> sourceStates =
1374 generationInfo.rowExpressionAdapter->translateExpression(transitionReward.getSourceStatePredicateExpression());
1375 storm::dd::Add<Type, ValueType> targetStates =
1376 generationInfo.rowExpressionAdapter->translateExpression(transitionReward.getTargetStatePredicateExpression());
1377 storm::dd::Add<Type, ValueType> rewards = generationInfo.rowExpressionAdapter->translateExpression(transitionReward.getRewardValueExpression());
1379 storm::dd::Add<Type, ValueType> synchronization = generationInfo.manager->template getAddOne<ValueType>();
1381 storm::dd::Add<Type, ValueType> transitions;
1382 if (transitionReward.isLabeled()) {
1384 synchronization = getSynchronizationDecisionDiagram(generationInfo, transitionReward.getActionIndex());
1386 transitions = globalModule.synchronizingActionToDecisionDiagramMap.at(transitionReward.getActionIndex()).transitionsDd;
1389 synchronization = getSynchronizationDecisionDiagram(generationInfo);
1391 transitions = globalModule.independentAction.transitionsDd;
1394 storm::dd::Add<Type, ValueType> transitionRewardDd = synchronization * sourceStates * targetStates * rewards;
1397 transitionRewardDd = transitions * transitionRewardDd;
1400 transitionRewardDd = transitions.
notZero().template toAdd<ValueType>() * transitionRewardDd;
1404 transitionRewards.get() += transitionRewardDd;
1408 checkRewards(transitionRewards.get(),
"transition rewards");
1412 transitionRewards.get() /= stateActionDd.get();
1416 return storm::models::symbolic::StandardRewardModel<Type, ValueType>(stateRewards, stateActionRewards, transitionRewards);
1419template<storm::dd::DdType Type,
typename ValueType>
1420std::shared_ptr<storm::models::symbolic::Model<Type, ValueType>> DdPrismModelBuilder<Type, ValueType>::buildInternal(
1421 storm::prism::Program
const& program,
Options const& options, std::shared_ptr<storm::dd::DdManager<Type>>
const& manager) {
1426 SystemResult system = createSystemDecisionDiagram(generationInfo);
1427 storm::dd::Add<Type, ValueType> transitionMatrix = system.allTransitionsDd;
1429 ModuleDecisionDiagram
const& globalModule = system.globalModule;
1432 storm::dd::Bdd<Type> terminalStatesBdd = generationInfo.manager->getBddZero();
1433 if (!options.terminalStates.empty()) {
1434 storm::expressions::Expression terminalExpression = options.terminalStates.asExpression([&program](std::string
const& labelName) {
1438 STORM_LOG_THROW(labelName ==
"init" || labelName ==
"deadlock", storm::exceptions::InvalidArgumentException,
1439 "Terminal states refer to illegal label '" << labelName <<
"'.");
1445 terminalStatesBdd = generationInfo.rowExpressionAdapter->translateExpression(terminalExpression).toBdd();
1446 transitionMatrix *= (!terminalStatesBdd).
template toAdd<ValueType>();
1450 storm::dd::Bdd<Type> initialStates = createInitialStatesDecisionDiagram(generationInfo);
1452 storm::dd::Bdd<Type> transitionMatrixBdd = transitionMatrix.
notZero();
1454 transitionMatrixBdd = transitionMatrixBdd.
existsAbstract(generationInfo.allNondeterminismVariables);
1458 generationInfo.columnMetaVariables)
1460 storm::dd::Add<Type, ValueType> reachableStatesAdd = reachableStates.template toAdd<ValueType>();
1461 transitionMatrix *= reachableStatesAdd;
1462 if (system.stateActionDd) {
1463 system.stateActionDd.get() *= reachableStatesAdd;
1467 storm::dd::Bdd<Type> statesWithTransition = transitionMatrixBdd.
existsAbstract(generationInfo.columnMetaVariables);
1468 storm::dd::Bdd<Type> deadlockStates = reachableStates && !statesWithTransition;
1471 if (!deadlockStates.
isZero()) {
1476 storm::dd::Add<Type, ValueType> deadlockStatesAdd = deadlockStates.template toAdd<ValueType>();
1477 uint_fast64_t
count = 0;
1478 for (
auto it = deadlockStatesAdd.
begin(), ite = deadlockStatesAdd.
end(); it != ite && count < 3; ++it, ++count) {
1479 STORM_LOG_INFO((*it).first.toPrettyString(generationInfo.rowMetaVariables) <<
'\n');
1483 storm::dd::Add<Type, ValueType> identity = globalModule.identity;
1486 for (
auto const& var : generationInfo.allGlobalVariables) {
1487 identity *= generationInfo.variableToIdentityMap.at(var);
1491 transitionMatrix += deadlockStatesAdd * identity;
1495 storm::dd::Add<Type, ValueType> action = generationInfo.manager->template getAddOne<ValueType>();
1496 for (
auto const& metaVariable : generationInfo.allNondeterminismVariables) {
1497 action *= generationInfo.manager->template getIdentity<ValueType>(metaVariable);
1500 for (
auto const& var : generationInfo.allGlobalVariables) {
1501 action *= generationInfo.variableToIdentityMap.at(var);
1503 transitionMatrix += deadlockStatesAdd * globalModule.identity * action;
1508 <<
" deadlock states. Please unset the option to not fix deadlocks, if you want to fix them automatically.");
1513 deadlockStates = deadlockStates && !terminalStatesBdd;
1516 std::vector<std::reference_wrapper<storm::prism::RewardModel const>> selectedRewardModels;
1519 for (
auto const& rewardModelName : options.rewardModelsToBuild) {
1521 "Model does not possess a reward model with the name '" << rewardModelName <<
"'.");
1525 if (options.buildAllRewardModels || options.rewardModelsToBuild.find(rewardModel.
getName()) != options.rewardModelsToBuild.end()) {
1526 selectedRewardModels.push_back(rewardModel);
1531 if (selectedRewardModels.empty() && program.
getNumberOfRewardModels() == 1 && options.rewardModelsToBuild.size() == 1 &&
1532 *options.rewardModelsToBuild.begin() ==
"") {
1536 std::unordered_map<std::string, storm::models::symbolic::StandardRewardModel<Type, ValueType>> rewardModels =
1537 createRewardModelDecisionDiagrams(selectedRewardModels, system, generationInfo, globalModule, reachableStatesAdd, transitionMatrix);
1540 std::map<std::string, storm::expressions::Expression> labelToExpressionMapping;
1541 for (
auto const& label : program.
getLabels()) {
1542 labelToExpressionMapping.emplace(label.getName(), label.getStatePredicateExpression());
1545 std::shared_ptr<storm::models::symbolic::Model<Type, ValueType>> result;
1547 result = std::shared_ptr<storm::models::symbolic::Model<Type, ValueType>>(
new storm::models::symbolic::Dtmc<Type, ValueType>(
1548 generationInfo.manager, reachableStates, initialStates, deadlockStates, transitionMatrix, generationInfo.rowMetaVariables,
1549 generationInfo.rowExpressionAdapter, generationInfo.columnMetaVariables, generationInfo.rowColumnMetaVariablePairs, labelToExpressionMapping,
1552 result = std::shared_ptr<storm::models::symbolic::Model<Type, ValueType>>(
new storm::models::symbolic::Ctmc<Type, ValueType>(
1553 generationInfo.manager, reachableStates, initialStates, deadlockStates, transitionMatrix, system.stateActionDd, generationInfo.rowMetaVariables,
1554 generationInfo.rowExpressionAdapter, generationInfo.columnMetaVariables, generationInfo.rowColumnMetaVariablePairs, labelToExpressionMapping,
1557 result = std::shared_ptr<storm::models::symbolic::Model<Type, ValueType>>(
new storm::models::symbolic::Mdp<Type, ValueType>(
1558 generationInfo.manager, reachableStates, initialStates, deadlockStates, transitionMatrix, generationInfo.rowMetaVariables,
1559 generationInfo.rowExpressionAdapter, generationInfo.columnMetaVariables, generationInfo.rowColumnMetaVariablePairs,
1560 generationInfo.allNondeterminismVariables, labelToExpressionMapping, rewardModels));
1562 STORM_LOG_THROW(
false, storm::exceptions::InvalidArgumentException,
"Invalid model type.");
1565 if (std::is_same<ValueType, storm::RationalFunction>::value) {
1566 result->addParameters(generationInfo.parameters);
1572template<storm::dd::DdType Type,
typename ValueType>
1576 std::vector<std::reference_wrapper<storm::prism::Constant const>> undefinedConstants = program.
getUndefinedConstants();
1577 std::stringstream stream;
1578 bool printComma =
false;
1579 for (
auto const& constant : undefinedConstants) {
1585 stream << constant.get().getName() <<
" (" << constant.get().getType() <<
")";
1588 STORM_LOG_THROW(
false, storm::exceptions::InvalidArgumentException,
"Program still contains these undefined constants: " + stream.str());
1591 "Program contains unbounded variables which is not supported by the DD engine.");
1593 "Program contains interval updates which are not supported by the DD engnie.");
1595 STORM_LOG_TRACE(
"Building representation of program:\n" << program <<
'\n');
1597 auto manager = std::make_shared<storm::dd::DdManager<Type>>();
1598 std::shared_ptr<storm::models::symbolic::Model<Type, ValueType>> result;
1599 manager->execute([&program, &options, &manager, &result,
this]() { result = this->buildInternal(program, options, manager); });