packages feed

creatur-2.0.10: test/ALife/Creatur/Genetics/CodeQC.hs

{-# LANGUAGE UnicodeSyntax #-}

module ALife.Creatur.Genetics.CodeQC
  (
    test
  ) where

import ALife.Creatur.Genetics.Code
import ALife.Creatur.Genetics.CodeInternal
import Data.Eq.Unicode ((≡))
import Data.Ord.Unicode ((≤))
import Data.List (nub)
import Test.Framework as TF (Test, testGroup)
import Test.Framework.Providers.QuickCheck2 (testProperty)
import Test.QuickCheck (Arbitrary, Gen, Property, arbitrary, property, 
  sized, vectorOf)

-- guaranteed not to have multiple values for the same code (but might have
-- multiple codes for the same value)
data TestCode = TestCode (Code Char Bool) deriving Show

sizedArbTestCode ∷ Int → Gen TestCode
sizedArbTestCode n = do
  cs ← vectorOf n arbitrary
  xs ← vectorOf n arbitrary
  return $ TestCode $ Code n $ zip cs (nub xs)

instance Arbitrary TestCode where
  arbitrary = sized sizedArbTestCode

prop_encoding_round_trippable ∷ TestCode → Char → Property
prop_encoding_round_trippable (TestCode g) c =
  property $ maybe Nothing (decode g) (encode g c) ≡ c'
    where c' = if c `elem` cs then Just c else Nothing
          cs = map fst $ cTable g

-- guaranteed not to have multiple values for the same code, or multiple codes
-- for the same value
data TestCode2 = TestCode2 (Code Char Bool) deriving Show

sizedArbTestCode2 ∷ Int → Gen TestCode2
sizedArbTestCode2 n = do
  cs ← vectorOf n arbitrary
  xs ← vectorOf n arbitrary
  return $ TestCode2 $ Code n $ zip (nub cs) (nub xs)

instance Arbitrary TestCode2 where
  arbitrary = sized sizedArbTestCode2

prop_decoding_round_trippable ∷ TestCode2 → [Bool] → Property
prop_decoding_round_trippable (TestCode2 g) x =
  property $ maybe Nothing (encode g) (decode g x) ≡ x'
    where x' = if x `elem` xs then Just x else Nothing
          xs = map snd $ cTable g

data TestParms = TestParms String deriving Show

sizedTestParms ∷ Int → Gen TestParms
sizedTestParms n = do
  let n' = 2 + min 8 n -- keep number of values low to speed up tests
  let values = take n' ['a' .. 'z']
  return $ TestParms values

instance Arbitrary TestParms where
  arbitrary = sized sizedTestParms
  
prop_gray_code_is_efficient ∷ TestParms → Property
prop_gray_code_is_efficient (TestParms values) = 
  property $ 2 ^ (nBits - 1) < nValues && nValues ≤ 2 ^ nBits
    where g = mkGrayCode values
          nValues = length values
          nBits = (length . snd . head . cTable) g

test ∷ Test
test = testGroup "QuickCheck ALife.Creatur.Genetics.CodeQC"
  [
    testProperty "prop_encoding_round_trippable"
      prop_encoding_round_trippable,
    testProperty "prop_decoding_round_trippable"
      prop_decoding_round_trippable,
    testProperty "prop_gray_code_is_efficient"
      prop_gray_code_is_efficient
  ]