swarming: add support everywhere

Swarming implies that a single instance of the kripke
structure (or product) will be explored by diffrent threads
with their own exploration order. Most of the modification
aims to have a thread safe kripke structure.

* spot/kripke/kripke.hh, spot/ltsmin/ltsmin.cc,
spot/ltsmin/ltsmin.hh, spot/mc/ec.hh,
spot/mc/intersect.hh, spot/mc/reachability.hh,
spot/misc/hash.hh, spot/twacube/twacube.hh,
tests/core/twacube.test, tests/ltsmin/modelcheck.cc: here.
This commit is contained in:
Etienne Renault 2016-10-27 12:03:14 +02:00
parent ae1a3601e6
commit 72948661e9
10 changed files with 248 additions and 119 deletions

View file

@ -45,10 +45,10 @@ namespace spot
public:
ec_renault13lpar(kripkecube<State, SuccIterator>& sys,
twacube_ptr twa)
twacube_ptr twa, unsigned tid, bool stop)
: intersect<State, SuccIterator, StateHash, StateEqual,
ec_renault13lpar<State, SuccIterator,
StateHash, StateEqual>>(sys, twa),
StateHash, StateEqual>>(sys, twa, tid, stop),
acc_(twa->acc()), sccs_(0U)
{
}
@ -114,6 +114,8 @@ namespace spot
}
roots_.back().acc |= cond;
found_ = acc_.accepting(roots_.back().acc);
if (SPOT_UNLIKELY(found_))
this->stop_ = true;
return found_;
}
@ -147,7 +149,7 @@ namespace spot
acc_cond::mark_t acc = 0U;
bfs.push(new ctrx_element({&this->todo.back().st, nullptr,
this->sys_.succ(this->todo.back().st.st_kripke),
this->sys_.succ(this->todo.back().st.st_kripke, this->tid_),
this->twa_->succ(this->todo.back().st.st_prop)}));
while (true)
{
@ -160,7 +162,7 @@ namespace spot
while (!front->it_prop->done())
{
if (this->twa_->get_cubeset().intersect
(this->twa_->trans_data(front->it_prop).cube_,
(this->twa_->trans_data(front->it_prop, this->tid_).cube_,
front->it_kripke->condition()))
{
const product_state dst = {
@ -181,7 +183,8 @@ namespace spot
// This is a valid transition. If this transition
// is the one we are looking for, update the counter-
// -example and flush the bfs queue.
auto mark = this->twa_->trans_data(front->it_prop).acc_;
auto mark = this->twa_->trans_data(front->it_prop,
this->tid_).acc_;
if (!acc.has(mark))
{
ctrx_element* current = front;
@ -213,7 +216,7 @@ namespace spot
const product_state* q = &(it->first);
ctrx_element* root = new ctrx_element({
q , nullptr,
this->sys_.succ(q->st_kripke),
this->sys_.succ(q->st_kripke, this->tid_),
this->twa_->succ(q->st_prop)
});
bfs.push(root);
@ -224,7 +227,7 @@ namespace spot
const product_state* q = &(it->first);
ctrx_element* root = new ctrx_element({
q , nullptr,
this->sys_.succ(q->st_kripke),
this->sys_.succ(q->st_kripke, this->tid_),
this->twa_->succ(q->st_prop)
});
bfs.push(root);
@ -243,7 +246,7 @@ namespace spot
virtual istats stats() override
{
return {this->states(), this->trans(), sccs_,
(unsigned)roots_.size(), dfs_};
(unsigned) roots_.size(), dfs_, found_};
}
private:

View file

@ -34,6 +34,7 @@ namespace spot
unsigned sccs;
unsigned instack_sccs;
unsigned instack_item;
bool is_empty;
};
/// \brief This class explores (with a DFS) a product between a
@ -59,8 +60,8 @@ namespace spot
{
public:
intersect(kripkecube<State, SuccIterator>& sys,
twacube_ptr twa):
sys_(sys), twa_(twa)
twacube_ptr twa, unsigned tid, bool& stop):
sys_(sys), twa_(twa), tid_(tid), stop_(stop)
{
SPOT_ASSERT(is_a_kripkecube(sys));
map.reserve(2000000);
@ -87,10 +88,10 @@ namespace spot
bool run()
{
self().setup();
product_state initial = {sys_.initial(), twa_->get_initial()};
product_state initial = {sys_.initial(tid_), twa_->get_initial()};
if (SPOT_LIKELY(self().push_state(initial, dfs_number+1, 0U)))
{
todo.push_back({initial, sys_.succ(initial.st_kripke),
todo.push_back({initial, sys_.succ(initial.st_kripke, tid_),
twa_->succ(initial.st_prop)});
// Not going further! It's a product with a single state.
@ -100,7 +101,7 @@ namespace spot
forward_iterators(true);
map[initial] = ++dfs_number;
}
while (!todo.empty())
while (!todo.empty() && !stop_)
{
// Check the kripke is enough since it's the outer loop. More
// details in forward_iterators.
@ -113,8 +114,8 @@ namespace spot
is_init,
newtop,
map[newtop])))
{
sys_.recycle(todo.back().it_kripke);
{
sys_.recycle(todo.back().it_kripke, tid_);
// FIXME a local storage for twacube iterator?
todo.pop_back();
if (SPOT_UNLIKELY(self().counterexample_found()))
@ -126,9 +127,9 @@ namespace spot
++transitions;
product_state dst = {
todo.back().it_kripke->state(),
twa_->trans_storage(todo.back().it_prop).dst
twa_->trans_storage(todo.back().it_prop, tid_).dst
};
auto acc = twa_->trans_data(todo.back().it_prop).acc_;
auto acc = twa_->trans_data(todo.back().it_prop, tid_).acc_;
forward_iterators(false);
auto it = map.find(dst);
if (it == map.end())
@ -136,7 +137,7 @@ namespace spot
if (SPOT_LIKELY(self().push_state(dst, dfs_number+1, acc)))
{
map[dst] = ++dfs_number;
todo.push_back({dst, sys_.succ(dst.st_kripke),
todo.push_back({dst, sys_.succ(dst.st_kripke, tid_),
twa_->succ(dst.st_prop)});
forward_iterators(true);
}
@ -167,7 +168,7 @@ namespace spot
virtual istats stats()
{
return {dfs_number, transitions, 0U, 0U, 0U};
return {dfs_number, transitions, 0U, 0U, 0U, false};
}
protected:
@ -190,7 +191,7 @@ namespace spot
// There is no need to move iterators forward.
SPOT_ASSERT(!(todo.back().it_prop->done()));
if (just_pushed && twa_->get_cubeset()
.intersect(twa_->trans_data(todo.back().it_prop).cube_,
.intersect(twa_->trans_data(todo.back().it_prop, tid_).cube_,
todo.back().it_kripke->condition()))
return;
@ -207,7 +208,7 @@ namespace spot
while (!todo.back().it_prop->done())
{
if (SPOT_UNLIKELY(twa_->get_cubeset()
.intersect(twa_->trans_data(todo.back().it_prop).cube_,
.intersect(twa_->trans_data(todo.back().it_prop, tid_).cube_,
todo.back().it_kripke->condition())))
return;
todo.back().it_prop->next();
@ -263,5 +264,7 @@ namespace spot
visited_map map;
unsigned int dfs_number = 0;
unsigned int transitions = 0;
unsigned tid_;
bool& stop_; // Do not need to be atomic.
};
}

View file

@ -32,8 +32,8 @@ namespace spot
class SPOT_API seq_reach_kripke
{
public:
seq_reach_kripke(kripkecube<State, SuccIterator>& sys):
sys_(sys)
seq_reach_kripke(kripkecube<State, SuccIterator>& sys, unsigned tid):
sys_(sys), tid_(tid)
{
SPOT_ASSERT(is_a_kripkecube(sys));
visited.reserve(2000000);
@ -54,15 +54,15 @@ namespace spot
void run()
{
self().setup();
State initial = sys_.initial();
todo.push_back({initial, sys_.succ(initial)});
State initial = sys_.initial(tid_);
todo.push_back({initial, sys_.succ(initial, tid_)});
visited[initial] = ++dfs_number;
self().push(initial, dfs_number);
while (!todo.empty())
{
if (todo.back().it->done())
{
sys_.recycle(todo.back().it);
sys_.recycle(todo.back().it, tid_);
todo.pop_back();
}
else
@ -76,7 +76,7 @@ namespace spot
self().push(dst, dfs_number);
self().edge(visited[todo.back().s], dfs_number);
todo.back().it->next();
todo.push_back({dst, sys_.succ(dst)});
todo.push_back({dst, sys_.succ(dst, tid_)});
}
else
{
@ -113,5 +113,6 @@ namespace spot
visited_map visited;
unsigned int dfs_number = 0;
unsigned int transitions = 0;
unsigned int tid_;
};
}