mCRL2
Loading...
Searching...
No Matches
rewrite.cpp
Go to the documentation of this file.
1// Author(s): Muck van Weerdenburg
2// Copyright: see the accompanying file COPYING or copy at
3// https://github.com/mCRL2org/mCRL2/blob/master/COPYING
4//
5// Distributed under the Boost Software License, Version 1.0.
6// (See accompanying file LICENSE_1_0.txt or copy at
7// http://www.boost.org/LICENSE_1_0.txt)
8
12
13#ifdef MCRL2_ENABLE_JITTYC
15#endif
16
18
21
22using namespace mcrl2::core;
23using namespace mcrl2::core::detail;
24using namespace mcrl2::log;
25
26namespace mcrl2
27{
28namespace data
29{
30namespace detail
31{
32
33#ifndef NDEBUG
34// function object to test if it is an aterm with function symbol "f"
36{
37 bool operator()(const atermpp::aterm& t) const
38 {
39 return is_variable(t);
40 }
41};
42
43static
44bool occur_check(const variable& v, const atermpp::aterm& e)
45{
46 if (v==e)
47 {
48 // The variable is reset. This is ok.
49 return true;
50 }
51 std::set<variable> s;
52 find_all_if(e,is_a_variable(),std::inserter(s,s.begin()));
53 if (s.count(v)>0)
54 {
55 return false; // Occur check failed.
56 }
57 return true;
58}
59#endif
60
62 const where_clause& term,
64{
65 data_expression result;
66 rewrite_where(result, term, sigma);
67 return result;
68}
69
71 data_expression& result,
72 const where_clause& term,
74{
75 const assignment_list& assignments = term.assignments();
76 const data_expression& body=term.body();
77
79 bool rewrite_stack_too_big_exception_thrown=false;
80 try
81 {
82 for (const assignment& a: assignments)
83 {
84 const variable& v=a.lhs();
85 const variable v_fresh(m_generator(), v.sort());
86 variable_renaming[v]=v_fresh;
87 sigma[v_fresh]=rewrite(a.rhs(),sigma);
88 }
89 rewrite(result, replace_variables(body,variable_renaming),sigma);
90 }
92 {
93 rewrite_stack_too_big_exception_thrown=true;
94 }
95
96 // Reset variables in sigma
97 for (mutable_map_substitution<std::map < variable,data_expression> >::const_iterator it=variable_renaming.begin();
98 it!=variable_renaming.end(); ++it)
99 {
100 sigma[atermpp::down_cast<variable>(it->second)]=it->second;
101 }
102 if (rewrite_stack_too_big_exception_thrown)
103 {
105 }
106 return;
107}
108
110 data_expression& result,
111 const variable_list& vl,
112 const data_expression& body,
113 const bool body_in_normal_form,
115{
116 assert(vl.size()>0);
117 // A lambda term without arguments; Take care that the bound variable is made unique with respect to
118 // the variables occurring in sigma. But in case vl is empty, just rewrite...
119
120 // First filter the variables in vl by those occuring as left/right hand sides in sigma.
121
122 std::size_t number_of_renamed_variables=0;
123 std::size_t count=0;
124 std::vector<variable> new_variables(vl.size());
125 {
126 // Create new unique variables to replace the old and create storage for
127 // storing old values for variables in vl.
128 for(const variable& v: vl)
129 {
130 if (sigma(v)!=v || sigma.variable_occurs_in_a_rhs(v))
131 {
132 number_of_renamed_variables++;
133 new_variables[count]=data::variable(m_generator(), v.sort());
134 assert(occur_check(v, new_variables[count]));
135 }
136 else
137 {
138 new_variables[count]=v;
139 }
140 count++;
141 }
142 }
143
144 if (number_of_renamed_variables==0)
145 {
146 make_abstraction(result,lambda_binder(),vl,(body_in_normal_form?body:rewrite(body,sigma)));
147 return;
148 }
149
150 data_expression result_aux;
152 if (body_in_normal_form)
153 {
154 // If the body is already in normal form, a simple replacement of the old variables
155 // by the new ones will do
157 for(v = vl.begin(), count = 0; v != vl.end(); ++v, ++count)
158 {
159 if (*v != new_variables[count])
160 {
161 variable_renaming[*v] = new_variables[count];
162 }
163 }
164 result_aux = replace_variables(body, variable_renaming);
165 }
166 else
167 {
168 // If the body is not in normal form, then we have to rewrite with an updated sigma.
169 // We first change sigma and save the values in sigma we overwrote...
170 std::vector<data_expression> saved_substitutions;
171 for(v = vl.begin(), count = 0; v != vl.end(); ++v, ++count)
172 {
173 if (*v != new_variables[count])
174 {
175 saved_substitutions.push_back(sigma(*v));
176 sigma[*v] = new_variables[count];
177 }
178 }
179 // ... then we rewrite with the new sigma ...
180 bool rewrite_stack_too_big_exception_thrown=false;
181 try
182 {
183 rewrite(result_aux,body,sigma);
184 }
186 {
187 rewrite_stack_too_big_exception_thrown=true;
188 }
189 // ... and then we restore sigma to its old state.
190 std::size_t new_variable_count = 0;
191 for(v = vl.begin(), count = 0; v != vl.end(); ++v, ++count)
192 {
193 if (*v != new_variables[count])
194 {
195 sigma[*v] = saved_substitutions[new_variable_count++];
196 }
197 }
198 if (rewrite_stack_too_big_exception_thrown)
199 {
201 }
202 }
203 variable_list new_variable_list(new_variables.begin(), new_variables.end());
204 make_abstraction(result, lambda_binder(),new_variable_list,result_aux);
205 return;
206}
207
208
209// The function rewrite_lambda_application assumes that t has the shape
210// application(...application(lambda x:D...., arg1,...,argn),argn+1,...,argN).
211// It applies the lambda term to its arguments, and rewrites the result to
212// normal form.
213
215 data_expression& result,
216 const data_expression& t,
218{
219 if (is_lambda(t))
220 {
221 const abstraction& ta=atermpp::down_cast<abstraction>(t);
222 rewrite_single_lambda(result,ta.variables(),ta.body(),false,sigma);
223 return;
224 }
225
226 const application ta(t);
227 if (is_lambda(ta.head()))
228 {
229 rewrite_lambda_application(result,atermpp::down_cast<abstraction>(ta.head()),ta,sigma);
230 return;
231 }
233 data_expression aux; // TODO. Optimize.
234 make_application(aux,result,ta.begin(),ta.end());
235 rewrite(result,aux,sigma);
236 return;
237}
238
239
240
241// The function rewrite_lambda_application rewrites a lambda term to a set of
242// arguments which are the arguments 1,...,n of t. If t has the shape
243// #REWR#(t0,t1,....,tn) and the lambda term is L, we calculate the normal form
244// in internal format for L(t1,...,tn). Note that the term t0 is ignored.
245// Note that we assume that neither L, nor t is in normal form.
246
248 data_expression& result,
249 const abstraction& lambda_term,
250 const application& t,
252{
253 assert(is_lambda(lambda_term)); // The function symbol in this position cannot be anything else than a lambda term.
254 const variable_list& vl=lambda_term.variables();
255 const data_expression& lambda_body=lambda_term.body();
256 std::size_t arity=t.size();
257 if (arity==0) // The term has shape application(lambda d..:D...t), i.e. without arguments.
258 {
259 rewrite_single_lambda(result, vl, lambda_body, true, sigma);
260 return;
261 }
262 assert(vl.size()<=arity);
263
264 // The variable vl_backup will be used to first store the values to be substituted
265 // for the variables in vl. Subsequently, it will be used to temporarily save the values in sigma
266 // assigned to vl.
267 data_expression* vl_backup = MCRL2_SPECIFIC_STACK_ALLOCATOR(data_expression,vl.size());
268
269 // Calculate the values that must be substituted for the variables in vl and store these in vl_backup.
270 for(std::size_t count=0; count<vl.size(); count++)
271 {
272 new (&vl_backup[count]) data_expression(rewrite(t[count],sigma));
273 }
274
275 // Swap the values assigned to variables in vl with those in vl_backup.
276 std::size_t count=0;
277 for(const variable& v: vl)
278 {
279 const data_expression temp=sigma(v);
280 sigma[v]=vl_backup[count];
281 vl_backup[count]=temp;
282 count++;
283 }
284
285 bool rewrite_stack_too_big_exception_thrown=false;
286 try
287 {
288 rewrite(result,lambda_body,sigma);
289 }
291 {
292 rewrite_stack_too_big_exception_thrown=true;
293 }
294
295 // Reset variables in sigma and destroy the elements in vl_backup.
296 count=0;
297 for(const variable& v: vl)
298 {
299 sigma[v]=vl_backup[count];
300 vl_backup[count].~data_expression();
301 count++;
302 }
303 if (rewrite_stack_too_big_exception_thrown)
304 {
306 }
307
308 if (vl.size()==arity)
309 {
310 return;
311 }
312
313 // There are more arguments than bound variables.
314 // Rewrite the remaining arguments and apply the rewritten lambda term to them.
315 make_application(result,
316 result,
317 t.begin()+vl.size(),
318 t.end(),
319 [this, &sigma](const data_expression& t) -> data_expression { return rewrite(t, sigma); },
320 false // This false indicates that the function is not applied to head, i.e., result.
321 );
322 return;
323}
324
326 data_expression& result,
327 const abstraction& t,
329{
330 // This is a quantifier elimination that works on the existential quantifier as specified
331 // in data types, i.e. without applying the implement function anymore.
332
333 assert(is_exists(t));
334 existential_quantifier_enumeration(result, t.variables(), t.body(), false, sigma);
335 return;
336}
337
338// Generate a term equivalent to exists vl.t1.
339// The variable t1_is_normal_form indicates whether t1 is in normal
340// form, but this information is not used as it stands.
342 data_expression& result,
343 const variable_list& vl,
344 const data_expression& t1,
345 const bool t1_is_normal_form,
347{
348 quantifier_enumeration(result, vl, t1, t1_is_normal_form, sigma, exists_binder(), &lazy::or_, sort_bool::false_(), sort_bool::true_());
349 return;
350}
351
352
354 data_expression& result,
355 const abstraction& t,
357{
358 assert(is_forall(t));
360 return;
361}
362
363// Generate a term equivalent to forall vl.t1.
364// The variable t1_is_normal_form indicates whether t1 is in normal
365// form, but this information is not used as it stands.
367 data_expression& result,
368 const variable_list& vl,
369 const data_expression& t1,
370 const bool t1_is_normal_form,
372{
373 quantifier_enumeration(result, vl, t1, t1_is_normal_form, sigma, forall_binder(), &lazy::and_, sort_bool::true_(), sort_bool::false_());
374 return;
375}
376
378 data_expression& result,
379 const variable_list& vl,
380 const data_expression& t1,
381 const bool t1_is_normal_form,
383 const binder_type& binder,
384 data_expression (*lazy_op)(const data_expression&, const data_expression&),
385 const data_expression& identity_element,
386 const data_expression& absorbing_element
387 )
388{
389 // Rename the bound variables to unique
390 // variables, to avoid naming conflicts.
391
393 variable_vector vl_new_v;
394 for(const variable& v: vl)
395 {
396 if (sigma(v)!=v || sigma.variable_occurs_in_a_rhs(v))
397 {
398 const variable v_fresh(m_generator(), v.sort());
399 variable_renaming[v]=v_fresh;
400 vl_new_v.push_back(v_fresh);
401 }
402 else
403 {
404 vl_new_v.push_back(v);
405 }
406 }
407
408 const data_expression t2=replace_variables(t1,variable_renaming);
409 const data_expression t3=(t1_is_normal_form?t2:rewrite(t2,sigma));
410
411 // Check whether the bound variables occur free in the rewritten body
412 std::set < variable > free_variables=find_free_variables(t3);
413 variable_list vl_new_l_enum;
414 variable_list vl_new_l_other;
415
416 bool sorts_are_finite=true;
417 for(variable_vector::const_reverse_iterator i=vl_new_v.rbegin(); i!=vl_new_v.rend(); ++i)
418 {
419 const variable v = *i;
420 if (free_variables.count(v)>0)
421 {
423 {
424 vl_new_l_enum.push_front(v);
425 sorts_are_finite = sorts_are_finite && m_data_specification_for_enumeration.is_certainly_finite(v.sort());
426 }
427 else
428 {
429 vl_new_l_other.push_front(v);
430 }
431 }
432 }
433
434 if (vl_new_l_enum.empty())
435 {
436 if (vl_new_l_other.empty())
437 {
438 result=t3;
439 return; // No quantified variables are bound.
440 }
441 else
442 {
443 make_abstraction(result, binder, vl_new_l_other, t3);
444 return;
445 }
446 }
447
449 typedef data::enumerator_list_element<data_expression> enumerator_element;
450
451
452 /* Find A solution*/
453 rewriter_wrapper wrapped_rewriter(this);
454 const std::size_t max_count = sorts_are_finite || data::detail::get_enumerator_iteration_limit()==0?
455 std::numeric_limits<std::size_t>::max() :
457 try
458 {
459 enumerator_type enumerator(wrapped_rewriter, m_data_specification_for_enumeration,
460 wrapped_rewriter, m_generator, false, max_count);
461
462 /* Create a list to store solutions */
463 data_expression partial_result = identity_element;
464
465 std::size_t count=enumerator.enumerate(enumerator_element(vl_new_l_enum, t3),
466 sigma,
467 [&](const enumerator_element& p)
468 {
469 partial_result = lazy_op(partial_result, p.expression());
470 return partial_result==absorbing_element;
471 },
472 [&identity_element](const data_expression& d)->bool { return d==identity_element; },
473 [&absorbing_element](const data_expression& d)->bool { return d==absorbing_element; }
474 );
475
476 if (count<=max_count) // Enumeration is successful. If not fall through and return the original, simplified expression.
477 {
478 if (vl_new_l_other.empty())
479 {
480 result=partial_result;
481 return;
482 }
483 else
484 {
485 make_abstraction(result,binder, vl_new_l_other, partial_result);
486 return;
487 }
488 }
489 }
490 catch(const mcrl2::runtime_error& e)
491 {
492 // if (max_count==std::numeric_limits<std::size_t>::max()) // No bound on enumeration.
493 // {
494 // throw e;
495 // }
496 // It is not possible to enumerate one of the bound variables, or the enumerator limit of the
497 // iterator is exceeded. So, we just return the original non enumerated, simplified expression.
498 }
499 make_abstraction(result, binder,vl_new_l_enum+vl_new_l_other,rewrite(t3,sigma));
500 return;
501}
502
503
504std::shared_ptr<Rewriter> createRewriter(
505 const data_specification& data_spec,
506 const used_data_equation_selector& equations_selector,
508{
509 switch (strategy)
510 {
511 case jitty:
512 return std::shared_ptr<Rewriter>(new RewriterJitty(data_spec,equations_selector));
513#ifdef MCRL2_ENABLE_JITTYC
514 case jitty_compiling:
515 return std::shared_ptr<Rewriter>(new RewriterCompilingJitty(data_spec,equations_selector));
516#endif
517 case jitty_prover:
518 return std::shared_ptr<Rewriter>(new RewriterProver(data_spec,jitty,equations_selector));
519#ifdef MCRL2_ENABLE_JITTYC
520 case jitty_compiling_prover:
521 return std::shared_ptr<Rewriter>(new RewriterProver(data_spec,jitty_compiling,equations_selector));
522#endif
523 default: throw mcrl2::runtime_error("Cannot create a rewriter using strategy " + pp(strategy) + ".");
524 }
525}
526
527//Prototype
528static void check_vars(const data_expression& expr, const std::set <variable>& vars, std::set <variable>& used_vars);
529
532 const std::set <variable>& vars,
533 std::set <variable>& used_vars)
534{
535 while (begin != end)
536 {
537 check_vars(*begin++, vars, used_vars);
538 }
539}
540
541static void check_vars(const data_expression& expr, const std::set <variable>& vars, std::set <variable>& used_vars)
542{
543 if (is_application(expr))
544 {
545 const application& a=atermpp::down_cast<application>(expr);
546 check_vars(a.head(),vars,used_vars);
547 check_vars(a.begin(),a.end(),vars,used_vars);
548 }
549 else if (is_variable(expr))
550 {
551 const variable& v=atermpp::down_cast<variable>(expr);
552 used_vars.insert(v);
553
554 if (vars.count(v)==0)
555 {
556 throw v;
557 }
558 }
559}
560
561//Prototype
562static void checkPattern(const data_expression& p);
563
566{
567 while (begin != end)
568 {
569 checkPattern(*begin++);
570 }
571}
572
573static void checkPattern(const data_expression& p)
574{
575 if (is_application(p))
576 {
577 if (is_variable(atermpp::down_cast<application>(p).head()))
578 {
579 throw mcrl2::runtime_error(std::string("variable ") + data::pp(application(p).head()) +
580 " is used as head symbol in an application, which is not supported");
581 }
582 const application& a=atermpp::down_cast<application>(p);
583 checkPattern(a.head());
584 checkPattern(a.begin(),a.end());
585 }
586}
587
588void CheckRewriteRule(const data_equation& data_eqn)
589{
590 const variable_list& rule_var_list = data_eqn.variables();
591 const std::set <variable> rule_vars(rule_var_list.begin(),rule_var_list.end());
592
593 // collect variables from lhs and check that they are in rule_vars
594 std::set <variable> lhs_vars;
595 try
596 {
597 check_vars(data_eqn.lhs(),rule_vars,lhs_vars);
598 }
599 catch (variable& var)
600 {
601 // This should never occur if data_eqn is a valid data equation
602 mCRL2log(log::error) << "Data equation: " << data_expression(data_eqn) << std::endl;
603 assert(0);
604 throw runtime_error("variable " + pp(var) + " occurs in left-hand side of equation but is not defined (in equation: " + pp(data_eqn) + ")");
605 }
606
607 // check that variables from the condition occur in the lhs
608 try
609 {
610 std::set <variable> dummy;
611 check_vars(data_eqn.condition(),lhs_vars,dummy);
612 }
613 catch (variable& var)
614 {
615 throw runtime_error("variable " + pp(var) + " occurs in condition of equation but not in left-hand side (in equation: " +
616 pp(data_eqn) + "); equation cannot be used as rewrite rule");
617 }
618
619 // check that variables from the rhs are occur in the lhs
620 try
621 {
622 std::set <variable> dummy;
623 check_vars(data_eqn.rhs(),lhs_vars,dummy);
624 }
625 catch (variable& var)
626 {
627 throw runtime_error("variable " + pp(var) + " occurs in right-hand side of equation but not in left-hand side (in equation: " +
628 pp(data_eqn) + "); equation cannot be used as rewrite rule");
629 }
630
631 // check that the lhs is a supported pattern
632 if (is_variable(data_eqn.lhs()))
633 {
634 throw runtime_error("left-hand side of equation is a variable; this is not allowed for rewriting");
635 }
636 try
637 {
638 checkPattern(data_eqn.lhs());
639 }
640 catch (mcrl2::runtime_error& s)
641 {
642 throw runtime_error(std::string(s.what()) + " (in equation: " + pp(data_eqn) + "); equation cannot be used as rewrite rule");
643 }
644}
645
647{
648 try
649 {
650 CheckRewriteRule(data_eqn);
651 return true;
652 }
653 catch (runtime_error&)
654 {
655 return false;
656 }
657 return false; // compiler warning
658}
659
660}
661}
662}
Iterator for term_appl.
Iterator for term_list.
size_type size() const
Returns the size of the term_list.
Definition aterm_list.h:256
const_iterator end() const
Returns a const_iterator pointing to the end of the term_list.
Definition aterm_list.h:282
const_iterator begin() const
Returns a const_iterator pointing to the beginning of the term_list.
Definition aterm_list.h:275
bool empty() const
Returns true if the list's size is 0.
Definition aterm_list.h:268
void push_front(const Term &el)
Inserts a new element at the beginning of the current list.
An abstraction expression.
Definition abstraction.h:26
const variable_list & variables() const
Definition abstraction.h:63
const data_expression & body() const
Definition abstraction.h:68
An application of a data expression to a number of arguments.
const_iterator end() const
Returns an iterator pointing past the last argument of the application.
const_iterator begin() const
Returns an iterator pointing to the first argument of the application.
const data_expression & head() const
Get the function at the head of this expression.
std::size_t size() const
\brief Assignment of a data expression to a variable
Definition assignment.h:91
\brief A data equation
const data_expression & lhs() const
const data_expression & condition() const
const data_expression & rhs() const
const variable_list & variables() const
bool is_certainly_finite(const sort_expression &s) const
Checks whether a sort is certainly finite.
mcrl2::data::data_specification m_data_specification_for_enumeration
Definition rewrite.h:230
void rewrite_lambda_application(data_expression &result, const data_expression &t, substitution_type &sigma)
Rewrite t, assuming that the headsymbol of t, which can be nested, is a lambda term.
Definition rewrite.cpp:214
void rewrite_where(data_expression &result, const where_clause &term, substitution_type &sigma)
Definition rewrite.cpp:70
void existential_quantifier_enumeration(data_expression &result, const abstraction &t, substitution_type &sigma)
Definition rewrite.cpp:325
void universal_quantifier_enumeration(data_expression &result, const abstraction &t, substitution_type &sigma)
Definition rewrite.cpp:353
virtual data_expression rewrite(const data_expression &term, substitution_type &sigma)=0
Rewrite an mCRL2 data term.
void rewrite_single_lambda(data_expression &result, const variable_list &vl, const data_expression &body, const bool body_in_normal_form, substitution_type &sigma)
Definition rewrite.cpp:109
enumerator_identifier_generator m_generator
Definition rewrite.h:44
void quantifier_enumeration(data_expression &result, const variable_list &vl, const data_expression &t1, const bool t1_is_normal_form, substitution_type &sigma, const binder_type &binder, data_expression(*lazy_op)(const data_expression &, const data_expression &), const data_expression &identity_element, const data_expression &absorbing_element)
Definition rewrite.cpp:377
A strategy is a list of rules and the number of variables that occur in it.
An enumerator algorithm that generates solutions of a condition.
Definition enumerator.h:601
The default element for the todo list of the enumerator.
Definition enumerator.h:231
\brief Binder for existential quantification
\brief Binder for universal quantification
\brief Binder for lambda abstraction
Generic substitution function. The substitution is stored as a mapping of variables to expressions....
const_iterator begin() const
Returns an iterator pointing to the beginning of the sequence of assignments TODO: should become prot...
const_iterator end() const
Returns an iterator pointing past the end of the sequence of assignments TODO: should become protecte...
Component for selecting a subset of equations that are actually used in an encompassing specification...
Definition selection.h:37
\brief A data variable
Definition variable.h:28
const sort_expression & sort() const
Definition variable.h:43
\brief A where expression
const assignment_list & assignments() const
const data_expression & body() const
Standard exception class for reporting runtime errors.
Definition exception.h:27
The class enumerator.
Stores a static variable that indicates the number of iterations allowed during enumeration.
static RewriterCompilingJitty::substitution_type & sigma(RewriterCompilingJitty *this_rewriter)
#define mCRL2log(LEVEL)
mCRL2log(LEVEL) provides the stream used to log.
Definition logger.h:391
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...
Definition rewrite.cpp:588
static void checkPattern(const data_expression &p)
Definition rewrite.cpp:573
bool isValidRewriteRule(const data_equation &data_eqn)
Check whether or not an mCRL2 data equation is a valid rewrite rule.
Definition rewrite.cpp:646
static bool occur_check(const variable &v, const atermpp::aterm &e)
Definition rewrite.cpp:44
bool is_enumerable(const data_specification &dataspec, const Rewriter &rewr, const sort_expression &sort, std::list< sort_expression > &parents)
Definition enumerator.h:159
static void check_vars(const data_expression &expr, const std::set< variable > &vars, std::set< variable > &used_vars)
Definition rewrite.cpp:541
std::string pp(const detail::lhs_t &lhs)
std::shared_ptr< detail::Rewriter > createRewriter(const data_specification &DataSpec, const used_data_equation_selector &equations_selector, const rewrite_strategy Strategy=jitty)
Create a rewriter.
Definition rewrite.cpp:504
std::size_t get_enumerator_iteration_limit()
data_expression and_(data_expression const &p, data_expression const &q)
Returns an expression equivalent to p or q.
data_expression or_(data_expression const &p, data_expression const &q)
Returns an expression equivalent to p and q.
const function_symbol & false_()
Constructor for function symbol false.
Definition bool.h:109
const function_symbol & true_()
Constructor for function symbol true.
Definition bool.h:77
variable_list free_variables(const data_expression &x)
Definition data.cpp:195
std::vector< variable > variable_vector
\brief vector of variables
Definition variable.h:89
rewrite_strategy
The strategy of the rewriter.
@ jitty_prover
JITty.
std::string pp(const abstraction &x)
Definition data.cpp:39
bool is_forall(const atermpp::aterm &x)
Returns true if the term t is a universal quantification.
std::set< data::variable > find_free_variables(const data::data_expression &x)
Definition data.cpp:99
void make_abstraction(atermpp::aterm &result, ARGUMENTS... arguments)
Definition abstraction.h:75
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_application(const atermpp::aterm &x)
Returns true if the term t is an application.
void replace_variables(T &x, const Substitution &sigma, typename std::enable_if<!std::is_base_of< atermpp::aterm, T >::value >::type *=nullptr)
Definition replace.h:213
bool is_variable(const atermpp::aterm &x)
Returns true if the term t is a variable.
void make_application(atermpp::aterm &result)
Make function for an application.
A class that takes a linear process specification and checks all tau-summands of that LPS for conflue...
Definition indexed_set.h:72
bool operator()(const atermpp::aterm &t) const
Definition rewrite.cpp:37
Rewriting combined with semantic simplification using a prover.