* src/tgbaalgos/tarjan_on_fly.hh,

src/tgbaalgos/tarjan_on_fly.cc,
src/tgbaalgos/nesteddfs.hh,
src/tgbaalgos/nesteddfs.cc,
src/tgbaalgos/minimalce.hh,
src/tgbaalgos/minimalce.cc,
src/tgbaalgos/colordfs.hh,
src/tgbaalgos/colordfs.cc: four new algorithms for emptyness check.

src/tgbaalgos/gtec/ce.hh,
src/tgbaalgos/gtec/ce.cc: Adapt the counter exemple for the ce
object in minimalce.hh.

src/tgbatest/ltl2tgba.cc,
src/tgbatest/emptchk.test,
src/tgbaalgos/Makefile.am: Add files for emptyness-check.


* src/tgbaalgos/reductgba_sim_del.cc: Restrict to degeneralize automata.
* src/tgba/tgbareduc.hh: src/tgba/tgbareduc.cc: Merge transition
for scc reduce.
This commit is contained in:
martinez 2004-08-23 12:48:33 +00:00
parent 3d2135c883
commit 2d1151e018
17 changed files with 2526 additions and 157 deletions

View file

@ -35,6 +35,8 @@ namespace spot
eccf)
: ecs_(ecs)
{
counter_ = new ce::counter_example(ecs->aut);
assert(!ecs_->root.empty());
assert(suffix.empty());
@ -76,6 +78,10 @@ namespace spot
assert(spi.first);
suffix.push_front(spi.first);
/////
counter_->prefix.push_front(ce::state_ce(spi.first->clone(), bddfalse));
////
// We build a path trough each SCC in the stack. For the
// first SCC, the starting state is the initial state of the
// automaton. The destination state is the closest state
@ -113,21 +119,35 @@ namespace spot
const state* h_dest = scc[k]->has_state(dest);
if (!h_dest)
{
// If we have found a state in the next SCC.
// If we have found a state in greater SCC which.
// Unwind the path and populate SUFFIX.
h_dest = scc[k+1]->has_state(dest);
if (h_dest)
{
state_sequence seq;
///
ce::l_state_ce seq_count;
///
seq.push_front(h_dest);
while (src->compare(start))
{
///
seq_count.push_front(ce::state_ce(src->clone(), bddfalse));
///
seq.push_front(src);
src = father[src];
}
// Append SEQ to SUFFIX.
suffix.splice(suffix.end(), seq);
///
counter_->prefix.splice(counter_->prefix.end(),
seq_count);
///
// Exit this BFS for this SCC.
while (!todo.empty())
{
@ -211,14 +231,27 @@ namespace spot
if (h_dest == to)
{
cycle_path p;
///
ce::l_state_ce p_counter;
p_counter.push_front(ce::state_ce(h_dest->clone(), cond));
///
p.push_front(state_proposition(h_dest, cond));
while (src != from)
{
const state_proposition& psi = father[src];
///
p_counter.push_front(ce::state_ce(src->clone(), psi.second));
///
p.push_front(state_proposition(src, psi.second));
src = psi.first;
}
period.splice(period.end(), p);
///
counter_->cycle.splice(counter_->cycle.end(),
p_counter);
///
// Exit the BFS, but release all iterators first.
while (!todo.empty())
@ -256,6 +289,9 @@ namespace spot
}
////////////////////////////////////////////////////////////////////////
/*
void
counter_example::accepting_path(const explicit_connected_component* scc,
const state* start, bdd acc_to_traverse)
@ -380,7 +416,12 @@ namespace spot
// Append our best path to the period.
for (cycle_path::iterator it = best_path.begin();
it != best_path.end(); ++it)
period.push_back(*it);
{
period.push_back(*it);
ce::state_ce ce(it->first, it->second);
counter_->cycle.push_back(ce);
counter_->cycle.push_back(*it);
}
// Prepare to find another path for the remaining acceptance
// conditions.
@ -393,6 +434,153 @@ namespace spot
complete_cycle(scc, start, suffix.back());
}
*/
////////////////////////////////////////////////////////////////////////
void
counter_example::accepting_path(const explicit_connected_component* scc,
const state* start, bdd acc_to_traverse)
{
// State seen during the DFS.
typedef Sgi::hash_set<const state*,
state_ptr_hash, state_ptr_equal> set_type;
set_type seen;
// DFS stack.
std::stack<triplet> todo;
while (acc_to_traverse != bddfalse)
{
// Initial state.
{
tgba_succ_iterator* i = ecs_->aut->succ_iter(start);
i->first();
todo.push(triplet(start, i, bddfalse));
seen.insert(start);
}
// The path being explored currently.
cycle_path path;
// The best path seen so far.
cycle_path best_path;
// The acceptance conditions traversed by BEST_PATH.
bdd best_acc = bddfalse;
while (!todo.empty())
{
tgba_succ_iterator* iter = todo.top().iter;
const state* s = todo.top().s;
// Nothing more to explore, backtrack.
if (iter->done())
{
todo.pop();
delete iter;
seen.erase(s);
if (todo.size())
{
assert(path.size());
path.pop_back();
}
continue;
}
// We must not escape the current SCC.
const state* dest = iter->current_state();
const state* h_dest = scc->has_state(dest);
if (!h_dest)
{
delete dest;
iter->next();
continue;
}
bdd acc = iter->current_acceptance_conditions() | todo.top().acc;
path.push_back(state_proposition(h_dest,
iter->current_condition()));
// Advance iterator for next step.
iter->next();
if (seen.find(h_dest) == seen.end())
{
// A new state: continue the DFS.
tgba_succ_iterator* di = ecs_->aut->succ_iter(h_dest);
di->first();
todo.push(triplet(h_dest, di, acc));
seen.insert(h_dest);
continue;
}
// We have completed a full cycle.
// If we already have a best path, let see if the current
// one is better.
if (best_path.size())
{
// When comparing the merits of two paths, only the
// acceptance conditions we are trying the traverse
// are important.
bdd acc_restrict = acc & acc_to_traverse;
bdd best_acc_restrict = best_acc & acc_to_traverse;
// If the best path and the current one traverse the
// same acceptance conditions, we keep the shorter
// path. Otherwise, we keep the path which has the
// more acceptance conditions.
if (best_acc_restrict == acc_restrict)
{
if (best_path.size() <= path.size())
goto backtrack_path;
}
else
{
// `best_acc_restrict >> acc_restrict' is true
// when the set of acceptance conditions of
// best_acc_restrict is included in the set of
// acceptance conditions of acc_restrict.
//
// FIXME: It would be better to count the number
// of acceptance conditions.
if (bddtrue != (best_acc_restrict >> acc_restrict))
goto backtrack_path;
}
}
// The current path the best one.
best_path = path;
best_acc = acc;
backtrack_path:
// Continue exploration from parent to find better paths.
// (Do not pop PATH if ITER is done, because that will be
// done at the top of the loop, among other things.)
if (!iter->done())
path.pop_back();
}
// Append our best path to the period.
for (cycle_path::iterator it = best_path.begin();
it != best_path.end(); ++it)
{
period.push_back(*it);
ce::state_ce ce(it->first->clone(), it->second);
counter_->cycle.push_back(ce);
//counter_->cycle.push_back(*it);
}
// Prepare to find another path for the remaining acceptance
// conditions.
acc_to_traverse -= best_acc;
start = period.back().first;
}
// Complete the path so that it goes back to its beginning,
// forming a cycle.
complete_cycle(scc, start, suffix.back());
}
/////////////
std::ostream&
counter_example::print_result(std::ostream& os, const tgba* restrict) const
{
@ -444,4 +632,10 @@ namespace spot
os << period.size() << " states in period" << std::endl;
}
ce::counter_example*
counter_example::get_counter_example() const
{
return counter_;
}
}