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)) let complement (dfa: DFA) : DFA = { sigma = dfa.sigma; states = dfa.states; delta = dfa.delta; beginState = dfa.beginState; acceptingStates = dfa.states |> List.filter (fun x -> not (List.contains x dfa.acceptingStates)) }