22 #include <spot/twa/acc.hh>
23 #include <spot/mc/unionfind.hh>
24 #include <spot/mc/intersect.hh>
25 #include <spot/mc/mc.hh>
26 #include <spot/misc/timer.hh>
27 #include <spot/twacube/twacube.hh>
28 #include <spot/twacube/fwd.hh>
38 template<
typename State,
typename SuccIterator,
39 typename StateHash,
typename StateEqual>
48 struct product_state_equal
51 operator()(
const product_state lhs,
52 const product_state rhs)
const
55 return (lhs.st_prop == rhs.st_prop) &&
56 equal(lhs.st_kripke, rhs.st_kripke);
60 struct product_state_hash
63 operator()(
const product_state that)
const noexcept
68 return wang32_hash(that.st_prop) ^ hasher(that.st_kripke);
91 std::atomic<bool>& stop)
92 : sys_(sys), twa_(
twa), tid_(tid), stop_(stop),
93 acc_(
twa->acc()), sccs_(0
U)
96 State, SuccIterator>::value,
97 "error: does not match the kripkecube requirements");
104 while (!todo.empty())
106 sys_.recycle(todo.back().it_kripke, tid_);
115 product_state initial = {sys_.initial(tid_), twa_->get_initial()};
116 if (SPOT_LIKELY(push_state(initial, dfs_number+1, {})))
118 todo.push_back({initial, sys_.succ(initial.st_kripke, tid_),
119 twa_->succ(initial.st_prop)});
122 if (todo.back().it_prop->done())
125 forward_iterators(sys_, twa_, todo.back().it_kripke,
126 todo.back().it_prop,
true, 0);
127 map[initial] = ++dfs_number;
129 while (!todo.empty() && !stop_.load(std::memory_order_relaxed))
133 if (todo.back().it_kripke->done())
135 bool is_init = todo.size() == 1;
136 auto newtop = is_init? todo.back().st: todo[todo.size() -2].st;
137 if (SPOT_LIKELY(pop_state(todo.back().st,
143 sys_.recycle(todo.back().it_kripke, tid_);
146 if (SPOT_UNLIKELY(found_))
158 todo.back().it_kripke->state(),
159 twa_->trans_storage(todo.back().it_prop, tid_).dst
161 auto acc = twa_->trans_data(todo.back().it_prop, tid_).acc_;
162 forward_iterators(sys_, twa_, todo.back().it_kripke,
163 todo.back().it_prop,
false, 0);
164 auto it = map.find(dst);
167 if (SPOT_LIKELY(push_state(dst, dfs_number+1, acc)))
169 map[dst] = ++dfs_number;
170 todo.push_back({dst, sys_.succ(dst.st_kripke, tid_),
171 twa_->succ(dst.st_prop)});
172 forward_iterators(sys_, twa_, todo.back().it_kripke,
173 todo.back().it_prop,
true, 0);
176 else if (SPOT_UNLIKELY(update(todo.back().st,
178 dst, map[dst], acc)))
192 tm_.start(
"DFS thread " + std::to_string(tid_));
199 roots_.push_back({dfsnum, cond, {}});
210 bool pop_state(product_state,
unsigned top_dfsnum,
bool,
211 product_state,
unsigned)
213 if (top_dfsnum == roots_.back().dfsnum)
217 uf_.markdead(top_dfsnum);
219 dfs_ = todo.size() > dfs_ ? todo.size() : dfs_;
228 product_state,
unsigned dst_dfsnum,
231 if (uf_.isdead(dst_dfsnum))
234 while (!uf_.sameset(dst_dfsnum, roots_.back().dfsnum))
236 auto& el = roots_.back();
238 uf_.unite(dst_dfsnum, el.dfsnum);
239 cond |= el.acc | el.ingoing;
241 roots_.back().acc |= cond;
242 found_ = acc_.accepting(roots_.back().acc);
243 if (SPOT_UNLIKELY(found_))
251 bool tst_val =
false;
253 bool exchanged = stop_.compare_exchange_strong(tst_val, new_val);
256 tm_.stop(
"DFS thread " + std::to_string(tid_));
280 return tm_.timer(
"DFS thread " + std::to_string(tid_)).walltime();
286 return "renault_lpar13";
305 std::string res =
"Prefix:\n";
309 res +=
" " + std::to_string(s.st.st_prop) +
310 +
"*" + sys_.to_string(s.st.st_kripke) +
"\n";
317 const product_state* prod_st;
318 ctrx_element* parent_st;
319 SuccIterator* it_kripke;
320 std::shared_ptr<trans_index> it_prop;
322 std::queue<ctrx_element*> bfs;
326 bfs.push(
new ctrx_element({&todo.back().st,
nullptr,
327 sys_.succ(todo.back().st.st_kripke, tid_),
328 twa_->succ(todo.back().st.st_prop)}));
332 auto* front = bfs.front();
335 while (!front->it_kripke->done())
337 while (!front->it_prop->done())
339 if (twa_->get_cubeset().intersect
340 (twa_->trans_data(front->it_prop, tid_).cube_,
341 front->it_kripke->condition()))
343 const product_state dst = {
344 front->it_kripke->state(),
345 twa_->trans_storage(front->it_prop).dst
349 auto it = map.find(dst);
350 if (it == map.end() ||
351 !uf_.sameset(it->second,
352 map[todo.back().st]))
354 front->it_prop->next();
361 auto mark = twa_->trans_data(front->it_prop,
365 ctrx_element* current = front;
366 while (current !=
nullptr)
370 std::to_string(current->prod_st->st_prop) +
372 sys_. to_string(current->prod_st->st_kripke) +
374 current = current->parent_st;
380 auto* e = bfs.front();
381 sys_.recycle(e->it_kripke, tid_);
385 sys_.recycle(front->it_kripke, tid_);
390 if (twa_->acc().accepting(acc))
395 const product_state* q = &(it->first);
396 ctrx_element* root =
new ctrx_element({
398 sys_.succ(q->st_kripke, tid_),
399 twa_->succ(q->st_prop)
406 const product_state* q = &(it->first);
407 ctrx_element* root =
new ctrx_element({
409 sys_.succ(q->st_kripke, tid_),
410 twa_->succ(q->st_prop)
414 front->it_prop->next();
416 front->it_prop->reset();
417 front->it_kripke->next();
419 sys_.recycle(front->it_kripke, tid_);
432 SuccIterator* it_kripke;
433 std::shared_ptr<trans_index> it_prop;
436 struct root_element {
438 acc_cond::mark_t ingoing;
439 acc_cond::mark_t acc;
442 typedef std::unordered_map<
const product_state, int,
444 product_state_equal> visited_map;
446 kripkecube<State, SuccIterator>& sys_;
448 std::vector<todo_element> todo;
450 unsigned int dfs_number = 0;
451 unsigned int trans_ = 0;
453 std::atomic<bool>& stop_;
455 std::vector<root_element> roots_;
461 bool finisher_ =
false;
This class allows to ensure (at compile time) if a given parameter is of type kripkecube....
Definition: kripke.hh:71
This class is a template representation of a Kripke structure. It is composed of two template paramet...
Definition: kripke.hh:40
This class implements the sequential emptiness check as presented in "Three SCC-based Emptiness Check...
Definition: lpar13.hh:41
bool run()
Run the algorithm.
Definition: lpar13.hh:112
bool update(product_state, unsigned, product_state, unsigned dst_dfsnum, acc_cond::mark_t cond)
This method is called for every closing, back, or forward edge.
Definition: lpar13.hh:227
unsigned int transitions()
Return number of transitions traversed.
Definition: lpar13.hh:272
mc_rvalue result()
Return emptiness check result.
Definition: lpar13.hh:296
bool push_state(product_state, unsigned dfsnum, acc_cond::mark_t cond)
Push product state to stack.
Definition: lpar13.hh:196
unsigned int states()
Return number of states visited.
Definition: lpar13.hh:266
int shared_map
Type alias for shared map (useless for sequential algorithm)
Definition: lpar13.hh:75
int sccs()
Return number of SCCs found.
Definition: lpar13.hh:290
bool finisher()
Check if this thread finished the search.
Definition: lpar13.hh:260
void setup()
Setup thread resources.
Definition: lpar13.hh:190
bool pop_state(product_state, unsigned top_dfsnum, bool, product_state, unsigned)
This method is called to notify the emptiness checks that a state will be popped. If the method retur...
Definition: lpar13.hh:210
void finalize()
Finalize thread resources.
Definition: lpar13.hh:249
unsigned walltime()
Return wall time in milliseconds.
Definition: lpar13.hh:278
int shared_struct
Type alias for shared structure (useless here)
Definition: lpar13.hh:77
std::string name()
Return algorithm name.
Definition: lpar13.hh:284
std::string trace()
Return trace.
Definition: lpar13.hh:302
static shared_struct * make_shared_structure(shared_map m, unsigned i)
Create shared structure for thread tid.
Definition: lpar13.hh:80
virtual ~lpar13()
Destructor.
Definition: lpar13.hh:101
lpar13(kripkecube< State, SuccIterator > &sys, twacube_ptr twa, shared_map &map, shared_struct *, unsigned tid, std::atomic< bool > &stop)
Constructor for LPAR13 emptiness check.
Definition: lpar13.hh:86
A map of timer, where each timer has a name.
Definition: timer.hh:231
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
std::shared_ptr< twacube > twacube_ptr
Definition: fwd.hh:25
Definition: automata.hh:26
mc_rvalue
Return value of a parallel model-checking algorithm.
Definition: mc.hh:50
@ NOT_EMPTY
The product is not empty.
@ EMPTY
The product is empty.
An acceptance mark.
Definition: acc.hh:76