spot 2.16
Loading...
Searching...
No Matches
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
25namespace 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:
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
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;
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:28
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.8