* src/tgbaalgos/gtec/gtec.cc (couvreur99_check_shy::check):

Reorganize this function so that syntactically there is only one
loop over the successors, and not two.  Call reintroduce the call
to couvreur99_check_shy::state_index(), needed by SSP, and
suppress that to index_and_insert introduced on 2004-12-29.  Also
split the "group" option in two: "group" and "group2".  "group2"
is the equivalent of the older "group", while the new "group" is
weaker and faster.
(couvreur99_check_shy::state_index): Change prototype as needed by
the algorithm.
* src/tgbaalgos/gtec/gtec.hh: Adjust.
* src/tgbaalgos/gtec/nsheap.hh, src/tgbaalgos/gtec/nsheap.cc
(index_and_insert): Remove.
* iface/gspn/ssp.cc (couvreur99_check_shy_ssp::state_index): Adjust
to new prototype.
* bench/emptchk/README, bench/emptchk/algorithms: Adjust references
to group/group2.
This commit is contained in:
Alexandre Duret-Lutz 2006-02-02 13:46:04 +00:00
parent d9d4804bc9
commit 236742aed8
8 changed files with 197 additions and 214 deletions

View file

@ -1,3 +1,23 @@
2006-02-02 Alexandre Duret-Lutz <adl@src.lip6.fr>
* src/tgbaalgos/gtec/gtec.cc (couvreur99_check_shy::check):
Reorganize this function so that syntactically there is only one
loop over the successors, and not two. Call reintroduce the call
to couvreur99_check_shy::state_index(), needed by SSP, and
suppress that to index_and_insert introduced on 2004-12-29. Also
split the "group" option in two: "group" and "group2". "group2"
is the equivalent of the older "group", while the new "group" is
weaker and faster.
(couvreur99_check_shy::state_index): Change prototype as needed by
the algorithm.
* src/tgbaalgos/gtec/gtec.hh: Adjust.
* src/tgbaalgos/gtec/nsheap.hh, src/tgbaalgos/gtec/nsheap.cc
(index_and_insert): Remove.
* iface/gspn/ssp.cc (couvreur99_check_shy_ssp::state_index): Adjust
to new prototype.
* bench/emptchk/README, bench/emptchk/algorithms: Adjust references
to group/group2.
2006-01-30 Alexandre Duret-Lutz <adl@src.lip6.fr> 2006-01-30 Alexandre Duret-Lutz <adl@src.lip6.fr>
* NEWS, configure.ac: Bump version to 0.3a. * NEWS, configure.ac: Bump version to 0.3a.

View file

@ -194,9 +194,11 @@ This directory contains:
Cou99 Cou99
Cou99(shy !group) Cou99(shy !group)
Cou99(shy group) Cou99(shy group)
Cou99(shy group2)
> Cou99(poprem) # called `Cou99' in the paper > Cou99(poprem) # called `Cou99' in the paper
> Cou99(poprem shy !group) # called `Cou99 Shy-' in the paper > Cou99(poprem shy !group) # called `Cou99 Shy-' in the paper
> Cou99(poprem shy group) # called `Cou99 Shy' in the paper Cou99(poprem shy group)
> Cou99(poprem shy group2) # called `Cou99 Shy' in the paper
> CVWY90 > CVWY90
> GV04 > GV04
> SE05 > SE05

View file

@ -1,9 +1,11 @@
Cou99 Cou99
Cou99(shy !group) Cou99(shy !group)
Cou99(shy group) Cou99(shy group)
Cou99(shy group2)
Cou99(poprem) Cou99(poprem)
Cou99(poprem shy !group) Cou99(poprem shy !group)
Cou99(poprem shy group) Cou99(poprem shy group)
Cou99(poprem shy group2)
GV04 GV04
CVWY90 CVWY90
SE05 SE05

View file

@ -1,4 +1,4 @@
// Copyright (C) 2003, 2004, 2005 Laboratoire d'Informatique de Paris 6 (LIP6), // Copyright (C) 2003, 2004, 2005, 2006 Laboratoire d'Informatique de Paris 6 (LIP6),
// département Systèmes Répartis Coopératifs (SRC), Université Pierre // département Systèmes Répartis Coopératifs (SRC), Université Pierre
// et Marie Curie. // et Marie Curie.
// //
@ -924,7 +924,7 @@ namespace spot
// children to the list of children of that older state. We cannot // children to the list of children of that older state. We cannot
// to this by sub-classing numbered_state_heap since TODO is not // to this by sub-classing numbered_state_heap since TODO is not
// available. So we override find_state() instead. // available. So we override find_state() instead.
virtual int* virtual numbered_state_heap::state_index_p
find_state(const state* s) find_state(const state* s)
{ {
typedef numbered_state_heap_ssp_semi::hash_type hash_type; typedef numbered_state_heap_ssp_semi::hash_type hash_type;
@ -979,11 +979,22 @@ namespace spot
} }
} }
} }
state_index_p res;
if (i == h.end()) if (i == h.end())
return 0; {
if (i->first != s) res.first = 0;
res.second = 0;
}
else
{
res.first = i->first;
res.second = &i->second;
if (s != i->first)
delete s; delete s;
return &i->second; }
return res;
} }
}; };

