12#ifndef MCRL2_PBES_PBESINST_LAZY_H
13#define MCRL2_PBES_PBESINST_LAZY_H
22#include "mcrl2/utilities/detail/container_utility.h"
23#include "mcrl2/atermpp/standard_containers/deque.h"
24#include "mcrl2/atermpp/standard_containers/indexed_set.h"
25#include "mcrl2/data/substitution_utility.h"
26#include "mcrl2/pbes/detail/bes_equation_limit.h"
27#include "mcrl2/pbes/detail/instantiate_global_variables.h"
28#include "mcrl2/pbes/pbes_equation_index.h"
29#include "mcrl2/pbes/pbes_expression.h"
30#include "mcrl2/pbes/pbessolve_options.h"
31#include "mcrl2/pbes/remove_equations.h"
32#include "mcrl2/pbes/replace_constants_by_variables.h"
33#include "mcrl2/pbes/rewriters/enumerate_quantifiers_rewriter.h"
34#include "mcrl2/pbes/rewriters/one_point_rule_rewriter.h"
35#include "mcrl2/pbes/rewriters/simplify_quantifiers_rewriter.h"
36#include "mcrl2/pbes/structure_graph.h"
37#include "mcrl2/pbes/transformation_strategy.h"
38#include "mcrl2/pbes/transformations.h"
54 std::unordered_set<propositional_variable_instantiation> tmp(todo.begin(), todo.end());
55 return tmp.size() == todo.size();
99 template <
typename FwdIter,
bool ThreadSafe>
102 const atermpp::indexed_set<propositional_variable_instantiation, ThreadSafe>& discovered,
103 const std::size_t thread_index)
107 for (FwdIter i = first; i != last; ++i)
109 if (!contains(discovered, *i, thread_index))
116 void set_todo(atermpp::deque<propositional_variable_instantiation>& new_todo)
127 return out <<
"todo = " << core::detail::print_list(todo.elements()) << std::endl;
175 if (equation_count > 0 && equation_count % 1000 == 0)
177 std::ostringstream out;
178 out <<
"Generated " << equation_count <<
" BES equations" << std::endl;
190 pbes_system::detail::instantiate_global_variables(p);
193 for (pbes_equation& eqn: p.equations())
196 pbes_expression aux = simplify_rewriter(eqn.formula());
197 pbes_expression aux1 = one_point_rule_rewriter(aux);
198 pbes_expression aux2 = order_quantified_variables(aux1,p.data());
199 eqn.formula() = aux2;
236 return data::rewriter(pbesspec.data(),
242 return data::rewriter(pbesspec.data(),
m_options.rewrite_strategy);
255 std::optional<data::rewriter> rewriter =
std::
nullopt
287 result = todo.front();
292 result = todo.back();
299 return m_pbes.equations()[i].symbol();
311 return true_false_substitution(symbol, X);
314 return pbes_system::no_substitution();
333 std::atomic<std::size_t>& number_of_active_processes,
334 data::mutable_indexed_substitution<> sigma,
342 mCRL2log(log::debug) <<
"Start thread " << thread_index <<
".\n";
350 while (number_of_active_processes > 0)
352 m_todo_access.lock();
353 while (!todo.elements().empty() && !m_must_abort)
356 std::size_t local_current_prune_round = global_current_prune_round;
357 if (std::optional<std::string> message = status_message(m_iteration_count))
362 detail::check_bes_equation_limit(m_iteration_count);
365 m_todo_access.unlock();
367 std::size_t index = m_equation_index.index(X_e.name());
368 const pbes_equation& eqn = m_pbes.equations()[index];
369 const auto& phi = eqn.formula();
370 data::add_assignments(sigma, eqn.variable().parameters(), X_e.parameters());
371 R(psi_e, phi, sigma, phi_substitution(thread_index, eqn.symbol(), X_e, phi));
372 R.clear_identifier_generator();
373 data::remove_assignments(sigma, eqn.variable().parameters());
376 m_todo_access.lock();
378 rewrite_psi(thread_index, psi_e, eqn.symbol(), X_e, tmp);
379 m_todo_access.unlock();
381 std::set<propositional_variable_instantiation> occ = find_propositional_variable_instantiations(psi_e);
384 std::size_t k = m_equation_index.rank(X_e.name());
385 m_todo_access.lock();
391 if (local_current_prune_round == global_current_prune_round)
393 mCRL2log(log::debug) <<
"generated equation " << X_e <<
" = " << psi_e
394 <<
" with rank " << k << std::endl;
395 on_report_equation(thread_index, X_e, psi_e, k);
396 todo.insert(occ.begin(), occ.end(), discovered, thread_index);
397 for (
const propositional_variable_instantiation& i : occ)
399 std::ignore = discovered.insert(i, thread_index);
401 on_discovered_elements(occ);
403 if (solution_found(init))
409 m_todo_access.unlock();
415 number_of_active_processes--;
416 std::this_thread::sleep_for(std::chrono::milliseconds(100));
417 if (number_of_active_processes > 0)
419 number_of_active_processes++;
425 mCRL2log(log::debug) <<
"Stop thread " << thread_index <<
".\n";
432 m_iteration_count = 0;
434 const std::size_t number_of_threads = m_options.number_of_threads;
435 const std::size_t initialisation_thread_index = (number_of_threads==1?0:1);
436 std::atomic<std::size_t> number_of_active_processes = number_of_threads;
437 std::vector<std::thread> threads;
439 data::mutable_indexed_substitution<> sigma;
442 pbes_system::replace_constants_by_variables(m_pbes, datar, sigma);
445 init = atermpp::down_cast<propositional_variable_instantiation>(m_global_R(m_pbes.initial_state(), sigma));
447 std::ignore = discovered.insert(init, initialisation_thread_index);
449 if (number_of_threads>1)
451 threads.reserve(number_of_threads);
452 for (std::size_t i = 1; i <= number_of_threads; ++i)
454 std::thread tr([&, i](){
457 number_of_active_processes,
462 threads.push_back(std::move(tr));
465 for (std::size_t i = 1; i <= number_of_threads; ++i)
473 const std::size_t single_thread_index=0;
474 run_thread(single_thread_index,
476 number_of_active_processes,
483 mCRL2log(log::verbose) <<
"Generated " << m_iteration_count <<
" BES equations" << std::endl;
488 return m_equation_index;
Rewriter that operates on data expressions.
Component for selecting a subset of equations that are actually used in an encompassing specification...
bool is_mu() const
Returns true if the symbol is mu.
A rewriter that applies one point rule quantifier elimination to a PBES.
parameterized boolean equation system
A PBES instantiation algorithm that uses a lazy strategy.
const pbes_equation_index & equation_index() const
const pbessolve_options & m_options
Algorithm options.
void next_todo(propositional_variable_instantiation &result)
const data::rewriter & data_rewriter() const
virtual void on_report_equation(const std::size_t, const propositional_variable_instantiation &, const pbes_expression &, std::size_t)
Reports BES equations that are produced by the algorithm. This function is called for every BES equat...
virtual void on_end_while_loop()
This function is called right after the while loop is finished.
virtual bool solution_found(const propositional_variable_instantiation &) const
virtual ~pbesinst_lazy_algorithm()=default
virtual void rewrite_psi(const std::size_t, pbes_expression &result, const fixpoint_symbol &symbol, const propositional_variable_instantiation &X, const pbes_expression &psi)
pbes preprocess(const pbes &x) const
pbesinst_lazy_algorithm(const pbessolve_options &options, const pbes &p, std::optional< data::rewriter > rewriter=std::nullopt)
Constructor.
utilities::mutex m_todo_access
data::rewriter construct_rewriter(const pbes &pbesspec)
pbesinst_lazy_todo todo
The propositional variable instantiations that need to be handled.
volatile bool m_must_abort
propositional_variable_instantiation init
The initial value (after rewriting).
virtual std::function< pbes_expression(const propositional_variable_instantiation &)> phi_substitution(const std::size_t, const fixpoint_symbol &symbol, const propositional_variable_instantiation &X, const pbes_expression &)
virtual void on_discovered_elements(const std::set< propositional_variable_instantiation > &)
This function is called when new elements are added to discovered.
std::size_t m_iteration_count
std::size_t global_current_prune_round
virtual void run()
Runs the algorithm. The result is obtained by calling the function get_result.
pbes_equation_index m_equation_index
A lookup map for PBES equations.
enumerate_quantifiers_rewriter m_global_R
The rewriter.
const fixpoint_symbol & symbol(std::size_t i) const
virtual std::optional< std::string > status_message(std::size_t equation_count)
enumerate_quantifiers_rewriter & rewriter()
data::rewriter datar
Data rewriter.
atermpp::indexed_set< propositional_variable_instantiation, true > discovered
The propositional variable instantiations that have been discovered (not necessarily handled)....
virtual void run_thread(const std::size_t thread_index, pbesinst_lazy_todo &todo, std::atomic< std::size_t > &number_of_active_processes, data::mutable_indexed_substitution<> sigma, enumerate_quantifiers_rewriter R)
atermpp::deque< propositional_variable_instantiation > todo
const propositional_variable_instantiation & back() const
void insert(const propositional_variable_instantiation &x)
bool check_invariants() const
const propositional_variable_instantiation & front() const
const atermpp::deque< propositional_variable_instantiation > & elements() const
void set_todo(atermpp::deque< propositional_variable_instantiation > &new_todo)
void insert(FwdIter first, FwdIter last, const atermpp::indexed_set< propositional_variable_instantiation, ThreadSafe > &discovered, const std::size_t thread_index)
\brief A propositional variable instantiation
#define mCRL2log(LEVEL)
mCRL2log(LEVEL) provides the stream used to log.
const pbes_expression & true_()
std::ostream & operator<<(std::ostream &out, const pbesinst_lazy_todo &todo)
partial_solve_strategy
Enumeration of partial strategies for solving PBESs.
const pbes_expression & false_()
An attempt for improving the efficiency.
void thread_initialise()
Initialises this rewriter with thread dependent information.
pbes_expression operator()(const propositional_variable_instantiation &Y) const
true_false_substitution(const fixpoint_symbol &symbol, const propositional_variable_instantiation &X)
const propositional_variable_instantiation & X
const fixpoint_symbol & symbol
search_strategy exploration_strategy
bool replace_constants_by_variables
partial_solve_strategy optimization
bool remove_unused_rewrite_rules
A rewriter that simplifies boolean expressions and quantifiers, and rewrites data expressions.