mCRL2
Loading...
Searching...
No Matches
bisimulation.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/bisimulation.h
10/// \brief Bisimulation algorithms.
11
12#ifndef MCRL2_PBES_BISIMULATION_H
13#define MCRL2_PBES_BISIMULATION_H
14
15#include "mcrl2/atermpp/aterm.h"
16#include "mcrl2/data/data_expression.h"
17#include "mcrl2/data/merge_data_specifications.h"
18#include "mcrl2/lps/replace.h"
19#include "mcrl2/pbes/detail/lps2pbes_utility.h"
20#include "mcrl2/pbes/join.h"
21#include <ranges>
22#include <type_traits>
23
24
25
26namespace mcrl2::pbes_system
27{
28
29/// \brief Base class for bisimulation algorithms.
31{
32 public:
33 /// \brief The iterator type for non-delta summands
35
36 protected:
37 /// \brief A map type for mapping summands to strings.
39
40 /// \brief Maps summands to strings.
42
43 /// \brief Store the address of the model.
44 const lps::linear_process* model_ptr = nullptr;
45
46 /// \brief Generates a name for an action_list.
47 /// \param l A sequence of actions
48 /// \return A string representation of the list \p l
50 {
51 std::ostringstream out;
52 for (auto i = l.begin(); i != l.end(); ++i)
53 {
54 out << (i != l.begin() ? "-" : "") << std::string(i->label().name());
55 }
56 std::string result = out.str();
57 if (result.empty())
58 {
59 result = "tau";
60 }
61 return result;
62 }
63
64 /// \brief Returns the name of a summand
65 /// \param i A summand iterator
66 /// \return The name of the summand referred to by \p i
68 {
69 const lps::action_summand* t = &(*i);
70 auto j = summand_names.find(t);
71 assert(j != summand_names.end());
72 return j->second;
73 }
74
75 /// \brief Returns true if p is the linear process of the model.
76 /// \param p A linear process
77 /// \return True if p is the linear process of the model.
78 bool is_from_model(const lps::linear_process& p) const
79 {
80 return &p == model_ptr;
81 }
82
83 /// \brief Returns a name of a linear process.
84 /// \param p A linear process
85 /// \return The name of the linear process.
87 {
88 if (is_from_model(p))
89 {
90 return "m";
91 }
92 else
93 {
94 return "s";
95 }
96 }
97
98 /// \brief Used for initializing summand names.
99 /// \param p A linear process
101 {
103 for (const lps::action_summand& s: p.action_summands())
104 {
105 std::string name = generator(action_list_name(s.multi_action().actions()));
106 summand_names[&s] = name;
107 }
108 }
109
110 // creates the substitution v[i] := e[i]
111 // pre: v.size() == e.size()
112 template<std::ranges::range R>
115 {
116 assert(v.size() == e.size());
117 auto vi = v.begin();
118 auto ei = e.begin();
119 for (; vi != v.end(); ++vi, ++ei)
120 {
121 result[*vi] = *ei;
122 }
123 }
124
125 public:
126 /// \brief Creates a name for the propositional variable Xpq
127 /// \param p A linear process
128 /// \param q A linear process
129 /// \return The name for the propositional variable Xpq
131 {
132 std::string s = "X" + process_name(p) + process_name(q);
133 return core::identifier_string(s);
134 }
135
136 /// \brief Creates a name for the propositional variable Ypq
137 /// \param p A linear process
138 /// \param q A linear process
139 /// \return The name for the propositional variable Ypq
141 {
142 std::string s = "Y" + process_name(p) + process_name(q);
143 return core::identifier_string(s);
144 }
145
146 /// \brief Creates a name for the propositional variable Ypqi
147 /// \pre The iterator i must be in p.action_summands().
148 /// \param p A linear process
149 /// \param q A linear process
150 /// \param i A summand iterator
151 /// \return The name for the propositional variable Ypqi
153 {
154 std::string s = "Y" + process_name(p) + process_name(q) + "_" + summand_name(i);
155 return core::identifier_string(s);
156 }
157
158 /// \brief Creates a name for the propositional variable Y1pqi
159 /// \pre The iterator i must be in p.action_summands().
160 /// \param p A linear process
161 /// \param q A linear process
162 /// \param i A summand iterator
163 /// \return The name for the propositional variable Y1pqi
165 {
166 std::string s = "Y1" + process_name(p) + process_name(q) + "_" + summand_name(i);
167 return core::identifier_string(s);
168 }
169
170 /// \brief Creates a name for the propositional variable Y2pqi
171 /// \pre The iterator i must be in p.action_summands().
172 /// \param p A linear process
173 /// \param q A linear process
174 /// \param i A summand iterator
175 /// \return The name for the propositional variable Y2pqi
177 {
178 std::string s = "Y2" + process_name(p) + process_name(q) + "_" + summand_name(i);
179 return core::identifier_string(s);
180 }
181
182 /// \brief Creates a propositional variable.
183 /// \param name A
184 /// \param parameters A sequence of data variables
185 /// \return The created propositional variable
187 {
189 }
190
191 /// \brief Creates a propositional variable.
192 /// \param name A
193 /// \param parameters A sequence of data expressions
194 /// \return The created propositional variable
196 {
198 }
199
200 /// \brief Returns a pbes expression that expresses equality of the multi-actions a and b.
201 /// \param a A sequence of actions
202 /// \param b A sequence of actions
203 /// \return Necessary conditions for the equality of a and b
205 {
207 }
208
209 /// \brief Returns the fixpoint symbol mu.
210 /// \return The fixpoint symbol mu.
212 {
213 return fixpoint_symbol::mu();
214 }
215
216 /// \brief Returns the fixpoint symbol nu.
217 /// \return The fixpoint symbol nu.
219 {
220 return fixpoint_symbol::nu();
221 }
222
223 /// \brief Returns a substitution of variables in q such that there are no name clashes
224 /// between p and q.
225 /// \param p A linear process specification
226 /// \param q A linear process specification
227 /// \return A substitution that should be applied to q to remove name clashes between p and q.
228 /// \details After this substitution the following holds:
229 /// \f[ ((param(p)\cup glob(p))\cap ((param(q)\cup glob(q))=\emptyset \f]
230 /// where param(p) denotes p.process().process_parameters() and glob(p) denotes p.global_variables().
232 {
234
235 // put the names of variables appearing in p and q in an identifier generator
240 for (const data::variable& v: context)
241 {
243 }
244
245 // generate renamings for variables appearing in qvars
246 for (const data::variable& w: q.process().process_parameters())
247 {
249 if (v != w)
250 {
251 result[w] = v;
252 }
253 }
254 return result;
255 }
256
257 /// \brief Returns a substitution of variables in q such that there are no name clashes
258 /// between the summation variables of p and q.
259 /// \param p A linear process specification
260 /// \param q A linear process specification
261 /// \return A substitution that should be applied to q to remove name clashes between p and q.
263 {
265
266 // put the names of variables appearing in p and q in an identifier generator
271 for (const data::variable& v: context)
272 {
274 }
275
276 // put the summation variables of q in qvars
278 for (const lps::action_summand& s: q.process().action_summands())
279 {
281 qvars.insert(v.begin(), v.end());
282 }
284 {
286 qvars.insert(v.begin(), v.end());
287 }
288
289 // generate renamings for variables appearing in qvars
290 for (const data::variable& w: qvars)
291 {
293 if (v != w)
294 {
295 result[w] = v;
296 }
297 }
298 return result;
299 }
300
301 /// \brief Resolves name clashes between model and spec.
303 {
307 {
310 }
311 mCRL2log(log::debug) << "bisimulation spec after resolving name clashes:\n" << lps::pp(spec) << std::endl;
312 }
313
314 /// \brief Initializes the name lookup table.
315 /// \param model A linear process
316 /// \param spec A linear process
317 /// \pre model and spec must have the same data specification
319 {
323 model_ptr = &model;
324 assert(is_from_model(model));
325 assert(!is_from_model(spec));
326 }
327
328 /// \brief Builds a pbes from the given equations.
329 /// \param equations A sequence of pbes equations
330 /// \param M A specification
331 /// \param S A specification
332 /// \return The constructed pbes
334 const lps::specification& M,
335 const lps::specification& S
336 )
337 {
338 const lps::linear_process& m = M.process();
339 const lps::linear_process& s = S.process();
340
342
344 assert(result.is_closed());
345 return result;
346 }
347};
348
349//--------------------------------------------------------------//
350// branching bisimulation
351//--------------------------------------------------------------//
352
353/// \brief Algorithm class for branching bisimulation.
355{
356 public:
357 /// \brief The match function.
358 /// \param p A linear process
359 /// \param q A linear process
360 /// \return The function result
362 {
363 std::vector<pbes_expression> result;
364 for (auto i = p.action_summands().begin(); i != p.action_summands().end(); ++i)
365 {
366 data::data_expression ci = i->condition();
367 const data::variable_list& d = p.process_parameters();
368 data::variable_list e = i->summation_variables();
369 const data::variable_list& d1 = q.process_parameters();
370 pbes_expression expr;
371 optimized_imp(expr, atermpp::down_cast<pbes_expression>(ci), var(Y(p, q, i), d + d1 + e));
372 expr = make_forall_(e, expr);
373 result.push_back(expr);
374 }
375 return optimized_join_and(result.begin(), result.end());
376 }
377
378 /// \brief The step function.
379 /// \param p A linear process
380 /// \param q A linear process
381 /// \param i A summand iterator
382 /// \return The function result
383 pbes_expression step(const lps::linear_process& p, const lps::linear_process& q, my_iterator i) const
384 {
385 const data::variable_list& d1 = q.process_parameters();
386 data::data_expression_list gi = i->next_state(p.process_parameters());
387 if (i->is_tau())
388 {
389 std::vector<pbes_expression> v;
390 pbes_expression expr;
391 for (auto j = q.action_summands().begin(); j != q.action_summands().end(); ++j)
392 {
393 if (!j->is_tau())
394 {
395 continue;
396 }
397 data::data_expression cj = j->condition();
398 data::variable_list e1 = j->summation_variables();
399 data::data_expression_list gj = j->next_state(q.process_parameters());
400 optimized_and(expr, atermpp::down_cast<pbes_expression>(cj), var(X(p, q), gi + gj));
401 expr = make_exists_(e1, expr);
402 v.push_back(expr);
403 }
404 optimized_or(expr, optimized_join_or(v.begin(), v.end()), var(X(p, q), gi + d1));
405 return expr;
406 }
407 else
408 {
409 std::vector<pbes_expression> v;
410 for (auto j = q.action_summands().begin(); j != q.action_summands().end(); ++j)
411 {
412 data::data_expression cj = j->condition();
413 data::variable_list e1 = j->summation_variables();
414 data::data_expression_list gj = j->next_state(q.process_parameters());
415 lps::multi_action ai = i->multi_action();
416 lps::multi_action aj = j->multi_action();
417 pbes_expression expr;
418 optimized_and(expr, atermpp::down_cast<pbes_expression>(cj), equals(ai, aj));
419 optimized_and(expr, expr, var(X(p, q), gi + gj));
420 expr = make_exists_(e1, expr);
421 v.push_back(expr);
422 }
423 return optimized_join_or(v.begin(), v.end());
424 }
425 }
426
427 /// \brief The close function.
428 /// \param p A linear process
429 /// \param q A linear process
430 /// \param i A summand iterator
431 /// \return The function result
432 pbes_expression close(const lps::linear_process& p, const lps::linear_process& q, my_iterator i) const
433 {
434 std::vector<pbes_expression> v;
435 pbes_expression expr;
436 const data::variable_list& d = p.process_parameters();
437 const data::variable_list& d1 = q.process_parameters();
438 data::variable_list e = i->summation_variables();
439 for (auto j = q.action_summands().begin(); j != q.action_summands().end(); ++j)
440 {
441 if (!j->is_tau())
442 {
443 continue;
444 }
445 data::data_expression cj = j->condition();
446 data::variable_list e1 = j->summation_variables();
447 data::data_expression_list gj = j->next_state(q.process_parameters());
448 optimized_and(expr, atermpp::down_cast<pbes_expression>(cj), var(Y(p, q, i),
449 variable_list_to_data_expression_list(d) +
450 gj +
451 data::variable_list_to_data_expression_list(e)));
452 expr = make_exists_(e1, expr);
453 v.push_back(expr);
454 }
455
456 optimized_and(expr, var(X(p, q), d + d1), step(p, q, i));
457 optimized_or(expr, optimized_join_or(v.begin(), v.end()), expr);
458 return expr;
459 }
460
461 /// \brief Returns a pbes that expresses branching bisimulation between
462 /// two specifications.
463 /// \param model A linear process specification
464 /// \param spec A linear process specification
465 /// \return A pbes that expresses branching bisimulation between the
466 /// two specifications.
467 pbes run(const lps::specification& model, const lps::specification& spec)
468 {
469 // resolve name clashes, and merge the data specifications of model and spec
470 data::data_specification dataspec = data::merge_data_specifications(model.data(), spec.data());
471 lps::specification spec1 = spec;
472 lps::specification model1 = model;
473 resolve_name_clashes(model1, spec1, true);
474 model1.data() = dataspec;
475 spec1.data() = dataspec;
476 lps::normalize_sorts(model1, model1.data());
477 lps::normalize_sorts(spec1, spec1.data());
478
479 const lps::linear_process& m = model1.process();
480 const lps::linear_process& s = spec1.process();
481 init(m, s);
482
483 const data::variable_list& d = m.process_parameters();
484 const data::variable_list& d1 = s.process_parameters();
485 std::vector<pbes_equation> equations;
486
487
488 // E1
489 pbes_expression expr;
491 equations.emplace_back(nu(), propositional_variable(X(m, s), d + d1), expr);
492 equations.emplace_back(nu(), propositional_variable(X(s, m), d1 + d), var(X(m, s), d + d1));
493
494 // E2
495 for (auto i = m.action_summands().begin(); i != m.action_summands().end(); ++i)
496 {
497 data::variable_list e = i->summation_variables();
498 pbes_equation e1(mu(), propositional_variable(Y(m, s, i), d + d1 + e), close(m, s, i));
499 equations.push_back(e1);
500 }
501 for (auto i = s.action_summands().begin(); i != s.action_summands().end(); ++i)
502 {
503 data::variable_list e = i->summation_variables();
504 pbes_equation e1(mu(), propositional_variable(Y(s, m, i), d1 + d + e), close(s, m, i));
505 equations.push_back(e1);
506 }
507
508 return build_pbes(equations, model1, spec1);
509 }
510};
511
512/// \brief Returns a pbes that expresses branching bisimulation between two specifications.
513/// \param model A linear process specification
514/// \param spec A linear process specification
515/// \return A pbes that expresses branching bisimulation between the two specifications.
516inline
518{
520}
521
522//--------------------------------------------------------------//
523// strong bisimulation
524//--------------------------------------------------------------//
525
526/// \brief Algorithm class for strong bisimulation.
528{
529 public:
530 /// \brief The match function.
531 /// \param p A linear process
532 /// \param q A linear process
533 /// \return The function result
535 {
536 std::vector<pbes_expression> result;
537 for (auto i = p.action_summands().begin(); i != p.action_summands().end(); ++i)
538 {
539 data::data_expression ci = i->condition();
540 data::variable_list e = i->summation_variables();
541 pbes_expression expr;
542 optimized_imp(expr, atermpp::down_cast<pbes_expression>(ci), step(p, q, i));
543 expr = make_forall_(e, expr);
544 result.push_back(expr);
545 }
546 return optimized_join_and(result.begin(), result.end());
547 }
548
549 /// \brief The step function.
550 /// \param p A linear process
551 /// \param q A linear process
552 /// \param i A summand iterator
553 /// \return The function result
554 pbes_expression step(const lps::linear_process& p, const lps::linear_process& q, my_iterator i) const
555 {
556 data::data_expression_list gi = i->next_state(p.process_parameters());
557
558 std::vector<pbes_expression> result;
559 for (auto j = q.action_summands().begin(); j != q.action_summands().end(); ++j)
560 {
561 data::data_expression cj = j->condition();
562 data::variable_list e1 = j->summation_variables();
563 data::data_expression_list gj = j->next_state(q.process_parameters());
564 lps::multi_action ai = i->multi_action();
565 lps::multi_action aj = j->multi_action();
566 pbes_expression expr;
567 optimized_and(expr, atermpp::down_cast<pbes_expression>(cj), equals(ai, aj));
568 optimized_and(expr, expr, var(X(p, q), gi + gj));
569 expr = make_exists_(e1, expr);
570 result.push_back(expr);
571 }
572 return optimized_join_or(result.begin(), result.end());
573 }
574
575 /// \brief Runs the algorithm
576 /// \param model A linear process specification
577 /// \param spec A linear process specification
578 /// \return A pbes that expresses strong bisimulation between stwo specifications.
579 pbes run(const lps::specification& model, const lps::specification& spec)
580 {
581 lps::specification spec1 = spec;
582 resolve_name_clashes(model, spec1, true);
583 const lps::linear_process& m = model.process();
584 const lps::linear_process& s = spec1.process();
585 init(m, s);
586
587 const data::variable_list& d = m.process_parameters();
588 const data::variable_list& d1 = s.process_parameters();
589 std::vector<pbes_equation> equations;
590
591
592 // E
593 pbes_expression expr;
595 equations.emplace_back(nu(), propositional_variable(X(m, s), d + d1), expr);
596 equations.emplace_back(nu(), propositional_variable(X(s, m), d1 + d), var(X(m, s), d + d1));
597
598 return build_pbes(equations, model, spec1);
599 }
600};
601
602/// \brief Returns a pbes that expresses strong bisimulation between two specifications.
603/// \param model A linear process specification
604/// \param spec A linear process specification
605/// \return A pbes that expresses strong bisimulation between the two specifications.
606inline
608{
609 return strong_bisimulation_algorithm().run(model, spec);
610}
611
612//--------------------------------------------------------------//
613// weak bisimulation
614//--------------------------------------------------------------//
615
616/// \brief Algorithm class for weak bisimulation.
618{
619 protected:
621
622 public:
623 /// \brief The match function.
624 /// \param p A linear process
625 /// \param q A linear process
626 /// \return The function result
628 {
629 std::vector<pbes_expression> result;
630 for (auto i = p.action_summands().begin(); i != p.action_summands().end(); ++i)
631 {
632 data::data_expression ci = i->condition();
633 const data::variable_list& d = p.process_parameters();
634 data::variable_list e = i->summation_variables();
635 const data::variable_list& d1 = q.process_parameters();
636 pbes_expression expr;
637 optimized_imp(expr, atermpp::down_cast<pbes_expression>(ci), var(Y1(p, q, i), d + d1 + e));
638 expr = make_forall_(e, expr);
639 result.push_back(expr);
640 }
641 return optimized_join_and(result.begin(), result.end());
642 }
643
644 /// \brief The step function.
645 /// \param p A linear process
646 /// \param q A linear process
647 /// \param i A summand iterator
648 /// \return The function result
649 pbes_expression step(const lps::linear_process& p, const lps::linear_process& q, my_iterator i) const
650 {
651 const data::variable_list& d1 = q.process_parameters();
652 data::data_expression_list gi = i->next_state(p.process_parameters());
653 lps::multi_action ai(i->multi_action().actions());
654 if (i->is_tau())
655 {
656 return close2(p, q, i, gi, data::data_expression_list(d1.begin(), d1.end()));
657 }
658 else
659 {
660 std::vector<pbes_expression> v;
661 for (auto j = q.action_summands().begin(); j != q.action_summands().end(); ++j)
662 {
663 data::data_expression cj = j->condition();
664 data::variable_list e1 = j->summation_variables();
665 data::data_expression_list gj = j->next_state(q.process_parameters());
666 lps::multi_action aj(j->multi_action().actions());
667 pbes_expression expr;
668 optimized_and(expr, atermpp::down_cast<pbes_expression>(cj), equals(ai, aj)), close2(p, q, i, gi, gj);
669 optimized_and(expr, expr, close2(p, q, i, gi, gj));
670 expr = make_exists_(e1, expr);
671 v.push_back(expr);
672 }
673 return optimized_join_or(v.begin(), v.end());
674 }
675 }
676
677 /// \brief The close1 function.
678 /// \param p A linear process
679 /// \param q A linear process
680 /// \param i A summand iterator
681 /// \return The function result
682 pbes_expression close1(const lps::linear_process& p, const lps::linear_process& q, my_iterator i) const
683 {
684 std::vector<pbes_expression> v;
685 pbes_expression expr;
686 data::variable_list e = i->summation_variables();
687 const data::variable_list& d = p.process_parameters();
688 const data::variable_list& d1 = q.process_parameters();
689 for (auto j = q.action_summands().begin(); j != q.action_summands().end(); ++j)
690 {
691 if (!j->is_tau())
692 {
693 continue;
694 }
695 data::data_expression cj = j->condition();
696 data::variable_list e1 = j->summation_variables();
697 data::data_expression_list gj = j->next_state(d1);
698 optimized_and(expr, atermpp::down_cast<pbes_expression>(cj), var(Y1(p, q, i),
699 data::variable_list_to_data_expression_list(d) +
700 gj +
701 data::variable_list_to_data_expression_list(e)));
702 expr = make_exists_(e1, expr);
703 v.push_back(expr);
704 }
705 optimized_or(expr, optimized_join_or(v.begin(), v.end()), step(p, q, i));
706 return expr;
707 }
708
709 /// \brief The close function.
710 /// \param p A linear process
711 /// \param q A linear process
712 /// \param i A summand iterator
713 /// \param d A sequence of data expressions
714 /// \param d1 A sequence of data expressions
715 /// \return The function result
716 pbes_expression close2(const lps::linear_process& p, const lps::linear_process& q, my_iterator i, const data::data_expression_list& d, const data::data_expression_list& d1) const
717 {
718 const data::variable_list& parameters = q.process_parameters();
719 data::mutable_map_substitution<> sigma; // q.process_parameters() := d1
720 make_substitution(parameters, d1, sigma);
721 data::set_identifier_generator id_generator;
722 for (const data::variable& v: data::find_free_variables(d1))
723 {
724 id_generator.add_identifier(v.name());
725 }
726
727 std::vector<pbes_expression> v;
728 pbes_expression expr;
729
730 for (auto j = q.action_summands().begin(); j != q.action_summands().end(); ++j)
731 {
732 if (!j->is_tau())
733 {
734 continue;
735 }
736 // d' == q.process_parameters()
737 // e' == j->summand_variables()
738 data::data_expression cj = j->condition(); // cj == cj(d',e')
739 data::data_expression_list gj = j->next_state(q.process_parameters()); // gj == gj(d',e')
740 data::variable_list e1 = j->summation_variables(); // e1 == e'
741
742 // replace d' by d1 (if needed)
743 if (d1 != data::data_expression_list(parameters.begin(), parameters.end()))
744 {
745 cj = data::replace_variables_capture_avoiding(cj, sigma, id_generator);
746 gj = data::replace_variables_capture_avoiding(gj, sigma, id_generator);
747 }
748
749 // replace e' (e1) by fresh variables e'' (e11)
750 std::vector<data::variable> tmp;
751 for (const data::variable& w: e1)
752 {
753 tmp.emplace_back(m_generator(std::string(w.name())), w.sort());
754 }
755 data::variable_list e11(tmp.begin(), tmp.end());
756
757 data::mutable_map_substitution<> sigma1;
758 make_substitution(e1, e11 | std::views::transform([](const data::variable& v) { return atermpp::down_cast<data::data_expression>(v); }), sigma1);
759 for (const data::variable& w: e11)
760 {
761 id_generator.add_identifier(w.name());
762 }
763 data::data_expression cj_new = data::replace_variables_capture_avoiding(cj, sigma1, id_generator);
764 data::data_expression_list gj_new = data::replace_variables_capture_avoiding(gj, sigma1, id_generator);
765
766 optimized_and(expr, atermpp::down_cast<pbes_expression>(cj_new), var(Y2(p, q, i), d + gj_new));
767 expr = make_exists_(e11, expr);
768 v.push_back(expr);
769 }
770 optimized_or(expr, var(X(p, q), d + d1), optimized_join_or(v.begin(), v.end()));
771 return expr;
772 }
773
774 /// \brief Runs the algorithm
775 /// \param model A linear process specification
776 /// \param spec A linear process specification
777 /// \return A pbes that expresses weak bisimulation between two specifications.
778 pbes run(const lps::specification& model, const lps::specification& spec)
779 {
780 lps::specification spec1 = spec;
781 resolve_name_clashes(model, spec1, true);
782 const lps::linear_process& m = model.process();
783 const lps::linear_process& s = spec1.process();
784 init(m, s);
785
786 m_generator.clear_context();
787 m_generator.add_identifiers(data::function_and_mapping_identifiers(model.data()));
788 m_generator.add_identifiers(data::function_and_mapping_identifiers(spec.data()));
789 m_generator.add_identifiers(lps::find_identifiers(model));
790 m_generator.add_identifiers(lps::find_identifiers(spec));
791
792 data::variable_list const& d = m.process_parameters();
793 data::variable_list const& d1 = s.process_parameters();
794 std::vector<pbes_equation> equations;
795
796 // E1
797 pbes_expression expr;
799 equations.emplace_back(nu(), propositional_variable(X(m, s), d + d1), expr);
800 equations.emplace_back(nu(), propositional_variable(X(s, m), d1 + d), var(X(m, s), d + d1));
801
802 // E2
803 for (auto i = m.action_summands().begin(); i != m.action_summands().end(); ++i)
804 {
805 data::variable_list e = i->summation_variables();
806 pbes_equation e1(mu(), propositional_variable(Y1(m, s, i), d + d1 + e), close1(m, s, i));
807 pbes_equation e2(mu(), propositional_variable(Y2(m, s, i), d + d1), close2(m, s, i, data::data_expression_list(d.begin(), d.end()), data::data_expression_list(d1.begin(), d1.end())));
808 equations.push_back(e1);
809 equations.push_back(e2);
810 }
811 for (auto i = s.action_summands().begin(); i != s.action_summands().end(); ++i)
812 {
813 data::variable_list e = i->summation_variables();
814 pbes_equation e1(mu(), propositional_variable(Y1(s, m, i), d1 + d + e), close1(s, m, i));
815 pbes_equation e2(mu(), propositional_variable(Y2(s, m, i), d1 + d), close2(s, m, i, data::data_expression_list(d1.begin(), d1.end()), data::data_expression_list(d.begin(), d.end())));
816 equations.push_back(e1);
817 equations.push_back(e2);
818 }
819
820 return build_pbes(equations, model, spec1);
821 }
822};
823
824/// \brief Returns a pbes that expresses weak bisimulation between two specifications.
825/// \param model A linear process specification
826/// \param spec A linear process specification
827/// \return A pbes that expresses weak bisimulation between the two specifications.
828inline
830{
831 return weak_bisimulation_algorithm().run(model, spec);
832}
833
834//--------------------------------------------------------------//
835// branching simulation equivalence
836//--------------------------------------------------------------//
837
838/// \brief Algorithm class for branching simulation equivalence.
840{
841 public:
842 /// \brief Runs the algorithm
843 /// \param model A linear process specification
844 /// \param spec A linear process specification
845 /// \return A pbes that expresses branching simulation equivalence between two specifications.
846 pbes run(const lps::specification& model, const lps::specification& spec)
847 {
848 lps::specification spec1 = spec;
849 resolve_name_clashes(model, spec1, true);
850 const lps::linear_process& m = model.process();
851 const lps::linear_process& s = spec1.process();
852 init(m, s);
853
854 data::variable_list const& d = m.process_parameters();
855 data::variable_list const& d1 = s.process_parameters();
856 std::vector<pbes_equation> equations;
857
858
859 // E1
860 pbes_expression expr;
861 optimized_and(expr, match(m, s), match(s, m));
862 equations.emplace_back(nu(), propositional_variable(X(m, s), d + d1), expr);
863 equations.emplace_back(nu(), propositional_variable(X(s, m), d1 + d), var(X(m, s), d + d1));
864
865 // E2
866 for (auto i = m.action_summands().begin(); i != m.action_summands().end(); ++i)
867 {
868 data::variable_list e = i->summation_variables();
869 pbes_equation e1(mu(), propositional_variable(Y(m, s, i), d + d1 + e), close(m, s, i));
870 equations.push_back(e1);
871 }
872 for (auto i = s.action_summands().begin(); i != s.action_summands().end(); ++i)
873 {
874 data::variable_list e = i->summation_variables();
875 pbes_equation e1(mu(), propositional_variable(Y(s, m, i), d1 + d + e), close(s, m, i));
876 equations.push_back(e1);
877 }
878
879 return build_pbes(equations, model, spec1);
880 }
881};
882
883/// \brief Returns a pbes that expresses branching simulation equivalence between two specifications.
884/// \param model A linear process specification
885/// \param spec A linear process specification
886/// \return A pbes that expresses branching simulation equivalence between the two specifications.
887inline
889{
891}
892
893} // namespace mcrl2::pbes_system
894
895
896
897#endif // MCRL2_PBES_BISIMULATION_H
Identifier generator that stores the identifiers of the context in a set. Using the operator()() and ...
LPS summand containing a multi-action.
\brief A timed multi-action
Linear process specification.
Base class for bisimulation algorithms.
const lps::linear_process * model_ptr
Store the address of the model.
name_map summand_names
Maps summands to strings.
std::string process_name(const lps::linear_process &p) const
Returns a name of a linear process.
std::string summand_name(my_iterator i) const
Returns the name of a summand.
bool is_from_model(const lps::linear_process &p) const
Returns true if p is the linear process of the model.
std::string action_list_name(const process::action_list &l) const
Generates a name for an action_list.
void set_summand_names(const lps::linear_process &p)
Used for initializing summand names.
Algorithm class for branching bisimulation.
pbes_expression close(const lps::linear_process &p, const lps::linear_process &q, my_iterator i) const
The close function.
pbes_expression match(const lps::linear_process &p, const lps::linear_process &q) const
The match function.
pbes_expression step(const lps::linear_process &p, const lps::linear_process &q, my_iterator i) const
The step function.
pbes run(const lps::specification &model, const lps::specification &spec)
Returns a pbes that expresses branching bisimulation between two specifications.
Algorithm class for branching simulation equivalence.
pbes run(const lps::specification &model, const lps::specification &spec)
Runs the algorithm.
parameterized boolean equation system
Definition pbes.h:54
Algorithm class for strong bisimulation.
pbes_expression match(const lps::linear_process &p, const lps::linear_process &q) const
The match function.
pbes_expression step(const lps::linear_process &p, const lps::linear_process &q, my_iterator i) const
The step function.
pbes run(const lps::specification &model, const lps::specification &spec)
Runs the algorithm.
Algorithm class for weak bisimulation.
pbes run(const lps::specification &model, const lps::specification &spec)
Runs the algorithm.
pbes_expression close2(const lps::linear_process &p, const lps::linear_process &q, my_iterator i, const data::data_expression_list &d, const data::data_expression_list &d1) const
The close function.
pbes_expression close1(const lps::linear_process &p, const lps::linear_process &q, my_iterator i) const
The close1 function.
data::set_identifier_generator m_generator
pbes_expression step(const lps::linear_process &p, const lps::linear_process &q, my_iterator i) const
The step function.
pbes_expression match(const lps::linear_process &p, const lps::linear_process &q) const
The match function.
#define mCRL2log(LEVEL)
mCRL2log(LEVEL) provides the stream used to log.
Definition logger.h:393
data_specification merge_data_specifications(const data_specification &dataspec1, const data_specification &dataspec2)
Merges two data specifications. Throws an exception if conflicts are detected.
The main namespace for the LPS library.
Definition constelm.h:18
pbes strong_bisimulation(const lps::specification &model, const lps::specification &spec)
Returns a pbes that expresses strong bisimulation between two specifications.
pbes branching_simulation_equivalence(const lps::specification &model, const lps::specification &spec)
Returns a pbes that expresses branching simulation equivalence between two specifications.
pbes branching_bisimulation(const lps::specification &model, const lps::specification &spec)
Returns a pbes that expresses branching bisimulation between two specifications.
pbes weak_bisimulation(const lps::specification &model, const lps::specification &spec)
Returns a pbes that expresses weak bisimulation between two specifications.
void optimized_and(pbes_expression &result, const pbes_expression &p, const pbes_expression &q)
Make a conjunction.