mCRL2
Loading...
Searching...
No Matches
fsm_builder.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/lts/detail/fsm_builder.h
10/// \brief The code in this file is used to construct an lts in fsm format.
11
12#ifndef MCRL2_LTS_DETAIL_FSM_BUILDER_H
13#define MCRL2_LTS_DETAIL_FSM_BUILDER_H
14
15#include <map>
16#include "mcrl2/lts/lts_fsm.h"
17#include "mcrl2/utilities/parse_numbers.h"
18
19namespace mcrl2::lts::detail {
20
21// Read a numeric value before a symbol c1 or c2, and remove it from s, including the symbol.
22inline std::string split_string_until(std::string& s, const std::string& c1, const std::string& c2="")
23{
24 std::size_t n=s.find(c1);
25 if (!c2.empty())
26 {
27 n=std::min(n,s.find(c2));
28 }
29 if (n==std::string::npos)
30 {
31 if (c2.empty())
32 {
33 throw mcrl2::runtime_error("Expect '" + c1 + "' in distribution " + s + ".");
34 }
35 else
36 {
37 throw mcrl2::runtime_error("Expect either '" + c1 + "' or '" + c2 + " in distribution " + s + ".");
38 }
39 }
40 std::string result=s.substr(0,n);
41 s=s.substr(n+1);
42 return result;
43}
44
46{
47 if (distribution.find('[')==std::string::npos) // So the distribution must consist of a state index.
48 {
49 std::size_t state_number=utilities::parse_natural_number(distribution);
50 if (state_number==0)
51 {
52 throw mcrl2::runtime_error("Transition has a zero as target state number.");
53 }
54 return lts_fsm_base::probabilistic_state(state_number-1);
55 }
56
57 // Otherwise the distribution has the shape [state1 enumerator1/denominator1 ... staten enumeratorn/denominatorn]
58 std::vector<lts_fsm_base::state_probability_pair> result;
59 std::string s = utilities::trim_copy(distribution);
60 if (!s.starts_with("["))
61 {
62 throw mcrl2::runtime_error("Distribution does not start with ']': " + distribution + ".");
63 }
64 s = s.substr(1); // Remove initial "[";
65 for(; s.size() > 1; s = utilities::trim_copy(s))
66 {
67 std::size_t state_number = utilities::parse_natural_number(split_string_until(s," "));
68 if (state_number == 0)
69 {
70 throw mcrl2::runtime_error("Transition has a zero as target state number.");
71 }
72 std::string enumerator = split_string_until(s,"/");
73 std::string denominator = split_string_until(s," ","]");
74 result.emplace_back(state_number - 1, utilities::probabilistic_arbitrary_precision_fraction(enumerator,denominator));
75 }
76 return lts_fsm_base::probabilistic_state(result.begin(), result.end());
77}
78
80{
81 protected:
86
87 public:
88 fsm_parameter(const std::string& name, const std::string& cardinality, const std::string& sort, const std::vector<std::string>& values)
89 : m_name(name),
91 m_sort(sort),
93 {}
94
95 const std::string& name() const
96 {
97 return m_name;
98 }
99
101 {
102 return m_name;
103 }
104
105 const std::string& sort() const
106 {
107 return m_sort;
108 }
109
111 {
112 return m_sort;
113 }
114
115 // If the cardinality is zero, the sort and the values are ignored in the FSM.
117 {
118 return m_cardinality;
119 }
120
122 {
123 return m_cardinality;
124 }
125
126 const std::vector<std::string>& values() const
127 {
128 return m_values;
129 }
130
132 {
133 return m_values;
134 }
135};
136
137/// \brief Transitions in an FSM
138///
139/// \note All state numbers in an FSM file are larger or equal to 1. When reading one is subtracted.
141{
142 protected:
146
147 public:
148 fsm_transition(std::size_t source, std::size_t target, const std::string& label)
149 : m_source(source - 1),
152 {
153 if (source == 0 || target == 0)
154 {
155 throw mcrl2::runtime_error("A transition contains a state with state number 0.");
156 }
157 }
158
159 fsm_transition(const std::string& source_text, const std::string& target_text, const std::string& label)
160 : m_label(label)
161 {
162 std::size_t source = utilities::parse_natural_number(source_text);
163 if (source == 0)
164 {
165 throw mcrl2::runtime_error("A transition constains a source state with number 0.");
166 }
167 m_source = source - 1;
168 m_target = parse_distribution(target_text);
169 }
170
172 {
173 return m_source;
174 }
175
177 {
178 return m_source;
179 }
180
182 {
183 return m_target;
184 }
185
187 {
188 return m_target;
189 }
190
191 const std::string& label() const
192 {
193 return m_label;
194 }
195
197 {
198 return m_label;
199 }
200};
201
203{
205 : fsm(fsm_)
206 {}
207
208 // Contains the result
210
211 // The parameters of the FSM
213
214 // Maps labels of the FSM to numbers
216
217 // This variable records if the initial state is set explicitly.
218 // If not it needs to be done while finishing the fsm.
220
221 void start()
222 {
223 parameters.clear();
224 labels.clear();
225 labels[action_label_string::tau_action()] = 0; // The label 0 is the tau action by default.
226 fsm.clear();
227 }
228
230 {
231 std::size_t max = 0;
232 if (distribution.size()>1)
233 {
234 for (const detail::lts_fsm_base::state_probability_pair& p: distribution)
235 {
236 max = std::max(max, p.state());
237 }
238 }
239 else
240 {
241 max=distribution.get();
242 }
243 return max;
244 }
245
246 void add_transition(const std::string& source, const std::string& target, const std::string& label)
247 {
248 fsm_transition t(source, target, label);
249
250 // Apply a correction with +1 for the mismatch between numbering in lts_fsm and the fsm file format
251 std::size_t max = std::max(t.source(),find_maximal_state_index(t.target()))+1;
252
253 if (fsm.num_states() <= max)
254 {
255 fsm.set_num_states(max, fsm.has_state_info());
256 }
257 auto i = labels.find(t.label());
258 lts_fsm_t::labels_size_type label_index = 0;
259 if (i == labels.end())
260 {
261 assert(t.label() != action_label_string::tau_action());
262 label_index = fsm.add_action(action_label_string(t.label()));
263 labels[t.label()] = label_index;
264 }
265 else
266 {
267 label_index = i->second;
268 }
269
270 const std::size_t probabilistic_state_index = fsm.add_probabilistic_state(detail::lts_fsm_base::probabilistic_state(t.target()));
271 fsm.add_transition(transition(t.source(), label_index, probabilistic_state_index));
272 }
273
274 void add_state(const std::vector<std::size_t>& values)
275 {
276 fsm.add_state(state_label_fsm(values));
277 }
278
279 void add_parameter(const std::string& name, const std::string& cardinality, const std::string& sort, const std::vector<std::string>& domain_values)
280 {
281 parameters.emplace_back(name, cardinality, sort, domain_values);
282 }
283
284 void add_initial_distribution(const std::string& distribution)
285 {
286 const lts_fsm_base::probabilistic_state d=parse_distribution(distribution);
287 std::size_t max=find_maximal_state_index(d)+1; // Add one as state numbers are subtracted by one when parsing.
288
289 if (fsm.num_states() <= max)
290 {
291 fsm.set_num_states(max, fsm.has_state_info());
292 }
293 fsm.add_probabilistic_state(detail::lts_fsm_base::probabilistic_state(d));
294
295 fsm.set_initial_probabilistic_state(d);
297 }
298
300 {
301 std::size_t index = 0;
302 for (const fsm_parameter& param: parameters)
303 {
304 if (param.cardinality() > 0)
305 {
306 fsm.add_process_parameter(param.name(), param.sort());
307 for (const std::string& value: param.values())
308 {
309 fsm.add_state_element_value(index, value);
310 }
311 }
312 index++;
313 }
314 }
315
316 void finish()
317 {
318 // guarantee that the LTS has at least one state
319 if (fsm.num_states() == 0)
320 {
321 fsm.add_state();
322 }
324 {
325 fsm.set_initial_probabilistic_state(detail::lts_fsm_base::probabilistic_state(0));
326 }
327 }
328};
329
330} // namespace mcrl2::lts::detail
331
332#endif // MCRL2_LTS_DETAIL_FSM_BUILDER_H
function object to compare two constln_t pointers based on their contents
std::vector< std::string > m_values
Definition fsm_builder.h:85
const std::vector< std::string > & values() const
std::size_t cardinality() const
const std::string & name() const
Definition fsm_builder.h:95
fsm_parameter(const std::string &name, const std::string &cardinality, const std::string &sort, const std::vector< std::string > &values)
Definition fsm_builder.h:88
std::vector< std::string > & values()
const std::string & sort() const
const std::string & label() const
const lts_fsm_base::probabilistic_state & target() const
lts_fsm_base::probabilistic_state & target()
fsm_transition(std::size_t source, std::size_t target, const std::string &label)
fsm_transition(const std::string &source_text, const std::string &target_text, const std::string &label)
detail::lts_fsm_base::probabilistic_state m_target
std::vector< std::string > parse_domain_values(const std::string &text)
Definition parse.h:59
void run(std::istream &from)
Definition parse.h:134
void parse_parameter(const std::string &line)
Definition parse.h:77
states next_state(states state)
Definition parse.h:44
const std::regex regex_quoted_string
Definition parse.h:39
void parse_state(const std::string &line)
Definition parse.h:92
const std::regex regex_parameter
Definition parse.h:30
simple_fsm_parser(probabilistic_lts_fsm_t &fsm)
Definition parse.h:130
const std::regex regex_transition
Definition parse.h:37
void parse_initial_distribution(const std::string &line)
Definition parse.h:119
detail::fsm_builder builder
Definition parse.h:28
void parse_transition(const std::string &line)
Definition parse.h:105
const std::regex regex_probabilistic_initial_distribution
Definition parse.h:42
A class to contain labelled transition systems in graphviz format.
Definition lts_dot.h:132
void save(const std::string &filename) const
Save the labelled transition system to a file.
void save(std::ostream &os) const
Save the labelled transition system to a stream.
A class to contain labelled transition systems in graphviz format.
Definition lts_dot.h:158
void save(std::ostream &os) const
Save the labelled transition system to a stream.
void save(const std::string &filename) const
Save the labelled transition system to a file.
The class lts_fsm_t contains labelled transition systems in .fsm format.
Definition lts_fsm.h:282
std::string split_string_until(std::string &s, const std::string &c1, const std::string &c2="")
Definition fsm_builder.h:22
lts_fsm_base::probabilistic_state parse_distribution(const std::string &distribution)
Definition fsm_builder.h:45
void parse_fsm_specification(std::istream &from, probabilistic_lts_fsm_t &result)
Definition parse.h:168
void parse_fsm_specification(const std::string &text, probabilistic_lts_fsm_t &result)
Definition parse.h:175
fsm_builder(probabilistic_lts_fsm_t &fsm_)
std::map< std::string, std::size_t > labels
void add_initial_distribution(const std::string &distribution)
void add_state(const std::vector< std::size_t > &values)
probabilistic_lts_fsm_t & fsm
void add_parameter(const std::string &name, const std::string &cardinality, const std::string &sort, const std::vector< std::string > &domain_values)
void add_transition(const std::string &source, const std::string &target, const std::string &label)
std::vector< fsm_parameter > parameters
std::size_t find_maximal_state_index(const lts_fsm_base::probabilistic_state &distribution)