示例#1
0
 /**
  * expect an XmppException with the desired XmppError would be thrown while the State parameter
  * handles the xml string
  *
  * @param state
  * @param xml
  * @param error
  */
 protected void expectXmppException(State state, String xml, XmppError error) {
   try {
     state.step(context, xml);
     fail("Should throw an XmppException");
   } catch (XmppException e) {
     assertSame(error, e.getXmppError());
   }
 }
 /**
  * Returns true if the given string is accepted by the automaton.
  *
  * <p>Complexity: linear in the length of the string.
  *
  * <p><b>Note:</b> for full performance, use the {@link RunAutomaton} class.
  */
 public static boolean run(Automaton a, String s) {
   if (a.isSingleton()) return s.equals(a.singleton);
   if (a.deterministic) {
     State p = a.initial;
     for (int i = 0, cp = 0; i < s.length(); i += Character.charCount(cp)) {
       State q = p.step(cp = s.codePointAt(i));
       if (q == null) return false;
       p = q;
     }
     return p.accept;
   } else {
     State[] states = a.getNumberedStates();
     LinkedList<State> pp = new LinkedList<State>();
     LinkedList<State> pp_other = new LinkedList<State>();
     BitSet bb = new BitSet(states.length);
     BitSet bb_other = new BitSet(states.length);
     pp.add(a.initial);
     ArrayList<State> dest = new ArrayList<State>();
     boolean accept = a.initial.accept;
     for (int i = 0, c = 0; i < s.length(); i += Character.charCount(c)) {
       c = s.codePointAt(i);
       accept = false;
       pp_other.clear();
       bb_other.clear();
       for (State p : pp) {
         dest.clear();
         p.step(c, dest);
         for (State q : dest) {
           if (q.accept) accept = true;
           if (!bb_other.get(q.number)) {
             bb_other.set(q.number);
             pp_other.add(q);
           }
         }
       }
       LinkedList<State> tp = pp;
       pp = pp_other;
       pp_other = tp;
       BitSet tb = bb;
       bb = bb_other;
       bb_other = tb;
     }
     return accept;
   }
 }
