* src/tgbaalgos/tau03opt.cc: Add a first version of the computation of
accepting runs
This commit is contained in:
parent
e58743dbb7
commit
0531dfe6e5
2 changed files with 244 additions and 28 deletions
|
|
@ -1,3 +1,8 @@
|
|||
2004-11-29 Denis Poitrenaud <Denis.Poitrenaud@lip6.fr>
|
||||
|
||||
* src/tgbaalgos/tau03opt.cc: Add a first version of the computation of
|
||||
accepting runs
|
||||
|
||||
2004-11-29 Alexandre Duret-Lutz <adl@src.lip6.fr>
|
||||
|
||||
* src/tgbaalgos/minimizerun.cc, src/tgbaalgos/minimizerun.hh
|
||||
|
|
|
|||
|
|
@ -20,10 +20,9 @@
|
|||
// 02111-1307, USA.
|
||||
|
||||
/// FIXME:
|
||||
/// * Add the necessary calls to pop_notify in the subclass result.
|
||||
///
|
||||
/// * Add the computation of a counter example if detected.
|
||||
///
|
||||
/// * Add some heuristics on the order of visit of the successors in the blue
|
||||
/// * Test some heuristics on the order of visit of the successors in the blue
|
||||
/// dfs:
|
||||
/// - favorize the arcs conducting to the blue stack (the states of color
|
||||
/// cyan)
|
||||
|
|
@ -90,7 +89,7 @@ namespace spot
|
|||
}
|
||||
}
|
||||
|
||||
/// \brief Perform a Magic Search.
|
||||
/// \brief Perform an emptiness check.
|
||||
///
|
||||
/// \return non null pointer iff the algorithm has found an
|
||||
/// accepting path.
|
||||
|
|
@ -104,10 +103,7 @@ namespace spot
|
|||
h.add_new_state(s0, CYAN, current_weight);
|
||||
push(st_blue, s0, bddfalse, bddfalse);
|
||||
if (dfs_blue())
|
||||
if (a_->number_of_acceptance_conditions() <=1)
|
||||
return new result(*this);
|
||||
else
|
||||
return new emptiness_check_result(a_);
|
||||
return new result(*this);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -343,6 +339,19 @@ namespace spot
|
|||
ms_(ms)
|
||||
{
|
||||
}
|
||||
virtual ~result()
|
||||
{
|
||||
while (!st1.empty())
|
||||
{
|
||||
delete st1.front().it;
|
||||
st1.pop_front();
|
||||
}
|
||||
while (!st2.empty())
|
||||
{
|
||||
delete st2.front().it;
|
||||
st2.pop_front();
|
||||
}
|
||||
}
|
||||
virtual tgba_run* accepting_run()
|
||||
{
|
||||
assert(!ms_.st_blue.empty());
|
||||
|
|
@ -350,45 +359,247 @@ namespace spot
|
|||
|
||||
tgba_run* run = new tgba_run;
|
||||
|
||||
typename stack_type::const_reverse_iterator i, j, end;
|
||||
tgba_run::steps* l;
|
||||
|
||||
const state* target = ms_.st_red.front().s;
|
||||
bdd covered_acc = bddfalse;
|
||||
typename stack_type::const_reverse_iterator i, j, end;
|
||||
|
||||
l = &run->prefix;
|
||||
|
||||
i = ms_.st_blue.rbegin();
|
||||
end = ms_.st_blue.rend(); --end;
|
||||
j = i; ++j;
|
||||
for (; i != end; ++i, ++j)
|
||||
i = j = ms_.st_blue.rbegin(); ++j;
|
||||
for (; i->s->compare(target) != 0; ++i, ++j)
|
||||
{
|
||||
if (l == &run->prefix && i->s->compare(target) == 0)
|
||||
l = &run->cycle;
|
||||
tgba_run::step s = { i->s->clone(), j->label, j->acc };
|
||||
l->push_back(s);
|
||||
run->prefix.push_back(s);
|
||||
}
|
||||
|
||||
if (l == &run->prefix && i->s->compare(target) == 0)
|
||||
l = &run->cycle;
|
||||
assert(l == &run->cycle);
|
||||
end = ms_.st_blue.rend();
|
||||
for (; j != end; ++i, ++j)
|
||||
{
|
||||
covered_acc |= j->acc;
|
||||
tgba_run::step s = { i->s->clone(), j->label, j->acc };
|
||||
run->cycle.push_back(s);
|
||||
}
|
||||
|
||||
j = ms_.st_red.rbegin();
|
||||
covered_acc |= j->acc;
|
||||
tgba_run::step s = { i->s->clone(), j->label, j->acc };
|
||||
l->push_back(s);
|
||||
run->cycle.push_back(s);
|
||||
|
||||
i = j; ++j;
|
||||
end = ms_.st_red.rend(); --end;
|
||||
for (; i != end; ++i, ++j)
|
||||
end = ms_.st_red.rend();
|
||||
for (; j != end; ++i, ++j)
|
||||
{
|
||||
covered_acc |= j->acc;
|
||||
tgba_run::step s = { i->s->clone(), j->label, j->acc };
|
||||
l->push_back(s);
|
||||
run->cycle.push_back(s);
|
||||
}
|
||||
|
||||
if (ms_.all_acc != covered_acc)
|
||||
{
|
||||
ms_.push(st1, target, bddfalse, bddfalse);
|
||||
bool b = dfs1(target, run->cycle, covered_acc);
|
||||
assert(b);
|
||||
(void)b;
|
||||
}
|
||||
|
||||
return run;
|
||||
}
|
||||
|
||||
private:
|
||||
stack_type st1, st2;
|
||||
tau03_opt_search& ms_;
|
||||
};
|
||||
|
||||
void complete_cycle(tgba_run::steps& cycle, bdd& covered_acc)
|
||||
{
|
||||
tgba_run::steps new_cycle;
|
||||
typename stack_type::const_reverse_iterator i, j, end;
|
||||
|
||||
i = j = st1.rbegin(); ++j;
|
||||
end = st1.rend();
|
||||
for (; j != end; ++i, ++j)
|
||||
{
|
||||
covered_acc |= j->acc;
|
||||
tgba_run::step s = { i->s->clone(), j->label, j->acc };
|
||||
new_cycle.push_back(s);
|
||||
}
|
||||
|
||||
j = st2.rbegin();
|
||||
covered_acc |= j->acc;
|
||||
tgba_run::step s = { i->s->clone(), j->label, j->acc };
|
||||
new_cycle.push_back(s);
|
||||
|
||||
i = j; ++j;
|
||||
end = st2.rend();
|
||||
for (; j != end; ++i, ++j)
|
||||
{
|
||||
covered_acc |= j->acc;
|
||||
tgba_run::step s = { i->s->clone(), j->label, j->acc };
|
||||
new_cycle.push_back(s);
|
||||
}
|
||||
cycle.splice(cycle.end(), new_cycle);
|
||||
}
|
||||
|
||||
typedef Sgi::hash_map<const state*, bdd,
|
||||
state_ptr_hash, state_ptr_equal> seen_type;
|
||||
|
||||
bool dfs1(const state* target, tgba_run::steps& cycle, bdd& covered_acc)
|
||||
{
|
||||
seen_type seen;
|
||||
seen.insert(std::make_pair(target, covered_acc));
|
||||
while (!st1.empty())
|
||||
{
|
||||
stack_item& f = st1.front();
|
||||
trace << "DFS1 treats: " << a_->format_state(f.s) << std::endl;
|
||||
if (!f.it->done())
|
||||
{
|
||||
const state *s_prime = f.it->current_state();
|
||||
trace << " Visit the successor: "
|
||||
<< a_->format_state(s_prime) << std::endl;
|
||||
bdd label = f.it->current_condition();
|
||||
bdd acc = f.it->current_acceptance_conditions();
|
||||
f.it->next();
|
||||
typename heap::color_ref c_prime =
|
||||
ms_.h.get_color_ref(s_prime);
|
||||
if (!c_prime.is_white())
|
||||
{
|
||||
seen_type::iterator it = seen.find(s_prime);
|
||||
if (it == seen.end())
|
||||
{
|
||||
trace << " it is not seen, go down" << std::endl;
|
||||
seen.insert(std::make_pair(s_prime, covered_acc));
|
||||
ms_.push(st1, s_prime, label, acc);
|
||||
}
|
||||
else if ((acc & (it->second | covered_acc)) != acc)
|
||||
{
|
||||
it->second |= acc;
|
||||
ms_.push(st2, s_prime, label, acc);
|
||||
trace << " a propagation is needed, start a dfs2"
|
||||
<< std::endl;
|
||||
if (dfs2(seen, target, cycle, covered_acc, acc))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
delete s_prime;
|
||||
}
|
||||
else
|
||||
{
|
||||
trace << " all the successors have been visited"
|
||||
<< std::endl;
|
||||
stack_item f_dest(f);
|
||||
ms_.pop(st1);
|
||||
if (!st1.empty())
|
||||
{
|
||||
seen_type::iterator it = seen.find(f_dest.s);
|
||||
assert(it != seen.end());
|
||||
if ((f_dest.acc & (it->second | covered_acc)) !=
|
||||
f_dest.acc)
|
||||
{
|
||||
it->second |= f_dest.acc | covered_acc;
|
||||
ms_.push(st2, f_dest.s, f_dest.label, f_dest.acc);
|
||||
trace << " a propagation is needed, start a dfs2"
|
||||
<< std::endl;
|
||||
if (dfs2(seen, target, cycle, covered_acc,
|
||||
f_dest.acc))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool dfs2(seen_type& seen, const state* target, tgba_run::steps& cycle,
|
||||
bdd& covered_acc, const bdd& acu)
|
||||
{
|
||||
if (st2.front().s->compare(target)==0)
|
||||
{
|
||||
trace << " complete the cycle" << std::endl;
|
||||
complete_cycle(cycle, covered_acc);
|
||||
delete st2.front().it;
|
||||
st2.pop_front();
|
||||
if (covered_acc == ms_.all_acc)
|
||||
{
|
||||
trace << " the cycle is complete, report it"
|
||||
<< std::endl;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
typedef Sgi::hash_set<const state*,
|
||||
state_ptr_hash, state_ptr_equal> l_seen_type;
|
||||
l_seen_type l_seen;
|
||||
|
||||
while (!st2.empty())
|
||||
{
|
||||
stack_item& f = st2.front();
|
||||
trace << "DFS2 treats: " << a_->format_state(f.s) << std::endl;
|
||||
if (!f.it->done())
|
||||
{
|
||||
const state *s_prime = f.it->current_state();
|
||||
trace << " Visit the successor: "
|
||||
<< a_->format_state(s_prime) << std::endl;
|
||||
bdd label = f.it->current_condition();
|
||||
bdd acc = f.it->current_acceptance_conditions();
|
||||
f.it->next();
|
||||
typename heap::color_ref c_prime =
|
||||
ms_.h.get_color_ref(s_prime);
|
||||
if (!c_prime.is_white())
|
||||
{
|
||||
seen_type::iterator it = seen.find(s_prime);
|
||||
if (it != seen.end())
|
||||
{
|
||||
if ((acu & (it->second | covered_acc)) != acu)
|
||||
{
|
||||
it->second |= acu | covered_acc;
|
||||
ms_.push(st2, s_prime, label, acc);
|
||||
if (s_prime->compare(target)==0)
|
||||
{
|
||||
trace << " complete the cycle" << std::endl;
|
||||
complete_cycle(cycle, covered_acc);
|
||||
while (!st2.empty())
|
||||
{
|
||||
delete st2.front().it;
|
||||
st2.pop_front();
|
||||
}
|
||||
if (covered_acc == ms_.all_acc)
|
||||
{
|
||||
trace << " the cycle is complete, "
|
||||
<< "report it" << std::endl;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (l_seen.find(s_prime) == l_seen.end())
|
||||
{
|
||||
l_seen.insert(s_prime);
|
||||
ms_.push(st2, s_prime, label, acc);
|
||||
trace << " the propagation continues"
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
trace << " it is unknown, pop it"
|
||||
<< std::endl;
|
||||
delete s_prime;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
trace << " all the successors have been visited, pop it"
|
||||
<< std::endl;
|
||||
ms_.pop(st2);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue