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 = {
}
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
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