public void resetState(Automaton a, int state) { assert a.getNumTransitions(state) != 0; this.state = state; transition = 0; a.getTransition(state, 0, t); label = t.min; to = t.dest; }
/** Returns next label of current transition, or * advances to next transition and returns its first * label, if current one is exhausted. If there are * no more transitions, returns -1. */ public int nextLabel(Automaton a) { if (label > t.max) { // We've exhaused the current transition's labels; // move to next transitions: transition++; if (transition >= a.getNumTransitions(state)) { // We're done iterating transitions leaving this state label = -1; return -1; } a.getTransition(state, transition, t); label = t.min; to = t.dest; } return label++; } }
/** * Checks whether there is a loop containing state. (This is sufficient since * there are never transitions to dead states.) */ // TODO: not great that this is recursive... in theory a // large automata could exceed java's stack so the maximum level of recursion is bounded to 1000 private static boolean isFinite(Transition scratch, Automaton a, int state, BitSet path, BitSet visited, int level) { if (level > MAX_RECURSION_LEVEL) { throw new IllegalArgumentException("input automaton is too large: " + level); } path.set(state); int numTransitions = a.initTransition(state, scratch); for(int t=0;t<numTransitions;t++) { a.getTransition(state, t, scratch); if (path.get(scratch.dest) || (!visited.get(scratch.dest) && !isFinite(scratch, a, scratch.dest, path, visited, level+1))) { return false; } } path.clear(state); visited.set(state); return true; }
/** * Returns the longest string that is a prefix of all accepted strings and * visits each state at most once. The automaton must be deterministic. * * @return common prefix, which can be an empty (length 0) String (never null) */ public static String getCommonPrefix(Automaton a) { if (a.isDeterministic() == false) { throw new IllegalArgumentException("input automaton must be deterministic"); } StringBuilder b = new StringBuilder(); HashSet<Integer> visited = new HashSet<>(); int s = 0; boolean done; Transition t = new Transition(); do { done = true; visited.add(s); if (a.isAccept(s) == false && a.getNumTransitions(s) == 1) { a.getTransition(s, 0, t); if (t.min == t.max && !visited.contains(t.dest)) { b.appendCodePoint(t.min); s = t.dest; done = false; } } } while (!done); return b.toString(); }
/** * Returns true if the given automaton accepts all strings for the specified min/max * range of the alphabet. The automaton must be minimized. */ public static boolean isTotal(Automaton a, int minAlphabet, int maxAlphabet) { if (a.isAccept(0) && a.getNumTransitions(0) == 1) { Transition t = new Transition(); a.getTransition(0, 0, t); return t.dest == 0 && t.min == minAlphabet && t.max == maxAlphabet; } return false; }
/** Sugar to get all transitions for all states. This is * object-heavy; it's better to iterate state by state instead. */ public Transition[][] getSortedTransitions() { int numStates = getNumStates(); Transition[][] transitions = new Transition[numStates][]; for(int s=0;s<numStates;s++) { int numTransitions = getNumTransitions(s); transitions[s] = new Transition[numTransitions]; for(int t=0;t<numTransitions;t++) { Transition transition = new Transition(); getTransition(s, t, transition); transitions[s][t] = transition; } } return transitions; }
/** * Returns the longest BytesRef that is a prefix of all accepted strings and * visits each state at most once. The automaton must be deterministic. * * @return common prefix, which can be an empty (length 0) BytesRef (never null) */ public static BytesRef getCommonPrefixBytesRef(Automaton a) { BytesRefBuilder builder = new BytesRefBuilder(); HashSet<Integer> visited = new HashSet<>(); int s = 0; boolean done; Transition t = new Transition(); do { done = true; visited.add(s); if (a.isAccept(s) == false && a.getNumTransitions(s) == 1) { a.getTransition(s, 0, t); if (t.min == t.max && !visited.contains(t.dest)) { builder.append((byte) t.min); s = t.dest; done = false; } } } while (!done); return builder.get(); }
/** If this automaton accepts a single input, return it. Else, return null. * The automaton must be deterministic. */ public static IntsRef getSingleton(Automaton a) { if (a.isDeterministic() == false) { throw new IllegalArgumentException("input automaton must be deterministic"); } IntsRefBuilder builder = new IntsRefBuilder(); HashSet<Integer> visited = new HashSet<>(); int s = 0; Transition t = new Transition(); while (true) { visited.add(s); if (a.isAccept(s) == false) { if (a.getNumTransitions(s) == 1) { a.getTransition(s, 0, t); if (t.min == t.max && !visited.contains(t.dest)) { builder.append(t.min); s = t.dest; continue; } } } else if (a.getNumTransitions(s) == 0) { return builder.get(); } // Automaton accepts more than one string: return null; } }
a.getTransition(0, 0, t); if (t.dest == 0 && t.min == Character.MIN_CODE_POINT && t.max == Character.MAX_CODE_POINT) {
automaton.getTransition(state, maxIndex, transition); automaton.getTransition(state, numTransitions-1, transition); term.grow(1+idx);
automaton.getTransition(state, 0, transition);
public void resetState(Automaton a, int state) { assert a.getNumTransitions(state) != 0; this.state = state; transition = 0; a.getTransition(state, 0, t); label = t.min; to = t.dest; }
public void resetState(Automaton a, int state) { assert a.getNumTransitions(state) != 0; this.state = state; transition = 0; a.getTransition(state, 0, t); label = t.min; to = t.dest; }
public void resetState(Automaton a, int state) { assert a.getNumTransitions(state) != 0; this.state = state; transition = 0; a.getTransition(state, 0, t); label = t.min; to = t.dest; }
/** * Returns true if the given automaton accepts all strings for the specified min/max * range of the alphabet. The automaton must be minimized. */ public static boolean isTotal(Automaton a, int minAlphabet, int maxAlphabet) { if (a.isAccept(0) && a.getNumTransitions(0) == 1) { Transition t = new Transition(); a.getTransition(0, 0, t); return t.dest == 0 && t.min == minAlphabet && t.max == maxAlphabet; } return false; }
/** * Returns true if the given automaton accepts all strings for the specified min/max * range of the alphabet. The automaton must be minimized. */ public static boolean isTotal(Automaton a, int minAlphabet, int maxAlphabet) { if (a.isAccept(0) && a.getNumTransitions(0) == 1) { Transition t = new Transition(); a.getTransition(0, 0, t); return t.dest == 0 && t.min == minAlphabet && t.max == maxAlphabet; } return false; }
/** * Returns true if the given automaton accepts all strings for the specified min/max * range of the alphabet. The automaton must be minimized. */ public static boolean isTotal(Automaton a, int minAlphabet, int maxAlphabet) { if (a.isAccept(0) && a.getNumTransitions(0) == 1) { Transition t = new Transition(); a.getTransition(0, 0, t); return t.dest == 0 && t.min == minAlphabet && t.max == maxAlphabet; } return false; }
/** Sugar to get all transitions for all states. This is * object-heavy; it's better to iterate state by state instead. */ public Transition[][] getSortedTransitions() { int numStates = getNumStates(); Transition[][] transitions = new Transition[numStates][]; for(int s=0;s<numStates;s++) { int numTransitions = getNumTransitions(s); transitions[s] = new Transition[numTransitions]; for(int t=0;t<numTransitions;t++) { Transition transition = new Transition(); getTransition(s, t, transition); transitions[s][t] = transition; } } return transitions; }
/** Sugar to get all transitions for all states. This is * object-heavy; it's better to iterate state by state instead. */ public Transition[][] getSortedTransitions() { int numStates = getNumStates(); Transition[][] transitions = new Transition[numStates][]; for(int s=0;s<numStates;s++) { int numTransitions = getNumTransitions(s); transitions[s] = new Transition[numTransitions]; for(int t=0;t<numTransitions;t++) { Transition transition = new Transition(); getTransition(s, t, transition); transitions[s][t] = transition; } } return transitions; }
/** Sugar to get all transitions for all states. This is * object-heavy; it's better to iterate state by state instead. */ public Transition[][] getSortedTransitions() { int numStates = getNumStates(); Transition[][] transitions = new Transition[numStates][]; for(int s=0;s<numStates;s++) { int numTransitions = getNumTransitions(s); transitions[s] = new Transition[numTransitions]; for(int t=0;t<numTransitions;t++) { Transition transition = new Transition(); getTransition(s, t, transition); transitions[s][t] = transition; } } return transitions; }