13#ifndef MCRL2_PBES_PBESINST_ALTERNATIVE_LAZY_ALGORITHM_H
14#define MCRL2_PBES_PBESINST_ALTERNATIVE_LAZY_ALGORITHM_H
16#include "mcrl2/pbes/remove_level.h"
17#include "mcrl2/pbes/detail/check_well_formed_bes.h"
18#include "mcrl2/pbes/pbesinst_algorithm.h"
19#include "mcrl2/pbes/search_strategy.h"
20#include "mcrl2/pbes/transformation_strategy.h"
81 using namespace mcrl2;
86 const and_& pa=atermpp::down_cast<and_>(p);
92 const or_& po=atermpp::down_cast<or_>(p);
98 const imp& pi=atermpp::down_cast<imp>(p);
104 return not_(pbes_expression_order_quantified_variables(atermpp::down_cast<not_>(p).operand(),data_spec));
108 const forall& pf=atermpp::down_cast<forall>(p);
110 return make_forall_(mcrl2::data::order_variables_to_optimise_enumeration(pf.variables(),data_spec),expr);
114 const exists& pe=atermpp::down_cast<exists>(p);
116 return make_exists_(mcrl2::data::order_variables_to_optimise_enumeration(pe.variables(),data_spec),expr);
199 const std::size_t nr_of_generated_variables,
200 const std::size_t todo_size)
const
202 static time_t last_log_time = time(
nullptr) - 1;
203 time_t new_log_time=0;
204 if (time(&new_log_time) > last_log_time)
206 last_log_time = new_log_time;
207 mCRL2log(mcrl2::log::status) <<
"Processed " << nr_of_processed_variables <<
208 " and generated " << nr_of_generated_variables <<
209 " boolean variables";
210 if (m_maximum_todo_size != std::numeric_limits<std::size_t>::max())
212 mCRL2log(mcrl2::log::status) <<
" with a todo buffer of size " << todo_size <<
". \n";
216 mCRL2log(mcrl2::log::status) <<
". \n";
236 search_strategy search_strategy = breadth_first,
237 transformation_strategy transformation_strategy = lazy,
240 const bool approximate_true =
true)
252 time_t t=time(
nullptr);
253 for (; t == time(
nullptr);)
257 srand((
unsigned)time(
nullptr));
271 assert(todo.size()==todo_set.size());
290 if (todo.size()<m_maximum_todo_size)
297 ++m_elements_not_stored_in_todo_buffer;
298 if ((rand() % (todo.size() + m_elements_not_stored_in_todo_buffer)) < todo.size())
300 std::size_t index = rand() % (todo.size());
302 equation[Y]=(m_approximate_true?false_():true_());
303 trivial[Y]=equation[Y];
304 instantiations[equation_index[Y.name()]].push_back(Y);
312 equation[X]=(m_approximate_true?false_():true_());
313 instantiations[equation_index[X.name()]].push_back(X);
314 trivial[X]=equation[X];
321 return ranks[equation_index[X.name()]];
324 template <
bool is_mu>
329 std::unordered_map<propositional_variable_instantiation,
bool>& visited)
342 else if (get_rank(Y) != rank)
346 if (visited.count(Y))
350 if (equation.count(Y) == 0)
355 bool b = find_loop_rec<is_mu>(equation[Y], X, rank, visited);
364 const and_& expra=atermpp::down_cast<and_>(expr);
365 return find_loop_rec<is_mu>(expra.left(), X, rank, visited) ||
366 find_loop_rec<is_mu>(expra.right(), X, rank, visited);
370 const or_& expro=atermpp::down_cast<or_>(expr);
371 return find_loop_rec<is_mu>(expro.left(), X, rank, visited) &&
372 find_loop_rec<is_mu>(expro.right(), X, rank, visited);
379 const and_& expra=atermpp::down_cast<and_>(expr);
380 return find_loop_rec<is_mu>(expra.left(), X, rank, visited) &&
381 find_loop_rec<is_mu>(expra.right(), X, rank, visited);
385 const or_& expro=atermpp::down_cast<or_>(expr);
386 return find_loop_rec<is_mu>(expro.left(), X, rank, visited) ||
387 find_loop_rec<is_mu>(expro.right(), X, rank, visited);
393 template <
bool is_mu>
396 std::unordered_map<propositional_variable_instantiation,
bool> visited;
397 return find_loop_rec<is_mu>(expr, X, get_rank(X), visited);
402 if (m_erase_unused_bes_variables==pbes_system::none)
411 std::unordered_set<propositional_variable_instantiation> reachable;
416 for(std::vector<propositional_variable_instantiation>& vec: instantiations)
420 assert(instantiations.size()==0 || instantiations[0].size()==0);
423 std::stack<pbes_expression> stack;
426 while (!stack.empty())
428 const pbes_expression expr = stack.top();
431 if (is_propositional_variable_instantiation(expr))
433 const propositional_variable_instantiation& X = atermpp::vertical_cast<propositional_variable_instantiation>(expr);
434 if (reachable.count(X) == 0)
436 if (equation.count(X)>0)
438 stack.push(equation[X]);
447 else if (is_and(expr))
449 const and_& expra=atermpp::down_cast<and_>(expr);
450 stack.push(expra.left());
451 stack.push(expra.right());
453 else if (is_or(expr))
455 const or_& expro=atermpp::down_cast<or_>(expr);
456 stack.push(expro.left());
457 stack.push(expro.right());
461 std::unordered_map<propositional_variable_instantiation, pbes_expression> new_equations;
462 for (
const auto& i: equation)
465 if (reachable.count(i.first) > 0
466 || (m_erase_unused_bes_variables == pbes_system::some && (is_true(i.second) || is_false(i.second))))
468 new_equations.insert(i);
469 std::size_t index = equation_index[i.first.name()];
470 instantiations[index].push_back(i.first);
471 std::set<propositional_variable_instantiation> rhs_variables
472 = find_propositional_variable_instantiations(i.second);
473 for (
const propositional_variable_instantiation& v: rhs_variables)
475 occurrence[v].insert(i.first);
480 equation.swap(new_equations);
493 const std::unordered_map<propositional_variable_instantiation, pbes_expression>::const_iterator i=
494 trivial.find(atermpp::down_cast<propositional_variable_instantiation>(p));
495 if (i!=trivial.end() && (is_true(i->second) || is_false(i->second)))
497 return pbes_expression_pair(p,i->second);
499 return pbes_expression_pair(p,p);
503 return pbes_expression_pair(p,p);
507 const and_& pa=atermpp::down_cast<and_>(p);
508 const pbes_expression_pair lhs=simplify_pbes_expression(pa.left(),trivial);
509 const pbes_expression_pair rhs=simplify_pbes_expression(pa.right(),trivial);
510 if (is_false(lhs.second))
514 if (is_false(rhs.second))
518 if (is_true(lhs.second))
520 return pbes_expression_pair(and_(lhs.first,rhs.first),rhs.second);
522 if (is_true(rhs.second))
524 return pbes_expression_pair(and_(lhs.first,rhs.first),lhs.second);
526 return pbes_expression_pair(and_(lhs.first,rhs.first),and_(lhs.first,rhs.first));
529 const or_& po=atermpp::down_cast<or_>(p);
530 const pbes_expression_pair lhs=simplify_pbes_expression(po.left(),trivial);
531 const pbes_expression_pair rhs=simplify_pbes_expression(po.right(),trivial);
532 if (is_true(lhs.second))
536 if (is_true(rhs.second))
540 if (is_false(lhs.second))
542 return pbes_expression_pair(or_(lhs.first,rhs.first),rhs.second);
544 if (is_false(rhs.second))
546 return pbes_expression_pair(or_(lhs.first,rhs.first),lhs.second);;
548 return pbes_expression_pair(or_(lhs.first,rhs.first),or_(lhs.first,rhs.first));
560 std::size_t regeneration_count=regeneration_count_init;
561 pbes_system::detail::instantiate_global_variables(p);
563 std::vector<pbes_equation>& pbes_equations = p.equations();
574 for (pbes_equation& eq: pbes_equations)
576 eq.formula() = pbes_expression_order_quantified_variables(one_point_rule_rewriter(simplify_rewriter(eq.formula())), m_data_spec);
580 std::size_t eqn_index = 0;
581 ranks.resize(pbes_equations.size());
582 instantiations.resize(pbes_equations.size());
583 for (
const pbes_equation& eqn: pbes_equations)
585 equation_index[eqn.variable().name()] = eqn_index;
586 symbols.push_back(eqn.symbol());
589 ranks[eqn_index] = ranks[eqn_index-1] + (symbols[eqn_index] == symbols[eqn_index-1] ? 0 : 1);
594 init = atermpp::down_cast<propositional_variable_instantiation>(R(p.initial_state()));
596 while (!todo.empty())
598 const propositional_variable_instantiation X_e = next_todo();
599 std::size_t index = equation_index[X_e.name()];
600 instantiations[index].push_back(X_e);
602 const pbes_equation& eqn = pbes_equations[index];
603 data::rewriter::substitution_type sigma;
604 make_pbesinst_substitution(eqn.variable().parameters(), X_e.parameters(), sigma);
605 const pbes_expression& phi = eqn.formula();
606 pbes_expression psi_e = R(phi, sigma);
607 R.clear_identifier_generator();
610 check_whether_argument_is_a_well_formed_bes(psi_e);
612 catch (mcrl2::runtime_error& e)
614 throw mcrl2::runtime_error(
"Generated boolean equation system is not well formed.\n" + std::string(e.what()));
616 pbes_expression rewritten_psi_e;
618 if (m_transformation_strategy >= optimize)
621 pbes_expression_pair p=simplify_pbes_expression(psi_e,trivial);
623 rewritten_psi_e=p.second;
627 rewritten_psi_e=psi_e;
630 equation[X_e] = psi_e;
632 if (m_transformation_strategy >= on_the_fly_with_fixed_points)
635 if (eqn.symbol() == fixpoint_symbol::mu())
637 if (find_loop<
true>(psi_e, X_e))
639 rewritten_psi_e = false_();
644 if (find_loop<
false>(psi_e, X_e))
646 rewritten_psi_e = true_();
654 std::set<propositional_variable_instantiation> psi_variables = find_propositional_variable_instantiations(psi_e);
655 for (
const propositional_variable_instantiation& v: psi_variables)
657 if (todo_set.count(v) == 0 && equation.count(v) == 0)
661 occurrence[v].insert(X_e);
664 if (m_transformation_strategy >= optimize && (is_true(rewritten_psi_e) || is_false(rewritten_psi_e)))
666 trivial[X_e] = rewritten_psi_e;
667 if (m_transformation_strategy >= on_the_fly)
672 std::stack<propositional_variable_instantiation> new_trivials;
673 new_trivials.push(X_e);
674 while (!new_trivials.empty())
676 const propositional_variable_instantiation X = new_trivials.top();
679 const std::unordered_set<propositional_variable_instantiation> oc = occurrence[X];
680 std::unordered_map<propositional_variable_instantiation, pbes_expression> trivial_X;
681 trivial_X[X] = psi_e;
682 for (
const propositional_variable_instantiation& Y: oc)
684 pbes_expression_pair p=simplify_pbes_expression(equation[Y],trivial);
686 const pbes_expression f=p.second;
687 if (is_true(f) || is_false(f))
690 new_trivials.push(Y);
698 if (m_transformation_strategy >= on_the_fly)
700 if (--regeneration_count == 0 || trivial.count(init)>0 )
702 regeneration_count = equation.size() / 2;
707 print_equation_count(equation.size(), equation.size()+todo.size(), todo.size());
708 detail::check_bes_equation_limit(equation.size());
718 mCRL2log(log::verbose) <<
"Generated " << equation.size() <<
" BES equations in total, generating BES" << std::endl;
720 std::size_t index = 0;
721 const std::unordered_map<propositional_variable_instantiation,propositional_variable_instantiation>
722 pv_renaming = detail::create_pv_renaming(instantiations,short_rename_scheme);
723 detail::rename_pbesinst_consecutively renamer(pv_renaming);
724 for (
const std::vector<propositional_variable_instantiation>& vec: instantiations)
726 const fixpoint_symbol symbol = symbols[index++];
727 for (
const propositional_variable_instantiation& X_e: vec)
729 const propositional_variable lhs = propositional_variable(renamer(X_e).name(), data::variable_list());
730 const pbes_expression rhs = replace_propositional_variables(equation[X_e], renamer);
731 result.equations().emplace_back(symbol, lhs, rhs);
732 mCRL2log(log::debug) <<
"BESEquation: " << atermpp::aterm(symbol) <<
" " << lhs <<
" = " << rhs << std::endl;
Rewriter that operates on data expressions.
\brief The and operator for pbes expressions
and_(const pbes_expression &left, const pbes_expression &right)
\brief Constructor Z14.
const pbes_expression & left() const
const pbes_expression & right() const
\brief The existential quantification operator for pbes expressions
const pbes_expression & body() const
\brief The universal quantification operator for pbes expressions
const pbes_expression & body() const
\brief The implication operator for pbes expressions
const pbes_expression & left() const
imp(const pbes_expression &left, const pbes_expression &right)
\brief Constructor Z14.
const pbes_expression & right() const
A rewriter that applies one point rule quantifier elimination to a PBES.
\brief The or operator for pbes expressions
const pbes_expression & left() const
or_(const pbes_expression &left, const pbes_expression &right)
\brief Constructor Z14.
const pbes_expression & right() const
parameterized boolean equation system
propositional_variable_instantiation & initial_state()
Returns the initial state.
An alternative lazy algorithm for instantiating a PBES, ported from bes_deprecated....
pbes_expression_pair simplify_pbes_expression(const pbes_expression &p, const std::unordered_map< propositional_variable_instantiation, pbes_expression > &trivial)
bool find_loop_rec(const pbes_expression &expr, propositional_variable_instantiation X, std::size_t rank, std::unordered_map< propositional_variable_instantiation, bool > &visited)
propositional_variable_instantiation next_todo()
void add_todo(const propositional_variable_instantiation &X)
const data::rewriter & m_datar
Data rewriter.
propositional_variable_instantiation init
The initial value.
static const std::size_t regeneration_count_init
Initial value for regeneration_period.
std::vector< fixpoint_symbol > symbols
symbols[i] contains the fixedpoint symbol of the i-th equation in the PBES.
std::unordered_map< core::identifier_string, std::size_t > equation_index
A lookup map for PBES equations.
std::size_t m_elements_not_stored_in_todo_buffer
void run(pbes &p)
Runs the algorithm. The result is obtained by calling the function get_result.
enumerate_quantifiers_rewriter R
The rewriter.
const mcrl2::pbes_system::remove_level m_erase_unused_bes_variables
bool find_loop(pbes_expression expr, propositional_variable_instantiation X)
const data::data_specification & m_data_spec
search_strategy m_search_strategy
The search strategy to use when exploring the state space.
transformation_strategy m_transformation_strategy
Transformation strategy.
pbesinst_alternative_lazy_algorithm(const data::data_specification &data_spec, const data::rewriter &datar, search_strategy search_strategy=breadth_first, transformation_strategy transformation_strategy=lazy, const mcrl2::pbes_system::remove_level erase_unused_bes_variables=mcrl2::pbes_system::none, const std::size_t maximum_todo_size=std::numeric_limits< std::size_t >::max(), const bool approximate_true=true)
Constructor.
void print_equation_count(const std::size_t nr_of_processed_variables, const std::size_t nr_of_generated_variables, const std::size_t todo_size) const
Prints a log message for every 1000-th equation.
std::unordered_map< propositional_variable_instantiation, pbes_expression > trivial
Map a variable instantiations to its right hand side when the latter is trivial (either true or false...
std::deque< propositional_variable_instantiation > todo
Propositional variable instantiations that need to be handled.
const bool m_approximate_true
const std::size_t m_maximum_todo_size
The maximum size that the todo buffer is allowed to have.
std::size_t get_rank(const propositional_variable_instantiation &X)
std::unordered_set< propositional_variable_instantiation > todo_set
The content of todo as a set.
enumerate_quantifiers_rewriter & rewriter()
std::unordered_map< propositional_variable_instantiation, pbes_expression > equation
Map a variable instantiation to its right hand side.
pbes get_result(bool short_rename_scheme=true)
Returns the computed bes in pbes format.
std::unordered_map< propositional_variable_instantiation, std::unordered_set< propositional_variable_instantiation > > occurrence
Map a variable instantiation to a set of other variable instantiations on whose right hand sides it a...
std::vector< std::size_t > ranks
ranks[i] contains the rank of the i-th equation in the PBES.
\brief A propositional variable instantiation
#define mCRL2log(LEVEL)
mCRL2log(LEVEL) provides the stream used to log.
std::unordered_map< propositional_variable_instantiation, propositional_variable_instantiation > create_pv_renaming(std::vector< std::vector< propositional_variable_instantiation > > &instantiations, bool short_renaming_scheme)
bool is_pbes_exists(const pbes_expression &t)
Returns true if the term t is an existential quantification.
bool is_pbes_not(const pbes_expression &t)
Returns true if the term t is a not expression.
bool is_pbes_forall(const pbes_expression &t)
Returns true if the term t is a universal quantification.
bool is_or(const atermpp::aterm &x)
bool is_pbes_or(const pbes_expression &t)
Returns true if the term t is an or expression.
bool is_false(const pbes_expression &t)
Test for the value false.
bool is_pbes_imp(const pbes_expression &t)
Returns true if the term t is an imp expression.
bool is_pbes_and(const pbes_expression &t)
Returns true if the term t is an and expression.
bool is_propositional_variable_instantiation(const atermpp::aterm &x)
mcrl2::pbes_system::pbes_expression pbes_expression_order_quantified_variables(const mcrl2::pbes_system::pbes_expression &p, const mcrl2::data::data_specification &data_spec)
bool is_and(const atermpp::aterm &x)
bool is_true(const pbes_expression &t)
Test for the value true.
An attempt for improving the efficiency.
A rewriter that simplifies boolean expressions and quantifiers, and rewrites data expressions.