Module Nfa


module Nfa: sig .. end
Nondeterministic finite state automata, implemented using explicit Hashtbl representations for delta (transitions that consume a symbol) and epsilon (transitions that do not consume a symbol).


Constants
val def_machine_size : int
val def_delta_size : int
val def_eps_size : int

We model characters (i.e. elements of the alphabet) as integers; see also Charset.
type charset = Charset.set 

type symbol =
| Character of int
| Epsilon

We model the transition function delta as a mapping state -> (state -> character set). Epsilon transitions are modeled separately by a mapping state -> state set:
type 'a delta = ('a, ('a, charset) Hashtbl.t) Hashtbl.t 
type 'a epsilon = ('a, 'a Hashset.hashset) Hashtbl.t 
type state = int 

type nfa = {
   mutable s : state;
   mutable f : state;
   mutable delta : state delta;
   mutable epsilon : state epsilon;
   mutable q : state Hashset.hashset;
   mutable next_q : state;
}
Nfa with state type 'a, a single start state s, and a single accepting state f:

Basic transition function handling

val all_delta : ?create:bool -> 'a delta -> 'a -> ('a, charset) Hashtbl.t
Get the rhs (state -> character set) mapping for a given origin state s in transition function d
Returns A mapping state -> charset containing all states reachable from s by a direct (non-epsilon) transition, with the associated set of transition symbols.
create : Whether the inner hashtable should be instantiated if none currently exists
d : A transition function
val which_symbols : ?create:bool -> 'a delta -> 'a -> 'a -> charset
Get the character set by applying (delta s1) s2
Returns A charset of all non-epsilon transition symbols that reach s2 from s1 through a direct edge.
create : Whether the inner hashtable and the inner character set should be created if they do not already exist
s1 : Origin state
s2 : Destination state
val which_states : ?create:bool -> 'a epsilon -> 'a -> 'a Hashset.hashset
Get the rhs state set in the epsilon mapping e
Returns The set of states reachable from s1 through a single epsilon-transition. If no such states exist, an empty set is created.
create : Add empty state set if none is found
e : An epsilon mapping
s1 : An origin state
val copy_table : ('a, ('a, 'b) Hashtbl.t) Hashtbl.t ->
('c, ('c, 'b) Hashtbl.t) Hashtbl.t -> ('a -> 'c) -> unit
Copy a delta or epsilon, applying a transformation to each element
s : Source
t : Target
f : transformation
val nested_ht_iter : ('a, 'b) Hashtbl.t ->
('c, 'd) Hashtbl.t -> ('a -> 'b -> 'c -> 'd -> unit) -> unit
For all mappings p -> q in hashtable a and for all r -> s in hashtable b, execute f p q r s. Used by Nfa.intersect
val fmap : 'a Hashset.hashset -> ('a -> 'b) -> ('a, 'b) Hashtbl.t

NFA Construction

val new_nfa_states : state -> state -> nfa
Create an empty NFA with start state s and accepting state f; note that s and f should not be equal.
Returns An NFA consisting of states s and f, with no transitions.
s : Start state
f : Final state
val new_state : nfa -> state
Add a new state
Returns The integer id of the state that was added
n : An NFA
val add_state : nfa -> state -> unit
Add a specific state
n : An NFA
s : State id to add
val add_trans : nfa -> state -> symbol -> state -> unit
Add single transition s1 -c-> s2
nfa : An NFA
s1 : The origin state
c : The transition symbol; either a string or epsilon
s2 : The destination state
val add_all_trans : nfa -> state -> state -> unit
Add transitions s1 -c-> s2 for all c
nfa : An NFA
s1 : The origin state
s2 : The destination state
val add_set_trans : nfa -> state -> charset -> state -> unit
Add transitions s1 -c-> s2 for all c in l
nfa : An NFA
s1 : The origin state
cs : A (char)set of characters that reach s2 from s1
s2 : The destination state
val new_sigmastar : unit -> nfa
Construct an NFA that accepts

Basic NFA operations

val print_nfa : nfa -> unit
Pretty print an NFA.
nfa : NFA to print
val nfa_to_dot : nfa -> string
Convert an NFA to Graphviz dot format
Returns A string containing a (currently rather rough) dot file representation of the NFA, where nodes are states and edges are transitions.
nfa : An NFA
val neighbors : nfa -> state -> state list
Get all immediate outbound neighbors of a given state
Returns All states reachable from s in nfa through a single transition (nfa is unchanged)
nfa : An nfa
q : A state in nfa

We use integer sets for the epsilon closure; this is vaguely because we do a lot of comparing between closures
module StateSet: Set.Make(sig
type t = Nfa.state 
val compare : 'a -> 'a -> int
end)
type stateset = StateSet.t 
val eps_closure : nfa -> state -> stateset
Epsilon closure for a given NFA state
Returns The set of states transitively reachable through epsilon transitions, starting at q, including q
q : A state in nfa
val rhs : nfa -> state -> int -> stateset
Find all states q' such that q reaches q' on c through a single transition.
Returns The set of reachable states
n : An NFA
q : A state in n
c : A character
val forward_fold_nfa : (state -> 'a -> 'a) -> nfa -> state -> 'a -> 'a
Generic forward walk over an NFA (depth first; visits all states forward-reachable from s). Not-quite tail-recursive.
f : A function state -> accumulator -> accumulator.
nfa : NFA to walk
s : State to start the walk from
acc : Initial accumulator value
val backward_mapping : nfa -> (state, state Hashset.hashset) Hashtbl.t
Construct a reverse reachability mapping
Returns A mapping s -> R for all states s in nfa.q, where R contains all the states that have an edge to s
nfa : an NFA
val backward_reachable : nfa -> state -> state Hashset.hashset
Backward reachability from a specified state
Returns All states that are backward-reachable from s in nfa
nfa : An NFA
s : State of interest
val elim_dead_states : nfa -> unit
Eliminate states that do not reach the final state.
nfa : An NFA (modified in place)
val reverse : nfa -> nfa
Reverse all transitions, swap start and final states; used by Nfa.minimize
Returns A reversed copy of n
n : An NFA (not modified)
val copy_nfa : nfa -> nfa
Copy an NFA
Returns a copy of nfa
nfa : NFA to copy (parameter is unmodified)
val extract_nfa : nfa -> state -> state -> nfa
Extract a subNFA from a bigger NFA
Returns A copy of nfa with start state s, final state f, and a subset of nfa's states
nfa : NFA to (partially) copy
s : Start state for the result
f : Final state for the result
val merge_nfas : nfa -> nfa -> unit
Merge two NFAs
target : An NFA to "host" the a copy of source
source : Another NFA (unmodified)
val normalize_nfa : nfa -> state -> nfa
Rebuild NFA with contiquous integer state space.
Returns NFA with base as the lowest state ID and base + (size nfa.q) - 1 as the highest
nfa : An NFA (not modified)
base : Lowest state ID for output machine

DFA-related operations

val nfa_to_dfa : nfa -> nfa
Determinize an NFA (necessary for e.g. compliment)
Returns An NFA that looks mostly like a DFA: all states have outbound edges for every alphabet symbol, and no epsilon transitions are used *except* for transitions to the (single) final state.
n : NFA to turn into a DFA
val complement : nfa -> unit
Compute the complement of a given determinized NFA. Note: Changes its parameter in place.
dfa : An NFA that has been determinized; this function will fail miserably if it was not.
val minimize : nfa -> nfa
Minimize an NFA using Brzozowski's minimization algorithm
Returns A minimized copy of n
n : NFA to minimize

Language Operations

val concat : nfa ->
nfa ->
state Hashset.hashset ->
state Hashset.hashset ->
(state, state) Hashtbl.t * (state, state) Hashtbl.t * nfa
Annotated NFA concatenation using a single epsilon-transition.
Returns A tree-tuple (p1', p2', m3) So that m3 is an NFA with language L(m3) = L(m1) concat L(m2); p1' subset m3.q is the set of states that correspond to states in p1; and p2' subset m3.q is the set of states that correspond to states in p2. (Note: for the current concat implementation, p1 = p1' for all calls to concat).
p1 : A subset of m1.q
p2 : A subset of m2.q
val simple_concat : nfa -> nfa -> nfa
Concat without the state-converting frills
Returns An NFA that accepts L(m1).L(m2)
m1 : An NFA (unmodified)
m2 : Another NFA (unmodified)
val union : nfa -> nfa -> nfa
Applicative NFA union
Returns An NFA that accepts L(a) cup L(b)
a : An NFA (unchanged)
b : Another NFA (unchanged)
val intersect : nfa ->
nfa ->
state Hashset.hashset -> (state, state list) Hashtbl.t * nfa
Annotated NFA intersection using the cross-product construction
Returns A tuple (p1', m3) So that m3 is an NFA with language L(m3) = L(m1) cap L(m2); p1' is a mapping from states in p1 to their corresponding states in m3.q
p1 : A subset of m1.q
val simple_intersect : nfa -> nfa -> nfa
Intersection without the state-converting frills
exception Found_it
val is_empty : nfa -> bool
Language emptiness
Returns true if nfa accepts no strings; false otherwise
nfa : NFA to check for emptiness
val nfa_eq : nfa -> nfa -> bool
Language equality
Returns true if L(a) = L(b); false otherwise
a : An NFA (unmodified)
b : Another NFA (also unmodified)
val nfa_subseteq : nfa -> nfa -> bool
Language subseteq
Returns true if L(a) subseteq L(b); false otherwise
a : An NFA (unmodified)
b : Another NFA (also unmodified)
val gen_string : nfa -> string option