View file

@ -1,6 +1,6 @@
// Copyright (C) 2003, 2004, 2005 Laboratoire d'Informatique de Paris 6 (LIP6), // Copyright (C) 2003, 2004, 2005, 2006 Laboratoire d'Informatique de
// département Systèmes Répartis Coopératifs (SRC), Université Pierre // Paris 6 (LIP6), département Systèmes Répartis Coopératifs (SRC),
// et Marie Curie. // Université Pierre et Marie Curie.
// //
// This file is part of Spot, a model checking library. // This file is part of Spot, a model checking library.
// //
@ -288,6 +288,20 @@ namespace spot
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
couvreur99_check_shy::todo_item::todo_item(const state* s, int n,
couvreur99_check_shy* shy)
: s(s), n(n)
{
tgba_succ_iterator* iter = shy->ecs_->aut->succ_iter(s);
for (iter->first(); !iter->done(); iter->next(), shy->inc_transitions())
{
q.push_back(successor(iter->current_acceptance_conditions(),
iter->current_state()));
shy->inc_depth();
}
delete iter;
}
couvreur99_check_shy::couvreur99_check_shy(const tgba* a, couvreur99_check_shy::couvreur99_check_shy(const tgba* a,
option_map o, option_map o,
const numbered_state_heap_factory* const numbered_state_heap_factory*
@ -295,11 +309,15 @@ namespace spot
: couvreur99_check(a, o, nshf), num(1) : couvreur99_check(a, o, nshf), num(1)
{ {
group_ = o.get("group", 1); group_ = o.get("group", 1);
group2_ = o.get("group2", 0);
group_ |= group2_;
// Setup depth-first search from the initial state. // Setup depth-first search from the initial state.
todo.push_back(todo_item(0, 0)); const state* i = ecs_->aut->get_init_state();
todo.back().q.push_front(successor(bddtrue, ecs_->aut->get_init_state())); ecs_->h->insert(i, ++num);
inc_depth(2); ecs_->root.push(num);
todo.push_back(todo_item(i, num, this));
inc_depth(1);
} }
couvreur99_check_shy::~couvreur99_check_shy() couvreur99_check_shy::~couvreur99_check_shy()
@ -334,9 +352,12 @@ namespace spot
emptiness_check_result* emptiness_check_result*
couvreur99_check_shy::check() couvreur99_check_shy::check()
{ {
// Position in the loop seeking known successors.
succ_queue::iterator pos = todo.back().q.begin();
for (;;) for (;;)
{ {
assert(ecs_->root.size() == arc.size()); assert(ecs_->root.size() == 1 + arc.size());
// Get the successors of the current state. // Get the successors of the current state.
succ_queue& queue = todo.back().q; succ_queue& queue = todo.back().q;
@ -361,6 +382,8 @@ namespace spot
return 0; return 0;
} }
pos = todo.back().q.begin();
// If poprem is used, fill rem with any component removed, // If poprem is used, fill rem with any component removed,
// so that remove_component() does not have to traverse // so that remove_component() does not have to traverse
// the SCC again. // the SCC again.
@ -386,61 +409,45 @@ namespace spot
continue; continue;
} }
// Pick one successor off the list. // We always make a first pass over the successors of a state
successor succ = queue.front(); // to check whether it contains some state we have already seen.
queue.pop_front(); // This way we hope to merge the most SCCs before stacking new
dec_depth(); // states.
//
// So are we checking for known states ? If yes, POS tells us
// which state we are considering. Otherwise just pick the
// first one.
succ_queue::iterator old;
if (pos == queue.end())
old = queue.begin();
else
old = pos++;
successor succ = *old;
int& n = ecs_->h->index_and_insert(succ.s); numbered_state_heap::state_index_p sip = find_state(succ.s);
// Skip dead states.
if (n == -1)
continue;
// If it is known, it is necessarily in the current condition.
if (n != 0)
{
assert(n >= ecs_->root.top().index);
ecs_->root.top().condition |= succ.acc;
// Have we found all acceptance conditions?
if (ecs_->root.top().condition
== ecs_->aut->all_acceptance_conditions())
{
// Use this state to start the computation of an accepting
// cycle.
ecs_->cycle_seed = succ.s;
// We have found an accepting SCC. Clean up TODO.
clear_todo();
set_states(ecs_->states());
return new couvreur99_check_result(ecs_, options());
}
continue;
}
// It is a new state. Number it, and stack it.
n = ++num;
ecs_->root.push(num);
arc.push(succ.acc);
todo.push_back(todo_item(succ.s, num));
inc_depth();
succ_queue* new_queue = &todo.back().q;
tgba_succ_iterator* iter = ecs_->aut->succ_iter(succ.s);
succ_queue::iterator merge_end;
bool merged = false;
for (iter->first(); !iter->done(); iter->next(), inc_transitions())
{
const state* dest = iter->current_state();
bdd acc = iter->current_acceptance_conditions();
numbered_state_heap::state_index_p sip = ecs_->h->find(dest);
int* i = sip.second; int* i = sip.second;
// Add new states to the queue.
if (!i) if (!i)
{ {
new_queue->push_back(successor(acc, dest)); // It's a new state.
// If we are seeking known states, just skip it.
if (pos != queue.end())
continue;
// Otherwise, number it and stack it so we recurse.
queue.erase(old);
dec_depth();
ecs_->h->insert(succ.s, ++num);
ecs_->root.push(num);
arc.push(succ.acc);
todo.push_back(todo_item(succ.s, num, this));
pos = todo.back().q.begin();
inc_depth(); inc_depth();
continue; continue;
} }
queue.erase(old);
dec_depth();
// Skip dead states. // Skip dead states.
if (*i == -1) if (*i == -1)
continue; continue;
@ -461,6 +468,7 @@ namespace spot
// (called the "threshold"). // (called the "threshold").
int threshold = *i; int threshold = *i;
std::list<const state*> rem; std::list<const state*> rem;
bdd acc = succ.acc;
while (threshold < ecs_->root.top().index) while (threshold < ecs_->root.top().index)
{ {
assert(!ecs_->root.empty()); assert(!ecs_->root.empty());
@ -492,7 +500,6 @@ namespace spot
// We have found an accepting SCC. Clean up TODO. // We have found an accepting SCC. Clean up TODO.
clear_todo(); clear_todo();
set_states(ecs_->states()); set_states(ecs_->states());
delete iter;
return new couvreur99_check_result(ecs_, options()); return new couvreur99_check_result(ecs_, options());
} }
// Group the pending successors of formed SCC if requested. // Group the pending successors of formed SCC if requested.
@ -503,12 +510,12 @@ namespace spot
{ {
todo_list::reverse_iterator prev = todo.rbegin(); todo_list::reverse_iterator prev = todo.rbegin();
todo_list::reverse_iterator last = prev++; todo_list::reverse_iterator last = prev++;
if (!merged) // If group2 is used we insert the last->q in front
{ // of prev->q so that the states in prev->q are checked
merge_end = last->q.begin(); // for existence again after we have done with the states
merged = true; // of last->q. Otherwise we just append to the end.
} prev->q.splice(group2_ ? prev->q.begin() : prev->q.end(),
prev->q.splice(prev->q.end(), last->q); last->q);
if (poprem_) if (poprem_)
{ {
@ -525,54 +532,15 @@ namespace spot
} }
todo.pop_back(); todo.pop_back();
} }
new_queue = &todo.back().q; pos = todo.back().q.begin();
}
}
delete iter;
if (merged)
{
succ_queue::iterator q = new_queue->begin();
while (q != merge_end && q != new_queue->end())
{
numbered_state_heap::state_index_p sip = ecs_->h->find(q->s);
succ_queue::iterator old = q++;
int* i = sip.second;
// Skip new states.
if (!i)
continue;
bdd acc = old->acc;
// Delete other states.
new_queue->erase(old);
dec_depth();
// Delete dead states.
if (*i == -1)
continue;
// Merge existing states.
assert(n >= ecs_->root.top().index);
ecs_->root.top().condition |= acc;
// Have we found all acceptance conditions?
if (ecs_->root.top().condition
== ecs_->aut->all_acceptance_conditions())
{
// Use this state to start the computation of an accepting
// cycle.
ecs_->cycle_seed = sip.first;
// We have found an accepting SCC. Clean up TODO.
clear_todo();
set_states(ecs_->states());
return new couvreur99_check_result(ecs_, options());
}
}
} }
} }
} }
int* numbered_state_heap::state_index_p
couvreur99_check_shy::find_state(const state* s) couvreur99_check_shy::find_state(const state* s)
{ {
return ecs_->h->find(s).second; return ecs_->h->find(s);
} }
emptiness_check* emptiness_check*

