{- | IO for graph files, graph6, sparse6 and digraph6 encodings.
-}
module Music.Theory.Graph.IO where
import Data.List.Split {- split -}
import System.Process {- process -}
import qualified Music.Theory.Graph.Type as T {- hmt -}
import qualified Music.Theory.List as T {- hmt -}
-- * G6 (graph6)
-- | Load Graph6 file, discard optional header if present.
g6_load :: FilePath -> IO [String]
g6_load fn = do
s <- readFile fn
let s' = if take 6 s == ">>graph6<<" then drop 6 s else s
return (lines s')
-- | Load G6 file variant where each line is "Description\tG6"
g6_dsc_load :: FilePath -> IO [(String,String)]
g6_dsc_load fn = do
s <- readFile fn
let r = map (T.split_on_1_err "\t") (lines s)
return r
-- | Call nauty-listg to transform a sequence of G6.
-- debian = nauty
g6_to_edg :: [String] -> IO [T.EDG]
g6_to_edg g6 = do
r <- readProcess "nauty-listg" ["-q","-l0","-e"] (unlines g6)
return (map T.edg_parse (chunksOf 2 (lines r)))
-- | 'T.edg_to_g' of 'g6_to_edg'
g6_to_gr :: [String] -> IO [T.G]
g6_to_gr = fmap (map T.edg_to_g) . g6_to_edg
-- | 'g6_to_edg' of 'g6_dsc_load'.
g6_dsc_load_edg :: FilePath -> IO [(String,T.EDG)]
g6_dsc_load_edg fn = do
dat <- g6_dsc_load fn
let (dsc,g6) = unzip dat
gr <- g6_to_edg g6
return (zip dsc gr)
-- | 'T.edg_to_g' of 'g6_dsc_load_edg'
g6_dsc_load_gr :: FilePath -> IO [(String,T.G)]
g6_dsc_load_gr = fmap (map (\(dsc,e) -> (dsc,T.edg_to_g e))) . g6_dsc_load_edg
{- | Generate the text format read by nauty-amtog.
> e = ((4,3),[(0,3),(1,3),(2,3)])
> m = T.edg_to_adj_mtx_undir e
> putStrLn (adj_mtx_to_am m)
-}
adj_mtx_to_am :: T.ADJ_MTX -> String
adj_mtx_to_am (nv,mtx) =
unlines ["n=" ++ show nv
,"m"
,unlines (map (unwords . map show) mtx)]
-- | Call nauty-amtog to transform a sequence of ADJ_MTX to G6.
--
-- > adj_mtx_to_g6 [m,m]
adj_mtx_to_g6 :: [T.ADJ_MTX] -> IO [String]
adj_mtx_to_g6 adj = do
r <- readProcess "nauty-amtog" ["-q"] (unlines (map adj_mtx_to_am adj))
return (lines r)