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() {
173 std::pair<storm::expressions::Variable, storm::expressions::Variable> variablePair = manager->addMetaVariable(program.
getActionName(actionIndex));
174 synchronizationMetaVariables.push_back(variablePair.first);
175 allSynchronizationMetaVariables.insert(variablePair.first);
176 allNondeterminismVariables.insert(variablePair.first);
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));
186 nondeterminismMetaVariables.push_back(variablePair.first);
187 allNondeterminismVariables.insert(variablePair.first);
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() <<
"]");
200 rowMetaVariables.insert(variablePair.first);
201 variableToRowMetaVariableMap->emplace(integerVariable.getExpressionVariable(), variablePair.first);
203 columnMetaVariables.insert(variablePair.second);
204 variableToColumnMetaVariableMap->emplace(integerVariable.getExpressionVariable(), variablePair.second);
206 storm::dd::Bdd<Type> variableIdentity = manager->getIdentity(variablePair.first, variablePair.second);
207 variableToIdentityMap.emplace(integerVariable.getExpressionVariable(), variableIdentity.template toAdd<ValueType>());
208 rowColumnMetaVariablePairs.push_back(variablePair);
210 allGlobalVariables.insert(integerVariable.getExpressionVariable());
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() <<
"]");
219 rowMetaVariables.insert(variablePair.first);
220 variableToRowMetaVariableMap->emplace(booleanVariable.getExpressionVariable(), variablePair.first);
222 columnMetaVariables.insert(variablePair.second);
223 variableToColumnMetaVariableMap->emplace(booleanVariable.getExpressionVariable(), variablePair.second);
225 storm::dd::Bdd<Type> variableIdentity = manager->getIdentity(variablePair.first, variablePair.second);
226 variableToIdentityMap.emplace(booleanVariable.getExpressionVariable(), variableIdentity.template toAdd<ValueType>());
228 rowColumnMetaVariablePairs.push_back(variablePair);
229 allGlobalVariables.insert(booleanVariable.getExpressionVariable());
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() <<
"]");
246 rowMetaVariables.insert(variablePair.first);
247 variableToRowMetaVariableMap->emplace(integerVariable.getExpressionVariable(), variablePair.first);
249 columnMetaVariables.insert(variablePair.second);
250 variableToColumnMetaVariableMap->emplace(integerVariable.getExpressionVariable(), variablePair.second);
252 storm::dd::Bdd<Type> variableIdentity = manager->getIdentity(variablePair.first, variablePair.second);
253 variableToIdentityMap.emplace(integerVariable.getExpressionVariable(), variableIdentity.template toAdd<ValueType>());
254 moduleIdentity &= variableIdentity;
255 moduleRange &= manager->getRange(variablePair.first);
257 rowColumnMetaVariablePairs.push_back(variablePair);
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() <<
"]");
265 rowMetaVariables.insert(variablePair.first);
266 variableToRowMetaVariableMap->emplace(booleanVariable.getExpressionVariable(), variablePair.first);
268 columnMetaVariables.insert(variablePair.second);
269 variableToColumnMetaVariableMap->emplace(booleanVariable.getExpressionVariable(), variablePair.second);
271 storm::dd::Bdd<Type> variableIdentity = manager->getIdentity(variablePair.first, variablePair.second);
272 variableToIdentityMap.emplace(booleanVariable.getExpressionVariable(), variableIdentity.template toAdd<ValueType>());
273 moduleIdentity &= variableIdentity;
274 moduleRange &= manager->getRange(variablePair.first);
276 rowColumnMetaVariablePairs.push_back(variablePair);
278 moduleToIdentityMap[
module.getName()] = moduleIdentity.template toAdd<ValueType>();
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>(
293 composition.
accept(*
this, newSynchronizingActionToOffsetMap()));
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);
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);
336 std::map<uint_fast64_t, uint_fast64_t> newSynchronizingActionToOffsetMap = synchronizingActionToOffsetMap;
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 <<
".");
341 newSynchronizingActionToOffsetMap[indexPair.first] = it->second;
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);
364 std::map<uint_fast64_t, uint_fast64_t> newSynchronizingActionToOffsetMap = synchronizingActionToOffsetMap;
365 for (
auto const& index : actionIndicesToHide) {
366 newSynchronizingActionToOffsetMap[index] = 0;
371 boost::any_cast<typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram>(
375 hide(sub, actionIndicesToHide);
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);
386 std::map<uint_fast64_t, uint_fast64_t> newSynchronizingActionToOffsetMap = synchronizingActionToOffsetMap;
387 for (
auto const& action : left.synchronizingActionToDecisionDiagramMap) {
388 newSynchronizingActionToOffsetMap[action.first] = action.second.numberOfUsedNondeterminismVariables;
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);
410 boost::any_cast<typename DdPrismModelBuilder<Type, ValueType>::ModuleDecisionDiagram>(composition.
getLeftSubcomposition().
accept(*
this, data));
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));
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);
433 std::map<uint_fast64_t, uint_fast64_t> newSynchronizingActionToOffsetMap = synchronizingActionToOffsetMap;
434 for (
auto const& actionIndex : synchronizingActionIndices) {
435 auto it = left.synchronizingActionToDecisionDiagramMap.find(actionIndex);
436 if (it != left.synchronizingActionToDecisionDiagramMap.end()) {
437 newSynchronizingActionToOffsetMap[actionIndex] = it->second.numberOfUsedNondeterminismVariables;
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);
470 for (
auto const& actionIndex : actionIndicesToHide) {
471 auto it = sub.synchronizingActionToDecisionDiagramMap.find(actionIndex);
472 if (it != sub.synchronizingActionToDecisionDiagramMap.end()) {
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>
607 : buildAllRewardModels(false), rewardModelsToBuild(), buildAllLabels(false), labelsToBuild(), terminalStates() {
611template<storm::dd::DdType Type,
typename ValueType>
613 : buildAllRewardModels(false), rewardModelsToBuild(), buildAllLabels(false), labelsToBuild(
std::set<
std::string>()) {
618template<storm::dd::DdType Type,
typename ValueType>
620 : buildAllRewardModels(false), rewardModelsToBuild(), buildAllLabels(false), labelsToBuild() {
621 for (
auto const& formula : formulas) {
624 if (formulas.size() == 1) {
629template<storm::dd::DdType Type,
typename ValueType>
632 terminalStates.clear();
635 if (!buildAllRewardModels) {
637 rewardModelsToBuild.insert(referencedRewardModels.begin(), referencedRewardModels.end());
641 std::vector<std::shared_ptr<storm::logic::AtomicLabelFormula const>> atomicLabelFormulas = formula.
getAtomicLabelFormulas();
642 for (
auto const& formula : atomicLabelFormulas) {
643 if (!labelsToBuild) {
644 labelsToBuild = std::set<std::string>();
646 labelsToBuild.get().insert(formula.get()->getLabel());
650template<storm::dd::DdType Type,
typename ValueType>
655template<storm::dd::DdType Type,
typename ValueType>
659 : allTransitionsDd(allTransitionsDd), globalModule(globalModule), stateActionDd(stateActionDd) {
668template<storm::dd::DdType Type,
typename ValueType>
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(
734 generationInfo.moduleToRangeMap[
module.getName()].notZero();
739 std::vector<UpdateDecisionDiagram> updateResults;
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);
774 auto updateResultsIt = updateResults.begin();
775 for (
auto updateIt = command.
getUpdates().begin(), updateIte = command.
getUpdates().end(); updateIt != updateIte; ++updateIt, ++updateResultsIt) {
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;
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(
877 GenerationInformation& generationInfo, std::vector<ActionDecisionDiagram>& commandDds) {
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>
903 uint_fast64_t nondeterminismVariableOffset,
904 uint_fast64_t numberOfBinaryVariables, int_fast64_t value) {
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);
919 result.
setValue(metaVariableNameToValueMap, storm::utility::one<ValueType>());
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) {
930 std::set<storm::expressions::Variable> assignedGlobalVariables = equalizeAssignedGlobalVariables(generationInfo, commandDds);
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)));
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,
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) {
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) {
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;
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;
1100 for (
auto const& actionIndex : module.getSynchronizingActionIndices()) {
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>
1113 uint_fast64_t actionIndex) {
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>
1133 ModuleDecisionDiagram& module) {
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()));
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);
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()));
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(
1241 GenerationInformation& generationInfo) {
1242 ModuleComposer<Type, ValueType> composer(generationInfo);
1243 ModuleDecisionDiagram system =
1244 composer.compose(generationInfo.program.specifiesSystemComposition() ? generationInfo.program.getSystemCompositionConstruct().getSystemComposition()
1245 : *generationInfo.program.getDefaultSystemComposition());
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);
1265 return SystemResult(result, system, stateActionDd);
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,
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>();
1303 for (
auto const& stateReward : rewardModel.getStateRewards()) {
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>();
1322 for (
auto const& stateActionReward : rewardModel.getStateActionRewards()) {
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;
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>();
1372 for (
auto const& transitionReward : rewardModel.getTransitionRewards()) {
1374 generationInfo.rowExpressionAdapter->translateExpression(transitionReward.getSourceStatePredicateExpression());
1376 generationInfo.rowExpressionAdapter->translateExpression(transitionReward.getTargetStatePredicateExpression());
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;
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();
1419template<storm::dd::DdType Type,
typename ValueType>
1420std::shared_ptr<storm::models::symbolic::Model<Type, ValueType>> DdPrismModelBuilder<Type, ValueType>::buildInternal(
1424 GenerationInformation generationInfo(program, manager);
1426 SystemResult system = createSystemDecisionDiagram(generationInfo);
1429 ModuleDecisionDiagram
const& globalModule = system.globalModule;
1433 if (!options.terminalStates.empty()) {
1436 return program.getLabelExpression(labelName);
1438 STORM_LOG_THROW(labelName ==
"init" || labelName ==
"deadlock", storm::exceptions::InvalidArgumentException,
1439 "Terminal states refer to illegal label '" << labelName <<
"'.");
1441 return program.getManager().boolean(labelName ==
"init");
1445 terminalStatesBdd = generationInfo.rowExpressionAdapter->translateExpression(terminalExpression).toBdd();
1446 transitionMatrix *= (!terminalStatesBdd).
template toAdd<ValueType>();
1454 transitionMatrixBdd = transitionMatrixBdd.
existsAbstract(generationInfo.allNondeterminismVariables);
1457 storm::dd::Bdd<Type> reachableStates = storm::utility::dd::computeReachableStates<Type>(initialStates, transitionMatrixBdd, generationInfo.rowMetaVariables,
1458 generationInfo.columnMetaVariables)
1461 transitionMatrix *= reachableStatesAdd;
1462 if (system.stateActionDd) {
1463 system.stateActionDd.get() *= reachableStatesAdd;
1471 if (!deadlockStates.
isZero()) {
1473 if (!storm::settings::getModule<storm::settings::modules::BuildSettings>().isDontFixDeadlocksSet()) {
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');
1486 for (
auto const& var : generationInfo.allGlobalVariables) {
1487 identity *= generationInfo.variableToIdentityMap.at(var);
1491 transitionMatrix += deadlockStatesAdd * identity;
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 <<
"'.");
1524 for (
auto const& rewardModel : program.getRewardModels()) {
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;
1548 generationInfo.manager, reachableStates, initialStates, deadlockStates, transitionMatrix, generationInfo.rowMetaVariables,
1549 generationInfo.rowExpressionAdapter, generationInfo.columnMetaVariables, generationInfo.rowColumnMetaVariablePairs, labelToExpressionMapping,
1553 generationInfo.manager, reachableStates, initialStates, deadlockStates, transitionMatrix, system.stateActionDd, generationInfo.rowMetaVariables,
1554 generationInfo.rowExpressionAdapter, generationInfo.columnMetaVariables, generationInfo.rowColumnMetaVariablePairs, labelToExpressionMapping,
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); });