Fix random_graph() not to generate dead states.

This is actually the third time I fix random_graph().  On
2007-02-06 I changed the function not to generated dead states,
but in a way that made it non-deterministic.  On 2010-01-20 I made
the function deterministic again, but it started to generate dead
states as a side effect.  This time, I'm making sure that dead
states won't come again with a test-case that we should have had
from the beginning.

* src/tgbaalgos/randomgraph.cc (random_graph): Add an extra
indirection array, state_randomizer[], so that we can reorder
states indices after a random selection without actually changing
the value of the indices used by unreachable_states and
nodes_to_process.
* src/tgbatest/randtgba.test: New file.
* src/tgbatest/Makefile.am: Add randtgba.test.
This commit is contained in:
Alexandre Duret-Lutz 2010-02-23 17:20:59 +01:00
parent 72b7deec12
commit 2183276008
4 changed files with 72 additions and 9 deletions

View file

@ -108,6 +108,8 @@ namespace spot
props[pi++] = dict->register_proposition(*i, res);
std::vector<tgba_explicit::state*> states(n);
// Indirect access to state[] to help random selection of successors.
std::vector<int> state_randomizer(n);
std::list<bdd> accs;
bdd allneg = bddtrue;
@ -134,11 +136,13 @@ namespace spot
node_set unreachable_nodes;
states[0] = res->add_state(st(0));
state_randomizer[0] = 0;
nodes_to_process.insert(0);
for (int i = 1; i < n; ++i)
{
states[i] = res->add_state(st(i));
state_randomizer[i] = i;
unreachable_nodes.insert(i);
}
@ -163,6 +167,8 @@ namespace spot
int possibilities = n;
while (nsucc--)
{
// No connection to unreachable successors so far. This
// is our last chance, so force it now.
if (nsucc == 0
&& !saw_unreachable
&& !unreachable_nodes.empty())
@ -180,21 +186,23 @@ namespace spot
}
else
{
// Pick a random node.
// Pick the index of a random node.
int index = mrand(possibilities--);
tgba_explicit::state* dest = states[index];
// Permute the state with states[possibilities], so we
// cannot pick it again.
states[index] = states[possibilities];
states[possibilities] = dest;
// Permute it with state_randomizer[possibilities], so
// we cannot pick it again.
int x = state_randomizer[index];
state_randomizer[index] = state_randomizer[possibilities];
state_randomizer[possibilities] = x;
tgba_explicit::state* dest = states[x];
random_labels(res, src, dest, props, props_n, t, accs, a);
node_set::iterator j = unreachable_nodes.find(possibilities);
node_set::iterator j = unreachable_nodes.find(x);
if (j != unreachable_nodes.end())
{
nodes_to_process.insert(possibilities);
nodes_to_process.insert(x);
unreachable_nodes.erase(j);
saw_unreachable = true;
}