module AI.Tests where import AI.VersionSpaces import AI.Examples import AI.LogicHelpers import Control.Monad (liftM4, liftM2, liftM) import Data.List import Control.Monad.Logic import Test.Framework (defaultMain, testGroup) -- import Test.Framework.Providers.HUnit -- import Test.HUnit import Test.Framework.Providers.QuickCheck (testProperty) import Test.QuickCheck tests = testGroup "LogicHelpers tests" [ testGroup "absMinVal properties" [ testProperty "same sign GT" prop_absMinVal_sameSignGt , testProperty "same sign LT" prop_absMinVal_sameSignLt , testProperty "zero-span" prop_absMinVal_span0 ] , testGroup "fairInts properties" [ testProperty "associate" prop_fairInts_associate , testProperty "unique" prop_fairInts_unique ] ] prop_absMinVal_sameSignGt :: Int -> Int -> Property prop_absMinVal_sameSignGt x y = x > 0 && y > 0 ==> absMinVal x y == min x y prop_absMinVal_sameSignLt :: Int -> Int -> Property prop_absMinVal_sameSignLt x y = x < 0 && y < 0 ==> absMinVal x y == max x y prop_absMinVal_span0 :: Int -> Int -> Property prop_absMinVal_span0 x y = signum x /= signum y ==> absMinVal x y == 0 prop_fairInts_associate :: Int -> Int -> Property prop_fairInts_associate x y = abs (x - y) < 10000 ==> -- stop the tests before they get huge (observeAll $ fairInts x y) == (observeAll $ fairInts y x) prop_fairInts_unique :: Int -> Int -> Property prop_fairInts_unique x y = abs (x - y) < 10000 ==> -- stop the tests before they get huge let ints = (observeAll $ fairInts x y) in nub ints == ints -- | threw an @*** Exception: Ratio.%: zero denominator@ initially. checkSizes = let screen800 = Rect 0 0 800 600 example = (Rect 0 0 80 60) rvs = train rectangleVS screen800 example -- this is not yet demanded, because the condition -- fails too soon: results = runVS rvs screen800 in -- Only 0,0,80x60 is valid, but it can be generated two ways: (length results == 2) && (results!!0 == example) && (results!!1 == example) -- arbitraryBSR :: BSR a i o => Gen a -- arbitraryBSR = oneof [AnyInt, AnyRat] -- instance Arbitrary (VersionSpace i o) where -- arbitrary = sized arbitraryVS -- arbitraryVS :: Int -> Gen (VersionSpace i o) -- arbitraryVS n | n <= 0 = liftM VS arbitraryBSR -- | otherwise = oneof [ liftM2 join (arbitraryVS n/2) (arbitraryVS n/2) -- , liftM2 union (arbitraryVS n/2) (arbitraryVS n/2) -- -- we should reduce the tr size a bit, but halving it may be excessive. -- , liftM4 tr (return id) (return id) (return id) (arbitraryVS n/2) -- ] -- Quickcheck property ideas: -- -- * every hypotheses is consistent with some training input, or no hypotheses exist: -- case hypotheses (train v i o) of -- Empty -> True -- hs -> map (\f -> f i) hs == take (length hs) $ repeat o -- -- * Hypotheses sets shrink monotonically: -- length $ hypotheses v >= length $ hypotheses $ train v i o -- -- * Joining two version spaces results in hypotheses that are the cross product of the inputs. -- (even if some are Empty) -- let l1 = length $ hypotheses v1 -- l2 = length $ hypotheses v2 -- in l1 * l2 == length $ hypotheses $ join v1 v2 -- -- * Unioning two version spaces is additive in the size of the hypotheses. -- let l1 = length $ hypotheses v1 -- l2 = length $ hypotheses v2 -- in l1 + l2 == length $ hypotheses $ union v1 v2 --