mCRL2
Loading...
Searching...
No Matches
pbesinst_finite_algorithm.h
Go to the documentation of this file.
1// Author(s): Wieger Wesselink; Alexander van Dam
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/pbesinst_finite_algorithm.h
10/// \brief add your file description here.
11
12#ifndef MCRL2_PBES_PBESINST_FINITE_ALGORITHM_H
13#define MCRL2_PBES_PBESINST_FINITE_ALGORITHM_H
14
15#include "mcrl2/data/consistency.h"
16#include "mcrl2/data/enumerator.h"
17#include "mcrl2/data/replace.h"
18#include "mcrl2/pbes/algorithms.h"
19#include "mcrl2/pbes/detail/pbes_parameter_map.h"
20#include "mcrl2/pbes/join.h"
21#include "mcrl2/pbes/rewriters/data_rewriter.h"
22
23namespace mcrl2
24{
25
26namespace pbes_system
27{
28
29/// \brief Data structure for storing the indices of the variables that should be expanded by the finite pbesinst algorithm.
31
32/// \brief Data structure for storing the variables that should be expanded by the finite pbesinst algorithm.
34
35/// \brief Function object for renaming a propositional variable instantiation
37{
38 protected:
41
43 {
44 std::ostringstream out;
45 out << std::string(name);
46 for (const data::data_expression& param: parameters)
47 {
48 out << "_" << data::pp(param);
49 }
50 return core::identifier_string(out.str());
51 }
52
53 public:
54 /// \brief Renames the propositional variable x.
56 {
58 auto i = m.find(P);
59 if (i == m.end())
60 {
61 core::identifier_string dest = rename(name, parameters);
62 if (id_generator.has_identifier(dest))
63 {
64 dest = id_generator(dest);
65 }
66 else
67 {
68 id_generator.add_identifier(dest);
69 }
70 m[P] = dest;
71 return dest;
72 }
73 else
74 {
75 return i->second;
76 }
77 }
78};
79
80/// \brief Exception that is used to signal an empty parameter selection
82{
83 explicit empty_parameter_selection(const std::string& msg)
84 : mcrl2::runtime_error(msg)
85 {}
86};
87
88namespace detail
89{
90
91/// \brief Computes the subset with variables of finite sort and infinite.
92/// \param X A propositional variable instantiation
93/// \param index_map a container storing the indices of the variables that
94/// should be expanded by the finite pbesinst algorithm.
95/// \param finite A sequence of data expressions
96/// \param infinite A sequence of data expressions
97template <typename PropositionalVariable, typename Parameter>
98void split_parameters(const PropositionalVariable& X,
99 const pbesinst_index_map& index_map,
100 std::vector<Parameter>& finite,
101 std::vector<Parameter>& infinite
102 )
103{
104 auto pi = index_map.find(X.name());
105 assert(pi != index_map.end());
106 const std::vector<std::size_t>& v = pi->second;
107 auto i = X.parameters().begin();
108 std::size_t index = 0;
109 auto j = v.begin();
110 for (; i != X.parameters().end(); ++i, ++index)
111 {
112 if (j != v.end() && index == *j)
113 {
114 finite.push_back(*i);
115 ++j;
116 }
117 else
118 {
119 infinite.push_back(*i);
120 }
121 }
122}
123
124/// \brief Visitor that applies a propositional variable substitution to a pbes expression.
125template <typename DataRewriter, typename SubstitutionFunction>
126struct pbesinst_finite_builder: public pbes_system::detail::data_rewriter_builder<pbesinst_finite_builder<DataRewriter, SubstitutionFunction>, DataRewriter, SubstitutionFunction>
127{
128 typedef pbes_system::detail::data_rewriter_builder<pbesinst_finite_builder, DataRewriter, SubstitutionFunction> super;
129 using super::apply;
130 using super::sigma;
131
136
137 pbesinst_finite_builder(const DataRewriter& R,
138 SubstitutionFunction& sigma,
139 const pbesinst_finite_rename& rho,
140 const data::data_specification& data_spec,
141 const pbesinst_index_map& index_map,
142 const pbesinst_variable_map& variable_map
143 )
144 : super(R, sigma),
145 m_rename(rho),
146 m_data_spec(data_spec),
147 m_index_map(index_map),
148 m_variable_map(variable_map)
149 {}
150
151 std::string print_parameters(const std::vector<data::data_expression>& finite_parameters,
152 const std::vector<data::data_expression>& infinite_parameters
153 ) const
154 {
155 std::ostringstream out;
156 out << "<finite>";
157 for (const data::data_expression& e: finite_parameters)
158 {
159 out << e << " ";
160 }
161 out << "<infinite>";
162 for (const data::data_expression& e: infinite_parameters)
163 {
164 out << e << " ";
165 }
166 out << std::endl;
167 return out.str();
168 }
169
170 /// \brief Computes the condition 'for all i: variables[i] == expressions[i]'.
171 template <typename VariableContainer, typename ExpressionContainer>
172 data::data_expression make_condition(const VariableContainer& variables, const ExpressionContainer& expressions) const
173 {
174 assert(variables.size() == expressions.size());
175 if (variables.empty())
176 {
177 return data::true_();
178 }
179 auto vi = variables.begin();
180 auto ei = expressions.begin();
181 data::data_expression result = data::equal_to(*vi, *ei);
182 ++vi;
183 ++ei;
184 for (; vi != variables.end(); ++vi, ++ei)
185 {
186 result = data::and_(result, data::equal_to(*vi, *ei));
187 }
188 return result;
189 }
190
191 template <typename DataExpressionContainer>
192 data::data_expression_list rewrite_container(const DataExpressionContainer& v, const data::rewriter& rewr)
193 {
194 return data::data_expression_list(v.begin(), v.end(), [&](const data::data_expression& x) { return rewr(x); });
195 }
196
197 template <typename DataExpressionContainer>
198 data::data_expression_list rewrite_container(const DataExpressionContainer& v, const data::rewriter& rewr, const data::mutable_indexed_substitution<>& sigma)
199 {
200 return data::data_expression_list(v.begin(), v.end(), [&](const data::data_expression& x) { return rewr(x, sigma); });
201 }
202
203 template <class T>
205 {
206 typedef data::enumerator_list_element_with_substitution<> enumerator_element;
207
208 // TODO: this code contains too much conversion between vectors and aterm lists
209 std::vector<data::data_expression> finite_parameters;
210 std::vector<data::data_expression> infinite_parameters;
211 split_parameters(x, m_index_map, finite_parameters, infinite_parameters);
212 mCRL2log(log::debug) << print_parameters(finite_parameters, infinite_parameters);
213 data::data_expression_list d(finite_parameters.begin(), finite_parameters.end());
214 data::data_expression_list e(infinite_parameters.begin(), infinite_parameters.end());
215 const core::identifier_string& Xi = x.name();
216 // x = Xi(d,e)
217
218 auto vi = m_variable_map.find(Xi);
219 std::vector<data::variable> di;
220 if (vi != m_variable_map.end())
221 {
222 di = vi->second;
223 }
224
225 std::set<pbes_expression> result_set;
226 bool accept_solutions_with_variables = false;
228 data::enumerator_algorithm<> E(super::R, m_data_spec, super::R, id_generator, accept_solutions_with_variables);
229 const data::variable_list di_list(di.begin(), di.end());
230 data::mutable_indexed_substitution<> local_sigma;
231 E.enumerate(enumerator_element(di_list, data::true_()),
232 local_sigma,
233 [&](const enumerator_element& p) {
234 data::mutable_indexed_substitution<> sigma_i;
235 p.add_assignments(di_list, sigma_i, super::R);
236 data::data_expression_list d_copy = rewrite_container(d, super::R, sigma);
237 data::data_expression_list e_copy = rewrite_container(e, super::R, sigma);
238 data::data_expression_list di_copy = atermpp::container_cast<data::data_expression_list>(di_list);
239 di_copy = data::replace_free_variables(di_copy, sigma_i);
240 data::data_expression c = make_condition(di_copy, d_copy);
241 core::identifier_string Y = m_rename(Xi, di_copy);
242 result_set.insert(and_(c, propositional_variable_instantiation(Y, e_copy)));
243 return false;
244 }
245 );
246 result = join_or(result_set.begin(), result_set.end());
247 }
248
249 /// \return Visits the initial state
251 {
252 std::vector<data::data_expression> finite_parameters_vector;
253 std::vector<data::data_expression> infinite_parameters_vector;
254 split_parameters(init, m_index_map, finite_parameters_vector, infinite_parameters_vector);
255
256 data::data_expression_list finite_parameters = rewrite_container(finite_parameters_vector, super::R);
257 data::data_expression_list infinite_parameters = rewrite_container(infinite_parameters_vector, super::R);
258 core::identifier_string X = m_rename(init.name(), finite_parameters);
259 return propositional_variable_instantiation(X, infinite_parameters);
260 }
261};
262
263} // namespace detail
264
265/// \brief Algorithm class for the finite pbesinst algorithm.
267{
268 protected:
269 /// \brief The strategy of the data rewriter.
271
272 /// \brief The number of generated equations.
274
275 /// \brief Identifier generator for the enumerator
277
278 /// \brief Returns true if the container contains the given element
279 void compute_index_map(const std::vector<pbes_equation>& equations,
280 const pbesinst_variable_map& variable_map,
281 pbesinst_index_map& index_map)
282 {
283 using utilities::detail::contains;
284 for (const pbes_equation& eqn: equations)
285 {
286 const core::identifier_string& name = eqn.variable().name();
287 const data::variable_list& parameters = eqn.variable().parameters();
288
289 std::vector<std::size_t> v;
290 auto j = variable_map.find(name);
291 if (j != variable_map.end())
292 {
293 std::size_t index = 0;
294 for (auto k = parameters.begin(); k != parameters.end(); ++k, ++index)
295 {
296 if (contains(j->second, *k))
297 {
298 v.push_back(index);
299 }
300 }
301 }
302 index_map[name] = v;
303 }
304 }
305
306 /// \brief Prints a message for every 1000-th equation
307 std::string print_equation_count(std::size_t size) const
308 {
309 if (size > 0 && size % 1000 == 0)
310 {
311 std::ostringstream out;
312 out << "Generated " << size << " BES equations" << std::endl;
313 return out.str();
314 }
315 return "";
316 }
317
318 public:
319
320 /// \brief Constructor.
321 /// \param rewriter_strategy Strategy to be used for the data rewriter.
322 explicit pbesinst_finite_algorithm(data::rewriter::strategy rewriter_strategy = data::jitty)
324 {}
325
326 /// \brief Runs the algorithm.
327 /// \param pbesspec A PBES
328 /// \param variable_map A map containing the finite parameters that should be expanded by the algorithm.
329 void run(pbes& pbesspec, const pbesinst_variable_map& variable_map)
330 {
334
335 // compute index map corresponding to the variable map
336 pbesinst_index_map index_map;
337 compute_index_map(pbesspec.equations(), variable_map, index_map);
338
339 data::rewriter rewr(pbesspec.data(), m_rewriter_strategy);
340
341 // compute new equations
342 std::vector<pbes_equation> equations;
343 for (const pbes_equation& eqn: pbesspec.equations())
344 {
345 std::vector<data::variable> finite_parameters;
346 std::vector<data::variable> infinite_parameters;
347 detail::split_parameters(eqn.variable(), index_map, finite_parameters, infinite_parameters);
348 data::variable_list infinite(infinite_parameters.begin(), infinite_parameters.end());
349
350 typedef data::enumerator_list_element_with_substitution<> enumerator_element;
351 bool accept_solutions_with_variables = false;
352 data::enumerator_algorithm<> E(rewr, pbesspec.data(), rewr, m_id_generator, accept_solutions_with_variables);
353 data::variable_list finite_parameter_list(finite_parameters.begin(), finite_parameters.end());
354 data::mutable_indexed_substitution<> sigma;
355 E.enumerate(enumerator_element(finite_parameter_list, data::true_()),
356 sigma,
357 [&](const enumerator_element& p) {
358 data::mutable_indexed_substitution<> sigma_j;
359 p.add_assignments(finite_parameter_list, sigma_j, rewr);
360 std::vector<data::data_expression> finite;
361 for (const data::variable& v: finite_parameters)
362 {
363 finite.push_back(sigma_j(v));
364 }
365 core::identifier_string name = rename(eqn.variable().name(), data::data_expression_list(finite.begin(), finite.end()));
366 propositional_variable X(name, infinite);
367 detail::pbesinst_finite_builder<data::rewriter, data::mutable_indexed_substitution<>> visitor(rewr, sigma_j, rename, pbesspec.data(), index_map, variable_map);
368 pbes_expression formula;
369 visitor.apply(formula, eqn.formula());
370 equations.emplace_back(eqn.symbol(), X, formula);
371 mCRL2log(log::debug) << print_equation_count(++m_equation_count);
372 mCRL2log(log::debug) << "Added equation " << pbes_system::pp(eqn) << "\n";
373 return false;
374 }
375 );
376 }
377
378 // compute new initial state
379 data::no_substitution sigma;
380 detail::pbesinst_finite_builder<data::rewriter, data::no_substitution> visitor(rewr, sigma, rename, pbesspec.data(), index_map, variable_map);
381 propositional_variable_instantiation initial_state = visitor.visit_initial_state(pbesspec.initial_state());
382
383 // assign the result
384 pbesspec.equations() = equations;
385 pbesspec.initial_state() = initial_state;
386 }
387
388 /// \brief Runs the algorithm.
389 /// \param p A PBES
390 void run(pbes& p)
391 {
392 // put all finite variables in a variable map
393 pbesinst_variable_map variable_map;
394 for (const pbes_equation& eqn: p.equations())
395 {
396 for (const data::variable& v: eqn.variable().parameters())
397 {
398 if (p.data().is_certainly_finite(v.sort()))
399 {
400 variable_map[eqn.variable().name()].push_back(v);
401 }
402 }
403 }
404
405 run(p, variable_map);
406 }
407};
408
409inline
410void pbesinst_finite(pbes& p, data::rewrite_strategy rewrite_strategy, const std::string& finite_parameter_selection)
411{
412 if (finite_parameter_selection.empty())
413 {
414 throw empty_parameter_selection("no finite parameters were selected!");
415 }
416 pbesinst_finite_algorithm algorithm(rewrite_strategy);
418
419 bool is_empty = true;
420 for (auto& i: parameter_map)
421 {
422 if (!((i.second).empty()))
423 {
424 is_empty = false;
425 break;
426 }
427 }
428 if (is_empty)
429 {
430 mCRL2log(log::verbose) << "Warning: no parameters were found that match the string \"" + finite_parameter_selection + "\"" << std::endl;
431 }
432 else
433 {
434 algorithm.run(p, parameter_map);
435 }
436}
437
438} // namespace pbes_system
439
440} // namespace mcrl2
441
442#endif // MCRL2_PBES_PBESINST_FINITE_ALGORITHM_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
parameterized boolean equation system
Definition pbes.h:58
propositional_variable_instantiation & initial_state()
Returns the initial state.
Definition pbes.h:199
Algorithm class for the finite pbesinst algorithm.
data::enumerator_identifier_generator m_id_generator
Identifier generator for the enumerator.
std::size_t m_equation_count
The number of generated equations.
void run(pbes &pbesspec, const pbesinst_variable_map &variable_map)
Runs the algorithm.
std::string print_equation_count(std::size_t size) const
Prints a message for every 1000-th equation.
data::rewriter::strategy m_rewriter_strategy
The strategy of the data rewriter.
void compute_index_map(const std::vector< pbes_equation > &equations, const pbesinst_variable_map &variable_map, pbesinst_index_map &index_map)
Returns true if the container contains the given element.
pbesinst_finite_algorithm(data::rewriter::strategy rewriter_strategy=data::jitty)
Constructor.
\brief A propositional variable instantiation
propositional_variable_instantiation(const core::identifier_string &name, const data::data_expression_list &parameters)
Constructor.
propositional_variable_instantiation & operator=(const propositional_variable_instantiation &) noexcept=default
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
atermpp::aterm_string identifier_string
String type of the LPS library. Identifier strings are represented internally as ATerms.
Namespace for all data library functionality.
Definition data.cpp:22
data_expression and_(const data_expression &x, const data_expression &y)
const data_expression & true_()
Definition consistency.h:92
rewrite_strategy
The strategy of the rewriter.
atermpp::term_list< data_expression > data_expression_list
\brief list of data_expressions
atermpp::term_list< variable > variable_list
\brief list of variables
@ verbose
Definition logger.h:37
std::set< data::variable > significant_variables(const pbes_expression &x)
Returns the significant variables of a pbes expression.
void remove_parameters(pbes &x, const std::set< data::variable > &to_be_removed)
Removes parameters from propositional variable instantiations in a pbes expression.
void pbesinst_finite(pbes &p, data::rewrite_strategy rewrite_strategy, const std::string &finite_parameter_selection)
Apply finite instantiation to the given PBES.
void instantiate_global_variables(pbes &p)
Attempts to eliminate the free variables of a PBES, by substituting a constant value for them....
Definition pbes.cpp:65
bool is_normalized(const pbes &x)
Checks if a PBEs is normalized.
std::vector< propositional_variable > remove_unreachable_variables(pbes &p)
Removes equations that are not (syntactically) reachable from the initial state of a PBES.
std::string print_removed_equations(const std::vector< propositional_variable > &removed)
Print removed equations.
void normalize(pbes &x)
The function normalize brings (embedded) pbes expressions into positive normal form,...
std::map< core::identifier_string, std::vector< data::variable > > pbes_parameter_map
Data structure for storing the variables that should be expanded by the finite pbesinst algorithm.
void split_parameters(const PropositionalVariable &X, const pbesinst_index_map &index_map, std::vector< Parameter > &finite, std::vector< Parameter > &infinite)
Computes the subset with variables of finite sort and infinite.
pbes_parameter_map parse_pbes_parameter_map(const pbes &p, const std::string &text)
Parses parameter selection for finite pbesinst algorithm.
The main namespace for the PBES library.
std::map< core::identifier_string, std::vector< data::variable > > pbesinst_variable_map
Data structure for storing the variables that should be expanded by the finite pbesinst algorithm.
void pbesinst_finite(pbes &p, data::rewrite_strategy rewrite_strategy, const std::string &finite_parameter_selection)
std::map< core::identifier_string, std::vector< std::size_t > > pbesinst_index_map
Data structure for storing the indices of the variables that should be expanded by the finite pbesins...
A class that takes a linear process specification and checks all tau-summands of that LPS for conflue...
An empty struct that is used to denote the absence of a substitution. Used for rewriters.
Visitor that applies a propositional variable substitution to a pbes expression.
data::data_expression make_condition(const VariableContainer &variables, const ExpressionContainer &expressions) const
Computes the condition 'for all i: variables[i] == expressions[i]'.
void apply(T &result, const propositional_variable_instantiation &x)
data::data_expression_list rewrite_container(const DataExpressionContainer &v, const data::rewriter &rewr, const data::mutable_indexed_substitution<> &sigma)
std::string print_parameters(const std::vector< data::data_expression > &finite_parameters, const std::vector< data::data_expression > &infinite_parameters) const
propositional_variable_instantiation visit_initial_state(const propositional_variable_instantiation &init)
pbes_system::detail::data_rewriter_builder< pbesinst_finite_builder, DataRewriter, SubstitutionFunction > super
data::data_expression_list rewrite_container(const DataExpressionContainer &v, const data::rewriter &rewr)
pbesinst_finite_builder(const DataRewriter &R, SubstitutionFunction &sigma, const pbesinst_finite_rename &rho, const data::data_specification &data_spec, const pbesinst_index_map &index_map, const pbesinst_variable_map &variable_map)
Exception that is used to signal an empty parameter selection.
Function object for renaming a propositional variable instantiation.
core::identifier_string operator()(const core::identifier_string &name, const data::data_expression_list &parameters) const
Renames the propositional variable x.
std::unordered_map< propositional_variable_instantiation, core::identifier_string > m
core::identifier_string rename(const core::identifier_string &name, const data::data_expression_list &parameters) const
std::size_t operator()(const atermpp::detail::reference_aterm< T > &t) const