packages feed

clustering-0.4.0: tests/Test/KMeans.hs

{-# LANGUAGE QuasiQuotes     #-}
{-# LANGUAGE TemplateHaskell #-}

module Test.KMeans
    ( tests
    ) where

import           Control.Monad
import           Data.Int                      (Int32)
import           Data.List
import qualified Data.Matrix.Unboxed           as MU
import           Data.Maybe
import qualified Data.Vector.SEXP              as S
import qualified Data.Vector.Unboxed           as V
import qualified Foreign.R                     as R
import qualified Foreign.R.Type                as R
import qualified H.Prelude                     as H
import           Language.R.HExp
import           Language.R.QQ
import           System.Random.MWC
import           Test.Tasty
import           Test.Tasty.HUnit
import           Test.Tasty.QuickCheck

import           AI.Clustering.KMeans
import           AI.Clustering.KMeans.Internal

import           Test.Utils

tests :: TestTree
tests = testGroup "KMeans:"
    [ testCase "KMeans" testKMeans
    ]

rKmeans :: Int -> [Double] -> [Double] -> IO [Int]
rKmeans n' dat center = fmap (map (fromIntegral :: Int32 -> Int)) $ H.runRegion $ do
    xxx <- [r| x <- matrix(dat_hs, ncol=n_hs,byrow=T);
             y <- matrix(center_hs, ncol=n_hs,byrow=T);
             kmeans(x,y,iter.max=10000,algorithm="Lloyd")$cluster
    |]
    return $ H.fromSEXP $ H.cast R.SInt xxx
  where
    n = fromIntegral n' :: Double

testKMeans :: Assertion
testKMeans = do
    let n = 2000
        d = 15
        k = 10
    g <- createSystemRandom
    xs <- randVectors n d

    let mat = MU.fromRows xs :: MU.Matrix Double
        dat = V.enumFromN 0 $ MU.rows mat
        fn = MU.takeRow mat

    init_centers <- kmeansPP g k dat fn

    result_r <- rKmeans d (MU.toList mat) (MU.toList init_centers)

    let result = sort $ map sort $ fromJust $ clusters $ kmeans k mat defaultKMeansOpts{kmeansMethod=Centers init_centers}
        true = sort $ map sort $ decode (V.fromList $ map (subtract 1) result_r) xs

    assertBool ("Expect: " ++ show (map length true) ++ "\nBut saw: " ++ show (map length result)) $
        result == true