Skip to content
This repository has been archived by the owner on Jan 9, 2024. It is now read-only.

Commit

Permalink
feat(test-lib): use CSVData for Measured
Browse files Browse the repository at this point in the history
  • Loading branch information
marmitar committed Jan 5, 2024
1 parent 2cf05f3 commit a663d07
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 157 deletions.
8 changes: 5 additions & 3 deletions app/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ module Main (main) where
import Prelude hiding (String)

import Control.Monad (forM_, replicateM_)
import Data.Data (Proxy (..))
import Data.Word (Word8)
import System.IO (hFlush, stdout)

import MCSP.Data.String (String)
import MCSP.System.Random (Random, generate, uniformR)
import MCSP.TestLib.Heuristics (csvHeader, heuristics, measure, toCsvRow)
import MCSP.TestLib.Heuristics (Measured, heuristics, measure)
import MCSP.TestLib.Sample (ShuffleMethod (..), SimpleEnum, StringParameters (..), randomPairWith)
import MCSP.Text.CSV (headers, row)

randomPair :: SimpleEnum a => Random (String a, String a)
randomPair = do
Expand All @@ -26,11 +28,11 @@ randomPair = do

main :: IO ()
main = do
putLn csvHeader
putLn $ headers (Proxy @Measured)
replicateM_ 10_000 $ do
pair <- generate randomPair
forM_ heuristics $ \heuristc -> do
result <- measure @Word8 heuristc pair
putLn $ toCsvRow result
putLn $ row result
where
putLn line = putStrLn line >> hFlush stdout
19 changes: 6 additions & 13 deletions bench/blocks/Bench.hs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ module Main (main) where
import Prelude

import Control.Monad (forM_)
import Data.Data (Proxy (..))
import Data.Time.Clock.System (SystemTime (..), getSystemTime)
import Data.Vector qualified as V (Vector)
import Data.Vector.Generic qualified as G
Expand All @@ -21,18 +22,9 @@ import MCSP.Data.Pair (both, ($:))
import MCSP.System.Path (createDirectory, getCurrentTimestamp, packageRoot, (<.>), (</>))
import MCSP.System.Random (generate)
import MCSP.System.Statistics (absolute, cl99, confidenceInterval, sampleCI)
import MCSP.TestLib.Heuristics (
Debug,
Measured,
NamedHeuristic,
blocks,
csvHeader,
heuristics,
measure,
score,
toCsvRow,
)
import MCSP.TestLib.Heuristics (Debug, Measured, NamedHeuristic, blocks, heuristics, measure, score)
import MCSP.TestLib.Sample (SimpleEnum, StringParameters, benchParams, randomPairWith, repr)
import MCSP.Text.CSV (headers, row)

-- ---------------- --
-- Benchmark Limits --
Expand Down Expand Up @@ -197,13 +189,14 @@ measuring params heuristic = generate (randomPairWith params) >>= measure heuris

-- | Writes the measured information in CSV format and returns it unchanged.
writeCsv :: PutStrLn -> Measured -> IO Measured
writeCsv writeLn result = writeLn (toCsvRow result) >> pure result
writeCsv writeLn result = writeLn (row result) >> pure result

-- | Run a matrix of benchmarks for each parameter set and heuristic, writing output and results to
-- the with the input writers.
report :: PutStrLn -> PutStrLn -> IO ()
report printLn putRow = putRow csvHeader >> forM_ benchParams (forM_ heuristics . run)
report printLn putRow = putRow csvHeaders >> forM_ benchParams (forM_ heuristics . run)
where
csvHeaders = headers (Proxy @Measured)
run params heuristic = do
printLn $ "benchmarking " ++ repr params ++ "/" ++ fst heuristic
-- run benchmark and analyse results
Expand Down
1 change: 0 additions & 1 deletion package.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ internal-libraries:
- MCSP.System.TimeIt
- MCSP.TestLib.Heuristics
- MCSP.TestLib.Heuristics.Safe
- MCSP.TestLib.Heuristics.TH
- MCSP.TestLib.Random
- MCSP.TestLib.Sample
- MCSP.Text.CSV
Expand Down
92 changes: 39 additions & 53 deletions test/lib/MCSP/TestLib/Heuristics.hs
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
-- | Tools for testing heuristics.
module MCSP.TestLib.Heuristics (
-- * Standard Heuristics
Debug,
Heuristic,
NamedHeuristic,
heuristics,

-- * Measuring Heuristic input and output
Measured (..),
measure,
csvHeader,
toCsvRow,
) where

import Prelude hiding (String, lookup)

import Control.DeepSeq (NFData (..))
import Data.List (intercalate)
import Data.Maybe (fromMaybe)
import Data.String qualified as Text
import Data.Vector.Generic qualified as Vector (length)
Expand All @@ -23,14 +23,15 @@ import Safe.Foldable (maximumBound)

