mCRL2
Loading...
Searching...
No Matches
binary.h
Go to the documentation of this file.
1// Author(s): Jeroen Keiren
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 binary.h
10/// \brief The binary algorithm.
11
12#ifndef MCRL2_LPS_BINARY_H
13#define MCRL2_LPS_BINARY_H
14
15#include "mcrl2/data/enumerator.h"
16#include "mcrl2/lps/detail/lps_algorithm.h"
17#include "mcrl2/lps/detail/parameter_selection.h"
18
19namespace mcrl2
20{
21
22namespace lps
23{
24
25// Compute the number of booleans needed to represent a set of size n.
26inline
28{
29 if(n == 1)
30 {
31 return 1;
32 }
33 else
34 {
35 return utilities::ceil_log2(n-1);
36 }
37}
38
39/// \brief Algorithm class that can be used to apply the binary algorithm
40///
41/// All parameters of finite data types are replaced with a vector of
42/// booleans.
43template<typename DataRewriter, typename Specification>
44class binary_algorithm: public detail::lps_algorithm<Specification>
45{
47 typedef typename detail::lps_algorithm<Specification> super;
48 typedef typename Specification::process_type process_type;
50 using super::m_spec;
51
52 protected:
53 /// Rewriter
54 DataRewriter m_rewriter;
55
57
58 /// Mapping of finite variables to boolean vectors
60
61 /// Mapping of variables to all values they can be assigned
63
64 /// Mapping of variables to corresponding if-tree
66
67 /// Contains the names of variables appearing in rhs of m_if_trees
69
70 /// Identifier generator for the enumerator
72
73 /// \brief Build an if-then-else tree of enumerated elements in terms
74 /// of new parameters.
75 /// \pre enumerated_elements.size() <= 2^new_parameters.size()
76 /// \return if then else tree from enumerated_elements in terms of new_parameters
78 const data::data_expression_vector& enumerated_elements)
79 {
80 data::data_expression result;
81
82 if (new_parameters.empty())
83 {
84 result = enumerated_elements.front();
85 }
86 else
87 {
88 std::size_t n = enumerated_elements.size();
89 std::size_t m = static_cast<std::size_t>(1) << (new_parameters.size() - 1); //m == 2^(new_parameters.size() - 1)
90
91 if (m > n)
92 {
93 m = n;
94 }
95
96 data::data_expression_vector left_list(enumerated_elements.begin(), enumerated_elements.begin() + m);
97 data::data_expression_vector right_list;
98 if (m == n)
99 {
100 right_list = data::data_expression_vector(enumerated_elements.begin() + m - 1, enumerated_elements.end());
101 }
102 else
103 {
104 right_list = data::data_expression_vector(enumerated_elements.begin() + m, enumerated_elements.end());
105 }
106
107 data::data_expression condition = new_parameters.back();
108 new_parameters.pop_back();
109 result = if_(condition,
110 make_if_tree(new_parameters, right_list),
111 make_if_tree(new_parameters, left_list));
112 }
113
114 return result;
115 }
116
117 /// \brief Determine which variables should be replaced, based on parameter_selection
118 /// \return A subset of the process parameters, with a finite sort that is not Bool
120 {
121 const data::variable_list& process_parameters = m_spec.process().process_parameters();
122 bool use_selection = !parameter_selection.empty();
123
124 std::list<data::variable> selected_params;
125 if (use_selection)
126 {
127 const data::variable_vector sel =
128 detail::parse_lps_parameter_selection(process_parameters, m_spec.data(), parameter_selection);
129 selected_params = std::list<data::variable>(sel.begin(), sel.end());
130 }
131 else
132 {
133 selected_params = std::list<data::variable>(process_parameters.begin(), process_parameters.end());
134 }
135 selected_params.remove_if([&](const data::variable& v)
136 {
137 bool cannot_replace = v.sort() == data::sort_bool::bool_() || !m_spec.data().is_certainly_finite(v.sort());
138 if (cannot_replace && use_selection)
139 {
140 mCRL2log(log::info) << "Not selecting " << v << ":" << v.sort() << " since it is already Bool, or its type is not finite." << std::endl;
141 }
142 return cannot_replace;
143 }
144 );
145
146 if (use_selection && selected_params.empty())
147 {
148 mCRL2log(log::info) << "No parameters were selected to be replaced." << std::endl;
149 }
150
151 return std::set<data::variable>(selected_params.begin(), selected_params.end());
152 }
153
154 /// \brief Take a specification and calculate a vector of boolean variables for each process
155 /// parameter in selected_params. A mapping variable -> vector of booleans is stored in new_parameters_table
156 /// a mapping variable -> enumerated elements is stored in enumerated_elements_table
157 /// \pre all elements in selected_params should not be of type Bool and should have a finite type
158 /// \return data variable list with the new process parameters (i.e. with all variables of a
159 /// finite type != bool replaced by a vector of boolean variables.
160 void replace_enumerated_parameters(const std::set<data::variable>& selected_params)
161 {
162 data::variable_list process_parameters = m_spec.process().process_parameters();
163 data::variable_vector new_parameters;
164
165 mCRL2log(log::debug) << "Original process parameters: " << data::pp(process_parameters) << std::endl;
166
168 generator.add_identifiers(lps::find_identifiers(m_spec));
169 generator.add_identifiers(data::function_and_mapping_identifiers(m_spec.data()));
170 bool accept_solutions_with_variables = false;
171 data::enumerator_algorithm<> enumerator(m_rewriter, m_spec.data(), m_rewriter, m_id_generator, accept_solutions_with_variables);
172
173 // Transpose all process parameters, and replace those that are finite, and not bool with boolean variables.
174 for (const data::variable& par: process_parameters)
175 {
176 if (selected_params.find(par) != selected_params.end())
177 {
178 //Get all constructors for par
179 data::data_expression_vector enumerated_elements; // List to store enumerated elements of a parameter
180
181 data::mutable_indexed_substitution<> local_sigma;
182 const data::variable_list vl{ par };
183 enumerator.enumerate(enumerator_element(vl, data::sort_bool::true_()),
184 local_sigma,
185 [&](const enumerator_element& p)
186 {
187 p.add_assignments(vl, local_sigma, m_rewriter);
188 enumerated_elements.push_back(local_sigma(par));
189 return false;
190 }
191 );
192 m_enumerated_elements[par] = enumerated_elements;
193
194 //Calculate the number of booleans needed to encode par
195 std::size_t n = nr_of_booleans_for_elements(enumerated_elements.size());
196
197 //Set hint for fresh variable names
198 std::string par_name = par.name();
199
200 // Temp list for storage
201 data::variable_vector new_pars;
202 //Create new parameters and add them to the parameter list.
203 for (std::size_t i = 0; i<n; ++i)
204 {
205 data::variable v(generator(par_name), data::sort_bool::bool_());
206 new_parameters.push_back(v);
207 new_pars.push_back(v);
208 }
209 // n = new_pars.size() && new_pars.size() = ceil(log_2(j)) && new_pars.size() = ceil(log_2(enumerated_elements.size()))
210
211 mCRL2log(log::verbose) << "Parameter " << data::pp(par) << ":" << data::pp(par.sort()) << " has been replaced by " << new_pars.size() << " parameter(s) " << data::pp(new_pars) << " of sort Bool" << std::endl;
212
213 //Store new parameters in a hastable
214 m_new_parameters[par]=new_pars;
215
216 m_if_trees[par]=make_if_tree(new_pars,
217 enumerated_elements);
218 }
219 else
220 {
221 new_parameters.push_back(par);
222 }
223 }
224
225 mCRL2log(log::debug) << "New process parameter(s): " << data::pp(new_parameters) << std::endl;
226
227 m_spec.process().process_parameters() = data::variable_list(new_parameters.begin(),new_parameters.end());
228 for (const data::variable& v: data::substitution_variables(m_if_trees))
229 {
230 m_if_trees_generator.add_identifier(v.name());
231 }
232 }
233
234 /// \brief Replace expressions in v that are of a finite sort with a
235 /// vector of assignments to Boolean variables.
237 const data::variable_list& vl,
238 const data::data_expression_list& el)
239 {
240 // We use replace_variables, to make sure that the binding variables of assignments are ignored.
241 // Note that this operation is safe because the generated fresh variables can not clash with other
242 // binding variables.
243 const data::data_expression_list el_ = data::replace_variables(el, m_if_trees);
244
246 data::variable_list::const_iterator i=vl.begin();
247 for (const data::data_expression& a: el_)
248 {
249 const data::variable par= *i;
250 i++;
251 if (m_new_parameters.find(par) == m_new_parameters.end()) // This parameter is not replaced by a boolean parameters.
252 {
253 result.push_back(a);
254 }
255 else
256 {
257 data::variable_vector new_parameters = m_new_parameters[par];
258 data::data_expression_vector elements = m_enumerated_elements[par];
259
260 mCRL2log(log::debug) << "Found " << new_parameters.size() << " new parameter(s) for parameter " << data::pp(par) << std::endl;
261
262 for (std::size_t j = 0; j < new_parameters.size(); ++j)
263 {
264 data::data_expression_vector disjuncts;
265
266 data::data_expression_vector::iterator k = elements.begin();
267 while (k != elements.end())
268 {
269 // Elements that get boolean value false
270 std::ptrdiff_t count(static_cast<std::ptrdiff_t>(1) << j);
271 if (std::distance(k, elements.end()) < count)
272 {
273 k = elements.end();
274 }
275 else
276 {
277 std::advance(k, count);
278 }
279
280 // Elements that get value true
281 for (std::ptrdiff_t l = 0; l < count && k != elements.end(); ++l)
282 {
283 disjuncts.push_back(data::equal_to(a, *k++));
284 }
285 }
286 result.push_back(data::lazy::join_or(disjuncts.begin(), disjuncts.end()));
287 }
288 }
289 }
290
291 mCRL2log(log::debug) << "Replaced expression(s) " << data::pp(el_) << " in the initial state with expression(s) " << data::pp(result) << std::endl;
292
293 return data::data_expression_list(result.begin(),result.end());
294 }
295
296 /// \brief Replace assignments in v that are of a finite sort with a
297 /// vector of assignments to Boolean variables.
299 {
300 // We use replace_variables, to make sure that the binding variables of assignments are ignored.
301 // Note that this operation is safe because the generated fresh variables can not clash with other
302 // binding variables.
303 v = data::replace_variables(v, m_if_trees);
304
305 data::assignment_vector result;
306 for (const data::assignment& a: v)
307 {
308 if (m_new_parameters.find(a.lhs()) == m_new_parameters.end())
309 {
310 result.push_back(a);
311 }
312 else
313 {
314 data::variable_vector new_parameters = m_new_parameters[a.lhs()];
315 data::data_expression_vector elements = m_enumerated_elements[a.lhs()];
316
317 mCRL2log(log::debug) << "Found " << new_parameters.size() << " new parameter(s) for parameter " << data::pp(a.lhs()) << std::endl;
318
319 for (std::size_t j = 0; j < new_parameters.size(); ++j)
320 {
321 data::data_expression_vector disjuncts;
322
323 data::data_expression_vector::iterator k = elements.begin();
324 while (k != elements.end())
325 {
326 // Elements that get boolean value false
327 std::ptrdiff_t count(static_cast<std::ptrdiff_t>(1) << j);
328 if (std::distance(k, elements.end()) < count)
329 {
330 k = elements.end();
331 }
332 else
333 {
334 std::advance(k, count);
335 }
336
337 // Elements that get value true
338 for (std::ptrdiff_t l = 0; l < count && k != elements.end(); ++l)
339 {
340 disjuncts.push_back(data::equal_to(a.rhs(), *k++));
341 }
342 }
343 result.push_back(data::assignment(new_parameters[j], data::lazy::join_or(disjuncts.begin(), disjuncts.end())));
344 }
345
346 }
347 }
348
349 mCRL2log(log::debug) << "Replaced assignment(s) " << data::pp(v) << " with assignment(s) " << data::pp(result) << std::endl;
350
351 return data::assignment_list(result.begin(),result.end());
352 }
353
354 /// \brief Update an action summand with the new Boolean parameters
356 {
357 s.condition() = data::replace_variables_capture_avoiding(s.condition(), m_if_trees, m_if_trees_generator);
358 s.multi_action()=lps::replace_variables_capture_avoiding(s.multi_action(), m_if_trees, m_if_trees_generator);
359 s.assignments() = replace_enumerated_parameters_in_assignments(s.assignments());
360 }
361
362 /// \brief Update an action summand with the new Boolean parameters
364 {
365 update_action_summand(static_cast<action_summand&>(s));
366 s.distribution() = lps::replace_variables_capture_avoiding(s.distribution(), m_if_trees, m_if_trees_generator);
367 }
368
369 /// \brief Update a deadlock summand with the new Boolean parameters
371 {
372 s.condition() = data::replace_variables_capture_avoiding(s.condition(), m_if_trees, m_if_trees_generator);
373 lps::replace_variables_capture_avoiding(s.deadlock(), m_if_trees, m_if_trees_generator);
374 }
375
377 {
378 return process_initializer(replace_enumerated_parameters_in_initial_expressions(parameters, init.expressions()));
379 }
380
382 {
383 /* return stochastic_process_initializer(replace_enumerated_parameters_in_initial_expressions(parameters, init.expressions()),
384 lps::replace_variables_capture_avoiding(init.distribution(), m_if_trees, m_if_trees_generator)
385 ); */
386 data::data_expression_list d = replace_enumerated_parameters_in_initial_expressions(parameters, init.expressions());
387 const stochastic_distribution dist = lps::replace_variables_capture_avoiding(init.distribution(), d, m_if_trees, m_if_trees_generator);
388 return stochastic_process_initializer(d, dist);
389 }
390
391 public:
392 /// \brief Constructor for binary algorithm
393 /// \param spec Specification to which the algorithm should be applied
394 /// \param r a rewriter for data
395 binary_algorithm(Specification& spec,
396 DataRewriter& r,
397 const std::string parameter_selection = "")
398 : detail::lps_algorithm<Specification>(spec),
399 m_rewriter(r),
401 {}
402
403 /// \brief Apply the algorithm to the specification passed in the
404 /// constructor
405 void run()
406 {
407 data::variable_list old_parameters = m_spec.process().process_parameters();
408 const std::set<data::variable> to_replace = select_parameters(m_parameter_selection);
409 replace_enumerated_parameters(to_replace);
410
411 // Initial process
412 mCRL2log(log::debug) << "Updating process initializer" << std::endl;
413 m_spec.initial_process() = update_initial_process(old_parameters, m_spec.initial_process());
414
415 // Summands
416 mCRL2log(log::debug) << "Updating summands" << std::endl;
417
418 for (action_summand& a: m_spec.process().action_summands())
419 {
420 update_action_summand(a);
421 }
422
423 for (deadlock_summand& d: m_spec.process().deadlock_summands())
424 {
426 }
427 }
428};
429
430} // namespace lps
431
432} // namespace mcrl2
433
434#endif // MCRL2_LPS_BINARY_H
Rewriter that operates on data expressions.
Definition rewriter.h:81
Identifier generator that stores the identifiers of the context in a set. Using the operator()() and ...
logger(const log_level_t l)
Default constructor.
Definition logger.h:164
LPS summand containing a multi-action.
Algorithm class that can be used to apply the binary algorithm.
Definition binary.h:45
data::assignment_list replace_enumerated_parameters_in_assignments(data::assignment_list v)
Replace assignments in v that are of a finite sort with a vector of assignments to Boolean variables.
Definition binary.h:298
data::data_expression make_if_tree(data::variable_vector new_parameters, const data::data_expression_vector &enumerated_elements)
Build an if-then-else tree of enumerated elements in terms of new parameters.
Definition binary.h:77
binary_algorithm(Specification &spec, DataRewriter &r, const std::string parameter_selection="")
Constructor for binary algorithm.
Definition binary.h:395
void update_deadlock_summand(deadlock_summand &s)
Update a deadlock summand with the new Boolean parameters.
Definition binary.h:370
detail::lps_algorithm< Specification > super
Definition binary.h:47
std::map< data::variable, std::vector< data::data_expression > > m_enumerated_elements
Mapping of variables to all values they can be assigned.
Definition binary.h:62
stochastic_process_initializer update_initial_process(const data::variable_list &parameters, const stochastic_process_initializer &init)
Definition binary.h:381
Specification::process_type process_type
Definition binary.h:48
data::set_identifier_generator m_if_trees_generator
Contains the names of variables appearing in rhs of m_if_trees.
Definition binary.h:68
const std::string m_parameter_selection
Definition binary.h:56
void replace_enumerated_parameters(const std::set< data::variable > &selected_params)
Take a specification and calculate a vector of boolean variables for each process parameter in select...
Definition binary.h:160
data::data_expression_list replace_enumerated_parameters_in_initial_expressions(const data::variable_list &vl, const data::data_expression_list &el)
Replace expressions in v that are of a finite sort with a vector of assignments to Boolean variables.
Definition binary.h:236
void update_action_summand(action_summand &s)
Update an action summand with the new Boolean parameters.
Definition binary.h:355
std::set< data::variable > select_parameters(const std::string parameter_selection) const
Determine which variables should be replaced, based on parameter_selection.
Definition binary.h:119
void run()
Apply the algorithm to the specification passed in the constructor.
Definition binary.h:405
process_type::action_summand_type action_summand_type
Definition binary.h:49
data::mutable_map_substitution m_if_trees
Mapping of variables to corresponding if-tree.
Definition binary.h:65
process_initializer update_initial_process(const data::variable_list &parameters, const process_initializer &init)
Definition binary.h:376
DataRewriter m_rewriter
Rewriter.
Definition binary.h:54
std::map< data::variable, std::vector< data::variable > > m_new_parameters
Mapping of finite variables to boolean vectors.
Definition binary.h:59
void update_action_summand(stochastic_action_summand &s)
Update an action summand with the new Boolean parameters.
Definition binary.h:363
data::enumerator_list_element_with_substitution enumerator_element
Definition binary.h:46
data::enumerator_identifier_generator m_id_generator
Identifier generator for the enumerator.
Definition binary.h:71
Algorithm class for elimination of constant parameters.
Definition constelm.h:26
LPS summand containing a deadlock.
Algorithm class for algorithms on linear process specifications. It can be instantiated with lps::spe...
Stores the following properties of a linear process specification:
LPS summand containing a multi-action.
\brief A stochastic distribution
Standard exception class for reporting runtime errors.
Definition exception.h:27
#define mCRL2log(LEVEL)
mCRL2log(LEVEL) provides the stream used to log.
Definition logger.h:391
std::string pp(const atermpp::aterm &t)
Transform an aterm to an ascii string.
Definition aterm.h:440
std::string pp_format_to_string(const print_format_type pp_format)
Print string representation of pretty print format.
smt_solver_type
The enumeration type smt_solver_type enumerates all available SMT solvers.
Definition solver_type.h:27
Namespace for all data library functionality.
Definition data.cpp:22
std::vector< assignment > assignment_vector
\brief vector of assignments
Definition assignment.h:149
std::vector< variable > variable_vector
\brief vector of variables
Definition variable.h:89
std::vector< data_expression > data_expression_vector
\brief vector of data_expressions
atermpp::term_list< data_expression > data_expression_list
\brief list of data_expressions
atermpp::term_list< variable > variable_list
\brief list of variables
atermpp::term_list< assignment > assignment_list
\brief list of assignments
Definition assignment.h:146
std::string pp(const data::sort_expression_vector &x)
Definition data.cpp:26
@ warning
Definition logger.h:34
@ verbose
Definition logger.h:37
The main namespace for the LPS library.
Definition constelm.h:21
void lpspp(const std::string &input_filename, const std::string &output_filename, bool print_summand_numbers, core::print_format_type format)
Definition tools.cpp:171
void lpssumelm(const std::string &input_filename, const std::string &output_filename, const bool decluster)
Definition tools.cpp:246
void txt2lps(const std::string &input_filename, const std::string &output_filename)
Definition tools.cpp:310
void lpsuntime(const std::string &input_filename, const std::string &output_filename, const bool add_invariants, const bool apply_fourier_motzkin, const data::rewriter::strategy rewrite_strategy)
Definition tools.cpp:296
std::string pp(const lps::stochastic_specification &x)
Definition lps.cpp:37
void lpssuminst(const std::string &input_filename, const std::string &output_filename, const data::rewriter::strategy rewrite_strategy, const std::string &sorts_string, const bool finite_sorts_only, const bool tau_summands_only)
Definition tools.cpp:259
std::size_t nr_of_booleans_for_elements(std::size_t n)
Definition binary.h:27
bool lpsinvelm(const std::string &input_filename, const std::string &output_filename, const std::string &invariant_filename, const std::string &dot_file_name, data::rewriter::strategy rewrite_strategy, data::detail::smt_solver_type solver_type, const bool no_check, const bool no_elimination, const bool simplify_all, const bool all_violations, const bool counter_example, const bool path_eliminator, const bool apply_induction, const int time_limit)
Definition tools.cpp:86
void lpsparelm(const std::string &input_filename, const std::string &output_filename)
Definition tools.cpp:161
void lpsbinary(const std::string &input_filename, const std::string &output_filename, const std::string &parameter_selection)
Definition tools.cpp:31
lps_rewriter_type
An enumerated type for the available lps rewriters.
void lpsconstelm(const std::string &input_filename, const std::string &output_filename, data::rewriter::strategy rewrite_strategy, bool instantiate_free_variables, bool ignore_conditions, bool remove_trivial_summands, bool remove_singleton_sorts)
Definition tools.cpp:43
void lpsinfo(const std::string &input_filename, const std::string &input_file_message)
Definition tools.cpp:75
void parse_lps< stochastic_specification >(std::istream &from, stochastic_specification &result)
Parses a stochastic linear process specification from an input stream.
Definition parse.h:183
void lpsrewr(const std::string &input_filename, const std::string &output_filename, const data::rewriter::strategy rewrite_strategy, const lps_rewriter_type rewriter_type)
Definition tools.cpp:213
std::string pp_with_summand_numbers(const stochastic_specification &x)
Definition lps.cpp:83
std::size_t ceil_log2(std::size_t n)
Definition math.h:28
A class that takes a linear process specification and checks all tau-summands of that LPS for conflue...
std::size_t operator()(const atermpp::detail::reference_aterm< T > &t) const