Index: lucene/src/java/org/apache/lucene/util/automaton/MinimizationOperations.java =================================================================== --- lucene/src/java/org/apache/lucene/util/automaton/MinimizationOperations.java (revision 1026182) +++ lucene/src/java/org/apache/lucene/util/automaton/MinimizationOperations.java (working copy) @@ -29,7 +29,7 @@ package org.apache.lucene.util.automaton; -import java.util.ArrayList; +import org.apache.lucene.util.OpenBitSet; import java.util.LinkedList; /** @@ -72,24 +72,18 @@ final int[] sigma = a.getStartPoints(); final State[] states = a.getNumberedStates(); final int sigmaLen = sigma.length, statesLen = states.length; - @SuppressWarnings("unchecked") final LinkedList[][] reverse = - (LinkedList[][]) new LinkedList[statesLen][sigmaLen]; - @SuppressWarnings("unchecked") final LinkedList[] partition = - (LinkedList[]) new LinkedList[statesLen]; - @SuppressWarnings("unchecked") final ArrayList[] splitblock = - (ArrayList[]) new ArrayList[statesLen]; + final OpenBitSet[][] reverse = new OpenBitSet[statesLen][sigmaLen]; + final OpenBitSet[] splitblock = new OpenBitSet[statesLen], partition = new OpenBitSet[statesLen]; final int[] block = new int[statesLen]; final StateList[][] active = new StateList[statesLen][sigmaLen]; final StateListNode[][] active2 = new StateListNode[statesLen][sigmaLen]; final LinkedList pending = new LinkedList(); - final boolean[][] pending2 = new boolean[sigmaLen][statesLen]; - final ArrayList split = new ArrayList(); - final boolean[] split2 = new boolean[statesLen]; - final ArrayList refine = new ArrayList(); - final boolean[] refine2 = new boolean[statesLen]; + final OpenBitSet pending2 = new OpenBitSet(sigmaLen*statesLen); + final OpenBitSet split = new OpenBitSet(statesLen), + refine = new OpenBitSet(statesLen), refine2 = new OpenBitSet(statesLen); for (int q = 0; q < statesLen; q++) { - splitblock[q] = new ArrayList(); - partition[q] = new LinkedList(); + splitblock[q] = new OpenBitSet(statesLen); + partition[q] = new OpenBitSet(statesLen); for (int x = 0; x < sigmaLen; x++) { active[q][x] = new StateList(); } @@ -98,27 +92,31 @@ for (int q = 0; q < statesLen; q++) { final State qq = states[q]; final int j = qq.accept ? 0 : 1; - partition[j].add(qq); - block[qq.number] = j; + partition[j].fastSet(q); + block[q] = j; for (int x = 0; x < sigmaLen; x++) { - final LinkedList[] r = + final OpenBitSet[] r = reverse[qq.step(sigma[x]).number]; if (r[x] == null) - r[x] = new LinkedList(); - r[x].add(qq); + r[x] = new OpenBitSet(); + r[x].fastSet(q); } } // initialize active sets - for (int j = 0; j <= 1; j++) - for (int x = 0; x < sigmaLen; x++) - for (State qq : partition[j]) - if (reverse[qq.number][x] != null) - active2[qq.number][x] = active[j][x].add(qq); + for (int j = 0; j <= 1; j++) { + final OpenBitSet part = partition[j]; + for (int x = 0; x < sigmaLen; x++) { + for (int i = part.nextSetBit(0); i >= 0; i = part.nextSetBit(i+1)) { + if (reverse[i][x] != null) + active2[i][x] = active[j][x].add(states[i]); + } + } + } // initialize pending for (int x = 0; x < sigmaLen; x++) { final int j = (active[0][x].size <= active[1][x].size) ? 0 : 1; pending.add(new IntPair(j, x)); - pending2[x][j] = true; + pending2.fastSet(x*statesLen + j); } // process pending until fixed point int k = 2; @@ -126,68 +124,69 @@ IntPair ip = pending.removeFirst(); final int p = ip.n1; final int x = ip.n2; - pending2[x][p] = false; + pending2.fastClear(x*statesLen + p); // find states that need to be split off their blocks for (StateListNode m = active[p][x].first; m != null; m = m.next) { - final LinkedList r = reverse[m.q.number][x]; - if (r != null) for (State s : r) { - if (!split2[s.number]) { - split2[s.number] = true; - split.add(s); - final int j = block[s.number]; - splitblock[j].add(s); - if (!refine2[j]) { - refine2[j] = true; - refine.add(j); + final OpenBitSet r = reverse[m.q.number][x]; + if (r != null) for (int i = r.nextSetBit(0); i >= 0; i = r.nextSetBit(i+1)) { + if (!split.fastGet(i)) { + split.fastSet(i); + final int j = block[i]; + splitblock[j].fastSet(i); + if (!refine2.fastGet(j)) { + refine2.fastSet(j); + refine.fastSet(j); } } } } // refine blocks - for (int j : refine) { - if (splitblock[j].size() < partition[j].size()) { - final LinkedList b1 = partition[j]; - final LinkedList b2 = partition[k]; - for (State s : splitblock[j]) { - b1.remove(s); - b2.add(s); - block[s.number] = k; + for (int j = refine.nextSetBit(0); j >= 0; j = refine.nextSetBit(j+1)) { + final OpenBitSet sb = splitblock[j]; + if (sb.cardinality() < partition[j].cardinality()) { + final OpenBitSet b1 = partition[j], b2 = partition[k]; + for (int i = sb.nextSetBit(0); i >= 0; i = sb.nextSetBit(i+1)) { + b1.fastClear(i); + b2.fastSet(i); + block[i] = k; for (int c = 0; c < sigmaLen; c++) { - final StateListNode sn = active2[s.number][c]; + final StateListNode sn = active2[i][c]; if (sn != null && sn.sl == active[j][c]) { sn.remove(); - active2[s.number][c] = active[k][c].add(s); + active2[i][c] = active[k][c].add(states[i]); } } } // update pending for (int c = 0; c < sigmaLen; c++) { - final int aj = active[j][c].size; - final int ak = active[k][c].size; - if (!pending2[c][j] && 0 < aj && aj <= ak) { - pending2[c][j] = true; + final int aj = active[j][c].size, + ak = active[k][c].size, + ofs = c*statesLen; + if (!pending2.fastGet(ofs + j) && 0 < aj && aj <= ak) { + pending2.fastSet(ofs + j); pending.add(new IntPair(j, c)); } else { - pending2[c][k] = true; + pending2.fastSet(ofs + k); pending.add(new IntPair(k, c)); } } k++; } - for (State s : splitblock[j]) - split2[s.number] = false; - refine2[j] = false; - splitblock[j].clear(); + refine2.fastClear(j); + for (int i = sb.nextSetBit(0); i >= 0; i = sb.nextSetBit(i+1)) + split.fastClear(i); + sb.clear(0, sb.size()); } - split.clear(); - refine.clear(); + refine.clear(0, refine.size()); } // make a new state for each equivalence class, set initial state State[] newstates = new State[k]; for (int n = 0; n < newstates.length; n++) { final State s = new State(); newstates[n] = s; - for (State q : partition[n]) { + OpenBitSet part = partition[n]; + for (int i = part.nextSetBit(0); i >= 0; i = part.nextSetBit(i+1)) { + final State q = states[i]; if (q == a.initial) a.initial = s; s.accept = q.accept; s.number = q.number; // select representative