import MCSP.Data.MatchingGraph (edgeSet)
import MCSP.Data.Meta (lookup, (<::))
import MCSP.Data.Pair (Pair, both, second)
import MCSP.Data.Pair (Pair, both)
import MCSP.Data.String (String)
import MCSP.Data.String.Extra (occurrences, repeated, singletons)
import MCSP.Heuristics (Heuristic, UseSingletons (..), combine, greedy, pso)
import MCSP.Heuristics.PSOBased (PSOCombine (..), PSOPure (..), getFirstBestIter)
import MCSP.System.TimeIt (timeIt)
import MCSP.TestLib.Heuristics.Safe (Debug, checkedDiv, checkedLen, runChecked)
import MCSP.TestLib.Heuristics.TH (mkNamed)
import MCSP.Text.CSV (CSVData (..), mkColumn, readColumn, readColumnWith, strColumn)
import MCSP.Text.ReadP (eof, readP, (<++))

-- | The heuristic with its defined name.
type NamedHeuristic a = (Text.String, Heuristic a)
Expand Down Expand Up @@ -129,51 +130,36 @@ measure (name, heuristic) pair = do
pair = show pair
}

-- | A list of pairs @(columnName, showColumn)@ used to construct the CSV for `Measured`.
--
-- >>> map fst csvColumns
-- ["size","repeats","singles","heuristic","blocks","score","time","left","right"]
csvColumns :: [(Text.String, Measured -> Text.String)]
csvColumns =
[ second (showColumn 3 show) $(mkNamed 'size),
second (showColumn 2 show) $(mkNamed 'repeats),
second (showColumn 2 show) $(mkNamed 'singles),
second (showColumn 3 show) $(mkNamed 'maxRepeat),
second (showColumn 3 show) $(mkNamed 'edges),
second (showColumn 3 (maybe "" show)) $(mkNamed 'psoIter),
second (showColumn 8 id) $(mkNamed 'heuristic),
second (showColumn 3 show) $(mkNamed 'blocks),
second (showColumn 4 (showDP 2)) $(mkNamed 'score),
second (showColumn 8 (showDP 3)) $(mkNamed 'time),
second (showColumn 0 show) $(mkNamed 'left),
second (showColumn 0 show) $(mkNamed 'right),
second (showColumn 0 show) $(mkNamed 'pair)
]

-- Compose a function that show a value with one that extracts that value from a measurement.
--
-- Also has a parameter for padding the resulting text if it is too short.
--
-- >>> showColumn 10 show id 12
-- " 12"
showColumn :: Int -> (b -> Text.String) -> (a -> b) -> (a -> Text.String)
showColumn minWidth showIt = ((padLeft . showIt) .)
where
padLeft str = replicate (minWidth - length str) ' ' ++ str

-- | The CSV header for the columns of `Measured`.
--
-- >>> csvHeader
-- "size,repeats,singles,heuristic,blocks,score,time,left,right"
csvHeader :: Text.String
csvHeader = intercalate "," (map fst csvColumns)

-- | The CSV row representing the values of a `Measured`.
--
-- >>> result <- measure $(mkNamed 'combine) ("abcd", "cdab")
-- >>> toCsvRow result
-- " 4, 0, 4, combine, 2,0.67, 0.000,\"[ab,cd]\",\"[cd,ab]\""
toCsvRow :: Measured -> Text.String
toCsvRow measured = intercalate "," (map getValue csvColumns)
where
getValue (_, showIt) = showIt measured
instance CSVData Measured where
writer =
$$(mkColumn [||size||] 3 [||show||])
<> $$(mkColumn [||repeats||] 2 [||show||])
<> $$(mkColumn [||singles||] 2 [||show||])
<> $$(mkColumn [||maxRepeat||] 3 [||show||])
<> $$(mkColumn [||edges||] 3 [||show||])
<> $$(mkColumn [||psoIter||] 3 [||maybe "" show||])
<> $$(mkColumn [||heuristic||] 8 [||id||])
<> $$(mkColumn [||blocks||] 3 [||show||])
<> $$(mkColumn [||score||] 4 [||showDP 2||])
<> $$(mkColumn [||time||] 8 [||showDP 3||])
<> $$(mkColumn [||left||] 0 [||id||])
<> $$(mkColumn [||right||] 0 [||id||])
<> $$(mkColumn [||pair||] 0 [||id||])
parser = do
heuristic <- strColumn "heuristic"
blocks <- readColumn "blocks"
size <- readColumn "size"
score <- readColumn "score"
time <- readColumn "time"
singles <- readColumn "singles"
repeats <- readColumn "repeats"
maxRepeat <- readColumn "maxRepeat"
edges <- readColumn "edges"
psoIter <- readColumnWith "psoIter" (readNothing <++ readJust)
left <- strColumn "left"
right <- strColumn "right"
pair <- strColumn "pair"
pure Measured {..}
where
readNothing = eof >> pure Nothing
readJust = Just <$> readP
87 changes: 0 additions & 87 deletions test/lib/MCSP/TestLib/Heuristics/TH.hs

This file was deleted.

0 comments on commit a663d07

Please sign in to comment.