1
Fork 0
mirror of https://github.com/Jaxan/monoid-learner.git synced 2025-04-27 06:57:44 +02:00
monoid-learner/app/Main.hs
2021-07-29 14:54:52 +02:00

144 lines
No EOL
3.9 KiB
Haskell

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PartialTypeSignatures #-}
{-# OPTIONS_GHC -Wno-partial-type-signatures #-}
module Main where
import Data.Foldable (Foldable (toList))
import Data.IORef (IORef, modifyIORef', newIORef, readIORef)
import qualified Data.Map as Map
import qualified Data.Sequence as Seq
import qualified Data.Set as Set
import Equivalence (searchCounterexample)
import Examples.Examples
import KnuthBendix (knuthBendix, rewrite)
import MStar
import Monoid
import Word (Word)
import Prelude hiding (Word)
-- We use the alphabet {a, b} as always
symbols :: Set.Set Char
symbols = Set.fromList "ab"
example :: MonoidAcceptor Char _
example =
-- 1. the first example I tried:
mainExample
-- 2. a* or b*:
-- predSymbol (== 'a') `union` predSymbol (== 'b')
-- 3. just the word abba:
-- finiteLanguage (Set.fromList ["abba"])
-- Let's count the number of membership queries
-- and print all the queries
languageM :: IORef Int -> Word Char -> IO Bool
languageM count w = do
modifyIORef' count succ
n <- readIORef count
let nstr = show n
wstr = toList w
r = acceptMonoid example w
putStr "m "
putStr nstr
putStr (replicate (6 - length nstr) ' ')
putStr wstr
putStr (replicate (24 - length wstr) ' ')
print r
return r
-- Let's count the number of equivalence queries
equiv :: _ => IORef Int -> MonoidAcceptor Char _ -> IO (Maybe (Word Char))
equiv count m = do
modifyIORef' count succ
n <- readIORef count
let nstr = show n
r = searchCounterexample symbols m example
putStr "e "
putStr nstr
putStr (replicate (6 - length nstr) ' ')
print r
return r
logger :: Show a => LogMessage a -> IO ()
logger (NewRow w) = putStr "Adding row " >> print (toList w)
logger (NewContext (l, r)) = putStr "Adding context " >> print (toList l, toList r)
logger (Stage str) = putStr "Stage: " >> putStrLn str
main :: IO ()
main = do
putStrLn "Welcome to the monoid learner"
mqCount <- newIORef 0
eqCount <- newIORef 0
let lang = languageM mqCount
let equi = equiv eqCount
-- Initialise
s <- initialState symbols lang
-- learn
(s2, m2) <- learn logger lang equi s
-- Hypothesis is now correct
let sFinal = s2
mFinal = m2
-- Print as multiplication table
putStrLn ""
putStrLn "Monoid with the elements:"
putStr " "
print (elements mFinal)
putStrLn "accepting elements:"
putStr " "
print (filter (accept mFinal) $ elements mFinal)
putStrLn "unit element"
putStr " "
print (unit mFinal)
putStrLn "multiplication table"
let multTable = (\x y -> (x, y, multiplication mFinal x y)) <$> elements mFinal <*> elements mFinal
mapM_
( \(x, y, z) -> do
putStr " "
putStr (show x)
putStr " x "
putStr (show y)
putStr " = "
print z
)
multTable
-- Print as monoid presentation
let -- Extract the rewrite rules from the table
-- For this we simply look at products r1 r2 and see which row is equivalent to it
rowPairs = Set.filter (\w -> not (w `Set.member` rows sFinal)) . Set.map (uncurry (<>)) $ Set.cartesianProduct (rows sFinal) (rows sFinal)
representatives = Map.fromList (fmap (\w -> (row sFinal w, w)) (Set.toList (rows sFinal)))
rules0 = Map.fromSet (\w -> representatives Map.! row sFinal w) rowPairs
rules = Map.toList rules0
kbRules = knuthBendix rules
-- Also extract final set
accRows0 = Set.filter (\m -> row sFinal m Map.! (Seq.empty, Seq.empty)) $ rows sFinal
accRows = Set.map (rewrite kbRules) accRows0
putStrLn ""
putStrLn "Monoid on the generators:"
putStr " "
print (fmap (: []) (toList symbols))
putStrLn "accepting strings:"
putStr " "
print (fmap toList (toList accRows))
putStrLn "with equations:"
mapM_
( \(l, r) -> do
putStr " "
putStr (toList l)
putStr " = "
putStrLn (toList r)
)
kbRules