12#ifndef MCRL2_DATA_ENUMERATOR_H
13#define MCRL2_DATA_ENUMERATOR_H
15#include <boost/iterator/iterator_facade.hpp>
35 for (
const auto & set_element : set_elements)
37 if (function_index % 2 == 1)
41 function_index = function_index / 2;
48 const std::size_t argument_index,
49 const std::vector<data_expression_vector>& data_domain_expressions,
53 if (argument_index == data_domain_expressions.size())
55 std::size_t result_expression_index = function_index % codomain_expressions.
size();
56 function_index = function_index / codomain_expressions.size();
57 return codomain_expressions[result_expression_index];
62 for (
auto i = current_enumerated_elements.rbegin(); i != current_enumerated_elements.rend(); ++i)
64 if (i == current_enumerated_elements.rbegin())
66 result =
make_if_expression_(function_index, argument_index + 1, data_domain_expressions, codomain_expressions, parameters);
73 result =
if_(
equal_to(parameters[argument_index], *i), lhs, result);
81template <
class Rewriter,
class MutableSubstitution>
91 if (all_element_expressions.size() >= 32)
95 if (all_element_expressions.size() > 16)
97 mCRL2log(
log::warning) <<
"Generate 2^" << all_element_expressions.size() <<
" sets to enumerate sort " << sort <<
"\n";
100 for (std::size_t i = 0; i < number_of_sets; ++i)
108template <
class Rewriter>
118 std::vector<data_expression_vector> domain_expressions;
119 std::size_t total_domain_size = 1;
125 total_domain_size = total_domain_size * domain_expressions.back().size();
126 function_parameters.emplace_back(id_generator(), s);
136 mCRL2log(
log::warning) <<
"Generate " << codomain_expressions.size() <<
"^" << total_domain_size <<
" functions to enumerate sort " << sort <<
"\n";
139 function_parameter_list =
variable_list(function_parameters.begin(), function_parameters.end());
141 const std::size_t number_of_functions =
utilities::power_size_t(codomain_expressions.size(), total_domain_size);
143 if (number_of_functions == 1)
149 for (std::size_t i = 0; i < number_of_functions; ++i)
151 std::size_t function_index = i;
158template <
typename Rewriter>
162 std::list<sort_expression>& parents)
183 return dataspec.
is_certainly_finite(atermpp::down_cast<container_sort>(sort).element_sort()) &&
189 if (constructors.empty())
195 if (std::find(parents.begin(), parents.end(), sort) != parents.end())
199 parents.push_back(sort);
200 bool result = std::all_of(constructors.begin(), constructors.end(), [&](
const function_symbol& constructor)
202 return !is_function_sort(constructor.sort()) ||
203 std::all_of(atermpp::down_cast<function_sort>(constructor.sort()).domain().begin(), atermpp::down_cast<function_sort>(constructor.sort()).domain().end(),
204 [&](const sort_expression& arg_sort){ return is_enumerable(dataspec, rewr, arg_sort, parents); });
221template <
typename Rewriter>
224 std::list<sort_expression> parentstack;
225 return detail::is_enumerable(dataspec, rewr, sort, parentstack);
229template <
typename Expression = data::data_expression>
244 : v(
std::move(v_)), phi(phi_)
249 const Expression& phi_,
252 : v(
std::move(v_)), phi(phi_)
257 const Expression& phi_,
262 : v(
std::move(v_)), phi(phi_)
288 phi = data::undefined_data_expression();
295 return phi != data::undefined_data_expression();
333 const Expression& phi_,
346template <
typename Expression = data::data_expression>
366 const Expression& phi,
370 m_variables(elem.m_variables),
371 m_expressions(elem.m_expressions)
378 const Expression& phi,
384 m_variables(elem.m_variables),
385 m_expressions(elem.m_expressions)
392 template <
typename VariableList,
typename MutableSubstitution,
typename Rewriter>
404 template <
typename VariableList,
typename MutableSubstitution>
415 template <
typename VariableList,
typename Rewriter>
432 void mark(std::stack<std::reference_wrapper<atermpp::detail::_aterm>>& todo)
const
442 const Expression& phi,
457 const Expression& phi,
466template <
typename Expression>
471 for (
auto i = variables.begin(); i != variables.end(); ++i)
473 if (i != variables.begin())
477 out << *i <<
": " << i->sort();
479 return out <<
"], " << p.
expression() <<
" }";
482template <
typename Expression>
487 for (
auto i = variables.begin(); i != variables.end(); ++i)
489 if (i != variables.begin())
493 out << *i <<
": " << i->sort();
499template <
typename EnumeratorListElement>
530#ifdef MCRL2_LOG_ENUMERATOR
531 std::cout <<
"push_back " << x << std::endl;
536 template <
class... Args>
539#ifdef MCRL2_LOG_ENUMERATOR
540 std::cout <<
"emplace_back " << EnumeratorListElement(args...) << std::endl;
560 const EnumeratorListElement&
front()
const
570 const EnumeratorListElement&
back()
const
590 template <
class... Args>
593 m_enumerator_element_cache.set(args...);
594 return m_enumerator_element_cache;
599template <
typename Rewriter = data::rewriter,
typename DataRewriter = data::rewriter>
610 const DataRewriter&
r;
621#ifdef MCRL2_ENUMERATOR_COUNT_REWRITE_CALLS
622 mutable std::size_t rewrite_calls = 0;
627 std::ostringstream out;
628 out << x <<
": " << x.
sort();
632 template <
typename Expression,
typename MutableSubstitution>
634 Expression
rewrite(
const Expression& phi, MutableSubstitution&
sigma)
const
636#ifdef MCRL2_ENUMERATOR_COUNT_REWRITE_CALLS
639 return const_cast<Rewriter&
>(R)(phi,
sigma);
642 template <
typename Expression,
typename MutableSubstitution>
644 void rewrite(Expression& result,
const Expression& phi, MutableSubstitution&
sigma)
const
646#ifdef MCRL2_ENUMERATOR_COUNT_REWRITE_CALLS
649 const_cast<Rewriter&
>(R)(result, phi,
sigma);
655 const DataRewriter& datar_,
657 bool accept_solutions_with_variables,
658 std::size_t max_count = (std::numeric_limits<std::size_t>::max)()
663 id_generator(id_generator_),
664 m_max_count(max_count),
665 m_accept_solutions_with_variables(accept_solutions_with_variables)
672#ifdef MCRL2_ENUMERATOR_COUNT_REWRITE_CALLS
673 std::cout <<
"number of enumerator rewrite calls: " << rewrite_calls << std::endl;
679 id_generator.
clear();
682 template <
typename T>
701 template <
typename EnumeratorListElement,
702 typename MutableSubstitution,
703 typename ReportSolution,
704 typename Reject = always_false<typename EnumeratorListElement::expression_type>,
705 typename Accept = always_false<typename EnumeratorListElement::expression_type>
708 MutableSubstitution&
sigma,
709 ReportSolution report_solution,
710 Reject reject = Reject(),
711 Accept accept = Accept()
715 const EnumeratorListElement& p = P.
front();
718 const typename EnumeratorListElement::expression_type& phi,
740 const typename EnumeratorListElement::expression_type& phi,
750 bool added_variables_empty = added_variables.empty() || (P.
scratch_expression == phi && m_accept_solutions_with_variables);
751 if ((accept(P.
scratch_expression) && m_accept_solutions_with_variables) || (variables.
empty() && added_variables_empty))
756 if (added_variables_empty)
768 const auto& phi = p.expression();
781 const auto& v1 = v.front();
782 const auto& v_tail = v.tail();
783 const auto& v1_sort = v1.sort();
789 else if (data::is_function_sort(v1_sort))
791 const function_sort& function = atermpp::down_cast<function_sort>(v1_sort);
796 bool result = detail::compute_finite_function_sorts(function, id_generator, dataspec, r, function_sorts, function_parameter_list);
799 throw mcrl2::runtime_error(
"Sort " + data::pp(v1_sort) +
" has too many elements to enumerate.");
805 if (add_element(v_tail, phi, v1, f))
814 throw mcrl2::runtime_error(
"Cannot enumerate elements of function sort " + data::pp(v1_sort) +
".");
817 else if (sort_set::is_set(v1_sort))
819 const sort_expression& element_sort = atermpp::down_cast<container_sort>(v1_sort).element_sort();
823 const variable fset_variable(id_generator(), sort_fset::fset(element_sort));
824 data_expression e = sort_set::constructor(element_sort, lambda_term, fset_variable);
826 if (add_element_with_variables(v_tail, { fset_variable }, phi, v1, e))
837 else if (sort_fset::is_fset(v1_sort))
839 const auto& fset = atermpp::down_cast<container_sort>(v1_sort);
843 bool result = detail::compute_finite_set_elements(fset, dataspec, r,
sigma, set_elements, id_generator);
846 throw mcrl2::runtime_error(
"Finite set sort " + data::pp(v1_sort) +
" has too many elements to enumerate.");
852 if (add_element(v_tail, phi, v1, e))
861 throw mcrl2::runtime_error(
"Cannot enumerate elements of finite set sort " + data::pp(v1_sort) +
".");
864 else if (sort_bag::is_bag(v1_sort))
868 else if (sort_fbag::is_fbag(v1_sort))
870 throw mcrl2::runtime_error(
"Cannot enumerate elements of finite bag sort " + data::pp(v1_sort) +
".");
879 if (data::is_function_sort(c.sort()))
881 const sort_expression_list& domain = atermpp::down_cast<data::function_sort>(c.sort()).domain();
911 throw mcrl2::runtime_error(
"Cannot enumerate elements of sort " + data::pp(v1_sort) +
" without constructors.");
930 template <
typename EnumeratorListElement,
931 typename MutableSubstitution,
932 typename ReportSolution,
933 typename Reject = always_false<typename EnumeratorListElement::expression_type>,
934 typename Accept = always_false<typename EnumeratorListElement::expression_type>
937 MutableSubstitution&
sigma,
938 ReportSolution report_solution,
939 Reject reject = Reject(),
940 Accept accept = Accept()
943 std::size_t count = 0;
946 if (count++ >= m_max_count)
950 if (enumerate_front(P,
sigma, report_solution, reject, accept))
971 template <
typename EnumeratorListElement,
972 typename MutableSubstitution,
973 typename ReportSolution,
974 typename Reject = always_false<typename EnumeratorListElement::expression_type>,
975 typename Accept = always_false<typename EnumeratorListElement::expression_type>
978 MutableSubstitution&
sigma,
979 ReportSolution report_solution,
980 Reject reject = Reject(),
981 Accept accept = Accept()
985 return enumerate_all(P,
sigma, report_solution, reject, accept);
1000 template <
typename EnumeratorListElement,
1001 typename MutableSubstitution,
1002 typename ReportSolution,
1003 typename Reject = always_false<typename EnumeratorListElement::expression_type>,
1004 typename Accept = always_false<typename EnumeratorListElement::expression_type>
1007 const typename EnumeratorListElement::expression_type& cond,
1008 MutableSubstitution&
sigma,
1009 ReportSolution report_solution,
1010 Reject reject = Reject(),
1011 Accept accept = Accept()
1016 return enumerate_all(P,
sigma, report_solution, reject, accept);
1031template <
class Rewriter>
1034 const Rewriter& rewr,
1037 typedef typename Rewriter::term_type term_type;
1041 bool accept_solutions_with_variables =
false;
1047 E.template enumerate<enumerator_element>(
1051 [&](
const enumerator_element& p)
1053 p.add_assignments(v_list,
sigma, rewr);
1054 result.push_back(
sigma(v));
1066template <
class Rewriter>
1069 const Rewriter& rewr)
size_type size() const
Returns the number of arguments of this term.
A deque class in which aterms can be stored.
reference emplace_back(Args &&... args)
void push_back(const T &value)
super::size_type size_type
const_iterator end() const
Returns a const_iterator pointing to the end of the term_list.
const Term & front() const
Returns the first element of the list.
const_iterator begin() const
Returns a const_iterator pointing to the beginning of the term_list.
bool empty() const
Returns true if the list's size is 0.
void push_front(const Term &el)
Inserts a new element at the beginning of the current list.
An abstraction expression.
An application of a data expression to a number of arguments.
const sort_expression & element_sort() const
bool is_certainly_finite(const sort_expression &s) const
Checks whether a sort is certainly finite.
const function_symbol_vector & constructors() const
Gets all constructors including those that are system defined.
Rewriter interface class.
An enumerator algorithm that generates solutions of a condition.
void rewrite(Expression &result, const Expression &phi, MutableSubstitution &sigma) const
enumerator_identifier_generator & id_generator
std::size_t m_max_count
max_count The enumeration is aborted after max_count iterations
std::size_t enumerate(const EnumeratorListElement &p, MutableSubstitution &sigma, ReportSolution report_solution, Reject reject=Reject(), Accept accept=Accept()) const
Enumerates the element p. Solutions are reported using the callback function report_solution....
void reset_id_generator()
enumerator_algorithm(const enumerator_algorithm< Rewriter, DataRewriter > &)=delete
std::size_t enumerate(const variable_list &vars, const typename EnumeratorListElement::expression_type &cond, MutableSubstitution &sigma, ReportSolution report_solution, Reject reject=Reject(), Accept accept=Accept()) const
Enumerates the variables v for condition c. Solutions are reported using the callback function report...
std::size_t max_count() const
bool enumerate_front(enumerator_queue< EnumeratorListElement > &P, MutableSubstitution &sigma, ReportSolution report_solution, Reject reject=Reject(), Accept accept=Accept()) const
Enumerates the front element of the todo list P. The enumeration is interrupted when report_solution ...
std::string print(const data::variable &x) const
bool m_accept_solutions_with_variables
If true, solutions with a non-empty list of variables may be reported.
const data::data_specification & dataspec
A data specification.
std::size_t enumerate_all(enumerator_queue< EnumeratorListElement > &P, MutableSubstitution &sigma, ReportSolution report_solution, Reject reject=Reject(), Accept accept=Accept()) const
Enumerates until P is empty. Solutions are reported using the callback function report_solution....
enumerator_algorithm(const Rewriter &R_, const data::data_specification &dataspec_, const DataRewriter &datar_, enumerator_identifier_generator &id_generator_, bool accept_solutions_with_variables, std::size_t max_count=(std::numeric_limits< std::size_t >::max)())
Expression rewrite(const Expression &phi, MutableSubstitution &sigma) const
An element for the todo list of the enumerator that collects the substitution corresponding to the ex...
enumerator_list_element_with_substitution(const data::variable_list &v, const Expression &phi, const enumerator_list_element_with_substitution< Expression > &elem, const data::variable &d, const data::data_expression &e)
Constructs the element (v, phi, e.sigma[v := x])
data::data_expression_list assign_expressions(const VariableList &v, const Rewriter &rewriter) const
Returns the right hand sides corresponding to the variables v.
enumerator_list_element_with_substitution(const data::variable_list &v, const Expression &phi)
Constructs the element (v, phi, [])
void remove_assignments(const VariableList &v, MutableSubstitution &result) const
Removes the assignments corresponding with this element from the substitution result.
void set(const data::variable_list &v, const Expression &phi, const enumerator_list_element_with_substitution< Expression > &elem, const data::variable &d, const data::data_expression &e)
Set the variable ands and the expression explicitly as the element (v, phi, e.sigma[v := x]).
data::variable_list m_variables
Expression expression_type
data::data_expression_list m_expressions
void add_assignments(const VariableList &v, MutableSubstitution &result, const Rewriter &rewriter) const
Adds the assignments that correspond with this element to the substitution result.
void set(const data::variable_list &v, const Expression &phi, const enumerator_list_element_with_substitution< Expression > &elem)
Set the variable ands and the expression explicitly as the element (v, phi, e.sigma[v := x]).
void mark(std::stack< std::reference_wrapper< atermpp::detail::_aterm > > &todo) const
The following function is needed to mark the aterms in this class, when elements of this class are us...
data::enumerator_substitution sigma() const
enumerator_list_element_with_substitution(const data::variable_list &v, const Expression &phi, const enumerator_list_element_with_substitution< Expression > &elem)
Constructs the element (v, phi, e.sigma[v := x])
enumerator_list_element_with_substitution()=default
Default constructor.
The default element for the todo list of the enumerator.
enumerator_list_element(data::variable_list v_, const Expression &phi_, const enumerator_list_element &, const data::variable &, const data::data_expression &)
Constructs the element (v, phi)
void set(const data::variable_list &v_, const Expression &phi_)
Set the variables and the condition explicitly.
enumerator_list_element(data::variable_list v_, const Expression &phi_)
Constructs the element (v, phi)
enumerator_list_element(data::variable_list v_, const Expression &phi_, const enumerator_list_element &)
Constructs the element (v, phi)
bool is_valid() const
Returns true if the element is valid. If it becomes false, this is used to signal that the enumeratio...
void set(const data::variable_list &v_, const Expression &phi_, const enumerator_list_element &, const data::variable &, const data::data_expression &)
Set the variable ands and the expression explicitly as the element (v, phi, e.sigma[v := x]).
Expression & expression()
enumerator_list_element()=default
Default constructor.
Expression expression_type
void mark(atermpp::term_mark_stack &todo) const
The following function is needed to mark the aterms in this class, when elements of this class are us...
void set(const data::variable_list &v_, const Expression &phi_, const enumerator_list_element &)
Set the variables and the condition explicitly.
void invalidate()
Invalidates the element, by giving phi an undefined value.
const data::variable_list & variables() const
const Expression & expression() const
Contains the enumerator queue.
atermpp::deque< EnumeratorListElement > P
atermpp::deque< EnumeratorListElement >::size_type size() const
enumerator_queue()=default
Default constructor.
const EnumeratorListElement & enumerator_element_cache(const Args &... args)
atermpp::deque< EnumeratorListElement >::size_type size_type
EnumeratorListElement::expression_type scratch_expression
variable_list scratch_variable_list
const EnumeratorListElement & back() const
void push_back(const EnumeratorListElement &x)
void emplace_back(Args &&... args)
EnumeratorListElement m_enumerator_element_cache
EnumeratorListElement & back()
EnumeratorListElement & front()
enumerator_queue(const EnumeratorListElement &value)
Initializes the enumerator queue with the given value.
EnumeratorListElement value_type
data_expression scratch_data_expression
const EnumeratorListElement & front() const
const sort_expression & codomain() const
const sort_expression_list & domain() const
\brief Binder for lambda abstraction
Generic substitution function.
Rewriter that operates on data expressions.
const sort_expression & sort() const
Standard exception class for reporting runtime errors.
add your file description here.
add your file description here.
static RewriterCompilingJitty::substitution_type & sigma(RewriterCompilingJitty *this_rewriter)
static void rewrite(data_expression &result, const data_expression &t, RewriterCompilingJitty *this_rewriter)
#define mCRL2log(LEVEL)
mCRL2log(LEVEL) provides the stream used to log.
_aterm * address(const unprotected_aterm_core &t)
void make_term_list(term_list< Term > &target)
Make an empty list and put it in target;.
std::stack< std::reference_wrapper< detail::_aterm > > term_mark_stack
data_expression make_if_expression_(std::size_t &function_index, const std::size_t argument_index, const std::vector< data_expression_vector > &data_domain_expressions, const data_expression_vector &codomain_expressions, const variable_vector ¶meters)
bool is_enumerable(const data_specification &dataspec, const Rewriter &rewr, const sort_expression &sort, std::list< sort_expression > &parents)
data_expression make_set_(std::size_t function_index, const sort_expression &element_sort, const data_expression_vector &set_elements)
bool compute_finite_function_sorts(const function_sort &sort, enumerator_identifier_generator &id_generator, const data::data_specification &dataspec, Rewriter datar, data_expression_vector &result, variable_list &function_parameter_list)
Computes the elements of a finite function sort, and puts them in result. If there are too many eleme...
bool compute_finite_set_elements(const container_sort &sort, const data_specification &dataspec, Rewriter datar, MutableSubstitution &sigma, data_expression_vector &result, enumerator_identifier_generator &id_generator)
Computes the elements of a finite set sort, and puts them in result. If there are too many elements,...
bool is_bag(const sort_expression &e)
Recogniser for sort expression Bag(s)
bool is_fbag(const sort_expression &e)
Recogniser for sort expression FBag(s)
function_symbol insert(const sort_expression &s)
Constructor for function symbol @fset_insert.
bool is_fset(const sort_expression &e)
Recogniser for sort expression FSet(s)
function_symbol empty(const sort_expression &s)
Constructor for function symbol {}.
bool is_set(const sort_expression &e)
Recogniser for sort expression Set(s)
std::vector< variable > variable_vector
\brief vector of variables
data_expression_vector enumerate_expressions(const sort_expression &s, const data_specification &dataspec, const Rewriter &rewr, enumerator_identifier_generator &id_generator)
Returns a vector with all expressions of sort s.
std::vector< data_expression > data_expression_vector
\brief vector of data_expressions
atermpp::term_list< variable > variable_list
\brief list of variables
bool is_function_sort(const atermpp::aterm &x)
Returns true if the term t is a function sort.
data_expression normalize_sorts(const data_expression &x, const data::sort_specification &sortspec)
function_symbol equal_to(const sort_expression &s)
Constructor for function symbol ==.
std::vector< function_symbol > function_symbol_vector
\brief vector of function_symbols
function_symbol if_(const sort_expression &s)
Constructor for function symbol if.
std::size_t power_size_t(const std::size_t n_in, const std::size_t m_in)
std::size_t ceil_log2(std::size_t n)
A class that takes a linear process specification and checks all tau-summands of that LPS for conflue...
bool operator()(const T &)
enumerator_error(const std::string &message)
Substitution that stores the assignments as a sequence of variables and a sequence of expressions....