View file

@ -1,6 +1,6 @@
// Copyright (C) 2003, 2004, 2005 Laboratoire d'Informatique de Paris 6 (LIP6), // Copyright (C) 2003, 2004, 2005, 2006 Laboratoire d'Informatique de
// département Systèmes Répartis Coopératifs (SRC), Université Pierre // Paris 6 (LIP6), département Systèmes Répartis Coopératifs (SRC),
// et Marie Curie. // Université Pierre et Marie Curie.
// //
// This file is part of Spot, a model checking library. // This file is part of Spot, a model checking library.
// //
@ -222,11 +222,8 @@ namespace spot
{ {
const state* s; const state* s;
int n; int n;
succ_queue q; succ_queue q; // Unprocessed successors of S
todo_item(const state* s, int n) todo_item(const state* s, int n, couvreur99_check_shy* shy);
: s(s), n(n)
{
}
}; };
typedef std::list<todo_item> todo_list; typedef std::list<todo_item> todo_list;
@ -237,6 +234,9 @@ namespace spot
// Whether successors should be grouped for states in the same // Whether successors should be grouped for states in the same
// SCC. // SCC.
bool group_; bool group_;
// If the "group2" option is set (it implies "group"), we
// reprocess the successor states of SCC that have been merged.
bool group2_;
/// \brief find the SCC number of a unprocessed state. /// \brief find the SCC number of a unprocessed state.
/// ///
@ -246,7 +246,7 @@ namespace spot
/// to TODO during this step. (Because TODO must be known, /// to TODO during this step. (Because TODO must be known,
/// sub-classing spot::numbered_state_heap is not enough.) Then /// sub-classing spot::numbered_state_heap is not enough.) Then
/// overriding this method is the way to go. /// overriding this method is the way to go.
virtual int* find_state(const state* s); virtual numbered_state_heap::state_index_p find_state(const state* s);
}; };

