> {-# OPTIONS_HADDOCK show-extensions #-}
> {-|
> Module    : LTK.Decide.Finite
> Copyright : (c) 2021 Dakotah Lambert
> License   : MIT

> This module implements an algorithm to decide whether a given FSA
> is finite.  Also included for convenience is a test for cofiniteness.
>
> @since 1.0
> -}
> module LTK.Decide.Finite (isFinite, isCofinite) where

> import LTK.FSA
> import LTK.Traversals

> -- |True iff the automaton accepts only finitely many words.
> isFinite :: (Ord n, Ord e) => FSA n e -> Bool
> isFinite :: FSA n e -> Bool
isFinite = FSA Integer e -> Bool
forall n e. (Ord n, Ord e) => FSA n e -> Bool
isAcyclic (FSA Integer e -> Bool)
-> (FSA n e -> FSA Integer e) -> FSA n e -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FSA n e -> FSA Integer e
forall e n. (Ord e, Ord n) => FSA n e -> FSA Integer e
normalize

> -- |True iff the automaton accepts all but finitely many words.
> isCofinite :: (Ord n, Ord e) => FSA n e -> Bool
> isCofinite :: FSA n e -> Bool
isCofinite = FSA (Set n) e -> Bool
forall n e. (Ord n, Ord e) => FSA n e -> Bool
isFinite (FSA (Set n) e -> Bool)
-> (FSA n e -> FSA (Set n) e) -> FSA n e -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FSA n e -> FSA (Set n) e
forall e n. (Ord e, Ord n) => FSA n e -> FSA (Set n) e
complement