blob: 37797e9928a672620004fea1ca9b9aa882de9e93 [file] [log] [blame] [edit]
{-# LANGUAGE FlexibleContexts #-}
--
-- Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
--
-- SPDX-License-Identifier: BSD-2-Clause
--
module CapDL.Matrix(
Matrix
,isConnected
,connect
,newEmptyMatrix
,printMatrix
,printDotMatrix
,showDotMatrix
,getSize
,disconnect
) where
import Data.Array.IO
import Prelude ()
import Prelude.Compat
import Data.Map (Map)
import qualified Data.Map as Map
import Control.Monad
import Data.Char
newtype Matrix = Matrix (IOUArray (Int,Int) Bool)
{- This function takes a matrix and prints a literal table representation
with 0 for False and 1 for True, should be for debugging only -}
printMatrix :: Matrix -> IO()
printMatrix (Matrix m) =
do ((minx, miny), (maxx, maxy)) <- getBounds m
forM_ [minx .. maxx] $ \i ->
forM_ [miny .. maxy] $ \j ->
do elt <- readArray m (i,j)
putStr $ (if elt then "1" else "0")
++ if j == maxy then "\n" else " "
{- This function takes a matrix and a map of labels for
the nodes being represented by the matrix and prints
a .dot file representation of the graph.
This is hacky and only works for the specific 'names' used
in the -}
printDotMatrix :: Matrix -> Map Int (String, Maybe Word) -> IO ()
printDotMatrix (Matrix m) nameMap =
do putStrLn "digraph {"
((min, _), (_, max)) <- getBounds m
forM_ [min .. max] $ \i ->
do let iobjID = Map.findWithDefault (e i) i nameMap
putStrLn $ cf $ fst iobjID
forM_ [i .. max] $ \j ->
do outb <- readArray m (i,j)
inb <- readArray m (j,i)
let iname = fst (iobjID) ++ maybe "" show (snd (iobjID))
jobjID = Map.findWithDefault (e j) j nameMap
jname = fst (jobjID) ++ maybe "" show (snd (jobjID))
case (inb,outb) of
(False, False) -> return ()
(False, True) -> putStrLn $ cf iname ++ " -> " ++ cf jname ++ ";"
(True, False) -> putStrLn $ cf jname ++ " -> " ++ cf iname ++ ";"
(True, True) -> putStrLn $ cf iname ++ " -> " ++ cf jname ++ "[dir=both];"
putStrLn "}"
where
e x = error ("Can't find name for object " ++ show x)
cf = filter (\c -> isDigit c || isAlpha c)
showDotMatrix :: Matrix -> Map Int (String, Maybe Word) -> IO String
showDotMatrix (Matrix m) nameMap =
do
((min, _), (_, max)) <- getBounds m
rows <- forM [min .. max] $ \i ->
do let iobjID = Map.findWithDefault (e i) i nameMap
cells <- forM [i .. max] $ \j ->
do outb <- readArray m (i,j)
inb <- readArray m (j,i)
let iname = fst (iobjID) ++ maybe "" show (snd (iobjID))
jobjID = Map.findWithDefault (e j) j nameMap
jname = fst (jobjID) ++ maybe "" show (snd (jobjID))
return $ case (inb,outb) of
(False, False) -> ""
(False, True) -> cf iname ++ " -> " ++ cf jname ++ ";\n"
(True, False) -> cf jname ++ " -> " ++ cf iname ++ ";\n"
(True, True) -> cf iname ++ " -> " ++ cf jname ++ "[dir=both];\n"
return $ (cf (fst iobjID)) ++ "\n" ++ (concat cells)
return $ "digraph {\n" ++ (concat rows) ++ "}\n"
where
e x = error ("Can't find name for object " ++ show x)
cf = filter (\c -> isDigit c || isAlpha c)
isConnected :: Matrix -> Int -> Int -> IO Bool
isConnected (Matrix m) x y = readArray m (x,y)
{- Sets (x,y) to True -}
connect :: Matrix -> Int -> Int -> IO ()
connect (Matrix m) x y = writeArray m (x,y) True
{- Sets (x,y) to False -}
disconnect :: Matrix -> Int -> Int -> IO ()
disconnect (Matrix m) x y = writeArray m (x,y) False
{- Returns a new empty matrix -}
newEmptyMatrix :: Int -> IO Matrix
newEmptyMatrix n = liftM Matrix $ newArray ((0,0),(n-1,n-1)) False
{- Returns the dimensions of the matrix -}
getSize (Matrix m) = getBounds m