Storm
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
ToJaniConverter.cpp
Go to the documentation of this file.
2
4
13
16
17namespace storm {
18namespace prism {
19
21 std::set<storm::expressions::Variable> const& givenVariablesToMakeGlobal, std::string suffix) {
22 labelRenaming.clear();
23 rewardModelRenaming.clear();
24 formulaToFunctionCallMap.clear();
25
26 std::shared_ptr<storm::expressions::ExpressionManager> manager = program.getManager().getSharedPointer();
27
28 // Start by creating an empty JANI model.
29 storm::jani::ModelType modelType;
30 switch (program.getModelType()) {
33 break;
36 break;
39 break;
42 break;
45 break;
48 break;
49 default:
51 }
52 storm::jani::Model janiModel("jani_from_prism", modelType, 1, manager);
53
55
56 // Add all constants of the PRISM program to the JANI model.
57 for (auto const& constant : program.getConstants()) {
58 janiModel.addConstant(storm::jani::Constant(constant.getName(), constant.getExpressionVariable(),
59 constant.isDefined() ? constant.getExpression() : storm::expressions::Expression()));
60 }
61
62 // Maintain a mapping of each variable to a flag that is true if the variable will be made global.
63 std::map<storm::expressions::Variable, bool> variablesToMakeGlobal;
64 for (auto const& var : givenVariablesToMakeGlobal) {
65 variablesToMakeGlobal.emplace(var, true);
66 }
67
68 // Get the set of variables that appeare in a renaimng of a renamed module
69 if (program.getNumberOfFormulas() > 0) {
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));
76 }
77 if (manager->hasVariable(renaimingPair.second)) {
78 renamedVariables.insert(manager->getVariable(renaimingPair.second));
79 }
80 }
81 }
82 }
83
84 // Add all formulas of the PRISM program to the JANI model.
85 // Also collect a substitution of formula placeholder variables to function call expressions.
86 for (auto const& formula : program.getFormulas()) {
87 // First find 1. all variables that occurr in the formula definition (including the ones used in called formulae) and 2. the called formulae
88 // Variables that occurr in a renaming need to become a parameter of the function.
89 // Others need to be made global.
90 std::set<storm::expressions::Variable> variablesInFormula, placeholdersInFormula;
91 for (auto const& var : formula.getExpression().getVariables()) {
92 // Check whether var is an actual variable/constant or another formula
93 auto functionCallIt = formulaToFunctionCallMap.find(var);
94 if (functionCallIt == formulaToFunctionCallMap.end()) {
95 if (renamedVariables.count(var) > 0) {
96 variablesInFormula.insert(var);
97 } else {
98 variablesToMakeGlobal.emplace(var, true);
99 }
100 } else {
101 storm::expressions::FunctionCallExpression const& innerFunctionCall =
102 dynamic_cast<storm::expressions::FunctionCallExpression const&>(functionCallIt->second.getBaseExpression());
103 for (auto const& innerFunctionArg : innerFunctionCall.getArguments()) {
104 auto const& argVar = innerFunctionArg->asVariableExpression().getVariable();
105 if (renamedVariables.count(argVar) > 0) {
106 variablesInFormula.insert(argVar);
107 } else {
108 variablesToMakeGlobal.emplace(argVar, true);
109 }
110 }
111 placeholdersInFormula.insert(var);
112 }
113 }
114
115 // Add a function argument and parameter for each occurring variable and prepare the substitution for the function body
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();
123 }
124 for (auto const& formulaVar : placeholdersInFormula) {
125 functionBodySubstitution[formulaVar] =
126 storm::jani::substituteJaniExpression(formulaToFunctionCallMap[formulaVar], functionBodySubstitution, false);
127 }
128
129 storm::jani::FunctionDefinition funDef(formula.getName(), formula.getType(), functionParameters,
130 storm::jani::substituteJaniExpression(formula.getExpression(), functionBodySubstitution, false));
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();
135 }
136 }
137
138 // Maintain a mapping from expression variables to JANI variables so we can fill in the correct objects when
139 // creating assignments.
140 std::map<storm::expressions::Variable, std::reference_wrapper<storm::jani::Variable const>> variableToVariableMap;
141
142 // Add all global variables of the PRISM program to the JANI model.
143 for (auto const& variable : program.getGlobalIntegerVariables()) {
144 if (variable.hasLowerBoundExpression() || variable.hasUpperBoundExpression()) {
145 storm::jani::Variable const& createdVariable = janiModel.addVariable(
146 *storm::jani::Variable::makeBoundedIntegerVariable(variable.getName(), variable.getExpressionVariable(), variable.getInitialValueExpression(),
147 false, variable.getLowerBoundExpression(), variable.getUpperBoundExpression()));
148 variableToVariableMap.emplace(variable.getExpressionVariable(), createdVariable);
149 } else {
150 storm::jani::Variable const& createdVariable = janiModel.addVariable(
151 *storm::jani::Variable::makeIntegerVariable(variable.getName(), variable.getExpressionVariable(), variable.getInitialValueExpression(), false));
152 variableToVariableMap.emplace(variable.getExpressionVariable(), createdVariable);
153 }
154 }
155 for (auto const& variable : program.getGlobalBooleanVariables()) {
156 storm::jani::Variable const& createdVariable = janiModel.addVariable(
157 *storm::jani::Variable::makeBooleanVariable(variable.getName(), variable.getExpressionVariable(), variable.getInitialValueExpression(), false));
158 variableToVariableMap.emplace(variable.getExpressionVariable(), createdVariable);
159 }
160
161 // Add all actions of the PRISM program to the JANI model.
162 for (auto const& action : program.getActions()) {
163 // Ignore the empty action as every JANI program has predefined tau action.
164 if (!action.empty()) {
165 janiModel.addAction(storm::jani::Action(action));
166 }
167 }
168
169 // Because of the rules of JANI, we have to make all variables of modules global that are read by other modules.
170 // Create a mapping from variables to the indices of module indices that write/read the variable.
171 std::map<storm::expressions::Variable, std::set<uint_fast64_t>> variablesToAccessingModuleIndices;
172 for (uint_fast64_t index = 0; index < program.getNumberOfModules(); ++index) {
173 storm::prism::Module const& module = program.getModule(index);
174
175 // Gather all variables occurring in this module
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());
184 }
185 }
186 }
187
188 // insert the accessing module index for each accessed variable
189 std::map<storm::expressions::Variable, storm::expressions::Expression> renamedFormulaToFunctionCallMap;
190 if (module.isRenamedFromModule()) {
191 renamedFormulaToFunctionCallMap = program.getSubstitutionForRenamedModule(module, formulaToFunctionCallMap);
192 }
193
194 for (auto const& variable : variables) {
195 // Check whether the variable actually is a formula
196 if (formulaToFunctionCallMap.count(variable) > 0) {
197 std::set<storm::expressions::Variable> variablesInFunctionCall;
198 if (module.isRenamedFromModule()) {
199 variablesInFunctionCall = renamedFormulaToFunctionCallMap[variable].getVariables();
200 } else {
201 variablesInFunctionCall = formulaToFunctionCallMap[variable].getVariables();
202 }
203 for (auto const& funVar : variablesInFunctionCall) {
204 variablesToAccessingModuleIndices[funVar].insert(index);
205 }
206 } else {
207 variablesToAccessingModuleIndices[variable].insert(index);
208 }
209 }
210 }
211
212 // Create a mapping from variables to a flag indicating whether it should be made global
213 for (auto const& varMods : variablesToAccessingModuleIndices) {
214 assert(!varMods.second.empty());
215 auto varIt = variablesToMakeGlobal.find(varMods.first);
216 // If there is exactly one module reading and writing the variable, we can make the variable local to this module.
217 if (varIt == variablesToMakeGlobal.end()) {
218 variablesToMakeGlobal.emplace(varMods.first, allVariablesGlobal || (varMods.second.size() > 1));
219 } else {
220 varIt->second = varIt->second || allVariablesGlobal || (varMods.second.size() > 1);
221 }
222 }
223
224 // Go through the labels and construct assignments to transient variables that are added to the locations.
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();
229 if (renameLabel) {
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;
233 }
234 auto newExpressionVariable = manager->declareBooleanVariable(finalLabelName);
235 storm::jani::Variable const& newTransientVariable = janiModel.addVariable(
236 *storm::jani::Variable::makeBooleanVariable(newExpressionVariable.getName(), newExpressionVariable, manager->boolean(false), true));
237 transientLocationAssignments.emplace_back(storm::jani::LValue(newTransientVariable), label.getStatePredicateExpression());
238
239 // Variables that are accessed in the label predicate expression should be made global.
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;
245 }
246 } else {
247 variablesToMakeGlobal[variable] = true;
248 }
249 }
250 }
251
252 // Create an initial state restriction if there was an initial construct in the program.
253 if (program.hasInitialConstruct()) {
254 janiModel.setInitialStatesRestriction(program.getInitialStatesExpression());
255 // Variables in the initial state expression should be made global
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;
261 }
262 } else {
263 variablesToMakeGlobal[variable] = true;
264 }
265 }
266 } else {
267 janiModel.setInitialStatesRestriction(manager->boolean(true));
268 }
269
270 // Go through the reward models and construct assignments to the transient variables that are to be added to
271 // edges and transient assignments that are added to the locations.
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";
278 } else {
279 if (manager->hasVariable(rewardModel.getName())) {
280 // Rename
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;
285 } else {
286 finalRewardModelName = rewardModel.getName();
287 }
288 }
289
290 auto newExpressionVariable = manager->declareRationalVariable(finalRewardModelName);
291 storm::jani::Variable const& newTransientVariable = janiModel.addVariable(
292 *storm::jani::Variable::makeRealVariable(newExpressionVariable.getName(), newExpressionVariable, manager->rational(0.0), true));
293
294 if (rewardModel.hasStateRewards()) {
295 hasStateRewards = true;
296 storm::expressions::Expression transientLocationExpression;
297 for (auto const& stateReward : rewardModel.getStateRewards()) {
299 stateReward.getStatePredicateExpression().isTrue()
300 ? stateReward.getRewardValueExpression()
301 : storm::expressions::ite(stateReward.getStatePredicateExpression(), stateReward.getRewardValueExpression(), manager->rational(0));
302 if (transientLocationExpression.isInitialized()) {
303 transientLocationExpression = transientLocationExpression + rewardTerm;
304 } else {
305 transientLocationExpression = rewardTerm;
306 }
307 }
308 transientLocationAssignments.emplace_back(storm::jani::LValue(newTransientVariable), transientLocationExpression);
309 // Variables that are accessed in a reward term should be made global.
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;
315 }
316 } else {
317 variablesToMakeGlobal[variable] = true;
318 }
319 }
320 }
321
322 std::map<uint_fast64_t, storm::expressions::Expression> actionIndexToExpression;
323 for (auto const& actionReward : rewardModel.getStateActionRewards()) {
325 actionReward.getStatePredicateExpression().isTrue()
326 ? actionReward.getRewardValueExpression()
327 : storm::expressions::ite(actionReward.getStatePredicateExpression(), actionReward.getRewardValueExpression(), manager->rational(0));
328 auto it = actionIndexToExpression.find(janiModel.getActionIndex(actionReward.getActionName()));
329 if (it != actionIndexToExpression.end()) {
330 it->second = it->second + rewardTerm;
331 } else {
332 actionIndexToExpression[janiModel.getActionIndex(actionReward.getActionName())] = rewardTerm;
333 }
334 }
335
336 for (auto const& entry : actionIndexToExpression) {
337 auto it = transientEdgeAssignments.find(entry.first);
338 if (it != transientEdgeAssignments.end()) {
339 it->second.push_back(storm::jani::Assignment(storm::jani::LValue(newTransientVariable), entry.second));
340 } else {
341 std::vector<storm::jani::Assignment> assignments = {storm::jani::Assignment(storm::jani::LValue(newTransientVariable), entry.second)};
342 transientEdgeAssignments.emplace(entry.first, assignments);
343 }
344 // Variables that are accessed in a reward term should be made global.
345 std::set<storm::expressions::Variable> variables = entry.second.getVariables();
346 for (auto const& variable : variables) {
347 variablesToMakeGlobal[variable] = true;
348 }
349 }
350 STORM_LOG_THROW(!rewardModel.hasTransitionRewards(), storm::exceptions::NotImplementedException,
351 "Transition reward translation currently not implemented.");
352 }
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.");
355 // if there are state rewards and the model is a discrete time model, we add the corresponding model feature
356 if (janiModel.isDiscreteTimeModel() && hasStateRewards) {
357 janiModel.getModelFeatures().add(storm::jani::ModelFeature::StateExitRewards);
358 }
359
360 // Now create the separate JANI automata from the modules of the PRISM program. While doing so, we use the
361 // previously built mapping to make variables global that are read by more than one module.
362 std::set<uint64_t> firstModules;
363 bool firstModule = true;
364 for (auto const& module : program.getModules()) {
365 // Keep track of the action indices contained in this module.
366 std::set<uint_fast64_t> actionIndicesOfModule;
367
368 storm::jani::Automaton automaton(module.getName(), manager->declareIntegerVariable("_loc_prism2jani_" + module.getName() + "_" + suffix));
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());
377 storm::jani::Variable const& createdVariable =
378 makeVarGlobal ? janiModel.addVariable(*newIntegerVariable) : automaton.addVariable(*newIntegerVariable);
379 variableToVariableMap.emplace(variable.getExpressionVariable(), createdVariable);
380 } else {
381 auto newIntegerVariable = storm::jani::Variable::makeIntegerVariable(variable.getName(), variable.getExpressionVariable(),
382 variable.getInitialValueExpression(), false);
383 storm::jani::Variable const& createdVariable =
384 makeVarGlobal ? janiModel.addVariable(*newIntegerVariable) : automaton.addVariable(*newIntegerVariable);
385 variableToVariableMap.emplace(variable.getExpressionVariable(), createdVariable);
386 }
387 } else {
388 STORM_LOG_INFO("Variable " << variable.getName() << " is declared but never used.");
389 }
390 }
391 for (auto const& variable : module.getBooleanVariables()) {
392 auto newBooleanVariable = storm::jani::Variable::makeBooleanVariable(
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;
398 storm::jani::Variable const& createdVariable =
399 makeVarGlobal ? janiModel.addVariable(*newBooleanVariable) : automaton.addVariable(*newBooleanVariable);
400 variableToVariableMap.emplace(variable.getExpressionVariable(), createdVariable);
401 } else {
402 STORM_LOG_INFO("Variable " << variable.getName() << " is declared but never used.");
403 }
404 }
405 for (auto const& variable : module.getClockVariables()) {
406 auto newClockVariable = storm::jani::Variable::makeClockVariable(
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;
412 storm::jani::Variable const& createdVariable =
413 makeVarGlobal ? janiModel.addVariable(*newClockVariable) : automaton.addVariable(*newClockVariable);
414 variableToVariableMap.emplace(variable.getExpressionVariable(), createdVariable);
415 } else {
416 STORM_LOG_INFO("Variable " << variable.getName() << " is declared but never used.");
417 }
418 }
419
420 automaton.setInitialStatesRestriction(manager->boolean(true));
421
422 // Create a single location that will have all the edges.
423 uint64_t onlyLocationIndex = automaton.addLocation(storm::jani::Location("l"));
424 automaton.addInitialLocation(onlyLocationIndex);
425
426 if (module.hasInvariant()) {
427 storm::jani::Location& onlyLocation = automaton.getLocation(onlyLocationIndex);
428 onlyLocation.setTimeProgressInvariant(module.getInvariant());
429 }
430
431 // If we are translating the first module that has the action, we need to add the transient assignments to the location.
432 // However, in standard compliant JANI, there are no state rewards
433 if (firstModule) {
434 storm::jani::Location& onlyLocation = automaton.getLocation(onlyLocationIndex);
435 for (auto const& assignment : transientLocationAssignments) {
436 onlyLocation.addTransientAssignment(assignment);
437 }
438 }
439
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()));
444
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();
451 } else {
452 rateExpression = update.getLikelihoodExpression();
453 }
454 }
455 }
456
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(
462 storm::jani::Assignment(storm::jani::LValue(variableToVariableMap.at(assignment.getVariable()).get()), assignment.getExpression()));
463 }
464
465 if (rateExpression) {
466 destinationLocationsAndProbabilities.emplace_back(onlyLocationIndex, update.getLikelihoodExpression() / rateExpression.get());
467 } else {
468 destinationLocationsAndProbabilities.emplace_back(onlyLocationIndex, update.getLikelihoodExpression());
469 }
470
471 templateEdge->addDestination(storm::jani::TemplateEdgeDestination(assignments));
472 }
473
474 // Then add the transient assignments for the rewards. Note that we may do this only for the first
475 // module that has this action, so we remove the assignments from the global list of assignments
476 // to add after adding them to the created edge.
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);
481 }
482 }
483
484 // Create the edge object.
485 storm::jani::Edge newEdge;
486 if (command.getActionName().empty()) {
487 newEdge = storm::jani::Edge(onlyLocationIndex, storm::jani::Model::SILENT_ACTION_INDEX, rateExpression, templateEdge,
488 destinationLocationsAndProbabilities);
489 } else {
490 newEdge = storm::jani::Edge(onlyLocationIndex, janiModel.getActionIndex(command.getActionName()), rateExpression, templateEdge,
491 destinationLocationsAndProbabilities);
492 }
493
494 // Finally add the constructed edge.
495 automaton.addEdge(newEdge);
496 }
497
498 // Now remove for all actions of this module the corresponding transient assignments, because we must
499 // not deal out this reward multiple times.
500 // NOTE: This only works for the standard composition and not for any custom compositions. This case
501 // must be checked for earlier.
502 for (auto actionIndex : actionIndicesOfModule) {
503 // Do not delete rewards dealt out on non-synchronizing edges.
504 if (actionIndex == janiModel.getActionIndex("")) {
505 continue;
506 }
507
508 auto it = transientEdgeAssignments.find(actionIndex);
509 if (it != transientEdgeAssignments.end()) {
510 transientEdgeAssignments.erase(it);
511 }
512 }
513
514 // if there are formulas and if the current module was renamed, we need to apply the renaming to the resulting function calls before replacing the
515 // formula placeholders. Note that the formula placeholders of non-renamed modules are replaced later.
516 if (program.getNumberOfFormulas() > 0 && module.isRenamedFromModule()) {
517 auto renamedFormulaToFunctionCallMap = program.getSubstitutionForRenamedModule(module, formulaToFunctionCallMap);
518 automaton.substitute(renamedFormulaToFunctionCallMap, false);
519 }
520
521 janiModel.addAutomaton(automaton);
522 firstModule = false;
523 }
524
525 // Set the standard system composition. This is possible, because we reject non-standard compositions anyway.
526 if (program.specifiesSystemComposition()) {
527 CompositionToJaniVisitor visitor;
528 janiModel.setSystemComposition(visitor.toJani(program.getSystemCompositionConstruct().getSystemComposition(), janiModel));
529 } else {
530 janiModel.setSystemComposition(janiModel.getStandardSystemComposition());
531 }
532
533 // if there are formulas, replace the remaining placeholder variables by actual function calls in all expressions
534 if (program.getNumberOfFormulas() > 0) {
535 janiModel.getModelFeatures().add(storm::jani::ModelFeature::Functions);
536 janiModel.substitute(formulaToFunctionCallMap, false);
537 }
538
539 janiModel.finalize();
540
541 return janiModel;
542}
543
544bool ToJaniConverter::labelsWereRenamed() const {
545 return !labelRenaming.empty();
546}
547
548bool ToJaniConverter::rewardModelsWereRenamed() const {
549 return !rewardModelRenaming.empty();
550}
551
552std::map<std::string, std::string> const& ToJaniConverter::getLabelRenaming() const {
553 return labelRenaming;
554}
555
556std::map<std::string, std::string> const& ToJaniConverter::getRewardModelRenaming() const {
557 return rewardModelRenaming;
558}
559
560storm::jani::Property ToJaniConverter::applyRenaming(storm::jani::Property const& property) const {
562 bool initialized = false;
563
564 if (rewardModelsWereRenamed()) {
565 result = property.substituteRewardModelNames(getRewardModelRenaming());
566 initialized = true;
567 }
568 if (labelsWereRenamed()) {
569 storm::jani::Property const& currProperty = initialized ? result : property;
570 result = currProperty.substituteLabels(getLabelRenaming());
571 initialized = true;
572 }
573 if (!formulaToFunctionCallMap.empty()) {
574 storm::jani::Property const& currProperty = initialized ? result : property;
575 result = currProperty.substitute(formulaToFunctionCallMap);
576 initialized = true;
577 }
578 if (!initialized) {
579 result = property.clone();
580 }
581 return result;
582}
583
584std::vector<storm::jani::Property> ToJaniConverter::applyRenaming(std::vector<storm::jani::Property> const& properties) const {
585 std::vector<storm::jani::Property> result;
586 for (auto const& p : properties) {
587 result.push_back(applyRenaming(p));
588 }
589 return result;
590}
591} // namespace prism
592} // namespace storm
VariableExpression const & asVariableExpression() const
std::set< storm::expressions::Variable > getVariables() const
Retrieves the set of all variables that appear in the expression.
bool isTrue() const
Checks if the expression is equal to the boolean literal true.
bool isInitialized() const
Checks whether the object encapsulates a base-expression.
std::shared_ptr< ExpressionManager > getSharedPointer()
Retrieves a shared pointer to the expression manager.
Represents an array with a given list of elements.
Variable const & getVariable() const
Retrieves the variable associated with this expression.
Jani Location:
Definition Location.h:15
void addTransientAssignment(storm::jani::Assignment const &assignment)
Adds the given transient assignment to this location.
Definition Location.cpp:31
void setTimeProgressInvariant(storm::expressions::Expression const &expression)
Sets the time progress invariant of this location.
Definition Location.cpp:44
ModelFeatures & add(ModelFeature const &modelFeature)
static const uint64_t SILENT_ACTION_INDEX
The index of the silent action.
Definition Model.h:642
void addConstant(Constant const &constant)
Adds the given constant to the model.
Definition Model.cpp:654
ModelFeatures const & getModelFeatures() const
Retrieves the enabled model features.
Definition Model.cpp:129
Property substitute(std::map< storm::expressions::Variable, storm::expressions::Expression > const &substitution) const
Definition Property.cpp:54
Property substituteRewardModelNames(std::map< std::string, std::string > const &rewardModelNameSubstitution) const
Definition Property.cpp:76
Property substituteLabels(std::map< std::string, std::string > const &labelSubstitution) const
Definition Property.cpp:72
Property clone() const
Definition Property.cpp:84
static std::shared_ptr< Variable > makeIntegerVariable(std::string const &name, storm::expressions::Variable const &variable, boost::optional< storm::expressions::Expression > const &initValue, bool transient)
Definition Variable.cpp:115
static std::shared_ptr< Variable > makeRealVariable(std::string const &name, storm::expressions::Variable const &variable, boost::optional< storm::expressions::Expression > const &initValue, bool transient)
Definition Variable.cpp:120
static std::shared_ptr< Variable > makeBooleanVariable(std::string const &name, storm::expressions::Variable const &variable, boost::optional< storm::expressions::Expression > const &initValue, bool transient)
Definition Variable.cpp:110
static std::shared_ptr< Variable > makeBoundedIntegerVariable(std::string const &name, storm::expressions::Variable const &variable, boost::optional< storm::expressions::Expression > const &initValue, bool transient, boost::optional< storm::expressions::Expression > const &lowerBound, boost::optional< storm::expressions::Expression > const &upperBound)
Definition Variable.cpp:136
std::string const & getName() const
Retrieves the name of the variable.
Definition Variable.cpp:34
static std::shared_ptr< Variable > makeClockVariable(std::string const &name, storm::expressions::Variable const &variable, boost::optional< storm::expressions::Expression > const &initValue, bool transient)
Definition Variable.cpp:155
ModelType getModelType() const
Retrieves the model type of the model.
Definition Program.cpp:247
std::vector< Module > const & getModules() const
Retrieves all modules of the program.
Definition Program.cpp:629
std::vector< Constant > const & getConstants() const
Retrieves all constants defined in the program.
Definition Program.cpp:402
storm::expressions::ExpressionManager & getManager() const
Retrieves the manager responsible for the expressions of this program.
Definition Program.cpp:2359
std::size_t getNumberOfFormulas() const
Retrieves the number of formulas in the program.
Definition Program.cpp:607
storm::jani::Model convert(storm::prism::Program const &program, bool allVariablesGlobal=true, std::set< storm::expressions::Variable > const &variablesToMakeGlobal={}, std::string suffix="")
storm::expressions::Expression getExpression() const
Retrieves the expression associated with this variable.
Definition Variable.cpp:44
#define STORM_LOG_INFO(message)
Definition logging.h:29
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
Expression ite(Expression const &condition, Expression const &thenExpression, Expression const &elseExpression)
storm::expressions::Expression substituteJaniExpression(storm::expressions::Expression const &expression, std::map< storm::expressions::Variable, storm::expressions::Expression > const &identifierToExpressionMap, bool const substituteTranscendentalNumbers)
SettingsManager const & manager()
Retrieves the settings manager.
std::set< storm::RationalFunctionVariable > getVariables(std::vector< storm::RationalFunction > const &vector)
LabParser.cpp.
Definition cli.cpp:18