Contains the DFA definition.

Imports

module Agdomaton.DfaDef where

open import Relation.Binary.PropositionalEquality using (_≡_; refl)
open import Data.Nat using (; zero; suc; _≤_; s≤s)
open import Data.Empty using (; ⊥-elim)
open import Data.Sum using (_⊎_; inj₁; inj₂; [_,_])
open import Data.Product using (_×_; _,_; proj₁; proj₂)
open import Relation.Nullary using (¬_)
open import Axiom.Extensionality.Propositional using (Extensionality)
open import Data.List.Relation.Binary.Subset.Propositional.Properties
open import Relation.Unary using (Pred; _⊆_; _∈_)
open import Data.Fin.Base using (Fin; zero; suc; fromℕ; fromℕ<)
open import Data.Vec using (Vec; _∷_; []; map)
open import Agda.Builtin.List using (List; _∷_; [])
open import Data.Bool.Base using (Bool; _∧_; true; false; if_then_else_)
open import Agda.Primitive using (Set; Level; lzero; lsuc)

open import Agdomaton.LogicBase

Defining the DFA

data State {n : } : Set where
  q : (Fin n)  State

data Symbol {n : } : Set where
  σ : (Fin n)  Symbol

-- A word, a list of symbols
data Word {ns : } :   Set where
  [] : Word {ns} zero
  _∷_ :  {n} (s : Symbol {ns}) (w : Word {ns} n)  Word {ns} (suc n)

-- A possibly infinite word, a list of symbols
data IWord {ns : } : Set where
  [] : IWord {ns}
  _∷_ : (Symbol {ns})  IWord {ns}  IWord {ns}

TransitionFunction : {nq ns : }  Set
TransitionFunction {nq} {ns} = (State {nq} × Symbol {ns})  State {nq}

record DFA
  {nq ns nf : }
  -- (Q : Vec (State {nq}) nq)
  -- (Σ : Vec (Symbol {ns}) ns)
  : Set where
  field
    δ : TransitionFunction {nq} {ns}
    q₀ : State {nq}
    F : Vec (State {nq}) nf

Helpers

-- Check if two finite numbers are equal
fin-eq : {n : }
   (Fin n)
   (Fin n)
   Bool
fin-eq zero zero = true
fin-eq zero (suc y) = false
fin-eq (suc x) zero = false
fin-eq (suc x) (suc y) = fin-eq x y

-- Check if two states are equal
state-eq : {n : }
   State {n}
   State {n}
   Bool
state-eq (q x) (q y) = fin-eq x y

-- Check if a state is in a vec of states
elem-state : {nq n : }
   (State {nq})
   Vec (State {nq}) n
   Bool
elem-state x [] = false
elem-state x (y  ys) = if (state-eq x y) then true else elem-state x ys

postulate
  all-symbols-impl : {ns : }  (n : )  (n  (suc ns))  Vec (Symbol {suc ns}) n
-- all-symbols-impl {ns} zero n≤ns = []
-- all-symbols-impl {ns} (suc n) n1≤ns = σ (fromℕ< {n} n1≤ns) ∷ all-symbols-impl {ns} n (s≤s n1≤ns)

postulate
  all-symbols : {ns : }  Vec (Symbol {ns}) ns
-- all-symbols {zero} = []
-- all-symbols {suc ns} = all-symbols-impl {ns} (suc ns)

all-true : {n : }  Vec Bool n  Bool
all-true [] = true
all-true (x  xs) = x  all-true xs

∀symbols-check : {ns : }
   ((Symbol {ns})  Bool)
   Bool
∀symbols-check {ns} p = all-true (map p (all-symbols {ns}))

∀symbols : {ns : }
   ((Symbol {ns})  Bool)
   Bool
∀symbols {ns} p = ∀symbols-check {ns} p

-- Follow a single symbol through a DFA, returning a new DFA which starts on
-- the state reached by following the symbol
dfa-transition-one : {nq ns nf : }
   (Symbol {ns})
   DFA {nq} {ns} {nf}
   DFA {nq} {ns} {nf}
dfa-transition-one sym dfa = record dfa { q₀ = (DFA.δ dfa) ((DFA.q₀ dfa), sym) }

-- Check if a DFA is in an accept state.
-- This checks if q₀ is in the set of accept states.
dfa-in-accept-state : {nq ns nf : }
   DFA {nq} {ns} {nf}
   Bool
dfa-in-accept-state dfa = elem-state (DFA.q₀ dfa) (DFA.F dfa)

cyclic-edge : {nq ns : }
   State {nq}
   Symbol {ns}
   TransitionFunction {nq} {ns}
   Bool
cyclic-edge state sym δ = state-eq (δ (state , sym)) state

dead-state : {nq ns : }
   State {nq}
   TransitionFunction {nq} {ns}
   Bool
dead-state state δ = ∀symbols  sym  cyclic-edge state sym δ)

Check if a DFA accepts a word

-- Follow a word through a DFA, returning a
-- new DFA which starts on the state reached
-- by following the symbols.
dfa-follow : {nq ns nf n : }
   Word {ns} n
   DFA {nq} {ns} {nf}
   DFA {nq} {ns} {nf}
dfa-follow [] dfa = dfa
dfa-follow (sym  ss) dfa = dfa-follow ss (dfa-transition-one sym dfa)

-- Check if a DFA accepts a word.
dfa-accepts : {nq ns nf n : }
   Word {ns} n
   DFA {nq} {ns} {nf}
   Bool
dfa-accepts ls dfa = dfa-in-accept-state (dfa-follow ls dfa)

-- Follow a possibly infinite word through a DFA,
-- returning a new DFA which starts on
-- the state reached by following the symbols.
dfa-follow-infinite : {nq ns nf : }
   IWord {ns}
   DFA {nq} {ns} {nf}
   DFA {nq} {ns} {nf}
dfa-follow-infinite [] dfa = dfa
dfa-follow-infinite (sym  ss) dfa = dfa-follow-infinite ss (dfa-transition-one sym dfa)

-- Check if a DFA accepts a possibly infinite word.
dfa-accepts-infinite : {nq ns nf n : }
   IWord {ns}
   DFA {nq} {ns} {nf}
   Bool
dfa-accepts-infinite ls dfa = dfa-in-accept-state (dfa-follow-infinite ls dfa)