1
Fork 0
mirror of https://github.com/Jaxan/ons-hs.git synced 2025-04-27 22:57:44 +02:00
ons-hs/app/ExampleAutomata.hs

163 lines
5.2 KiB
Haskell

{-# language DeriveGeneric #-}
{-# language DerivingVia #-}
{-# language FlexibleContexts #-}
{-# language ImportQualifiedPost #-}
{-# language RecordWildCards #-}
{-# language UndecidableInstances #-}
{-# OPTIONS_GHC -Wno-missing-signatures #-}
module ExampleAutomata
( module ExampleAutomata
, module Automata
) where
import Automata
import EquivariantMap qualified as Map
import EquivariantSet qualified as Set
import IO
import Nominal hiding (product)
import OrbitList
import Permutable
import Data.Foldable (fold)
import Data.Map.Strict qualified as Data.Map
import GHC.Generics (Generic)
import Prelude as P hiding (map, product, words, filter, foldr)
atoms = rationals
-- words of length <= m
words m = fold $ go (m+1) (singleOrbit []) where
go 0 _ = []
go k acc = acc : go (k-1) (productWith (:) atoms acc)
fromKeys f = Map.fromSet f . Set.fromOrbitList
ltPair = filter (\(a, b) -> a < b) $ product atoms atoms
data DoubleWord = Store [Atom] | Check [Atom] | Accept | Reject
deriving (Eq, Ord, Generic)
deriving Nominal via Generically DoubleWord
instance ToStr DoubleWord where
toStr (Store w) = "S " ++ toStr w
toStr (Check w) = "C " ++ toStr w
toStr Accept = "A"
toStr Reject = "R"
doubleWordAut 0 = Automaton {..} where
states = fromList [Accept, Reject]
initialState = Accept
acceptance = fromKeys (Accept ==) states
transition = fromKeys (const Reject) $ product states rationals
doubleWordAut n = Automaton {..} where
states = fromList [Accept, Reject] <> map Store (words (n-1)) <> map Check (productWith (:) rationals (words (n-1)))
initialState = Store []
acceptance = fromKeys (Accept ==) states
trans Accept _ = Reject
trans Reject _ = Reject
trans (Store l) a
| length l + 1 < n = Store (a:l)
| otherwise = Check (reverse (a:l))
trans (Check (a:as)) b
| a == b = if (P.null as) then Accept else Check as
| otherwise = Reject
transition = fromKeys (uncurry trans) $ product states rationals
-- alphetbet for the Fifo queue example
data FifoA = Put Atom | Get Atom
deriving (Eq, Ord, Show, Generic)
deriving Nominal via Generically FifoA
-- TODO: find a generic way to derive this.
instance Permutable FifoA where
act (Permuted (Perm m) (Put p)) = Put $ Data.Map.findWithDefault p p m
act (Permuted (Perm m) (Get p)) = Get $ Data.Map.findWithDefault p p m
instance ToStr FifoA where
toStr (Put a) = "Put " ++ toStr a
toStr (Get a) = "Get " ++ toStr a
instance FromStr FifoA where
fromStr ('P':'u':'t':' ':a) = let (x, r) = fromStr a in (Put x, r)
fromStr ('G':'e':'t':' ':a) = let (x, r) = fromStr a in (Get x, r)
fromStr _ = error "Cannot parse Fifo"
fifoAlph = map Put rationals <> map Get rationals
data FifoS = FifoS [Atom] [Atom]
deriving (Eq, Ord, Generic)
deriving Nominal via Generically FifoS
instance ToStr FifoS where
toStr (FifoS l1 l2) = "F " ++ toStr l1 ++ " - " ++ toStr l2
fifoAut n = Automaton {..} where
states0 = filter (\(FifoS l1 l2) -> length l1 + length l2 <= n) $ productWith (\l1 l2 -> FifoS l1 l2) (words n) (words n)
states = fromList [Nothing] <> map Just states0
initialState = Just (FifoS [] [])
acceptance = fromKeys (Nothing /=) states
trans Nothing _ = Nothing
trans (Just (FifoS l1 l2)) (Put a)
| length l1 + length l2 >= n = Nothing
| otherwise = Just (FifoS (a:l1) l2)
trans (Just (FifoS [] [])) (Get _) = Nothing
trans (Just (FifoS l1 [])) (Get b) = trans (Just (FifoS [] (reverse l1))) (Get b)
trans (Just (FifoS l1 (a:l2))) (Get b)
| a == b = Just (FifoS l1 l2)
| otherwise = Nothing
transition = fromKeys (uncurry trans) $ product states fifoAlph
data Lint a = Lint_start | Lint_single a | Lint_full a a | Lint_semi a a | Lint_error
deriving (Eq, Ord, Show, Generic)
deriving Nominal via Generically (Lint a)
lintExample ::Automaton (Lint Atom) Atom
lintExample = Automaton {..} where
states = fromList [Lint_start, Lint_error]
<> map Lint_single atoms
<> map (uncurry Lint_full) ltPair
<> map (uncurry Lint_semi) ltPair
initialState = Lint_start
acc (Lint_full _ _) = True
acc _ = False
acceptance = fromKeys acc states
trans Lint_start a = Lint_single a
trans (Lint_single a) b
| a < b = Lint_full a b
| otherwise = Lint_error
trans (Lint_full a b) c
| a < c && c < b = Lint_semi c b
| otherwise = Lint_error
trans (Lint_semi a b) c
| a < c && c < b = Lint_full a c
| otherwise = Lint_error
trans Lint_error _ = Lint_error
transition = fromKeys (uncurry trans) $ product states atoms
data Lmax a = Lmax_start | Lmax_single a | Lmax_double a a
deriving (Eq, Ord, Show, Generic)
deriving Nominal via Generically (Lmax a)
lmaxExample :: Automaton (Lmax Atom) Atom
lmaxExample = Automaton {..} where
states = singleOrbit Lmax_start
<> map Lmax_single atoms
<> productWith Lmax_double atoms atoms
initialState = Lmax_start
acc (Lmax_double a b) = a == b
acc _ = False
acceptance = fromKeys acc states
trans Lmax_start a = Lmax_single a
trans (Lmax_single a) b = Lmax_double a b
trans (Lmax_double b c) a
| b >= c = Lmax_double b a
| otherwise = Lmax_double c a
transition = fromKeys (uncurry trans) $ product states atoms