11#include "mcrl2/data/detail/rewrite/jitty.h"
12#include "mcrl2/data/detail/rewrite/jitty_jittyc.h"
13#include "mcrl2/data/detail/enumerator_iteration_limit.h"
15#ifdef MCRL2_ENABLE_JITTYC
16#include "mcrl2/data/detail/rewrite/jittyc.h"
19#include "mcrl2/data/detail/rewrite/with_prover.h"
21#include "mcrl2/data/detail/rewriter_wrapper.h"
22#include "mcrl2/data/enumerator.h"
24using namespace mcrl2::
core;
26using namespace mcrl2::log;
52 find_all_if(e,is_a_variable(),std::inserter(s,s.begin()));
64 substitution_type& sigma)
69 mutable_map_substitution<std::map < variable,data_expression> > variable_renaming;
70 bool rewrite_stack_too_big_exception_thrown=
false;
73 for (
const assignment& a: assignments)
75 const variable& v=a.lhs();
76 const variable v_fresh(m_generator(), v.sort());
77 variable_renaming[v]=v_fresh;
78 sigma[v_fresh]=rewrite(a.rhs(),sigma);
80 rewrite(result, replace_variables(body,variable_renaming),sigma);
84 rewrite_stack_too_big_exception_thrown=
true;
88 for (mutable_map_substitution<std::map < variable,data_expression> >::const_iterator it=variable_renaming.begin();
89 it!=variable_renaming.end(); ++it)
91 sigma[atermpp::down_cast<variable>(it->second)]=it->second;
93 if (rewrite_stack_too_big_exception_thrown)
102 const variable_list& vl,
104 substitution_type& sigma,
105 const bool body_in_normal_form)
113 std::size_t number_of_renamed_variables=0;
115 std::vector<variable> new_variables(vl.size());
119 for(
const variable& v: vl)
121 if (sigma(v)!=v || sigma.variable_occurs_in_a_rhs(v))
123 number_of_renamed_variables++;
124 new_variables[count]=data::variable(m_generator(), v.sort());
125 assert(occur_check(v, new_variables[count]));
129 new_variables[count]=v;
135 if (number_of_renamed_variables==0)
137 make_abstraction(result,lambda_binder(),vl,(body_in_normal_form?body:rewrite(body,sigma)));
142 variable_list::const_iterator v;
143 if (body_in_normal_form)
147 mutable_map_substitution<std::map<variable,data_expression> > variable_renaming;
148 for(v = vl.begin(), count = 0; v != vl.end(); ++v, ++count)
150 if (*v != new_variables[count])
152 variable_renaming[*v] = new_variables[count];
155 result_aux = replace_variables(body, variable_renaming);
161 std::vector<data_expression> saved_substitutions;
162 for(v = vl.begin(), count = 0; v != vl.end(); ++v, ++count)
164 if (*v != new_variables[count])
166 saved_substitutions.push_back(sigma(*v));
167 sigma[*v] = new_variables[count];
171 bool rewrite_stack_too_big_exception_thrown=
false;
174 rewrite(result_aux,body,sigma);
178 rewrite_stack_too_big_exception_thrown=
true;
181 std::size_t new_variable_count = 0;
182 for(v = vl.begin(), count = 0; v != vl.end(); ++v, ++count)
184 if (*v != new_variables[count])
186 sigma[*v] = saved_substitutions[new_variable_count++];
189 if (rewrite_stack_too_big_exception_thrown)
194 variable_list new_variable_list(new_variables.begin(), new_variables.end());
195 make_abstraction(result, lambda_binder(),new_variable_list,result_aux);
208 substitution_type& sigma,
209 const bool arguments_are_in_normal_form )
213 const abstraction& ta=atermpp::down_cast<abstraction>(t);
214 rewrite_single_lambda(result,ta.variables(),ta.body(), sigma, arguments_are_in_normal_form);
218 const application ta(t);
220 rewrite_lambda_application(result,atermpp::down_cast<abstraction>(ta.head()),ta,sigma, arguments_are_in_normal_form);
233 const application& t,
234 substitution_type& sigma,
235 const bool arguments_are_in_normal_form )
240 std::size_t arity=t.size();
243 rewrite_single_lambda(result, vl, lambda_body, sigma, arguments_are_in_normal_form);
246 assert(vl.size()<=arity);
251 data_expression* vl_backup = MCRL2_SPECIFIC_STACK_ALLOCATOR(data_expression,vl.size());
254 for(std::size_t count=0; count<vl.size(); count++)
256 if (arguments_are_in_normal_form)
258 new (&vl_backup[count]) data_expression(t[count]);
262 new (&vl_backup[count]) data_expression(rewrite(t[count],sigma));
268 for(
const variable& v: vl)
270 const data_expression temp=sigma(v);
271 sigma[v]=vl_backup[count];
272 vl_backup[count]=temp;
276 bool rewrite_stack_too_big_exception_thrown=
false;
279 rewrite(result,lambda_body,sigma);
283 rewrite_stack_too_big_exception_thrown=
true;
288 for(
const variable& v: vl)
290 sigma[v]=vl_backup[count];
291 vl_backup[count].~data_expression();
294 if (rewrite_stack_too_big_exception_thrown)
299 if (vl.size()==arity)
306 make_application(result,
308 t.begin()+
static_cast<std::ptrdiff_t>(vl.size()),
310 [
this, arguments_are_in_normal_form, &sigma](data_expression& result,
const data_expression& t) ->
void
312 if (arguments_are_in_normal_form){ result=t;}
else { result=rewrite(t, sigma); }
322 substitution_type& sigma,
323 const bool t_is_normal_form )
329 existential_quantifier_enumeration(result, t.variables(), t.body(), sigma, t_is_normal_form);
338 const variable_list& vl,
340 substitution_type& sigma,
341 const bool t1_is_normal_form )
343 quantifier_enumeration(result, vl, t1, t1_is_normal_form, sigma, exists_binder(), &lazy::or_, sort_bool::false_(), sort_bool::true_());
351 substitution_type& sigma,
352 const bool t_is_normal_form )
355 universal_quantifier_enumeration(result, t.variables(),t.body(),sigma, t_is_normal_form);
364 const variable_list& vl,
366 substitution_type& sigma,
367 const bool t1_is_normal_form)
369 quantifier_enumeration(result, vl, t1, t1_is_normal_form, sigma, forall_binder(), &lazy::and_, sort_bool::true_(), sort_bool::false_());
375 const variable_list& vl,
377 const bool t1_is_normal_form,
378 substitution_type& sigma,
388 mutable_map_substitution<std::map < variable,data_expression> > variable_renaming;
389 variable_vector vl_new_v;
390 for(
const variable& v: vl)
392 if (sigma(v)!=v || sigma.variable_occurs_in_a_rhs(v))
394 const variable v_fresh(m_generator(), v.sort());
395 variable_renaming[v]=v_fresh;
396 vl_new_v.push_back(v_fresh);
400 vl_new_v.push_back(v);
408 std::set < variable > free_variables=find_free_variables(t3);
409 variable_list vl_new_l_enum;
410 variable_list vl_new_l_other;
412 bool sorts_are_finite=
true;
413 for (
const variable& v: std::ranges::reverse_view(vl_new_v))
415 if (free_variables.count(v)>0)
417 if (is_enumerable(m_data_specification_for_enumeration, rewriter_wrapper(
this), v.sort()))
419 vl_new_l_enum.push_front(v);
420 sorts_are_finite = sorts_are_finite && m_data_specification_for_enumeration.is_certainly_finite(v.sort());
424 vl_new_l_other.push_front(v);
429 if (vl_new_l_enum.empty())
431 if (vl_new_l_other.empty())
438 make_abstraction(result, binder, vl_new_l_other, t3);
448 const std::size_t max_count = sorts_are_finite || data::detail::get_enumerator_iteration_limit()==0?
449 std::numeric_limits<std::size_t>::max() :
450 data::detail::get_enumerator_iteration_limit();
453 enumerator_type enumerator(wrapped_rewriter, m_data_specification_for_enumeration,
454 wrapped_rewriter, m_generator,
false, max_count);
459 std::size_t count=enumerator.enumerate(enumerator_element(vl_new_l_enum, t3),
461 [&](
const enumerator_element& p)
463 partial_result = lazy_op(partial_result, p.expression());
464 return partial_result==absorbing_element;
466 [&identity_element](
const data_expression& d)->
bool {
return d==identity_element; },
467 [&absorbing_element](
const data_expression& d)->
bool {
return d==absorbing_element; }
470 if (count<=max_count)
472 if (vl_new_l_other.empty())
474 result
=partial_result;
479 make_abstraction(result,binder, vl_new_l_other, partial_result);
484 catch(
const mcrl2::runtime_error&)
493 make_abstraction(result, binder,vl_new_l_enum+vl_new_l_other,rewrite(t3,sigma));
501 const rewrite_strategy strategy)
505 case data::rewrite_strategy::jitty:
506 return std::shared_ptr<Rewriter>(
new RewriterJitty(data_spec,equations_selector));
507#ifdef MCRL2_ENABLE_JITTYC
508 case data::rewrite_strategy::jitty_compiling:
509 return std::shared_ptr<Rewriter>(
new RewriterCompilingJitty(data_spec,equations_selector));
511 case data::rewrite_strategy::jitty_prover:
512 return std::shared_ptr<Rewriter>(
new RewriterProver(data_spec,data::rewrite_strategy::jitty,equations_selector));
513#ifdef MCRL2_ENABLE_JITTYC
514 case data::rewrite_strategy::jitty_compiling_prover:
515 return std::shared_ptr<Rewriter>(
new RewriterProver(data_spec,data::rewrite_strategy::jitty_compiling,equations_selector));
517 default:
throw mcrl2::runtime_error(
"Cannot create a rewriter using strategy " + pp(strategy) +
".");
525 const application::const_iterator& end,
526 const std::set <variable>& vars,
527 std::set <variable>& used_vars)
531 check_vars(*begin++, vars, used_vars);
539 const application& a=atermpp::down_cast<application>(expr);
540 check_vars(a.head(),vars,used_vars);
541 check_vars(a.begin(),a.end(),vars,used_vars);
545 const variable& v=atermpp::down_cast<variable>(expr);
548 if (vars.count(v)==0)
559 const application::const_iterator& end)
563 checkPattern(*begin++);
571 if (is_variable(atermpp::down_cast<application>(p).head()))
573 throw mcrl2::runtime_error(std::string(
"variable ") + data::pp(application(p).head()) +
574 " is used as head symbol in an application, which is not supported");
576 const application& a=atermpp::down_cast<application>(p);
578 checkPattern(a.begin(),a.end());
584 const variable_list& rule_var_list = data_eqn
.variables();
585 const std::set <variable> rule_vars(rule_var_list.begin(),rule_var_list.end());
588 std::set <variable> lhs_vars;
591 check_vars(data_eqn.lhs(),rule_vars,lhs_vars);
596 mCRL2log(log::log_level_t::error) <<
"Data equation: " << data_expression(data_eqn) << std::endl;
598 throw runtime_error(
"variable " + pp(var) +
" occurs in left-hand side of equation but is not defined (in equation: " + pp(data_eqn) +
")");
604 std::set <variable> dummy;
605 check_vars(data_eqn.condition(),lhs_vars,dummy);
609 throw runtime_error(
"variable " + pp(var) +
" occurs in condition of equation but not in left-hand side (in equation: " +
610 pp(data_eqn) +
"); equation cannot be used as rewrite rule");
616 std::set <variable> dummy;
617 check_vars(data_eqn.rhs(),lhs_vars,dummy);
621 throw runtime_error(
"variable " + pp(var) +
" occurs in right-hand side of equation but not in left-hand side (in equation: " +
622 pp(data_eqn) +
"); equation cannot be used as rewrite rule");
628 throw runtime_error(
"left-hand side of equation is a variable; this is not allowed for rewriting");
634 catch (mcrl2::runtime_error& s)
636 throw runtime_error(std::string(s.what()) +
" (in equation: " + pp(data_eqn) +
"); equation cannot be used as rewrite rule");
647 catch (runtime_error&)
A unordered_map class in which aterms can be stored.
An abstraction expression.
const variable_list & variables() const
const data_expression & body() const
const data_expression & lhs() const
const variable_list & variables() const
data_expression & operator=(const data_expression &) noexcept=default
Rewriter interface class.
void rewrite_where(data_expression &result, const where_clause &term, substitution_type &sigma)
An enumerator algorithm that generates solutions of a condition.
The default element for the todo list of the enumerator.
Component for selecting a subset of equations that are actually used in an encompassing specification...
variable(const variable &) noexcept=default
Move semantics.
\brief A where expression
const assignment_list & assignments() const
const data_expression & body() const
#define mCRL2log(LEVEL)
mCRL2log(LEVEL) provides the stream used to log.
void CheckRewriteRule(const data_equation &data_eqn)
Check that an mCRL2 data equation is a valid rewrite rule. If not, an runtime_error is thrown indicat...
static void checkPattern(const data_expression &p)
static void check_vars(application::const_iterator begin, const application::const_iterator &end, const std::set< variable > &vars, std::set< variable > &used_vars)
bool isValidRewriteRule(const data_equation &data_eqn)
Check whether or not an mCRL2 data equation is a valid rewrite rule.
static bool occur_check(const variable &v, const atermpp::aterm &e)
static void checkPattern(application::const_iterator begin, const application::const_iterator &end)
static void check_vars(const data_expression &expr, const std::set< variable > &vars, std::set< variable > &used_vars)
bool is_application(const data_expression &t)
Returns true if the term t is an application.
bool is_forall(const atermpp::aterm &x)
Returns true if the term t is a universal quantification.
bool is_exists(const atermpp::aterm &x)
Returns true if the term t is an existential quantification.
bool is_lambda(const atermpp::aterm &x)
Returns true if the term t is a lambda abstraction.
bool is_variable(const atermpp::aterm &x)
Returns true if the term t is a variable.
bool operator()(const atermpp::aterm &t) const
rewriter_wrapper(Rewriter *r)