mCRL2
Loading...
Searching...
No Matches
unfold_pattern_matching.h
Go to the documentation of this file.
1// Author(s): Ruud Koolen, Thomas Neele
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
9#ifndef MCRL2_DATA_UNFOLD_PATTERN_MATCHING_H
10#define MCRL2_DATA_UNFOLD_PATTERN_MATCHING_H
11
12#include "mcrl2/data/join.h"
13#include "mcrl2/data/replace.h"
14#include "mcrl2/data/substitutions/data_expression_assignment.h"
15#include "mcrl2/data/representative_generator.h"
16#include "mcrl2/data/substitutions/map_substitution.h"
17#include "mcrl2/data/substitutions/variable_substitution.h"
18
19namespace mcrl2::data
20{
21
22namespace detail
23{
24/**
25 * \brief A rule describes a partially pattern-matched rewrite rule.
26 * \details match_criteria is a set of data_expression pairs (A, B)
27 * where A is a data_expression over variables in the left hand
28 * side of a function definition, and B is a pattern consisting of
29 * constructor applications over free variables.
30 *
31 * The rule match_criteria = { (A, B), (C, D) }, condition = E, rhs = R
32 * describes the following rewrite proposition:
33 *
34 * "if the data expression A pattern-matches to pattern B, and the
35 * data expression C pattern-matches to pattern D, and the condition
36 * E is true after substituting the proper pattern-matching variables,
37 * then the right hand side R applies (again with substitution of
38 * pattern-matched variables."
39 *
40 * Pattern matching can then be performed by deconstructing the patterns
41 * in the right hand sides of match_criteria, and rewriting rules accordingly.
42 * As an example, the following rewrite rule:
43 *
44 * is_even(n) -> sign_of_list_sum(n |> l) = sign_of_list_sum(l)
45 *
46 * Can be represented as the following rule:
47 *
48 * match_criteria = { v1 -> n |> l }, condition = is_even(n), rhs = sign_of_list_sum(l)
49 *
50 * Which, after one step of pattern matching, gets simplified to the following rule:
51 *
52 * match_criteria = { head(v1) -> n, tail(v1) -> l }, condition = is_even(n), rhs = sign_of_list_sum(l)
53 */
54struct rule
55{
59 variable_list variables;
60
61 rule(const std::map<data_expression, data_expression>& mc,
62 const data_expression& r,
63 const data_expression& c,
64 const variable_list& v)
66 , rhs(r)
68 , variables(v)
69 {
71 }
72
73};
74
75inline
77{
78 return out << core::detail::print_list(r.variables) << ". " << r.condition << " -> " << core::detail::print_map(r.match_criteria) << " = " << r.rhs;
79}
80
81
82/// @brief Get the top level function symbol f if expr is of the shape f or f(t1,...,tn)
83/// @param expr The expression from which to extract the top function symbol
84/// @return The top function symbol, or function_symbol() if it has none
85inline
87{
89 {
90 return atermpp::down_cast<function_symbol>(expr);
91 }
92 if (is_application(expr))
93 {
94 const application& expr_appl = atermpp::down_cast<application>(expr);
95 if (is_function_symbol(expr_appl.head()))
96 {
97 return atermpp::down_cast<function_symbol>(expr_appl.head());
98 }
99 }
100 return function_symbol();
101}
102
103/**
104 * \brief For a list of rules with equal left hand sides of match_criteria and only variables in
105 * the right hand sides of match_criteria, construct a right hand side based on the
106 * conditions and right hand sides of the rules.
107 */
108inline
109data_expression construct_condition_rhs(const std::vector<rule>& rules, const data_expression& representative)
110{
111 // TODO: Check whether else_clause is equivalent to false. Can we use the enumerator for this?
112 if (rules.size() == 0)
113 {
114 return representative;
115 }
116
117 data_expression result;
118 for (const rule& r: rules)
119 {
120 std::map<variable, data_expression> substitution_map;
121 for (const auto& [var_expr, pattern]: r.match_criteria)
122 {
123 assert(is_variable(pattern));
124 substitution_map[atermpp::down_cast<variable>(pattern)] = var_expr;
125 }
126 map_substitution<std::map<variable, data_expression> > substitution(substitution_map);
127
128 data_expression condition = replace_variables_capture_avoiding(r.condition, substitution);
129 data_expression rhs = replace_variables_capture_avoiding(r.rhs, substitution);
130
131 if (result == data_expression())
132 {
133 result = rhs;
134 }
135 else
136 {
137 result = lazy::if_(condition, rhs, result);
138 }
139 }
140
141 return result;
142}
143
144/**
145 * \brief For a list of rules with equal left hand sides of match_criteria, construct a right hand side.
146 */
147template <typename StructInfo>
149 StructInfo& ssf,
151 const std::vector<rule>& rules,
152 const sort_expression& sort
153)
154{
155 if (rules.empty())
156 {
157 return construct_condition_rhs(rules, gen(sort));
158 }
159
160 /*
161 * For each matching rule LHS, check whether pattern matching needs to happen on that LHS.
162 *
163 * We prefer to match on an expression such that *all* rules perform matching on that expression.
164 * For example, for a ruleset representing the following rewrite rules:
165 *
166 * optionally_remove_first_element(false, l) = l
167 * optionally_remove_first_element(true, []) = []
168 * optionally_remove_first_element(true, x |> l) = l
169 *
170 * We prefer to pattern match on the first parameter, not the second. Pattern matching on the
171 * second parameter will (recursively) happen only on the true-branch, not the false-branch.
172 * Pattern matching on the second parameter is still possible if there is no other option, but
173 * it requires splitting the first rewrite rule into different cases for different
174 * constructors -- suboptimal.
175 */
176 data_expression matching_target;
177 enum class MatchType
178 {
179 NONE, INCOMPLETE, PARTIAL, FULL
180 };
181 MatchType matching_type = MatchType::NONE;
182 // iterate over matches, this is the same for all rules, so just use rules[0]
183 // More formally, we have rules[i].match_criteria->first is equivalent for all i.
184 for (const auto& [var_expr, _]: rules[0].match_criteria)
185 {
186 bool variable_seen = false;
187 std::set<function_symbol> constructors_seen;
188 for (const rule& r: rules)
189 {
190 const data_expression& pattern = r.match_criteria.at(var_expr);
191 if (is_variable(pattern))
192 {
193 variable_seen = true;
194 }
195 else
196 {
197 // either function symbol or application of function symbol
198 function_symbol fs = get_top_fs(pattern);
199 // this also means fs != function_symbol()
200 assert(ssf.is_constructor(fs));
201 constructors_seen.insert(fs);
202 }
203 }
204
205 MatchType new_matching_type;
206 if (constructors_seen.empty())
207 {
208 // No pattern matching is possible on this variable.
209 new_matching_type = MatchType::NONE;
210 }
211 else if (variable_seen)
212 {
213 // There are both rules that match on this variable and rules that do not.
214 // That's better than an incomplete matching but worse than a full matching.
215 new_matching_type = MatchType::PARTIAL;
216 }
217 else if (constructors_seen.size() != ssf.get_constructors(var_expr.sort()).size())
218 {
219 // There are constructors for which there are no rules.
220 // Thus, we have an incomplete function definition, that needs to be completed artificially.
221 // A partial matching would be a better choice.
222 new_matching_type = MatchType::INCOMPLETE;
223 }
224 else
225 {
226 // There is a matching rule for each constructor, and no rule with a plain variable.
227 // This variable is a perfect pattern matching candidate.
228 new_matching_type = MatchType::FULL;
229 }
230
231 if (new_matching_type > matching_type)
232 {
233 matching_target = var_expr;
234 matching_type = new_matching_type;
235 }
236 if (matching_type == MatchType::FULL)
237 {
238 break;
239 }
240 }
241
242 if (matching_type == MatchType::NONE)
243 {
244 // No constructor-based matching needs to happen.
245 // All that needs to happen is incorporating the rule conditions.
246 return construct_condition_rhs(rules, gen(sort));
247 }
248
249 /*
250 * For each constructor, find the set of rules that apply to it, rewritten to match the constructor.
251 */
252 // auto type below depends on the type of ssf
253 const auto& match_constructors = ssf.get_constructors(matching_target.sort());
254 std::map<function_symbol, std::vector<rule> > constructor_rules;
255 for (const rule& r: rules)
256 {
257 const data_expression& pattern = r.match_criteria.at(matching_target);
258 if (is_function_symbol(pattern) || is_application(pattern))
259 {
260 /*
261 * For a rule with a constructor pattern, strip the constructor and
262 * introduce patterns for the constructor parameters.
263 */
264 function_symbol constructor = get_top_fs(pattern);
265 assert(constructor != function_symbol());
266 assert(utilities::detail::contains(match_constructors, constructor));
267
268 data_expression_vector parameters;
269 if (is_application(pattern))
270 {
271 const application& pattern_appl = atermpp::down_cast<application>(pattern);
272 parameters.insert(parameters.end(), pattern_appl.begin(), pattern_appl.end());
273 }
274
275 rule rule = r;
276 rule.match_criteria.erase(matching_target);
277 // To prevent creating expressions of the shape head(l) |> tail(l), we perform a substitution here
278 // This is only safe if there are no binders in the right-hand side
279 std::set<data_expression> subexpr = find_data_expressions(rule.rhs);
280 if (!parameters.empty() && std::none_of(subexpr.begin(), subexpr.end(), [](const data_expression& e) { return is_abstraction(e); }))
281 {
282 data_expression_assignment sigma(pattern,matching_target);
283 rule.rhs = replace_data_expressions(rule.rhs, sigma, true);
284 rule.condition = replace_data_expressions(rule.condition, sigma, true);
285 }
286 for (std::size_t j = 0; j < parameters.size(); j++)
287 {
288 function_symbol projection_function = ssf.get_projection_funcs(constructor)[j];
289 data_expression lhs_expression = application(projection_function, matching_target);
290 rule.match_criteria[lhs_expression] = parameters[j];
291 }
292 constructor_rules[constructor].push_back(rule);
293 }
294 else
295 {
296 /*
297 * For a rule with a variable pattern that nonetheless needs to pattern match
298 * against the possible constructors for that variable, copy the rule for each
299 * possible constructor. Substitute the original un-matched term for the pattern
300 * variable that disappears.
301 */
302 assert(is_variable(pattern));
303 variable_substitution sigma(atermpp::down_cast<variable>(pattern), matching_target);
304 data_expression condition = replace_variables_capture_avoiding(r.condition, sigma);
305 data_expression rhs = replace_variables_capture_avoiding(r.rhs, sigma);
306
307 for (const function_symbol& f: match_constructors)
308 {
309 rule rule(r.match_criteria, rhs, condition, r.variables);
310 rule.match_criteria.erase(matching_target);
311
312 set_identifier_generator generator;
313 for (const variable& v: r.variables)
314 {
315 generator.add_identifier(v.name());
316 }
317
318 if (is_function_sort(f.sort()))
319 {
320 function_sort sort(f.sort());
321 std::size_t index = 0;
322 for (const sort_expression& s: sort.domain())
323 {
324 variable variable(generator("v"), s);
325 function_symbol projection_function = ssf.get_projection_funcs(f)[index];
326 data_expression lhs_expression = application(projection_function, matching_target);
327 rule.match_criteria[lhs_expression] = variable;
328 index++;
329 }
330 }
331
332 constructor_rules[f].push_back(rule);
333 }
334 }
335 }
336
337 /*
338 * Construct an rhs of the form if(is_cons1, rhs_cons1, if(is_cons2, rhs_cons2, ...)) or equivalent
339 * The exact form depends on the implementation in ssf
340 */
341 data_expression_vector rhs;
342 for (const auto& f: match_constructors)
343 {
344 rhs.push_back(construct_rhs(ssf, gen, constructor_rules[f], sort));
345 }
346 return ssf.create_cases(matching_target, rhs);
347}
348
349} // namespace detail
350
351/**
352 * \brief Check whether the given rewrite rule can be classified as a pattern matching rule.
353 * \details That is, its arguments are constructed only out of unique variable occurrences and
354 * constructor function symbols and constructor function applications.
355 */
356template <typename StructInfo>
357bool is_pattern_matching_rule(StructInfo& ssf, const data_equation& rewrite_rule)
358{
359 // For this rewrite rule to be usable in pattern matching, its lhs must only contain
360 // constructor functions and variables that occur at most once.
361
362 std::set<data_expression> subexpressions = find_data_expressions(rewrite_rule.lhs());
363 subexpressions.erase(rewrite_rule.lhs());
364 if (is_application(rewrite_rule.lhs()))
365 {
366 subexpressions.erase(application(rewrite_rule.lhs()).head());
367 }
368
369 bool all_pattern = std::all_of(subexpressions.begin(), subexpressions.end(), [&ssf](const data_expression& expr) {
370 return
371 is_variable(expr) ||
372 (is_function_symbol(expr) && ssf.is_constructor(atermpp::down_cast<function_symbol>(expr))) ||
373 (is_application(expr) && is_function_symbol(atermpp::down_cast<application>(expr).head()) &&
374 ssf.is_constructor(function_symbol(atermpp::down_cast<application>(expr).head())));
375 });
376 if (!all_pattern)
377 {
378 return false;
379 }
380 if (std::all_of(subexpressions.begin(), subexpressions.end(), [](const data_expression& x){ return is_variable(x); }))
381 {
382 // Each argument is a variable, this is just an ordinarily defined function
383 return false;
384 }
385
386 // Check whether each variable occurs at most once
387 std::set<variable> variable_set;
388 std::multiset<variable> variable_multiset;
389 find_all_variables(rewrite_rule.lhs(), std::inserter(variable_set, variable_set.end()));
390 find_all_variables(rewrite_rule.lhs(), std::inserter(variable_multiset, variable_multiset.end()));
391 return variable_set.size() == variable_multiset.size();
392}
393
394/**
395 * \brief This converts a collection of rewrite rules for a give function symbol into a
396 * one-rule specification of the function, using recogniser and projection functions
397 * to implement pattern matching.
398 * \details For example, the collection of rewrite rules below:
399 *
400 * sign_of_list_sum([]) = false;
401 * is_even(n) -> sign_of_list_sum(n |> l) = sign_of_list_sum(l);
402 * !is_even(n) -> sign_of_list_sum(n |> l) = !sign_of_list_sum(l);
403 *
404 * gets translated into the following function specification:
405 *
406 * sign_of_list_sum(l) = if(is_emptylist(l), false,
407 * if(is_even(head(l)), sign_of_list_sum(tail(l)),
408 * !sign_of_list_sum(tail(l))))
409 *
410 * Two complications can arise. The rewrite rule set may contain rules that do not
411 * pattern-match on the function parameters, such as 'not(not(b)) = b`; rules like
412 * these are discarded.
413 * More problematically, the set of rewrite rules may not be complete, or may not
414 * easily be proven complete; in the example above, if the rewriter cannot rewrite
415 * 'is_even(n) || !is_even(n)' to 'true', the translation cannot tell that the
416 * rewrite rule set is complete.
417 * In cases where a (non-constructor )function invocation can genuinely not be
418 * rewritten any further, the MCRL2 semantics are unspecified (TODO check this);
419 * the translation resolves this situation by returning an arbitrary value in this
420 * case. Thus, in practice, the function definion above might well be translated
421 * into the following:
422 *
423 * sign_of_list_sum(l) = if(is_emptylist(l), false,
424 * if(is_even(head(l)), sign_of_list_sum(tail(l)),
425 * if(!is_even(head(l)), !sign_of_list_sum(tail(l)),
426 * false)))
427 *
428 * Where 'false' is a representative of sort_bool.
429 */
430template <typename StructInfo>
432 const function_symbol& mapping,
433 const data_equation_vector& rewrite_rules,
434 StructInfo& ssf,
437)
438{
439 sort_expression codomain = mapping.sort().target_sort();
440 variable_vector temp_par;
441 if (is_function_sort(mapping.sort()))
442 {
443 const function_sort& sort = atermpp::down_cast<function_sort>(mapping.sort());
444 for (const sort_expression& s: sort.domain())
445 {
446 temp_par.emplace_back(id_gen("x"), s);
447 }
448 }
449 variable_list new_parameters(temp_par.begin(), temp_par.end());
450
451 // Create a rule for each data_equation
452 std::vector<detail::rule> rules;
453 for (const data_equation& eq: rewrite_rules)
454 {
455 assert(is_pattern_matching_rule(ssf, eq));
456
457 std::map<data_expression, data_expression> match_criteria;
458 if (is_application(eq.lhs()))
459 {
460 const application& lhs_appl = atermpp::down_cast<application>(eq.lhs());
461
462 assert(lhs_appl.head() == mapping);
463 assert(new_parameters.size() == lhs_appl.size());
464
465 // Simultaneously iterate the parameters defined by the mapping and this
466 // left-hand side to determine how matching occurs
467 auto mappar_it = new_parameters.begin();
468 auto lhspar_it = lhs_appl.begin();
469 while(mappar_it != new_parameters.end())
470 {
471 match_criteria[*mappar_it] = *lhspar_it;
472 ++mappar_it, ++lhspar_it;
473 }
474
475 assert(lhspar_it == lhs_appl.end());
476 }
477
478 detail::rule rule(match_criteria, eq.rhs(), eq.condition(), eq.variables());
479 rules.push_back(rule);
480 }
481#ifdef MCRL2_ENABLE_MACHINENUMBERS
482 assert(rules.size() != 0 || sort_pos::is_most_significant_digit_function_symbol(mapping));
483#else
484 assert(rules.size() != 0);
485#endif
486
487 data_expression new_lhs(application(mapping, new_parameters));
488 data_expression new_rhs(construct_rhs(ssf, gen, rules, codomain));
489 return data_equation(new_parameters, new_lhs, new_rhs);
490}
491
492} // namespace mcrl2::data
493
494#endif
aterm_string()=default
Default constructor.
\brief A basic sort
Definition basic_sort.h:25
basic_sort & operator=(basic_sort &&) noexcept=default
\brief A data equation
const data_expression & lhs() const
data_expression()
\brief Default constructor X3.
data_expression & operator=(data_expression &&) noexcept=default
sort_expression sort() const
Returns the sort of the data expression.
Definition data.cpp:107
data_expression(const data_expression &) noexcept=default
Move semantics.
void add_mapping(const function_symbol &f)
Adds a mapping to this specification.
void add_equation(const data_equation &e)
Adds an equation to this specification.
\brief A function sort
\brief A function symbol
function_symbol & operator=(function_symbol &&) noexcept=default
function_symbol()
Default constructor.
const sort_expression & sort() const
Components for generating an arbitrary element of a sort.
Rewriter that operates on data expressions.
Definition rewriter.h:84
Identifier generator that stores the identifiers of the context in a set. Using the operator()() and ...
\brief A sort expression
const sort_expression & target_sort() const
Returns the target sort of this expression.
sort_expression()
\brief Default constructor X3.
void add_sort(const basic_sort &s)
Adds a sort to this specification.
\brief A data variable
Definition variable.h:25
const sort_expression & sort() const
Definition variable.h:40
Fresh variable generator for the arguments of a function symbol.
data::set_identifier_generator & m_identifier_generator
std::map< data::sort_expression, data::variable_vector > m_variables
data::variable_vector arguments(const data::function_symbol &f)
Generate argument variables for f.
data_equation_argument_generator(data::set_identifier_generator &identifier_generator)
Algorithm class for algorithms on linear process specifications. It can be instantiated with lps::spe...
Class for unfolding expressions f(a1,...,an) based on the pattern-matching rewrite rules that define ...
std::map< data::function_symbol, bool > m_is_pattern_matching
bool matches_only_known_sorts(const data::function_symbol &f)
Determines whether f pattern matches on argument arg.
bool is_det_or_pi(const data::application &expr) const
Checks whether expr is of the shape Det(h(a1,...,an)) or pi(h(a1,...,an)), where h is defined by patt...
data::data_equation_vector find_equations(const data::function_symbol &f)
Finds all rewriting equations for f.
void operator()(T &result, const data::application &x)
Unfolds expr if it is of the shape h(a1,...,an) and h is defined by pattern matching.
pattern_match_unfolder(unfold_data_manager &datamgr)
data::data_expression unfolded_expr(const data::function_symbol &f, const data::data_expression_vector &args)
bool is_pattern_matching(const data::function_symbol &f)
Checks whether f is defined by pattern matching.
bool is_constructor(const data::function_symbol &f)
data::representative_generator m_repgen
std::vector< std::size_t > pattern_matching_args(const data::function_symbol &f)
std::map< data::function_symbol, data::data_equation > m_new_eqns
bool can_unfold(const data::data_expression &x)
void add_used_identifier(const core::identifier_string &id)
data::data_specification & m_dataspec
bool m_possibly_inconsistent
Boolean indicating whether rewrite rules may be added that could make the data specification inconsis...
mcrl2::data::set_identifier_generator m_identifier_generator
set of identifiers to use during fresh variable generation
void create_determine_function(const data::sort_expression &sort)
Creates the determine function.
void add_used_identifiers(const std::set< core::identifier_string > &ids)
bool is_constructor(const data::function_symbol &f) const
unfold_cache_element & get_cache_element(const data::sort_expression &sort)
mcrl2::core::identifier_string generate_fresh_function_symbol_name(const std::string &str)
Generates a fresh name for a constructor or mapping.
void generate_case_function_equations(const data::sort_expression &sort, const data::function_symbol &case_function)
Create the data equations for case functions.
const data::data_specification & dataspec() const
data::set_identifier_generator & id_gen()
void generate_determine_function_equations(const data::sort_expression &sort)
Create the data equations for the determine function.
void generate_projection_function_equations(const data::sort_expression &sort)
Create the data equations for the projection functions.
void create_new_constructors(const data::sort_expression &sort)
Creates a set of constructors for the fresh basic sort.
std::map< mcrl2::data::sort_expression, unfold_cache_element > & m_cache
cache for previously unfolded sorts. facilitates reuse of previously introduced sorts and function sy...
std::string filter_illegal_characters(std::string in) const
mcrl2::data::variable generate_fresh_variable(std::string str, const data::sort_expression &sort)
Generates variable of type sort based on a given string str.
mcrl2::data::representative_generator m_representative_generator
a generator for default data expressions of a given sort;
mcrl2::data::basic_sort generate_fresh_basic_sort(const data::sort_expression &sort)
Generates a fresh basic sort given a sort expression.
const data::function_symbol_vector & get_projection_funcs(const data::function_symbol &f)
void create_distribution_law_over_case(const data::sort_expression &sort, const data::function_symbol &function_for_distribution, data::function_symbol case_function)
Create distribution rules for distribution_functions over case_functions.
data::function_symbol create_case_function(const data::sort_expression &det_sort, const data::sort_expression &output_sort)
Creates the case function with number of arguments determined by the number of affected constructors,...
data::data_expression create_cases(const data::data_expression &target, const data::data_expression_vector &rhss)
unfold_data_manager(std::map< mcrl2::data::sort_expression, unfold_cache_element > &cache, data::data_specification &dataspec, bool possibly_inconsistent)
detail::data_equation_argument_generator m_data_equation_argument_generator
generator for arguments in left hand side of data equations
bool is_cached(const data::sort_expression &sort) const
const std::vector< data::function_symbol > & get_constructors(const data::sort_expression &sort)
void create_projection_functions(const data::sort_expression &sort)
Creates projection functions for the unfolded process parameter.
void determine_affected_constructors(const data::sort_expression &sort)
Determines the constructors that are affected with the unfold process parameter.
std::map< mcrl2::data::variable, mcrl2::data::data_expression > parameter_substitution()
substitute function for replacing process parameters with unfolded process parameters functions.
void update_linear_process(std::size_t parameter_at_index)
substitute unfold process parameter in the linear process
void update_linear_process_initialization(std::size_t parameter_at_index)
substitute unfold process parameter in the initialization of the linear process
detail::pattern_match_unfolder m_pattern_unfolder
bool m_alt_case_placement
Boolean to indicate if alternative placement of case functions should be used.
mcrl2::data::variable process_parameter_at(std::size_t index)
Get the process parameter at given index.
lpsparunfold(lps::stochastic_specification &spec, std::map< data::sort_expression, unfold_cache_element > &cache, bool alt_case_placement=false, bool possibly_inconsistent=false, bool unfold_pattern_matching=true)
Constructor for lpsparunfold algorithm.
case_func_replacement parameter_case_function()
bool m_run_before
set to true when the algorithm has been run once; as the algorithm should run only once....
bool m_unfold_pattern_matching
Indicates whether functions defined by pattern matching that occur in the scope of a Det or pi in a s...
mcrl2::data::data_expression_vector unfold_constructor(const mcrl2::data::data_expression &de)
unfolds a data expression into a vector of process parameters
void unfold_summands(mcrl2::lps::stochastic_action_summand_vector &summands)
detail::unfold_data_manager m_datamgr
Bookkeeper for recogniser and projection functions.
data::data_expression apply_function(const data::function_symbol &f, const data::data_expression &de) const
mcrl2::data::variable m_unfold_parameter
The process parameter that needs to be unfold.
void algorithm(std::size_t parameter_at_index)
Applies lpsparunfold algorithm on a process parameter of an mCRL2 process specification .
mcrl2::data::variable_vector m_injected_parameters
The process parameters that are inserted.
#define mCRL2log(LEVEL)
mCRL2log(LEVEL) provides the stream used to log.
Definition logger.h:393
data_expression construct_rhs(StructInfo &ssf, representative_generator &gen, const std::vector< rule > &rules, const sort_expression &sort)
For a list of rules with equal left hand sides of match_criteria, construct a right hand side.
std::ostream & operator<<(std::ostream &out, const rule &r)
data_expression construct_condition_rhs(const std::vector< rule > &rules, const data_expression &representative)
For a list of rules with equal left hand sides of match_criteria and only variables in the right hand...
function_symbol get_top_fs(const data_expression &expr)
Get the top level function symbol f if expr is of the shape f or f(t1,...,tn)
Namespace for system defined sort bool_.
Definition bool.h:29
bool is_false_function_symbol(const atermpp::aterm &e)
Recogniser for function false.
Definition bool.h:116
bool is_or_application(const atermpp::aterm &e)
Recogniser for application of ||.
Definition bool.h:342
bool is_bool(const sort_expression &e)
Recogniser for sort expression Bool.
Definition bool.h:51
const basic_sort & bool_()
Constructor for sort expression Bool.
Definition bool.h:41
bool is_implies_application(const atermpp::aterm &e)
Recogniser for application of =>.
Definition bool.h:406
application not_(const data_expression &arg0)
Application of function symbol !.
Definition bool.h:194
application and_(const data_expression &arg0, const data_expression &arg1)
Application of function symbol &&.
Definition bool.h:257
application implies(const data_expression &arg0, const data_expression &arg1)
Application of function symbol =>.
Definition bool.h:385
application or_(const data_expression &arg0, const data_expression &arg1)
Application of function symbol ||.
Definition bool.h:321
const function_symbol & false_()
Constructor for function symbol false.
Definition bool.h:106
bool is_and_application(const atermpp::aterm &e)
Recogniser for application of &&.
Definition bool.h:278
bool is_true_function_symbol(const atermpp::aterm &e)
Recogniser for function true.
Definition bool.h:84
bool is_not_application(const atermpp::aterm &e)
Recogniser for application of !.
Definition bool.h:214
const function_symbol & true_()
Constructor for function symbol true.
Definition bool.h:74
data_expression not_(const data_expression &x)
bool is_application(const data_expression &t)
Returns true if the term t is an application.
bool is_or(const data_expression &x)
Test if x is a disjunction.
Definition consistency.h:52
bool is_false(const data_expression &x)
Test if x is false.
Definition consistency.h:36
data_expression make_exists_(const data::variable_list &v, const data_expression &x)
Make an existential quantification. It checks for an empty variable list, which is not allowed.
data_expression make_forall_(const data::variable_list &v, const data_expression &x)
Make a universal quantification. It checks for an empty variable list, which is not allowed.
data_expression or_(const data_expression &x, const data_expression &y)
bool is_not(const data_expression &x)
Test if x is a negation.
Definition consistency.h:44
data_expression and_(const data_expression &x, const data_expression &y)
const data_expression & false_()
Definition consistency.h:98
bool is_true(const data_expression &x)
Test if x is true.
Definition consistency.h:28
bool is_not_equal_to(const data_expression &x)
Test if x is an inequality.
Definition consistency.h:84
const data_expression & true_()
Definition consistency.h:91
bool is_imp(const data_expression &x)
Test if x is an implication.
Definition consistency.h:68
sort_expression bool_()
bool is_container_sort(const atermpp::aterm &x)
Returns true if the term t is a container sort.
bool is_function_symbol(const atermpp::aterm &x)
Returns true if the term t is a function symbol.
bool is_pattern_matching_rule(StructInfo &ssf, const data_equation &rewrite_rule)
Check whether the given rewrite rule can be classified as a pattern matching rule.
bool is_equal_to(const data_expression &x)
Test if x is an equality.
Definition consistency.h:76
bool is_basic_sort(const atermpp::aterm &x)
Returns true if the term t is a basic sort.
data_expression imp(const data_expression &x, const data_expression &y)
bool is_function_sort(const atermpp::aterm &x)
Returns true if the term t is a function sort.
bool is_bool(const sort_expression &x)
function_symbol if_(const sort_expression &s)
Constructor for function symbol if.
Definition standard.h:196
data_equation unfold_pattern_matching(const function_symbol &mapping, const data_equation_vector &rewrite_rules, StructInfo &ssf, representative_generator &gen, set_identifier_generator &id_gen)
This converts a collection of rewrite rules for a give function symbol into a one-rule specification ...
bool is_and(const data_expression &x)
Test if x is a conjunction.
Definition consistency.h:60
A class that takes a linear process specification and checks all tau-summands of that LPS for conflue...
data::data_expression unfold_pattern_matching(const data::data_expression &x, pattern_match_unfolder &unfolder)
The main namespace for the LPS library.
Definition constelm.h:18
parunfold_replacement< Builder, Binder > apply_parunfold_replacement_builder(const lpsparunfold::case_func_replacement &case_funcs, data::set_identifier_generator &id_generator)
A rule describes a partially pattern-matched rewrite rule.
std::map< data_expression, data_expression > match_criteria
rule(const std::map< data_expression, data_expression > &mc, const data_expression &r, const data_expression &c, const variable_list &v)
static constexpr std::size_t max_unfold_depth
Maximum number of times an expression is unfolded before recursion stops; unfolding this often is eno...
void apply(T &result, const data::application &x)
bool is_applied_to_constructor(const data::application &x)
replace_pattern_match_builder(pattern_match_unfolder &unfolder)
data::data_expression current_replacement
data::detail::capture_avoiding_substitution_updater< parunfold_replacement< Builder, Binder > > sigma1
data::data_expression operator()(const data::variable &x)
parunfold_replacement(const lpsparunfold::case_func_replacement &case_funcs, data::set_identifier_generator &id_generator)
void apply(T &result, const data::application &x)
void apply_case_function(data::data_expression &result, const data::application &expr)
lpsparunfold::case_func_replacement case_funcs
Element in the cache that keeps track of the information for a single unfolded sort,...
std::map< mcrl2::data::sort_expression, mcrl2::data::function_symbol > case_functions
mcrl2::data::basic_sort fresh_basic_sort
mcrl2::data::function_symbol_vector affected_constructors
mcrl2::data::function_symbol determine_function
mcrl2::data::function_symbol_vector projection_functions
mcrl2::data::function_symbol_vector new_constructors
mcrl2::core::identifier_string case_function_name