mCRL2
Loading...
Searching...
No Matches
srf_pbes.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/srf_pbes.h
10/// \brief add your file description here.
11
12#ifndef MCRL2_PBES_SRF_PBES_H
13#define MCRL2_PBES_SRF_PBES_H
14
15#include "mcrl2/atermpp/aterm.h"
16#include "mcrl2/core/detail/print_utility.h"
17#include "mcrl2/data/data_expression.h"
18#include "mcrl2/pbes/detail/pbes_remove_counterexample_info.h"
19#include "mcrl2/pbes/find.h"
20#include "mcrl2/pbes/join.h"
21#include "mcrl2/pbes/pbes_equation.h"
22#include "mcrl2/pbes/pbes_expression.h"
23#include "mcrl2/pbes/pbes_functions.h"
24#include "mcrl2/pbes/pbes.h"
25#include "mcrl2/pbes/rewriters/pbes2data_rewriter.h"
26#include "mcrl2/utilities/exception.h"
27#include "mcrl2/utilities/logger.h"
28
29namespace mcrl2
30{
31
32namespace pbes_system
33{
34
35namespace detail
36{
37
39{
41 {
42 return atermpp::down_cast<pbes_expression>(data::sort_bool::arg(atermpp::down_cast<data::data_expression>(x)));
43 }
44 else if (is_not(x))
45 {
46 return accessors::arg(x);
47 }
48 return not_(x);
49}
50
51template <typename Iterator>
52pbes_expression make_conjunction(Iterator first, Iterator last)
53{
54 if (first == last)
55 {
56 return true_();
57 }
58
59 Iterator it = first;
60 pbes_expression result = *it;
61 ++it;
62
63 while (it != last)
64 {
65 make_and_(result, result, *it);
66 ++it;
67 }
68
69 return result;
70}
71
72template <typename Iterator>
73pbes_expression make_disjunction(Iterator first, Iterator last)
74{
75 if (first == last)
76 {
77 return false_();
78 }
79
80 Iterator it = first;
81 pbes_expression result = *it;
82 ++it;
83
84 while (it != last)
85 {
86 make_or_(result, result, *it);
87 ++it;
88 }
89
90 return result;
91}
92
93/// @brief Assuming that x is of the form (x1 && x2 && ... xn), generates
94/// expression !x1 || !x2 || ... !xn
95/// @param x a pbes_expression that is conjunctive
96/// @return disjunctive expression that is equivalent to !x.
98{
99 std::set<pbes_expression> conjuncts = split_and(x);
100 std::set<pbes_expression> disjuncts;
101 // negate each of the expressions
102 for (const pbes_expression& conjunct : conjuncts)
103 {
104 disjuncts.insert(make_not(conjunct));
105 }
106 return make_disjunction(disjuncts.begin(), disjuncts.end());
107}
108
109/// A summand in a srf equation, if allow_ce is true then counter example information is
110/// allowed in the condition. This means that the condition contains propositional variables.
111template <bool allow_ce>
113{
115protected:
116 data::variable_list m_parameters;
119
120public:
121 pre_srf_summand(data::variable_list parameters,
122 const pbes_expression& condition,
125 m_X(std::move(X))
126 {
127 if constexpr (!allow_ce)
128 {
129 m_condition = detail::pbes2data(condition);
130 }
131 else
132 {
133 m_condition = condition;
134 }
135 }
136
137 const data::variable_list& parameters() const { return m_parameters; }
138
139 data::variable_list& parameters() { return m_parameters; }
140
141 const condition_type& condition() const { return m_condition; }
142
143 condition_type& condition() { return m_condition; }
144
146
148
149 void add_variables(const data::variable_list& variables) { m_parameters = variables + m_parameters; }
150
152 {
153 if constexpr (allow_ce)
154 {
155 m_condition = pbes_system::and_(f, m_condition);
156 }
157 else
158 {
159 m_condition = data::and_(pbes2data(f), m_condition);
160 }
161 }
162
163 pbes_expression to_pbes(bool conjunctive) const
164 {
165 if (conjunctive)
166 {
167 // if counterexample information is allowed, we may have generated conjuncts
168 // with guards of the form !X, where X is a variable that encodes counterexample
169 // information. As other algorithms expect expressions in positive form, we need
170 // to push the negation inside.
171 return make_forall_(m_parameters, or_(distribute_not_over_and(atermpp::down_cast<pbes_expression>(m_condition)), m_X));
172 }
173 else
174 {
175 return make_exists_(m_parameters, and_(atermpp::down_cast<pbes_expression>(m_condition), m_X));
176 }
177 }
178};
179
180template <bool allow_ce>
182{
183 return out << "variables = " << core::detail::print_list(summand.parameters()) << " f = " << summand.condition()
184 << " X = " << summand.variable();
185}
186
187template <bool allow_ce>
189{
190protected:
195
196public:
197 explicit pre_srf_equation(const fixpoint_symbol& sigma,
198 const propositional_variable& variable,
199 std::vector<pre_srf_summand<allow_ce>> summands,
200 bool conjunctive)
201 : m_sigma(sigma),
202 m_variable(variable),
204 m_conjunctive(conjunctive)
205 {}
206
207 const fixpoint_symbol& symbol() const { return m_sigma; }
208
210
211 const propositional_variable& variable() const { return m_variable; }
212
214
215 const std::vector<pre_srf_summand<allow_ce>>& summands() const { return m_summands; }
216
217 std::vector<pre_srf_summand<allow_ce>>& summands() { return m_summands; }
218
219 bool& is_conjunctive() { return m_conjunctive; }
220
221 bool is_conjunctive() const { return m_conjunctive; }
222
224 {
225 if (is_counter_example_variable(variable()))
226 {
227 if (is_counter_example_positive(variable().name()))
228 {
230 }
231 else
232 {
234 }
235 }
236
237 std::vector<pbes_expression> v;
238 for (const auto& summand : m_summands)
239 {
240 v.push_back(summand.to_pbes(m_conjunctive));
241 }
242 pbes_expression rhs = m_conjunctive ? join_and(v.begin(), v.end()) : join_or(v.begin(), v.end());
244 }
245
246 /// Ensures that the equation is total, by adding the summands corresponding to true and false
247 void make_total(const pre_srf_summand<allow_ce>& true_summand, const pre_srf_summand<allow_ce>& false_summand)
248 {
249 if (m_conjunctive)
250 {
251 m_summands.push_back(true_summand);
252 }
253 else
254 {
255 m_summands.push_back(false_summand);
256 }
257 }
258};
259
260template <bool allow_ce>
262{
263 out << "srf equation" << std::endl;
264 for (const auto& summand : eqn.summands())
265 {
266 out << summand << std::endl;
267 }
268 return out;
269}
270
271template <bool allow_ce>
274 const pbes_equation& eqn,
275 const data::variable_list& V,
281
282template <bool allow_ce>
284{
286 using super::apply;
287 using super::enter;
288 using super::leave;
289
290 // The remaining PBES equations
292
293 // The current equation
295
296 const data::variable_list& V;
297
298 // Used for creating new equations
300
301 // The names of the true and false equations
302 const core::identifier_string& X_true;
303 const core::identifier_string& X_false;
304
305 // The equations of the resulting srf PBES
307
308 // The summands of the generated equation
310
311 /// If true do not introduce a new PBES equation for simple expressions, and instead add them to every summand
312 /// separately.
314
315 srf_or_traverser(std::deque<pbes_equation>& equations_,
316 const pbes_equation& eqn_,
317 const data::variable_list& V_,
318 data::set_identifier_generator& id_generator_,
319 const core::identifier_string& X_true_,
320 const core::identifier_string& X_false_,
321 std::vector<pre_srf_equation<allow_ce>>& result_,
322 bool merge_simple_expressions)
324 eqn(eqn_),
325 V(V_),
326 id_generator(id_generator_),
327 X_true(X_true_),
328 X_false(X_false_),
330 m_merge_simple_expressions(merge_simple_expressions)
331 {}
332
333 void apply(const and_& x)
334 {
335 if (m_merge_simple_expressions && is_simple_expression(x.left(), allow_ce))
336 {
337 std::size_t size = summands.size();
338 apply(x.right());
339 for (auto i = summands.begin() + size; i != summands.end(); ++i)
340 {
341 i->add_condition(x.left());
342 }
343 }
344 else if (m_merge_simple_expressions && is_simple_expression(x.right(), allow_ce))
345 {
346 std::size_t size = summands.size();
347 apply(x.left());
348 for (auto i = summands.begin() + size; i != summands.end(); ++i)
349 {
350 i->add_condition(x.right());
351 }
352 }
353 else
354 {
357 const pbes_expression& f = true_();
358 equations.emplace_front(eqn.symbol(), X1, x);
359 summands.emplace_back(data::variable_list(),
360 f,
361 propositional_variable_instantiation(X1.name(), data::make_data_expression_list(V)));
362 }
363 }
364
365
366 void apply(const or_& x)
367 {
368 if (!allow_ce)
369 {
370 return super::apply(x);
371 }
372
373 mCRL2log(log::trace) << "Or expression " << x << "\n";
374
375 // Special case for pre-SRF with simple expressions.
376 std::set<pbes_expression> clauses = split_or(x, false);
377
378 std::vector<pbes_expression> simple_clauses;
379 for (const auto& clause : clauses)
380 {
381 if (m_merge_simple_expressions && is_simple_expression(clause, false))
382 {
383 simple_clauses.emplace_back(clause);
384 apply(clause);
385 }
386 }
387
388 if (simple_clauses.empty())
389 {
390 // No simple clauses, so we can just apply the or_ operator.
391 super::apply(x);
392 return;
393 }
394
395 pbes_expression condition = make_disjunction(simple_clauses.begin(), simple_clauses.end());
396 mCRL2log(log::trace) << "Simple condition " << condition << "\n";
397
398 for (const auto& clause : clauses)
399 {
400 if (!m_merge_simple_expressions || !is_simple_expression(clause, false))
401 {
402 mCRL2log(log::trace) << "Clause " << clause << "\n";
403 std::size_t size = summands.size();
404 apply(clause);
405 for (auto i = summands.begin() + size; i != summands.end(); ++i)
406 {
407 i->add_condition(detail::make_not(condition));
408 }
409 }
410 }
411 }
412
413
414 void apply(const exists& x)
415 {
416 std::vector<pre_srf_summand<allow_ce>> body_summands = srf_or(x.body(),
417 equations,
418 eqn,
419 V + x.variables(),
420 id_generator,
421 X_true,
422 X_false,
423 result,
424 m_merge_simple_expressions);
425 for (auto& summand : body_summands)
426 {
427 summand.add_variables(x.variables());
428 }
429 summands.insert(summands.end(), body_summands.begin(), body_summands.end());
430 }
431
432 void apply(const forall& x)
433 {
434 if (is_simple_expression(x.body(), allow_ce))
435 {
436 const pbes_expression& f = x.body();
437 const propositional_variable_instantiation& X = propositional_variable_instantiation(X_true, {});
438 summands.emplace_back(x.variables(), f, X);
439 }
440 else
441 {
444 const pbes_expression& f = true_();
445 equations.emplace_front(eqn.symbol(), X1, x);
446 summands.emplace_back(data::variable_list(),
447 f,
448 propositional_variable_instantiation(X1.name(), data::make_data_expression_list(V)));
449 }
450 }
451
453 {
454 const pbes_expression& f = true_();
455 summands.emplace_back(data::variable_list(), f, x);
456 }
457
458 void apply(const pbes_expression& x)
459 {
460 if (is_simple_expression(x, allow_ce))
461 {
462 const propositional_variable_instantiation& X = propositional_variable_instantiation(X_true, {});
463 const pbes_expression& f = x;
464 summands.emplace_back(data::variable_list(), f, X);
465 }
466 else
467 {
468 super::apply(x);
469 }
470 }
471
472 void apply(const not_& x) {
473 throw mcrl2::runtime_error("srf_or_traverser::apply(not_) unsupported term " + pbes_system::pp(x));
474 }
475
476 void apply(const imp& x) {
477 throw mcrl2::runtime_error("srf_or_traverser::apply(imp) unsupported term " + pbes_system::pp(x));
478 }
479};
480
481template<bool allow_ce>
484 const pbes_equation& eqn,
485 const data::variable_list& V,
491{
492 srf_or_traverser<allow_ce> f(equations, eqn, V, id_generator, X_true, X_false, result, merge_simple_expressions);
493 f.apply(phi);
494 return std::move(f.summands);
495}
496
497template<bool allow_ce>
500 const pbes_equation& eqn,
501 const data::variable_list& V,
507
508template<bool allow_ce>
510{
512 using super::apply;
513 using super::enter;
514 using super::leave;
515
516 // The remaining PBES equations
518
519 // The current equation
521
522 const data::variable_list& V;
523
524 // Used for creating new equations
526
527 // The names of the true and false equations
528 const core::identifier_string& X_true;
529 const core::identifier_string& X_false;
530
531 // The equations of the resulting srf PBES
533
534 // The summands of the generated equation
536
537 /// If true do not introduce a new PBES equation for simple expressions, and instead add them to every summand
538 /// separately.
540
541 srf_and_traverser(std::deque<pbes_equation>& equations_,
542 const pbes_equation& eqn_,
543 const data::variable_list& V_,
544 data::set_identifier_generator& id_generator_,
545 const core::identifier_string& X_true_,
546 const core::identifier_string& X_false_,
547 std::vector<pre_srf_equation<allow_ce>>& result_,
548 bool merge_simple_expressions)
550 eqn(eqn_),
551 V(V_),
552 id_generator(id_generator_),
553 X_true(X_true_),
554 X_false(X_false_),
556 m_merge_simple_expressions(merge_simple_expressions)
557 {}
558
559 void apply(const or_& x)
560 {
561 if (m_merge_simple_expressions && is_simple_expression(x.left(), allow_ce))
562 {
563 std::size_t size = summands.size();
564 apply(x.right());
565 for (auto i = summands.begin() + size; i != summands.end(); ++i)
566 {
567 i->add_condition(detail::make_not(x.left()));
568 }
569 }
570 else if (m_merge_simple_expressions && is_simple_expression(x.right(), allow_ce))
571 {
572 std::size_t size = summands.size();
573 apply(x.left());
574 for (auto i = summands.begin() + size; i != summands.end(); ++i)
575 {
576 i->add_condition(detail::make_not(x.right()));
577 }
578 }
579 else
580 {
583 const pbes_expression& f = true_();
584 equations.emplace_front(eqn.symbol(), X1, x);
585 summands.emplace_back(data::variable_list(),
586 f,
587 propositional_variable_instantiation(X1.name(), data::make_data_expression_list(V)));
588 }
589 }
590
591 void apply(const and_& x)
592 {
593 if (!allow_ce)
594 {
595 super::apply(x);
596 return;
597 }
598
599 mCRL2log(log::trace) << "Expression " << x << "\n";
600
601 // Special case for pre-SRF with simple expressions.
602 std::set<pbes_expression> clauses = split_and(x, false);
603
604 std::vector<pbes_expression> simple_clauses;
605 // Collect simple expressions to strengthen conjuncts of result of
606 // recursive calls. We do not include counterexample information to
607 // ensure that the PBES remains in positive form.
608 for (const auto& clause : clauses)
609 {
610 if (m_merge_simple_expressions && is_simple_expression(clause, false))
611 {
612 simple_clauses.emplace_back(clause);
613 apply(clause);
614 }
615 }
616
617 if (simple_clauses.empty())
618 {
619 // No simple clauses, so we can just apply the or_ operator.
620 super::apply(x);
621 return;
622 }
623
624 // condition used for strengthening guards of dependencies.
625 pbes_expression condition = make_conjunction(simple_clauses.begin(), simple_clauses.end());
626 mCRL2log(log::trace) << "Simple condition " << condition << "\n";
627
628 // Recursively apply (pre)SRF transformation.
629 for (const auto& clause : clauses)
630 {
631 if (!m_merge_simple_expressions || !is_simple_expression(clause, false))
632 {
633 mCRL2log(log::trace) << "Clause " << clause << "\n";
634 std::size_t size = summands.size();
635 apply(clause);
636 for (auto i = summands.begin() + size; i != summands.end(); ++i)
637 {
638 i->add_condition(condition);
639 }
640 }
641 }
642 }
643
644 void apply(const forall& x)
645 {
646 std::vector<pre_srf_summand<allow_ce>> body_summands = srf_and(x.body(),
647 equations,
648 eqn,
649 V + x.variables(),
650 id_generator,
651 X_true,
652 X_false,
653 result,
654 m_merge_simple_expressions);
655 for (auto& summand : body_summands)
656 {
657 summand.add_variables(x.variables());
658 }
659 summands.insert(summands.end(), body_summands.begin(), body_summands.end());
660 }
661
662 void apply(const exists& x)
663 {
664 if (is_simple_expression(x.body(), allow_ce))
665 {
666 const pbes_expression& f = x.body();
667 const propositional_variable_instantiation& X = propositional_variable_instantiation(X_true, {});
668 summands.emplace_back(x.variables(), f, X);
669 }
670 else
671 {
674 const pbes_expression& f = true_();
675 equations.emplace_front(eqn.symbol(), X1, x);
676 summands.emplace_back(data::variable_list(),
677 f,
678 propositional_variable_instantiation(X1.name(), data::make_data_expression_list(V)));
679 }
680 }
681
683 {
684 const pbes_expression& f = true_();
685 summands.emplace_back(data::variable_list(), f, x);
686 }
687
688 void apply(const pbes_expression& x)
689 {
690 if (is_simple_expression(x, allow_ce))
691 {
692 const propositional_variable_instantiation& X = propositional_variable_instantiation(X_false, {});
693 const pbes_expression& f = x;
694 summands.emplace_back(data::variable_list(), detail::make_not(f), X);
695 }
696 else
697 {
698 super::apply(x);
699 }
700 }
701
702 void apply(const not_& x) {
703 throw mcrl2::runtime_error("srf_and_traverser::apply(not_) unsupported term " + pbes_system::pp(x));
704 }
705
706 void apply(const imp& x) {
707 throw mcrl2::runtime_error("srf_and_traverser::apply(imp) unsupported term " + pbes_system::pp(x));
708 }
709};
710
711template<bool allow_ce>
714 const pbes_equation& eqn,
715 const data::variable_list& V,
721{
722 srf_and_traverser f(equations, eqn, V, id_generator, X_true, X_false, result, merge_simple_expressions);
723 f.apply(phi);
724 return std::move(f.summands);
725}
726
727inline bool is_conjunctive(const pbes_expression& phi, bool allow_ce)
728{
729 if (is_simple_expression(phi, allow_ce))
730 {
731 return false;
732 }
734 {
735 return false;
736 }
737 else if (is_or(phi))
738 {
739 const auto& phi_ = atermpp::down_cast<or_>(phi);
740 return (is_simple_expression(phi_.left(), allow_ce) && is_propositional_variable_instantiation(phi_.right()))
741 || (is_simple_expression(phi_.right(), allow_ce) && is_propositional_variable_instantiation(phi_.left()));
742 }
743 else if (is_and(phi))
744 {
745 const auto& phi_ = atermpp::down_cast<and_>(phi);
746 bool result = !((is_simple_expression(phi_.left(), allow_ce) && is_propositional_variable_instantiation(phi_.right()))
747 || (is_simple_expression(phi_.right(), allow_ce) && is_propositional_variable_instantiation(phi_.left())));
748 return result;
749 }
750 else if (is_exists(phi))
751 {
752 return false;
753 }
754 else if (is_forall(phi))
755 {
756 return true;
757 }
758 throw mcrl2::runtime_error("is_conjunctive: unexpected case " + pbes_system::pp(phi));
759}
760
761/// explicit representation of a pbes in SRF format
762///
763/// If allow_ce is true, then counter example expressions are allowed in the
764/// PBES. We refer to this as kind of `pre_srf`. When the counter example
765/// information is replaced by `true` or `false` in every condition, we obtain a
766/// `srf`.
767template <bool allow_ce>
769{
770protected:
774
775public:
776 pre_srf_pbes() = default;
777
779 std::vector<pre_srf_equation<allow_ce>> equations,
784 {}
785
786 const std::vector<pre_srf_equation<allow_ce>>& equations() const { return m_equations; }
787
788 std::vector<pre_srf_equation<allow_ce>>& equations() { return m_equations; }
789
791
793
794 const data::data_specification& data() const { return m_dataspec; }
795
796 data::data_specification& data() { return m_dataspec; }
797
798 pbes to_pbes() const
799 {
800 std::vector<pbes_equation> v;
801 for (const auto& eqn : equations())
802 {
803 v.push_back(eqn.to_pbes());
804 }
805 return pbes(m_dataspec, std::set<data::variable>(), v, m_initial_state);
806 }
807
808 // Adds extra clauses to the equations to enforce that the PBES is in total SRF format
809 // Precondition: the last two equations must be the equations corresponding to false and true
811 {
812 // TODO: Remove this hack.
813 std::size_t N = m_equations.size();
814 const auto& false_summand = m_equations[N - 2].summands().front();
815 const auto& true_summand = m_equations[N - 1].summands().front();
816 for (std::size_t i = 0; i < N - 2; i++)
817 {
818 m_equations[i].make_total(true_summand, false_summand);
819 }
820 }
821};
822
823/// \brief Converts a PBES into standard recursive form
824/// \pre The pbes p must be normalized
825/// \param allow_ce If true, then counter example expressions are allowed in the simple expressions of the PBES.
826/// \param merge_simple_expressions If true, then simple expressions are merged into the summands of the SRF equations.
827///
828/// \return A pre-SRF PBES, which is a PBES in SRF format
829template<bool allow_ce>
830inline detail::pre_srf_pbes<allow_ce> pbes2pre_srf(const pbes& p, bool merge_simple_expressions = true)
831{
832 data::set_identifier_generator id_generator;
833 for (const core::identifier_string& id : pbes_system::find_identifiers(p))
834 {
835 id_generator.add_identifier(id);
836 }
837
838 core::identifier_string X_false = id_generator("X_false");
839 core::identifier_string X_true = id_generator("X_true");
840 pbes_equation eqn_false(fixpoint_symbol::mu(),
841 propositional_variable(X_false, {}),
842 or_(atermpp::down_cast<pbes_expression>(data::sort_bool::false_()), propositional_variable_instantiation(X_false, {})));
844 propositional_variable(X_true, {}),
845 propositional_variable_instantiation(X_true, {}));
846
847 const auto& p_equations = p.equations();
848 std::deque<pbes_equation> equations(p_equations.begin(), p_equations.end());
849 equations.emplace_back(eqn_false);
850 equations.emplace_back(eqn_true);
851
852 std::vector<detail::pre_srf_equation<allow_ce>> srf_equations;
853 while (!equations.empty())
854 {
855 pbes_equation eqn = equations.front();
856 equations.pop_front();
857 bool is_conjunctive = detail::is_conjunctive(eqn.formula(), allow_ce);
858 std::vector<detail::pre_srf_summand<allow_ce>> summands = is_conjunctive ? detail::srf_and(eqn.formula(),
859 equations,
860 eqn,
861 eqn.variable().parameters(),
862 id_generator,
863 X_true,
864 X_false,
865 srf_equations,
866 merge_simple_expressions)
867 : detail::srf_or(eqn.formula(),
868 equations,
869 eqn,
870 eqn.variable().parameters(),
871 id_generator,
872 X_true,
873 X_false,
874 srf_equations,
875 merge_simple_expressions);
876 srf_equations.emplace_back(eqn.symbol(), eqn.variable(), summands, is_conjunctive);
877 }
878
879 auto result = detail::pre_srf_pbes<allow_ce>(p.data(),
880 std::vector<detail::pre_srf_equation<allow_ce>>(srf_equations.begin(), srf_equations.end()),
881 p.initial_state());
882 return result;
883}
884
885} // namespace detail
886
887using srf_summand = detail::pre_srf_summand<false>;
888
889using srf_equation = detail::pre_srf_equation<false>;
890
891/// This is a PBES in SRF format
892using srf_pbes = detail::pre_srf_pbes<false>;
893
894/// This is a PBES in pre-SRF format, where counter example expressions, i.e., propositional variables are allowed in
895/// simple expressions.
896using srf_pbes_with_ce = detail::pre_srf_pbes<true>;
897
898
899/// \brief Converts a pre-SRF PBES into standard recursive form. Note that the
900/// counter example information of the pre_srf_pbes is removed since otherwise
901/// the result is not in SRF.
902inline srf_pbes pre_srf2srfpbes(const srf_pbes_with_ce& p)
903{
904 // Used to remove counter example information
906 simplify_rewriter simplify;
907
908 std::vector<detail::pre_srf_equation<false>> equations;
909 for (const auto& equation : p.equations())
910 {
911 if (!detail::is_counter_example_equation(equation.to_pbes()))
912 {
913 std::vector<detail::pre_srf_summand<false>> summands;
914 for (const auto& summand : equation.summands())
915 {
916 pbes_expression result;
917 f.apply(result, summand.variable());
918 propositional_variable_instantiation variable = atermpp::down_cast<propositional_variable_instantiation>(simplify(result));
919
920 f.apply(result, summand.condition());
921
922 summands.emplace_back(summand.parameters(), simplify(result), variable);
923 }
924
925 equations.emplace_back(equation.symbol(), equation.variable(), summands, equation.is_conjunctive());
926 }
927 }
928
929 return srf_pbes(p.data(), equations, p.initial_state());
930}
931
932
933/// \brief Converts a PBES into pre standard recursive form
934/// \pre The pbes p must be normalized
935inline srf_pbes_with_ce pbes2pre_srf(const pbes& p, bool merge_simple_expressions = true)
936{
937 return detail::pbes2pre_srf<true>(p, merge_simple_expressions);
938}
939
940/// \brief Converts a PBES into standard recursive form
941/// \pre The pbes p must be normalized
942inline srf_pbes pbes2srf(const pbes& p, bool merge_simple_expressions = true)
943{
944 return detail::pbes2pre_srf<false>(p, merge_simple_expressions);
945}
946
947} // namespace pbes_system
948
949inline bool is_srf(const pbes_system::pbes& pbes, bool merge_simple_expressions = true)
950{
951 return pbes_system::pbes2srf(pbes, merge_simple_expressions).equations().size() == pbes.equations().size() + 2;
952}
953
954} // namespace mcrl2
955
956#endif // MCRL2_PBES_SRF_PBES_H
Identifier generator that stores the identifiers of the context in a set. Using the operator()() and ...
\brief The and operator for pbes expressions
const pbes_expression & left() const
const pbes_expression & right() const
std::vector< pre_srf_summand< allow_ce > > m_summands
Definition srf_pbes.h:193
const propositional_variable & variable() const
Definition srf_pbes.h:211
const fixpoint_symbol & symbol() const
Definition srf_pbes.h:207
const std::vector< pre_srf_summand< allow_ce > > & summands() const
Definition srf_pbes.h:215
propositional_variable & variable()
Definition srf_pbes.h:213
pre_srf_equation(const fixpoint_symbol &sigma, const propositional_variable &variable, std::vector< pre_srf_summand< allow_ce > > summands, bool conjunctive)
Definition srf_pbes.h:197
void make_total(const pre_srf_summand< allow_ce > &true_summand, const pre_srf_summand< allow_ce > &false_summand)
Ensures that the equation is total, by adding the summands corresponding to true and false.
Definition srf_pbes.h:247
std::vector< pre_srf_summand< allow_ce > > & summands()
Definition srf_pbes.h:217
propositional_variable_instantiation m_initial_state
Definition srf_pbes.h:773
data::data_specification m_dataspec
Definition srf_pbes.h:771
pre_srf_pbes(const data::data_specification &dataspec, std::vector< pre_srf_equation< allow_ce > > equations, propositional_variable_instantiation initial_state)
Definition srf_pbes.h:778
std::vector< pre_srf_equation< allow_ce > > & equations()
Definition srf_pbes.h:788
const std::vector< pre_srf_equation< allow_ce > > & equations() const
Definition srf_pbes.h:786
propositional_variable_instantiation & initial_state()
Definition srf_pbes.h:792
const propositional_variable_instantiation & initial_state() const
Definition srf_pbes.h:790
std::vector< pre_srf_equation< allow_ce > > m_equations
Definition srf_pbes.h:772
void add_condition(const pbes_expression &f)
Definition srf_pbes.h:151
propositional_variable_instantiation & variable()
Definition srf_pbes.h:147
const propositional_variable_instantiation & variable() const
Definition srf_pbes.h:145
propositional_variable_instantiation m_X
Definition srf_pbes.h:118
const condition_type & condition() const
Definition srf_pbes.h:141
void add_variables(const data::variable_list &variables)
Definition srf_pbes.h:149
const data::variable_list & parameters() const
Definition srf_pbes.h:137
pbes_expression to_pbes(bool conjunctive) const
Definition srf_pbes.h:163
pre_srf_summand(data::variable_list parameters, const pbes_expression &condition, propositional_variable_instantiation X)
Definition srf_pbes.h:121
\brief The existential quantification operator for pbes expressions
const pbes_expression & body() const
static fixpoint_symbol nu()
Returns the nu symbol.
fixpoint_symbol(const fixpoint_symbol &) noexcept=default
Move semantics.
\brief The universal quantification operator for pbes expressions
const pbes_expression & body() const
\brief The implication operator for pbes expressions
\brief The not operator for pbes expressions
not_(const pbes_expression &operand)
\brief Constructor Z14.
\brief The or operator for pbes expressions
const pbes_expression & left() const
const pbes_expression & right() const
pbes_equation(const fixpoint_symbol &symbol, const propositional_variable &variable, const pbes_expression &expr)
Constructor.
const propositional_variable & variable() const
Returns the pbes variable of the equation.
parameterized boolean equation system
Definition pbes.h:54
\brief A propositional variable instantiation
\brief A propositional variable declaration
propositional_variable(const propositional_variable &) noexcept=default
Move semantics.
const core::identifier_string & name() const
#define mCRL2log(LEVEL)
mCRL2log(LEVEL) provides the stream used to log.
Definition logger.h:393
Namespace for system defined sort bool_.
Definition bool.h:29
bool is_not_application(const atermpp::aterm &e)
Recogniser for application of !.
Definition bool.h:214
bool is_data_expression(const atermpp::aterm &x)
Test for a data_expression expression.
The namespace for accessor functions on pbes expressions.
const pbes_expression & arg(const pbes_expression &t)
Returns the pbes expression argument of expressions of type not, exists and forall.
detail::pre_srf_pbes< allow_ce > pbes2pre_srf(const pbes &p, bool merge_simple_expressions=true)
Converts a PBES into standard recursive form.
Definition srf_pbes.h:830
pbes_expression make_not(const pbes_expression &x)
Definition srf_pbes.h:38
std::vector< pre_srf_summand< allow_ce > > srf_and(const pbes_expression &phi, std::deque< pbes_equation > &equations, const pbes_equation &eqn, const data::variable_list &V, data::set_identifier_generator &id_generator, const core::identifier_string &X_true, const core::identifier_string &X_false, std::vector< pre_srf_equation< allow_ce > > &result, bool merge_simple_expressions)
Definition srf_pbes.h:712
std::vector< pre_srf_summand< allow_ce > > srf_or(const pbes_expression &phi, std::deque< pbes_equation > &equations, const pbes_equation &eqn, const data::variable_list &V, data::set_identifier_generator &id_generator, const core::identifier_string &X_true, const core::identifier_string &X_false, std::vector< pre_srf_equation< allow_ce > > &result, bool merge_simple_expressions)
Definition srf_pbes.h:482
pbes_expression make_disjunction(Iterator first, Iterator last)
Definition srf_pbes.h:73
std::ostream & operator<<(std::ostream &out, const pre_srf_summand< allow_ce > &summand)
Definition srf_pbes.h:181
pbes_expression make_conjunction(Iterator first, Iterator last)
Definition srf_pbes.h:52
pbes_expression distribute_not_over_and(const pbes_expression &x)
Assuming that x is of the form (x1 && x2 && ... xn), generates expression !x1 || !...
Definition srf_pbes.h:97
bool is_conjunctive(const pbes_expression &phi, bool allow_ce)
Definition srf_pbes.h:727
std::ostream & operator<<(std::ostream &out, const pre_srf_equation< allow_ce > &eqn)
Definition srf_pbes.h:261
const pbes_expression & true_()
bool is_not(const atermpp::aterm &x)
bool is_exists(const atermpp::aterm &x)
srf_pbes_with_ce pbes2pre_srf(const pbes &p, bool merge_simple_expressions=true)
Converts a PBES into pre standard recursive form.
Definition srf_pbes.h:935
bool is_or(const atermpp::aterm &x)
srf_pbes pre_srf2srfpbes(const srf_pbes_with_ce &p)
Converts a pre-SRF PBES into standard recursive form. Note that the counter example information of th...
Definition srf_pbes.h:902
bool is_forall(const atermpp::aterm &x)
srf_pbes pbes2srf(const pbes &p, bool merge_simple_expressions=true)
Converts a PBES into standard recursive form.
Definition srf_pbes.h:942
bool is_propositional_variable_instantiation(const atermpp::aterm &x)
bool is_and(const atermpp::aterm &x)
const pbes_expression & false_()
bool is_srf(const pbes_system::pbes &pbes, bool merge_simple_expressions=true)
Definition srf_pbes.h:949
const core::identifier_string & X_true
Definition srf_pbes.h:528
void apply(const propositional_variable_instantiation &x)
Definition srf_pbes.h:682
std::vector< pre_srf_equation< allow_ce > > & result
Definition srf_pbes.h:532
void apply(const pbes_expression &x)
Definition srf_pbes.h:688
std::deque< pbes_equation > & equations
Definition srf_pbes.h:517
srf_and_traverser(std::deque< pbes_equation > &equations_, const pbes_equation &eqn_, const data::variable_list &V_, data::set_identifier_generator &id_generator_, const core::identifier_string &X_true_, const core::identifier_string &X_false_, std::vector< pre_srf_equation< allow_ce > > &result_, bool merge_simple_expressions)
Definition srf_pbes.h:541
const core::identifier_string & X_false
Definition srf_pbes.h:529
data::set_identifier_generator & id_generator
Definition srf_pbes.h:525
std::vector< pre_srf_summand< allow_ce > > summands
Definition srf_pbes.h:535
std::deque< pbes_equation > & equations
Definition srf_pbes.h:291
std::vector< pre_srf_summand< allow_ce > > summands
Definition srf_pbes.h:309
std::vector< pre_srf_equation< allow_ce > > & result
Definition srf_pbes.h:306
const core::identifier_string & X_true
Definition srf_pbes.h:302
srf_or_traverser(std::deque< pbes_equation > &equations_, const pbes_equation &eqn_, const data::variable_list &V_, data::set_identifier_generator &id_generator_, const core::identifier_string &X_true_, const core::identifier_string &X_false_, std::vector< pre_srf_equation< allow_ce > > &result_, bool merge_simple_expressions)
Definition srf_pbes.h:315
const core::identifier_string & X_false
Definition srf_pbes.h:303
void apply(const pbes_expression &x)
Definition srf_pbes.h:458
data::set_identifier_generator & id_generator
Definition srf_pbes.h:299
void apply(const propositional_variable_instantiation &x)
Definition srf_pbes.h:452
subsitute_counterexample(bool replace_Lplus, bool replace_Lminus)
A rewriter that simplifies boolean expressions in a term.