public RandomAcceptedStrings(Automaton a)
{
this.a = a;
if (!String.IsNullOrEmpty(a.Singleton))
{
LeadsToAccept = null;
return;
}
// must use IdentityHashmap because two Transitions w/
// different start nodes can be considered the same
LeadsToAccept = new IdentityHashMap<Transition, bool?>();
IDictionary<State, IList<ArrivingTransition>> allArriving = new Dictionary<State, IList<ArrivingTransition>>();
LinkedList<State> q = new LinkedList<State>();
HashSet<State> seen = new HashSet<State>();
// reverse map the transitions, so we can quickly look
// up all arriving transitions to a given state
foreach (State s in a.NumberedStates)
{
for (int i = 0; i < s.numTransitions; i++)
{
Transition t = s.TransitionsArray[i];
IList<ArrivingTransition> tl;
allArriving.TryGetValue(t.Dest, out tl);
if (tl == null)
{
tl = new List<ArrivingTransition>();
allArriving[t.Dest] = tl;
}
tl.Add(new ArrivingTransition(s, t));
}
if (s.Accept)
{
q.AddLast(s);
seen.Add(s);
}
}
// Breadth-first search, from accept states,
// backwards:
while (q.Count > 0)
{
State s = q.First.Value;
q.RemoveFirst();
IList<ArrivingTransition> arriving;
allArriving.TryGetValue(s, out arriving);
if (arriving != null)
{
foreach (ArrivingTransition at in arriving)
{
State from = at.From;
if (!seen.Contains(from))
{
q.AddLast(from);
seen.Add(from);
LeadsToAccept[at.t] = true;
}
}
}
}
}