示例#3
0
 /**
  * Constructs a new <code>RunAutomaton</code> from a deterministic <code>Automaton</code>. If the
  * given automaton is not deterministic, it is determinized first.
  *
  * @param a an automaton
  * @param tableize if true, a transition table is created which makes the <code>run</code> method
  *     faster in return of a higher memory usage
  */
 public RunAutomaton(Automaton a, boolean tableize) {
   a.determinize();
   points = a.getStartPoints();
   Set<State> states = a.getStates();
   Automaton.setStateNumbers(states);
   initial = a.initial.number;
   size = states.size();
   accept = new boolean[size];
   transitions = new int[size * points.length];
   for (int n = 0; n < size * points.length; n++) transitions[n] = -1;
   for (State s : states) {
     int n = s.number;
     accept[n] = s.accept;
     for (int c = 0; c < points.length; c++) {
       State q = s.step(points[c]);
       if (q != null) transitions[n * points.length + c] = q.number;
     }
   }
   if (tableize) setAlphabet();
 }
 /** Minimizes the given automaton using Hopcroft's algorithm. */
 public static void minimizeHopcroft(Automaton a) {
   a.determinize();
   Set<Transition> tr = a.initial.getTransitions();
   if (tr.size() == 1) {
     Transition t = tr.iterator().next();
     if (t.to == a.initial && t.min == Transition.MIN_VALUE && t.max == Transition.MAX_VALUE)
       return;
   }
   a.totalize();
   // make arrays for numbered states and effective alphabet
   Set<State> ss = a.getStates();
   State[] states = new State[ss.size()];
   int number = 0;
   for (State q : ss) {
     states[number] = q;
     q.number = number++;
   }
   int[] sigma = a.getStartPoints();
   // initialize data structures
   ArrayList<ArrayList<LinkedList<State>>> reverse = new ArrayList<ArrayList<LinkedList<State>>>();
   for (int q = 0; q < states.length; q++) {
     ArrayList<LinkedList<State>> v = new ArrayList<LinkedList<State>>();
     initialize(v, sigma.length);
     reverse.add(v);
   }
   boolean[][] reverse_nonempty = new boolean[states.length][sigma.length];
   ArrayList<LinkedList<State>> partition = new ArrayList<LinkedList<State>>();
   initialize(partition, states.length);
   int[] block = new int[states.length];
   StateList[][] active = new StateList[states.length][sigma.length];
   StateListNode[][] active2 = new StateListNode[states.length][sigma.length];
   LinkedList<IntPair> pending = new LinkedList<IntPair>();
   boolean[][] pending2 = new boolean[sigma.length][states.length];
   ArrayList<State> split = new ArrayList<State>();
   boolean[] split2 = new boolean[states.length];
   ArrayList<Integer> refine = new ArrayList<Integer>();
   boolean[] refine2 = new boolean[states.length];
   ArrayList<ArrayList<State>> splitblock = new ArrayList<ArrayList<State>>();
   initialize(splitblock, states.length);
   for (int q = 0; q < states.length; q++) {
     splitblock.set(q, new ArrayList<State>());
     partition.set(q, new LinkedList<State>());
     for (int x = 0; x < sigma.length; x++) {
       reverse.get(q).set(x, new LinkedList<State>());
       active[q][x] = new StateList();
     }
   }
   // find initial partition and reverse edges
   for (int q = 0; q < states.length; q++) {
     State qq = states[q];
     int j;
     if (qq.accept) j = 0;
     else j = 1;
     partition.get(j).add(qq);
     block[qq.number] = j;
     for (int x = 0; x < sigma.length; x++) {
       int y = sigma[x];
       State p = qq.step(y);
       reverse.get(p.number).get(x).add(qq);
       reverse_nonempty[p.number][x] = true;
     }
   }
   // initialize active sets
   for (int j = 0; j <= 1; j++)
     for (int x = 0; x < sigma.length; x++)
       for (State qq : partition.get(j))
         if (reverse_nonempty[qq.number][x]) active2[qq.number][x] = active[j][x].add(qq);
   // initialize pending
   for (int x = 0; x < sigma.length; x++) {
     int a0 = active[0][x].size;
     int a1 = active[1][x].size;
     int j;
     if (a0 <= a1) j = 0;
     else j = 1;
     pending.add(new IntPair(j, x));
     pending2[x][j] = true;
   }
   // process pending until fixed point
   int k = 2;
   while (!pending.isEmpty()) {
     IntPair ip = pending.removeFirst();
     int p = ip.n1;
     int x = ip.n2;
     pending2[x][p] = false;
     // find states that need to be split off their blocks
     for (StateListNode m = active[p][x].first; m != null; m = m.next)
       for (State s : reverse.get(m.q.number).get(x))
         if (!split2[s.number]) {
           split2[s.number] = true;
           split.add(s);
           int j = block[s.number];
           splitblock.get(j).add(s);
           if (!refine2[j]) {
             refine2[j] = true;
             refine.add(j);
           }
         }
     // refine blocks
     for (int j : refine) {
       if (splitblock.get(j).size() < partition.get(j).size()) {
         LinkedList<State> b1 = partition.get(j);
         LinkedList<State> b2 = partition.get(k);
         for (State s : splitblock.get(j)) {
           b1.remove(s);
           b2.add(s);
           block[s.number] = k;
           for (int c = 0; c < sigma.length; c++) {
             StateListNode sn = active2[s.number][c];
             if (sn != null && sn.sl == active[j][c]) {
               sn.remove();
               active2[s.number][c] = active[k][c].add(s);
             }
           }
         }
         // update pending
         for (int c = 0; c < sigma.length; c++) {
           int aj = active[j][c].size;
           int ak = active[k][c].size;
           if (!pending2[c][j] && 0 < aj && aj <= ak) {
             pending2[c][j] = true;
             pending.add(new IntPair(j, c));
           } else {
             pending2[c][k] = true;
             pending.add(new IntPair(k, c));
           }
         }
         k++;
       }
       for (State s : splitblock.get(j)) split2[s.number] = false;
       refine2[j] = false;
       splitblock.get(j).clear();
     }
     split.clear();
     refine.clear();
   }
   // make a new state for each equivalence class, set initial state
   State[] newstates = new State[k];
   for (int n = 0; n < newstates.length; n++) {
     State s = new State();
     newstates[n] = s;
     for (State q : partition.get(n)) {
       if (q == a.initial) a.initial = s;
       s.accept = q.accept;
       s.number = q.number; // select representative
       q.number = n;
     }
   }
   // build transitions and set acceptance
   for (int n = 0; n < newstates.length; n++) {
     State s = newstates[n];
     s.accept = states[s.number].accept;
     for (Transition t : states[s.number].transitions)
       s.transitions.add(new Transition(t.min, t.max, newstates[t.to.number]));
   }
   a.removeDeadTransitions();
 }