module Tests.Matrix where import Test.Framework (defaultMain, testGroup) import Test.Framework.Providers.QuickCheck2 (testProperty) import Test.QuickCheck import Control.Monad (liftM) import Data.Function (on) import Data.Foldable as F import Data.List as L import Data.IntMap as M hiding ((!)) import Math.LinearAlgebra.Sparse.Matrix import Math.LinearAlgebra.Sparse.Vector import Tests.Generators testgr_matrix = testGroup "MATRIX TESTS" [ testgr_lookup_update , testgr_to_from_list , testgr_trans , testgr_muls ] -------------------------------------------------------------------------------- -- LOOKUP/UPDATE -- ------------------- testgr_lookup_update = testGroup "LOOKUP/UPDATE" [ testProperty "Insert/Erase" prop_ins ] -- Test for `ins`, `(#)` and `erase` prop_ins = forAll (genPair (genSize (0,300)) (genSize (1,400))) $ \(h,w) -> forAll (genSparseMatrix (h,w)) $ \m -> forAll (genPair (genIndex (1,h)) (genIndex (1,w))) $ \(i,j) -> forAll (arbitrary :: Gen Int) $ \x -> -- collect (h,w) $ let m' = m `ins` ((i,j),x) in m' # (i,j) == x && (m' `erase` (i,j)) # (i,j) == 0 -------------------------------------------------------------------------------- -- TO/FROM LIST -- ------------------ testgr_to_from_list = testGroup "TO/FROM LIST" [ testProperty "fillMx . sparseMx == id" prop_fill_sparse_mx , testProperty "sparseMx . fillMx == id" prop_sparse_fill_mx , testProperty "toAssocList . fromAssocList == id" prop_to_from_AssocList , testProperty "fromAssocList . toAssocList == id" prop_from_to_AssocList ] prop_sparse_fill_mx = forAll (genPair (genSize (1,100)) (genSize (1,150))) $ \(h,w) -> forAll (genSparseMatrix (h,w) :: Gen (SparseMatrix Integer)) $ \m -> sparseMx (fillMx m) == m prop_fill_sparse_mx = forAll (genPair (genSize (1,100)) (genSize (1,150))) $ \(h,w) -> forAll (vectorOf h (genSparseList w) :: Gen [[Integer]]) $ \m -> fillMx (sparseMx m) == m prop_to_from_AssocList = forAll (genPair (genSize (1,50)) (genSize (1,60))) $ \(h,w) -> forAll (choose (0,h*w)) $ \n -> forAll (genAssocList n (h,w) :: Gen [((Index,Index),Integer)]) $ \l -> sort (toAssocList (fromAssocList l)) == sort l prop_from_to_AssocList = forAll (genPair (genSize (1,100)) (genSize (1,150))) $ \(h,w) -> forAll (genSparseMatrix (h,w) :: Gen (SparseMatrix Integer)) $ \m -> -- collect (toAssocList m) $ fromAssocList (toAssocList m) == m -------------------------------------------------------------------------------- -- TRANSPOSITION -- ------------------- testgr_trans = testGroup "TRANSPOSITION" [ testProperty "Transposition" prop_trans ] prop_trans = forAll (genPair (genSize (1,100)) (genSize (1,150))) $ \(h,w) -> forAll (genSparseMatrix (h,w) :: Gen (SparseMatrix Integer)) $ \m -> collect (size (mx m), L.sum [ size r | r <- elems (mx m) ]) $ trans (trans m) == m -------------------------------------------------------------------------------- -- MULTIPLICATIONS -- --------------------- testgr_muls = testGroup "MULTIPLICATIONS" [ testProperty "Matrix-by-vector multiplication" prop_mulMV , testProperty "Vector-by-matrix multiplication" prop_mulVM , testProperty "Sparse matrices multiplication" prop_mul ] dotL :: (Num α) => [α] -> [α] -> α dotL x y = L.sum $ zipWith (*) x y prop_mulMV = forAll (genSize (1,100)) $ \h -> forAll (genSize (1,200)) $ \w -> forAll (genSparseMatrix (h,w) :: Gen (SparseMatrix Integer)) $ \m -> forAll (genSparseVector h :: Gen (SparseVector Integer)) $ \v -> fillVec (m ×· v) == [ row `dotL` fillVec v | row <- fillMx m ] prop_mulVM = forAll (genSize (1,100)) $ \h -> forAll (genSize (1,200)) $ \w -> forAll (genSparseVector h :: Gen (SparseVector Integer)) $ \v -> forAll (genSparseMatrix (h,w) :: Gen (SparseMatrix Integer)) $ \m -> fillVec (v ·× m) == [ fillVec v `dotL` col | col <- transpose (fillMx m) ] mm :: (Num α) => [[α]] -> [[α]] -> [[α]] a `mm` b = [ [ row `dotL` col | col <- transpose b ] | row <- a ] prop_mul = forAll (genSize (1,100)) $ \h -> forAll (genSize (1,150)) $ \n -> forAll (genSize (1,130)) $ \w -> forAll (genSparseMatrix (h,n) :: Gen (SparseMatrix Integer)) $ \a -> forAll (genSparseMatrix (n,w) :: Gen (SparseMatrix Integer)) $ \b -> fillMx a `mm` fillMx b == fillMx (a × b)