mCRL2
Loading...
Searching...
No Matches
small_progress_measures.h
Go to the documentation of this file.
1// Author(s): Wieger Wesselink
2// Copyright: see the accompanying file COPYING or copy at
3// https://github.com/mCRL2org/mCRL2/blob/master/COPYING
4//
5// Distributed under the Boost Software License, Version 1.0.
6// (See accompanying file LICENSE_1_0.txt or copy at
7// http://www.boost.org/LICENSE_1_0.txt)
8//
9/// \file mcrl2/pbes/small_progress_measures.h
10/// \brief add your file description here.
11
12#ifndef MCRL2_BES_SMALL_PROGRESS_MEASURES_H
13#define MCRL2_BES_SMALL_PROGRESS_MEASURES_H
14
15// TODO: Make it possible to undefine this flag
16#define MCRL2_SMALL_PROGRESS_MEASURES_DEBUG
17
18#include <iomanip>
19#include "mcrl2/core/detail/print_utility.h"
20#include "mcrl2/pbes/find.h"
21#include "mcrl2/pbes/normal_forms.h"
22#include "mcrl2/pbes/print.h"
23#include "mcrl2/utilities/math.h"
24
25namespace mcrl2::pbes_system
26{
27
28template <typename InputIterator1, typename InputIterator2>
29int lexicographical_compare_3way(InputIterator1 first1, InputIterator1 last1,
30 InputIterator2 first2, InputIterator2 last2)
31{
32 while (first1 != last1 && first2 != last2)
33 {
34 if (*first1 < *first2)
35 {
36 return -1;
37 }
38 if (*first2 < *first1)
39 {
40 return 1;
41 }
42 ++first1;
43 ++first2;
44 }
45 if (first2 == last2)
46 {
47 return !(first1 == last1);
48 }
49 else
50 {
51 return -1;
52 }
53}
54
55inline
57{
58 return is_or(x);
59}
60
61inline
62int maximum_rank(const pbes& b)
63{
64 int result = 0;
65 fixpoint_symbol last_symbol;
66 for (auto i = b.equations().begin(); i != b.equations().end(); ++i)
67 {
68 if (i == b.equations().begin())
69 {
70 result = i->symbol().is_nu() ? 0 : 1;
71 }
72 else if (i->symbol() != last_symbol)
73 {
74 result++;
75 }
76 last_symbol = i->symbol();
77 }
78 return result;
79}
80
82{
83 explicit progress_measure(std::size_t d)
84 : v(d, 0)
85 {}
86
87 // N.B. The special value top is represented by alpha[0] == -1
88 std::vector<int> v;
89
90 bool is_top() const
91 {
92 return v[0] == -1;
93 }
94};
95
96inline
98{
99 if (pm.is_top())
100 {
101 out << "top";
102 }
103 else
104 {
105 out << core::detail::print_list(pm.v);
106 }
107 return out;
108}
109
110// increment position m of vector alpha
111inline
112void inc(std::vector<int>& alpha, int m, const std::vector<int>& beta)
113{
114 if (alpha[0] == -1)
115 {
116 return;
117 }
118 else if (m == -1)
119 {
120 alpha[0] = -1;
121 return;
122 }
123 else if (alpha[m] == beta[m])
124 {
125 alpha[m] = 0;
126 inc(alpha, m - 1, beta);
127 }
128 else
129 {
130 alpha[m]++;
131 }
132}
133
134/// \brief Vertex of the progress measures graph
136{
137 explicit progress_measures_vertex(bool even_ = false, int rank_ = 0, unsigned int d = 1)
138 : even(even_),
139 rank(rank_),
140 alpha(d)
141 {}
142
144 bool even;
145 int rank;
147
150#endif
151};
152
153// compare the positions with index in [0, ... ,m]
155{
156 unsigned int m;
157
158 explicit compare_progress_measures_vertex(unsigned int m_)
159 : m(m_)
160 {}
161
162 bool operator()(const progress_measures_vertex* x, const progress_measures_vertex* y) const
163 {
164 if (x->alpha.is_top())
165 {
166 return false;
167 }
168 else if (y->alpha.is_top())
169 {
170 return true;
171 }
172 int n = lexicographical_compare_3way(x->alpha.v.begin(), x->alpha.v.begin() + m + 1, y->alpha.v.begin(), y->alpha.v.begin() + m + 1);
173 return n < 0;
174 }
175};
176
177inline
179{
180 out << " alpha = " << v.alpha;
181 out << " successors = {";
182 for (auto i = v.successors.begin(); i != v.successors.end(); ++i)
183 {
184 if (i != v.successors.begin())
185 {
186 out << ", ";
187 }
188 out << std::string((*i)->name);
189 }
190 out << "}";
191 out << " rank = " << v.rank;
192 out << " disjunctive = " << std::boolalpha << v.even;
193 return out;
194}
195
196/// \brief Algorithm class for the small progress measures algorithm
198{
199 protected:
202
204 {
205 // first build the vertex map without successor information
207 unsigned int block_size = 0;
208 int last_rank = 0;
210 for (const pbes_equation& eqn: m_bes.equations())
211 {
212 if (eqn.symbol() != last_symbol)
213 {
214 if (utilities::is_even(m_beta.size()))
215 {
216 m_beta.push_back(0);
217 }
218 else
219 {
220 m_beta.push_back(static_cast<int>(block_size));
221 }
222 block_size = 0;
223 last_rank++;
224 last_symbol = eqn.symbol();
225 }
226 block_size++;
227 m_vertices[propositional_variable_instantiation(eqn.variable().name())] = vertex(is_disjunctive(eqn.formula()), last_rank, m_d);
228 }
229 if (utilities::is_even(m_beta.size()))
230 {
231 m_beta.push_back(0);
232 }
233 else
234 {
235 m_beta.push_back(static_cast<int>(block_size));
236 }
237
238 // add successor information
239 for (const pbes_equation& eqn: m_bes.equations())
240 {
241 std::set<propositional_variable_instantiation> succ = pbes_system::find_propositional_variable_instantiations(eqn.formula());
242 auto k = m_vertices.find(propositional_variable_instantiation(eqn.variable().name()));
243 std::vector<vertex*>& k_successors = k->second.successors;
244 for (const propositional_variable_instantiation& v: succ)
245 {
246 k_successors.push_back(&m_vertices[v]);
247 }
248
250 k->second.name = std::string(eqn.variable().name());
251#endif
252 }
253 }
254
256 {
257 std::ostringstream out;
258 for (const pbes_equation& eqn: m_bes.equations())
259 {
260 const vertex& v = m_vertices.find(propositional_variable_instantiation(eqn.variable().name()))->second;
261 out << v.name << " " << v << std::endl;
262 }
263 return out.str();
264 }
265
267 {
268 std::ostringstream out;
269 out << v.name << " (alpha = " << v.alpha << ", rank = " << v.rank << ")";
270 return out.str();
271 }
272
273 /// \brief Logs the neighbors of a vertex
275 {
276 std::ostringstream out;
277 for (progress_measures_vertex* successor: v.successors)
278 {
279 out << "\n " << print_vertex(*successor);
280 }
281 return out.str();
282 }
283
285 int m_d = 0;
286 const pbes& m_bes;
288
289 public:
291 : m_bes(b)
292 {}
293
294 bool run(const propositional_variable_instantiation& first_variable)
295 {
296 mCRL2log(log::verbose) << "Applying small progress measures.\n";
297 mCRL2log(log::debug) << "BES " << pbes_system::pp(m_bes) << "\n\n";
299 mCRL2log(log::debug) << "--- vertices ---\n" << print_vertices();
300 mCRL2log(log::debug) << "\nbeta = " << core::detail::print_list(m_beta) << "\n";
301 for (;;) // forever
302 {
303 bool changed = false;
304 for (auto &i: m_vertices)
305 {
306 vertex& v = i.second;
307 mCRL2log(log::debug) << "\nchoose vertex " << print_vertex(v);
308 int m = v.rank;
309 std::vector<progress_measures_vertex*>::const_iterator j;
310 mCRL2log(log::debug) << "\n neighbors:" << print_neighbors(v);
311 if (v.even)
312 {
313 j = std::min_element(v.successors.begin(), v.successors.end(), compare_progress_measures_vertex(m));
314 mCRL2log(log::debug) << "\n minimum neighbor " << print_vertex(**j);
315 }
316 else
317 {
318 j = std::max_element(v.successors.begin(), v.successors.end(), compare_progress_measures_vertex(m));
319 mCRL2log(log::debug) << "\n maximum neighbor " << print_vertex(**j);
320 }
321 std::vector<int> alpha(m_d, 0);
322 const progress_measures_vertex& w = **j;
323 std::copy(w.alpha.v.begin(), w.alpha.v.begin() + m + 1, alpha.begin());
324 if (utilities::is_odd(m))
325 {
326 mCRL2log(log::debug) << "\n inc(" << core::detail::print_list(alpha) << ", " << std::to_string(m) << ") = ";
327 inc(alpha, m, m_beta);
328 mCRL2log(log::debug) << (alpha[0] < 0 ? "top" : core::detail::print_list(alpha));
329 }
330
331 if (!std::equal(alpha.begin(), alpha.end(), v.alpha.v.begin()))
332 {
333 changed = true;
334 v.alpha.v = alpha;
335 mCRL2log(log::debug) << "\nupdate vertex " << print_vertex(v);
336 }
337 }
338 if (!changed)
339 {
340 break;
341 }
342 }
343 mCRL2log(log::debug) << "\n--- vertices ---\n" << print_vertices();
344 return !m_vertices[first_variable].alpha.is_top();
345 }
346};
347
348inline
350{
351 propositional_variable_instantiation first(b.equations().front().variable().name());
352 assert(b.equations().front().variable().parameters().empty());
355 return algorithm.run(first);
356}
357
358} // namespace mcrl2::pbes_system
359
360#endif // MCRL2_BES_SMALL_PROGRESS_MEASURES_H
static fixpoint_symbol nu()
Returns the nu symbol.
parameterized boolean equation system
Definition pbes.h:54
\brief A propositional variable instantiation
Algorithm class for the small progress measures algorithm.
bool run(const propositional_variable_instantiation &first_variable)
std::string print_neighbors(const progress_measures_vertex &v) const
Logs the neighbors of a vertex.
#define mCRL2log(LEVEL)
mCRL2log(LEVEL) provides the stream used to log.
Definition logger.h:393
int lexicographical_compare_3way(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2)
bool is_or(const atermpp::aterm &x)
int maximum_rank(const pbes &b)
bool is_disjunctive(const pbes_expression &x)
void inc(std::vector< int > &alpha, int m, const std::vector< int > &beta)
std::ostream & operator<<(std::ostream &out, const progress_measures_vertex &v)
std::ostream & operator<<(std::ostream &out, const progress_measure &pm)
bool small_progress_measures(pbes &b)
void make_standard_form(pbes &eqn, bool recursive_form=false)
Transforms a PBES into standard form.
#define MCRL2_SMALL_PROGRESS_MEASURES_DEBUG
bool operator()(const progress_measures_vertex *x, const progress_measures_vertex *y) const