mCRL2
Loading...
Searching...
No Matches
absinthe.h
Go to the documentation of this file.
1// Author(s): Wieger Wesselink
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/// \file mcrl2/pbes/absinthe.h
10/// \brief add your file description here.
11
12#ifndef MCRL2_PBES_ABSINTHE_H
13#define MCRL2_PBES_ABSINTHE_H
14
15#include "mcrl2/atermpp/aterm.h"
16#include "mcrl2/data/data_expression.h"
17#include "mcrl2/data/consistency.h"
18#include "mcrl2/data/detail/data_construction.h"
19#include "mcrl2/pbes/builder.h"
20#include "mcrl2/utilities/detail/separate_keyword_section.h"
21#include "mcrl2/data/detail/print_parse_check.h"
22
23namespace mcrl2::pbes_system
24{
25
26template <typename Term>
28{
29 return data::pp(x) + " " + data::pp(x);
30 }
31
32 template <typename Term>
34 {
35 return data::pp(x) + ": " + data::pp(x.sort());
36 }
37
38namespace detail {
39
40 inline
42 {
43 static data::data_specification dataspec;
44 return dataspec;
45 }
46
47 template <typename T>
48 inline void absinthe_check_expression(const T& x)
49 {
50 data::detail::print_parse_check(x, absinthe_data_specification());
51 }
52
53 // Returns true if f appears as a structured sort constructor in dataspec.
54 inline
56 {
57 for (const data::alias& a: dataspec.user_defined_aliases())
58 {
59 if (f.sort() != a.name())
60 {
61 continue;
62 }
63 const data::sort_expression& s = a.reference();
64 if (data::is_structured_sort(s))
65 {
66 const auto& ss = atermpp::down_cast<data::structured_sort>(s);
67 for (const data::function_symbol& g: ss.constructor_functions())
68 {
69 if (f.name() == g.name())
70 {
71 return true;
72 }
73 }
74 }
75 }
76 return false;
77 }
78
79 inline
81 {
82 mCRL2log(log::debug) << "--- used function symbols ---" << std::endl;
83 for (const data::function_symbol& f: pbes_system::find_function_symbols(p))
84 {
85 mCRL2log(log::debug) << print_symbol(f) << std::endl;
86 }
87 }
88
89 // TODO: Is this correct if s has the shape A -> (B -> C)? Should the result be (B -> C) or C?
90 inline
92 {
94 {
95 return s;
96 }
98 {
99 const auto& fs = atermpp::down_cast<data::function_sort>(s);
100 return fs.codomain();
101 }
103 {
104 return s;
105 }
106 throw mcrl2::runtime_error("target_sort: unsupported sort " + print_term(s) + " detected!");
108 }
109
110} // namespace detail
111
113{
117
118 // Used for generating variables of sort comprehensions.
120
122 {
124 using super::apply;
125
130
131 absinthe_sort_expression_builder(const abstraction_map& sigmaA_,
132 const sort_expression_substitution_map& sigmaS_,
133 const function_symbol_substitution_map& sigmaF_,
134 data::set_identifier_generator& generator_
135 )
136 : sigmaH(sigmaA_),
139 generator(generator_)
140 {}
141
142 template <class T>
143 void apply(T& result, const data::sort_expression& x)
144 {
145 auto i = sigmaS.find(x);
146 if (i == sigmaS.end())
147 {
148 super::apply(result, x);
149 }
150 else
151 {
152 result = i->second;
153 }
154 }
155
156 template <class T>
157 void apply(T& result, const data::function_symbol& x)
158 {
159 auto i = sigmaF.find(x);
160 if (i != sigmaF.end())
161 {
162 result = i->second;
163 return;
164 }
165 throw mcrl2::runtime_error("function symbol " + print_symbol(x) + " not present in the function symbol mapping!");
166 }
167
168 template <class T>
169 void apply(T& result, const data::application& x)
170 {
171 if (data::is_variable(x.head()))
172 {
173 data::variable v = atermpp::down_cast<data::variable>(x.head());
174 data::sort_expression sort;
175 super::apply(sort, v.sort());
177 result = data::detail::create_finite_set(data::application(v, x.begin(), x.end()));
178 return;
179 }
180 else if (data::is_function_symbol(x.head()))
181 {
182 super::apply(result, x);
183 return;
184 }
185 else
186 {
187 throw mcrl2::runtime_error("don't know how to handle arbitrary expression as head: " + data::pp(x));
188 }
189 }
190
191 template <class T>
192 void apply(T& result, const data::lambda& x)
193 {
194 data::data_expression body;
195 super::apply(body, x);
197 generator.add_identifiers(data::find_identifiers(x));
198 data::variable v(generator("v"), s);
200 }
201
202 template <class T>
203 void apply(T& result, const data::data_expression& x)
204 {
206 {
207 super::apply(result, x);
209 }
210 else
211 {
212 // check if it is a "ground term", i.e. it does not contain any variables
213 auto i = sigmaH.find(x.sort());
214 if (i != sigmaH.end() && data::find_all_variables(x).empty())
215 {
216 data::data_expression_list args = { x };
217 result = data::detail::create_finite_set(data::application(i->second, args));
218 }
219 else
220 {
221 // first apply the sort and function symbol transformations
222 super::apply(result, x);
223 }
224 }
225 }
226 };
227
228 // Applies sigmaS to a sort expression
230 {
231 using argument_type = data::sort_expression;
232 using result_type = data::sort_expression;
233
235
236 sort_function(const abstraction_map& sigmaH,
237 const sort_expression_substitution_map& sigmaS,
238 const function_symbol_substitution_map& sigmaF,
240 )
242 {}
243
245 {
246 data::sort_expression sort;
247 f.apply(sort, x);
248 return sort;
249 }
250 };
251
253 {
255 using super::apply;
256 using super::update;
257
258 data::variable_list make_variables(const data::data_expression_list& x, const std::string& hint, sort_function sigma) const
259 {
260 std::vector<data::variable> result;
261 std::size_t i = 0;
262 for (auto j = x.begin(); j != x.end(); ++i, ++j)
263 {
264 result.emplace_back(hint + utilities::number2string(i), sigma(j->sort()));
265 }
266 return data::variable_list(result.begin(), result.end());
267 }
268
274
276 {
277 data::data_expression result;
278 absinthe_sort_expression_builder(sigmaH, sigmaS, sigmaF, generator).apply(result, x);
279 return result;
280 }
281
282 data::data_expression_list lift(const data::data_expression_list& x)
283 {
284 data::data_expression_list result;
285 absinthe_sort_expression_builder(sigmaH, sigmaS, sigmaF, generator).apply(result, x);
286 return result;
287 }
288
289 data::variable_list lift(const data::variable_list& x)
290 {
291 data::variable_list result;
292 absinthe_sort_expression_builder(sigmaH, sigmaS, sigmaF, generator).apply(result, x);
293 return result;
294 }
295
297 {
299 absinthe_sort_expression_builder(sigmaH, sigmaS, sigmaF, generator).apply(result, x);
300 return result;
301 }
302
303 absinthe_data_expression_builder(const abstraction_map& sigmaA_,
304 const sort_expression_substitution_map& sigmaS_,
305 const function_symbol_substitution_map& sigmaF_,
306 data::set_identifier_generator& generator_,
307 bool is_over_approximation)
308 : sigmaH(sigmaA_),
311 generator(generator_),
312 m_is_over_approximation(is_over_approximation)
313 {}
314
315 template <class T>
316 void apply(T& result, const data::data_expression& x)
317 {
320 {
321 result = atermpp::down_cast<T>(data::detail::create_set_in(data::true_(), x1));
322 }
323 else
324 {
325 result = atermpp::down_cast<T>(data::not_(data::detail::create_set_in(data::false_(), x1)));
326 }
327 }
328
329 template <class T>
331 {
332 data::data_expression_list e = lift(x.parameters());
333 data::variable_list variables = make_variables(x.parameters(), "x", sort_function(sigmaH, sigmaS, sigmaF, generator));
334 data::data_expression_list::iterator i = e.begin();
335 data::variable_list::iterator j = variables.begin();
336 data::data_expression_vector z;
337 for (; i != e.end(); ++i, ++j)
338 {
339 z.push_back(data::detail::create_set_in(*j, *i));
340 }
341 data::data_expression q = data::lazy::join_and(z.begin(), z.end());
343 {
344 result = make_exists_(variables, and_(atermpp::down_cast<pbes_expression>(q),
345 propositional_variable_instantiation(x.name(), data::data_expression_list(variables))));
346 }
347 else
348 {
349 result = make_forall_(variables, imp(atermpp::down_cast<pbes_expression>(q), propositional_variable_instantiation(x.name(), data::data_expression_list(variables))));
350 }
351 }
352
353 template <class T>
354 void apply(T& result, const pbes_system::forall& x)
355 {
357 super::apply(body, x.body());
358 result = make_forall_(lift(x.variables()), body);
359 }
360
361 template <class T>
362 void apply(T& result, const pbes_system::exists& x)
363 {
365 super::apply(body, x.body());
366 result = make_exists_(lift(x.variables()), body);
367 }
368
370 {
373 super::apply(result, x.formula());
374 x.formula() = result;
375 }
376
378 {
379 super::update(x.equations());
380 pbes_expression kappa;
381 apply(kappa, x.initial_state());
382 core::identifier_string name("GeneratedZ");
383 propositional_variable Z(name, data::variable_list());
384 x.equations().emplace_back(fixpoint_symbol::mu(), Z, kappa);
385 x.initial_state() = propositional_variable_instantiation(name, data::data_expression_list());
386 }
387 };
388
390 {
391 sort_expression_substitution_map result;
392
393 for (const std::string& line: utilities::regex_split(text, "\\n"))
394 {
395 std::vector<std::string> words = utilities::regex_split(line, ":=");
396 if (words.size() == 2)
397 {
398 data::sort_expression lhs = data::parse_sort_expression(words[0], dataspec);
399 data::sort_expression rhs = data::parse_sort_expression(words[1], dataspec);
400 result[lhs] = rhs;
401 }
402 }
403 return result;
404 }
405
406 // Parse the right hand sides of the function symbol mapping in text, and add them to dataspec if needed
407 void parse_right_hand_sides(const std::string& text, data::data_specification& dataspec)
408 {
409 std::string dataspec_text = data::pp(dataspec);
410 for (const std::string& line: utilities::regex_split(text, "\\n"))
411 {
412 std::vector<std::string> words = utilities::regex_split(line, ":=");
413 if (words.size() == 2)
414 {
415 data::function_symbol f = data::parse_function_symbol(words[1], dataspec_text);
416 if (!pbes_system::detail::is_structured_sort_constructor(dataspec, f))
417 {
418 dataspec.add_mapping(f);
419 }
420 }
421 }
422 }
423
425 {
426 function_symbol_substitution_map result;
427 std::string dataspec_text = data::pp(dataspec);
428
429 for (const std::string& line: utilities::regex_split(text, "\\n"))
430 {
431 std::vector<std::string> words = utilities::regex_split(line, ":=");
432 if (words.size() == 2)
433 {
434 data::function_symbol lhs = data::parse_function_symbol(words[0], dataspec_text);
435 std::string s = words[1];
436 s = utilities::regex_replace(";\\s*$", "", s);
437 data::function_symbol rhs = data::parse_function_symbol(s, dataspec_text);
438 result[lhs] = rhs;
439 }
440 }
441 return result;
442 }
443
444 // text is a data_specification; extract the user defined mappings
446 {
447 abstraction_map result;
448 data::data_specification dataspec = data::parse_data_specification(text);
449 for (const data::function_symbol& i: dataspec.user_defined_mappings())
450 {
451 const auto& f = atermpp::down_cast<data::function_sort>(i.sort());
452 if (f.domain().size() != 1)
453 {
454 throw mcrl2::runtime_error("cannot abstract the function " + data::pp(i) + " since the arity of the domain is not equal to one!");
455 }
456 result[f.domain().front()] = i;
457 }
458 return result;
459 }
460
461 // creates a finite set containing one data expression
463 {
465 {
468 result = data::sort_fset::cons_(s, x, result);
469 return result;
470 }
471 };
472
473 // transforms the sort expression s to Set(s)
474 struct make_set
475 {
477 {
479 }
480 };
481
482 // function that transforms a function symbol
484 {
487
489 {
490 unprintable["&&"] = "and";
491 unprintable["||"] = "or";
492 unprintable["!"] = "not";
493 unprintable["#"] = "len";
494 unprintable["."] = "element_at";
495 unprintable["+"] = "plus";
496 unprintable["-"] = "minus";
497 unprintable[">"] = "greater";
498 unprintable["<"] = "less";
499 unprintable[">="] = "ge";
500 unprintable["<="] = "le";
501 unprintable["=="] = "eq";
502 unprintable["!="] = "neq";
503 unprintable["[]"] = "emptylist";
504 unprintable["++"] = "concat";
505 unprintable["<|"] = "snoc";
506 unprintable["|>"] = "cons";
507 unprintable["@cNat"] = "cNat";
508 unprintable["@cDub"] = "cDub";
509 unprintable["@c0"] = "c0";
510 unprintable["@c1"] = "c1";
511 unprintable["@func_update"] = "func_update";
512 unprintable["@cInt"] = "cInt";
513 unprintable["@cNeg"] = "cNeg";
514 unprintable["@most_significant_digit"] = "most_significant_digit";
515 unprintable["@succ_pos"] = "succpos";
516 unprintable["@most_significant_digitNat"] = "most_significant_digitNat";
517 unprintable["@concat_digit"] = "concat_digit";
518 unprintable["@succ_nat"] = "succ_nat";
519
520
521 suffix_with_sort.insert("[]");
522 suffix_with_sort.insert("|>");
523 }
524
526 {
527 std::string result = data::pp(s);
528 result = utilities::regex_replace("\\‍(", "_", result);
529 result = utilities::regex_replace("\\‍)", "_", result);
530 result = utilities::regex_replace("#", "_", result);
531 result = utilities::regex_replace("->", "_", result);
532 result = utilities::remove_whitespace(result);
533 return result;
534 }
535
536
538 {
539 using utilities::detail::contains;
540
541 std::string name = std::string(f.name());
542
543 bool print_sort = contains(suffix_with_sort, std::string(f.name()));
544 auto i = unprintable.find(name);
545 if (i != unprintable.end())
546 {
547 name = i->second;
548 }
549 name = "Generated_" + name;
550 if (print_sort)
551 {
552 name = name + print_cleaned(f.sort());
553 }
554
555 const data::sort_expression& s = f.sort();
557 {
558 return data::function_symbol(name, sigma(s));
559 }
560 else if (data::is_function_sort(s))
561 {
562 // Apply sigmaS recursively to s
563 // f: tail: List(Nat) -> List(Nat)
564 // result: generated_tail: List(AbsNat) -> Set(List(AbsNat))
565 data::function_sort fs = atermpp::down_cast<data::function_sort>(sigma(s));
566 return data::function_symbol(name, data::function_sort(fs.domain(), make_set()(fs.codomain())));
567 }
569 {
570 // Apply sigmaS recursively to s
571 // Example: List(Nat) -> List(AbsNat)
572 return data::function_symbol(name, sigma(s));
573 }
574 throw mcrl2::runtime_error("absinthe algorithm: unsupported sort " + print_term(s) + " detected!");
576 }
577 };
578
579 // function that lifts a function symbol
581 {
583 {
584 using namespace data;
585 std::string name = "Lift" + utilities::trim_copy(std::string(f.name()));
586 const sort_expression &s = f.sort();
587 if (is_basic_sort(s))
588 {
589 return function_symbol(name, make_set()(s));
590 }
591 else if (is_function_sort(s))
592 {
593 const auto& fs = atermpp::down_cast<data::function_sort>(s);
594 const sort_expression_list& sl = fs.domain();
595 return function_symbol(name, function_sort(sort_expression_list(sl.begin(),sl.end(), make_set()), fs.codomain()));
596 }
597 else if (is_container_sort(s))
598 {
599 return data::function_symbol(name, make_set()(s));
600 }
601 throw mcrl2::runtime_error("absinthe algorithm (lift): unsupported sort " + print_term(s) + " detected!");
602 }
603 };
604
605 // function that generates an equation from a function symbol and it's corresponding 'generated' version
607 {
608 lift_equation_1_2() = default;
609
611 {
612 std::vector<data::variable> result;
613 std::size_t i = 0;
614 for (auto j = sorts.begin(); j != sorts.end(); ++i, ++j)
615 {
616 result.emplace_back(hint + utilities::number2string(i), sigma(*j));
617 }
618 return result;
619 }
620
621 // sigmaH is used for checking consistency of the user input
622 data::data_equation operator()(const data::function_symbol& f1, const data::function_symbol& f2, sort_function sigma, const abstraction_map& sigmaH) const
623 {
624 mCRL2log(log::debug) << "lift_equation_1_2 f1 = " << print_symbol(f1) << " f2 = " << print_symbol(f2) << std::endl;
625 data::variable_list variables;
626 const data::data_expression& condition = data::true_();
629
631
633 {
634 lhs = f2;
635 data::function_symbol f1_sigma(f1.name(), sigma(f1.sort()));
636
637 auto i = sigmaH.find(f1.sort());
638 if (i == sigmaH.end())
639 {
640 rhs = f1_sigma;
641 }
642 else
643 {
644 data::function_symbol h = i->second;
645 rhs = data::application(h, f1);
646 }
647 }
648 else if (data::is_function_sort(s1))
649 {
652
653 // check validity
655 {
656 // TODO: add check that the domain of the updated function does not contain abstraction sorts
657 }
658 else if (fs1.domain() != fs2.domain())
659 {
660 throw std::runtime_error("can not generalize functions with abstraction sorts in the domain: " + data::pp(f1) + ": " + data::pp(s1));
661 }
662
663 data::variable_vector x = make_variables(fs2.domain(), "x", sigma);
664 variables = data::variable_list(x.begin(),x.end());
665 lhs = data::application(f2, x.begin(), x.end());
666 data::application f_x(f1, x.begin(), x.end());
667
668 data::function_symbol f1_sigma(f1.name(), sigma(f1.sort()));
669
670 auto i = sigmaH.find(detail::target_sort(f1.sort()));
671 if (i == sigmaH.end())
672 {
673 data::application f1_sigma_x(f1_sigma, x.begin(), x.end());
675 }
676 else
677 {
678 data::function_symbol h = i->second;
679 rhs = data::detail::create_finite_set(data::application(h, f_x));
680 }
681 }
682 else if (data::is_container_sort(s1))
683 {
684 // Example:
685 // f1: [] : List(Nat)
686 // f2: generated_emptylist : List(AbsNat)
687 // eqn: generated_emptylist = [] met [] : List(AbsNat)
688 // tail: List(AbsNat) -> List(Nat)
689 lhs = f2;
690 data::function_symbol f1_sigma(f1.name(), sigma(f1.sort()));
691 rhs = f1_sigma;
692 }
693 else
694 {
695 throw mcrl2::runtime_error("absinthe algorithm (lift_equation_1_2): unsupported sort " + print_term(s1) + " detected!");
696 }
697
698 if (lhs.sort() != rhs.sort())
699 {
700 throw mcrl2::runtime_error("absinthe algorithm (lift_equation_1_2): lhs.sort() and rhs.sort are not equal: " + data::pp(lhs.sort()) + " <-> " + data::pp(rhs.sort()));
701 }
702
703 return data::data_equation(variables, condition, lhs, rhs);
704 }
705 };
706
707 // function that generates an equation from a function symbol and it's corresponding lifted version
709 {
710 lift_equation_2_3() = default;
711
713 {
714 std::vector<data::variable> result;
715 std::size_t i = 0;
716 for (auto j = sorts.begin(); j != sorts.end(); ++i, ++j)
717 {
718 result.emplace_back(hint + utilities::number2string(i), sigma(*j));
719 }
720 return result;
721 }
722
723 // Let x = [x1:D1, ..., xn:Dn] and X = [X1:Set(D1), ..., Xn:Set(Dn)]. Returns the expression
724 //
725 // (x1 in X1 /\ ... /\ xn in Xn)
726 data::data_expression enumerate_domain(const std::vector<data::variable>& x, const std::vector<data::variable>& X) const
727 {
728 std::vector<data::data_expression> a;
729 auto i = x.begin();
730 auto j = X.begin();
731 for (; i != x.end(); ++i, ++j)
732 {
733 a.push_back(data::detail::create_set_in(*i, *j));
734 }
735 data::data_expression body = data::lazy::join_and(a.begin(), a.end());
736 return body;
737 }
738
740 {
741 data::variable_list variables;
742 const data::data_expression& condition = data::true_();
745
746 const data::sort_expression& s2 = f2.sort();
747
749 {
750 lhs = f3;
752 }
753 else if (data::is_function_sort(s2))
754 {
757
759 {
760 throw mcrl2::runtime_error("The codomain " + data::pp(fs2.codomain()) + " of function " + data::pp(f2.name()) + " should be a container sort!");
761 }
762
763 // TODO: generate these variables in a proper way
764 std::vector<data::variable> x = make_variables(fs2.domain(), "x", sigma);
765 std::vector<data::variable> X = make_variables(fs3.domain(), "X", sigma);
766
767 variables = data::variable_list(X.begin(), X.end());
768 lhs = data::application(f3, X.begin(), X.end());
769 data::variable y("y", data::detail::get_set_sort(atermpp::down_cast<data::container_sort>(fs2.codomain())));
770 data::data_expression Y = data::application(f2, x.begin(), x.end());
771 data::data_expression body = data::and_(enumerate_domain(x, X), data::detail::create_set_in(y, Y));
772 rhs = data::detail::create_set_comprehension(y, data::exists(x, body));
773 }
774 else if (data::is_container_sort(s2))
775 {
776 lhs = f3;
778 }
779 else
780 {
781 throw mcrl2::runtime_error("absinthe algorithm (lift_equation_2_3): unsupported sort " + print_term(s2) + " detected!");
782 }
783 return data::data_equation(variables, condition, lhs, rhs);
784 }
785 };
786
787 template <typename Map>
789 {
790 std::ostringstream out;
791 for (auto i = m.begin(); i != m.end(); ++i)
792 {
793 out << i->first << " -> " << i->second << std::endl;
794 }
795 return out.str();
796 }
797
798 void check_consistency(const data::sort_expression& s, const data::sort_expression& t, const data::function_symbol& f, sort_expression_substitution_map& sigmaS) const
799 {
800 sort_expression_substitution_map::const_iterator i = sigmaS.find(s);
801 if (i != sigmaS.end() && i->second != t)
802 {
803 throw mcrl2::runtime_error("inconsistent abstraction " + data::pp(s) + " := " + data::pp(t) + " detected in the abstraction of " + print_symbol(f) + " (elsewhere it is abstracted as " + data::pp(s) + " := " + data::pp(i->second) + ").");
804 }
805 else
806 {
807 sigmaS[s] = t;
808 }
809 }
810
811 // Let f1: s1 x ... sn -> s and f2: t1 x ... tn -> t
812 // This function checks if the correspondence si -> ti conflicts with sigmaS.
813 void check_consistency(const data::function_symbol& f1, const data::function_symbol& f2, sort_expression_substitution_map& sigmaS) const
814 {
815 const data::sort_expression& s1 = f1.sort();
816 const data::sort_expression& s2 = f2.sort();
817
819 {
820 check_consistency(s1, s2, f1, sigmaS);
821 }
822 else if (data::is_function_sort(s1))
823 {
824 data::function_sort fs1(s1);
825 data::function_sort fs2(s2);
826
827 const data::sort_expression_list& domain1 = fs1.domain();
828 const data::sort_expression_list& domain2 = fs2.domain();
829
830 data::sort_expression_list::iterator i1 = domain1.begin();
831 data::sort_expression_list::iterator i2 = domain2.begin();
832
833 for (; i1 != domain1.end(); ++i1, ++i2)
834 {
835 check_consistency(*i1, *i2, f1, sigmaS);
836 }
837 }
838// else if (data::is_container_sort(s1))
839// {
840// }
841 }
842
843 // add lifted mappings and equations to the data specification
844 void lift_data_specification(const pbes& p, const abstraction_map& sigmaH, const sort_expression_substitution_map& sigmaS, function_symbol_substitution_map& sigmaF, data::data_specification& dataspec)
845 {
846 using utilities::detail::has_key;
847
848 sort_expression_substitution_map sigmaS_consistency = sigmaS; // is only used for consistency checking
849 sort_function sigma(sigmaH, sigmaS, sigmaF, m_generator);
850
851 // add lifted versions of used function symbols that are not specified by the user to sigmaF, and adds them to the data specification as well
852 std::set<data::function_symbol> used_function_symbols = pbes_system::find_function_symbols(p);
853
854 // add List containers for user defined sorts, since they are used in the translation
855 const data::basic_sort_vector& sorts = dataspec.user_defined_sorts();
856 for (const data::basic_sort& sort: sorts)
857 {
858 data::sort_expression s = data::container_sort(data::list_container(), sort);
859 dataspec.add_context_sort(s);
860 }
861
862 // add constructor functions of List containers of abstracted sorts to sigmaF
863 for (const auto& i: sigmaH)
864 {
865 data::sort_expression s = data::container_sort(data::list_container(), i.first);
866 dataspec.add_context_sort(s);
867 data::function_symbol_vector list_constructors = dataspec.constructors(s);
868 for (const data::function_symbol& f1: list_constructors)
869 {
870 data::function_symbol f2 = lift_function_symbol_1_2()(f1, sigma);
871 sigmaF[f1] = f2;
872 dataspec.add_mapping(f2);
873 mCRL2log(log::debug) << "adding list constructor " << f1 << " to sigmaF" << std::endl;
874 }
875 }
876
877 for (const data::function_symbol& f1: used_function_symbols)
878 {
879 mCRL2log(log::debug) << "lifting function symbol: " << f1 << std::endl;
880 if (!has_key(sigmaF, f1))
881 {
882 data::function_symbol f2 = lift_function_symbol_1_2()(f1, sigma);
883 mCRL2log(log::debug) << "lifted function symbol: " << f1 << " to " << f2 << std::endl;
884 check_consistency(f1, f2, sigmaS_consistency);
885 sigmaF[f1] = f2;
886 dataspec.add_mapping(f2);
887
888 data::data_equation eq = lift_equation_1_2()(f1, f2, sigma, sigmaH);
889 mCRL2log(log::debug) << "adding equation: " << eq << std::endl;
890 dataspec.add_equation(eq);
891 }
892 }
893
894 for (auto& i : sigmaF)
895 {
896 data::function_symbol f2 = i.second;
897 data::function_symbol f3 = lift_function_symbol_2_3()(f2);
898
899 mCRL2log(log::debug) << "adding mapping: " << f3 << " " << f3.sort() << std::endl;
900 dataspec.add_mapping(f3);
901
902 // update sigmaF
903 i.second = f3;
904
905 // make an equation for the lifted function symbol f
906 data::data_equation eq = lift_equation_2_3()(f2, f3, sigma);
907 mCRL2log(log::debug) << "adding equation: " << eq << std::endl;
908 dataspec.add_equation(eq);
909 }
910 }
911
912 void print_fsvec(const data::function_symbol_vector& v, const std::string& msg) const
913 {
914 mCRL2log(log::debug) << "--- " << msg << std::endl;
915 for (const data::function_symbol& f: v)
916 {
917 mCRL2log(log::debug) << print_symbol(f) << std::endl;
918 }
919 }
920
921 void print_fsmap(const function_symbol_substitution_map& v, const std::string& msg) const
922 {
923 mCRL2log(log::debug) << "--- " << msg << std::endl;
924 for (const auto& i: v)
925 {
926 mCRL2log(log::debug) << print_symbol(i.first) << " --> " << print_symbol(i.second) << std::endl;
927 }
928 }
929
931 {
932 log::logger::set_reporting_level(log::debug);
933 }
934
935 void run(pbes& p, const std::string& abstraction_text, bool is_over_approximation)
936 {
937 // split the string abstraction_text into four different parts
938 std::string function_symbol_mapping_text;
939 std::string user_sorts_text;
940 std::string user_equations_text;
941 std::string abstraction_mapping_text;
942 std::string pbes_sorts_text;
943
944 std::string text = abstraction_text;
945 std::vector<std::string> all_keywords = { "sort", "var", "eqn", "map", "cons", "absfunc", "absmap" };
946 std::pair<std::string, std::string> q;
947
948 q = utilities::detail::separate_keyword_section(text, "sort", all_keywords);
949 user_sorts_text = q.first;
950 text = q.second;
951
952 q = utilities::detail::separate_keyword_section(text, "absmap", all_keywords);
953
954 abstraction_mapping_text = q.first;
955 text = q.second;
956
957 // must be the last one!
958 q = utilities::detail::separate_keyword_section(text, "absfunc", all_keywords);
959 function_symbol_mapping_text = q.first;
960 user_equations_text = q.second;
961
962 // extract pbes sorts
963 std::string ptext = data::pp(p.data());
964 q = utilities::detail::separate_keyword_section(ptext, "sort", all_keywords);
965 pbes_sorts_text = q.first;
966
967 // 0) split user_dataspec_text into user_sorts_text and user_equations_text
968 mCRL2log(log::debug) << "--- user sorts ---\n" << user_sorts_text << std::endl;
969 mCRL2log(log::debug) << "--- user equations ---\n" << user_equations_text << std::endl;
970 mCRL2log(log::debug) << "--- function mapping ---\n" << function_symbol_mapping_text << std::endl;
971 mCRL2log(log::debug) << "--- abstraction mapping ---\n" << abstraction_mapping_text << std::endl;
972 mCRL2log(log::debug) << "--- pbes sorts ---\n" << pbes_sorts_text << std::endl;
973
974 if (!abstraction_mapping_text.starts_with("absmap"))
975 {
976 throw mcrl2::runtime_error("the abstraction mapping may not be empty!");
977 }
978
979 // 1) create the data specification dataspec, which consists of user_sorts_text, abstract_mapping_text and p.data()
980 data::data_specification dataspec = data::parse_data_specification(data::pp(p.data()) + "\n" + user_sorts_text + "\n" + abstraction_mapping_text.substr(3));
981 mCRL2log(log::debug) << "--- data specification 1) ---\n" << dataspec << std::endl;
982
983 // 2) parse the right hand sides of the function symbol mapping, and add them to dataspec
984 parse_right_hand_sides(function_symbol_mapping_text, dataspec);
985 mCRL2log(log::debug) << "--- data specification 2) ---\n" << dataspec << std::endl;
986
987 // 3) add user_equations_text to dataspec
988 dataspec = data::parse_data_specification(data::pp(dataspec) + "\n" + user_equations_text);
989 mCRL2log(log::debug) << "--- data specification 3) ---\n" << dataspec << std::endl;
990
991 // abstraction functions (specified by the user)
992 abstraction_map sigmaH = parse_abstraction_map(pbes_sorts_text + "\n" + user_sorts_text + "\n" + abstraction_mapping_text.substr(3));
993
994 // sort expressions replacements (extracted from sigmaH)
995 sort_expression_substitution_map sigmaS;
996 for (auto& i: sigmaH)
997 {
998 data::function_symbol f = i.second;
999 const data::function_sort& fs = atermpp::down_cast<data::function_sort>(f.sort());
1000 sigmaS[i.first] = fs.codomain();
1001 }
1002 mCRL2log(log::debug) << "\n--- sort expression mapping ---\n" << print_mapping(sigmaS) << std::endl;
1003
1004 // function symbol replacements (specified by the user)
1005 function_symbol_substitution_map sigmaF = parse_function_symbol_mapping(function_symbol_mapping_text, dataspec);
1006 mCRL2log(log::debug) << "\n--- function symbol mapping ---\n" << print_mapping(sigmaF) << std::endl;
1007
1008 m_generator.add_identifiers(data::function_and_mapping_identifiers(p.data()));
1009 m_generator.add_identifiers(data::function_and_mapping_identifiers(dataspec));
1010
1011 // 4) add lifted sorts, mappings and equations to dataspec
1012 // before: the mapping sigmaF is f1 -> f2
1013 // after: the mapping sigmaF is f1 -> f3
1014 // after: f2 and f3 have been added to dataspec
1015 // after: equations for f3 have been added to dataspec
1016 // generate mapping f1 -> f2 for missing function symbols
1017 lift_data_specification(p, sigmaH, sigmaS, sigmaF, dataspec);
1018 mCRL2log(log::debug) << "--- data specification 4) ---\n" << dataspec << std::endl;
1019
1020 mCRL2log(log::debug) << "\n--- function symbol mapping after lifting ---\n" << print_mapping(sigmaF) << std::endl;
1021
1022 mCRL2log(log::debug) << "--- pbes before ---\n" << p << std::endl;
1023
1024 p.data() = dataspec;
1025
1026 // then transform the data expressions and the propositional variable instantiations
1027 absinthe_data_expression_builder(sigmaH, sigmaS, sigmaF, m_generator, is_over_approximation).update(p);
1028
1029 mCRL2log(log::debug) << "--- pbes after ---\n" << p << std::endl;
1030 }
1031};
1032
1033} // namespace mcrl2::pbes_system
1034
1035#endif // MCRL2_PBES_ABSINTHE_H
\brief A data equation
data_expression & operator=(const data_expression &) noexcept=default
data_expression & operator=(data_expression &&) noexcept=default
sort_expression sort() const
Returns the sort of the data expression.
Definition data.cpp:107
\brief A function sort
const sort_expression & codomain() const
function_sort(const atermpp::aterm &term)
const sort_expression_list & domain() const
\brief A function symbol
function_symbol(const core::identifier_string &name, const sort_expression &sort)
Constructor.
function_symbol()
Default constructor.
const core::identifier_string & name() const
const sort_expression & sort() const
function symbol.
Definition lambda.h:24
Identifier generator that stores the identifiers of the context in a set. Using the operator()() and ...
\brief A sort expression
sort_expression()
\brief Default constructor X3.
\brief A data variable
Definition variable.h:25
const core::identifier_string & name() const
Definition variable.h:35
variable & operator=(variable &&) noexcept=default
variable(const core::identifier_string &name, const sort_expression &sort)
Constructor.
Definition variable.h:59
\brief The existential quantification operator for pbes expressions
const data::variable_list & variables() const
static fixpoint_symbol mu()
Returns the mu symbol.
\brief The universal quantification operator for pbes expressions
const data::variable_list & variables() const
propositional_variable & variable()
Returns the pbes variable of the equation.
pbes_expression & formula()
Returns the predicate formula on the right hand side of the equation.
pbes_expression & operator=(const pbes_expression &) noexcept=default
parameterized boolean equation system
Definition pbes.h:54
propositional_variable_instantiation & initial_state()
Returns the initial state.
Definition pbes.h:195
\brief A propositional variable instantiation
propositional_variable_instantiation(const core::identifier_string &name, const data::data_expression_list &parameters)
Constructor.
propositional_variable_instantiation & operator=(propositional_variable_instantiation &&) noexcept=default
\brief A propositional variable declaration
propositional_variable & operator=(propositional_variable &&) noexcept=default
propositional_variable(const core::identifier_string &name, const data::variable_list &parameters)
\brief Constructor Z12.
#define mCRL2log(LEVEL)
mCRL2log(LEVEL) provides the stream used to log.
Definition logger.h:393
data_expression create_finite_set(const data_expression &x)
Create the finite set { x }, with x a data expression.
data_expression create_set_comprehension(const variable &x, const data_expression &phi)
Create the set { x | phi }, with phi a predicate that may depend on the variable x.
Namespace for system defined sort fset.
Definition fset1.h:32
application cons_(const sort_expression &s, const data_expression &arg0, const data_expression &arg1)
Application of function symbol @fset_cons.
Definition fset1.h:228
function_symbol empty(const sort_expression &s)
Constructor for function symbol {}.
Definition fset1.h:72
Namespace for system defined sort set_.
Definition set1.h:33
container_sort set_(const sort_expression &s)
Constructor for sort expression Set(S)
Definition set1.h:39
const data_expression & true_()
Definition consistency.h:91
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_basic_sort(const atermpp::aterm &x)
Returns true if the term t is a basic sort.
bool is_function_sort(const atermpp::aterm &x)
Returns true if the term t is a function sort.
bool is_function_update_application(const atermpp::aterm &e)
Recogniser for application of @func_update.
application equal_to(const data_expression &arg0, const data_expression &arg1)
Application of function symbol ==.
Definition standard.h:140
bool is_variable(const atermpp::aterm &x)
Returns true if the term t is a variable.
void absinthe_check_expression(const T &x)
Definition absinthe.h:48
data::data_specification & absinthe_data_specification()
Definition absinthe.h:41
void print_used_function_symbols(const pbes &p)
Definition absinthe.h:80
bool is_structured_sort_constructor(const data::data_specification &dataspec, const data::function_symbol &f)
Definition absinthe.h:55
data::sort_expression target_sort(const data::sort_expression &s)
Definition absinthe.h:91
std::string print_term(const Term &x)
Definition absinthe.h:27
std::string print_symbol(const Term &x)
Definition absinthe.h:33
void apply(T &result, const data::data_expression &x)
Definition absinthe.h:316
pbes_system::propositional_variable lift(const pbes_system::propositional_variable &x)
Definition absinthe.h:296
data::variable_list lift(const data::variable_list &x)
Definition absinthe.h:289
data::data_expression lift(const data::data_expression &x)
Definition absinthe.h:275
void apply(T &result, const pbes_system::exists &x)
Definition absinthe.h:362
void apply(T &result, const propositional_variable_instantiation &x)
Definition absinthe.h:330
void apply(T &result, const pbes_system::forall &x)
Definition absinthe.h:354
data::data_expression_list lift(const data::data_expression_list &x)
Definition absinthe.h:282
absinthe_data_expression_builder(const abstraction_map &sigmaA_, const sort_expression_substitution_map &sigmaS_, const function_symbol_substitution_map &sigmaF_, data::set_identifier_generator &generator_, bool is_over_approximation)
Definition absinthe.h:303
data::variable_list make_variables(const data::data_expression_list &x, const std::string &hint, sort_function sigma) const
Definition absinthe.h:258
void apply(T &result, const data::data_expression &x)
Definition absinthe.h:203
void apply(T &result, const data::function_symbol &x)
Definition absinthe.h:157
void apply(T &result, const data::sort_expression &x)
Definition absinthe.h:143
absinthe_sort_expression_builder(const abstraction_map &sigmaA_, const sort_expression_substitution_map &sigmaS_, const function_symbol_substitution_map &sigmaF_, data::set_identifier_generator &generator_)
Definition absinthe.h:131
data::data_equation operator()(const data::function_symbol &f1, const data::function_symbol &f2, sort_function sigma, const abstraction_map &sigmaH) const
Definition absinthe.h:622
std::vector< data::variable > make_variables(const data::sort_expression_list &sorts, const std::string &hint, sort_function sigma) const
Definition absinthe.h:610
std::vector< data::variable > make_variables(const data::sort_expression_list &sorts, const std::string &hint, sort_function sigma) const
Definition absinthe.h:712
data::data_expression enumerate_domain(const std::vector< data::variable > &x, const std::vector< data::variable > &X) const
Definition absinthe.h:726
data::data_equation operator()(const data::function_symbol &f2, const data::function_symbol &f3, sort_function sigma) const
Definition absinthe.h:739
std::string print_cleaned(const data::sort_expression &s) const
Definition absinthe.h:525
data::function_symbol operator()(const data::function_symbol &f, sort_function sigma) const
Definition absinthe.h:537
data::function_symbol operator()(const data::function_symbol &f) const
Definition absinthe.h:582
data::data_expression operator()(const data::data_expression &x) const
Definition absinthe.h:464
data::sort_expression operator()(const data::sort_expression &s) const
Definition absinthe.h:476
data::sort_expression operator()(const data::sort_expression &x)
Definition absinthe.h:244
sort_function(const abstraction_map &sigmaH, const sort_expression_substitution_map &sigmaS, const function_symbol_substitution_map &sigmaF, data::set_identifier_generator &generator)
Definition absinthe.h:236
sort_expression_substitution_map parse_sort_expression_mapping(const std::string &text, const data::data_specification &dataspec)
Definition absinthe.h:389
void print_fsvec(const data::function_symbol_vector &v, const std::string &msg) const
Definition absinthe.h:912
void run(pbes &p, const std::string &abstraction_text, bool is_over_approximation)
Definition absinthe.h:935
void parse_right_hand_sides(const std::string &text, data::data_specification &dataspec)
Definition absinthe.h:407
void check_consistency(const data::sort_expression &s, const data::sort_expression &t, const data::function_symbol &f, sort_expression_substitution_map &sigmaS) const
Definition absinthe.h:798
void lift_data_specification(const pbes &p, const abstraction_map &sigmaH, const sort_expression_substitution_map &sigmaS, function_symbol_substitution_map &sigmaF, data::data_specification &dataspec)
Definition absinthe.h:844
function_symbol_substitution_map parse_function_symbol_mapping(const std::string &text, const data::data_specification &dataspec)
Definition absinthe.h:424
data::set_identifier_generator m_generator
Definition absinthe.h:119
void print_fsmap(const function_symbol_substitution_map &v, const std::string &msg) const
Definition absinthe.h:921
void check_consistency(const data::function_symbol &f1, const data::function_symbol &f2, sort_expression_substitution_map &sigmaS) const
Definition absinthe.h:813
abstraction_map parse_abstraction_map(const std::string &text)
Definition absinthe.h:445
std::string print_mapping(const Map &m)
Definition absinthe.h:788