/** * Constructs sub-automaton corresponding to decimal numbers of value at least * x.substring(n) and length x.substring(n).length(). */ private static int atLeast(Automaton.Builder builder, String x, int n, Collection<Integer> initials, boolean zeros) { int s = builder.createState(); if (x.length() == n) { builder.setAccept(s, true); } else { if (zeros) { initials.add(s); } char c = x.charAt(n); builder.addTransition(s, atLeast(builder, x, n + 1, initials, zeros && c == '0'), c); if (c < '9') { builder.addTransition(s, anyOfRightLength(builder, x, n + 1), (char) (c + 1), '9'); } } return s; }
for(int i=0;i<count;i++) { a.getNextTransition(t); builder.addTransition(t.dest, s, t.min, t.max);
/** * Internal recursive traversal for conversion. */ private static int convert(Automaton.Builder a, State s, IdentityHashMap<State,Integer> visited) { Integer converted = visited.get(s); if (converted != null) { return converted; } converted = a.createState(); a.setAccept(converted, s.is_final); visited.put(s, converted); int i = 0; int[] labels = s.labels; for (DaciukMihovAutomatonBuilder.State target : s.states) { a.addTransition(converted, convert(a, target, visited), labels[i++]); } return converted; }
builder.addTransition(posData.arriving, posData.leaving, POS_SEP); if (posInc > 1) { c = termUTF8.bytes[termUTF8.offset + byteIDX] & 0xff; builder.addTransition(state, nextState, c); state = nextState; while (true) { int state1 = builder.createState(); builder.addTransition(lastState, state1, HOLE); endPosInc--; if (endPosInc == 0) { builder.addTransition(state1, state2, POS_SEP); lastState = state2; if (posData.arriving != -1) { if (endState != -1) { builder.addTransition(posData.arriving, endState, POS_SEP); } else { builder.setAccept(posData.arriving, true);
b.addTransition(r, q, lastPoint, point-1);
utf8.addTransition(start, end, startUTF8.byteAt(upto), endUTF8.byteAt(upto)); return; } else { utf8.addTransition(start, n, startUTF8.byteAt(upto)); if (upto == startUTF8.len-1) { utf8.addTransition(start, end, startUTF8.byteAt(upto), endUTF8.byteAt(upto)); } else { start(start, end, startUTF8, upto, false);
builder.addTransition(pos, endPos, id);
for(int i=0;i<count;i++) { a.getNextTransition(t); builder.addTransition(0, t.dest+1, t.min, t.max); for(int i=0;i<count;i++) { a.getNextTransition(t); builder.addTransition(s+1, t.dest+1, t.min, t.max);
for(int i=0;i<numTransitions;i++) { a.getNextTransition(t); builder.addTransition(t.dest+1, s+1, t.min, t.max);
/** * Constructs sub-automaton corresponding to decimal numbers of value between * x.substring(n) and y.substring(n) and of length x.substring(n).length() * (which must be equal to y.substring(n).length()). */ private static int between(Automaton.Builder builder, String x, String y, int n, Collection<Integer> initials, boolean zeros) { int s = builder.createState(); if (x.length() == n) { builder.setAccept(s, true); } else { if (zeros) { initials.add(s); } char cx = x.charAt(n); char cy = y.charAt(n); if (cx == cy) { builder.addTransition(s, between(builder, x, y, n + 1, initials, zeros && cx == '0'), cx); } else { // cx<cy builder.addTransition(s, atLeast(builder, x, n + 1, initials, zeros && cx == '0'), cx); builder.addTransition(s, atMost(builder, y, n + 1), cy); if (cx + 1 < cy) { builder.addTransition(s, anyOfRightLength(builder, x, n+1), (char) (cx + 1), (char) (cy - 1)); } } } return s; }
/** * Returns the articulation points (or cut vertices) of the graph: * https://en.wikipedia.org/wiki/Biconnected_component */ public int[] articulationPoints() { if (det.getNumStates() == 0) { return new int[0]; } // Automaton.Builder undirect = new Automaton.Builder(); undirect.copy(det); for (int i = 0; i < det.getNumStates(); i++) { int numT = det.initTransition(i, transition); for (int j = 0; j < numT; j++) { det.getNextTransition(transition); undirect.addTransition(transition.dest, i, transition.min); } } int numStates = det.getNumStates(); BitSet visited = new BitSet(numStates); int[] depth = new int[det.getNumStates()]; int[] low = new int[det.getNumStates()]; int[] parent = new int[det.getNumStates()]; Arrays.fill(parent, -1); List<Integer> points = new ArrayList<>(); articulationPointsRecurse(undirect.finish(), 0, 0, depth, low, parent, visited, points); Collections.reverse(points); return points.stream().mapToInt(p -> p).toArray(); }
private static void addHoles(Automaton.Builder builder, RollingBuffer<Position> positions, int pos) { Position posData = positions.get(pos); Position prevPosData = positions.get(pos-1); while(posData.arriving == -1 || prevPosData.leaving == -1) { if (posData.arriving == -1) { posData.arriving = builder.createState(); builder.addTransition(posData.arriving, posData.leaving, POS_SEP); } if (prevPosData.leaving == -1) { if (pos == 1) { prevPosData.leaving = 0; } else { prevPosData.leaving = builder.createState(); } if (prevPosData.arriving != -1) { builder.addTransition(prevPosData.arriving, prevPosData.leaving, POS_SEP); } } builder.addTransition(prevPosData.leaving, posData.arriving, HOLE); pos--; if (pos <= 0) { break; } posData = prevPosData; prevPosData = positions.get(pos-1); } } }
private void end(int start, int end, UTF8Sequence endUTF8, int upto, boolean doAll) { if (upto == endUTF8.len-1) { // Done recursing //start.addTransition(new Transition(endUTF8.byteAt(upto) & (~MASKS[endUTF8.numBits(upto)-1]), endUTF8.byteAt(upto), end)); // type=end utf8.addTransition(start, end, endUTF8.byteAt(upto) & (~MASKS[endUTF8.numBits(upto)-1]), endUTF8.byteAt(upto)); } else { final int startCode; if (endUTF8.numBits(upto) == 5) { // special case -- avoid created unused edges (endUTF8 // doesn't accept certain byte sequences) -- there // are other cases we could optimize too: startCode = 194; } else { startCode = endUTF8.byteAt(upto) & (~MASKS[endUTF8.numBits(upto)-1]); } if (doAll && endUTF8.byteAt(upto) != startCode) { all(start, end, startCode, endUTF8.byteAt(upto)-1, endUTF8.len-upto-1); } int n = utf8.createState(); //start.addTransition(new Transition(endUTF8.byteAt(upto), n)); // type=end utf8.addTransition(start, n, endUTF8.byteAt(upto)); end(n, end, endUTF8, 1+upto, true); } }
private void all(int start, int end, int startCode, int endCode, int left) { if (left == 0) { //start.addTransition(new Transition(startCode, endCode, end)); // type=all utf8.addTransition(start, end, startCode, endCode); } else { int lastN = utf8.createState(); //start.addTransition(new Transition(startCode, endCode, lastN)); // type=all utf8.addTransition(start, lastN, startCode, endCode); while (left > 1) { int n = utf8.createState(); //lastN.addTransition(new Transition(128, 191, n)); // type=all* utf8.addTransition(lastN, n, 128, 191); // type=all* left--; lastN = n; } //lastN.addTransition(new Transition(128, 191, end)); // type = all* utf8.addTransition(lastN, end, 128, 191); // type = all* } }
/** * Constructs sub-automaton corresponding to decimal numbers of value at most * x.substring(n) and length x.substring(n).length(). */ private static int atMost(Automaton.Builder builder, String x, int n) { int s = builder.createState(); if (x.length() == n) { builder.setAccept(s, true); } else { char c = x.charAt(n); builder.addTransition(s, atMost(builder, x, (char) n + 1), c); if (c > '0') { builder.addTransition(s, anyOfRightLength(builder, x, n + 1), '0', (char) (c - 1)); } } return s; }
private void start(int start, int end, UTF8Sequence startUTF8, int upto, boolean doAll) { if (upto == startUTF8.len-1) { // Done recursing utf8.addTransition(start, end, startUTF8.byteAt(upto), startUTF8.byteAt(upto) | MASKS[startUTF8.numBits(upto)-1]); // type=start //start.addTransition(new Transition(startUTF8.byteAt(upto), startUTF8.byteAt(upto) | MASKS[startUTF8.numBits(upto)-1], end)); // type=start } else { int n = utf8.createState(); utf8.addTransition(start, n, startUTF8.byteAt(upto)); //start.addTransition(new Transition(startUTF8.byteAt(upto), n)); // type=start start(n, end, startUTF8, 1+upto, true); int endCode = startUTF8.byteAt(upto) | MASKS[startUTF8.numBits(upto)-1]; if (doAll && startUTF8.byteAt(upto) != endCode) { all(start, end, startUTF8.byteAt(upto)+1, endCode, startUTF8.len-upto-1); } } }
/** Copies over all states/transitions from other. */ public void copy(Automaton other) { int offset = getNumStates(); int otherNumStates = other.getNumStates(); // Copy all states copyStates(other); // Copy all transitions Transition t = new Transition(); for(int s=0;s<otherNumStates;s++) { int count = other.initTransition(s, t); for(int i=0;i<count;i++) { other.getNextTransition(t); addTransition(offset + s, offset + t.dest, t.min, t.max); } } }
/** 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) { for (int upto = 0; upto < nextTransition; upto += 4) { if (transitions[upto] == dest) { addTransition(source, transitions[upto + 1], transitions[upto + 2], transitions[upto + 3]); } } if (isAccept(dest)) { setAccept(source, true); } }
/** Add a new transition with min = max = label. */ public void addTransition(int source, int dest, int label) { addTransition(source, dest, label, label); }
/** * Constructs sub-automaton corresponding to decimal numbers of length * x.substring(n).length(). */ private static int anyOfRightLength(Automaton.Builder builder, String x, int n) { int s = builder.createState(); if (x.length() == n) { builder.setAccept(s, true); } else { builder.addTransition(s, anyOfRightLength(builder, x, n + 1), '0', '9'); } return s; }