21 std::set<storm::expressions::Variable>
const& givenVariablesToMakeGlobal, std::string suffix) {
22 labelRenaming.clear();
23 rewardModelRenaming.clear();
24 formulaToFunctionCallMap.clear();
63 std::map<storm::expressions::Variable, bool> variablesToMakeGlobal;
64 for (
auto const& var : givenVariablesToMakeGlobal) {
65 variablesToMakeGlobal.emplace(var,
true);
70 std::set<storm::expressions::Variable> renamedVariables;
71 for (
auto const& module : program.
getModules()) {
72 if (module.isRenamedFromModule()) {
73 for (
auto const& renaimingPair :
module.getRenaming()) {
74 if (manager->hasVariable(renaimingPair.first)) {
75 renamedVariables.insert(manager->getVariable(renaimingPair.first));
77 if (manager->hasVariable(renaimingPair.second)) {
78 renamedVariables.insert(manager->getVariable(renaimingPair.second));
86 for (
auto const& formula : program.getFormulas()) {
90 std::set<storm::expressions::Variable> variablesInFormula, placeholdersInFormula;
91 for (
auto const& var : formula.getExpression().getVariables()) {
93 auto functionCallIt = formulaToFunctionCallMap.find(var);
94 if (functionCallIt == formulaToFunctionCallMap.end()) {
95 if (renamedVariables.count(var) > 0) {
96 variablesInFormula.insert(var);
98 variablesToMakeGlobal.emplace(var,
true);
103 for (
auto const& innerFunctionArg : innerFunctionCall.getArguments()) {
105 if (renamedVariables.count(argVar) > 0) {
106 variablesInFormula.insert(argVar);
108 variablesToMakeGlobal.emplace(argVar,
true);
111 placeholdersInFormula.insert(var);
116 std::map<storm::expressions::Variable, storm::expressions::Expression> functionBodySubstitution;
117 std::vector<storm::expressions::Variable> functionParameters;
118 std::vector<std::shared_ptr<storm::expressions::BaseExpression const>> functionArguments;
119 for (
auto const& var : variablesInFormula) {
120 functionArguments.push_back(var.getExpression().getBaseExpressionPointer());
121 functionParameters.push_back(
manager->declareVariable(formula.getName() +
"__param__" + var.getName() + suffix, var.getType()));
122 functionBodySubstitution[var] = functionParameters.back().
getExpression();
124 for (
auto const& formulaVar : placeholdersInFormula) {
125 functionBodySubstitution[formulaVar] =
131 janiModel.addFunctionDefinition(funDef);
132 auto functionCallExpression =
133 std::make_shared<storm::expressions::FunctionCallExpression>(*manager, formula.getType(), formula.getName(), functionArguments);
134 formulaToFunctionCallMap[formula.getExpressionVariable()] = functionCallExpression->toExpression();
140 std::map<storm::expressions::Variable, std::reference_wrapper<storm::jani::Variable const>> variableToVariableMap;
143 for (
auto const& variable : program.getGlobalIntegerVariables()) {
144 if (variable.hasLowerBoundExpression() || variable.hasUpperBoundExpression()) {
147 false, variable.getLowerBoundExpression(), variable.getUpperBoundExpression()));
148 variableToVariableMap.emplace(variable.getExpressionVariable(), createdVariable);
152 variableToVariableMap.emplace(variable.getExpressionVariable(), createdVariable);
155 for (
auto const& variable : program.getGlobalBooleanVariables()) {
158 variableToVariableMap.emplace(variable.getExpressionVariable(), createdVariable);
162 for (
auto const& action : program.getActions()) {
164 if (!action.empty()) {
171 std::map<storm::expressions::Variable, std::set<uint_fast64_t>> variablesToAccessingModuleIndices;
172 for (uint_fast64_t index = 0; index < program.getNumberOfModules(); ++index) {
176 std::set<storm::expressions::Variable> variables =
module.getAllExpressionVariables();
177 for (
auto const& command : module.getCommands()) {
178 command.getGuardExpression().getBaseExpression().gatherVariables(variables);
179 for (
auto const& update : command.getUpdates()) {
180 update.getLikelihoodExpression().gatherVariables(variables);
181 for (
auto const& assignment : update.getAssignments()) {
182 assignment.getExpression().getBaseExpression().gatherVariables(variables);
183 variables.insert(assignment.getVariable());
189 std::map<storm::expressions::Variable, storm::expressions::Expression> renamedFormulaToFunctionCallMap;
190 if (module.isRenamedFromModule()) {
191 renamedFormulaToFunctionCallMap = program.getSubstitutionForRenamedModule(module, formulaToFunctionCallMap);
194 for (
auto const& variable : variables) {
196 if (formulaToFunctionCallMap.count(variable) > 0) {
197 std::set<storm::expressions::Variable> variablesInFunctionCall;
198 if (module.isRenamedFromModule()) {
199 variablesInFunctionCall = renamedFormulaToFunctionCallMap[variable].getVariables();
201 variablesInFunctionCall = formulaToFunctionCallMap[variable].getVariables();
203 for (
auto const& funVar : variablesInFunctionCall) {
204 variablesToAccessingModuleIndices[funVar].insert(index);
207 variablesToAccessingModuleIndices[variable].insert(index);
213 for (
auto const& varMods : variablesToAccessingModuleIndices) {
214 assert(!varMods.second.empty());
215 auto varIt = variablesToMakeGlobal.find(varMods.first);
217 if (varIt == variablesToMakeGlobal.end()) {
218 variablesToMakeGlobal.emplace(varMods.first, allVariablesGlobal || (varMods.second.size() > 1));
220 varIt->second = varIt->second || allVariablesGlobal || (varMods.second.size() > 1);
225 std::vector<storm::jani::Assignment> transientLocationAssignments;
226 for (
auto const& label : program.getLabels()) {
227 bool renameLabel =
manager->hasVariable(label.getName()) || program.hasRewardModel(label.getName());
228 std::string finalLabelName = renameLabel ?
"label_" + label.getName() + suffix : label.getName();
230 STORM_LOG_INFO(
"Label '" << label.getName() <<
"' was renamed to '" << finalLabelName
231 <<
"' in PRISM-to-JANI conversion, as another variable with that name already exists.");
232 labelRenaming[label.getName()] = finalLabelName;
234 auto newExpressionVariable =
manager->declareBooleanVariable(finalLabelName);
237 transientLocationAssignments.emplace_back(
storm::jani::LValue(newTransientVariable), label.getStatePredicateExpression());
240 std::set<storm::expressions::Variable> variables = label.getStatePredicateExpression().getVariables();
241 for (
auto const& variable : variables) {
242 if (formulaToFunctionCallMap.count(variable) > 0) {
243 for (
auto const& funVar : formulaToFunctionCallMap[variable].
getVariables()) {
244 variablesToMakeGlobal[funVar] =
true;
247 variablesToMakeGlobal[variable] =
true;
253 if (program.hasInitialConstruct()) {
254 janiModel.setInitialStatesRestriction(program.getInitialStatesExpression());
256 std::set<storm::expressions::Variable> variables = program.getInitialStatesExpression().getVariables();
257 for (
auto const& variable : variables) {
258 if (formulaToFunctionCallMap.count(variable) > 0) {
259 for (
auto const& funVar : formulaToFunctionCallMap[variable].
getVariables()) {
260 variablesToMakeGlobal[funVar] =
true;
263 variablesToMakeGlobal[variable] =
true;
267 janiModel.setInitialStatesRestriction(
manager->boolean(
true));
272 std::map<uint_fast64_t, std::vector<storm::jani::Assignment>> transientEdgeAssignments;
273 bool hasStateRewards =
false;
274 for (
auto const& rewardModel : program.getRewardModels()) {
275 std::string finalRewardModelName;
276 if (rewardModel.getName().empty()) {
277 finalRewardModelName =
"default_reward_model";
279 if (
manager->hasVariable(rewardModel.getName())) {
281 finalRewardModelName =
"rewardmodel_" + rewardModel.
getName() + suffix;
282 STORM_LOG_INFO(
"Rewardmodel '" << rewardModel.getName() <<
"' was renamed to '" << finalRewardModelName
283 <<
"' in PRISM-to-JANI conversion, as another variable with that name already exists.");
284 rewardModelRenaming[rewardModel.getName()] = finalRewardModelName;
286 finalRewardModelName = rewardModel.getName();
290 auto newExpressionVariable =
manager->declareRationalVariable(finalRewardModelName);
294 if (rewardModel.hasStateRewards()) {
295 hasStateRewards =
true;
297 for (
auto const& stateReward : rewardModel.getStateRewards()) {
299 stateReward.getStatePredicateExpression().
isTrue()
300 ? stateReward.getRewardValueExpression()
303 transientLocationExpression = transientLocationExpression + rewardTerm;
305 transientLocationExpression = rewardTerm;
308 transientLocationAssignments.emplace_back(
storm::jani::LValue(newTransientVariable), transientLocationExpression);
310 std::set<storm::expressions::Variable> variables = transientLocationExpression.
getVariables();
311 for (
auto const& variable : variables) {
312 if (formulaToFunctionCallMap.count(variable) > 0) {
313 for (
auto const& funVar : formulaToFunctionCallMap[variable].
getVariables()) {
314 variablesToMakeGlobal[funVar] =
true;
317 variablesToMakeGlobal[variable] =
true;
322 std::map<uint_fast64_t, storm::expressions::Expression> actionIndexToExpression;
323 for (
auto const& actionReward : rewardModel.getStateActionRewards()) {
325 actionReward.getStatePredicateExpression().
isTrue()
326 ? actionReward.getRewardValueExpression()
328 auto it = actionIndexToExpression.find(janiModel.getActionIndex(actionReward.getActionName()));
329 if (it != actionIndexToExpression.end()) {
330 it->second = it->second + rewardTerm;
332 actionIndexToExpression[janiModel.getActionIndex(actionReward.getActionName())] = rewardTerm;
336 for (
auto const& entry : actionIndexToExpression) {
337 auto it = transientEdgeAssignments.find(entry.first);
338 if (it != transientEdgeAssignments.end()) {
342 transientEdgeAssignments.emplace(entry.first, assignments);
345 std::set<storm::expressions::Variable> variables = entry.second.getVariables();
346 for (
auto const& variable : variables) {
347 variablesToMakeGlobal[variable] =
true;
350 STORM_LOG_THROW(!rewardModel.hasTransitionRewards(), storm::exceptions::NotImplementedException,
351 "Transition reward translation currently not implemented.");
353 STORM_LOG_THROW(transientEdgeAssignments.empty() || transientLocationAssignments.empty() || !program.specifiesSystemComposition(),
354 storm::exceptions::NotImplementedException,
"Cannot translate reward models from PRISM to JANI that specify a custom system composition.");
356 if (janiModel.isDiscreteTimeModel() && hasStateRewards) {
362 std::set<uint64_t> firstModules;
363 bool firstModule =
true;
364 for (
auto const& module : program.getModules()) {
366 std::set<uint_fast64_t> actionIndicesOfModule;
369 for (
auto const& variable : module.getIntegerVariables()) {
370 auto findRes = variablesToMakeGlobal.find(variable.getExpressionVariable());
371 if (findRes != variablesToMakeGlobal.end()) {
372 bool makeVarGlobal = findRes->second;
373 if (variable.hasLowerBoundExpression() || variable.hasUpperBoundExpression()) {
375 variable.getName(), variable.getExpressionVariable(), variable.getInitialValueExpression(),
false, variable.getLowerBoundExpression(),
376 variable.getUpperBoundExpression());
378 makeVarGlobal ? janiModel.addVariable(*newIntegerVariable) : automaton.addVariable(*newIntegerVariable);
379 variableToVariableMap.emplace(variable.getExpressionVariable(), createdVariable);
382 variable.getInitialValueExpression(),
false);
384 makeVarGlobal ? janiModel.addVariable(*newIntegerVariable) : automaton.addVariable(*newIntegerVariable);
385 variableToVariableMap.emplace(variable.getExpressionVariable(), createdVariable);
388 STORM_LOG_INFO(
"Variable " << variable.getName() <<
" is declared but never used.");
391 for (
auto const& variable : module.getBooleanVariables()) {
393 variable.getName(), variable.getExpressionVariable(),
394 variable.hasInitialValue() ? boost::make_optional(variable.getInitialValueExpression()) :
boost::none, false);
395 auto findRes = variablesToMakeGlobal.find(variable.getExpressionVariable());
396 if (findRes != variablesToMakeGlobal.end()) {
397 bool makeVarGlobal = findRes->second;
399 makeVarGlobal ? janiModel.addVariable(*newBooleanVariable) : automaton.addVariable(*newBooleanVariable);
400 variableToVariableMap.emplace(variable.getExpressionVariable(), createdVariable);
402 STORM_LOG_INFO(
"Variable " << variable.getName() <<
" is declared but never used.");
405 for (
auto const& variable : module.getClockVariables()) {
407 variable.getName(), variable.getExpressionVariable(),
408 variable.hasInitialValue() ? boost::make_optional(variable.getInitialValueExpression()) :
boost::none, false);
409 auto findRes = variablesToMakeGlobal.find(variable.getExpressionVariable());
410 if (findRes != variablesToMakeGlobal.end()) {
411 bool makeVarGlobal = findRes->second;
413 makeVarGlobal ? janiModel.addVariable(*newClockVariable) : automaton.addVariable(*newClockVariable);
414 variableToVariableMap.emplace(variable.getExpressionVariable(), createdVariable);
416 STORM_LOG_INFO(
"Variable " << variable.getName() <<
" is declared but never used.");
420 automaton.setInitialStatesRestriction(
manager->boolean(
true));
424 automaton.addInitialLocation(onlyLocationIndex);
426 if (module.hasInvariant()) {
435 for (
auto const& assignment : transientLocationAssignments) {
440 for (
auto const& command : module.getCommands()) {
441 std::shared_ptr<storm::jani::TemplateEdge> templateEdge = std::make_shared<storm::jani::TemplateEdge>(command.getGuardExpression());
442 automaton.registerTemplateEdge(templateEdge);
443 actionIndicesOfModule.insert(janiModel.getActionIndex(command.getActionName()));
445 boost::optional<storm::expressions::Expression> rateExpression;
446 if (program.getModelType() == Program::ModelType::CTMC || program.getModelType() == Program::ModelType::CTMDP ||
447 (program.getModelType() == Program::ModelType::MA && command.isMarkovian())) {
448 for (
auto const& update : command.getUpdates()) {
449 if (rateExpression) {
450 rateExpression = rateExpression.get() + update.getLikelihoodExpression();
452 rateExpression = update.getLikelihoodExpression();
457 std::vector<std::pair<uint64_t, storm::expressions::Expression>> destinationLocationsAndProbabilities;
458 for (
auto const& update : command.getUpdates()) {
459 std::vector<storm::jani::Assignment> assignments;
460 for (
auto const& assignment : update.getAssignments()) {
461 assignments.push_back(
465 if (rateExpression) {
466 destinationLocationsAndProbabilities.emplace_back(onlyLocationIndex, update.getLikelihoodExpression() / rateExpression.get());
468 destinationLocationsAndProbabilities.emplace_back(onlyLocationIndex, update.getLikelihoodExpression());
477 auto transientEdgeAssignmentsToAdd = transientEdgeAssignments.find(janiModel.getActionIndex(command.getActionName()));
478 if (transientEdgeAssignmentsToAdd != transientEdgeAssignments.end()) {
479 for (
auto const& assignment : transientEdgeAssignmentsToAdd->second) {
480 templateEdge->addTransientAssignment(assignment);
486 if (command.getActionName().empty()) {
488 destinationLocationsAndProbabilities);
490 newEdge =
storm::jani::Edge(onlyLocationIndex, janiModel.getActionIndex(command.getActionName()), rateExpression, templateEdge,
491 destinationLocationsAndProbabilities);
495 automaton.addEdge(newEdge);
502 for (
auto actionIndex : actionIndicesOfModule) {
504 if (actionIndex == janiModel.getActionIndex(
"")) {
508 auto it = transientEdgeAssignments.find(actionIndex);
509 if (it != transientEdgeAssignments.end()) {
510 transientEdgeAssignments.erase(it);
516 if (program.getNumberOfFormulas() > 0 && module.isRenamedFromModule()) {
517 auto renamedFormulaToFunctionCallMap = program.getSubstitutionForRenamedModule(module, formulaToFunctionCallMap);
518 automaton.substitute(renamedFormulaToFunctionCallMap,
false);
521 janiModel.addAutomaton(automaton);
526 if (program.specifiesSystemComposition()) {
527 CompositionToJaniVisitor visitor;
528 janiModel.setSystemComposition(visitor.toJani(program.getSystemCompositionConstruct().getSystemComposition(), janiModel));
530 janiModel.setSystemComposition(janiModel.getStandardSystemComposition());
534 if (program.getNumberOfFormulas() > 0) {
536 janiModel.substitute(formulaToFunctionCallMap,
false);
539 janiModel.finalize();