haal-0.2.0.0: examples/io.hs
-- we will attempt to reproduce the `div.hs` learning experiment,
-- but this time, instead of using a haskell function as a SUL,
-- we will use an actual program that performs IO, whose input and
-- output alphabet we know.
-- the output alphabet is just bool
-- the input alphabet is binary
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
import Data.Functor ((<&>))
import Haal.Automaton.MealyAutomaton
import Haal.BlackBox
import Haal.EquivalenceOracle.WpMethod
import Haal.Experiment
import Haal.Learning.LMstar
import System.Process (readProcess)
-- Note that this is relative to the project root. Otherwise
-- the executable will not be found
source :: String
source = "./examples/divisible3"
inputMap :: Int -> String
inputMap num = show num ++ "\n"
innerQuery :: String -> IO String
innerQuery = readProcess source []
outputMap :: String -> Bool
outputMap = read
query :: Int -> IO Bool
query = (<&> outputMap) . innerQuery . inputMap
data Binary = B0 | B1 deriving (Show, Eq, Ord, Enum, Bounded)
-- now we are in the position to use binary digits to construct integers.
-- we need a mapper that maps from binary digits to integers that the program can actually use
convert :: (Num a) => [Binary] -> a
convert [] = 0
convert [B0] = 0
convert [B1] = 1
convert (b : bs) = convert [b] + 2 * convert bs
-- this time, in contrast to div.hs, a Program performs IO actions,
-- instead of purely returning the computes values
data Program i o = Program
{ theStep :: i -> IO (Program i o, o)
, theReset :: IO (Program i o)
, buffer :: [i]
}
instance SUL Program IO Binary Bool where
step = theStep
reset = theReset
wrapped :: [Binary] -> IO Bool
wrapped = query . convert
mkProg :: [Binary] -> Program Binary Bool
mkProg buf =
Program
{ theStep = \x -> do
let newBuf = x : buf
o <- wrapped newBuf
return (mkProg newBuf, o)
, theReset = return (mkProg [])
, buffer = buf
}
-- construct a sul with an empty buffer
sul :: Program Binary Bool
sul = mkProg []
learner :: LMstar Binary Bool
learner = mkLMstar Star
oracle :: WpMethod
oracle = mkWpMethod (WpMethodConfig 3)
exper ::
ExperimentT
(Program Binary Bool)
IO
( MealyAutomaton
StateID
Binary
Bool
, Statistics
MealyAutomaton
StateID
Binary
Bool
)
exper = experiment learner oracle
main :: IO ()
main = do
(theModel, theStats) <- runExperimentT exper sul
putStrLn "Learning Experiment"
putStrLn "==================="
putStrLn "System Under Learning: \\x -> x `mod` 3 == 0"
putStrLn $ "Learned Model: " ++ show theModel
putStrLn $ "Experiment Statistics: " ++ show theStats