View file

@ -1,4 +1,4 @@
// Copyright (C) 2004 Laboratoire d'Informatique de Paris 6 (LIP6), // Copyright (C) 2004, 2006 Laboratoire d'Informatique de Paris 6 (LIP6),
// département Systèmes Répartis Coopératifs (SRC), Université Pierre // département Systèmes Répartis Coopératifs (SRC), Université Pierre
// et Marie Curie. // et Marie Curie.
// //
@ -150,19 +150,6 @@ namespace spot
h[s] = index; h[s] = index;
} }
int&
numbered_state_heap_hash_map::index_and_insert(const state*& s)
{
std::pair<hash_type::iterator, bool> r
= h.insert(hash_type::value_type(s, 0));
if (!r.second)
{
delete s;
s = r.first->first;
}
return r.first->second;
}
int int
numbered_state_heap_hash_map::size() const numbered_state_heap_hash_map::size() const
{ {

View file

@ -1,4 +1,4 @@
// Copyright (C) 2004 Laboratoire d'Informatique de Paris 6 (LIP6), // Copyright (C) 2004, 2006 Laboratoire d'Informatique de Paris 6 (LIP6),
// département Systèmes Répartis Coopératifs (SRC), Université Pierre // département Systèmes Répartis Coopératifs (SRC), Université Pierre
// et Marie Curie. // et Marie Curie.
// //
@ -89,12 +89,6 @@ namespace spot
/// Add a new state \a s with index \a index /// Add a new state \a s with index \a index
virtual void insert(const state* s, int index) = 0; virtual void insert(const state* s, int index) = 0;
/// \brief Get the index of a state, and insert that state if it is missing.
///
/// If a clone of \a s is already in the hash table, \a s will be deleted
/// and replaced by the address of the clone used.
virtual int& index_and_insert(const state*& s) = 0;
/// The number of stored states. /// The number of stored states.
virtual int size() const = 0; virtual int size() const = 0;
@ -120,7 +114,6 @@ namespace spot
virtual state_index_p find(const state* s); virtual state_index_p find(const state* s);
virtual state_index index(const state* s) const; virtual state_index index(const state* s) const;
virtual state_index_p index(const state* s); virtual state_index_p index(const state* s);
virtual int& index_and_insert(const state*& s);
virtual void insert(const state* s, int index); virtual void insert(const state* s, int index);
virtual int size() const; virtual int size() const;