Automaton result = new Automaton(); int numStates = a.getNumStates(); for(int i=0;i<numStates;i++) { result.createState(); result.setAccept(i, a.isAccept(i)); int deadState = result.createState(); result.addTransition(deadState, deadState, Character.MIN_CODE_POINT, Character.MAX_CODE_POINT); int count = a.initTransition(i, t); for(int j=0;j<count;j++) { a.getNextTransition(t); result.addTransition(i, t.dest, t.min, t.max); if (t.min > maxi) { result.addTransition(i, deadState, maxi, t.min-1); result.addTransition(i, deadState, maxi, Character.MAX_CODE_POINT); result.finishState(); return result;
/** * Returns an automaton that accepts the union of the empty string and the * language of the given automaton. This may create a dead state. * <p> * Complexity: linear in number of states. */ static public Automaton optional(Automaton a) { Automaton result = new Automaton(); result.createState(); result.setAccept(0, true); if (a.getNumStates() > 0) { result.copy(a); result.addEpsilon(0, 1); } result.finishState(); return result; }
/** * Returns a new (deterministic) automaton that accepts only the empty string. */ public static Automaton makeEmptyString() { Automaton a = new Automaton(); a.createState(); a.setAccept(0, true); return a; }
/** Appends the specified character to the specified state, returning a new state. */ public static int appendChar(Automaton a, int state, int c) { int newState = a.createState(); a.addTransition(state, newState, c, c); return newState; }
/** * Returns a new (deterministic) automaton that accepts all strings. */ public static Automaton makeAnyString() { Automaton a = new Automaton(); int s = a.createState(); a.setAccept(s, true); a.addTransition(s, s, Character.MIN_CODE_POINT, Character.MAX_CODE_POINT); a.finishState(); return a; }
return new Automaton(); int numStates = a.getNumStates(); int numTransitions = a.getNumTransitions(s); a.initTransition(s, t); for(int i=0;i<numTransitions;i++) { a.getNextTransition(t); builder.addTransition(t.dest+1, s+1, t.min, t.max); BitSet acceptStates = a.getAcceptStates(); while (s < numStates && (s = acceptStates.nextSetBit(s)) != -1) { result.addEpsilon(0, s+1); if (initialStates != null) { initialStates.add(s+1); result.finishState();
/** Returns sink state, if present, else -1. */ private static int findSinkState(Automaton automaton) { int numStates = automaton.getNumStates(); Transition t = new Transition(); int foundState = -1; for (int s=0;s<numStates;s++) { if (automaton.isAccept(s)) { int count = automaton.initTransition(s, t); boolean isSinkState = false; for(int i=0;i<count;i++) { automaton.getNextTransition(t); if (t.dest == s && t.min == 0 && t.max == 0xff) { isSinkState = true; break; } } if (isSinkState) { foundState = s; break; } } } return foundState; }
if (a.getNumStates() == 0 || (a.isAccept(0) == false && a.getNumTransitions(0) == 0)) { return new Automaton(); if (a.getNumTransitions(0) == 1) { Transition t = new Transition(); a.getTransition(0, 0, t); if (t.dest == 0 && t.min == Character.MIN_CODE_POINT && t.max == Character.MAX_CODE_POINT) { final int[] sigma = a.getStartPoints(); final int sigmaLen = sigma.length, statesLen = a.getNumStates(); final int j = a.isAccept(q) ? 0 : 1; partition[j].add(q); block[q] = j; for (int x = 0; x < sigmaLen; x++) { final ArrayList<Integer>[] r = reverse[a.step(q, sigma[x])]; if (r[x] == null) { r[x] = new ArrayList<>(); Automaton result = new Automaton(); result.createState(); newState = 0; } else { newState = result.createState();
if (a1.getNumStates() == 0) { return a1; if (a2.getNumStates() == 0) { return a2; Transition[][] transitions1 = a1.getSortedTransitions(); Transition[][] transitions2 = a2.getSortedTransitions(); Automaton c = new Automaton(); c.createState(); ArrayDeque<StatePair> worklist = new ArrayDeque<>(); HashMap<StatePair,StatePair> newstates = new HashMap<>(); while (worklist.size() > 0) { p = worklist.removeFirst(); c.setAccept(p.s, a1.isAccept(p.s1) && a2.isAccept(p.s2)); Transition[] t1 = transitions1[p.s1]; Transition[] t2 = transitions2[p.s2]; StatePair r = newstates.get(q); if (r == null) { q.s = c.createState(); worklist.add(q); newstates.put(q, q); c.addTransition(p.s, r.s, min, max); c.finishState();
/** Add a [virtual] epsilon transition between source and dest. * Dest state must already have all transitions added because this * method simply copies those same transitions over to source. */ public void addEpsilon(int source, int dest) { Transition t = new Transition(); int count = initTransition(dest, t); for(int i=0;i<count;i++) { getNextTransition(t); addTransition(source, t.dest, t.min, t.max); } if (isAccept(dest)) { setAccept(source, true); } }
/** Returns bitset marking states reachable from the initial state. */ private static BitSet getLiveStatesFromInitial(Automaton a) { int numStates = a.getNumStates(); BitSet live = new BitSet(numStates); if (numStates == 0) { return live; } ArrayDeque<Integer> workList = new ArrayDeque<>(); live.set(0); workList.add(0); Transition t = new Transition(); while (workList.isEmpty() == false) { int s = workList.removeFirst(); int count = a.initTransition(s, t); for(int i=0;i<count;i++) { a.getNextTransition(t); if (live.get(t.dest) == false) { live.set(t.dest); workList.add(t.dest); } } } return live; }
a1.addTransition(0, 0, '0'); for (int p : initials) { a1.addEpsilon(0, p); a1.finishState();
/** Returns true if, from this state, the automaton accepts any suffix * starting with a label between start and end, inclusive. We just * look for a transition, matching this range, to the sink state. */ private boolean acceptsSuffixRange(int state, int start, int end) { int count = automaton.initTransition(state, scratchTransition); for(int i=0;i<count;i++) { automaton.getNextTransition(scratchTransition); if (start >= scratchTransition.min && end <= scratchTransition.max && scratchTransition.dest == sinkState) { return true; } } return false; }
public void setState(int state) { this.state = state; transitionIndex = 0; transitionCount = ite.automaton.getNumTransitions(state); if (transitionCount != 0) { ite.automaton.initTransition(state, transition); ite.automaton.getNextTransition(transition); } else { // Must set min to -1 so the "label < min" check never falsely triggers: transition.min = -1; // Must set max to -1 so we immediately realize we need to step to the next transition and then pop this frame: transition.max = -1; } }
int numStates = a.getNumStates(); for(int s=0;s<numStates;s++) { builder.createState(); int count = a.initTransition(s, t); for(int i=0;i<count;i++) { a.getNextTransition(t); builder.addTransition(t.dest, s, t.min, t.max); BitSet acceptBits = a.getAcceptStates(); int s = 0; while (s < numStates && (s = acceptBits.nextSetBit(s)) != -1) { int count = a2.initTransition(s, t); for(int i=0;i<count;i++) { a2.getNextTransition(t); if (live.get(t.dest) == false) { live.set(t.dest);
int numTransitions = automaton.initTransition(state, transition); for(int i=0;i<numTransitions;i++) { automaton.getNextTransition(transition); if (transition.min < leadLabel) { maxIndex = i; automaton.getTransition(state, maxIndex, transition); numTransitions = automaton.getNumTransitions(state); if (numTransitions == 0) { automaton.getTransition(state, numTransitions-1, transition); term.grow(1+idx);
/** * Returns a (deterministic) automaton that accepts the complement of the * language of the given automaton. * <p> * Complexity: linear in number of states if already deterministic and * exponential otherwise. * @param maxDeterminizedStates maximum number of states determinizing the * automaton can result in. Set higher to allow more complex queries and * lower to prevent memory exhaustion. */ static public Automaton complement(Automaton a, int maxDeterminizedStates) { a = totalize(determinize(a, maxDeterminizedStates)); int numStates = a.getNumStates(); for (int p=0;p<numStates;p++) { a.setAccept(p, !a.isAccept(p)); } return removeDeadStates(a); }
/** * 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(); }
a = Operations.determinize(a, maxDeterminizedStates); this.automaton = a; points = a.getStartPoints(); size = Math.max(1,a.getNumStates()); accept = new boolean[size]; transitions = new int[size * points.length]; Arrays.fill(transitions, -1); for (int n=0;n<size;n++) { accept[n] = a.isAccept(n); for (int c = 0; c < points.length; c++) { int dest = a.step(n, points[c]); assert dest == -1 || dest < size; transitions[n * points.length + c] = dest;
if (a1.isDeterministic() == false) { throw new IllegalArgumentException("a1 must be deterministic"); if (a2.isDeterministic() == false) { throw new IllegalArgumentException("a2 must be deterministic"); if (a1.getNumStates() == 0) { } else if (a2.getNumStates() == 0) { return isEmpty(a1); Transition[][] transitions1 = a1.getSortedTransitions(); Transition[][] transitions2 = a2.getSortedTransitions(); ArrayDeque<StatePair> worklist = new ArrayDeque<>(); HashSet<StatePair> visited = new HashSet<>(); while (worklist.size() > 0) { p = worklist.removeFirst(); if (a1.isAccept(p.s1) && a2.isAccept(p.s2) == false) { return false;