mirror of
https://github.com/Jaxan/monoid-learner.git
synced 2025-04-27 06:57:44 +02:00
144 lines
No EOL
3.9 KiB
Haskell
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 |