ArrayList<TIntHashSet> layer = new ArrayList<TIntHashSet>();
TIntHashSet[] tmpQ = new TIntHashSet[totalSizes];
// DLList[vars.length+1];
for (i = 0; i <= size; i++) {
layer.add(new TIntHashSet());// = new DLList(nbNodes);
}
//forward pass, construct all paths described by the automaton for word of length nbVars.
layer.get(0).add(pi.getInitialState());
TIntHashSet succ = new TIntHashSet();
for (i = 0; i < size; i++) {
int ub = vars[i].getUB();
for (j = vars[i].getLB(); j <= ub; j = vars[i].nextValue(j)) {
layerIter = layer.get(i).iterator();
while (layerIter.hasNext()) {
k = layerIter.next();
succ.clear();
pi.delta(k, j, succ);
if (!succ.isEmpty()) {
TIntIterator it = succ.iterator();
for (; it.hasNext(); )
layer.get(i + 1).add(it.next());
int idx = starts[i] + j - offsets[i];
if (tmpQ[idx] == null)
tmpQ[idx] = new TIntHashSet();
tmpQ[idx].add(k);
}
}
}
}
//removing reachable non accepting states
layerIter = layer.get(size).iterator();
while (layerIter.hasNext()) {
k = layerIter.next();
if (!pi.isFinal(k)) {
layerIter.remove();
}
}
//backward pass, removing arcs that does not lead to an accepting state
int nbNodes = pi.getNbStates();
BitSet mark = new BitSet(nbNodes);
Node[] in = new Node[pi.getNbStates() * (size + 1)];
Node tink = new Node(pi.getNbStates() + 1, size + 1, nid++);
graph.addVertex(tink);
for (i = size - 1; i >= 0; i--) {
mark.clear(0, nbNodes);
int ub = vars[i].getUB();
for (j = vars[i].getLB(); j <= ub; j = vars[i].nextValue(j)) {
int idx = starts[i] + j - offsets[i];
TIntHashSet l = tmpQ[idx];
if (l != null) {
qijIter = l.iterator();
while (qijIter.hasNext()) {
k = qijIter.next();
succ.clear();
pi.delta(k, j, succ);
TIntIterator it = succ.iterator();
boolean added = false;
for (; it.hasNext(); ) {
int qn = it.next();
if (layer.get(i + 1).contains(qn)) {
added = true;
Node a = in[i * pi.getNbStates() + k];
if (a == null) {
a = new Node(k, i, nid++);
in[i * pi.getNbStates() + k] = a;
graph.addVertex(a);
}
Node b = in[(i + 1) * pi.getNbStates() + qn];
if (b == null) {
b = new Node(qn, i + 1, nid++);
in[(i + 1) * pi.getNbStates() + qn] = b;
graph.addVertex(b);
}
Arc arc = new Arc(a, b, j, aid++, pi.getCostByState(i, j, a.state));
graph.addEdge(a, b, arc);
tmp.get(idx).add(arc);
mark.set(k);
}
}
if (!added)
qijIter.remove();
}
}
}
layerIter = layer.get(i).iterator();
// If no more arcs go out of a given state in the layer, then we remove the state from that layer
while (layerIter.hasNext())
if (!mark.get(layerIter.next()))
layerIter.remove();
}
TIntHashSet th = new TIntHashSet();
int[][] intLayer = new int[size + 2][];
for (k = 0; k < pi.getNbStates(); k++) {
Node o = in[size * pi.getNbStates() + k];
{
if (o != null) {
Arc a = new Arc(o, tink, 0, aid++, 0.0);
graph.addEdge(o, tink, a);
}
}
}
for (i = 0; i <= size; i++) {
th.clear();
for (k = 0; k < pi.getNbStates(); k++) {
Node o = in[i * pi.getNbStates() + k];
if (o != null) {
th.add(o.id);
}
}
intLayer[i] = th.toArray();
}
intLayer[size + 1] = new int[]{tink.id};
if (intLayer[0].length > 0)