9#ifndef MCRL2_DATA_UNFOLD_PATTERN_MATCHING_H
10#define MCRL2_DATA_UNFOLD_PATTERN_MATCHING_H
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"
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
61 rule(
const std::map<data_expression, data_expression>& mc,
64 const variable_list& v)
78 return out << core::detail::print_list(r.variables) <<
". " << r.condition <<
" -> " << core::detail::print_map(r.match_criteria) <<
" = " << r.rhs;
90 return atermpp::down_cast<function_symbol>(expr);
94 const application& expr_appl = atermpp::down_cast<application>(expr);
97 return atermpp::down_cast<function_symbol>(expr_appl.head());
104
105
106
107
112 if (rules.size() == 0)
114 return representative;
118 for (
const rule& r: rules)
120 std::map<variable, data_expression> substitution_map;
121 for (
const auto& [var_expr, pattern]: r.match_criteria)
123 assert(is_variable(pattern));
124 substitution_map[atermpp::down_cast<variable>(pattern)] = var_expr;
126 map_substitution<std::map<variable, data_expression> > substitution(substitution_map);
128 data_expression condition = replace_variables_capture_avoiding(r.condition, substitution);
129 data_expression rhs = replace_variables_capture_avoiding(r.rhs, substitution);
131 if (result == data_expression())
137 result = lazy::if_(condition, rhs, result);
145
146
147template <
typename StructInfo>
151 const std::vector<rule>& rules,
157 return construct_condition_rhs(rules, gen(sort));
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
179 NONE, INCOMPLETE, PARTIAL, FULL
181 MatchType matching_type = MatchType::NONE;
184 for (
const auto& [var_expr, _]: rules[0].match_criteria)
186 bool variable_seen =
false;
187 std::set<function_symbol> constructors_seen;
188 for (
const rule& r: rules)
190 const data_expression& pattern = r.match_criteria.at(var_expr);
191 if (is_variable(pattern))
193 variable_seen =
true;
198 function_symbol fs = get_top_fs(pattern);
200 assert(ssf.is_constructor(fs));
201 constructors_seen.insert(fs);
205 MatchType new_matching_type;
206 if (constructors_seen.empty())
209 new_matching_type = MatchType::NONE;
211 else if (variable_seen)
215 new_matching_type = MatchType::PARTIAL;
217 else if (constructors_seen.size() != ssf.get_constructors(var_expr.sort()).size())
222 new_matching_type = MatchType::INCOMPLETE;
228 new_matching_type = MatchType::FULL;
231 if (new_matching_type > matching_type)
233 matching_target = var_expr;
234 matching_type = new_matching_type;
236 if (matching_type == MatchType::FULL)
242 if (matching_type == MatchType::NONE)
246 return construct_condition_rhs(rules, gen(sort));
250
251
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)
257 const data_expression& pattern = r.match_criteria.at(matching_target);
258 if (is_function_symbol(pattern) || is_application(pattern))
261
262
263
264 function_symbol constructor = get_top_fs(pattern);
265 assert(constructor != function_symbol());
266 assert(utilities::detail::contains(match_constructors, constructor));
268 data_expression_vector parameters;
269 if (is_application(pattern))
271 const application& pattern_appl = atermpp::down_cast<application>(pattern);
272 parameters.insert(parameters.end(), pattern_appl.begin(), pattern_appl.end());
276 rule.match_criteria.erase(matching_target);
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); }))
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);
286 for (std::size_t j = 0; j < parameters.size(); j++)
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];
292 constructor_rules[constructor].push_back(rule);
297
298
299
300
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);
307 for (
const function_symbol& f: match_constructors)
309 rule rule(r.match_criteria, rhs, condition, r.variables);
310 rule.match_criteria.erase(matching_target);
312 set_identifier_generator generator;
313 for (
const variable& v: r.variables)
315 generator.add_identifier(v.name());
318 if (is_function_sort(f.sort()))
320 function_sort sort(f.sort());
321 std::size_t index = 0;
322 for (
const sort_expression& s: sort.domain())
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;
332 constructor_rules[f].push_back(rule);
338
339
340
341 data_expression_vector rhs;
342 for (
const auto& f: match_constructors)
344 rhs.push_back(construct_rhs(ssf, gen, constructor_rules[f], sort));
346 return ssf.create_cases(matching_target, rhs);
352
353
354
355
356template <
typename StructInfo>
362 std::set<data_expression> subexpressions = find_data_expressions(rewrite_rule.lhs());
363 subexpressions.erase(rewrite_rule.lhs());
366 subexpressions.erase(application(rewrite_rule.lhs()).head());
369 bool all_pattern = std::all_of(subexpressions.begin(), subexpressions.end(), [&ssf](
const data_expression& 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())));
380 if (std::all_of(subexpressions.begin(), subexpressions.end(), [](
const data_expression& x){
return is_variable(x); }))
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();
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430template <
typename StructInfo>
433 const data_equation_vector& rewrite_rules,
440 variable_vector temp_par;
443 const function_sort& sort = atermpp::down_cast<function_sort>(mapping.sort());
444 for (
const sort_expression& s: sort.domain())
446 temp_par.emplace_back(id_gen(
"x"), s);
449 variable_list new_parameters(temp_par.begin(), temp_par.end());
452 std::vector<detail::rule> rules;
453 for (
const data_equation& eq: rewrite_rules)
455 assert(is_pattern_matching_rule(ssf, eq));
457 std::map<data_expression, data_expression> match_criteria;
458 if (is_application(eq.lhs()))
460 const application& lhs_appl = atermpp::down_cast<application>(eq.lhs());
462 assert(lhs_appl.head() == mapping);
463 assert(new_parameters.size() == lhs_appl.size());
467 auto mappar_it = new_parameters.begin();
468 auto lhspar_it = lhs_appl.begin();
469 while(mappar_it != new_parameters.end())
471 match_criteria[*mappar_it] = *lhspar_it;
472 ++mappar_it, ++lhspar_it;
475 assert(lhspar_it == lhs_appl.end());
478 detail::rule rule(match_criteria, eq.rhs(), eq.condition(), eq.variables());
479 rules.push_back(rule);
481#ifdef MCRL2_ENABLE_MACHINENUMBERS
482 assert(rules.size() != 0 || sort_pos::is_most_significant_digit_function_symbol(mapping));
484 assert(rules.size() != 0);
489 return data_equation(new_parameters, new_lhs, new_rhs);
aterm_string()=default
Default constructor.
basic_sort & operator=(basic_sort &&) noexcept=default
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.
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.
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.
Identifier generator that stores the identifiers of the context in a set. Using the operator()() and ...
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.
const sort_expression & sort() const
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)
unfold_data_manager & m_datamgr
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)
static bool char_filter(char c)
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.
Linear process specification.
#define mCRL2log(LEVEL)
mCRL2log(LEVEL) provides the stream used to log.
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_.
bool is_false_function_symbol(const atermpp::aterm &e)
Recogniser for function false.
bool is_or_application(const atermpp::aterm &e)
Recogniser for application of ||.
bool is_bool(const sort_expression &e)
Recogniser for sort expression Bool.
const basic_sort & bool_()
Constructor for sort expression Bool.
bool is_implies_application(const atermpp::aterm &e)
Recogniser for application of =>.
application not_(const data_expression &arg0)
Application of function symbol !.
application and_(const data_expression &arg0, const data_expression &arg1)
Application of function symbol &&.
application implies(const data_expression &arg0, const data_expression &arg1)
Application of function symbol =>.
application or_(const data_expression &arg0, const data_expression &arg1)
Application of function symbol ||.
const function_symbol & false_()
Constructor for function symbol false.
bool is_and_application(const atermpp::aterm &e)
Recogniser for application of &&.
bool is_true_function_symbol(const atermpp::aterm &e)
Recogniser for function true.
bool is_not_application(const atermpp::aterm &e)
Recogniser for application of !.
const function_symbol & true_()
Constructor for function symbol true.
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.
bool is_false(const data_expression &x)
Test if x is false.
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.
data_expression and_(const data_expression &x, const data_expression &y)
const data_expression & false_()
bool is_true(const data_expression &x)
Test if x is true.
bool is_not_equal_to(const data_expression &x)
Test if x is an inequality.
const data_expression & true_()
bool is_imp(const data_expression &x)
Test if x is an implication.
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.
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.
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.
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.
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)
data_expression condition
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)
pattern_match_unfolder & m_unfolder
bool is_applied_to_constructor(const data::application &x)
std::size_t m_current_depth
replace_pattern_match_builder(pattern_match_unfolder &unfolder)
bool m_currently_recursing
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