Line data Source code
1 : // Author(s): Gijs Kant
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/pbes_explorer.cpp
10 : /// \brief
11 : #include <climits>
12 : #include <queue>
13 :
14 : #include "mcrl2/data/detail/io.h"
15 : #include "mcrl2/data/representative_generator.h"
16 : #include "mcrl2/pbes/detail/ppg_visitor.h"
17 : #include "mcrl2/pbes/io.h"
18 : #include "mcrl2/pbes/pbes_explorer.h"
19 :
20 :
21 : namespace mcrl2
22 : {
23 :
24 : namespace pbes_system
25 : {
26 :
27 : namespace detail
28 : {
29 : template <typename MapContainer>
30 19364 : typename MapContainer::mapped_type map_at(const MapContainer& m, typename MapContainer::key_type key)
31 : {
32 19364 : typename MapContainer::const_iterator i = m.find(key);
33 19364 : if (i == m.end())
34 : {
35 0 : throw mcrl2::runtime_error("map_at: key is not present in the map: " + key);
36 : }
37 36996 : return i->second;
38 : }
39 : } // namespace detail
40 :
41 : /// lts_type
42 :
43 12 : lts_type::lts_type(int state_length)
44 : {
45 12 : this->state_length = state_length;
46 12 : }
47 :
48 :
49 12 : lts_type::~lts_type()
50 12 : {}
51 :
52 :
53 13730 : int lts_type::get_state_length() const
54 : {
55 13730 : return this->state_length;
56 : }
57 :
58 :
59 18 : std::size_t lts_type::get_number_of_state_types() const
60 : {
61 18 : return this->state_type_list.size();
62 : }
63 :
64 :
65 27696 : int lts_type::get_state_type_no(int part) const
66 : {
67 27696 : return this->state_type_no.at(part);
68 : }
69 :
70 0 : std::string lts_type::get_state_type_name(int type_no) const
71 : {
72 0 : return this->state_type_list.at(type_no);
73 : }
74 :
75 76 : const std::vector<std::string>& lts_type::get_state_names() const
76 : {
77 76 : return state_names;
78 : }
79 :
80 :
81 0 : const std::vector<std::string>& lts_type::get_state_types() const
82 : {
83 0 : return state_types;
84 : }
85 :
86 :
87 0 : std::size_t lts_type::get_number_of_state_labels() const
88 : {
89 0 : return this->state_label_names.size();
90 : }
91 :
92 :
93 0 : const std::vector<std::string>& lts_type::get_state_labels() const
94 : {
95 0 : return state_label_names;
96 : }
97 :
98 :
99 0 : const std::vector<std::string>& lts_type::get_state_label_types() const
100 : {
101 0 : return state_label_types;
102 : }
103 :
104 :
105 0 : std::size_t lts_type::get_number_of_edge_labels() const
106 : {
107 0 : return this->edge_label_names.size();
108 : }
109 :
110 :
111 0 : const std::vector<std::string>& lts_type::get_edge_labels() const
112 : {
113 0 : return edge_label_names;
114 : }
115 :
116 :
117 0 : const std::vector<std::string>& lts_type::get_edge_label_types() const
118 : {
119 0 : return edge_label_types;
120 : }
121 :
122 :
123 20 : void lts_type::add_state(const std::string& name, const std::string& type)
124 : {
125 : //std::clog << "Adding state part " << this->state_names->size() << ": "
126 : // << info::get_param_signature(name, type)
127 : // << std::endl;
128 20 : this->state_names.push_back(name);
129 20 : this->state_types.push_back(type);
130 : std::size_t type_index;
131 20 : std::map<std::string,int>::iterator type_index_it = this->state_type_index.find(type);
132 20 : if (type_index_it != this->state_type_index.end()) {
133 8 : type_index = type_index_it->second;
134 : } else {
135 12 : this->state_type_list.push_back(type);
136 12 : type_index = this->state_type_list.size() - 1;
137 12 : this->state_type_index[type] = type_index;
138 : }
139 20 : this->state_type_no.push_back(type_index);
140 : //std::clog << " type_no = " << type_index << ": " << this->state_type_list->at(type_index) << std::endl;
141 20 : }
142 :
143 :
144 12 : void lts_type::add_state_label(const std::string& name,
145 : const std::string& type)
146 : {
147 12 : this->state_label_names.push_back(name);
148 12 : this->state_label_types.push_back(type);
149 12 : }
150 :
151 :
152 0 : void lts_type::add_edge_label(const std::string& name,
153 : const std::string& type)
154 : {
155 0 : this->edge_label_names.push_back(name);
156 0 : this->edge_label_types.push_back(type);
157 0 : }
158 :
159 :
160 :
161 :
162 : /// lts_info
163 :
164 6 : lts_info::lts_info(pbes& p, detail::pbes_greybox_interface* pgg, bool reset = false, bool always_split = false):
165 6 : p(p),
166 6 : pgg(pgg),
167 6 : reset_option(reset),
168 6 : always_split_option(always_split),
169 6 : type(0)
170 : {
171 6 : if (!detail::is_ppg(p))
172 : {
173 0 : throw std::runtime_error("PBES is not a PPG! Please rewrite with pbesrewr -pppg.");
174 : }
175 : //std::clog << "info: resetOption = " << (this->resetOption ? "true":"false") << ", reset = " << reset << std::endl;
176 6 : compute_lts_type();
177 6 : compute_transition_groups();
178 6 : compute_dependency_matrix();
179 6 : }
180 :
181 :
182 6 : void lts_info::compute_lts_type()
183 : {
184 : //std::clog << "pbes_type:" << std::endl;
185 6 : mCRL2log(log::verbose) << "Compute LTS type." << std::endl;
186 6 : std::vector<std::string> params;
187 6 : std::map<std::string,std::string> paramtypes;
188 6 : data::representative_generator default_expression_generator(p.data());
189 :
190 20 : for (const auto& eqn : p.equations())
191 : {
192 : //std::clog << core::pp((*eqn).symbol()) << " " << (*eqn).variable().name()
193 : // << std::endl;
194 :
195 14 : propositional_variable var = eqn.variable();
196 48 : for (const variable& varparam: var.parameters())
197 : {
198 34 : std::string signature = get_param_signature(varparam);
199 34 : bool new_param = true;
200 98 : for (auto & param : params) {
201 64 : if (signature == param) new_param = false;
202 : }
203 34 : if (new_param) {
204 14 : params.push_back(signature);
205 14 : paramtypes[signature] = core::pp(varparam.sort());
206 : //std::clog << "paramtypes[" << signature << "] = " << paramtypes[signature] << std::endl;
207 14 : data_expression e(default_expression_generator(varparam.sort()));
208 14 : pbes_expression e1 = pgg->rewrite_and_simplify_expression(e,false);
209 14 : this->param_default_values.push_back(atermpp::down_cast<const data::data_expression>(e1));
210 14 : }
211 34 : }
212 : //params.sort();
213 14 : }
214 6 : this->type = lts_type(1 + params.size());
215 6 : this->type.add_state("var", "string"); // Propositional variable name
216 :
217 6 : int i = 0;
218 20 : for (const std::string& signature: params) {
219 14 : this->type.add_state(signature, paramtypes[signature]);
220 14 : this->param_index[signature] = i;
221 14 : i++;
222 : }
223 :
224 6 : this->type.add_state_label("priority", "int");
225 6 : this->type.add_state_label("type", "int");
226 :
227 : //this->type->add_edge_label("", "");
228 : //std::clog << "-- end of pbes_type." << std::endl;
229 6 : mCRL2log(log::verbose) << "end of compute_lts_type." << std::endl;
230 6 : }
231 :
232 :
233 8 : inline bool lts_info::is_pass_through_state(const propositional_variable_instantiation& propvar)
234 : {
235 8 : std::string varname = std::string(propvar.name());
236 8 : data::variable_list params = this->variable_parameters[varname];
237 8 : const data::data_expression_list& values = propvar.parameters();
238 8 : if (params.size() != values.size())
239 : {
240 0 : return false;
241 : }
242 : else
243 : {
244 8 : data::variable_list::const_iterator param_it = params.begin();
245 32 : for(const auto & value : values)
246 : {
247 24 : if (!data::is_variable(value))
248 : {
249 0 : return false;
250 : }
251 : else
252 : {
253 24 : data::variable param(*param_it);
254 24 : data::variable param_expr(value);
255 24 : if (param != param_expr)
256 : {
257 0 : return false;
258 : }
259 24 : }
260 24 : if (param_it != params.end())
261 : {
262 24 : ++param_it;
263 : }
264 : }
265 : }
266 8 : if(params != values)
267 : {
268 0 : throw mcrl2::runtime_error("is_pass_through_state check failed on " + data::pp(params) + " " + data::pp(values));
269 : }
270 8 : return true;
271 8 : }
272 :
273 :
274 368 : inline int lts_info::count_variables(const pbes_expression& e)
275 : {
276 368 : if (is_propositional_variable_instantiation(e))
277 : {
278 72 : return 1;
279 : }
280 296 : else if (is_and(e) || is_or(e) || is_imp(e))
281 : {
282 156 : return count_variables(pbes_system::accessors::left(e)) + count_variables(pbes_system::accessors::right(e));
283 : }
284 140 : else if (is_forall(e) || is_exists(e))
285 : {
286 36 : if (count_variables(pbes_system::accessors::arg(e)) > 0)
287 : {
288 36 : return INT_MAX;
289 : }
290 : else
291 : {
292 0 : return 0;
293 : }
294 : }
295 104 : else if (is_not(e))
296 : {
297 0 : return count_variables(pbes_system::accessors::arg(e));
298 : }
299 104 : else if (is_data(e))
300 : {
301 104 : return 0;
302 : }
303 : else
304 : {
305 0 : throw(std::runtime_error("Unexpected expression: " + pbes_system::pp(e)));
306 : }
307 : }
308 :
309 28 : std::vector<pbes_expression> lts_info::split_expression_and_substitute_variables(const pbes_expression& e, int current_priority, operation_type current_type, std::set<std::string> vars_stack)
310 : {
311 28 : std::vector<pbes_expression> result;
312 28 : std::vector<pbes_expression> parts;
313 28 : if (is_simple_expression(e))
314 : {
315 0 : result.push_back(e);
316 : }
317 28 : else if (!is_propositional_variable_instantiation(e) && count_variables(e) <= 1 && !always_split_option)
318 : {
319 20 : result.push_back(e);
320 : }
321 8 : else if (is_and(e)) {
322 0 : parts = split_conjuncts(e, true);
323 8 : } else if (is_or(e)) {
324 0 : parts = split_disjuncts(e, true);
325 : } else {
326 8 : parts.push_back(e);
327 : }
328 :
329 28 : bool pass_through = true;
330 :
331 36 : for(std::vector<pbes_expression>::iterator p_it = parts.begin(); pass_through && p_it != parts.end(); ++p_it)
332 : {
333 8 : pbes_expression part = *p_it;
334 8 : if (is_propositional_variable_instantiation(part))
335 : {
336 : // Try to substitute the variable instantiation with the associated expression
337 :
338 8 : propositional_variable_instantiation propvar = (propositional_variable_instantiation)part;
339 8 : if (is_pass_through_state(propvar))
340 : {
341 : // The variable instantiation only copies the current parameters and local data variables,
342 : // so substitution is safe with respect to that.
343 :
344 8 : std::string varname = std::string(propvar.name());
345 8 : int priority = this->variable_priority[varname];
346 8 : operation_type type = this->variable_type[varname];
347 8 : pbes_expression expr = this->variable_expression[varname];
348 :
349 0 : if ((priority == current_priority) &&
350 8 : (current_type == type || is_simple_expression(expr) || count_variables(expr) <= 1) &&
351 8 : vars_stack.find(varname) == vars_stack.end())
352 : {
353 : // The associated equation has the same priority and operation type as the current equation,
354 : // so substitution is safe.
355 :
356 : //std::clog << " Substituting variable instantiation: " << pbes_system::pp(part) << std::endl
357 : // << " with: " << pbes_system::pp(expr) << std::endl;
358 :
359 : // Recursively try to further substitute variables:
360 : // (vars_stack is used to prevent infinite recursion)
361 0 : std::set<std::string> new_vars_stack(vars_stack.begin(), vars_stack.end());
362 0 : new_vars_stack.insert(varname);
363 0 : std::vector<pbes_expression> part_result = split_expression_and_substitute_variables(expr, current_priority, current_type, new_vars_stack);
364 0 : result.insert(result.end(), part_result.begin(), part_result.end());
365 0 : }
366 : else
367 : {
368 8 : result.push_back(part);
369 : }
370 8 : }
371 : else
372 : {
373 0 : pass_through = false;
374 : }
375 8 : }
376 : else
377 : {
378 0 : pass_through = false;
379 : }
380 8 : }
381 28 : if (!pass_through)
382 : {
383 0 : if (always_split_option && !parts.empty())
384 : {
385 : // the old behaviour of the explorer: always split conjunctions and disjunctions
386 : // into subexpressions that form groups
387 0 : result = parts;
388 : }
389 : else
390 : {
391 : // the new behaviour: only split expressions if every part is a pass-through variable instantiation,
392 : // i.e., all values are copied and not changed.
393 0 : result.clear();
394 0 : result.push_back(e);
395 : }
396 : }
397 56 : return result;
398 28 : }
399 :
400 :
401 6 : void lts_info::compute_transition_groups()
402 : {
403 6 : mCRL2log(log::verbose) << "Compute transition groups." << std::endl;
404 :
405 6 : int group = 0;
406 6 : int priority = 0;
407 6 : operation_type type = parity_game_generator::PGAME_AND;
408 6 : fixpoint_symbol symbol = fixpoint_symbol::nu();
409 6 : detail::ppg_visitor checker;
410 :
411 6 : std::string name = "true";
412 12 : propositional_variable t{core::identifier_string(name), data::variable_list()};
413 6 : this->variables[name] = t;
414 6 : this->variable_type[name] = type;
415 6 : this->variable_symbol[name] = symbol;
416 6 : this->variable_priority[name] = priority;
417 6 : this->variable_parameters[name] = t.parameters();
418 6 : this->variable_parameter_signatures[name] = get_param_sequence(t.parameters());
419 6 : this->variable_parameter_indices[name] = this->get_param_indices(t.parameters());
420 6 : this->variable_parameter_index_positions[name] = this->get_param_index_positions(t.parameters());
421 6 : this->transition_expression_plain.push_back(true_());
422 6 : this->transition_expression.push_back(pgg->rewrite_and_simplify_expression(true_()));
423 6 : this->transition_variable_name.push_back(name);
424 6 : this->transition_type.push_back(type);
425 6 : group++;
426 6 : priority++;
427 :
428 6 : name = "false";
429 6 : type = parity_game_generator::PGAME_OR;
430 6 : symbol = fixpoint_symbol::mu();
431 12 : propositional_variable f{core::identifier_string(name), data::variable_list()};
432 6 : this->variables[name] = f;
433 6 : this->variable_type[name] = type;
434 6 : this->variable_symbol[name] = symbol;
435 6 : this->variable_priority[name] = priority;
436 6 : this->variable_parameters[name] = f.parameters();
437 6 : this->variable_parameter_signatures[name] = get_param_sequence(f.parameters());
438 6 : this->variable_parameter_indices[name] = this->get_param_indices(f.parameters());
439 6 : this->variable_parameter_index_positions[name] = this->get_param_index_positions(f.parameters());
440 6 : this->transition_expression_plain.push_back(false_());
441 6 : this->transition_expression.push_back(pgg->rewrite_and_simplify_expression(false_()));
442 6 : this->transition_variable_name.push_back(name);
443 6 : this->transition_type.push_back(type);
444 6 : group++;
445 6 : priority++;
446 :
447 6 : symbol = fixpoint_symbol::nu();
448 :
449 20 : for (auto & eqn : p.equations()) {
450 14 : pbes_expression expr = pgg->get_pbes_equation(eqn.variable().name()).formula();
451 14 : std::string variable_name = eqn.variable().name();
452 14 : this->variables[variable_name] = eqn.variable();
453 14 : type = pgg->get_expression_operation(expr);
454 14 : this->variable_type[variable_name] = type;
455 14 : this->variable_symbol[variable_name] = eqn.symbol();
456 14 : if (eqn.symbol() != symbol) {
457 4 : priority++;
458 4 : symbol = eqn.symbol();
459 : }
460 14 : mCRL2log(log::debug) << "Adding var " << variable_name << ", priority=" << priority << ", symbol=" << symbol << std::endl;
461 14 : this->variable_priority[variable_name] = priority;
462 14 : this->variable_parameters[variable_name] = eqn.variable().parameters();
463 14 : this->variable_parameter_signatures[variable_name] = get_param_sequence(eqn.variable().parameters());
464 14 : this->variable_parameter_indices[variable_name] = this->get_param_indices(eqn.variable().parameters());
465 14 : this->variable_parameter_index_positions[variable_name] = this->get_param_index_positions(eqn.variable().parameters());
466 14 : this->variable_expression[variable_name] = expr;
467 14 : }
468 :
469 : // Skip 'unused' equations....
470 6 : std::set<std::string> variable_set;
471 : {
472 6 : propositional_variable_instantiation init = p.initial_state();
473 6 : std::queue<std::string> variable_queue;
474 6 : variable_queue.push(init.name());
475 6 : variable_set.insert(init.name());
476 20 : while (!variable_queue.empty())
477 : {
478 14 : std::string var = variable_queue.front();
479 14 : variable_queue.pop();
480 14 : type = this->variable_type[var];
481 14 : priority = this->variable_priority[var];
482 14 : pbes_expression expr = this->variable_expression[var];
483 14 : std::set<std::string> vars_stack;
484 14 : std::vector<pbes_expression> expression_parts = split_expression_and_substitute_variables(expr, priority, type, vars_stack);
485 14 : for (std::vector<pbes_expression>::const_iterator e =
486 28 : expression_parts.begin(); e != expression_parts.end(); ++e) {
487 14 : std::set<std::string> occ_vars = lts_info::occ(*e);
488 40 : for (const auto & var_str : variable_set)
489 : {
490 26 : occ_vars.erase(var_str);
491 : }
492 22 : for(const auto & occ_var : occ_vars)
493 : {
494 8 : variable_queue.push(occ_var);
495 : }
496 14 : variable_set.insert(occ_vars.begin(), occ_vars.end());
497 14 : }
498 14 : }
499 6 : mCRL2log(log::debug) << "Set of 'used' variables: " << std::endl;
500 20 : for (const auto & var_str : variable_set)
501 : {
502 14 : mCRL2log(log::debug) << " " << var_str << std::endl;
503 : }
504 6 : mCRL2log(log::debug) << std::endl;
505 6 : }
506 :
507 20 : for (auto & eqn : p.equations()) {
508 14 : std::string variable_name = eqn.variable().name();
509 14 : if (variable_set.find(variable_name) != variable_set.end())
510 : {
511 14 : type = this->variable_type[variable_name];
512 14 : priority = this->variable_priority[variable_name];
513 14 : pbes_expression expr = this->variable_expression[variable_name];
514 14 : std::set<std::string> vars_stack;
515 14 : mCRL2log(log::debug) << std::endl << "Generating groups for equation " << variable_name << std::endl;
516 14 : std::vector<pbes_expression> expression_parts = split_expression_and_substitute_variables(expr, priority, type, vars_stack);
517 14 : for (std::vector<pbes_expression>::const_iterator e =
518 28 : expression_parts.begin(); e != expression_parts.end(); ++e) {
519 14 : this->transition_expression_plain.push_back(*e);
520 14 : this->transition_expression.push_back(pgg->rewrite_and_simplify_expression(*e));
521 14 : this->transition_variable_name.push_back(variable_name);
522 14 : this->transition_type.push_back(type);
523 28 : mCRL2log(log::debug) << "Add transition group " << group << ": "
524 14 : << (type==parity_game_generator::PGAME_AND ? "AND" : "OR") << " " << variable_name << " "
525 14 : << pbes_system::pp(*e) << std::endl;
526 14 : group++;
527 : }
528 14 : }
529 14 : }
530 6 : number_of_groups = group;
531 : //std::clog << "Added " << group << " transition groups." << std::endl;
532 6 : mCRL2log(log::debug) << "end of compute_transition_groups." << std::endl;
533 6 : }
534 :
535 :
536 6 : void lts_info::compute_dependency_matrix()
537 : {
538 6 : mCRL2log(log::verbose) << "Compute dependency matrix." << std::endl;
539 32 : for(int group=0; group < number_of_groups; group++)
540 : {
541 26 : std::vector<bool> dep_row;
542 26 : std::vector<bool> read_row;
543 26 : std::vector<bool> write_row;
544 26 : bool r = is_read_dependent_propvar(group);
545 26 : bool w = is_write_dependent_propvar(group);
546 26 : bool d = r || w;
547 26 : dep_row.push_back(d);
548 26 : read_row.push_back(r);
549 26 : write_row.push_back(w);
550 92 : for (int part = 1; part < type.get_state_length(); part++)
551 : {
552 66 : r = is_read_dependent_parameter(group, part);
553 66 : w = is_write_dependent_parameter(group, part);
554 66 : d = r || w;
555 66 : dep_row.push_back(d);
556 66 : read_row.push_back(r);
557 66 : write_row.push_back(w);
558 : }
559 26 : matrix[group] = dep_row;
560 26 : read_matrix[group] = read_row;
561 26 : write_matrix[group] = write_row;
562 26 : }
563 6 : mCRL2log(log::verbose) << "end of compute_dependency_matrix." << std::endl;
564 6 : }
565 :
566 :
567 3366 : bool lts_info::get_reset_option() const
568 : {
569 3366 : return reset_option;
570 : }
571 :
572 :
573 6 : int lts_info::get_number_of_groups() const
574 : {
575 6 : return number_of_groups;
576 : }
577 :
578 :
579 866 : const std::vector<pbes_expression>& lts_info::get_transition_expressions() const
580 : {
581 866 : return transition_expression;
582 : }
583 :
584 :
585 5168 : const std::vector<std::string>& lts_info::get_transition_variable_names() const
586 : {
587 5168 : return transition_variable_name;
588 : }
589 :
590 :
591 0 : const std::vector<lts_info::operation_type>& lts_info::get_transition_types() const
592 : {
593 0 : return transition_type;
594 : }
595 :
596 :
597 0 : const std::map<std::string, propositional_variable>& lts_info::get_variables() const
598 : {
599 0 : return variables;
600 : }
601 :
602 :
603 1732 : const std::map<std::string, lts_info::operation_type>& lts_info::get_variable_types() const
604 : {
605 1732 : return variable_type;
606 : }
607 :
608 0 : const std::map<std::string, fixpoint_symbol>& lts_info::get_variable_symbols() const
609 : {
610 0 : return variable_symbol;
611 : }
612 :
613 :
614 0 : const std::map<std::string, int>& lts_info::get_variable_priorities() const
615 : {
616 0 : return variable_priority;
617 : }
618 :
619 :
620 0 : const std::map<std::string, data::variable_list>& lts_info::get_variable_parameters() const
621 : {
622 0 : return variable_parameters;
623 : }
624 :
625 :
626 3366 : const std::map<std::string, std::vector<std::string> >& lts_info::get_variable_parameter_signatures() const
627 : {
628 3366 : return variable_parameter_signatures;
629 : }
630 :
631 :
632 5098 : const std::map<std::string, std::vector<int> >& lts_info::get_variable_parameter_indices() const
633 : {
634 5098 : return variable_parameter_indices;
635 : }
636 :
637 :
638 9168 : const std::map<std::string, std::map<int,int> >& lts_info::get_variable_parameter_index_positions() const
639 : {
640 9168 : return variable_parameter_index_positions;
641 : }
642 :
643 :
644 41352 : const lts_type& lts_info::get_lts_type() const
645 : {
646 41352 : return type;
647 : }
648 :
649 :
650 6 : const std::map<int,std::vector<bool> >& lts_info::get_dependency_matrix() const
651 : {
652 6 : return matrix;
653 : }
654 :
655 :
656 6 : const std::map<int,std::vector<bool> >& lts_info::get_read_matrix() const
657 : {
658 6 : return read_matrix;
659 : }
660 :
661 :
662 6 : const std::map<int,std::vector<bool> >& lts_info::get_write_matrix() const
663 : {
664 6 : return write_matrix;
665 : }
666 :
667 :
668 68 : int lts_info::get_index(const std::string& signature)
669 : {
670 68 : return param_index[signature];
671 : }
672 :
673 :
674 14 : const data_expression& lts_info::get_default_value(int index)
675 : {
676 14 : return param_default_values.at(index);
677 : }
678 :
679 :
680 26 : bool lts_info::is_read_dependent_propvar(int /* group */)
681 : {
682 26 : return true;
683 : }
684 :
685 :
686 66 : bool lts_info::is_read_dependent_parameter(int group, int part)
687 : {
688 66 : if (group==0 || group==1) return false;
689 38 : std::string p = type.get_state_names()[part];
690 38 : mCRL2log(log::debug) << "is_read_dependent_parameter (group=" << group << ", part=" << part << " [" << p << "]" << std::endl;
691 38 : pbes_expression phi = transition_expression_plain[group];
692 38 : std::string X = transition_variable_name[group];
693 38 : std::set<std::string> params = lts_info::get_param_set(variable_parameters[X]);
694 38 : if (params.find(p) == params.end())
695 : {
696 4 : return false; // Parameter is not in params(X).
697 : }
698 : else
699 : {
700 34 : std::set<std::string> usedSet = used(phi);
701 34 : std::set<std::string> changedSet = changed(phi);
702 34 : std::set<std::string> copySet = copied(phi);
703 34 : std::set<std::string> changedAndCopied;
704 34 : std::set_intersection(changedSet.begin(), changedSet.end(), copySet.begin(), copySet.end(),
705 : std::inserter(changedAndCopied, changedAndCopied.end()));
706 :
707 34 : if (usedSet.find(p) == usedSet.end() && changedAndCopied.find(p) == changedAndCopied.end())
708 : {
709 : // Parameter is not in used(phi) and not in (changed(phi) /\ copied(phi)).
710 12 : return false; // Parameter is not in used(phi).
711 : }
712 : else
713 : {
714 22 : return true; // Parameter is both in used(phi) and in params(X).
715 : }
716 34 : }
717 :
718 38 : }
719 :
720 :
721 26 : bool lts_info::is_write_dependent_propvar(int group)
722 : {
723 26 : if (group==0 || group==1) return false;
724 14 : pbes_expression phi = transition_expression_plain[group];
725 14 : std::string X = transition_variable_name[group];
726 14 : if (lts_info::tf(phi))
727 : {
728 10 : return true;
729 : }
730 4 : std::set<std::string> occ = lts_info::occ(phi);
731 4 : if (occ.empty())
732 : {
733 0 : return false; // Not dependent if occ(phi) == {}.
734 : }
735 4 : else if (occ.size() == 1)
736 : {
737 4 : bool containsX = occ.find(X) != occ.end();
738 4 : return !containsX; // Not dependent if occ(phi) == {X}.
739 : }
740 : else
741 : {
742 0 : return true; // Dependent, because occ(phi) contains multiple elements.
743 : }
744 14 : }
745 :
746 :
747 66 : bool lts_info::is_write_dependent_parameter(int group , int part)
748 : {
749 66 : if (group==0 || group==1) return false;
750 38 : std::string p = type.get_state_names().at(part);
751 38 : pbes_expression phi = transition_expression_plain[group];
752 38 : std::string X = transition_variable_name[group];
753 38 : if (this->reset_option) {
754 0 : if (lts_info::tf(phi))
755 : {
756 : // phi may have boolean result (not only propositional variable instantiations)
757 0 : return true;
758 : }
759 0 : std::set<std::string> params = lts_info::get_param_set(variable_parameters[X]);
760 0 : std::set<std::string> resetSet = reset(phi, params);
761 0 : if (resetSet.find(p) != resetSet.end())
762 : {
763 0 : return true; // Dependent, because p in reset(phi, params(X)).
764 : }
765 0 : }
766 38 : std::set<std::string> changedSet = changed(phi);
767 38 : bool changedSetContainsP = (changedSet.find(p) != changedSet.end());
768 38 : return changedSetContainsP; // Dependent, because p in changed(phi, {}).
769 38 : }
770 :
771 :
772 72 : std::set<std::string> lts_info::changed(const pbes_expression& phi)
773 : {
774 72 : std::set<std::string> empty;
775 144 : return changed(phi, empty);
776 72 : }
777 :
778 :
779 952 : std::set<std::string> lts_info::changed(const pbes_expression& phi, const std::set<std::string>& L)
780 : {
781 952 : std::set<std::string> result;
782 952 : if (is_not(phi))
783 : {
784 0 : result = changed(pbes_system::accessors::arg(phi), L);
785 : }
786 952 : else if (is_and(phi) || is_or(phi) || is_imp(phi))
787 : {
788 396 : std::set<std::string> l = changed(pbes_system::accessors::left(phi), L);
789 396 : result.insert(l.begin(), l.end());
790 396 : std::set<std::string> r = changed(pbes_system::accessors::right(phi), L);
791 396 : result.insert(r.begin(), r.end());
792 396 : }
793 556 : else if (is_forall(phi) || is_exists(phi))
794 : {
795 88 : std::set<std::string> LL;
796 88 : LL.insert(L.begin(), L.end());
797 88 : data::variable_list vars = quantifier_variables(phi);
798 176 : for (auto variable : vars)
799 : {
800 88 : LL.insert(get_param_signature(variable));
801 88 : }
802 88 : result = changed(pbes_system::accessors::arg(phi), LL);
803 88 : }
804 468 : else if (is_propositional_variable_instantiation(phi))
805 : {
806 : std::vector<std::string> var_param_signatures =
807 208 : variable_parameter_signatures[atermpp::down_cast<propositional_variable_instantiation>(phi).name()];
808 208 : data::data_expression_list values = atermpp::down_cast<propositional_variable_instantiation>(phi).parameters();
809 208 : assert(var_param_signatures.size() == values.size());
810 208 : data::data_expression_list::const_iterator val = values.begin();
811 208 : for (std::vector<std::string>::const_iterator param =
812 756 : var_param_signatures.begin(); param != var_param_signatures.end(); ++param) {
813 548 : std::string param_signature = *param;
814 548 : if (data::is_variable(*val))
815 : {
816 320 : const variable& value = atermpp::down_cast<variable>(*val);
817 320 : std::string value_signature = get_param_signature(value);
818 320 : if (param_signature != value_signature || L.find(value_signature) != L.end())
819 : {
820 20 : result.insert(param_signature);
821 : }
822 320 : }
823 : else
824 : {
825 228 : result.insert(param_signature);
826 : }
827 548 : if (val != values.end()) {
828 548 : ++val;
829 : }
830 548 : }
831 208 : }
832 952 : return result;
833 0 : }
834 :
835 :
836 0 : std::set<std::string> lts_info::reset(const pbes_expression& phi, const std::set<std::string>& d)
837 : {
838 0 : std::set<std::string> result;
839 0 : if (is_not(phi))
840 : {
841 0 : result = reset(pbes_system::accessors::arg(phi), d);
842 : }
843 0 : else if (is_and(phi) || is_or(phi) || is_imp(phi))
844 : {
845 0 : std::set<std::string> l = reset(pbes_system::accessors::left(phi), d);
846 0 : result.insert(l.begin(), l.end());
847 0 : std::set<std::string> r = reset(pbes_system::accessors::right(phi), d);
848 0 : result.insert(r.begin(), r.end());
849 0 : }
850 0 : else if (is_forall(phi) || is_exists(phi))
851 : {
852 0 : result = reset(pbes_system::accessors::arg(phi), d);
853 : }
854 0 : else if (is_propositional_variable_instantiation(phi))
855 : {
856 0 : std::set<std::string> params;
857 : std::vector<std::string> var_params =
858 0 : variable_parameter_signatures[atermpp::down_cast<propositional_variable_instantiation>(phi).name()];
859 0 : for (std::vector<std::string>::const_iterator param =
860 0 : var_params.begin(); param != var_params.end(); ++param) {
861 0 : std::string signature = *param;
862 0 : params.insert(signature);
863 0 : }
864 0 : for (auto signature : d) {
865 0 : if (params.find(signature) == params.end())
866 : {
867 0 : result.insert(signature);
868 : }
869 0 : }
870 0 : }
871 0 : return result;
872 0 : }
873 :
874 :
875 42 : bool lts_info::tf(const pbes_expression& phi)
876 : {
877 42 : if (is_not(phi))
878 : {
879 0 : return tf(pbes_system::accessors::arg(phi));
880 : }
881 42 : else if (is_and(phi) || is_or(phi) || is_imp(phi))
882 : {
883 20 : return tf(pbes_system::accessors::left(phi)) || tf(pbes_system::accessors::right(phi));
884 : }
885 22 : else if (is_forall(phi) || is_exists(phi))
886 : {
887 8 : return tf(pbes_system::accessors::arg(phi));
888 : }
889 14 : else if (is_propositional_variable_instantiation(phi))
890 : {
891 4 : return false;
892 : }
893 10 : return true;
894 : }
895 :
896 :
897 192 : std::set<std::string> lts_info::occ(const pbes_expression& expr)
898 : {
899 192 : std::set<std::string> result;
900 192 : if (is_propositional_variable_instantiation(expr))
901 : {
902 44 : result.insert(atermpp::down_cast<propositional_variable_instantiation>(expr).name());
903 : }
904 148 : else if (is_and(expr) || is_or(expr) ||is_imp(expr))
905 : {
906 78 : std::set<std::string> l = occ(pbes_system::accessors::left(expr));
907 78 : result.insert(l.begin(), l.end());
908 78 : std::set<std::string> r = occ(pbes_system::accessors::right(expr));
909 78 : result.insert(r.begin(), r.end());
910 78 : }
911 70 : else if (is_forall(expr) || is_exists(expr) || is_not(expr))
912 : {
913 18 : result = occ(pbes_system::accessors::arg(expr));
914 : }
915 192 : return result;
916 0 : }
917 :
918 :
919 224 : std::set<std::string> lts_info::free(const pbes_expression& expr)
920 : {
921 224 : std::set<std::string> result;
922 550 : for (const data::variable& var: pbes_system::find_free_variables(expr))
923 : {
924 326 : result.insert(get_param_signature(var));
925 224 : }
926 224 : return result;
927 0 : }
928 :
929 :
930 34 : std::set<std::string> lts_info::used(const pbes_expression& expr)
931 : {
932 34 : std::set<std::string> emptySet;
933 68 : return used(expr, emptySet);
934 34 : }
935 :
936 :
937 540 : std::set<std::string> lts_info::used(const pbes_expression& expr, const std::set<std::string>& L)
938 : {
939 : //std::clog << "lts_info::used(" << bqnf_visitor<equation_type, term_type>::print_brief(expr) << ", L)" << std::endl;
940 540 : std::set<std::string> result;
941 540 : if (is_data(expr))
942 : {
943 224 : std::set<std::string> fv = free(expr);
944 224 : result.insert(fv.begin(), fv.end());
945 224 : }
946 540 : if (is_propositional_variable_instantiation(expr))
947 : {
948 : data::variable_list var_params =
949 96 : variable_parameters[atermpp::down_cast<propositional_variable_instantiation>(expr).name()];
950 96 : data::data_expression_list values = atermpp::down_cast<propositional_variable_instantiation>(expr).parameters();
951 96 : assert(var_params.size() == values.size());
952 96 : data::data_expression_list::const_iterator val = values.begin();
953 352 : for (auto parameter : var_params) {
954 256 : std::string param_signature = get_param_signature(parameter);
955 256 : if (data::is_variable(*val))
956 : {
957 152 : const variable& value = atermpp::down_cast<variable>(*val);
958 152 : std::string value_signature = get_param_signature(value);
959 152 : if (param_signature != value_signature || L.find(value_signature) != L.end())
960 : {
961 8 : result.insert(value_signature);
962 : }
963 152 : }
964 : else
965 : {
966 : // add free variables in data expression
967 104 : std::set<std::string> l = used(*val, L);
968 104 : result.insert(l.begin(), l.end());
969 104 : }
970 256 : if (val != values.end()) {
971 256 : ++val;
972 : }
973 256 : }
974 96 : }
975 444 : else if (is_and(expr) || is_or(expr) || is_imp(expr))
976 : {
977 182 : std::set<std::string> l = used(pbes_system::accessors::left(expr), L);
978 182 : result.insert(l.begin(), l.end());
979 182 : std::set<std::string> r = used(pbes_system::accessors::right(expr), L);
980 182 : result.insert(r.begin(), r.end());
981 182 : }
982 262 : else if (is_not(expr))
983 : {
984 0 : result = used(pbes_system::accessors::arg(expr), L);
985 : }
986 262 : else if (is_forall(expr) || is_exists(expr))
987 : {
988 38 : std::set<std::string> LL;
989 38 : LL.insert(L.begin(), L.end());
990 38 : data::variable_list vars = quantifier_variables(expr);
991 76 : for (auto variable : vars)
992 : {
993 38 : LL.insert(get_param_signature(variable));
994 38 : }
995 38 : result = used(pbes_system::accessors::arg(expr), LL);
996 38 : }
997 540 : return result;
998 0 : }
999 :
1000 :
1001 34 : std::set<std::string> lts_info::copied(const pbes_expression& expr)
1002 : {
1003 34 : std::set<std::string> emptySet;
1004 68 : return copied(expr, emptySet);
1005 34 : }
1006 :
1007 :
1008 436 : std::set<std::string> lts_info::copied(const pbes_expression& expr, const std::set<std::string>& L)
1009 : {
1010 : //std::clog << "lts_info::copied(" << bqnf_visitor<equation_type, term_type>::print_brief(expr) << ", L)" << std::endl;
1011 436 : std::set<std::string> result;
1012 436 : if (is_data(expr))
1013 : {
1014 : // skip
1015 : }
1016 436 : if (is_propositional_variable_instantiation(expr))
1017 : {
1018 : data::variable_list var_params =
1019 96 : variable_parameters[atermpp::down_cast<propositional_variable_instantiation>(expr).name()];
1020 96 : data::data_expression_list values = atermpp::down_cast<propositional_variable_instantiation>(expr).parameters();
1021 96 : assert(var_params.size() == values.size());
1022 96 : data::data_expression_list::const_iterator val = values.begin();
1023 352 : for (auto parameter : var_params) {
1024 256 : std::string param_signature = get_param_signature(parameter);
1025 256 : if (data::is_variable(*val))
1026 : {
1027 152 : const variable& value = atermpp::down_cast<variable>(*val);
1028 152 : std::string value_signature = get_param_signature(value);
1029 152 : if (param_signature == value_signature && L.find(value_signature) == L.end())
1030 : {
1031 144 : result.insert(value_signature);
1032 : }
1033 152 : }
1034 256 : if (val != values.end()) {
1035 256 : ++val;
1036 : }
1037 256 : }
1038 96 : }
1039 340 : else if (is_and(expr) || is_or(expr) || is_imp(expr))
1040 : {
1041 182 : std::set<std::string> l = copied(pbes_system::accessors::left(expr), L);
1042 182 : result.insert(l.begin(), l.end());
1043 182 : std::set<std::string> r = copied(pbes_system::accessors::right(expr), L);
1044 182 : result.insert(r.begin(), r.end());
1045 182 : }
1046 158 : else if (is_not(expr))
1047 : {
1048 0 : result = copied(pbes_system::accessors::arg(expr), L);
1049 : }
1050 158 : else if (is_forall(expr) || is_exists(expr))
1051 : {
1052 38 : std::set<std::string> LL;
1053 38 : LL.insert(L.begin(), L.end());
1054 38 : data::variable_list vars = quantifier_variables(expr);
1055 76 : for (auto variable : vars)
1056 : {
1057 38 : LL.insert(get_param_signature(variable));
1058 38 : }
1059 38 : result = copied(pbes_system::accessors::arg(expr), LL);
1060 38 : }
1061 436 : return result;
1062 0 : }
1063 :
1064 :
1065 0 : std::string lts_info::state_to_string(const ltsmin_state& state)
1066 : {
1067 : //std::clog << "info::to_string" << std::endl;
1068 0 : std::string result;
1069 0 : std::stringstream ss;
1070 0 : operation_type type = detail::map_at(get_variable_types(), state.get_variable());
1071 0 : ss << (type==parity_game_generator::PGAME_AND ? "AND" : "OR");
1072 0 : ss << ":" << state.get_variable();
1073 0 : ss << "(";
1074 0 : const std::vector<data_expression>& param_values = state.get_parameter_values();
1075 : std::vector<std::string> param_signatures =
1076 0 : this->variable_parameter_signatures[state.get_variable()];
1077 : std::vector<std::string>::const_iterator param_signature =
1078 0 : param_signatures.begin();
1079 0 : for (std::vector<data_expression>::const_iterator param_value =
1080 0 : param_values.begin(); param_value != param_values.end(); ++param_value) {
1081 0 : if (param_value != param_values.begin())
1082 0 : ss << ", ";
1083 0 : ss << *param_signature << " = ";
1084 0 : ss << *param_value;
1085 0 : if (param_signature != param_signatures.end())
1086 : {
1087 0 : ++param_signature;
1088 : }
1089 : }
1090 0 : ss << ")";
1091 0 : result = ss.str();
1092 0 : return result;
1093 0 : }
1094 :
1095 :
1096 38 : std::set<std::string> lts_info::get_param_set(const data::variable_list& params)
1097 : {
1098 38 : std::set<std::string> result;
1099 136 : for (auto parameter : params) {
1100 98 : result.insert(get_param_signature(parameter));
1101 98 : }
1102 38 : return result;
1103 0 : }
1104 :
1105 :
1106 26 : std::vector<std::string> lts_info::get_param_sequence(const data::variable_list& params)
1107 : {
1108 26 : std::vector<std::string> result;
1109 60 : for (auto parameter : params) {
1110 34 : result.push_back(get_param_signature(parameter));
1111 34 : }
1112 26 : return result;
1113 0 : }
1114 :
1115 :
1116 26 : std::vector<int> lts_info::get_param_indices(const data::variable_list& params)
1117 : {
1118 26 : std::vector<int> result;
1119 60 : for (auto parameter : params) {
1120 34 : int index = this->get_index(get_param_signature(parameter));
1121 34 : result.push_back(index);
1122 34 : }
1123 26 : return result;
1124 0 : }
1125 :
1126 :
1127 26 : std::map<int,int> lts_info::get_param_index_positions(const data::variable_list& params)
1128 : {
1129 26 : std::map<int,int> result;
1130 26 : int i = 0;
1131 60 : for (auto parameter : params) {
1132 34 : int index = this->get_index(get_param_signature(parameter));
1133 34 : result.insert(std::make_pair(index,i));
1134 34 : i++;
1135 34 : }
1136 52 : return result;
1137 0 : }
1138 :
1139 :
1140 : std::map<variable,std::string> lts_info::variable_signatures;
1141 :
1142 :
1143 1860 : std::string lts_info::get_param_signature(const variable& param)
1144 : {
1145 1860 : std::map<variable,std::string>::const_iterator i = variable_signatures.find(param);
1146 1860 : if (i == variable_signatures.end())
1147 : {
1148 7 : std::string paramname = param.name();
1149 7 : std::string paramtype = core::pp(param.sort());
1150 7 : std::string signature = get_param_signature(paramname, paramtype);
1151 7 : variable_signatures[param] = signature;
1152 7 : return signature;
1153 7 : }
1154 1853 : return i->second;
1155 : }
1156 :
1157 :
1158 7 : std::string lts_info::get_param_signature(const std::string& paramname,
1159 : const std::string& paramtype)
1160 : {
1161 14 : return paramname + ":" + paramtype;
1162 : }
1163 :
1164 :
1165 :
1166 :
1167 : // ltsmin_state
1168 :
1169 6 : ltsmin_state::ltsmin_state(const std::string& varname)
1170 : {
1171 6 : this->var = varname;
1172 6 : }
1173 :
1174 :
1175 5098 : ltsmin_state::ltsmin_state(const std::string& varname,
1176 5098 : const pbes_expression& e)
1177 : {
1178 5098 : data_expression novalue;
1179 : //std::clog << "ltsmin_state v = " << pp(v) << std::endl;
1180 5098 : this->var = varname;
1181 5098 : if (is_propositional_variable_instantiation(e)) {
1182 5098 : assert(std::string(atermpp::down_cast<propositional_variable_instantiation>(e).name()) == varname);
1183 : //std::clog << "ltsmin_state: var = " << atermpp::down_cast<propositional_variable_instantiation>(e).name() << std::endl;
1184 5098 : const data::data_expression_list& values = atermpp::down_cast<propositional_variable_instantiation>(e).parameters();
1185 19024 : for (const auto & value : values)
1186 : {
1187 13926 : if (value == novalue)
1188 : {
1189 0 : throw(std::runtime_error("Error in ltsmin_state: state expression contains NoValue: "
1190 0 : + pp(e)));
1191 : }
1192 13926 : this->add_parameter_value(value);
1193 : //std::clog << "ltsmin_state: " << *val << std::endl;
1194 : }
1195 : //std::clog << std::endl;
1196 : } else {
1197 0 : throw(std::runtime_error("Not a valid state expression! " + pp(e)));
1198 : }
1199 5098 : }
1200 :
1201 0 : bool ltsmin_state::operator<( const ltsmin_state& other ) const
1202 : {
1203 0 : if (this->var < other.var) return true;
1204 0 : else if (this->var == other.var)
1205 : {
1206 0 : if (param_values.size() < other.param_values.size()) return true;
1207 0 : else if (param_values.size() == other.param_values.size())
1208 : {
1209 0 : if (param_values < other.param_values) return true;
1210 : }
1211 : }
1212 0 : return false;
1213 : }
1214 :
1215 :
1216 0 : bool ltsmin_state::operator==( const ltsmin_state& other ) const
1217 : {
1218 0 : return this->var==other.var
1219 0 : && param_values.size()==other.param_values.size()
1220 0 : && param_values == other.param_values;
1221 : }
1222 :
1223 :
1224 20224 : std::string ltsmin_state::get_variable() const
1225 : {
1226 20224 : return var;
1227 : }
1228 :
1229 :
1230 12198 : const std::vector<data_expression>& ltsmin_state::get_parameter_values() const
1231 : {
1232 12198 : return param_values;
1233 : }
1234 :
1235 :
1236 13926 : void ltsmin_state::add_parameter_value(const data_expression& value)
1237 : {
1238 13926 : param_values.push_back(value);
1239 13926 : }
1240 :
1241 :
1242 1732 : pbes_expression ltsmin_state::to_pbes_expression() const
1243 : {
1244 1732 : data::data_expression_vector parameter_values;
1245 6480 : for (const auto & param_value : param_values) {
1246 4748 : parameter_values.push_back(param_value);
1247 : }
1248 1732 : data::data_expression_list parameter_values_list(parameter_values.begin(), parameter_values.end());
1249 : // Create propositional variable instantiation.
1250 : propositional_variable_instantiation expr =
1251 1732 : propositional_variable_instantiation(core::identifier_string(var), parameter_values_list);
1252 3464 : return workaround::return_std_move(expr);
1253 1732 : }
1254 :
1255 :
1256 0 : std::string ltsmin_state::state_to_string() const
1257 : {
1258 0 : std::string result;
1259 0 : std::stringstream ss;
1260 0 : ss << (type==parity_game_generator::PGAME_AND ? "AND" : "OR");
1261 0 : ss << ":" << var;
1262 0 : ss << "[" << std::endl;
1263 0 : for (std::vector<data_expression>::const_iterator entry =
1264 0 : param_values.begin(); entry != param_values.end(); ++entry) {
1265 0 : if (entry != param_values.begin())
1266 0 : ss << std::endl << " value = ";
1267 0 : ss << *entry;
1268 : }
1269 0 : ss << "]";
1270 0 : result = ss.str();
1271 0 : return result;
1272 0 : }
1273 :
1274 :
1275 :
1276 :
1277 : /// explorer
1278 :
1279 2 : explorer::explorer(const std::string& filename, const std::string& rewrite_strategy = "jittyc", bool reset_flag = false, bool always_split_flag = false)
1280 : {
1281 2 : load_pbes(p, filename);
1282 8 : for (auto & eqn : p.equations()) {
1283 6 : std::string variable_name = eqn.variable().name();
1284 : //std::clog << "varname = " << variable_name << std::endl;
1285 6 : }
1286 2 : pbes_system::algorithms::normalize(p);
1287 2 : if (!detail::is_ppg(p))
1288 : {
1289 0 : mCRL2log(log::info) << "Rewriting to PPG..." << std::endl;
1290 0 : p = detail::to_ppg(p);
1291 0 : mCRL2log(log::info) << "Rewriting done." << std::endl;
1292 : }
1293 2 : this->pgg = new detail::pbes_greybox_interface(p, true, true, data::parse_rewrite_strategy(rewrite_strategy));
1294 2 : this->info = new lts_info(p, pgg, reset_flag, always_split_flag);
1295 : //std::clog << "explorer" << std::endl;
1296 6 : for (std::size_t i = 0; i < info->get_lts_type().get_number_of_state_types(); ++i) {
1297 4 : std::map<data_expression,int> data2int_map;
1298 4 : this->localmaps_data2int.push_back(data2int_map);
1299 4 : std::vector<data_expression> int2data_map;
1300 4 : this->localmaps_int2data.push_back(int2data_map);
1301 4 : }
1302 : //std::clog << "-- end of explorer." << std::endl;
1303 2 : }
1304 :
1305 :
1306 4 : explorer::explorer(const pbes& p_, const std::string& rewrite_strategy = "jittyc", bool reset_flag = false, bool always_split_flag = false)
1307 : {
1308 4 : p = p_;
1309 4 : this->pgg = new detail::pbes_greybox_interface(p, true, true, data::parse_rewrite_strategy(rewrite_strategy));
1310 4 : this->info = new lts_info(p, pgg, reset_flag, always_split_flag);
1311 : //std::clog << "explorer" << std::endl;
1312 12 : for (std::size_t i = 0; i < info->get_lts_type().get_number_of_state_types(); i++) {
1313 8 : std::map<data_expression,int> data2int_map;
1314 8 : this->localmaps_data2int.push_back(data2int_map);
1315 8 : std::vector<data_expression> int2data_map;
1316 8 : this->localmaps_int2data.push_back(int2data_map);
1317 8 : }
1318 : //std::clog << "-- end of explorer." << std::endl;
1319 4 : }
1320 :
1321 :
1322 6 : explorer::~explorer()
1323 : {
1324 6 : delete info;
1325 6 : delete pgg;
1326 6 : }
1327 :
1328 :
1329 16742 : lts_info* explorer::get_info() const
1330 : {
1331 16742 : return info;
1332 : }
1333 :
1334 :
1335 6 : ltsmin_state explorer::get_initial_state() const
1336 : {
1337 6 : propositional_variable_instantiation initial_state = pgg->get_initial_state();
1338 12 : return this->get_state(initial_state);
1339 6 : }
1340 :
1341 :
1342 6 : void explorer::initial_state(int* state)
1343 : {
1344 6 : ltsmin_state initial_state = this->get_initial_state();
1345 12 : ltsmin_state dummy("dummy");
1346 6 : this->to_state_vector(initial_state, state, dummy, nullptr);
1347 6 : }
1348 :
1349 :
1350 5098 : ltsmin_state explorer::get_state(const propositional_variable_instantiation& expr) const
1351 : {
1352 : //std::clog << "-- get_state --" << std::endl;
1353 : //std::clog << " expr = " << expr << std::endl;
1354 5098 : propositional_variable_instantiation novalue;
1355 5098 : assert(is_propositional_variable_instantiation(expr) && expr != novalue);
1356 5098 : std::string varname = expr.name();
1357 : //std::clog << " varname = " << varname << std::endl;
1358 5098 : ltsmin_state s(varname, expr);
1359 10196 : return s;
1360 5098 : }
1361 :
1362 :
1363 0 : ltsmin_state explorer::true_state()
1364 : {
1365 0 : return ltsmin_state("true");
1366 : }
1367 :
1368 :
1369 0 : ltsmin_state explorer::false_state()
1370 : {
1371 0 : return ltsmin_state("false");
1372 : }
1373 :
1374 :
1375 9998 : data::data_expression explorer::string_to_data(const std::string& s)
1376 : {
1377 9998 : atermpp::aterm t = atermpp::read_term_from_string(s);
1378 19996 : return atermpp::down_cast<data::data_expression>(data::detail::add_index(static_cast<const atermpp::aterm_appl&>(t)));
1379 9998 : }
1380 :
1381 :
1382 13364 : int explorer::get_index(int type_no, const std::string& s)
1383 : {
1384 13364 : if (type_no==0)
1385 : {
1386 3366 : return get_string_index(s);
1387 : }
1388 : else
1389 : {
1390 9998 : data_expression value = this->string_to_data(s);
1391 9998 : return get_value_index(type_no, value);
1392 9998 : }
1393 : }
1394 :
1395 :
1396 4572 : int explorer::get_string_index(const std::string& s)
1397 : {
1398 4572 : std::map<std::string,int>::iterator it = this->localmap_string2int.find(s);
1399 : std::size_t index;
1400 4572 : if (it != this->localmap_string2int.end()) {
1401 4558 : index = it->second;
1402 : } else {
1403 14 : this->localmap_int2string.push_back(s);
1404 14 : index = this->localmap_int2string.size() - 1;
1405 : //std::clog << "[" << getpid() << "] get_string_index DEBUG push_back " << index << ": " << s << std::endl;
1406 14 : this->localmap_string2int.insert(std::make_pair(s,index));
1407 : }
1408 : //std::clog << "get_string_index result =" << index << " (" << this->localmap_int2string->size() << ")" << std::endl;
1409 4572 : return index;
1410 : }
1411 :
1412 :
1413 13622 : int explorer::get_value_index(int type_no, const data_expression& value)
1414 : {
1415 : //std::clog << " get_value_index type_no=" << type_no << " (" << info->get_lts_type().get_number_of_state_types() << ")" << std::endl;
1416 : //std::clog << " type=" << info->get_lts_type().get_state_type_name(type_no) << std::endl;
1417 : //std::clog << " value=" << value << std::endl;
1418 13622 : std::map<data_expression,int>& data2int_map = this->localmaps_data2int.at(type_no);
1419 13622 : std::map<data_expression,int>::iterator it = data2int_map.find(value);
1420 : std::size_t index;
1421 13622 : if (it != data2int_map.end()) {
1422 13572 : index = it->second;
1423 : } else {
1424 50 : this->localmaps_int2data.at(type_no).push_back(value);
1425 50 : index = this->localmaps_int2data.at(type_no).size() - 1;
1426 50 : data2int_map.insert(std::make_pair(value,index));
1427 : }
1428 13622 : return index;
1429 : }
1430 :
1431 :
1432 3366 : void explorer::to_state_vector(const ltsmin_state& dst_state, int* dst, const ltsmin_state& src_state, int* const& src)
1433 : {
1434 : //std::clog << "to_state_vector: " << dst_state.to_string() << std::endl;
1435 :
1436 3366 : data_expression novalue;
1437 : //std::clog << "-- to_state_vector -- " << std::endl;
1438 3366 : int state_length = info->get_lts_type().get_state_length();
1439 :
1440 3366 : std::string varname = dst_state.get_variable();
1441 3366 : std::string src_varname;
1442 3366 : bool same_var = false;
1443 3366 : if (!(src==nullptr)) {
1444 3360 : src_varname = src_state.get_variable();
1445 3360 : same_var = (varname==src_varname);
1446 : }
1447 : int varindex;
1448 3366 : if (same_var) {
1449 2160 : varindex = src[0];
1450 : } else {
1451 1206 : varindex = this->get_string_index(varname);
1452 : }
1453 3366 : dst[0] = varindex;
1454 : //std::clog << " to_state_vector: DEBUG: varname = " << varname << " index = " << varindex << (same_var ? " SAME VAR": "") << std::endl;
1455 :
1456 :
1457 : // data_expression values[state_length]; N.B. This is not portable C++
1458 3366 : std::vector < data_expression > values(state_length);
1459 :
1460 3366 : if (info->get_reset_option() || src == nullptr) {
1461 : int type_no;
1462 20 : for (int i = 1; i < state_length; i++) {
1463 14 : data_expression default_value = info->get_default_value(i-1);
1464 14 : values[i] = default_value;
1465 14 : type_no = info->get_lts_type().get_state_type_no(i);
1466 14 : dst[i] = this->get_value_index(type_no, values[i]);
1467 14 : }
1468 : } else {
1469 13344 : for (int i = 1; i < state_length; i++) {
1470 9984 : dst[i] = src[i];
1471 : }
1472 : }
1473 3366 : bool error = false;
1474 3366 : const std::vector<data_expression>& parameter_values = dst_state.get_parameter_values();
1475 : std::vector<int> parameter_indices =
1476 3366 : detail::map_at(info->get_variable_parameter_indices(), varname);
1477 : std::vector<std::string> parameter_signatures =
1478 3366 : detail::map_at(info->get_variable_parameter_signatures(), varname);
1479 3366 : std::vector<std::string>::iterator param_signature = parameter_signatures.begin();
1480 3366 : int value_index = 0;
1481 12544 : for(int & parameter_indice : parameter_indices)
1482 : {
1483 9178 : int i = parameter_indice + 1;
1484 9178 : int type_no = info->get_lts_type().get_state_type_no(i);
1485 9178 : values[i] = parameter_values[value_index];
1486 9178 : if (values[i]==novalue)
1487 : {
1488 0 : error = true;
1489 : } else {
1490 9178 : if (src==nullptr) {
1491 : // no source state available; compute index for value.
1492 10 : dst[i] = this->get_value_index(type_no, values[i]);
1493 : }
1494 : else
1495 : {
1496 : // lookup src parameter value
1497 : // FIXME: this could be computed statically: a map from src_var, dst_var and part to boolean
1498 9168 : std::map<int,int> src_param_index_positions = detail::map_at(info->get_variable_parameter_index_positions(), src_state.get_variable());
1499 9168 : std::map<int,int>::iterator src_param_index_position_it = src_param_index_positions.find(parameter_indice);
1500 9168 : if ( src_param_index_position_it != src_param_index_positions.end()
1501 9168 : && src_state.get_parameter_values()[src_param_index_position_it->second] == values[i])
1502 : {
1503 : // src value exists and is equal to the dst value.
1504 : // save to copy index from src_state
1505 : // which has been done earlier
1506 : } else {
1507 : // parameter value has changed or does not exists in src; compute index for value.
1508 3600 : dst[i] = this->get_value_index(type_no, values[i]);
1509 : }
1510 9168 : }
1511 : }
1512 9178 : if (param_signature != parameter_signatures.end())
1513 : {
1514 9178 : ++param_signature;
1515 : }
1516 9178 : value_index++;
1517 : }
1518 3366 : if (error)
1519 : {
1520 0 : throw(std::runtime_error("Error in to_state_vector: NoValue in parameters of dst_state: "
1521 0 : + info->state_to_string(dst_state) + "."));
1522 : }
1523 : //std::clog << "-- to_state_vector: done --" << std::endl;
1524 3366 : }
1525 :
1526 :
1527 13364 : std::string explorer::get_value(int type_no, int index)
1528 : {
1529 : //std::clog << "get_value type_no = " << type_no << " index = " << index << std::endl;
1530 13364 : if (type_no==0)
1531 : {
1532 3366 : return this->get_string_value(index);
1533 : }
1534 : else
1535 : {
1536 9998 : data_expression value = get_data_value(type_no, index);
1537 : //std::stringstream os;
1538 : //write_term_to_text_stream(value, os);
1539 : //std::string s = atermpp::pp(value);
1540 : //return os.str();
1541 9998 : atermpp::aterm t = data::detail::remove_index(value);
1542 9998 : return pp(t);
1543 9998 : }
1544 : }
1545 :
1546 :
1547 9400 : const std::string& explorer::get_string_value(int index)
1548 : {
1549 9400 : if (index >= (int)(localmap_int2string.size()))
1550 : {
1551 0 : throw(std::runtime_error("Error in get_string_value: Value not found for index " + std::to_string(index) + "."));
1552 : }
1553 9400 : return localmap_int2string.at(index);
1554 : }
1555 :
1556 :
1557 15138 : const data_expression& explorer::get_data_value(int type_no, int index)
1558 : {
1559 15138 : std::vector<data_expression>& int2data_map = this->localmaps_int2data.at(type_no);
1560 15138 : if (index >= (int)(int2data_map.size()))
1561 : {
1562 0 : throw(std::runtime_error("Error in get_data_value: Value not found for type_no "
1563 0 : + std::to_string(type_no) + " at index " + std::to_string(index) + "."));
1564 : }
1565 15138 : return int2data_map.at(index);
1566 : }
1567 :
1568 :
1569 1732 : ltsmin_state explorer::from_state_vector(int* const& src)
1570 : {
1571 : //std::clog << "-- from_state_vector(model, src) --" << std::endl;
1572 1732 : data_expression novalue;
1573 1732 : int state_length = info->get_lts_type().get_state_length();
1574 :
1575 1732 : std::string varname = this->get_string_value(src[0]);
1576 : //std::clog << "from_state_vector: varname = " << varname << std::endl;
1577 :
1578 1732 : bool error = false;
1579 :
1580 : // data_expression values[state_length]; N.B. This is not portable C++
1581 1732 : std::vector <data_expression> values(state_length);
1582 :
1583 : int type_no;
1584 6872 : for (int i = 1; i < state_length; i++) {
1585 : //std::clog << "from_state_vector: values: " << i << " (" << src[i] << "): " << std::endl;
1586 5140 : type_no = info->get_lts_type().get_state_type_no(i);
1587 5140 : values[i] = this->get_data_value(type_no, src[i]);
1588 : //std::clog << "from_state_vector: " << values[i].to_string() << std::endl;
1589 : }
1590 : //std::clog << "from_state_vector: values done." << std::endl;
1591 1732 : data::data_expression_vector parameters;
1592 : std::vector<int> parameter_indices =
1593 1732 : detail::map_at(info->get_variable_parameter_indices(), varname);
1594 6480 : for (int & parameter_indice : parameter_indices) {
1595 4748 : if (values[parameter_indice+1]==novalue)
1596 : {
1597 0 : error = true;
1598 : //std::clog << "from_state_vector: varname = " << varname << ", values[" << *param_index+1 << "] = " << values[*param_index+1].to_string() << "(" << src[*param_index+1] << ")" << std::endl;
1599 : }
1600 4748 : parameters.push_back(values[parameter_indice+1]);
1601 : }
1602 1732 : if (error)
1603 : {
1604 0 : throw(std::runtime_error("Error in from_state_vector: NoValue in parameters."));
1605 : }
1606 1732 : data::data_expression_list paramlist(parameters.begin(), parameters.end());
1607 1732 : propositional_variable_instantiation state_expression(varname, paramlist);
1608 : //std::clog << "from_state_vector: state_expression = " << state_expression.to_string() << std::endl;
1609 1732 : ltsmin_state state = this->get_state(state_expression);
1610 : //std::clog << "from_state_vector: state = " << state->to_string() << std::endl;
1611 3464 : return state;
1612 1732 : }
1613 :
1614 :
1615 866 : std::vector<ltsmin_state> explorer::get_successors(const ltsmin_state& state)
1616 : {
1617 : //std::cout << "get_successors: " << state->to_string() << std::endl;
1618 866 : std::vector<ltsmin_state> result;
1619 :
1620 866 : pbes_expression e = state.to_pbes_expression();
1621 866 : assert(core::detail::check_term_PropVarInst(e));
1622 866 : if (state.get_variable()=="true")
1623 : {
1624 : // Adding true=true
1625 0 : result.push_back(state);
1626 : }
1627 866 : else if (state.get_variable()=="false")
1628 : {
1629 : // Adding false=false
1630 0 : result.push_back(state);
1631 : }
1632 : else
1633 : {
1634 : std::set<pbes_expression> successors
1635 866 : = pgg->get_successors(e);
1636 866 : operation_type type = detail::map_at(info->get_variable_types(), state.get_variable());
1637 2546 : for (const auto & successor : successors) {
1638 1680 : if (is_propositional_variable_instantiation(successor)) {
1639 1680 : result.push_back(get_state(atermpp::down_cast<propositional_variable_instantiation>(successor)));
1640 0 : } else if (is_true(successor)) {
1641 0 : if (type != parity_game_generator::PGAME_AND)
1642 : {
1643 0 : result.push_back(true_state());
1644 : }
1645 0 : } else if (is_false(successor)) {
1646 0 : if (type != parity_game_generator::PGAME_OR)
1647 : {
1648 0 : result.push_back(false_state());
1649 : }
1650 : } else {
1651 0 : throw(std::runtime_error("!! Successor is NOT a propvar: " + pbes_system::pp(successor)));
1652 : }
1653 : }
1654 866 : }
1655 1732 : return result;
1656 866 : }
1657 :
1658 :
1659 866 : std::vector<ltsmin_state> explorer::get_successors(const ltsmin_state& state,
1660 : int group)
1661 : {
1662 : //std::clog << "get_successors: group=" << group << std::endl;
1663 866 : std::vector<ltsmin_state> result;
1664 :
1665 866 : if (group == 0 && state.get_variable()=="true")
1666 : {
1667 : // Adding true=true
1668 0 : result.push_back(state);
1669 : }
1670 866 : else if (group == 1 && state.get_variable()=="false")
1671 : {
1672 : // Adding false=false
1673 0 : result.push_back(state);
1674 : }
1675 : else
1676 : {
1677 866 : std::string varname = state.get_variable();
1678 866 : std::string group_varname = info->get_transition_variable_names()[group];
1679 866 : if (varname==group_varname)
1680 : {
1681 866 : pbes_expression e = state.to_pbes_expression();
1682 : std::set<pbes_expression> successors
1683 866 : = pgg->get_successors(e, group_varname,
1684 866 : info->get_transition_expressions()[group]);
1685 866 : operation_type type = detail::map_at(info->get_variable_types(), state.get_variable());
1686 2546 : for (const auto & successor : successors) {
1687 : //std::clog << " * successor: " << pp(*expr) << std::endl;
1688 1680 : if (is_propositional_variable_instantiation(successor)) {
1689 1680 : result.push_back(get_state(atermpp::down_cast<propositional_variable_instantiation>(successor)));
1690 0 : } else if (is_true(successor)) {
1691 0 : if (type != parity_game_generator::PGAME_AND)
1692 : {
1693 0 : result.push_back(true_state());
1694 : }
1695 0 : } else if (is_false(successor)) {
1696 0 : if (type != parity_game_generator::PGAME_OR)
1697 : {
1698 0 : result.push_back(false_state());
1699 : }
1700 : } else {
1701 0 : throw(std::runtime_error("!! Successor is NOT a propvar: " + pbes_system::pp(successor)));
1702 : }
1703 : }
1704 866 : }
1705 866 : }
1706 866 : return result;
1707 0 : }
1708 :
1709 :
1710 : } // namespace pbes_system
1711 :
1712 : } // namespace mcrl2
|