Commit 393637f1 authored by Alexandre Duret-Lutz's avatar Alexandre Duret-Lutz
Browse files

gtec: replace nsheap by a simple unordered_map

nsheap was an horror full of virtual functions required to
customize gtec to implement inclusion-based emptiness-check
in GreatSPN support.  Since this support has been removed, we
can remove the nsheap cruft as well.  Note that nsheap was
also used in emptinessta for no good reason (the code from
emptinessta was simply copied from gtec without cleanup).

* src/tgbaalgos/gtec/nsheap.cc, src/tgbaalgos/gtec/nsheap.hh:
Delete.
* src/tgbaalgos/gtec/Makefile.am: Adjust.
* src/taalgos/emptinessta.cc, src/taalgos/emptinessta.hh,
src/taalgos/tgba2ta.cc, src/tgbaalgos/gtec/ce.cc,
src/tgbaalgos/gtec/gtec.cc, src/tgbaalgos/gtec/gtec.hh,
src/tgbaalgos/gtec/status.cc, src/tgbaalgos/gtec/status.hh:
Use a simple unordered_map.
parent 46e4408a
...@@ -58,8 +58,7 @@ namespace spot ...@@ -58,8 +58,7 @@ namespace spot
// * h: a hash of all visited nodes, with their order, // * h: a hash of all visited nodes, with their order,
// (it is called "Hash" in Couvreur's paper) // (it is called "Hash" in Couvreur's paper)
numbered_state_heap* h = hash_type h;
numbered_state_heap_hash_map_factory::instance()->build();
// * num: the number of visited nodes. Used to set the order of each // * num: the number of visited nodes. Used to set the order of each
// visited node, // visited node,
...@@ -107,13 +106,13 @@ namespace spot ...@@ -107,13 +106,13 @@ namespace spot
state_ta_product* init = new state_ta_product( state_ta_product* init = new state_ta_product(
(ta_init_it_->current_state()), kripke_init_state->clone()); (ta_init_it_->current_state()), kripke_init_state->clone());
numbered_state_heap::state_index_p h_init = h->find(init); if (!h.insert(std::make_pair(init, num + 1)).second)
{
init->destroy();
continue;
}
if (h_init.first) scc.push(++num);
continue;
h->insert(init, ++num);
scc.push(num);
arc.push(bddfalse); arc.push(bddfalse);
ta_succ_iterator_product* iter = a_->succ_iter(init); ta_succ_iterator_product* iter = a_->succ_iter(init);
...@@ -143,29 +142,25 @@ namespace spot ...@@ -143,29 +142,25 @@ namespace spot
// Backtrack TODO. // Backtrack TODO.
todo.pop(); todo.pop();
dec_depth(); dec_depth();
trace trace << "PASS 1 : backtrack\n";
<< "PASS 1 : backtrack" << std::endl;
if (a_->is_livelock_accepting_state(curr) if (a_->is_livelock_accepting_state(curr)
&& !a_->is_accepting_state(curr)) && !a_->is_accepting_state(curr))
{ {
livelock_acceptance_states_not_found = false; livelock_acceptance_states_not_found = false;
trace trace << "PASS 1 : livelock accepting state found\n";
<< "PASS 1 : livelock accepting state found" << std::endl;
} }
// fill rem with any component removed, // fill rem with any component removed,
numbered_state_heap::state_index_p spi = auto i = h.find(curr);
h->index(curr->clone()); assert(i != h.end());
assert(spi.first);
scc.rem().push_front(curr); scc.rem().push_front(curr);
inc_depth(); inc_depth();
// set the h value of the Backtracked state to negative value. // set the h value of the Backtracked state to negative value.
// colour[curr] = BLUE; // colour[curr] = BLUE;
*spi.second = -std::abs(*spi.second); i->second = -std::abs(i->second);
// Backtrack livelock_roots. // Backtrack livelock_roots.
if (activate_heuristic && !livelock_roots.empty() if (activate_heuristic && !livelock_roots.empty()
...@@ -176,21 +171,11 @@ namespace spot ...@@ -176,21 +171,11 @@ namespace spot
// remove that SSCC from the ROOT stacks. We must // remove that SSCC from the ROOT stacks. We must
// discard from H all reachable states from this SSCC. // discard from H all reachable states from this SSCC.
assert(!scc.empty()); assert(!scc.empty());
if (scc.top().index == std::abs(*spi.second)) if (scc.top().index == std::abs(i->second))
{ {
// removing states // removing states
std::list<state*>::iterator i; for (auto j: scc.rem())
h[j] = -1; //colour[*i] = BLACK;
for (i = scc.rem().begin(); i != scc.rem().end(); ++i)
{
numbered_state_heap::state_index_p spi = h->index(
(*i)->clone());
assert(spi.first->compare(*i) == 0);
assert(*spi.second != -1);
*spi.second = -1;
//colour[*i] = BLACK;
}
dec_depth(scc.rem().size()); dec_depth(scc.rem().size());
scc.pop(); scc.pop();
assert(!arc.empty()); assert(!arc.empty());
...@@ -205,8 +190,7 @@ namespace spot ...@@ -205,8 +190,7 @@ namespace spot
// We have a successor to look at. // We have a successor to look at.
inc_transitions(); inc_transitions();
trace trace << "PASS 1: transition\n";
<< "PASS 1: transition" << std::endl;
// Fetch the values destination state we are interested in... // Fetch the values destination state we are interested in...
state* dest = succ->current_state(); state* dest = succ->current_state();
...@@ -232,15 +216,12 @@ namespace spot ...@@ -232,15 +216,12 @@ namespace spot
// We do not need SUCC from now on. // We do not need SUCC from now on.
// Are we going to a new state? // Are we going to a new state?
numbered_state_heap::state_index_p spi = h->find(dest); auto p = h.insert(std::make_pair(dest, num + 1));
if (p.second)
// Is this a new state?
if (!spi.first)
{ {
// Number it, stack it, and register its successors // Number it, stack it, and register its successors
// for later processing. // for later processing.
h->insert(dest, ++num); scc.push(++num);
scc.push(num);
arc.push(acc_cond); arc.push(acc_cond);
ta_succ_iterator_product* iter = a_->succ_iter(dest); ta_succ_iterator_product* iter = a_->succ_iter(dest);
...@@ -258,7 +239,7 @@ namespace spot ...@@ -258,7 +239,7 @@ namespace spot
} }
// If we have reached a dead component, ignore it. // If we have reached a dead component, ignore it.
if (*spi.second == -1) if (p.first->second == -1)
continue; continue;
// Now this is the most interesting case. We have reached a // Now this is the most interesting case. We have reached a
...@@ -272,12 +253,11 @@ namespace spot ...@@ -272,12 +253,11 @@ namespace spot
// ROOT is ascending: we just have to merge all SSCCs from the // ROOT is ascending: we just have to merge all SSCCs from the
// top of ROOT that have an index greater to the one of // top of ROOT that have an index greater to the one of
// the SSCC of S2 (called the "threshold"). // the SSCC of S2 (called the "threshold").
int threshold = std::abs(*spi.second); int threshold = std::abs(p.first->second);
std::list<state*> rem; std::list<state*> rem;
bool acc = false; bool acc = false;
trace trace << "***PASS 1: CYCLE***\n";
<< "***PASS 1: CYCLE***" << std::endl;
while (threshold < scc.top().index) while (threshold < scc.top().index)
{ {
...@@ -310,15 +290,15 @@ namespace spot ...@@ -310,15 +290,15 @@ namespace spot
if (is_accepting_sscc) if (is_accepting_sscc)
{ {
trace trace
<< "PASS 1: SUCCESS : a_->is_livelock_accepting_state(curr): " << "PASS 1: SUCCESS: a_->is_livelock_accepting_state(curr): "
<< a_->is_livelock_accepting_state(curr) << std::endl; << a_->is_livelock_accepting_state(curr) << '\n';
trace trace
<< "PASS 1: scc.top().condition : " << "PASS 1: scc.top().condition : "
<< bdd_format_accset(a_->get_dict(), scc.top().condition) << bdd_format_accset(a_->get_dict(), scc.top().condition)
<< std::endl; << '\n';
trace trace
<< "PASS 1: a_->all_acceptance_conditions() : " << "PASS 1: a_->all_acceptance_conditions() : "
<< (a_->all_acceptance_conditions()) << std::endl; << (a_->all_acceptance_conditions()) << '\n';
trace trace
<< ("PASS 1 CYCLE and (scc.top().condition == " << ("PASS 1 CYCLE and (scc.top().condition == "
"a_->all_acceptance_conditions()) : ") "a_->all_acceptance_conditions()) : ")
...@@ -326,12 +306,12 @@ namespace spot ...@@ -326,12 +306,12 @@ namespace spot
== a_->all_acceptance_conditions()) << std::endl; == a_->all_acceptance_conditions()) << std::endl;
trace trace
<< "PASS 1: bddtrue : " << (a_->all_acceptance_conditions() << "PASS 1: bddtrue: " << (a_->all_acceptance_conditions()
== bddtrue) << std::endl; == bddtrue) << '\n';
trace trace
<< "PASS 1: bddfalse : " << (a_->all_acceptance_conditions() << "PASS 1: bddfalse: " << (a_->all_acceptance_conditions()
== bddfalse) << std::endl; == bddfalse) << '\n';
clear(h, todo, ta_init_it_); clear(h, todo, ta_init_it_);
return true; return true;
...@@ -341,9 +321,8 @@ namespace spot ...@@ -341,9 +321,8 @@ namespace spot
if (activate_heuristic && a_->is_livelock_accepting_state(curr) if (activate_heuristic && a_->is_livelock_accepting_state(curr)
&& is_stuttering_transition) && is_stuttering_transition)
{ {
trace trace << "PASS 1: heuristic livelock detection \n";
<< "PASS 1: heuristic livelock detection " << std::endl; const state* dest = p.first->first;
const state* dest = spi.first;
std::set<const state*, state_ptr_less_than> liveset_dest = std::set<const state*, state_ptr_less_than> liveset_dest =
liveset[dest]; liveset[dest];
...@@ -352,28 +331,23 @@ namespace spot ...@@ -352,28 +331,23 @@ namespace spot
int h_livelock_root = 0; int h_livelock_root = 0;
if (!livelock_roots.empty()) if (!livelock_roots.empty())
h_livelock_root = *(h->find((livelock_roots.top()))).second; h_livelock_root = h[livelock_roots.top()];
if (heuristic_livelock_detection(dest, h, h_livelock_root, if (heuristic_livelock_detection(dest, h, h_livelock_root,
liveset_curr)) liveset_curr))
{ {
clear(h, todo, ta_init_it_); clear(h, todo, ta_init_it_);
return true; return true;
} }
std::set<const state*, state_ptr_less_than>::const_iterator it; std::set<const state*, state_ptr_less_than>::const_iterator it;
for (it = liveset_dest.begin(); it != liveset_dest.end(); ++it) for (const state* succ: liveset_dest)
{ if (heuristic_livelock_detection(succ, h, h_livelock_root,
const state* succ = (*it); liveset_curr))
if (heuristic_livelock_detection(succ, h, h_livelock_root, {
liveset_curr)) clear(h, todo, ta_init_it_);
{ return true;
clear(h, todo, ta_init_it_); }
return true;
}
}
} }
} }
...@@ -389,26 +363,23 @@ namespace spot ...@@ -389,26 +363,23 @@ namespace spot
bool bool
ta_check::heuristic_livelock_detection(const state * u, ta_check::heuristic_livelock_detection(const state * u,
numbered_state_heap* h, int h_livelock_root, std::set<const state*, hash_type& h, int h_livelock_root, std::set<const state*,
state_ptr_less_than> liveset_curr) state_ptr_less_than> liveset_curr)
{ {
numbered_state_heap::state_index_p hu = h->find(u); int hu = h[u];
if (*hu.second > 0) // colour[u] == GREY if (hu > 0) // colour[u] == GREY
{ {
if (*hu.second >= h_livelock_root) if (hu >= h_livelock_root)
{ {
trace trace << "PASS 1: heuristic livelock detection SUCCESS\n";
<< "PASS 1: heuristic livelock detection SUCCESS" << std::endl;
return true; return true;
} }
liveset_curr.insert(u); liveset_curr.insert(u);
} }
return false; return false;
} }
bool bool
...@@ -421,8 +392,7 @@ namespace spot ...@@ -421,8 +392,7 @@ namespace spot
// * h: a hash of all visited nodes, with their order, // * h: a hash of all visited nodes, with their order,
// (it is called "Hash" in Couvreur's paper) // (it is called "Hash" in Couvreur's paper)
numbered_state_heap* h = hash_type h;
numbered_state_heap_hash_map_factory::instance()->build();
// * num: the number of visited nodes. Used to set the order of each // * num: the number of visited nodes. Used to set the order of each
// visited node, // visited node,
...@@ -448,7 +418,6 @@ namespace spot ...@@ -448,7 +418,6 @@ namespace spot
{ {
state* init_state = (*it); state* init_state = (*it);
ta_init_it_.push(init_state); ta_init_it_.push(init_state);
} }
while (!ta_init_it_.empty()) while (!ta_init_it_.empty())
...@@ -457,19 +426,19 @@ namespace spot ...@@ -457,19 +426,19 @@ namespace spot
{ {
state* init = ta_init_it_.front(); state* init = ta_init_it_.front();
ta_init_it_.pop(); ta_init_it_.pop();
numbered_state_heap::state_index_p h_init = h->find(init);
if (h_init.first) if (!h.insert(std::make_pair(init, num + 1)).second)
continue; {
init->destroy();
continue;
}
h->insert(init, ++num);
sscc.push(num); sscc.push(num);
sscc.top().is_accepting = t->is_livelock_accepting_state(init); sscc.top().is_accepting = t->is_livelock_accepting_state(init);
ta_succ_iterator_product* iter = t->succ_iter(init); ta_succ_iterator_product* iter = t->succ_iter(init);
iter->first(); iter->first();
todo.emplace(init, iter); todo.emplace(init, iter);
inc_depth(); inc_depth();
} }
while (!todo.empty()) while (!todo.empty())
...@@ -488,13 +457,11 @@ namespace spot ...@@ -488,13 +457,11 @@ namespace spot
// Backtrack TODO. // Backtrack TODO.
todo.pop(); todo.pop();
dec_depth(); dec_depth();
trace trace << "PASS 2 : backtrack\n";
<< "PASS 2 : backtrack" << std::endl;
// fill rem with any component removed, // fill rem with any component removed,
numbered_state_heap::state_index_p spi = auto i = h.find(curr);
h->index(curr->clone()); assert(i != h.end());
assert(spi.first);
sscc.rem().push_front(curr); sscc.rem().push_front(curr);
inc_depth(); inc_depth();
...@@ -503,19 +470,11 @@ namespace spot ...@@ -503,19 +470,11 @@ namespace spot
// remove that SSCC from the ROOT stacks. We must // remove that SSCC from the ROOT stacks. We must
// discard from H all reachable states from this SSCC. // discard from H all reachable states from this SSCC.
assert(!sscc.empty()); assert(!sscc.empty());
if (sscc.top().index == *spi.second) if (sscc.top().index == i->second)
{ {
// removing states // removing states
std::list<state*>::iterator i; for (auto j: sscc.rem())
h[j] = -1;
for (i = sscc.rem().begin(); i != sscc.rem().end(); ++i)
{
numbered_state_heap::state_index_p spi = h->index(
(*i)->clone());
assert(spi.first->compare(*i) == 0);
assert(*spi.second != -1);
*spi.second = -1;
}
dec_depth(sscc.rem().size()); dec_depth(sscc.rem().size());
sscc.pop(); sscc.pop();
} }
...@@ -528,8 +487,7 @@ namespace spot ...@@ -528,8 +487,7 @@ namespace spot
// We have a successor to look at. // We have a successor to look at.
inc_transitions(); inc_transitions();
trace trace << "PASS 2 : transition\n";
<< "PASS 2 : transition" << std::endl;
// Fetch the values destination state we are interested in... // Fetch the values destination state we are interested in...
state* dest = succ->current_state(); state* dest = succ->current_state();
...@@ -539,10 +497,10 @@ namespace spot ...@@ -539,10 +497,10 @@ namespace spot
succ->next(); succ->next();
// We do not need SUCC from now on. // We do not need SUCC from now on.
numbered_state_heap::state_index_p spi = h->find(dest); auto i = h.find(dest);
// Is this a new state? // Is this a new state?
if (!spi.first) if (i == h.end())
{ {
// Are we going to a new state through a stuttering transition? // Are we going to a new state through a stuttering transition?
...@@ -555,7 +513,7 @@ namespace spot ...@@ -555,7 +513,7 @@ namespace spot
// Number it, stack it, and register its successors // Number it, stack it, and register its successors
// for later processing. // for later processing.
h->insert(dest, ++num); h[dest] = ++num;
sscc.push(num); sscc.push(num);
sscc.top().is_accepting = t->is_livelock_accepting_state(dest); sscc.top().is_accepting = t->is_livelock_accepting_state(dest);
...@@ -565,24 +523,26 @@ namespace spot ...@@ -565,24 +523,26 @@ namespace spot
inc_depth(); inc_depth();
continue; continue;
} }
else
{
dest->destroy();
}
// If we have reached a dead component, ignore it. // If we have reached a dead component, ignore it.
if (*spi.second == -1) if (i->second == -1)
continue; continue;
//self loop state //self loop state
if (!curr->compare(spi.first)) if (!curr->compare(i->first))
{ {
state * self_loop_state = (curr); state* self_loop_state = curr;
if (t->is_livelock_accepting_state(self_loop_state)) if (t->is_livelock_accepting_state(self_loop_state))
{ {
clear(h, todo, ta_init_it_); clear(h, todo, ta_init_it_);
trace trace << "PASS 2: SUCCESS\n";
<< "PASS 2: SUCCESS" << std::endl;
return true; return true;
} }
} }
// Now this is the most interesting case. We have reached a // Now this is the most interesting case. We have reached a
...@@ -596,7 +556,7 @@ namespace spot ...@@ -596,7 +556,7 @@ namespace spot
// ROOT is ascending: we just have to merge all SSCCs from the // ROOT is ascending: we just have to merge all SSCCs from the
// top of ROOT that have an index greater to the one of // top of ROOT that have an index greater to the one of
// the SSCC of S2 (called the "threshold"). // the SSCC of S2 (called the "threshold").
int threshold = *spi.second; int threshold = i->second;
std::list<state*> rem; std::list<state*> rem;
bool acc = false; bool acc = false;
...@@ -634,11 +594,11 @@ namespace spot ...@@ -634,11 +594,11 @@ namespace spot
} }
void void
ta_check::clear(numbered_state_heap* h, std::stack<pair_state_iter> todo, ta_check::clear(hash_type& h, std::stack<pair_state_iter> todo,
std::queue<spot::state*> init_states) std::queue<spot::state*> init_states)
{ {
set_states(states() + h->size()); set_states(states() + h.size());
while (!init_states.empty()) while (!init_states.empty())
{ {
...@@ -653,15 +613,14 @@ namespace spot ...@@ -653,15 +613,14 @@ namespace spot
todo.pop(); todo.pop();
dec_depth(); dec_depth();
} }
delete h;
} }
void void
ta_check::clear(numbered_state_heap* h, std::stack<pair_state_iter> todo, ta_check::clear(hash_type& h, std::stack<pair_state_iter> todo,
spot::ta_succ_iterator* init_states_it) spot::ta_succ_iterator* init_states_it)
{ {
set_states(states() + h->size()); set_states(states() + h.size());
delete init_states_it; delete init_states_it;
...@@ -672,7 +631,6 @@ namespace spot ...@@ -672,7 +631,6 @@ namespace spot
todo.pop(); todo.pop();