mCRL2
Loading...
Searching...
No Matches
lpsparunfoldlib.cpp
Go to the documentation of this file.
1// Author(s): Frank Stappers, Jeroen Keiren, 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
16#include <iterator>
18#include "mcrl2/lps/replace.h"
19
20using namespace mcrl2;
21using namespace mcrl2::core;
22using namespace mcrl2::data;
23using namespace mcrl2::log;
25
26/* Remarks
27- replace on vectors does not work
28- vector pretty print does not work
29- alias::name() [basic_sort] results in a basic sort, differs form basic_sort::name() [string]
30*/
31
32namespace mcrl2::lps::detail
33{
34
36{
37 assert(sort != data::sort_expression());
38
39 std::map< data::sort_expression, unfold_cache_element >::iterator ce = m_cache.find(sort);
40 if(ce == m_cache.end())
41 {
42 /* Not using cache */
43 unfold_cache_element& new_cache_element = m_cache[sort];
44 /* Alg */
45 /* 1 */
46 new_cache_element.fresh_basic_sort = generate_fresh_basic_sort(sort);
47 m_dataspec.add_sort(new_cache_element.fresh_basic_sort );
48
49 /* 2 */
51
52 // If there are no constructors, there is nothing to be done.
53 if (!new_cache_element.affected_constructors.empty())
54 {
55 /* 4 */
57 /* 6 */
58 create_case_function(sort, sort);
59 /* 7 */
61 /* 8-12 */
63 }
64 return new_cache_element;
65 }
66 else
67 {
68 /* Using cache */
69 mCRL2log(log::debug) << "Update using cache for sort: \"" << data::pp(sort) << "\"..." << std::endl;
70 return ce->second;
71 }
72}
73
75{
76 //Generate a fresh Basic Sort
77 std::string hint("S");
78 if(data::is_basic_sort(sort))
79 {
80 hint = atermpp::down_cast<basic_sort>(sort).name();
81 }
82 else if(data::is_container_sort(sort))
83 {
85 }
86
87 const data::basic_sort result(m_identifier_generator(hint));
88 mCRL2log(log::verbose) << "Generated fresh sort \"" << data::pp(result) << "\" for \"" << data::pp(sort) << "\"" << std::endl;
89 return result;
90}
91
93{
94 //Generate a fresh name for a constructor of mapping
96 mCRL2log(debug) << "Generated a fresh function symbol name: " << result << std::endl;
97 return result;
98}
99
101{
102 return data::variable(m_identifier_generator(str.append("_pp")), sort);
103}
104
106{
107 unfold_cache_element& new_cache_element = m_cache[sort];
108 assert(new_cache_element.affected_constructors.empty());
109
110 new_cache_element.affected_constructors = m_dataspec.constructors(sort);
111
112 mCRL2log(debug) << "constructors of unfolded sort:\t";
113 mCRL2log(log::verbose) << "" << sort << " has " << new_cache_element.affected_constructors.size() << " constructor function(s)" << std::endl;
114
116 {
117 for (const function_symbol& f : new_cache_element.affected_constructors)
118 {
119 mCRL2log(debug) << "\t" << f << std::endl;
120 }
121 }
122}
123
125{
126 unfold_cache_element& new_cache_element = m_cache[sort];
127 assert(new_cache_element.new_constructors.empty());
128
129 for (const function_symbol& func: new_cache_element.affected_constructors)
130 {
131 std::string prefix = "c_";
132 prefix.append(func.name());
134 new_cache_element.fresh_basic_sort);
135 new_cache_element.new_constructors.push_back(f);
137 mCRL2log(debug) << "\t" << f << std::endl;
138 }
139 mCRL2log(debug) << "- Created " << new_cache_element.new_constructors.size() << " fresh \" c_ \" constructor(s)" << std::endl;
140}
141
143{
144 unfold_cache_element& new_cache_element = m_cache[det_sort];
145 // Generate new function symbol that is used for all case functions related
146 // to unfolding new_cache_element.fresh_basic_sort.
147 if (new_cache_element.case_function_name == core::identifier_string())
148 {
149 std::string str = "C_";
150 str.append(new_cache_element.fresh_basic_sort.name());
151 new_cache_element.case_function_name =
153 }
154
155 // Check if the function symbol was already in the cache; if not, create and add it
156 std::map<mcrl2::data::sort_expression, mcrl2::data::function_symbol>::const_iterator
157 case_function_it = new_cache_element.case_functions.find(output_sort);
158 if(case_function_it == new_cache_element.case_functions.end())
159 {
160 // all except first argument are the sort of the unfolded type.
161 data::sort_expression_vector fsl(new_cache_element.affected_constructors.size() + 1, output_sort);
162 fsl[0] = new_cache_element.fresh_basic_sort ;
163
164 data::function_symbol fs(new_cache_element.case_function_name,
165 data::function_sort(fsl, output_sort));
166
167 mCRL2log(debug) << "- Created C map: " << fs << std::endl;
168 new_cache_element.case_functions[output_sort] = fs;
170
171 // generate and add equations.
173 return fs;
174 }
175 else
176 {
177 return case_function_it->second;
178 }
179}
180
182{
183 unfold_cache_element& new_cache_element = m_cache[sort];
184 std::string str = "Det_";
185 str.append(std::string(new_cache_element.fresh_basic_sort.name()));
186 new_cache_element.determine_function =
189 new_cache_element.fresh_basic_sort ));
190 mCRL2log(debug) << "\t" << new_cache_element.determine_function << std::endl;
191 m_dataspec.add_mapping(new_cache_element.determine_function);
192
194}
195
197{
198 unfold_cache_element& new_cache_element = m_cache[sort];
199 std::string str = "pi_";
200 str.append(std::string(new_cache_element.fresh_basic_sort.name()));
201
202 for (const function_symbol& f: new_cache_element.affected_constructors)
203 {
204 if (is_function_sort(f.sort()))
205 {
206 const function_sort fs = atermpp::down_cast<function_sort>(f.sort());
207 for (const sort_expression& argument_sort: fs.domain())
208 {
211 argument_sort));
213 new_cache_element.projection_functions.push_back(map);
214 }
215 }
216 }
217
219 {
220 for (const function_symbol& f : new_cache_element.projection_functions)
221 {
222 mCRL2log(debug) << "\t" << f << std::endl;
223 }
224 }
225
227}
228
230{
231 unfold_cache_element& new_cache_element = m_cache[sort];
232 // Add projection functions for the arguments of the original constructors.
233 function_symbol_vector::const_iterator pi_it = new_cache_element.projection_functions.begin();
234 for (const function_symbol& f : new_cache_element.affected_constructors)
235 {
237 const variable_list f_arguments_list(f_arguments.begin(), f_arguments.end());
238
239 for(const variable& arg: f_arguments)
240 {
241 const application lhs(*pi_it, application(f, f_arguments_list));
242 m_dataspec.add_equation(data_equation(f_arguments_list, lhs, arg));
243
244 // For the same projection function, generate right hand sides with default
245 // values if the projection function is applied to an expression with a
246 // constructor that it was not intended for.
247 for (const function_symbol& g: new_cache_element.affected_constructors)
248 {
249 if (f != g)
250 {
251 const variable_vector g_arguments(
253 const variable_list g_arguments_list(g_arguments.begin(), g_arguments.end());
254 application lhs;
255 if (g_arguments.empty())
256 {
257 lhs = application(*pi_it, g);
258 }
259 else
260 {
261 lhs = application(
262 *pi_it, application(g, g_arguments_list));
263 }
264 try
265 {
267 m_dataspec.add_equation(data_equation(g_arguments_list, lhs, rhs));
268 }
269 catch (runtime_error& e)
270 {
271 mCRL2log(debug) << "Failed to generate equation " << data::pp(lhs)
272 << "= ... as no default term of sort "
273 << data::pp(lhs.sort()) << " could be generated.\n"
274 << e.what() << "\n";
275 }
276 }
277 }
278
279 // If so desired, add distribution of pi over if and case functions
280 // pi(if(b,x,y))=if(b,pi(x),pi(y));
281 // pi(C(e,x1,x2,...))=C(e,pi(x1),pi(x2),...);
282 create_distribution_law_over_case(sort, *pi_it, data::if_(sort));
283 create_distribution_law_over_case(sort, *pi_it, new_cache_element.case_functions[sort]);
284
285 ++pi_it;
286 }
287 }
288}
289
290// Add equation for f(C(e, d_1, ..., d_n)) = C(e, f(d_1), ..., f(d_n))
291// note: the case_function parameter must be copied; passing by reference
292// may lead to crashes if the argument is an element of
293// new_cache_element.case_functions if a new case function is introduced.
295 const data::sort_expression& sort,
296 const data::function_symbol& f,
297 const data::function_symbol case_function)
298{
299 assert(case_function.sort().target_sort() == atermpp::down_cast<function_sort>(f.sort()).domain().front());
300
301 // C(e, d_1, ..., d_n)
303 application lhs(f, application(case_function, lhs_args));
304
305 // Construct rhs arguments e, f(d_1), ..., f(d_n)
306 data_expression_vector rhs_args;
307 variable_vector::const_iterator args = lhs_args.begin();
308 for (variable_vector::const_iterator i = lhs_args.begin(); i != lhs_args.end(); ++i)
309 {
310 if(i == lhs_args.begin())
311 {
312 rhs_args.push_back(*args);
313 }
314 else
315 {
316 rhs_args.emplace_back(application(f, *i));
317 }
318 }
319
320 // Determine the new case function or if function symbol.
321 data::function_symbol new_case_function;
322 if(data::is_if_function_symbol(case_function))
323 {
324 new_case_function = data::if_(f.sort().target_sort());
325 }
326 else
327 {
328 new_case_function = create_case_function(sort, f.sort().target_sort());
329 }
330
331 data::application rhs(new_case_function , rhs_args);
332 data::data_equation result(lhs_args, lhs, rhs);
333 m_dataspec.add_equation(result);
334
335 mCRL2log(log::verbose) << "- Added distribution law for \"" << data::pp(f) << "\" over \"" << data::pp(case_function) << "\": " << data::pp(result) << std::endl;
336}
337
339{
340 mCRL2log(log::verbose) << "- Generating case function equations for:\t" << data::pp(case_function) << ": " << data::pp(case_function.sort()) << "" << std::endl;
341
342 unfold_cache_element& new_cache_element = m_cache[sort];
343 assert(atermpp::down_cast<function_sort>(case_function.sort()).domain().size() == new_cache_element.new_constructors.size() + 1);
344 /* Generate variable identifier string for projection */
346 const variable_list used_vars(++vars.begin(), vars.end()); // all but the first parameter are used in the data equation.
347
348 // We generate one equation for each of the constructors of the new sort,
349 // projecting out the corresponding argument.
350 // C(c_i, d_1,...,d_(i-1), d_i, d_(i+1), ..., d_n) = d_i;
351 data_expression_vector sub_args(vars.begin(), vars.end());
352 // vars_it represents d_i above.
353 variable_vector::const_iterator vars_it = vars.begin();
354 ++vars_it; // first variable to be skipped.
355
356 for(data::function_symbol new_constructor: new_cache_element.new_constructors)
357 {
358 sub_args[0] = new_constructor; // set c_i
359 const application lhs(case_function , sub_args);
360 m_dataspec.add_equation(data_equation(used_vars, lhs, *vars_it));
361 ++vars_it;
362 }
363
364 // Add an equation that removes a case function if all (except the first)
365 // argument are the same.
366 // C(x, d_n, ...., d_n) = d_n
367 data_expression_vector eq_args(new_cache_element.new_constructors.size() + 1, vars.back());
368 eq_args[0] = vars.front();
369 const application lhs(case_function , eq_args);
370 m_dataspec.add_equation(data_equation(data::variable_list({vars.front(), vars.back()}), lhs, vars.back()));
371
372 if (m_dataspec.equal_sorts(case_function.sort().target_sort(), vars.front().sort()))
373 {
374 // Add an equation that rewrites to the first argument if the remainder are the corresponding constructors
375 // C(x, c_1, ..., c_n) = x
376 data_expression_vector cs_args{vars.front()};
377 for (const function_symbol& cs: new_cache_element.new_constructors)
378 {
379 cs_args.push_back(cs);
380 }
381 m_dataspec.add_equation(data_equation(data::variable_list({vars.front()}), application(case_function, cs_args), vars.front()));
382 }
383
384 // If the case function maps to the Booleans, we can replace it by a disjunction.
385 // Note: this may make the data specification inconsistent.
387 {
388 // C(x, d_1, ..., d_n) = (d_1 && x == c_1) || (c_2 && x == c_2) || .... (d_n && x == c_n)
389 const data::variable_list args(vars.begin(), vars.end());
390 const application lhs(case_function, args);
391
392 data_expression_vector disjuncts;
393 vars_it = vars.begin();
394 const variable det_var = *vars_it++;
395 for(const function_symbol& constructor: new_cache_element.new_constructors)
396 {
397 if(vars_it == vars.end())
398 {
399 throw mcrl2::runtime_error("The number of variables and the number of constructors differs.");
400 }
401 disjuncts.push_back(
402 sort_bool::and_(*vars_it++, equal_to(det_var, constructor)));
403 }
404
405 m_dataspec.add_equation(data_equation(args, lhs, lazy::join_or(disjuncts.begin(), disjuncts.end())));
406
407 // We also need to add rules for equality on the new sort.
408 for(const function_symbol& left: new_cache_element.new_constructors)
409 {
410 for(const function_symbol& right: new_cache_element.new_constructors)
411 {
412 if (left != right)
413 {
414 const application lhs = data::equal_to(left, right);
415 const data_expression rhs = data::false_();
417 }
418 }
419 }
420 }
421}
422
424{
425 unfold_cache_element& new_cache_element = m_cache[sort];
426 function_symbol_vector::const_iterator constructor_it = new_cache_element.new_constructors.begin();
427 for (const function_symbol& f: new_cache_element.affected_constructors)
428 {
429 assert(constructor_it != new_cache_element.new_constructors.end());
430 /* Creating an equation for the detector function */
432 if(function_arguments.empty())
433 {
435 application(new_cache_element.determine_function, f),
436 *constructor_it));
437 }
438 else
439 {
440 const variable_list args(function_arguments.begin(), function_arguments.end());
442 args,
443 application(new_cache_element.determine_function,
444 application(f,args)),
445 *constructor_it));
446 }
447 ++constructor_it;
448 }
449
450 /* Add additional distribution laws for Det over if and case functions
451 Det(if(b,x,y))=if(b,Det(x),Det(y));
452 Det(C(e,x1,x2,...))=C(e,Det(x1),Det(x2),...);
453 */
454 create_distribution_law_over_case(sort, new_cache_element.determine_function, data::if_(sort));
455 create_distribution_law_over_case(sort, new_cache_element.determine_function, new_cache_element.case_functions[sort]);
456}
457
458} // namespace mcrl2::lps::detail
459
460
463 std::map< data::sort_expression , unfold_cache_element >& cache,
464 bool alt_case_placement,
465 bool possibly_inconsistent,
467 : lps::detail::lps_algorithm<lps::stochastic_specification>(spec),
468 m_run_before(false),
469 m_datamgr(cache, spec.data(), possibly_inconsistent),
470 m_pattern_unfolder(m_datamgr),
471 m_alt_case_placement(alt_case_placement),
472 m_unfold_pattern_matching(unfold_pattern_matching)
473{
476 for (const function_symbol& f : spec.data().constructors())
477 {
479 }
480 for (const function_symbol& f : spec.data().mappings())
481 {
483 }
484}
485
487{
488 for (lps::stochastic_action_summand& summand: summands)
489 {
490 data::assignment_vector new_assignments;
491 for (const data::assignment& k: summand.assignments())
492 {
493 if (k.lhs() == m_unfold_parameter)
494 {
495 const data::data_expression_vector new_rhs = unfold_constructor(k.rhs());
497 new_assignments.insert(new_assignments.end(), injected_assignments.begin(), injected_assignments.end());
498 }
499 else
500 {
501 new_assignments.push_back(k);
502 }
503 }
504 summand.assignments() = data::assignment_list(new_assignments.begin(), new_assignments.end());
505 }
506}
507
509{
512
513 auto new_pars_it = m_injected_parameters.cbegin();
514 ++new_pars_it;
515
516 for (const data::function_symbol& constr: new_cache_element.affected_constructors )
517 {
518 data::data_expression case_func_arg = constr;
519
520 if (is_function_sort(constr.sort()))
521 {
522 sort_expression_list dom = function_sort(constr.sort()).domain();
524
525 for (const data::sort_expression& arg_sort: dom)
526 {
527 if (new_pars_it->sort() != arg_sort)
528 {
529 throw runtime_error("Unexpected new parameter encountered, maybe they were not sorted well.");
530 }
531 arg.push_back(*new_pars_it++);
532 }
533 case_func_arg = data::application(constr, arg);
534 }
535
536 dev.push_back(case_func_arg);
537 }
538
539 return std::make_tuple(m_unfold_parameter, new_cache_element.case_functions, m_injected_parameters[0], dev);
540
541}
542
543void lpsparunfold::update_linear_process(std::size_t parameter_at_index)
544{
545 /* Get process parameters from lps */
546 const data::variable_list& process_parameters = m_spec.process().process_parameters();
547
548 /* Iterator pointing to the parameter that needs to be unfolded */
549 data::variable_list::const_iterator unfold_parameter_it =
550 process_parameters.begin();
551 std::advance(unfold_parameter_it, parameter_at_index);
552
553 mCRL2log(log::verbose) << "Updating LPS..." << std::endl;
554
555 /* Create new process parameters */
556 data::variable_vector new_process_parameters;
557
558 /* Expand unfold_parameter */
559 mCRL2log(log::verbose) << " Unfolding parameter " << unfold_parameter_it->name() << " at index " << parameter_at_index << "..." << std::endl;
560
561 /* First copy the initial part of the parameters */
562 new_process_parameters.insert(new_process_parameters.end(),
563 process_parameters.begin(),
564 unfold_parameter_it);
565
568 m_injected_parameters.push_back(param);
569
571 << "- Created process parameter " << data::pp(m_injected_parameters.back())
572 << " of type " << data::pp(new_cache_element.fresh_basic_sort ) << "" << std::endl;
573
574 for (const data::function_symbol& constructor: new_cache_element.affected_constructors)
575 {
576 if (is_function_sort(constructor.sort()))
577 {
578 const sort_expression_list domain = function_sort(constructor.sort()).domain();
579 for (const sort_expression& s: domain)
580 {
582 m_injected_parameters.push_back(param);
583 mCRL2log(log::verbose) << "- Injecting process parameter: " << param
584 << "::" << pp(s) << std::endl;
585 }
586 }
587 else if (is_basic_sort(constructor.sort())
588 || is_structured_sort(constructor.sort())
589 || is_container_sort(constructor.sort()))
590 {
591 mCRL2log(debug) << "- No process parameters are injected for constant: "
592 << constructor << std::endl;
593 }
594 else
595 {
596 throw mcrl2::runtime_error("Parameter " + pp(constructor) + " has an unsupported type " + pp(constructor.sort()));
597 }
598 }
599
600 new_process_parameters.insert(new_process_parameters.end(),
601 m_injected_parameters.begin(),
603
604
605 ++unfold_parameter_it;
606 /* Copy the remainder of the parameters */
607 new_process_parameters.insert(new_process_parameters.end(),
608 unfold_parameter_it, process_parameters.end());
609
610 mCRL2log(debug) << "- New LPS process parameters: " << data::pp(new_process_parameters) << std::endl;
611
612 // update the summands in new_lps
614
615 // Replace occurrences of unfolded parameters by the corresponding case function
616 // Clear process parameters first, to ensure capture avoiding substitution
617 // ignores the process parameters.
620 {
623
624 // process parameters
625 for (const data::variable& param : new_process_parameters)
626 {
628 }
629
630 // parameters of actions
631 for (const process::action_label& action_label : m_spec.action_labels())
632 {
633 for (const sort_expression& s : action_label.sorts())
634 {
636 }
637 }
638
639 mCRL2log(log::verbose) << "- Inserting case functions into the process using alternative case placement" << std::endl;
640 // place the case functions
642 }
643 else
644 {
645 mCRL2log(log::verbose) << "- Inserting case functions into the process using default case placement" << std::endl;
646 //Prepare parameter substitution
649 }
650
652 {
653 // Unfold pattern matching mappings in parameter updates, requires intermediate rewriting
654 data::rewriter rewr(m_spec.data());
656 {
657 data::assignment_vector new_assignments;
658 for (const assignment& as: sum.assignments())
659 {
660 new_assignments.emplace_back(as.lhs(), unfold_pattern_matching(rewr(as.rhs()), m_pattern_unfolder));
661 }
662 sum.assignments() = data::assignment_list(new_assignments.begin(), new_assignments.end());
663 }
664 }
665
666 // NB: order is important. If we first replace the parameters, they are changed
667 // again when performing the capture avoiding substitution, most likely leading
668 // to an LPS that is not well-formed.
669 m_spec.process().process_parameters() = data::variable_list(new_process_parameters.begin(), new_process_parameters.end());
670
671 mCRL2log(debug) << "\nNew LPS:\n" << lps::pp(m_spec.process()) << std::endl;
672
674}
675
677 std::size_t parameter_at_index)
678{
679 //
680 //update inital process
681 //
682 mCRL2log(log::verbose) << "Updating initialization...\n" << std::endl;
683
684 //Unfold parameters
686 size_t index=0;
688 {
689 if (index == parameter_at_index)
690 {
692 //Replace unfold parameters in affected assignments
693 new_init.insert(new_init.end(), ins.begin(), ins.end());
694 }
695 else
696 {
697 new_init.push_back(k);
698 }
699 ++index;
700 }
701
703 data_expression_list(new_init.begin(), new_init.end()),
705
706 mCRL2log(debug) << "Expressions for the new initial state: " << data::pp(m_spec.initial_process().expressions()) << std::endl;
707}
708
709std::map<data::variable, data::data_expression> lpsparunfold::parameter_substitution()
710{
712 std::map<data::variable, data::data_expression> result;
713
715
716 auto new_pars_it = m_injected_parameters.cbegin();
717 dev.push_back(data_expression(*new_pars_it));
718 ++new_pars_it;
719
720 for (const data::function_symbol& constr: new_cache_element.affected_constructors)
721 {
722 data::data_expression case_func_arg = constr;
723
724 if (is_function_sort(constr.sort()))
725 {
726 sort_expression_list dom = function_sort(constr.sort()).domain();
728
729 for (const data::sort_expression& arg_sort: dom)
730 {
731 if (new_pars_it->sort() != arg_sort)
732 {
733 throw runtime_error("Unexpected new parameter encountered, maybe they were not sorted well.");
734 }
735 arg.push_back(*new_pars_it++);
736 }
737 case_func_arg = data::application(constr, arg);
738 }
739
740 dev.push_back(case_func_arg);
741 }
743 << "Parameter substitution:\t" << m_unfold_parameter
744 << "\t->\t" << data::application(new_cache_element.case_functions.at(m_unfold_parameter.sort()), dev) << std::endl;
745 result.insert(std::make_pair(
747 return result;
748}
749
751{
753 {
754 return data::if_(atermpp::down_cast<data::application>(de)[0],
755 apply_function(f, atermpp::down_cast<data::application>(de)[1]),
756 apply_function(f, atermpp::down_cast<data::application>(de)[2]));
757 }
758 else
759 {
760 return application(f, de);
761 }
762}
763
765{
766 assert(de.sort() == m_unfold_parameter.sort());
769
770 // Replace global variables with fresh global variables.
771 if(data::is_variable(de) &&
772 m_spec.global_variables().find(atermpp::down_cast<variable>(de)) != m_spec.global_variables().end())
773 {
774 // don't care for det position
776 result.push_back(v);
777 m_spec.global_variables().insert(v);
778
779 // don't cares for each of the arguments
780 for (const function_symbol& f: new_cache_element.projection_functions)
781 {
782 v = m_datamgr.generate_fresh_variable("dc", f.sort().target_sort());
783 result.push_back(v);
784 m_spec.global_variables().insert(v);
785 }
786 }
787 else
788 {
789 /* Det function */
790 result.emplace_back(apply_function(new_cache_element.determine_function, de));
791
792 for (const function_symbol& f: new_cache_element.projection_functions)
793 {
794 result.emplace_back(apply_function(f, de));
795 }
796 }
797
798 return result;
799}
800
802{
803 mCRL2log(debug) << "- Number of parameters in LPS: " << m_spec.process().process_parameters().size() << "" << std::endl;
804 mCRL2log(log::verbose) << "Unfolding process parameter at index: " << index << "" << std::endl;
805 if ( m_spec.process().process_parameters().size() <= index)
806 {
807 throw mcrl2::runtime_error("Given index out of bounds. Index value needs to be in the range [0," + std::to_string(m_spec.process().process_parameters().size()) + ").");
808 }
809
811 std::advance(parameter_it, index);
812 return *parameter_it;
813}
814
815void lpsparunfold::algorithm(const std::size_t parameter_at_index)
816{
817 // Can only be run once as local data structures are not cleared
818 assert(!m_run_before);
819 m_run_before = true;
820
821 m_unfold_parameter = process_parameter_at(parameter_at_index);
823
824 // Perform the actual unfolding (if needed)
825 if (new_cache_element.affected_constructors.empty())
826 {
827 mCRL2log(log::verbose) << "The selected process parameter " << m_unfold_parameter.name() << " has no constructors." << std::endl;
828 mCRL2log(log::verbose) << "No need to unfold." << std::endl;
829 }
830 else
831 {
832 update_linear_process(parameter_at_index);
833 update_linear_process_initialization(parameter_at_index);
834 }
835
837}
Term containing a string.
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
An application of a data expression to a number of arguments.
\brief Assignment of a data expression to a variable
Definition assignment.h:91
\brief A basic sort
Definition basic_sort.h:26
const core::identifier_string & name() const
Definition basic_sort.h:57
\brief A data equation
sort_expression sort() const
Returns the sort of the data expression.
Definition data.cpp:108
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.
bool equal_sorts(sort_expression const &s1, sort_expression const &s2) const
Checks whether two sort expressions represent the same sort.
void add_constructor(const function_symbol &f)
Adds a constructor to this specification.
const function_symbol_vector & constructors() const
Gets all constructors including those that are system defined.
const function_symbol_vector & mappings() const
Gets all mappings in this specification including those that are system defined.
\brief A function sort
const sort_expression_list & domain() const
\brief A function symbol
const sort_expression & sort() const
Generic substitution function. The substitution is stored as a mapping of variables to expressions....
Rewriter that operates on data expressions.
Definition rewriter.h:81
\brief A sort expression
const sort_expression & target_sort() const
Returns the target sort of this expression.
void add_sort(const basic_sort &s)
Adds a sort to this specification.
\brief A data variable
Definition variable.h:28
const core::identifier_string & name() const
Definition variable.h:38
const sort_expression & sort() const
Definition variable.h:43
LPS summand containing a multi-action.
data::variable_vector arguments(const data::function_symbol &f)
Generate argument variables for f.
lps::stochastic_specification & m_spec
The specification that is processed by the algorithm.
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)
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.
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.
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,...
void create_distribution_law_over_case(const data::sort_expression &sort, const data::function_symbol &function_for_distribution, const data::function_symbol case_function)
Create distribution rules for distribution_functions over case_functions.
detail::data_equation_argument_generator m_data_equation_argument_generator
generator for arguments in left hand side of data equations
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.
const std::vector< ActionSummand > & action_summands() const
Returns the sequence of action summands.
const data::variable_list & process_parameters() const
Returns the sequence of process parameters.
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
std::tuple< data::variable, std::map< data::sort_expression, data::function_symbol >, data::variable, data::data_expression_vector > case_func_replacement
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
mcrl2::data::variable process_parameter_at(const std::size_t index)
Get the process parameter at given index.
bool m_alt_case_placement
Boolean to indicate if alternative placement of case functions should be used.
void algorithm(const std::size_t parameter_at_index)
Applies lpsparunfold algorithm on a process parameter of an mCRL2 process specification .
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.
mcrl2::data::variable_vector m_injected_parameters
The process parameters that are inserted.
data::data_expression_list expressions() const
const std::set< data::variable > & global_variables() const
Returns the declared free variables of the LPS.
const process::action_label_list & action_labels() const
Returns a sequence of action labels. This sequence contains all action labels occurring in the specif...
const InitialProcessExpression & initial_process() const
Returns the initial process.
const LinearProcess & process() const
Returns the linear process of the specification.
const data::data_specification & data() const
Returns the data specification.
LPS summand containing a multi-action.
const stochastic_distribution & distribution() const
\brief An action label
Standard exception class for reporting runtime errors.
Definition exception.h:27
@ func
Definition linearise.cpp:77
#define mCRL2log(LEVEL)
mCRL2log(LEVEL) provides the stream used to log.
Definition logger.h:391
add your file description here.
data_expression join_or(ForwardTraversalIterator first, ForwardTraversalIterator last)
Returns or applied to the sequence of data expressions [first, last)
bool is_bool(const sort_expression &e)
Recogniser for sort expression Bool.
Definition bool.h:54
const basic_sort & bool_()
Constructor for sort expression Bool.
Definition bool.h:44
const function_symbol & and_()
Constructor for function symbol &&.
Definition bool.h:235
const basic_sort & real_()
Constructor for sort expression Real.
Definition real1.h:48
Namespace for all data library functionality.
Definition abstraction.h:22
std::vector< assignment > assignment_vector
\brief vector of assignments
Definition assignment.h:149
bool is_structured_sort(const atermpp::aterm &x)
Returns true if the term t is a structured sort.
void find_identifiers(const T &x, OutputIterator o)
Definition find.h:359
std::vector< sort_expression > sort_expression_vector
\brief vector of sort_expressions
bool is_if_application(const DataExpression &e)
Recogniser for application of if.
Definition standard.h:232
std::vector< variable > variable_vector
\brief vector of variables
Definition variable.h:89
function_sort make_function_sort_(const sort_expression &dom1, const sort_expression &codomain)
Convenience constructor for function sort with domain size 1.
const data_expression & false_()
Definition consistency.h:99
std::vector< data_expression > data_expression_vector
\brief vector of data_expressions
std::string pp(const abstraction &x)
Definition data.cpp:39
bool is_container_sort(const atermpp::aterm &x)
Returns true if the term t is a container sort.
atermpp::term_list< data_expression > data_expression_list
\brief list of data_expressions
bool is_basic_sort(const atermpp::aterm &x)
Returns true if the term t is a basic sort.
bool is_if_function_symbol(const DataExpression &e)
Recogniser for function if.
Definition standard.h:209
atermpp::term_list< variable > variable_list
\brief list of variables
bool is_function_sort(const atermpp::aterm &x)
Returns true if the term t is a function sort.
assignment_vector make_assignment_vector(VariableSequence const &variables, ExpressionSequence const &expressions)
Constructs an assignment_list by pairwise combining a variable and expression.
Definition assignment.h:281
atermpp::term_list< assignment > assignment_list
\brief list of assignments
Definition assignment.h:146
function_symbol equal_to(const sort_expression &s)
Constructor for function symbol ==.
Definition standard.h:126
function_symbol if_(const sort_expression &s)
Constructor for function symbol if.
Definition standard.h:200
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_variable(const atermpp::aterm &x)
Returns true if the term t is a variable.
@ verbose
Definition logger.h:37
bool mCRL2logEnabled(const log_level_t level)
Definition logger.h:383
std::vector< stochastic_action_summand > stochastic_action_summand_vector
\brief vector of stochastic_action_summands
bool check_well_typedness(const linear_process &x)
Definition lps.cpp:92
void replace_variables_capture_avoiding(T &x, Substitution &sigma, data::set_identifier_generator &id_generator, typename std::enable_if<!std::is_base_of< atermpp::aterm, T >::value >::type *=nullptr)
std::string pp(const action_summand &x)
Definition lps.cpp:26
void insert_case_functions(T &x, const lpsparunfold::case_func_replacement &cfv, data::set_identifier_generator &id_generator, typename std::enable_if<!std::is_base_of< atermpp::aterm, T >::value >::type *=nullptr)
void find_identifiers(const T &x, OutputIterator o)
Definition find.h:96
A class that takes a linear process specification and checks all tau-summands of that LPS for conflue...
Definition indexed_set.h:72
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