mCRL2
Loading...
Searching...
No Matches
liblts_plts_merge.h
Go to the documentation of this file.
1// Author(s): Hector Joao Rivera Verduzco
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
10// This file contains the merge algorithm that merges two plts's.
11// Merges an LTS L with this LTS (say K) and stores the resulting LTS
12// (say M) in this LTS datastructure, effectively replacing K.
13// Conceptually, we just take the union of the sets of states and the
14// sets of transitions of K and L:
15// States_M = States_K + States_L
16// Transitions_M = Transitions_K + Transitions_L
17// where + denotes set union.
18// However, this assumes that States_K and States_L are disjoint,
19// which is generally not the case. More specifically we have:
20// States_K = { 0, ..., N_K - 1 } and
21// States_L = { 0, ..., N_L - 1 }
22// for some N_K, N_L > 0.
23// Therefore, state i of L will be numbered |N_K| + i in the resulting
24// LTS M and state i of K will be numbered i in M. This yields:
25// States_M = { 0, ..., N_K + N_L - 1 }.
26
27
28#ifndef MCRL2_LTS_LIBLTS_PLTS_MERGE_H
29#define MCRL2_LTS_LIBLTS_PLTS_MERGE_H
30
31#include "mcrl2/lts/lts_aut.h"
32#include "mcrl2/lts/lts_fsm.h"
33#include "mcrl2/lts/lts_lts.h"
34
35namespace mcrl2::lts::detail
36{
37
38template <class LTS_TYPE>
39void plts_merge(LTS_TYPE& l1, const LTS_TYPE& l2)
40{
41 const std::size_t old_nstates=l1.num_states();
42 const std::size_t old_n_prob_states = l1.num_probabilistic_states();
43 l1.set_num_states(l1.num_states() + l2.num_states());
44
45 // The resulting LTS will have state information only if BOTH LTSs
46 // currently have state information.
47 if (l1.has_state_info() && l2.has_state_info())
48 {
49 for (std::size_t i=0; i<l2.num_states(); ++i)
50 {
51 l1.add_state(l2.state_label(i));
52 }
53 }
54 else
55 {
56 // remove state information from this LTS, if any
57 l1.clear_state_labels();
58 }
59
60 // Before we can set the label data in a new transitions
61 // array, we first have to collect the labels of both LTSs in a
62 // map, of which the second element indicates the new index of each action label.
63
64 using type1 = typename LTS_TYPE::action_label_t;
65 using type2 = typename LTS_TYPE::labels_size_type;
66 using insert_type = typename std::pair<typename std::map<type1, type2>::const_iterator, bool>;
67 std::map < type1,type2 > labs;
68
69 // Put the labels of the LTS l1 in a map.
70 for (std::size_t i = 0; i < l1.num_action_labels(); ++i)
71 {
72 labs.insert(std::pair <typename LTS_TYPE::action_label_t,typename LTS_TYPE::labels_size_type>
73 (l1.action_label(i),i));
74 }
75 // Add the labels for the LTS l2, and put them there with a new index if it was
76 // not added yet.
77 // Furthermore, update the hidden_action_map.
78 // If label a1 is mapped on a2 in l2, then this must be the same
79 // in l1. It may be that label a1 did not exist yet in which case it needs
80 // to be added too.
81
82
83 for (std::size_t i=0; i<l2.num_action_labels(); ++i)
84 {
85 typename LTS_TYPE::labels_size_type new_index;
86 const insert_type it= labs.insert(std::pair < type1,type2 >
87 (l2.action_label(i),l1.num_action_labels()));
88 if (it.second)
89 {
90 // New element has been inserted.
91 new_index=l1.add_action(l2.action_label(i));
92 if (l2.is_tau(l2.apply_hidden_label_map(i)))
93 {
94 l1.hidden_label_set().insert(new_index);
95 }
96 }
97 else
98 {
99 new_index=it.first->second; // Old index to which i is mapped.
100 // If label i occurred in l1 and were not both mapped to the hidden label, raise an exception.
101 if (l1.is_tau(l1.apply_hidden_label_map(new_index)) != l2.is_tau(l2.apply_hidden_label_map(i)))
102 {
103 throw mcrl2::runtime_error("The action " + pp(l2.action_label(i)) + " has incompatible hidden actions " +
104 pp(l1.action_label(l1.apply_hidden_label_map(new_index))) + " and " +
105 pp(l2.action_label(l2.apply_hidden_label_map(i))) + ".");
106 }
107
108 }
109 assert(new_index==it.first->second);
110 }
111
112 // Update the label numbers of all transitions of the LTS l1 to reflect
113 // the new indices as given by labs.
114 std::vector<transition> &trans1=l1.get_transitions();
115 for (transition& t : trans1)
116 {
117 t.set_label(labs[l1.action_label(t.label())]);
118 }
119
120 // Now add the transition labels of LTS l2
121 // Now add the source and target states of the transitions of LTS l2.
122 // The labels will be added below, depending on whether there is label
123 // information in both LTSs.
124 const std::vector<transition> &trans2=l2.get_transitions();
125 for (const transition transition_to_add : trans2)
126 {
127 l1.add_transition(transition(transition_to_add.from()+old_nstates,
128 labs[l2.action_label(transition_to_add.label())],
129 transition_to_add.to()+old_n_prob_states));
130 }
131
132 // Now update the state number for each probability pairs of all
133 // probabilistic states
134 const std::size_t n_prob_states_l2 = l2.num_probabilistic_states();
135 for (std::size_t i = 0; i < n_prob_states_l2; ++i)
136 {
137 typename LTS_TYPE::probabilistic_state_t new_prob_state;
138 const typename LTS_TYPE::probabilistic_state_t& old_prob_state = l2.probabilistic_state(i);
139
140 if (old_prob_state.size()>1)
141 {
142 for (const typename LTS_TYPE::probabilistic_state_t::state_probability_pair& sp_pair : old_prob_state)
143 {
144 new_prob_state.add(sp_pair.state()+ old_nstates, sp_pair.probability());
145 }
146
147 }
148 else
149 {
150 new_prob_state.set(old_prob_state.get()+old_nstates);
151 }
152 l1.add_probabilistic_state(new_prob_state);
153 }
154
155 // Add the initial probabilistic state of both plts at the end of the merged plts.
156 // First add the initia probabilistic state of l1
157 l1.add_probabilistic_state(l1.initial_probabilistic_state());
158
159 // Then add the initia probabilistic state of l2
160 typename LTS_TYPE::probabilistic_state_t new_initial_prob_state_l2;
161 if (l2.initial_probabilistic_state().size()<=1)
162 {
163 new_initial_prob_state_l2.set(l2.initial_probabilistic_state().get() + old_nstates);
164 }
165 else // If the initial state is a distribution with more than one state.
166 {
167 for (const typename LTS_TYPE::probabilistic_state_t::state_probability_pair& sp_pair : l2.initial_probabilistic_state())
168 {
169 new_initial_prob_state_l2.add(sp_pair.state() + old_nstates, sp_pair.probability());
170 }
171 }
172 l1.add_probabilistic_state(new_initial_prob_state_l2);
173}
174} // namespace mcrl2::lts::detail
175
176#endif // MCRL2_LTS_LIBLTS_PLTS_MERGE_H
function object to compare two constln_t pointers based on their contents
void plts_merge(LTS_TYPE &l1, const LTS_TYPE &l2)