Commit 2e5cb9dd authored by Hans-Peter Deifel's avatar Hans-Peter Deifel
Browse files

Implement random DFA generator

This is still work in progress. At the moment, only graphviz is
available as output format and the command line interface isn't final
yet.
parent caba941c
......@@ -13,7 +13,7 @@ maintainer: hans-peter.deifel@fau.de
-- category:
build-type: Custom
cabal-version: >=1.24
custom-setup
setup-depends:
base, Cabal, cabal-doctest >= 1.0.2 && <1.1
......@@ -240,3 +240,20 @@ executable prism-converter
, microlens
, microlens-th
, microlens-platform
executable random-dfa
hs-source-dirs: src/random-dfa
main-is: Main.hs
other-modules: Type
, CoalgOutput
, DotOutput
default-language: Haskell2010
default-extensions: OverloadedStrings
, LambdaCase
build-depends: base
, vector
, microlens
, microlens-th
, microlens-platform
, random
, text
module CoalgOutput () where
module DotOutput (dotB) where
import Data.Foldable ( fold )
import qualified Data.Text.Lazy.Builder as Build
import qualified Data.Text.Lazy.Builder.Int as Build
import Lens.Micro.Platform
import Type
dotB :: DFA -> Build.Builder
dotB dfa = "digraph {\n" <> nodesB dfa <> transitionsB dfa <> "}"
nodesB :: DFA -> Build.Builder
nodesB dfa = foldMap (nodeB dfa) [0 .. dfa ^. states - 1]
nodeB :: DFA -> Int -> Build.Builder
nodeB dfa n = " \"n" <> Build.decimal n <> "\" [shape = " <> shape <> "];\n"
where shape = if dfa ^?! isFinal . ix n then "doublecircle" else "circle"
transitionsB :: DFA -> Build.Builder
transitionsB dfa = foldMap (transitionsForB dfa) [0 .. dfa ^. states - 1]
transitionsForB :: DFA -> Int -> Build.Builder
transitionsForB dfa n =
fold (zipWith (transitionB n) [0 ..] (dfa ^.. transitions . ix n . each))
transitionB :: Int -> Int -> Int -> Build.Builder
transitionB source letter target =
" n"
<> Build.decimal source
<> " -> n"
<> Build.decimal target
<> " [label=a"
<> Build.decimal letter
<> "];\n"
module Main (main) where
import System.Environment
import qualified Data.Text.Lazy.IO as TL
import qualified Data.Text.Lazy.Builder as Build
import qualified Data.Vector as V
import qualified Data.Vector.Unboxed as VU
import System.Random
import Type
import DotOutput
-- | Generate a random DFA
randomDFA
:: Int -- ^ Number of states
-> Int -- ^ Size of the alphabet
-> IO DFA
randomDFA s a = do
finals <- VU.replicateM s randomIO
matrix <- V.replicateM s (VU.replicateM a (randomRIO (0, s - 1)))
return DFA
{ _states = s
, _letters = a
, _isFinal = finals
, _transitions = matrix
}
main :: IO ()
main = do
[tNumStates, tSizeAlph] <- getArgs
let numStates = read tNumStates
sizeAlph = read tSizeAlph
dfa <- randomDFA numStates sizeAlph
TL.putStrLn (Build.toLazyText (dotB dfa))
return ()
{-# LANGUAGE TemplateHaskell #-}
module Type (DFA(..), states, letters, transitions, isFinal) where
import Data.Vector ( Vector )
import qualified Data.Vector.Unboxed as VU
import Lens.Micro.TH
data DFA = DFA
{ _states :: Int
, _letters :: Int
, _transitions :: Vector (VU.Vector Int)
, _isFinal :: VU.Vector Bool
}
makeLenses ''DFA
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment