
dk.brics.automaton.Automaton Maven / Gradle / Ivy
/*
* dk.brics.automaton
*
* Copyright (c) 2001-2011 Anders Moeller
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package dk.brics.automaton;
import java.io.IOException;
import java.io.InputStream;
import java.io.InvalidClassException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OptionalDataException;
import java.io.OutputStream;
import java.io.Serializable;
import java.net.URL;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Finite-state automaton with regular expression operations.
*
* Class invariants:
*
* - An automaton is either represented explicitly (with {@link State} and {@link Transition} objects)
* or with a singleton string (see {@link #getSingleton()} and {@link #expandSingleton()}) in case the automaton is known to accept exactly one string.
* (Implicitly, all states and transitions of an automaton are reachable from its initial state.)
*
- Automata are always reduced (see {@link #reduce()})
* and have no transitions to dead states (see {@link #removeDeadTransitions()}).
*
- If an automaton is nondeterministic, then {@link #isDeterministic()} returns false (but
* the converse is not required).
*
- Automata provided as input to operations are generally assumed to be disjoint.
*
*
* If the states or transitions are manipulated manually, the {@link #restoreInvariant()}
* and {@link #setDeterministic(boolean)} methods should be used afterwards to restore
* representation invariants that are assumed by the built-in automata operations.
*
* @author Anders Møller <[email protected]>
*/
public class Automaton implements Serializable, Cloneable {
static final long serialVersionUID = 10001;
/**
* Minimize using Huffman's O(n2) algorithm.
* This is the standard text-book algorithm.
* @see #setMinimization(int)
*/
public static final int MINIMIZE_HUFFMAN = 0;
/**
* Minimize using Brzozowski's O(2n) algorithm.
* This algorithm uses the reverse-determinize-reverse-determinize trick, which has a bad
* worst-case behavior but often works very well in practice
* (even better than Hopcroft's!).
* @see #setMinimization(int)
*/
public static final int MINIMIZE_BRZOZOWSKI = 1;
/**
* Minimize using Hopcroft's O(n log n) algorithm.
* This is regarded as one of the most generally efficient algorithms that exist.
* @see #setMinimization(int)
*/
public static final int MINIMIZE_HOPCROFT = 2;
/** Selects minimization algorithm (default: MINIMIZE_HOPCROFT
). */
static int minimization = MINIMIZE_HOPCROFT;
/** Initial state of this automaton. */
State initial;
/** If true, then this automaton is definitely deterministic
(i.e., there are no choices for any run, but a run may crash). */
boolean deterministic;
/** Extra data associated with this automaton. */
transient Object info;
/** Hash code. Recomputed by {@link #minimize()}. */
int hash_code;
/** Singleton string. Null if not applicable. */
String singleton;
/** Minimize always flag. */
static boolean minimize_always = false;
/** Selects whether operations may modify the input automata (default: false
). */
static boolean allow_mutation = false;
/** Caches the isDebug
state. */
static Boolean is_debug = null;
/**
* Constructs a new automaton that accepts the empty language.
* Using this constructor, automata can be constructed manually from
* {@link State} and {@link Transition} objects.
* @see #setInitialState(State)
* @see State
* @see Transition
*/
public Automaton() {
initial = new State();
deterministic = true;
singleton = null;
}
boolean isDebug() {
if (is_debug == null)
is_debug = Boolean.valueOf(System.getProperty("dk.brics.automaton.debug") != null);
return is_debug.booleanValue();
}
/**
* Selects minimization algorithm (default: MINIMIZE_HOPCROFT
).
* @param algorithm minimization algorithm
*/
static public void setMinimization(int algorithm) {
minimization = algorithm;
}
/**
* Sets or resets minimize always flag.
* If this flag is set, then {@link #minimize()} will automatically
* be invoked after all operations that otherwise may produce non-minimal automata.
* By default, the flag is not set.
* @param flag if true, the flag is set
*/
static public void setMinimizeAlways(boolean flag) {
minimize_always = flag;
}
/**
* Sets or resets allow mutate flag.
* If this flag is set, then all automata operations may modify automata given as input;
* otherwise, operations will always leave input automata languages unmodified.
* By default, the flag is not set.
* @param flag if true, the flag is set
* @return previous value of the flag
*/
static public boolean setAllowMutate(boolean flag) {
boolean b = allow_mutation;
allow_mutation = flag;
return b;
}
/**
* Returns the state of the allow mutate flag.
* If this flag is set, then all automata operations may modify automata given as input;
* otherwise, operations will always leave input automata languages unmodified.
* By default, the flag is not set.
* @return current value of the flag
*/
static boolean getAllowMutate() {
return allow_mutation;
}
void checkMinimizeAlways() {
if (minimize_always)
minimize();
}
boolean isSingleton() {
return singleton!=null;
}
/**
* Returns the singleton string for this automaton.
* An automaton that accepts exactly one string may be represented
* in singleton mode. In that case, this method may be used to obtain the string.
* @return string, null if this automaton is not in singleton mode.
*/
public String getSingleton() {
return singleton;
}
/**
* Sets initial state.
* @param s state
*/
public void setInitialState(State s) {
initial = s;
singleton = null;
}
/**
* Gets initial state.
* @return state
*/
public State getInitialState() {
expandSingleton();
return initial;
}
/**
* Returns deterministic flag for this automaton.
* @return true if the automaton is definitely deterministic, false if the automaton
* may be nondeterministic
*/
public boolean isDeterministic() {
return deterministic;
}
/**
* Sets deterministic flag for this automaton.
* This method should (only) be used if automata are constructed manually.
* @param deterministic true if the automaton is definitely deterministic, false if the automaton
* may be nondeterministic
*/
public void setDeterministic(boolean deterministic) {
this.deterministic = deterministic;
}
/**
* Associates extra information with this automaton.
* @param info extra information
*/
public void setInfo(Object info) {
this.info = info;
}
/**
* Returns extra information associated with this automaton.
* @return extra information
* @see #setInfo(Object)
*/
public Object getInfo() {
return info;
}
/**
* Returns the set of states that are reachable from the initial state.
* @return set of {@link State} objects
*/
public Set getStates() {
expandSingleton();
Set visited;
if (isDebug())
visited = new LinkedHashSet();
else
visited = new HashSet();
LinkedList worklist = new LinkedList();
worklist.add(initial);
visited.add(initial);
while (worklist.size() > 0) {
State s = worklist.removeFirst();
Collection tr;
if (isDebug())
tr = s.getSortedTransitions(false);
else
tr = s.transitions;
for (Transition t : tr)
if (!visited.contains(t.to)) {
visited.add(t.to);
worklist.add(t.to);
}
}
return visited;
}
/**
* Returns the set of reachable accept states.
* @return set of {@link State} objects
*/
public Set getAcceptStates() {
expandSingleton();
HashSet accepts = new HashSet();
HashSet visited = new HashSet();
LinkedList worklist = new LinkedList();
worklist.add(initial);
visited.add(initial);
while (worklist.size() > 0) {
State s = worklist.removeFirst();
if (s.accept)
accepts.add(s);
for (Transition t : s.transitions)
if (!visited.contains(t.to)) {
visited.add(t.to);
worklist.add(t.to);
}
}
return accepts;
}
/**
* Assigns consecutive numbers to the given states.
*/
static void setStateNumbers(Set states) {
int number = 0;
for (State s : states)
s.number = number++;
}
/**
* Adds transitions to explicit crash state to ensure that transition function is total.
*/
void totalize() {
State s = new State();
s.transitions.add(new Transition(Character.MIN_VALUE, Character.MAX_VALUE, s));
for (State p : getStates()) {
int maxi = Character.MIN_VALUE;
for (Transition t : p.getSortedTransitions(false)) {
if (t.min > maxi)
p.transitions.add(new Transition((char)maxi, (char)(t.min - 1), s));
if (t.max + 1 > maxi)
maxi = t.max + 1;
}
if (maxi <= Character.MAX_VALUE)
p.transitions.add(new Transition((char)maxi, Character.MAX_VALUE, s));
}
}
/**
* Restores representation invariant.
* This method must be invoked before any built-in automata operation is performed
* if automaton states or transitions are manipulated manually.
* @see #setDeterministic(boolean)
*/
public void restoreInvariant() {
removeDeadTransitions();
}
/**
* Reduces this automaton.
* An automaton is "reduced" by combining overlapping and adjacent edge intervals with same destination.
*/
public void reduce() {
if (isSingleton())
return;
Set states = getStates();
setStateNumbers(states);
for (State s : states) {
List st = s.getSortedTransitions(true);
s.resetTransitions();
State p = null;
int min = -1, max = -1;
for (Transition t : st) {
if (p == t.to) {
if (t.min <= max + 1) {
if (t.max > max)
max = t.max;
} else {
if (p != null)
s.transitions.add(new Transition((char)min, (char)max, p));
min = t.min;
max = t.max;
}
} else {
if (p != null)
s.transitions.add(new Transition((char)min, (char)max, p));
p = t.to;
min = t.min;
max = t.max;
}
}
if (p != null)
s.transitions.add(new Transition((char)min, (char)max, p));
}
clearHashCode();
}
/**
* Returns sorted array of all interval start points.
*/
char[] getStartPoints() {
Set pointset = new HashSet();
for (State s : getStates()) {
pointset.add(Character.MIN_VALUE);
for (Transition t : s.transitions) {
pointset.add(t.min);
if (t.max < Character.MAX_VALUE)
pointset.add((char)(t.max + 1));
}
}
char[] points = new char[pointset.size()];
int n = 0;
for (Character m : pointset)
points[n++] = m;
Arrays.sort(points);
return points;
}
/**
* Returns the set of live states. A state is "live" if an accept state is reachable from it.
* @return set of {@link State} objects
*/
public Set getLiveStates() {
expandSingleton();
return getLiveStates(getStates());
}
private Set getLiveStates(Set states) {
HashMap> map = new HashMap>();
for (State s : states)
map.put(s, new HashSet());
for (State s : states)
for (Transition t : s.transitions)
map.get(t.to).add(s);
Set live = new HashSet(getAcceptStates());
LinkedList worklist = new LinkedList(live);
while (worklist.size() > 0) {
State s = worklist.removeFirst();
for (State p : map.get(s))
if (!live.contains(p)) {
live.add(p);
worklist.add(p);
}
}
return live;
}
/**
* Removes transitions to dead states and calls {@link #reduce()} and {@link #clearHashCode()}.
* (A state is "dead" if no accept state is reachable from it.)
*/
public void removeDeadTransitions() {
clearHashCode();
if (isSingleton())
return;
Set states = getStates();
Set live = getLiveStates(states);
for (State s : states) {
Set st = s.transitions;
s.resetTransitions();
for (Transition t : st)
if (live.contains(t.to))
s.transitions.add(t);
}
reduce();
}
/**
* Returns a sorted array of transitions for each state (and sets state numbers).
*/
static Transition[][] getSortedTransitions(Set states) {
setStateNumbers(states);
Transition[][] transitions = new Transition[states.size()][];
for (State s : states)
transitions[s.number] = s.getSortedTransitionArray(false);
return transitions;
}
/**
* Expands singleton representation to normal representation.
* Does nothing if not in singleton representation.
*/
public void expandSingleton() {
if (isSingleton()) {
State p = new State();
initial = p;
for (int i = 0; i < singleton.length(); i++) {
State q = new State();
p.transitions.add(new Transition(singleton.charAt(i), q));
p = q;
}
p.accept = true;
deterministic = true;
singleton = null;
}
}
/**
* Returns the number of states in this automaton.
*/
public int getNumberOfStates() {
if (isSingleton())
return singleton.length() + 1;
return getStates().size();
}
/**
* Returns the number of transitions in this automaton. This number is counted
* as the total number of edges, where one edge may be a character interval.
*/
public int getNumberOfTransitions() {
if (isSingleton())
return singleton.length();
int c = 0;
for (State s : getStates())
c += s.transitions.size();
return c;
}
/**
* Returns true if the language of this automaton is equal to the language
* of the given automaton. Implemented using hashCode
and
* subsetOf
.
*/
@Override
public boolean equals(Object obj) {
if (obj == this)
return true;
if (!(obj instanceof Automaton))
return false;
Automaton a = (Automaton)obj;
if (isSingleton() && a.isSingleton())
return singleton.equals(a.singleton);
return hashCode() == a.hashCode() && subsetOf(a) && a.subsetOf(this);
}
/**
* Returns hash code for this automaton. The hash code is based on the
* number of states and transitions in the minimized automaton.
* Invoking this method may involve minimizing the automaton.
*/
@Override
public int hashCode() {
if (hash_code == 0)
minimize();
return hash_code;
}
/**
* Recomputes the hash code.
* The automaton must be minimal when this operation is performed.
*/
void recomputeHashCode() {
hash_code = getNumberOfStates() * 3 + getNumberOfTransitions() * 2;
if (hash_code == 0)
hash_code = 1;
}
/**
* Must be invoked when the stored hash code may no longer be valid.
*/
void clearHashCode() {
hash_code = 0;
}
/**
* Returns a string representation of this automaton.
*/
@Override
public String toString() {
StringBuilder b = new StringBuilder();
if (isSingleton()) {
b.append("singleton: ");
for (char c : singleton.toCharArray())
Transition.appendCharString(c, b);
b.append("\n");
} else {
Set states = getStates();
setStateNumbers(states);
b.append("initial state: ").append(initial.number).append("\n");
for (State s : states)
b.append(s.toString());
}
return b.toString();
}
/**
* Returns Graphviz Dot
* representation of this automaton.
*/
public String toDot() {
StringBuilder b = new StringBuilder("digraph Automaton {\n");
b.append(" rankdir = LR;\n");
Set states = getStates();
setStateNumbers(states);
for (State s : states) {
b.append(" ").append(s.number);
if (s.accept)
b.append(" [shape=doublecircle,label=\"\"];\n");
else
b.append(" [shape=circle,label=\"\"];\n");
if (s == initial) {
b.append(" initial [shape=plaintext,label=\"\"];\n");
b.append(" initial -> ").append(s.number).append("\n");
}
for (Transition t : s.transitions) {
b.append(" ").append(s.number);
t.appendDot(b);
}
}
return b.append("}\n").toString();
}
/**
* Returns a clone of this automaton, expands if singleton.
*/
Automaton cloneExpanded() {
Automaton a = clone();
a.expandSingleton();
return a;
}
/**
* Returns a clone of this automaton unless allow_mutation
is set, expands if singleton.
*/
Automaton cloneExpandedIfRequired() {
if (allow_mutation) {
expandSingleton();
return this;
} else
return cloneExpanded();
}
/**
* Returns a clone of this automaton.
*/
@Override
public Automaton clone() {
try {
Automaton a = (Automaton)super.clone();
if (!isSingleton()) {
HashMap m = new HashMap();
Set states = getStates();
for (State s : states)
m.put(s, new State());
for (State s : states) {
State p = m.get(s);
p.accept = s.accept;
if (s == initial)
a.initial = p;
for (Transition t : s.transitions)
p.transitions.add(new Transition(t.min, t.max, m.get(t.to)));
}
}
return a;
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
/**
* Returns a clone of this automaton, or this automaton itself if allow_mutation
flag is set.
*/
Automaton cloneIfRequired() {
if (allow_mutation)
return this;
else
return clone();
}
/**
* Retrieves a serialized Automaton
located by a URL.
* @param url URL of serialized automaton
* @exception IOException if input/output related exception occurs
* @exception OptionalDataException if the data is not a serialized object
* @exception InvalidClassException if the class serial number does not match
* @exception ClassCastException if the data is not a serialized Automaton
* @exception ClassNotFoundException if the class of the serialized object cannot be found
*/
public static Automaton load(URL url) throws IOException, OptionalDataException, ClassCastException,
ClassNotFoundException, InvalidClassException {
return load(url.openStream());
}
/**
* Retrieves a serialized Automaton
from a stream.
* @param stream input stream with serialized automaton
* @exception IOException if input/output related exception occurs
* @exception OptionalDataException if the data is not a serialized object
* @exception InvalidClassException if the class serial number does not match
* @exception ClassCastException if the data is not a serialized Automaton
* @exception ClassNotFoundException if the class of the serialized object cannot be found
*/
public static Automaton load(InputStream stream) throws IOException, OptionalDataException, ClassCastException,
ClassNotFoundException, InvalidClassException {
ObjectInputStream s = new ObjectInputStream(stream);
return (Automaton)s.readObject();
}
/**
* Writes this Automaton
to the given stream.
* @param stream output stream for serialized automaton
* @exception IOException if input/output related exception occurs
*/
public void store(OutputStream stream) throws IOException {
ObjectOutputStream s = new ObjectOutputStream(stream);
s.writeObject(this);
s.flush();
}
/**
* See {@link BasicAutomata#makeEmpty()}.
*/
public static Automaton makeEmpty() {
return BasicAutomata.makeEmpty();
}
/**
* See {@link BasicAutomata#makeEmptyString()}.
*/
public static Automaton makeEmptyString() {
return BasicAutomata.makeEmptyString();
}
/**
* See {@link BasicAutomata#makeAnyString()}.
*/
public static Automaton makeAnyString() {
return BasicAutomata.makeAnyString();
}
/**
* See {@link BasicAutomata#makeAnyChar()}.
*/
public static Automaton makeAnyChar() {
return BasicAutomata.makeAnyChar();
}
/**
* See {@link BasicAutomata#makeChar(char)}.
*/
public static Automaton makeChar(char c) {
return BasicAutomata.makeChar(c);
}
/**
* See {@link BasicAutomata#makeCharRange(char, char)}.
*/
public static Automaton makeCharRange(char min, char max) {
return BasicAutomata.makeCharRange(min, max);
}
/**
* See {@link BasicAutomata#makeCharSet(String)}.
*/
public static Automaton makeCharSet(String set) {
return BasicAutomata.makeCharSet(set);
}
/**
* See {@link BasicAutomata#makeInterval(int, int, int)}.
*/
public static Automaton makeInterval(int min, int max, int digits) throws IllegalArgumentException {
return BasicAutomata.makeInterval(min, max, digits);
}
/**
* See {@link BasicAutomata#makeString(String)}.
*/
public static Automaton makeString(String s) {
return BasicAutomata.makeString(s);
}
/**
* See {@link BasicAutomata#makeStringUnion(CharSequence...)}.
*/
public static Automaton makeStringUnion(CharSequence... strings) {
return BasicAutomata.makeStringUnion(strings);
}
/**
* See {@link BasicAutomata#makeMaxInteger(String)}.
*/
public static Automaton makeMaxInteger(String n) {
return BasicAutomata.makeMaxInteger(n);
}
/**
* See {@link BasicAutomata#makeMinInteger(String)}.
*/
public static Automaton makeMinInteger(String n) {
return BasicAutomata.makeMinInteger(n);
}
/**
* See {@link BasicAutomata#makeTotalDigits(int)}.
*/
public static Automaton makeTotalDigits(int i) {
return BasicAutomata.makeTotalDigits(i);
}
/**
* See {@link BasicAutomata#makeFractionDigits(int)}.
*/
public static Automaton makeFractionDigits(int i) {
return BasicAutomata.makeFractionDigits(i);
}
/**
* See {@link BasicAutomata#makeIntegerValue(String)}.
*/
public static Automaton makeIntegerValue(String value) {
return BasicAutomata.makeIntegerValue(value);
}
/**
* See {@link BasicAutomata#makeDecimalValue(String)}.
*/
public static Automaton makeDecimalValue(String value) {
return BasicAutomata.makeDecimalValue(value);
}
/**
* See {@link BasicAutomata#makeStringMatcher(String)}.
*/
public static Automaton makeStringMatcher(String s) {
return BasicAutomata.makeStringMatcher(s);
}
/**
* See {@link BasicOperations#concatenate(Automaton, Automaton)}.
*/
public Automaton concatenate(Automaton a) {
return BasicOperations.concatenate(this, a);
}
/**
* See {@link BasicOperations#concatenate(List)}.
*/
static public Automaton concatenate(List l) {
return BasicOperations.concatenate(l);
}
/**
* See {@link BasicOperations#optional(Automaton)}.
*/
public Automaton optional() {
return BasicOperations.optional(this);
}
/**
* See {@link BasicOperations#repeat(Automaton)}.
*/
public Automaton repeat() {
return BasicOperations.repeat(this);
}
/**
* See {@link BasicOperations#repeat(Automaton, int)}.
*/
public Automaton repeat(int min) {
return BasicOperations.repeat(this, min);
}
/**
* See {@link BasicOperations#repeat(Automaton, int, int)}.
*/
public Automaton repeat(int min, int max) {
return BasicOperations.repeat(this, min, max);
}
/**
* See {@link BasicOperations#complement(Automaton)}.
*/
public Automaton complement() {
return BasicOperations.complement(this);
}
/**
* See {@link BasicOperations#minus(Automaton, Automaton)}.
*/
public Automaton minus(Automaton a) {
return BasicOperations.minus(this, a);
}
/**
* See {@link BasicOperations#intersection(Automaton, Automaton)}.
*/
public Automaton intersection(Automaton a) {
return BasicOperations.intersection(this, a);
}
/**
* See {@link BasicOperations#subsetOf(Automaton, Automaton)}.
*/
public boolean subsetOf(Automaton a) {
return BasicOperations.subsetOf(this, a);
}
/**
* See {@link BasicOperations#union(Automaton, Automaton)}.
*/
public Automaton union(Automaton a) {
return BasicOperations.union(this, a);
}
/**
* See {@link BasicOperations#union(Collection)}.
*/
static public Automaton union(Collection l) {
return BasicOperations.union(l);
}
/**
* See {@link BasicOperations#determinize(Automaton)}.
*/
public void determinize() {
BasicOperations.determinize(this);
}
/**
* See {@link BasicOperations#addEpsilons(Automaton, Collection)}.
*/
public void addEpsilons(Collection pairs) {
BasicOperations.addEpsilons(this, pairs);
}
/**
* See {@link BasicOperations#isEmptyString(Automaton)}.
*/
public boolean isEmptyString() {
return BasicOperations.isEmptyString(this);
}
/**
* See {@link BasicOperations#isEmpty(Automaton)}.
*/
public boolean isEmpty() {
return BasicOperations.isEmpty(this);
}
/**
* See {@link BasicOperations#isTotal(Automaton)}.
*/
public boolean isTotal() {
return BasicOperations.isTotal(this);
}
/**
* See {@link BasicOperations#getShortestExample(Automaton, boolean)}.
*/
public String getShortestExample(boolean accepted) {
return BasicOperations.getShortestExample(this, accepted);
}
/**
* See {@link BasicOperations#run(Automaton, String)}.
*/
public boolean run(String s) {
return BasicOperations.run(this, s);
}
/**
* See {@link MinimizationOperations#minimize(Automaton)}.
*/
public void minimize() {
MinimizationOperations.minimize(this);
}
/**
* See {@link MinimizationOperations#minimize(Automaton)}.
* Returns the automaton being given as argument.
*/
public static Automaton minimize(Automaton a) {
a.minimize();
return a;
}
/**
* See {@link SpecialOperations#overlap(Automaton, Automaton)}.
*/
public Automaton overlap(Automaton a) {
return SpecialOperations.overlap(this, a);
}
/**
* See {@link SpecialOperations#singleChars(Automaton)}.
*/
public Automaton singleChars() {
return SpecialOperations.singleChars(this);
}
/**
* See {@link SpecialOperations#trim(Automaton, String, char)}.
*/
public Automaton trim(String set, char c) {
return SpecialOperations.trim(this, set, c);
}
/**
* See {@link SpecialOperations#compress(Automaton, String, char)}.
*/
public Automaton compress(String set, char c) {
return SpecialOperations.compress(this, set, c);
}
/**
* See {@link SpecialOperations#subst(Automaton, Map)}.
*/
public Automaton subst(Map> map) {
return SpecialOperations.subst(this, map);
}
/**
* See {@link SpecialOperations#subst(Automaton, char, String)}.
*/
public Automaton subst(char c, String s) {
return SpecialOperations.subst(this, c, s);
}
/**
* See {@link SpecialOperations#homomorph(Automaton, char[], char[])}.
*/
public Automaton homomorph(char[] source, char[] dest) {
return SpecialOperations.homomorph(this, source, dest);
}
/**
* See {@link SpecialOperations#projectChars(Automaton, Set)}.
*/
public Automaton projectChars(Set chars) {
return SpecialOperations.projectChars(this, chars);
}
/**
* See {@link SpecialOperations#isFinite(Automaton)}.
*/
public boolean isFinite() {
return SpecialOperations.isFinite(this);
}
/**
* See {@link SpecialOperations#getStrings(Automaton, int)}.
*/
public Set getStrings(int length) {
return SpecialOperations.getStrings(this, length);
}
/**
* See {@link SpecialOperations#getFiniteStrings(Automaton)}.
*/
public Set getFiniteStrings() {
return SpecialOperations.getFiniteStrings(this);
}
/**
* See {@link SpecialOperations#getFiniteStrings(Automaton, int)}.
*/
public Set getFiniteStrings(int limit) {
return SpecialOperations.getFiniteStrings(this, limit);
}
/**
* See {@link SpecialOperations#getCommonPrefix(Automaton)}.
*/
public String getCommonPrefix() {
return SpecialOperations.getCommonPrefix(this);
}
/**
* See {@link SpecialOperations#prefixClose(Automaton)}.
*/
public void prefixClose() {
SpecialOperations.prefixClose(this);
}
/**
* See {@link SpecialOperations#hexCases(Automaton)}.
*/
public static Automaton hexCases(Automaton a) {
return SpecialOperations.hexCases(a);
}
/**
* See {@link SpecialOperations#replaceWhitespace(Automaton)}.
*/
public static Automaton replaceWhitespace(Automaton a) {
return SpecialOperations.replaceWhitespace(a);
}
/**
* See {@link ShuffleOperations#shuffleSubsetOf(Collection, Automaton, Character, Character)}.
*/
public static String shuffleSubsetOf(Collection ca, Automaton a, Character suspend_shuffle, Character resume_shuffle) {
return ShuffleOperations.shuffleSubsetOf(ca, a, suspend_shuffle, resume_shuffle);
}
/**
* See {@link ShuffleOperations#shuffle(Automaton, Automaton)}.
*/
public Automaton shuffle(Automaton a) {
return ShuffleOperations.shuffle(this, a);
}
}