packages feed

easytensor-2.1.0.0: test/Numeric/DataFrame/BasicTest.hs

-----------------------------------------------------------------------------
-- |
-- Module      :  Numeric.DataFrame.BasicTest
-- Copyright   :  (c) Artem Chirkin
-- License     :  BSD3
--
-- Maintainer  :  chirkin@arch.ethz.ch
--
-- A set of basic validity tests for DataFrame type.
-- Num, Ord, Fractional, Floating, etc
--
-----------------------------------------------------------------------------
{-# LANGUAGE ConstraintKinds      #-}
{-# LANGUAGE DataKinds            #-}
{-# LANGUAGE FlexibleContexts     #-}
{-# LANGUAGE GADTs                #-}
{-# LANGUAGE KindSignatures       #-}
{-# LANGUAGE RankNTypes           #-}
{-# LANGUAGE ScopedTypeVariables  #-}
{-# LANGUAGE TemplateHaskell      #-}
{-# LANGUAGE TypeApplications     #-}
{-# LANGUAGE TypeOperators        #-}
{-# LANGUAGE UndecidableInstances #-}

module Numeric.DataFrame.BasicTest (runTests) where

import           Numeric.Arbitraries              ()
import           Numeric.DataFrame
import qualified Numeric.ProductOrd.NonTransitive as NonTransitive
import qualified Numeric.ProductOrd.Partial       as Partial
import           Test.QuickCheck

{-# ANN module "HLint: ignore Use <" #-}
{-# ANN module "HLint: ignore Use >" #-}
{-# ANN module "HLint: ignore Use >=" #-}
{-# ANN module "HLint: ignore Use <=" #-}
{-# ANN module "HLint: ignore Redundant compare" #-}

(===>) :: Bool -> Bool -> Bool
a ===> b = not a || b
infix 2 ===>

prop_vanillaOrdTransitivity :: SomeDataFrame '[Double, Double, Double] -> Property
prop_vanillaOrdTransitivity (SomeDataFrame (x :*: y :*: z :*: Z))
  = property $ (x <= y) && (y <= z) ===> x <= z

vanillaOrdComparisons :: Ord t => t -> t -> Property
vanillaOrdComparisons x y
  = conjoin
    [ counterexample "(x < y) == (compare x y == LT)"
          $ (x < y) == (compare x y == LT)
    , counterexample "(x > y) == (compare x y == GT)"
          $ (x > y) == (compare x y == GT)
    , counterexample "(x == y) == (compare x y == EQ)"
          $ (x == y) == (compare x y == EQ)
    , counterexample "min x y == if x <= y then x else y"
          $ min x y == if x <= y then x else y
    , counterexample "max x y == if x >= y then x else y"
          $ max x y == if x >= y then x else y
    ]


comparisons :: (Ord t, Num t) => t -> t -> Property
comparisons x y
  = conjoin
    [ counterexample "abs x <= abs x + abs y" $ abs x <= abs x + abs y
    , counterexample "x <= x" $ x <= x
    , counterexample "y <= y" $ y <= y
    , counterexample "x >= x" $ x >= x
    , counterexample "y >= y" $ y >= y
    , counterexample "x == x" $ x == x
    , counterexample "y == y" $ y == y
    , counterexample "(x > y) == (y < x)"
                              $ (x > y) == (y < x)
    , counterexample "(x >= y) == (y <= x)"
                              $ (x >= y) == (y <= x)
    , counterexample "(x < y) == (x <= y && x /= y)"
                              $ (x < y) == (x <= y && x /= y)
    , counterexample "(x > y) == (x >= y && x /= y)"
                              $ (x > y) == (x >= y && x /= y)
    , counterexample "x < x + 1" $ abs x < 10000000 ===> x < x + 1
    , counterexample "x > x - 1" $ abs x < 10000000 ===> x > x - 1
    , counterexample "abs x >= x" $ abs x >= x
    , counterexample "abs (-x) >= (-x)" $ abs (-x) >= (-x)
    , counterexample "x > y ==> x >= y"
      $ x > y            ===> x >= y
    , counterexample "x < y ==> x <= y"
      $ x < y            ===> x <= y
    , counterexample "not (x >= y) ==> not (x > y)"
      $ not (x >= y)     ===> not (x > y)
    , counterexample "not (x <= y) ==> not (x < y)"
      $ not (x <= y)     ===> not (x < y)
    , counterexample "x == y ==> not GT or LT, but GE and LE"
      $ x == y           ===> and [ not (x > y), not (y < x), x >= y, y <= x ]
    , counterexample "x >= y && x <= y ==> x == y"
      $ x >= y && x <= y ===> x == y
    ]

prop_comparisonsVanillaOrdFloat :: SomeDataFrame '[Float, Float] -> Property
prop_comparisonsVanillaOrdFloat (SomeDataFrame (x :*: y :*: Z)) =
  comparisons x y .&&. vanillaOrdComparisons x y
prop_comparisonsVanillaOrdDouble :: SomeDataFrame '[Double, Double] -> Property
prop_comparisonsVanillaOrdDouble (SomeDataFrame (x :*: y :*: Z)) =
  comparisons x y .&&. vanillaOrdComparisons x y
prop_comparisonsVanillaOrdInt :: SomeDataFrame '[Int, Int] -> Property
prop_comparisonsVanillaOrdInt (SomeDataFrame (x :*: y :*: Z)) =
  comparisons x y .&&. vanillaOrdComparisons x y


prop_comparisonsPPOrdFloat :: SomeDataFrame '[Float, Float] -> Property
prop_comparisonsPPOrdFloat (SomeDataFrame (x :*: y :*: Z))
  = comparisons (Partial.ProductOrd x) (Partial.ProductOrd y)
prop_comparisonsPPOrdDouble :: SomeDataFrame '[Double, Double] -> Property
prop_comparisonsPPOrdDouble (SomeDataFrame (x :*: y :*: Z))
  = comparisons (Partial.ProductOrd x) (Partial.ProductOrd y)
prop_comparisonsPPOrdInt :: SomeDataFrame '[Int, Int] -> Property
prop_comparisonsPPOrdInt (SomeDataFrame (x :*: y :*: Z))
  = comparisons (Partial.ProductOrd x) (Partial.ProductOrd y)


prop_comparisonsNTPOrdFloat :: SomeDataFrame '[Float, Float] -> Property
prop_comparisonsNTPOrdFloat (SomeDataFrame (x :*: y :*: Z))
  = comparisons (NonTransitive.ProductOrd x) (NonTransitive.ProductOrd y)
prop_comparisonsNTPOrdDouble :: SomeDataFrame '[Double, Double] -> Property
prop_comparisonsNTPOrdDouble (SomeDataFrame (x :*: y :*: Z))
  = comparisons (NonTransitive.ProductOrd x) (NonTransitive.ProductOrd y)
prop_comparisonsNTPOrdInt :: SomeDataFrame '[Int, Int] -> Property
prop_comparisonsNTPOrdInt (SomeDataFrame (x :*: y :*: Z))
  = comparisons (NonTransitive.ProductOrd x) (NonTransitive.ProductOrd y)


prop_Numeric :: SomeDataFrame '[Int, Int] -> Bool
prop_Numeric (SomeDataFrame (x :*: y :*: Z))
  = and
    [ x + x == 2 * x
    , x + y == y + x
    , x + y == max x y + min x y
    , abs x * signum x == x
    , x * y == y * x
    , x * 0 + y == y
    ]


prop_Floating :: SomeDataFrame '[Double, Double] -> Bool
prop_Floating (SomeDataFrame (x :*: y :*: Z))
  | lx <- log (0.01 + abs x)
  , ly <- log (0.01 + abs y)
  , eps <- 0.001
  = all ((eps >=) . abs)
    [ sin x * sin x + cos x * cos x - 1
    , exp lx * exp ly  / exp (lx + ly) - 1
    , exp (log $ 1 + abs x) / (1 + abs x) - 1
    , sin (asin (sin y)) - sin y
    , cos (acos (cos x)) - cos x
    ]


return []
runTests :: Int -> IO Bool
runTests n = $forAllProperties
  $ quickCheckWithResult stdArgs { maxSuccess = n }