check the number of lines

This commit is contained in:
Filip Gralinski 2015-11-06 21:57:36 +01:00 committed by Filip Gralinski
parent 9e96f5dfe4
commit 17d39c4293
11 changed files with 53 additions and 7 deletions

View File

@ -1,5 +1,5 @@
name: geval name: geval
version: 0.1.2.1 version: 0.2.0.0
synopsis: Machine learning evaluation tools synopsis: Machine learning evaluation tools
description: Please see README.md description: Please see README.md
homepage: http://github.com/name/project homepage: http://github.com/name/project

View File

@ -77,6 +77,9 @@ data GEvalException = NoExpectedFile FilePath
| NoExpectedTestDirectory FilePath | NoExpectedTestDirectory FilePath
| NoOutTestDirectory FilePath | NoOutTestDirectory FilePath
| FileAlreadyThere FilePath | FileAlreadyThere FilePath
| TooFewLines
| TooManyLines
deriving (Eq)
instance Exception GEvalException instance Exception GEvalException
@ -88,6 +91,8 @@ instance Show GEvalException where
show (NoExpectedTestDirectory filePath) = somethingWrongWithFilesMessage "No test subdirectory with the expected results" filePath show (NoExpectedTestDirectory filePath) = somethingWrongWithFilesMessage "No test subdirectory with the expected results" filePath
show (NoOutTestDirectory filePath) = somethingWrongWithFilesMessage "No test subdirectory with the results obtained" filePath show (NoOutTestDirectory filePath) = somethingWrongWithFilesMessage "No test subdirectory with the results obtained" filePath
show (FileAlreadyThere filePath) = somethingWrongWithFilesMessage "File already there" filePath show (FileAlreadyThere filePath) = somethingWrongWithFilesMessage "File already there" filePath
show TooFewLines = "Too few lines in the output file"
show TooManyLines = "Too many lines in the output file"
somethingWrongWithFilesMessage :: String -> FilePath -> String somethingWrongWithFilesMessage :: String -> FilePath -> String
somethingWrongWithFilesMessage msg filePath = Prelude.concat somethingWrongWithFilesMessage msg filePath = Prelude.concat
@ -148,28 +153,38 @@ gevalCore' Accuracy = gevalCore'' strip strip hitOrMiss averageC id
x /. 0 = 1.0 x /. 0 = 1.0
x /. y = (fromIntegral x) / (fromIntegral y) x /. y = (fromIntegral x) / (fromIntegral y)
data SourceItem a = Got a | Done
gevalCore'' :: (Text -> a) -> (Text -> b) -> ((a, b) -> c) -> (Sink c (ResourceT IO) d) -> (d -> Double ) -> String -> String -> IO (MetricValue) gevalCore'' :: (Text -> a) -> (Text -> b) -> ((a, b) -> c) -> (Sink c (ResourceT IO) d) -> (d -> Double ) -> String -> String -> IO (MetricValue)
gevalCore'' expParser outParser itemStep aggregator finalStep expectedFilePath outFilePath = do gevalCore'' expParser outParser itemStep aggregator finalStep expectedFilePath outFilePath = do
v <- runResourceT $ v <- runResourceT $
(getZipSource $ (,) (getZipSource $ (,)
<$> ZipSource (items expectedFilePath expParser) <$> ZipSource (items expectedFilePath expParser)
<*> ZipSource (items outFilePath outParser)) <*> ZipSource (items outFilePath outParser))
$$ (CL.map itemStep $$ (CL.map (checkStep itemStep)
=$= CL.catMaybes
=$ aggregator) =$ aggregator)
return $ finalStep v return $ finalStep v
checkStep :: ((a, b) -> c) -> (SourceItem a, SourceItem b) -> Maybe c
checkStep step (Got expectedItem, Got outItem) = Just $ step (expectedItem, outItem)
checkStep _ (Got _, Done) = throw TooFewLines
checkStep _ (Done, Got _) = throw TooManyLines
checkStep _ (Done, Done) = Nothing
averageC :: MonadResource m => Sink Double m Double averageC :: MonadResource m => Sink Double m Double
averageC = getZipSink averageC = getZipSink
$ (\total count -> total / fromIntegral count) $ (\total count -> total / fromIntegral count)
<$> ZipSink CC.sum <$> ZipSink CC.sum
<*> ZipSink CC.length <*> ZipSink CC.length
items :: MonadResource m => String -> (Text -> a) -> Source m a items :: MonadResource m => String -> (Text -> a) -> Source m (SourceItem a)
items filePath parser = items filePath parser =
CB.sourceFile filePath (CB.sourceFile filePath
$= (CT.decode CT.utf8 $= (CT.decode CT.utf8
=$= CT.lines =$= CT.lines
=$= CL.map parser) =$= CL.map ((\x -> Got x) . parser))) >> yield Done
itemError :: (Double, Double) -> Double itemError :: (Double, Double) -> Double
itemError (exp, out) = (exp-out)**2 itemError (exp, out) = (exp-out)**2

View File

@ -48,10 +48,22 @@ main = hspec $ do
precisionCount [["bar", "bar", "bar", "bar", "foo", "xyz", "foo"]] ["foo", "bar", "foo", "baz", "bar", "foo"] `shouldBe` 4 precisionCount [["bar", "bar", "bar", "bar", "foo", "xyz", "foo"]] ["foo", "bar", "foo", "baz", "bar", "foo"] `shouldBe` 4
it "multiple refs" $ do it "multiple refs" $ do
precisionCount [["foo", "baz"], ["bar"], ["baz", "xyz"]] ["foo", "bar", "foo"] `shouldBe` 2 precisionCount [["foo", "baz"], ["bar"], ["baz", "xyz"]] ["foo", "bar", "foo"] `shouldBe` 2
describe "error handling" $ do
it "too few lines are handled" $ do
runGEvalTest "error-too-few-lines" `shouldThrow` (== TooFewLines)
it "too many lines are handled" $ do
runGEvalTest "error-too-many-lines" `shouldThrow` (== TooManyLines)
extractVal :: (Either (ParserResult GEvalOptions) (Maybe MetricValue)) -> IO MetricValue extractVal :: (Either (ParserResult GEvalOptions) (Maybe MetricValue)) -> IO MetricValue
extractVal (Right (Just val)) = return val extractVal (Right (Just val)) = return val
runGEvalTest testName = (runGEval [
"--expected-directory",
"test/" ++ testName ++ "/" ++ testName,
"--out-directory",
"test/" ++ testName ++ "/" ++ testName ++ "-solution"]) >>= extractVal
class AEq a where class AEq a where
(=~) :: a -> a -> Bool (=~) :: a -> a -> Bool

View File

@ -0,0 +1 @@
1.0
1 1.0

View File

@ -0,0 +1 @@
--metric MSE

View File

@ -0,0 +1,3 @@
3.0
10.0
2.8
1 3.0
2 10.0
3 2.8

View File

@ -0,0 +1,3 @@
A b
B c
A c
1 A b
2 B c
3 A c

View File

@ -0,0 +1,4 @@
1.0
4.0
3.2
-1.0
1 1.0
2 4.0
3 3.2
4 -1.0

View File

@ -0,0 +1 @@
--metric MSE

View File

@ -0,0 +1,3 @@
3.0
10.0
2.8
1 3.0
2 10.0
3 2.8

View File

@ -0,0 +1,3 @@
A b
B c
A c
1 A b
2 B c
3 A c