mCRL2
Loading...
Searching...
No Matches
guard_traverser.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//
9/// \file mcrl2/pbes/detail/guard_traverser.h
10/// \brief add your file description here.
11
12#ifndef MCRL2_PBES_DETAIL_GUARD_TRAVERSER_H
13#define MCRL2_PBES_DETAIL_GUARD_TRAVERSER_H
14
15#include "mcrl2/data/rewriter.h"
16#include "mcrl2/pbes/pbes_expression.h"
17#include "mcrl2/pbes/pbes_functions.h"
18#include "mcrl2/pbes/rewrite.h"
19#include "mcrl2/pbes/rewriters/simplify_rewriter.h"
20
21#ifdef MCRL2_PBES_STATEGRAPH_CHECK_GUARDS
22#include "mcrl2/pbes/find.h"
23#endif
24
25
26
27
28
29namespace mcrl2::pbes_system::detail {
30
31#ifdef MCRL2_PBES_STATEGRAPH_CHECK_GUARDS
32inline
34{
35 if (is_simple_expression(x, false))
36 {
37 return x;
38 }
39 else
40 {
41 return true_();
42 }
43}
44
45inline
47{
48 if (is_simple_expression(x, false))
49 {
52 return result;
53 }
54 else
55 {
56 return true_();
57 }
58}
59
60inline
62{
64 return xocc.find(X) != xocc.end();
65}
66
67inline
69{
71 {
72 return false_();
73 }
75 {
76 return true_();
77 }
78 else if (pbes_system::is_true(x))
79 {
80 return false_();
81 }
82 else if (pbes_system::is_false(x))
83 {
84 return false_();
85 }
86
88 if (pbes_system::is_not(x))
89 {
92 return result;
93 }
94 else if (pbes_system::is_and(x))
95 {
99 {
101 }
102 else
103 {
105 }
106 return result;
107 }
108 else if (pbes_system::is_or(x))
109 {
113 {
115 }
116 else
117 {
119 }
120 return result;
121 }
122
123 else if (pbes_system::is_imp(x))
124 {
127 return guard_impl(X, or_(not_(phi), psi));
128 }
129 else if (pbes_system::is_forall(x))
130 {
132 return guard_impl(X, phi);
133 }
134 else if (pbes_system::is_exists(x))
135 {
137 return guard_impl(X, phi);
138 }
139
140 throw mcrl2::runtime_error("guard_impl: unknown term " + pbes_system::pp(x));
141 return result;
142}
143
144// Direct implementation of the definition, to be used for checking results.
145inline
147{
150 if (xocc.count(X) != 1)
151 {
152 throw mcrl2::runtime_error("guard is undefined for " + pbes_system::pp(X));
153 }
154 return guard_impl(X, x);
155}
156#endif // MCRL2_PBES_STATEGRAPH_CHECK_GUARDS
157
159{
162
163 bool is_simple() const
164 {
165 return guards.empty();
166 }
167
168 void add_guard(const pbes_expression& guard)
169 {
170 if (is_simple())
171 {
173 }
174 else
175 {
176 for (auto& g: guards)
177 {
178 pbes_system::make_optimized_and(g.second, guard, g.second);
179 }
180 }
181 }
182
183 void negate()
184 {
185 if (is_simple())
186 {
188 }
189 else
190 {
191 for (auto& g: guards)
192 {
193 pbes_system::make_optimized_not(g.second, g.second);
194 }
195 }
196 }
197
199 : condition(condition_)
200 {}
201
202#ifdef MCRL2_PBES_STATEGRAPH_CHECK_GUARDS
203 // Check if the guards were correctly computed with respect to x.
204 template <typename PbesRewriter>
205 bool check_guards(const pbes_expression& x, PbesRewriter R) const
206 {
207 mCRL2log(log::log_level_t::debug) << "check_guards: x = " << pbes_system::pp(x) << std::endl;
208 bool result = true;
209 for (const auto& i: guards)
210 {
211 try
212 {
214 const pbes_expression& g1 = i.second;
216 if (pbes_rewrite(g1, R) != pbes_rewrite(g2, R))
217 {
218 result = false;
219 mCRL2log(log::log_level_t::debug) << " g1 = " << g1 << " g2 = " << g2 << std::endl;
220 mCRL2log(log::log_level_t::debug) << "guard error: X = " << X << " g1 = " << pbes_rewrite(g1, R) << " g2 = " << pbes_rewrite(g2, R) << std::endl;
221 }
222 }
223 // NOLINTNEXTLINE(bugprone-empty-catch) intentional: do not check multiple instances of predicate variables
224 catch (mcrl2::runtime_error&)
225 {
226 // do not check multiple instances of predicate variables
227 }
228 }
229 return result;
230 }
231#else
232 // Check if the guards were correctly computed with respect to x.
233 template <typename PbesRewriter>
234 bool check_guards(const pbes_expression& /* x */, PbesRewriter /* R */) const
235 {
236 return true;
237 }
238#endif
239};
240
241inline
243{
244 if (x.is_simple())
245 {
246 out << "condition = " << pbes_system::pp(x.condition) << std::endl;
247 }
248 else
249 {
250 for (const auto& g: x.guards)
251 {
252 out << pbes_system::pp(g.first) << " guard = " << pbes_system::pp(g.second) << std::endl;
253 }
254 }
255 return out;
256}
257
258/// \brief Computes a multimap of propositional variable instantiations and the corresponding guards from a PBES expression
260{
262 using super::enter;
263 using super::leave;
264 using super::apply;
265
268
269 explicit guard_traverser(const data::rewriter& r)
270 : R(r)
271 {}
272
273 void push(const guard_expression& x)
274 {
275 mCRL2log(log::log_level_t::trace) << "<push>" << "\n" << x << std::endl;
276 expression_stack.push_back(x);
277 }
278
280 {
281 return expression_stack.back();
282 }
283
284 const guard_expression& top() const
285 {
286 return expression_stack.back();
287 }
288
290 {
291 guard_expression result = top();
292 expression_stack.pop_back();
293 return result;
294 }
295
296 void leave(const data::data_expression& x)
297 {
298 push(guard_expression(atermpp::down_cast<pbes_expression>(x)));
299 assert(top().check_guards(atermpp::down_cast<pbes_expression>(x), R));
300 }
301
303 {
304 guard_expression node;
305 node.guards.emplace_back(x, pbes_system::true_());
306 push(node);
307 assert(top().check_guards(x, R));
308 }
309
310 void leave( [[maybe_unused]] const pbes_system::not_& x)
311 {
313 assert(top().check_guards(x, R));
314 }
315
316 void leave( [[maybe_unused]] const pbes_system::and_& x)
317 {
318 guard_expression right = pop();
319 guard_expression left = pop();
320 pbes_expression new_condition;
322 if (left.is_simple() && right.is_simple())
323 {
324 left.condition = new_condition;
325 push(left);
326 }
327 else if (left.is_simple())
328 {
329 right.add_guard(left.condition);
330 right.condition = new_condition;
331 push(right);
332 }
333 else if (right.is_simple())
334 {
335 left.add_guard(right.condition);
336 left.condition = new_condition;
337 push(left);
338 }
339 else
340 {
341 left.guards.insert(left.guards.end(), right.guards.begin(), right.guards.end());
342 left.condition = new_condition;
343 push(left);
344 }
345 assert(top().check_guards(x, R));
346 }
347
348 void leave([[maybe_unused]] const pbes_system::or_& x)
349 {
350 guard_expression right = pop();
351 guard_expression left = pop();
352 pbes_expression new_condition;
354 if (left.is_simple() && right.is_simple())
355 {
356 left.condition = new_condition;
357 push(left);
358 }
359 else if (left.is_simple())
360 {
363 right.add_guard(d);
364 right.condition = new_condition;
365 push(right);
366 }
367 else if (right.is_simple())
368 {
371 left.add_guard(d);
372 left.condition = new_condition;
373 push(left);
374 }
375 else
376 {
377 left.guards.insert(left.guards.end(), right.guards.begin(), right.guards.end());
378 left.condition = new_condition;
379 push(left);
380 }
381 assert(top().check_guards(x, R));
382 }
383
384 void leave( [[maybe_unused]] const pbes_system::imp& x)
385 {
386 guard_expression right = pop();
387 guard_expression left = pop();
388 left.negate();
389 pbes_expression new_condition;
391 if (left.is_simple() && right.is_simple())
392 {
393 left.condition = new_condition;
394 push(left);
395 }
396 else if (left.is_simple())
397 {
400 right.add_guard(d);
401 right.condition = new_condition;
402 push(right);
403 }
404 else if (right.is_simple())
405 {
408 left.add_guard(d);
409 left.condition = new_condition;
410 push(left);
411 }
412 else
413 {
414 left.guards.insert(left.guards.end(), right.guards.begin(), right.guards.end());
415 left.condition = new_condition;
416 push(left);
417 }
418 assert(top().check_guards(x, R));
419 }
420
421 void leave(const pbes_system::forall& x)
422 {
423 // If x is a simple expression, quantifiers need to be handled differently!
425 {
427 }
428 assert(top().check_guards(x, R));
429 }
430
431 void leave(const pbes_system::exists& x)
432 {
433 // If x is a simple expression, quantifiers need to be handled differently!
435 {
437 }
438 assert(top().check_guards(x, R));
439 }
440};
441
442} // namespace mcrl2::pbes_system::detail
443
444
445
446
447
448#endif // MCRL2_PBES_DETAIL_GUARD_TRAVERSER_H
Rewriter that operates on data expressions.
Definition rewriter.h:84
\brief The and operator for pbes expressions
\brief The existential quantification operator for pbes expressions
\brief The universal quantification operator for pbes expressions
\brief The implication operator for pbes expressions
\brief The not operator for pbes expressions
\brief The or operator for pbes expressions
pbes_expression & operator=(const pbes_expression &) noexcept=default
pbes_expression(const pbes_expression &) noexcept=default
Move semantics.
\brief A propositional variable instantiation
#define mCRL2log(LEVEL)
mCRL2log(LEVEL) provides the stream used to log.
Definition logger.h:435
std::ostream & operator<<(std::ostream &out, const guard_expression &x)
void make_optimized_and(pbes_expression &result, const pbes_expression &p, const pbes_expression &q)
Make a conjunction.
const pbes_expression & true_()
void make_optimized_not(pbes_expression &result, const pbes_expression &p)
Make a negation.
void make_optimized_or(pbes_expression &result, const pbes_expression &p, const pbes_expression &q)
Make a disjunction.
guard_expression(const pbes_expression &condition_=pbes_system::true_())
bool check_guards(const pbes_expression &, PbesRewriter) const
void add_guard(const pbes_expression &guard)
Computes a multimap of propositional variable instantiations and the corresponding guards from a PBES...
void leave(const pbes_system::forall &x)
void push(const guard_expression &x)
void leave(const pbes_system::exists &x)
void leave(const pbes_system::not_ &x)
void leave(const data::data_expression &x)
const guard_expression & top() const
simplify_data_rewriter< data::rewriter > R
void leave(const pbes_system::and_ &x)
void leave(const pbes_system::imp &x)
void leave(const pbes_system::or_ &x)
void leave(const pbes_system::propositional_variable_instantiation &x)
std::vector< guard_expression > expression_stack
A rewriter that simplifies boolean expressions in a term, and rewrites data expressions using DataRew...