fsharp-finite-automata/DFA.fs
2019-03-15 21:20:25 +01:00

72 lines
No EOL
2 KiB
FSharp

module DFA
open System
open Shields.GraphViz
///
/// A deterministic finite automaton
///
type DFA = {
/// All possible characters
sigma: Char list
/// All possible states
states: String list
/// All possible transitions
delta: String -> Char -> String
/// The state this DFA begins in
beginState: String
/// The states in which this DFA accepts
/// the word
acceptingStates: String list
}
(*
let createGraph (dfa:DFA) =
let mutable graph = Graph.Directed.Add(EdgeStatement.For("a", "b"))
graph
*)
/// Returns true if the DFA is valid, false otherwise
let validateDFA (dfa:DFA) =
let allAcceptingStatesAreStates =
dfa.acceptingStates
|> List.map (fun x -> List.contains x dfa.states)
|> List.filter not
|> List.length
|> (<) 1
let deltaIsComplete =
// Gets the cartesian product of states * sigma
dfa.states
|> List.collect (fun x -> dfa.sigma |> List.map (fun y -> (x, y)))
// Processes all tuples through delta
|> List.map (fun x -> dfa.delta (fst x) (snd x))
// Checks if there is any result from delta which is not
// a valid state
|> List.filter (fun x -> not (List.contains x dfa.states))
|> List.length
|> (<) 1
List.contains dfa.beginState dfa.states ||
allAcceptingStatesAreStates ||
deltaIsComplete
/// Returns the state the DFA is in after
/// reading this character
let processChar (dfa: DFA) (state: String) (char: Char) =
dfa.delta state char
/// Returns the state the DFA is in after
/// reading this character array
let rec processCharArray (dfa: DFA) (state: String) (charArr: Char list) =
match charArr with
| [] -> state
| head :: tail -> processCharArray dfa (processChar dfa state head) tail
/// Returns whether the DFA accepts this word
let acceptsWord (dfa: DFA) (word: String) =
dfa.acceptingStates
|> List.contains (processCharArray dfa dfa.beginState (Seq.toList word))