Storm
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
JaniScopeChanger.cpp
Go to the documentation of this file.
2
3#include <boost/any.hpp>
4#include <map>
5#include <set>
6
11
12namespace storm {
13namespace jani {
14
15namespace detail {
17 public:
18 VariableAccessedTraverser(std::set<storm::expressions::Variable> const& varSet) : varSet(varSet) {
19 // Intentionally left empty
20 }
22
23 virtual void traverse(storm::expressions::Expression const& expression, boost::any const& data) override {
24 bool* result = boost::any_cast<bool*>(data);
25 if (*result) {
26 return;
27 }
28 *result = expression.containsVariable(varSet);
29 if (*result) {
30 STORM_LOG_TRACE("The expression " << expression << " 'contains' a variable in the variable set.");
31 }
32 }
33
34 virtual void traverse(LValue const& lValue, boost::any const& data) override {
35 bool* result = boost::any_cast<bool*>(data);
36 if (*result) {
37 return;
38 }
39 *result = varSet.count(lValue.getVariable().getExpressionVariable()) > 0;
40 }
41
42 private:
43 std::set<storm::expressions::Variable> varSet;
44};
45
46std::set<uint64_t> getAutomataAccessingVariable(storm::expressions::Variable const& variable, Model const& model) {
47 std::set<uint64_t> res;
48 for (uint64_t i = 0; i < model.getNumberOfAutomata(); ++i) {
49 if (model.getAutomaton(i).getVariables().hasVariable(variable)) {
50 STORM_LOG_TRACE("The automaton " << model.getAutomaton(i).getName() << " 'has' the variable " << variable.getName() << ".");
51 res.insert(i);
52 } else {
53 VariableAccessedTraverser vat({variable});
54 bool varAccessed = false;
55 vat.traverse(model.getAutomaton(i), &varAccessed);
56 if (varAccessed) {
57 res.insert(i);
58 STORM_LOG_TRACE("The automaton " << model.getAutomaton(i).getName() << " 'accesses' the variable " << variable.getName() << ".");
59 }
60 }
61 }
62 return res;
63}
64} // namespace detail
65
67 uint64_t automatonIndex = 0;
68 for (; automatonIndex < model.getNumberOfAutomata(); ++automatonIndex) {
69 if (model.getAutomaton(automatonIndex).getVariables().hasVariable(variable)) {
70 break;
71 }
72 }
73 std::map<Variable const*, std::reference_wrapper<Variable const>> remapping;
74 auto oldJaniVar = model.getAutomaton(automatonIndex).getVariables().eraseVariable(variable);
75 remapping.emplace(oldJaniVar.get(), model.addVariable(*oldJaniVar));
76
77 // Only one automaton accesses this variable
78 model.getAutomaton(automatonIndex).changeAssignmentVariables(remapping);
79}
80
81void JaniScopeChanger::makeVariableLocal(storm::expressions::Variable const& variable, Model& model, uint64_t automatonIndex) const {
82 std::map<Variable const*, std::reference_wrapper<Variable const>> remapping;
83 auto oldJaniVar = model.getGlobalVariables().eraseVariable(variable);
84 remapping.emplace(oldJaniVar.get(), model.getAutomaton(automatonIndex).addVariable(*oldJaniVar));
85 // Only one automaton accesses this variable (otherwise this call would be illegal)
86 model.getAutomaton(automatonIndex).changeAssignmentVariables(remapping);
87}
88
90 STORM_LOG_TRACE("Can the variable " << variable.getName() << " be made global?");
91
92 if (model.hasGlobalVariable(variable.getName())) {
93 return false;
94 }
95 // Check whether there are multiple local variables with this name
96 bool foundVar = false;
97 for (auto const& aut : model.getAutomata()) {
98 if (aut.hasVariable(variable.getName())) {
99 if (foundVar) {
100 return false;
101 }
102 foundVar = true;
103 }
104 }
105 return foundVar;
106}
107
108std::pair<bool, uint64_t> JaniScopeChanger::canMakeVariableLocal(storm::expressions::Variable const& variable, Model const& model,
109 storm::OptionalRef<std::vector<Property> const> properties,
110 std::optional<uint64_t> automatonIndex) const {
111 STORM_LOG_TRACE("Can the variable " << variable.getName() << " be made local?");
112
113 uint64_t index = model.getNumberOfAutomata();
114
115 if (!model.getGlobalVariables().hasVariable(variable)) {
116 return {false, index};
117 }
118
119 auto accessingAutomata = detail::getAutomataAccessingVariable(variable, model);
120 if (accessingAutomata.size() > 1 || (automatonIndex.has_value() && accessingAutomata.count(automatonIndex.value()) == 0)) {
121 STORM_LOG_TRACE(".. no!, multiple automata access the variable, e.g. automata " << model.getAutomaton(*accessingAutomata.begin()).getName() << " and "
122 << model.getAutomaton(*accessingAutomata.rbegin()).getName());
123 return {false, index};
124 }
125 if (model.getInitialStatesRestriction().containsVariable({variable})) {
126 STORM_LOG_TRACE(".. no!, initial states restriction contains variable");
127 return {false, index};
128 }
129 for (auto const& rewExp : model.getNonTrivialRewardExpressions()) {
130 if (rewExp.second.containsVariable({variable})) {
131 STORM_LOG_TRACE(".. no!, non trivial reward expression ");
132 return {false, index};
133 }
134 }
135 for (auto const& funDef : model.getGlobalFunctionDefinitions()) {
136 if (funDef.second.getFunctionBody().containsVariable({variable})) {
137 STORM_LOG_TRACE(".. no!, function definition: ");
138 return {false, index};
139 }
140 }
141 if (properties) {
142 for (auto const& p : *properties) {
143 if (p.getUsedVariablesAndConstants().count(variable) > 0) {
144 STORM_LOG_TRACE(".. no!, used variables definition: ");
145 return {false, index};
146 }
147 if (p.getUsedLabels().count(variable.getName()) > 0) {
148 STORM_LOG_TRACE(".. no!, used labels definition: ");
149 return {false, index};
150 }
151 }
152 }
153
154 if (accessingAutomata.empty()) {
155 index = automatonIndex.has_value() ? automatonIndex.value() : 0;
156 } else {
157 index = *accessingAutomata.begin();
158 assert(!automatonIndex.has_value() || index == automatonIndex.value());
159 }
160 STORM_LOG_TRACE(".. Yes, made local in automaton with index " << index);
161 return {true, index};
162}
163
165 for (uint64_t i = 0; i < model.getNumberOfAutomata(); ++i) {
166 // Make sure to not erase from a set while iterating over it...
167 std::set<storm::expressions::Variable> varsToMakeGlobal;
168 for (auto const& v : model.getAutomaton(i).getVariables()) {
169 if (canMakeVariableGlobal(v.getExpressionVariable(), model)) {
170 varsToMakeGlobal.insert(v.getExpressionVariable());
171 }
172 }
173 for (auto const& v : varsToMakeGlobal) {
174 makeVariableGlobal(v, model);
175 }
176 }
177}
178
179void JaniScopeChanger::makeVariablesLocal(Model& model, storm::OptionalRef<std::vector<Property> const> properties) const {
180 // Make sure to not erase from a set while iterating over it...
181 std::map<storm::expressions::Variable, uint64_t> varsToMakeLocal;
182 for (auto const& v : model.getGlobalVariables()) {
183 auto makeLocal = canMakeVariableLocal(v.getExpressionVariable(), model, properties);
184 if (makeLocal.first) {
185 varsToMakeLocal[v.getExpressionVariable()] = makeLocal.second;
186 }
187 }
188 for (auto const& v : varsToMakeLocal) {
189 makeVariableLocal(v.first, model, v.second);
190 }
191}
192
193} // namespace jani
194
195} // namespace storm
Helper class that optionally holds a reference to an object of type T.
Definition OptionalRef.h:48
bool containsVariable(std::set< storm::expressions::Variable > const &variables) const
Retrieves whether the expression contains any of the given variables.
std::string const & getName() const
Retrieves the name of the variable.
Definition Variable.cpp:46
VariableSet & getVariables()
Retrieves the variables of this automaton.
Definition Automaton.cpp:59
Variable const & addVariable(Variable const &variable)
Adds the given variable to this automaton.
Definition Automaton.cpp:51
void changeAssignmentVariables(std::map< Variable const *, std::reference_wrapper< Variable const > > const &remapping)
Changes all variables in assignments based on the given mapping.
std::string const & getName() const
Retrieves the name of the automaton.
Definition Automaton.cpp:47
virtual void traverse(Model const &model, boost::any const &data)
void makeVariablesGlobal(Model &model) const
Moves as many variables to the global scope as possible.
void makeVariablesLocal(Model &model, storm::OptionalRef< std::vector< Property > const > properties=storm::NullRef) const
Moves as many variables to a local scope as possible.
void makeVariableGlobal(storm::expressions::Variable const &variable, Model &model) const
Moves the given variable to the global scope.
bool canMakeVariableGlobal(storm::expressions::Variable const &variable, Model const &model) const
Checks whether this variable can be made global without introducing name clashes.
void makeVariableLocal(storm::expressions::Variable const &variable, Model &model, uint64_t automatonIndex) const
Moves the given variable into the local scope of the automaton with the given index.
std::pair< bool, uint64_t > canMakeVariableLocal(storm::expressions::Variable const &variable, Model const &model, storm::OptionalRef< std::vector< Property > const > properties=storm::NullRef, std::optional< uint64_t > automatonIndex=std::nullopt) const
Checks whether this variable can be made local without introducing out-of-scope accesses.
storm::jani::Variable const & getVariable() const
To check if the array is fully accessed, so result will be of the most inner child Type....
Definition LValue.cpp:28
VariableSet & getGlobalVariables()
Retrieves the variables of this automaton.
Definition Model.cpp:721
std::unordered_map< std::string, storm::expressions::Expression > const & getNonTrivialRewardExpressions() const
Retrieves all available non-trivial reward model names and expressions of the model.
Definition Model.cpp:855
storm::expressions::Expression const & getInitialStatesRestriction() const
Gets the expression restricting the legal initial values of the global variables.
Definition Model.cpp:1288
std::vector< Automaton > & getAutomata()
Retrieves the automata of the model.
Definition Model.cpp:872
Variable const & addVariable(Variable const &variable)
Adds the given variable to this model.
Definition Model.cpp:717
std::size_t getNumberOfAutomata() const
Retrieves the number of automata in this model.
Definition Model.cpp:914
bool hasGlobalVariable(std::string const &name) const
Retrieves whether this model has a global variable with the given name.
Definition Model.cpp:757
Automaton & getAutomaton(std::string const &name)
Retrieves the automaton with the given name.
Definition Model.cpp:888
std::unordered_map< std::string, FunctionDefinition > const & getGlobalFunctionDefinitions() const
Retrieves all global function definitions.
Definition Model.cpp:781
storm::expressions::Variable const & getExpressionVariable() const
Retrieves the associated expression variable.
Definition Variable.cpp:26
bool hasVariable(std::string const &name) const
Retrieves whether this variable set contains a variable with the given name.
std::shared_ptr< Variable > eraseVariable(storm::expressions::Variable const &variable)
Erases the given variable from this set.
virtual void traverse(LValue const &lValue, boost::any const &data) override
VariableAccessedTraverser(std::set< storm::expressions::Variable > const &varSet)
virtual void traverse(storm::expressions::Expression const &expression, boost::any const &data) override
#define STORM_LOG_TRACE(message)
Definition logging.h:17
std::set< uint64_t > getAutomataAccessingVariable(storm::expressions::Variable const &variable, Model const &model)
LabParser.cpp.
Definition cli.cpp:18