Rename Instance -> PMInstance and introduce PMatching type.
[match/match.git] / program / TestUtils.hs
CommitLineData
fd0d2377
MM
1module TestUtils where
2import Control.Concurrent
3import Data.Array.IArray
4import Data.Graph.Inductive.Graph
5import Data.Graph.Inductive.Graphviz
6import Data.Graph.Inductive.Tree
7import System.IO
8import System.Random
9import System.Posix.IO
10import System.Posix.Time
11import System.Process
05a6f0ed 12import PMInstance
fd0d2377
MM
13import ProposalMatcher
14import MonadStuff
15
16-- This module has stuff that is helpful for testing but isn't itself an example.
17
18-- A fixed-seeded random number generator for reproducible experimentation.
19myGen = read "314159265 1" :: StdGen
20
21-- Visualization stuff.
22data REdgeF = REdgeF Int Int Int Wt
23instance Show REdgeF where
24 show (REdgeF idx cap flow cost) = "#" ++ (show idx) ++ ": "
25 ++ (show flow) ++ " of " ++ (show cap) ++ " @ " ++ (show cost)
26flowAnnotate g fa =
27 mkGraph (labNodes g) (map (\(n1, n2, REdge i ca co) ->
28 (n1, n2, REdgeF i ca (fa ! i) co)) $ labEdges g) :: Gr () REdgeF
29
05a6f0ed
MM
30showInstanceAsGraph :: PMInstance -> PMatching -> Gr String String
31showInstanceAsGraph (PMInstance numRvrs numProps rloadA prefA) matchedPairs =
fd0d2377
MM
32 let
33 rvrNode i = i
34 propNode j = numRvrs + j
35 numNodes = numRvrs + numProps
36 theNodes = map (\i -> (rvrNode i, "R#" ++ show i ++
37 " (RLoad " ++ show (rloadA ! i) ++ ")")) [0..numRvrs-1] ++
38 map (\j -> (propNode j, "P#" ++ show j)) [0..numProps-1]
39 parenthesizeIf False s = s
40 parenthesizeIf True s = "(" ++ s ++ ")"
41 theEdges = do
42 i <- [0..numRvrs-1]
43 j <- [0..numProps-1]
44 return (rvrNode i, propNode j,
45 parenthesizeIf (elem (i, j) matchedPairs) $ show (prefA ! (i, j)))
46 in mkGraph theNodes theEdges
47
48goFile :: String -> IO ()
49goFile fname = do
50 pid <- runCommand ("gnome-open " ++ fname)
51 waitForProcess pid -- gnome-open exits immediately
52 nop
53
54createHandlePipe :: IO (Handle, Handle)
55createHandlePipe = do
56 (rFd, wFd) <- createPipe
57 rH <- fdToHandle rFd
58 wH <- fdToHandle wFd
59 return (rH, wH)
60
61-- GHCi seems to crash if I call this on a "showInstanceAsGraph" result without
62-- having previously forced evaluation of the matching.
63goGraph :: (Show a, Show b, Graph gr) => gr a b -> IO ()
64goGraph theGraph =
65 -- First generate graphviz code.
66 let gvCode = graphviz' theGraph in do
67 -- Then have `dot' convert it to postscript in a file.
68 (rH, wH) <- createHandlePipe
69 pt <- epochTime
70 let fname = "graph-" ++ show pt ++ ".ps"
71 dotPid <- runProcess "dot" ["-Tps", "-o", fname]
72 Nothing Nothing (Just rH) Nothing Nothing
73 forkIO (do
74 hPutStr wH gvCode
75 hClose wH)
76 waitForProcess dotPid
77 -- Then open the file.
78 goFile fname