mCRL2
Loading...
Searching...
No Matches
preprocess_state_formula.h
Go to the documentation of this file.
1// Author(s): Wieger Wesselink
2// Copyright: see the accompanying file COPYING or copy at
3// https://github.com/mCRL2org/mCRL2/blob/master/COPYING
4//
5// Distributed under the Boost Software License, Version 1.0.
6// (See accompanying file LICENSE_1_0.txt or copy at
7// http://www.boost.org/LICENSE_1_0.txt)
8//
11
12#ifndef MCRL2_MODAL_FORMULA_PREPROCESS_STATE_FORMULA_H
13#define MCRL2_MODAL_FORMULA_PREPROCESS_STATE_FORMULA_H
14
22
23namespace mcrl2
24{
25
26namespace state_formulas
27{
28
29namespace detail
30{
31
32struct count_modal_operator_nesting_traverser: public state_formula_traverser<count_modal_operator_nesting_traverser>
33{
35 using super::enter;
36 using super::leave;
37 using super::apply;
38
39 std::size_t result;
40 std::vector<std::size_t> nesting_depth;
41
43 : result(0)
44 {
46 }
47
49 {
50 nesting_depth.push_back(0);
51 }
52
54 {
55 nesting_depth.pop_back();
56 }
57
59 {
60 nesting_depth.back()++;
61 if (nesting_depth.back() > result)
62 {
63 result = nesting_depth.back();
64 }
65 }
66
68 {
69 nesting_depth.back()--;
70 }
71
72 void enter(const must&)
73 {
75 }
76
77 void leave(const must&)
78 {
80 }
81
82 void enter(const may&)
83 {
85 }
86
87 void leave(const may&)
88 {
90 }
91
92 void enter(const mu&)
93 {
95 }
96
97 void leave(const mu&)
98 {
100 }
101
102 void enter(const nu&)
103 {
104 enter_scope();
105 }
106
107 void leave(const nu&)
108 {
109 leave_scope();
110 }
111
112 void enter(const forall&)
113 {
114 enter_scope();
115 }
116
117 void leave(const forall&)
118 {
119 leave_scope();
120 }
121
122 void enter(const exists&)
123 {
124 enter_scope();
125 }
126
127 void leave(const exists&)
128 {
129 leave_scope();
130 }
131};
132
133inline
135{
137 f.apply(x);
138 return f.result;
139}
140
141struct has_unscoped_modal_formula_traverser: public state_formula_traverser<has_unscoped_modal_formula_traverser>
142{
144 using super::enter;
145 using super::leave;
146 using super::apply;
147
148 bool result;
149 std::vector<state_formula> fixpoints;
150
151 void push(const state_formula& x)
152 {
153 fixpoints.push_back(x);
154 }
155
156 void pop()
157 {
158 fixpoints.pop_back();
159 }
160
162 : result(false)
163 {}
164
165 void enter(const must&)
166 {
167 if (fixpoints.empty())
168 {
169 result = true;
170 }
171 }
172
173 void enter(const may&)
174 {
175 if (fixpoints.empty())
176 {
177 result = true;
178 }
179 }
180
181 void enter(const mu& x)
182 {
183 push(x);
184 }
185
186 void leave(const mu&)
187 {
188 pop();
189 }
190
191 void enter(const nu& x)
192 {
193 push(x);
194 }
195
196 void leave(const nu&)
197 {
198 pop();
199 }
200};
201
202inline
204{
206 f.apply(x);
207 return f.result;
208}
209
211template <typename IdentifierGenerator>
212struct state_formula_preprocess_nested_modal_operators_builder: public state_formulas::state_formula_builder<state_formula_preprocess_nested_modal_operators_builder<IdentifierGenerator> >
213{
215 using super::enter;
216 using super::leave;
217 using super::update;
218 using super::apply;
219
221 IdentifierGenerator& generator;
222 std::vector<state_formula> fixpoints;
223
228 {}
229
230 void push(const state_formula& x)
231 {
232 fixpoints.push_back(x);
233 }
234
235 void pop()
236 {
237 fixpoints.pop_back();
238 }
239
240 bool is_mu()
241 {
242 if (fixpoints.empty())
243 {
244 return true;
245 }
246 return state_formulas::is_mu(fixpoints.back());
247 }
248
249 void enter(const mu& x)
250 {
251 push(x);
252 }
253
254 void leave(const mu&)
255 {
256 pop();
257 }
258
259 void enter(const nu& x)
260 {
261 push(x);
262 }
263
264 void leave(const nu&)
265 {
266 pop();
267 }
268
269 template <class T>
270 void apply(T& result, const must& x)
271 {
272 state_formula operand;
273 apply(operand, x.operand());
274 if (!has_unscoped_modal_formulas(operand))
275 {
276 make_must(result, x.formula(), operand);
277 return;
278 }
280 if (is_mu())
281 {
282 make_must(result, x.formula(), mu(X, {}, operand));
283 return;
284 }
285 else
286 {
287 make_must(result, x.formula(), nu(X, {}, operand));
288 return;
289 }
290 }
291
292 template <class T>
293 void apply(T& result, const may& x)
294 {
295 state_formula operand;
296 apply(operand, x.operand());
297 if (!has_unscoped_modal_formulas(operand))
298 {
299 result = x;
300 return;
301 }
303 if (is_mu())
304 {
305 make_may(result, x.formula(), mu(X, {}, operand));
306 return;
307 }
308 else
309 {
310 make_may(result, x.formula(), nu(X, {}, operand));
311 return;
312 }
313 }
314};
315
319template <typename IdentifierGenerator>
321{
323}
324
325} // namespace detail
326
329inline
331{
333 std::set<core::identifier_string> ids = state_formulas::find_identifiers(x);
334 generator.add_identifiers(ids);
335 state_formula result;
337 return result;
338}
339
349inline
351 const std::set<core::identifier_string>& context_ids,
352 bool preprocess_modal_operators,
353 bool quantitative = false,
354 bool warn_for_modal_operator_nesting = true
355 )
356{
358
360 {
361 throw mcrl2::runtime_error("The formula " + state_formulas::pp(f) + " is not monotonous!");
362 }
363
364 if (!preprocess_modal_operators && warn_for_modal_operator_nesting && state_formulas::detail::count_modal_operator_nesting(formula) >= 3)
365 {
367 "Warning: detected nested modal operators. This may result in a long execution time.\n"
368 "Use the option -m (for lps2pbes/lps2pres), -p (for lts2pbes/lts2pres) or insert dummy fix \n"
369 "point operators in between manually to speed up the transformation." << std::endl;
370 }
371
372 mCRL2log(log::debug) << "Formula before preprocessing: " << f << ".\n";
373
374 // rename data variables in f, to prevent name clashes with data variables in the context
375 std::set<core::identifier_string> ids = state_formulas::find_identifiers(f);
376 ids.insert(context_ids.begin(), context_ids.end());
378
379 // rename predicate variables in f, to prevent name clashes
380 data::xyz_identifier_generator xyz_generator;
382 f = rename_predicate_variables(f, xyz_generator);
383
384 mCRL2log(log::debug) << "Formula after renaming variables: " << f << ".\n";
385
386 // add dummy fixpoints between nested modal operators
387 if (preprocess_modal_operators)
388 {
389 state_formula f0 = f;
391 if (f0 != f)
392 {
393 mCRL2log(log::debug) << "Formula after inserting dummy fix points between modal operators: " << f << ".\n";
394 }
395 }
396
397 // remove occurrences of ! and =>
399 {
400 f = state_formulas::normalize(f, quantitative); // true indicates that the formula is quantitative.
401 mCRL2log(log::debug) << "Formula after normalization: " << f << ".\n";
403 }
404
405 // wrap the formula inside a 'nu' if needed
407 {
410 core::identifier_string X = generator("X");
412 mCRL2log(log::debug) << "Formula after wrapping the formula inside a 'nu': " << f << ".\n";
413 }
414
415 // resolve name clashes like mu X(n: Nat). forall n: Nat
417 {
419 mCRL2log(log::debug) << "formula after removing data variable name clashes: " << f << std::endl;
420 }
421
422 mCRL2log(log::debug) << "formula after preprocessing: " << f << std::endl;
423
424 return f;
425}
426
427} // namespace state_formulas
428
429} // namespace mcrl2
430
431#endif // MCRL2_MODAL_FORMULA_PREPROCESS_STATE_FORMULA_H
Term containing a string.
void add_identifiers(const std::set< core::identifier_string > &ids)
Add a set of identifiers to the context.
Identifier generator that stores the identifiers of the context in a set. Using the operator()() and ...
Identifier generator that generates names from the range X, Y, Z, X0, Y0, Z0, X1, ....
Standard exception class for reporting runtime errors.
Definition exception.h:27
\brief The existential quantification operator for state formulas
\brief The universal quantification operator for state formulas
\brief The may operator for state formulas
const state_formula & operand() const
const regular_formulas::regular_formula & formula() const
\brief The mu operator for state formulas
\brief The must operator for state formulas
const regular_formulas::regular_formula & formula() const
const state_formula & operand() const
\brief The nu operator for state formulas
add your file description here.
#define mCRL2log(LEVEL)
mCRL2log(LEVEL) provides the stream used to log.
Definition logger.h:391
add your file description here.
Add your file description here.
state_formula_preprocess_nested_modal_operators_builder< IdentifierGenerator > make_state_formula_preprocess_nested_modal_operators_builder(IdentifierGenerator &generator)
Utility function for creating a state_formula_preprocess_nested_modal_operators_builder.
bool has_unscoped_modal_formulas(const state_formula &x)
std::size_t count_modal_operator_nesting(const state_formula &x)
state_formula rename_variables(const state_formula &f, const std::set< core::identifier_string > &forbidden_identifiers)
Renames all data variables in the formula f such that the forbidden identifiers are not used.
state_formula resolve_state_formula_data_variable_name_clashes(const state_formula &x, const std::set< core::identifier_string > &context_ids=std::set< core::identifier_string >())
Resolves name clashes in data variables of formula x.
state_formula preprocess_nested_modal_operators(const state_formula &x)
Preprocesses a state formula that contains (nested) modal operators.
bool has_data_variable_name_clashes(const state_formula &x)
Returns true if the formula contains parameter name clashes.
bool is_normalized(const T &x)
Checks if a state formula is normalized.
Definition normalize.h:411
state_formula rename_predicate_variables(const state_formula &f, IdentifierGenerator &generator)
Renames predicate variables of the formula f using the specified identifier generator.
void find_identifiers(const T &x, OutputIterator o)
Definition find.h:366
void pp(const T &t, std::ostream &out)
Prints the object t to a stream.
Definition print.h:668
void make_may(atermpp::aterm &t, const ARGUMENTS &... args)
void make_must(atermpp::aterm &t, const ARGUMENTS &... args)
bool is_nu(const atermpp::aterm &x)
state_formulas::state_formula preprocess_state_formula(const state_formulas::state_formula &formula, const std::set< core::identifier_string > &context_ids, bool preprocess_modal_operators, bool quantitative=false, bool warn_for_modal_operator_nesting=true)
Renames data variables and predicate variables in the formula f, and wraps the formula inside a 'nu' ...
bool is_monotonous(const state_formula &f, const std::set< core::identifier_string > &non_negated_variables, const std::set< core::identifier_string > &negated_variables)
Returns true if the state formula is monotonous.
bool is_mu(const atermpp::aterm &x)
void normalize(T &x, bool quantitative=false, bool negated=false, typename std::enable_if< !std::is_base_of< atermpp::aterm, T >::value >::type *=nullptr)
The function normalize brings (embedded) state formulas into positive normal form,...
Definition normalize.h:424
A class that takes a linear process specification and checks all tau-summands of that LPS for conflue...
Definition indexed_set.h:72
Add your file description here.
void update(state_formulas::state_formula_specification &x)
Definition builder.h:2526
void apply(T &result, const state_formulas::true_ &x)
Definition builder.h:2297
state_formula_traverser< count_modal_operator_nesting_traverser > super
state_formula_traverser< has_unscoped_modal_formula_traverser > super
Visitor that transforms state formulas. This can be useful if the state formula contains nested modal...
state_formulas::state_formula_builder< state_formula_preprocess_nested_modal_operators_builder< IdentifierGenerator > > super
Class that generates identifiers in the range X, Y, Z, X0, Y0, Z0, X1, ...