* src/tgbaalgos/emptinesscheck.cc (triplet): New class.
(emptiness_check::accepting_path): Simplify, comment, derecursive, and free memory...
This commit is contained in:
parent
20ca78a9b4
commit
89fddaaa81
3 changed files with 135 additions and 97 deletions
|
|
@ -1,3 +1,9 @@
|
||||||
|
2003-10-28 Alexandre Duret-Lutz <adl@src.lip6.fr>
|
||||||
|
|
||||||
|
* src/tgbaalgos/emptinesscheck.cc (triplet): New class.
|
||||||
|
(emptiness_check::accepting_path):
|
||||||
|
Simplify, comment, derecursive, and free memory...
|
||||||
|
|
||||||
2003-10-27 Alexandre Duret-Lutz <adl@src.lip6.fr>
|
2003-10-27 Alexandre Duret-Lutz <adl@src.lip6.fr>
|
||||||
|
|
||||||
* src/tgbaalgos/emptinesscheck.cc (connected_component): Split
|
* src/tgbaalgos/emptinesscheck.cc (connected_component): Split
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@
|
||||||
namespace spot
|
namespace spot
|
||||||
{
|
{
|
||||||
typedef std::pair<const spot::state*, tgba_succ_iterator*> pair_state_iter;
|
typedef std::pair<const spot::state*, tgba_succ_iterator*> pair_state_iter;
|
||||||
typedef std::pair<pair_state_iter, bdd> triplet;
|
|
||||||
|
|
||||||
emptiness_check::connected_component::connected_component(int i)
|
emptiness_check::connected_component::connected_component(int i)
|
||||||
{
|
{
|
||||||
|
|
@ -451,112 +450,145 @@ namespace spot
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Derecursive this function.
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
struct triplet
|
||||||
|
{
|
||||||
|
const state* s; // Current state.
|
||||||
|
tgba_succ_iterator* iter; // Iterator to successor of the current state.
|
||||||
|
bdd acc; // All acceptance conditions traversed by
|
||||||
|
// the path so far.
|
||||||
|
|
||||||
|
triplet (const state* s, tgba_succ_iterator* iter, bdd acc)
|
||||||
|
: s(s), iter(iter), acc(acc)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
emptiness_check::accepting_path(const connected_component_set& comp_path,
|
emptiness_check::accepting_path(const connected_component_set& scc,
|
||||||
const state* start_path, bdd to_accept)
|
const state* start, bdd acc_to_traverse)
|
||||||
{
|
{
|
||||||
hash_type seen_priority;
|
// State seen during the DFS.
|
||||||
std::stack<triplet> todo_path;
|
connected_component_set::set_type seen;
|
||||||
tgba_succ_iterator* t_s_i = aut_->succ_iter(start_path);
|
// DFS stack.
|
||||||
t_s_i->first();
|
std::stack<triplet> todo;
|
||||||
todo_path.push(triplet(pair_state_iter(start_path, t_s_i), bddfalse));
|
|
||||||
bdd tmp_acc = bddfalse;
|
while (acc_to_traverse != bddfalse)
|
||||||
|
{
|
||||||
|
// Initial state.
|
||||||
|
{
|
||||||
|
tgba_succ_iterator* i = 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;
|
bdd best_acc = bddfalse;
|
||||||
cycle_path tmp_lst;
|
|
||||||
cycle_path best_lst;
|
while (!todo.empty())
|
||||||
bool ok = false;
|
|
||||||
seen_priority[start_path] = h[start_path];
|
|
||||||
while (!todo_path.empty())
|
|
||||||
{
|
{
|
||||||
triplet step_ = todo_path.top();
|
tgba_succ_iterator* iter = todo.top().iter;
|
||||||
tgba_succ_iterator* iter_ = step_.first.second;
|
const state* s = todo.top().s;
|
||||||
if (iter_->done())
|
|
||||||
|
// Nothing more to explore, backtrack.
|
||||||
|
if (iter->done())
|
||||||
{
|
{
|
||||||
todo_path.pop();
|
todo.pop();
|
||||||
seen_priority.erase(step_.first.first);
|
delete iter;
|
||||||
tmp_lst.pop_back();
|
seen.erase(s);
|
||||||
|
path.pop_back();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const state* dest = iter->current_state();
|
||||||
|
|
||||||
|
// We must not escape the current SCC.
|
||||||
|
if (!scc.has_state(dest))
|
||||||
|
{
|
||||||
|
delete dest;
|
||||||
|
iter->next();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
dest = h_filt(dest);
|
||||||
|
bdd acc = iter->current_accepting_conditions() | todo.top().acc;
|
||||||
|
path.push_back(state_proposition(dest, iter->current_condition()));
|
||||||
|
|
||||||
|
// Advance iterator for next step.
|
||||||
|
iter->next();
|
||||||
|
|
||||||
|
if (seen.find(dest) == seen.end())
|
||||||
|
{
|
||||||
|
// A new state: continue the DFS.
|
||||||
|
tgba_succ_iterator* di = aut_->succ_iter(dest);
|
||||||
|
di->first();
|
||||||
|
todo.push(triplet(dest, di, acc));
|
||||||
|
seen.insert(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())
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
state* curr_state = iter_->current_state();
|
// `best_acc_restrict >> acc_restrict' is true
|
||||||
if (comp_path.has_state(curr_state))
|
// when the set of acceptance conditions of
|
||||||
{
|
// best_acc_restrict is included in the set of
|
||||||
hash_type::iterator i = seen_priority.find(curr_state);
|
// acceptance conditions of acc_restrict.
|
||||||
if (i == seen_priority.end())
|
//
|
||||||
{
|
// FIXME: It would be better to count the number
|
||||||
tgba_succ_iterator* c_iter = aut_->succ_iter(curr_state);
|
// of accepting conditions.
|
||||||
bdd curr_bdd =
|
if (bddtrue != (best_acc_restrict >> acc_restrict))
|
||||||
iter_->current_accepting_conditions() | step_.second;
|
continue;
|
||||||
c_iter->first();
|
|
||||||
todo_path.push(triplet(pair_state_iter(curr_state, c_iter),
|
|
||||||
curr_bdd));
|
|
||||||
tmp_lst.push_back(state_proposition(curr_state,
|
|
||||||
iter_->current_condition()));
|
|
||||||
seen_priority[curr_state] = h[curr_state];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (ok)
|
|
||||||
{
|
|
||||||
bdd last_ = iter_->current_accepting_conditions();
|
|
||||||
bdd prop_ = iter_->current_condition();
|
|
||||||
tmp_lst.push_back(state_proposition(curr_state, prop_));
|
|
||||||
tmp_acc = last_ | step_.second;
|
|
||||||
bdd curr_in = tmp_acc & to_accept;
|
|
||||||
bdd best_in = best_acc & to_accept;
|
|
||||||
if (curr_in == best_in)
|
|
||||||
{
|
|
||||||
if (tmp_lst.size() < best_lst.size())
|
|
||||||
{
|
|
||||||
cycle_path tmp(tmp_lst);
|
|
||||||
best_lst = tmp;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
// The current path the best one.
|
||||||
if (bddtrue == (best_in >> curr_in))
|
best_path = path;
|
||||||
{
|
best_acc = acc;
|
||||||
cycle_path tmp(tmp_lst);
|
|
||||||
best_lst = tmp;
|
|
||||||
best_acc = tmp_acc;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
// Append our best path to the period.
|
||||||
else
|
for (cycle_path::iterator it = best_path.begin();
|
||||||
{
|
it != best_path.end(); ++it)
|
||||||
bdd last_ = iter_->current_accepting_conditions();
|
|
||||||
bdd prop_ = iter_->current_condition();
|
|
||||||
tmp_acc = last_ | step_.second;
|
|
||||||
tmp_lst.push_back(state_proposition(curr_state,
|
|
||||||
prop_));
|
|
||||||
cycle_path tmp(tmp_lst);
|
|
||||||
best_lst = tmp;
|
|
||||||
best_acc = tmp_acc;
|
|
||||||
ok = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
iter_->next();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (cycle_path::iterator it = best_lst.begin();
|
|
||||||
it != best_lst.end(); ++it)
|
|
||||||
period.push_back(*it);
|
period.push_back(*it);
|
||||||
|
|
||||||
if (best_acc != to_accept)
|
// Prepare to find another path for the remaining acceptance
|
||||||
{
|
// conditions.
|
||||||
bdd rec_to_acc = to_accept - best_acc;
|
acc_to_traverse -= best_acc;
|
||||||
accepting_path(comp_path, period.back().first, rec_to_acc);
|
start = period.back().first;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!period.empty())
|
|
||||||
{
|
|
||||||
/// The path contains all accepting conditions. Then we
|
|
||||||
///complete the cycle in this SCC by calling complete_cycle.
|
|
||||||
complete_cycle(comp_path, period.back().first, suffix.back());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Complete the path so that it goes back to its beginning,
|
||||||
|
// forming a cycle.
|
||||||
|
complete_cycle(scc, start, suffix.back());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -102,12 +102,12 @@ namespace spot
|
||||||
/// Called by counter_example to find a path which traverses all
|
/// Called by counter_example to find a path which traverses all
|
||||||
/// accepting conditions in the accepted SCC.
|
/// accepting conditions in the accepted SCC.
|
||||||
void accepting_path (const connected_component_set& comp_path,
|
void accepting_path (const connected_component_set& comp_path,
|
||||||
const state* start_path, bdd to_accept);
|
const state* start_path, bdd acc_to_traverse);
|
||||||
|
|
||||||
/// Complete a cycle that caraterise the period of the counter
|
/// Complete a cycle that caraterise the period of the counter
|
||||||
/// example. Append a sequence to the path given by accepting_path.
|
/// example. Append a sequence to the path given by accepting_path.
|
||||||
void complete_cycle(const connected_component_set& comp_path,
|
void complete_cycle(const connected_component_set& comp_path,
|
||||||
const state* from_state,const state* to_state);
|
const state* from_state, const state* to_state);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif // SPOT_EMPTINESS_CHECK_HH
|
#endif // SPOT_EMPTINESS_CHECK_HH
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue