public virtual string ToDot() { StringBuilder b = new StringBuilder("digraph CompiledAutomaton {\n"); b.Append(" rankdir = LR;\n"); int initial = RunAutomaton.InitialState; for (int i = 0; i < sortedTransitions.Length; i++) { b.Append(" ").Append(i); if (RunAutomaton.IsAccept(i)) { b.Append(" [shape=doublecircle,label=\"\"];\n"); } else { b.Append(" [shape=circle,label=\"\"];\n"); } if (i == initial) { b.Append(" initial [shape=plaintext,label=\"\"];\n"); b.Append(" initial -> ").Append(i).Append("\n"); } for (int j = 0; j < sortedTransitions[i].Length; j++) { b.Append(" ").Append(i); sortedTransitions[i][j].AppendDot(b); } } return b.Append("}\n").ToString(); }
//private static final boolean DEBUG = BlockTreeTermsWriter.DEBUG; private BytesRef AddTail(int state, BytesRef term, int idx, int leadLabel) { // Find biggest transition that's < label // TODO: use binary search here Transition maxTransition = null; foreach (Transition transition in sortedTransitions[state]) { if (transition.min < leadLabel) { maxTransition = transition; } } if (Debugging.AssertsEnabled) { Debugging.Assert(maxTransition != null); } // Append floorLabel int floorLabel; if (maxTransition.max > leadLabel - 1) { floorLabel = leadLabel - 1; } else { floorLabel = maxTransition.max; } if (idx >= term.Bytes.Length) { term.Grow(1 + idx); } //if (DEBUG) System.out.println(" add floorLabel=" + (char) floorLabel + " idx=" + idx); term.Bytes[idx] = (byte)floorLabel; state = maxTransition.to.Number; idx++; // Push down to last accept state while (true) { Transition[] transitions = sortedTransitions[state]; if (transitions.Length == 0) { if (Debugging.AssertsEnabled) { Debugging.Assert(RunAutomaton.IsAccept(state)); } term.Length = idx; //if (DEBUG) System.out.println(" return " + term.utf8ToString()); return(term); } else { // We are pushing "top" -- so get last label of // last transition: if (Debugging.AssertsEnabled) { Debugging.Assert(transitions.Length != 0); } Transition lastTransition = transitions[transitions.Length - 1]; if (idx >= term.Bytes.Length) { term.Grow(1 + idx); } //if (DEBUG) System.out.println(" push maxLabel=" + (char) lastTransition.max + " idx=" + idx); term.Bytes[idx] = (byte)lastTransition.max; state = lastTransition.to.Number; idx++; } } }
/// <summary> /// Finds largest term accepted by this Automaton, that's /// <= the provided input term. The result is placed in /// output; it's fine for output and input to point to /// the same <see cref="BytesRef"/>. The returned result is either the /// provided output, or <c>null</c> if there is no floor term /// (ie, the provided input term is before the first term /// accepted by this <see cref="Automaton"/>). /// </summary> public virtual BytesRef Floor(BytesRef input, BytesRef output) { output.Offset = 0; //if (DEBUG) System.out.println("CA.floor input=" + input.utf8ToString()); int state = RunAutomaton.InitialState; // Special case empty string: if (input.Length == 0) { if (RunAutomaton.IsAccept(state)) { output.Length = 0; return output; } else { return null; } } IList<int> stack = new List<int>(); int idx = 0; while (true) { int label = ((sbyte)input.Bytes[input.Offset + idx]) & 0xff; int nextState = RunAutomaton.Step(state, label); //if (DEBUG) System.out.println(" cycle label=" + (char) label + " nextState=" + nextState); if (idx == input.Length - 1) { if (nextState != -1 && RunAutomaton.IsAccept(nextState)) { // Input string is accepted if (idx >= output.Bytes.Length) { output.Grow(1 + idx); } output.Bytes[idx] = (byte)label; output.Length = input.Length; //if (DEBUG) System.out.println(" input is accepted; return term=" + output.utf8ToString()); return output; } else { nextState = -1; } } if (nextState == -1) { // Pop back to a state that has a transition // <= our label: while (true) { Transition[] transitions = sortedTransitions[state]; if (transitions.Length == 0) { if (Debugging.AssertsEnabled) Debugging.Assert(RunAutomaton.IsAccept(state)); output.Length = idx; //if (DEBUG) System.out.println(" return " + output.utf8ToString()); return output; } else if (label - 1 < transitions[0].min) { if (RunAutomaton.IsAccept(state)) { output.Length = idx; //if (DEBUG) System.out.println(" return " + output.utf8ToString()); return output; } // pop if (stack.Count == 0) { //if (DEBUG) System.out.println(" pop ord=" + idx + " return null"); return null; } else { state = stack[stack.Count - 1]; stack.RemoveAt(stack.Count - 1); idx--; //if (DEBUG) System.out.println(" pop ord=" + (idx+1) + " label=" + (char) label + " first trans.min=" + (char) transitions[0].min); label = input.Bytes[input.Offset + idx] & 0xff; } } else { //if (DEBUG) System.out.println(" stop pop ord=" + idx + " first trans.min=" + (char) transitions[0].min); break; } } //if (DEBUG) System.out.println(" label=" + (char) label + " idx=" + idx); return AddTail(state, output, idx, label); } else { if (idx >= output.Bytes.Length) { output.Grow(1 + idx); } output.Bytes[idx] = (byte)label; stack.Add(state); state = nextState; idx++; } } }