content: {-# OPTIONS_GHC -fno-warn-orphans #-}
  module AvgPerceptronTests where
  
  import Control.Applicative ((<$>))
  import Test.QuickCheck ( Arbitrary(..), (==>), Property )
  import Test.QuickCheck.Instances ()
  import Test.Tasty (TestTree, testGroup)
  import Test.Tasty.QuickCheck (testProperty)
  
  import Data.Serialize (encode, decode)
  import Data.Map (Map)
  import qualified Data.Map as Map
  
  import NLP.ML.AvgPerceptron
  
  tests :: TestTree
  tests = testGroup "AvgPerceptron"
          [ testGroup "Encoding tests"
            [ testProperty "Features round-trip" prop_featureRoundtrips
            , testProperty "Perceptrons round-trip" prop_perceptronRoundtrips
            , testProperty "Map of features round-trip" prop_mapOfFeaturesRoundTrips
            ]
            , testProperty "Averaging reaches fixed point" prop_avgWeightsFixedpoint
          ]
  
  prop_avgWeightsFixedpoint :: Perceptron -> Property
  prop_avgWeightsFixedpoint per = instances per > 1 && Map.size (weights per) > 1 ==>
    (averageWeights per) == ((averageWeights . averageWeights) per)
  
  prop_mapOfFeaturesRoundTrips :: Map Feature Class -> Bool
  prop_mapOfFeaturesRoundTrips aMap =
    case (decode . encode) aMap of
      Left  _ -> False
      Right m -> m == aMap
  
  prop_featureRoundtrips :: Feature -> Bool
  prop_featureRoundtrips feat =
    case (decode . encode) feat of
      Left  _ -> False
      Right f -> f == feat
  
  prop_perceptronRoundtrips :: Perceptron -> Bool
  prop_perceptronRoundtrips per =
    case (decode . encode) per of
      Left  _ -> False
      Right p -> p == per
  
  instance Arbitrary Feature where
    arbitrary = Feat <$> arbitrary
  
  instance Arbitrary Class where
    arbitrary = Class <$> arbitrary
  
  instance Arbitrary Perceptron where
    arbitrary = do ws <- arbitrary
                   ts <- arbitrary
                   times <- arbitrary
                   counts <- arbitrary
                   return Perceptron { weights = ws
                                     , totals = ts
                                     , tstamps = times
                                     , instances = counts
                                     }
  