spot  2.16
utils.hh
1 // -*- coding: utf-8 -*-
2 // Copyright (C) by the Spot authors, see the AUTHORS file for details.
3 //
4 // This file is part of Spot, a model checking library.
5 //
6 // Spot is free software; you can redistribute it and/or modify it
7 // under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 3 of the License, or
9 // (at your option) any later version.
10 //
11 // Spot is distributed in the hope that it will be useful, but WITHOUT
12 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 // License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program. If not, see <http://www.gnu.org/licenses/>.
18 
19 #pragma once
20 
21 #include <spot/mc/intersect.hh>
22 #include <spot/twa/twa.hh>
23 #include <spot/twacube_algos/convert.hh>
24 
25 namespace spot
26 {
30  template<typename State, typename SuccIterator,
31  typename StateHash, typename StateEqual>
32  class SPOT_API kripkecube_to_twa
33  {
34  public:
35 
38  sys_(sys), dict_(dict)
39  {
40  static_assert(spot::is_a_kripkecube_ptr<decltype(&sys),
41  State, SuccIterator>::value,
42  "error: does not match the kripkecube requirements");
43  }
44 
47  {
48  visited_.clear();
49  }
50 
52  void run()
53  {
54  setup();
55  State initial = sys_.initial(0);
56  if (SPOT_LIKELY(push(initial, dfs_number_+1)))
57  {
58  visited_[initial] = dfs_number_++;
59  todo_.push_back({initial, sys_.succ(initial, 0)});
60  }
61  while (!todo_.empty())
62  {
63  if (todo_.back().it->done())
64  {
65  if (SPOT_LIKELY(pop(todo_.back().s)))
66  {
67  sys_.recycle(todo_.back().it, 0);
68  todo_.pop_back();
69  }
70  }
71  else
72  {
73  ++transitions_;
74  State dst = todo_.back().it->state();
75  auto it = visited_.find(dst);
76  if (it == visited_.end())
77  {
78  if (SPOT_LIKELY(push(dst, dfs_number_+1)))
79  {
80  visited_[dst] = dfs_number_++;
81  todo_.back().it->next();
82  todo_.push_back({dst, sys_.succ(dst, 0)});
83  }
84  }
85  else
86  {
87  edge(visited_[todo_.back().s], visited_[dst]);
88  todo_.back().it->next();
89  }
90  }
91  }
92  finalize();
93  }
94 
96  void setup()
97  {
98  auto d = spot::make_bdd_dict();
99  res_ = make_twa_graph(d);
100  names_ = new std::vector<std::string>();
101 
102  int i = 0;
103  for (auto ap : sys_.ap())
104  {
105  auto idx = res_->register_ap(ap);
106  reverse_binder_[i++] = idx;
107  }
108  }
109 
111  bool push(State s, unsigned i)
112  {
113 
114  unsigned st = res_->new_state();
115  names_->push_back(sys_.to_string(s));
116  if (!todo_.empty())
117  {
118  edge(visited_[todo_.back().s], st);
119  }
120 
121  SPOT_ASSERT(st+1 == i);
122  return true;
123  }
124 
126  bool pop(State)
127  {
128  return true;
129  }
130 
132  void edge(unsigned src, unsigned dst)
133  {
134  cubeset cs(sys_.ap().size());
135  bdd cond = cube_to_bdd(todo_.back().it->condition(),
136  cs, reverse_binder_);
137  res_->new_edge(src, dst, cond);
138  }
139 
141  void finalize()
142  {
143  res_->purge_unreachable_states();
144  res_->set_named_prop<std::vector<std::string>>("state-names", names_);
145  }
146 
149  {
150  return res_;
151  }
152 
153  protected:
156  {
158  State s;
160  SuccIterator* it;
161  };
162 
164  typedef std::unordered_map<const State, int,
165  StateHash, StateEqual> visited__map;
166 
170  std::vector<todo__element> todo_;
174  unsigned int dfs_number_ = 0;
176  unsigned int transitions_ = 0;
180  std::vector<std::string>* names_;
184  std::unordered_map<int, int> reverse_binder_;
185  };
186 
190  template<typename State, typename SuccIterator,
191  typename StateHash, typename StateEqual>
192  class SPOT_API product_to_twa
193  {
194  struct product_state
195  {
196  State st_kripke;
197  unsigned st_prop;
198  };
199 
200  struct product_state_equal
201  {
202  bool
203  operator()(const product_state lhs,
204  const product_state rhs) const
205  {
206  StateEqual equal;
207  return (lhs.st_prop == rhs.st_prop) &&
208  equal(lhs.st_kripke, rhs.st_kripke);
209  }
210  };
211 
212  struct product_state_hash
213  {
214  size_t
215  operator()(const product_state lhs) const noexcept
216  {
217  StateHash hash;
218  unsigned u = hash(lhs.st_kripke) % (1<<30);
219  u = wang32_hash(lhs.st_prop) ^ u;
220  u = u % (1<<30);
221  return u;
222  }
223  };
224 
225  public:
228  twacube_ptr twa):
229  sys_(sys), twa_(twa)
230  {
231  static_assert(spot::is_a_kripkecube_ptr<decltype(&sys),
232  State, SuccIterator>::value,
233  "error: does not match the kripkecube requirements");
234  }
235 
237  virtual ~product_to_twa()
238  {
239  map.clear();
240  }
241 
243  bool run()
244  {
245  setup();
246  product_state initial = {sys_.initial(0), twa_->get_initial()};
247  if (SPOT_LIKELY(push_state(initial, dfs_number_+1, {})))
248  {
249  todo_.push_back({initial, sys_.succ(initial.st_kripke, 0),
250  twa_->succ(initial.st_prop)});
251 
252  // Not going further! It's a product with a single state.
253  if (todo_.back().it_prop->done())
254  return false;
255 
256  forward_iterators(sys_, twa_, todo_.back().it_kripke,
257  todo_.back().it_prop, true, 0);
258  map[initial] = ++dfs_number_;
259  }
260  while (!todo_.empty())
261  {
262  // Check the kripke is enough since it's the outer loop. More
263  // details in forward_iterators.
264  if (todo_.back().it_kripke->done())
265  {
266  bool is_init = todo_.size() == 1;
267  auto newtop = is_init? todo_.back().st: todo_[todo_.size() -2].st;
268  if (SPOT_LIKELY(pop_state(todo_.back().st,
269  map[todo_.back().st],
270  is_init,
271  newtop,
272  map[newtop])))
273  {
274  sys_.recycle(todo_.back().it_kripke, 0);
275  todo_.pop_back();
276  }
277  }
278  else
279  {
280  ++transitions_;
281  product_state dst = {
282  todo_.back().it_kripke->state(),
283  twa_->trans_storage(todo_.back().it_prop, 0).dst
284  };
285  auto acc = twa_->trans_data(todo_.back().it_prop, 0).acc_;
286  forward_iterators(sys_, twa_, todo_.back().it_kripke,
287  todo_.back().it_prop, false, 0);
288  auto it = map.find(dst);
289  if (it == map.end())
290  {
291  if (SPOT_LIKELY(push_state(dst, dfs_number_+1, acc)))
292  {
293  map[dst] = ++dfs_number_;
294  todo_.push_back({dst, sys_.succ(dst.st_kripke, 0),
295  twa_->succ(dst.st_prop)});
296  forward_iterators(sys_, twa_, todo_.back().it_kripke,
297  todo_.back().it_prop, true, 0);
298  }
299  }
300  else if (SPOT_UNLIKELY(update(todo_.back().st, dfs_number_,
301  dst, map[dst], acc)))
302  return true;
303  }
304  }
305  return false;
306  }
307 
310  {
311  res_->purge_unreachable_states();
312  res_->set_named_prop<std::vector<std::string>>("state-names", names_);
313  return res_;
314  }
315 
317  void setup()
318  {
319  auto d = spot::make_bdd_dict();
320  res_ = make_twa_graph(d);
321  names_ = new std::vector<std::string>();
322 
323  int i = 0;
324  for (auto ap : sys_.ap())
325  {
326  auto idx = res_->register_ap(ap);
327  reverse_binder_[i++] = idx;
328  }
329  }
330 
332  bool push_state(product_state s, unsigned i, acc_cond::mark_t)
333  {
334  unsigned st = res_->new_state();
335 
336  if (!todo_.empty())
337  {
338  auto c = twa_->get_cubeset()
339  .intersection(twa_->trans_data
340  (todo_.back().it_prop).cube_,
341  todo_.back().it_kripke->condition());
342 
343  bdd x = spot::cube_to_bdd(c, twa_->get_cubeset(),
344  reverse_binder_);
345  twa_->get_cubeset().release(c);
346  res_->new_edge(map[todo_.back().st]-1, st, x,
347  twa_->trans_data
348  (todo_.back().it_prop).acc_);
349  }
350 
351 
352  names_->push_back(sys_.to_string(s.st_kripke) +
353  ('*' + std::to_string(s.st_prop)));
354  SPOT_ASSERT(st+1 == i);
355  return true;
356  }
357 
359  bool update(product_state, unsigned src,
360  product_state, unsigned dst,
361  acc_cond::mark_t cond)
362  {
363  auto c = twa_->get_cubeset()
364  .intersection(twa_->trans_data
365  (todo_.back().it_prop).cube_,
366  todo_.back().it_kripke->condition());
367 
368  bdd x = spot::cube_to_bdd(c, twa_->get_cubeset(),
369  reverse_binder_);
370  twa_->get_cubeset().release(c);
371  res_->new_edge(src-1, dst-1, x, cond);
372  return false;
373  }
374 
376  bool pop_state(product_state, unsigned, bool, product_state, unsigned)
377  {
378  return true;
379  }
380 
381  private:
383  struct todo__element
384  {
385  product_state st;
386  SuccIterator* it_kripke;
387  std::shared_ptr<trans_index> it_prop;
388  };
389 
391  typedef std::unordered_map<const product_state, int,
392  product_state_hash,
393  product_state_equal> visited_map;
394 
396  kripkecube<State, SuccIterator>& sys_;
398  twacube_ptr twa_;
400  std::vector<todo__element> todo_;
402  visited_map map;
404  unsigned int dfs_number_ = 0;
406  unsigned int transitions_ = 0;
408  spot::twa_graph_ptr res_;
410  std::vector<std::string>* names_;
412  std::unordered_map<int, int> reverse_binder_;
413  };
414 }
Manager for allocating and manipulating cubes (bit-encoded partial assignments over APs).
Definition: cube.hh:72
This class allows to ensure (at compile time) if a given parameter is of type kripkecube....
Definition: kripke.hh:71
Convert a (cube) model into a twa. Note that this algorithm cannot be run in parallel but could.
Definition: utils.hh:33
void run()
Run the conversion algorithm.
Definition: utils.hh:52
kripkecube< State, SuccIterator > & sys_
Reference to system model.
Definition: utils.hh:168
~kripkecube_to_twa()
Destructor.
Definition: utils.hh:46
kripkecube_to_twa(kripkecube< State, SuccIterator > &sys, bdd_dict_ptr dict)
Constructor for kripkecube-to-twa conversion.
Definition: utils.hh:37
bool push(State s, unsigned i)
Push state to stack.
Definition: utils.hh:111
spot::twa_graph_ptr res_
Result twa.
Definition: utils.hh:178
visited__map visited_
Visited states map.
Definition: utils.hh:172
std::vector< todo__element > todo_
DFS todo stack.
Definition: utils.hh:170
bool pop(State)
Pop state from stack.
Definition: utils.hh:126
void finalize()
Finalize the result twa.
Definition: utils.hh:141
twa_graph_ptr twa()
Return the resulting twa.
Definition: utils.hh:148
void edge(unsigned src, unsigned dst)
Add edge from src to dst.
Definition: utils.hh:132
std::vector< std::string > * names_
State names.
Definition: utils.hh:180
std::unordered_map< int, int > reverse_binder_
Reverse binding for APs.
Definition: utils.hh:184
std::unordered_map< const State, int, StateHash, StateEqual > visited__map
Type alias for visited map.
Definition: utils.hh:165
bdd_dict_ptr dict_
BDD dictionary.
Definition: utils.hh:182
void setup()
Setup algorithm resources.
Definition: utils.hh:96
This class is a template representation of a Kripke structure. It is composed of two template paramet...
Definition: kripke.hh:40
Convert a (cube) product automaton into a twa Note that this algorithm cannot be run in parallel.
Definition: utils.hh:193
bool push_state(product_state s, unsigned i, acc_cond::mark_t)
Push product state to stack.
Definition: utils.hh:332
bool update(product_state, unsigned src, product_state, unsigned dst, acc_cond::mark_t cond)
Update state with acceptance condition.
Definition: utils.hh:359
virtual ~product_to_twa()
Destructor.
Definition: utils.hh:237
product_to_twa(kripkecube< State, SuccIterator > &sys, twacube_ptr twa)
Constructor for product-to-twa conversion.
Definition: utils.hh:227
bool pop_state(product_state, unsigned, bool, product_state, unsigned)
Pop state from stack.
Definition: utils.hh:376
bool run()
Run the conversion algorithm.
Definition: utils.hh:243
twa_graph_ptr twa()
Return the resulting twa.
Definition: utils.hh:309
void setup()
Setup algorithm resources.
Definition: utils.hh:317
A Transition-based ω-Automaton.
Definition: twa.hh:648
size_t wang32_hash(size_t key)
Thomas Wang's 32 bit hash function.
Definition: hashfunc.hh:37
@ ap
Atomic proposition.
bdd_dict_ptr make_bdd_dict()
Create a new, empty bdd_dict wrapped in a shared pointer.
Definition: bdddict.hh:308
std::shared_ptr< bdd_dict > bdd_dict_ptr
Shared pointer to a bdd_dict.
Definition: bdddict.hh:304
std::shared_ptr< twa_graph > twa_graph_ptr
Shared pointer to a mutable twa_graph.
Definition: fwd.hh:44
twa_graph_ptr make_twa_graph(const bdd_dict_ptr &dict)
Build an explicit automaton from all states of aut,.
Definition: twagraph.hh:865
bdd cube_to_bdd(spot::cube cube, const cubeset &cubeset, std::unordered_map< int, int > &reverse_binder)
Transform a cube cube into a BDD using the map that binds cube indexes to BDD indexes.
std::shared_ptr< twacube > twacube_ptr
Definition: fwd.hh:25
Definition: automata.hh:26
An acceptance mark.
Definition: acc.hh:76
DFS stack element pairing a state its with successor iterator.
Definition: utils.hh:156
SuccIterator * it
Iterator over successors.
Definition: utils.hh:160
State s
State.
Definition: utils.hh:158

Please direct any question, comment, or bug report to the Spot mailing list at spot@lrde.epita.fr.
Generated on Fri Feb 27 2015 10:00:07 for spot by doxygen 1.9.1