12#ifndef MCRL2_PBES_SRF_PBES_H
13#define MCRL2_PBES_SRF_PBES_H
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"
42 return atermpp::down_cast<pbes_expression>(data::sort_bool::arg(atermpp::down_cast<data::data_expression>(x)));
51template <
typename Iterator>
65 make_and_(result, result, *it);
72template <
typename Iterator>
86 make_or_(result, result, *it);
99 std::set<pbes_expression> conjuncts = split_and(x);
100 std::set<pbes_expression> disjuncts;
102 for (
const pbes_expression& conjunct : conjuncts)
104 disjuncts.insert(make_not(conjunct));
106 return make_disjunction(disjuncts.begin(), disjuncts.end());
111template <
bool allow_ce>
127 if constexpr (!allow_ce)
129 m_condition = detail::pbes2data(condition);
133 m_condition = condition;
149 void add_variables(
const data::variable_list& variables) { m_parameters = variables + m_parameters; }
153 if constexpr (allow_ce)
155 m_condition = pbes_system::and_(f, m_condition);
159 m_condition = data::and_(pbes2data(f), m_condition);
171 return make_forall_(m_parameters, or_(distribute_not_over_and(atermpp::down_cast<pbes_expression>(m_condition)), m_X));
175 return make_exists_(m_parameters, and_(atermpp::down_cast<pbes_expression>(m_condition), m_X));
180template <
bool allow_ce>
183 return out <<
"variables = " << core::detail::print_list(summand.parameters()) <<
" f = " << summand.condition()
184 <<
" X = " << summand.variable();
187template <
bool allow_ce>
199 std::vector<pre_srf_summand<allow_ce>> summands,
225 if (is_counter_example_variable(variable()))
227 if (is_counter_example_positive(variable().name()))
237 std::vector<pbes_expression> v;
238 for (
const auto& summand : m_summands)
240 v.push_back(summand.to_pbes(m_conjunctive));
242 pbes_expression rhs = m_conjunctive ? join_and(v.begin(), v.end()) : join_or(v.begin(), v.end());
251 m_summands.push_back(true_summand);
255 m_summands.push_back(false_summand);
260template <
bool allow_ce>
263 out <<
"srf equation" << std::endl;
264 for (
const auto& summand : eqn.summands())
266 out << summand << std::endl;
271template <
bool allow_ce>
282template <
bool allow_ce>
317 const data::variable_list& V_,
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)
337 std::size_t size = summands.size();
339 for (
auto i = summands.begin() + size; i != summands.end(); ++i)
341 i->add_condition(x.left());
346 std::size_t size = summands.size();
348 for (
auto i = summands.begin() + size; i != summands.end(); ++i)
350 i->add_condition(x.right());
358 equations.emplace_front(eqn.symbol(), X1, x);
359 summands.emplace_back(data::variable_list(),
361 propositional_variable_instantiation(X1.name(), data::make_data_expression_list(V)));
370 return super::apply(x);
373 mCRL2log(log::trace) <<
"Or expression " << x <<
"\n";
376 std::set<pbes_expression> clauses = split_or(x,
false);
378 std::vector<pbes_expression> simple_clauses;
379 for (
const auto& clause : clauses)
381 if (m_merge_simple_expressions && is_simple_expression(clause,
false))
383 simple_clauses.emplace_back(clause);
388 if (simple_clauses.empty())
395 pbes_expression condition = make_disjunction(simple_clauses.begin(), simple_clauses.end());
396 mCRL2log(log::trace) <<
"Simple condition " << condition <<
"\n";
398 for (
const auto& clause : clauses)
400 if (!m_merge_simple_expressions || !is_simple_expression(clause,
false))
402 mCRL2log(log::trace) <<
"Clause " << clause <<
"\n";
403 std::size_t size = summands.size();
405 for (
auto i = summands.begin() + size; i != summands.end(); ++i)
407 i->add_condition(detail::make_not(condition));
416 std::vector<pre_srf_summand<allow_ce>> body_summands = srf_or(x.body(),
424 m_merge_simple_expressions);
425 for (
auto& summand : body_summands)
427 summand.add_variables(x.variables());
429 summands.insert(summands.end(), body_summands.begin(), body_summands.end());
434 if (is_simple_expression(x
.body(), allow_ce))
438 summands.emplace_back(x.variables(), f, X);
445 equations.emplace_front(eqn.symbol(), X1, x);
446 summands.emplace_back(data::variable_list(),
448 propositional_variable_instantiation(X1.name(), data::make_data_expression_list(V)));
455 summands.emplace_back(data::variable_list(), f, x);
460 if (is_simple_expression(x, allow_ce))
464 summands.emplace_back(data::variable_list(), f, X);
473 throw mcrl2::runtime_error(
"srf_or_traverser::apply(not_) unsupported term " + pbes_system::pp(x));
477 throw mcrl2::runtime_error(
"srf_or_traverser::apply(imp) unsupported term " + pbes_system::pp(x));
481template<
bool allow_ce>
492 srf_or_traverser<allow_ce> f(equations, eqn, V, id_generator, X_true, X_false, result, merge_simple_expressions);
494 return std::move(f.summands);
497template<
bool allow_ce>
508template<
bool allow_ce>
543 const data::variable_list& V_,
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)
563 std::size_t size = summands.size();
565 for (
auto i = summands.begin() + size; i != summands.end(); ++i)
567 i->add_condition(detail::make_not(x.left()));
572 std::size_t size = summands.size();
574 for (
auto i = summands.begin() + size; i != summands.end(); ++i)
576 i->add_condition(detail::make_not(x.right()));
584 equations.emplace_front(eqn.symbol(), X1, x);
585 summands.emplace_back(data::variable_list(),
587 propositional_variable_instantiation(X1.name(), data::make_data_expression_list(V)));
599 mCRL2log(log::trace) <<
"Expression " << x <<
"\n";
602 std::set<pbes_expression> clauses = split_and(x,
false);
604 std::vector<pbes_expression> simple_clauses;
608 for (
const auto& clause : clauses)
610 if (m_merge_simple_expressions && is_simple_expression(clause,
false))
612 simple_clauses.emplace_back(clause);
617 if (simple_clauses.empty())
625 pbes_expression condition = make_conjunction(simple_clauses.begin(), simple_clauses.end());
626 mCRL2log(log::trace) <<
"Simple condition " << condition <<
"\n";
629 for (
const auto& clause : clauses)
631 if (!m_merge_simple_expressions || !is_simple_expression(clause,
false))
633 mCRL2log(log::trace) <<
"Clause " << clause <<
"\n";
634 std::size_t size = summands.size();
636 for (
auto i = summands.begin() + size; i != summands.end(); ++i)
638 i->add_condition(condition);
646 std::vector<pre_srf_summand<allow_ce>> body_summands = srf_and(x.body(),
654 m_merge_simple_expressions);
655 for (
auto& summand : body_summands)
657 summand.add_variables(x.variables());
659 summands.insert(summands.end(), body_summands.begin(), body_summands.end());
664 if (is_simple_expression(x
.body(), allow_ce))
668 summands.emplace_back(x.variables(), f, X);
675 equations.emplace_front(eqn.symbol(), X1, x);
676 summands.emplace_back(data::variable_list(),
678 propositional_variable_instantiation(X1.name(), data::make_data_expression_list(V)));
685 summands.emplace_back(data::variable_list(), f, x);
690 if (is_simple_expression(x, allow_ce))
694 summands.emplace_back(data::variable_list(), detail::make_not(f), X);
703 throw mcrl2::runtime_error(
"srf_and_traverser::apply(not_) unsupported term " + pbes_system::pp(x));
707 throw mcrl2::runtime_error(
"srf_and_traverser::apply(imp) unsupported term " + pbes_system::pp(x));
711template<
bool allow_ce>
722 srf_and_traverser f(equations, eqn, V, id_generator, X_true, X_false, result, merge_simple_expressions);
724 return std::move(f.summands);
729 if (is_simple_expression(phi, allow_ce))
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()));
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())));
758 throw mcrl2::runtime_error(
"is_conjunctive: unexpected case " + pbes_system::pp(phi));
767template <
bool allow_ce>
779 std::vector<pre_srf_equation<allow_ce>> equations,
800 std::vector<pbes_equation> v;
801 for (
const auto& eqn : equations())
803 v.push_back(eqn.to_pbes());
805 return pbes(m_dataspec, std::set<data::variable>(), v, m_initial_state);
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++)
818 m_equations[i].make_total(true_summand, false_summand);
829template<
bool allow_ce>
833 for (
const core::identifier_string& id : pbes_system::find_identifiers(p))
835 id_generator.add_identifier(id);
838 core::identifier_string X_false = id_generator(
"X_false");
839 core::identifier_string X_true = id_generator(
"X_true");
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, {})
);
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);
852 std::vector<detail::pre_srf_equation<allow_ce>> srf_equations;
853 while (!equations.empty())
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(),
861 eqn.variable().parameters(),
866 merge_simple_expressions)
867 : detail::srf_or(eqn.formula(),
870 eqn.variable().parameters(),
875 merge_simple_expressions);
876 srf_equations.emplace_back(eqn.symbol(), eqn.variable(), summands, is_conjunctive);
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()),
908 std::vector<detail::pre_srf_equation<
false>> equations;
909 for (
const auto& equation : p.equations())
911 if (!detail::is_counter_example_equation(equation.to_pbes()))
913 std::vector<detail::pre_srf_summand<
false>> summands;
914 for (
const auto& summand : equation.summands())
916 pbes_expression result;
917 f.apply(result, summand.variable());
918 propositional_variable_instantiation variable = atermpp::down_cast<propositional_variable_instantiation>(simplify(result));
920 f.apply(result, summand.condition());
922 summands.emplace_back(summand.parameters(), simplify(result), variable);
925 equations.emplace_back(equation.symbol(), equation.variable(), summands, equation.is_conjunctive());
929 return srf_pbes(p.data(), equations, p.initial_state());
937 return detail::pbes2pre_srf<
true>(p, merge_simple_expressions);
942inline srf_pbes
pbes2srf(
const pbes& p,
bool merge_simple_expressions =
true)
944 return detail::pbes2pre_srf<
false>(p, merge_simple_expressions);
951 return pbes_system::pbes2srf(pbes, merge_simple_expressions).equations().size() == pbes.equations().size() + 2;
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
const propositional_variable & variable() const
pbes_equation to_pbes() const
const fixpoint_symbol & symbol() const
const std::vector< pre_srf_summand< allow_ce > > & summands() const
propositional_variable & variable()
pre_srf_equation(const fixpoint_symbol &sigma, const propositional_variable &variable, std::vector< pre_srf_summand< allow_ce > > summands, bool conjunctive)
propositional_variable m_variable
fixpoint_symbol & symbol()
bool is_conjunctive() const
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.
std::vector< pre_srf_summand< allow_ce > > & summands()
propositional_variable_instantiation m_initial_state
data::data_specification m_dataspec
pre_srf_pbes(const data::data_specification &dataspec, std::vector< pre_srf_equation< allow_ce > > equations, propositional_variable_instantiation initial_state)
std::vector< pre_srf_equation< allow_ce > > & equations()
const std::vector< pre_srf_equation< allow_ce > > & equations() const
propositional_variable_instantiation & initial_state()
const propositional_variable_instantiation & initial_state() const
std::vector< pre_srf_equation< allow_ce > > m_equations
data::variable_list & parameters()
void add_condition(const pbes_expression &f)
condition_type & condition()
propositional_variable_instantiation & variable()
condition_type m_condition
const propositional_variable_instantiation & variable() const
propositional_variable_instantiation m_X
const condition_type & condition() const
void add_variables(const data::variable_list &variables)
data::variable_list m_parameters
const data::variable_list & parameters() const
pbes_expression to_pbes(bool conjunctive) const
pre_srf_summand(data::variable_list parameters, const pbes_expression &condition, propositional_variable_instantiation X)
\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
\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.
Namespace for system defined sort bool_.
bool is_not_application(const atermpp::aterm &e)
Recogniser for application of !.
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.
pbes_expression make_not(const pbes_expression &x)
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)
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)
pbes_expression make_disjunction(Iterator first, Iterator last)
std::ostream & operator<<(std::ostream &out, const pre_srf_summand< allow_ce > &summand)
pbes_expression make_conjunction(Iterator first, Iterator last)
pbes_expression distribute_not_over_and(const pbes_expression &x)
Assuming that x is of the form (x1 && x2 && ... xn), generates expression !x1 || !...
bool is_conjunctive(const pbes_expression &phi, bool allow_ce)
std::ostream & operator<<(std::ostream &out, const pre_srf_equation< allow_ce > &eqn)
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.
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...
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.
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)
const core::identifier_string & X_true
const data::variable_list & V
void apply(const propositional_variable_instantiation &x)
std::vector< pre_srf_equation< allow_ce > > & result
const pbes_equation & eqn
void apply(const pbes_expression &x)
std::deque< pbes_equation > & equations
bool m_merge_simple_expressions
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)
void apply(const forall &x)
void apply(const and_ &x)
void apply(const exists &x)
void apply(const not_ &x)
const core::identifier_string & X_false
data::set_identifier_generator & id_generator
std::vector< pre_srf_summand< allow_ce > > summands
std::deque< pbes_equation > & equations
std::vector< pre_srf_summand< allow_ce > > summands
void apply(const and_ &x)
void apply(const not_ &x)
bool m_merge_simple_expressions
void apply(const exists &x)
const data::variable_list & V
void apply(const forall &x)
std::vector< pre_srf_equation< allow_ce > > & result
const pbes_equation & eqn
const core::identifier_string & X_true
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)
const core::identifier_string & X_false
void apply(const pbes_expression &x)
data::set_identifier_generator & id_generator
void apply(const propositional_variable_instantiation &x)
subsitute_counterexample(bool replace_Lplus, bool replace_Lminus)
A rewriter that simplifies boolean expressions in a term.