som 9.0.1 → 9.0.2
raw patch · 15 files changed
+96/−1052 lines, 15 filesdep ~MonadRandomdep ~QuickCheckdep ~assert
Dependency ranges changed: MonadRandom, QuickCheck, assert, base, containers, deepseq, grid, som, test-framework, test-framework-quickcheck2
Files
- LICENSE +22/−19
- som.cabal +65/−71
- src/Data/Datamining/Clustering/Classifier.hs +1/−1
- src/Data/Datamining/Clustering/DSOM.hs +1/−1
- src/Data/Datamining/Clustering/DSOMInternal.hs +1/−1
- src/Data/Datamining/Clustering/SGM.hs +1/−1
- src/Data/Datamining/Clustering/SGMInternal.hs +1/−1
- src/Data/Datamining/Clustering/SOM.hs +1/−1
- src/Data/Datamining/Clustering/SOMInternal.hs +1/−1
- src/Data/Datamining/Pattern.hs +1/−1
- test/Data/Datamining/Clustering/DSOMQC.hs +0/−287
- test/Data/Datamining/Clustering/SGMQC.hs +0/−241
- test/Data/Datamining/Clustering/SOMQC.hs +0/−338
- test/Data/Datamining/PatternQC.hs +0/−87
- test/Main.hs +1/−1
LICENSE view
@@ -1,27 +1,30 @@-Copyright (c) Amy de Buitléir 2010-2015+Copyright Amy de Buitléir (c) 2010-2017+ All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met:+Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met: -* Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer.-* Redistributions in binary form must reproduce the above copyright- notice, this list of conditions and the following disclaimer in the- documentation and/or other materials provided with the distribution.-* Neither the name of the author nor the names of other contributors- may be used to endorse or promote products derived from this software- without specific prior written permission.+ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS-IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Amy de Buitléir nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
som.cabal view
@@ -1,76 +1,70 @@-Name: som-Version: 9.0.1-Stability: experimental-Synopsis: Self-Organising Maps.-Description: A Kohonen Self-organising Map (SOM) maps input patterns - onto a regular grid (usually two-dimensional) where each- node in the grid is a model of the input data, and does- so using a method which ensures that any topological- relationships within the input data are also represented- in the grid. This implementation supports the use of - non-numeric patterns.- .- In layman's terms, a SOM can be useful when you you want- to discover the underlying structure of some data.- .- The userguide is available at - <https://github.com/mhwombat/som/wiki>.-Category: Math-License: BSD3-License-file: LICENSE-Copyright: (c) Amy de Buitléir 2010-2015-Homepage: https://github.com/mhwombat/som-Bug-reports: https://github.com/mhwombat/som/issues-Author: Amy de Buitléir-Maintainer: amy@nualeargais.ie-Build-Type: Simple-Cabal-Version: >=1.8+name: som+version: 9.0.2+cabal-version: >=1.10+build-type: Simple+license: BSD3+license-file: LICENSE+copyright: (c) 2010-2017 Amy de Buitléir+maintainer: amy@nualeargais.ie+homepage: https://github.com/mhwombat/som#readme+bug-reports: https://github.com/mhwombat/som/issues+synopsis: Self-Organising Maps.+description:+ A Kohonen Self-organising Map (SOM) maps input patterns+ onto a regular grid (usually two-dimensional) where each+ node in the grid is a model of the input data, and does+ so using a method which ensures that any topological+ relationships within the input data are also represented+ in the grid. This implementation supports the use of+ non-numeric patterns.+ .+ In layman's terms, a SOM can be useful when you you want+ to discover the underlying structure of some data.+ .+ The userguide is available at+ <https://github.com/mhwombat/som/wiki>.+category: Math+author: Amy de Buitléir source-repository head- type: git- location: https://github.com/mhwombat/som.git--source-repository this- type: git- location: https://github.com/mhwombat/som.git- tag: 8.2.3-+ type: git+ location: https://github.com/mhwombat/som library- hs-source-dirs: src- build-depends: assert ==0.0.*,- base >=4.8 && <5,- containers ==0.5.*,- deepseq ==1.4.*,- grid ==7.* && >=7.7,- MonadRandom ==0.4.*- ghc-options: -Wall- exposed-modules: Data.Datamining.Clustering.SOM,- Data.Datamining.Clustering.SOMInternal,- Data.Datamining.Clustering.DSOM,- Data.Datamining.Clustering.DSOMInternal,- Data.Datamining.Clustering.SGM,- Data.Datamining.Clustering.SGMInternal,- Data.Datamining.Clustering.Classifier,- Data.Datamining.Pattern--test-suite som-tests- type: exitcode-stdio-1.0- build-depends: assert ==0.0.*,- base >=4.8 && <5,- test-framework-quickcheck2 == 0.3.*,- QuickCheck ==2.8.*,- test-framework ==0.8.*,- som,- containers ==0.5.*,- grid ==7.* && >=7.7,- MonadRandom ==0.4.*,- random ==1.1.*- hs-source-dirs: test- ghc-options: -Wall- main-is: Main.hs- other-modules: Data.Datamining.Clustering.SOMQC,- Data.Datamining.Clustering.DSOMQC,- Data.Datamining.Clustering.SGMQC,- Data.Datamining.PatternQC+ exposed-modules:+ Data.Datamining.Clustering.SOM+ Data.Datamining.Clustering.SOMInternal+ Data.Datamining.Clustering.DSOM+ Data.Datamining.Clustering.DSOMInternal+ Data.Datamining.Clustering.SGM+ Data.Datamining.Clustering.SGMInternal+ Data.Datamining.Clustering.Classifier+ Data.Datamining.Pattern+ build-depends:+ assert >=0.0.1.2 && <0.1,+ base >=4.9.1.0 && <4.10,+ containers >=0.5.7.1 && <0.6,+ deepseq >=1.4.2.0 && <1.5,+ grid >=7.8.8 && <7.9,+ MonadRandom >=0.5.1 && <0.6+ default-language: Haskell2010+ hs-source-dirs: src+ ghc-options: -Wall +test-suite som-test+ type: exitcode-stdio-1.0+ main-is: Main.hs+ build-depends:+ assert >=0.0.1.2 && <0.1,+ base >=4.9.1.0 && <4.10,+ test-framework-quickcheck2 >=0.3.0.3 && <0.4,+ QuickCheck >=2.9.2 && <2.10,+ test-framework >=0.8.1.1 && <0.9,+ som >=9.0.2 && <9.1,+ containers >=0.5.7.1 && <0.6,+ grid >=7.8.8 && <7.9,+ MonadRandom >=0.5.1 && <0.6,+ random ==1.1.*+ default-language: Haskell2010+ hs-source-dirs: test+ ghc-options: -threaded -rtsopts -with-rtsopts=-N -Wall
src/Data/Datamining/Clustering/Classifier.hs view
@@ -1,7 +1,7 @@ ------------------------------------------------------------------------ -- | -- Module : Data.Datamining.Clustering.Classifier--- Copyright : (c) Amy de Buitléir 2012-2015+-- Copyright : (c) Amy de Buitléir 2012-2016 -- License : BSD-style -- Maintainer : amy@nualeargais.ie -- Stability : experimental
src/Data/Datamining/Clustering/DSOM.hs view
@@ -1,7 +1,7 @@ ------------------------------------------------------------------------ -- | -- Module : Data.Datamining.Clustering.SOM--- Copyright : (c) Amy de Buitléir 2012-2015+-- Copyright : (c) Amy de Buitléir 2012-2016 -- License : BSD-style -- Maintainer : amy@nualeargais.ie -- Stability : experimental
src/Data/Datamining/Clustering/DSOMInternal.hs view
@@ -1,7 +1,7 @@ ------------------------------------------------------------------------ -- | -- Module : Data.Datamining.Clustering.DSOMInternal--- Copyright : (c) Amy de Buitléir 2012-2015+-- Copyright : (c) Amy de Buitléir 2012-2016 -- License : BSD-style -- Maintainer : amy@nualeargais.ie -- Stability : experimental
src/Data/Datamining/Clustering/SGM.hs view
@@ -1,7 +1,7 @@ ------------------------------------------------------------------------ -- | -- Module : Data.Datamining.Clustering.SGM--- Copyright : (c) Amy de Buitléir 2012-2015+-- Copyright : (c) Amy de Buitléir 2012-2016 -- License : BSD-style -- Maintainer : amy@nualeargais.ie -- Stability : experimental
src/Data/Datamining/Clustering/SGMInternal.hs view
@@ -1,7 +1,7 @@ ------------------------------------------------------------------------ -- | -- Module : Data.Datamining.Clustering.SGMInternal--- Copyright : (c) Amy de Buitléir 2012-2015+-- Copyright : (c) Amy de Buitléir 2012-2016 -- License : BSD-style -- Maintainer : amy@nualeargais.ie -- Stability : experimental
src/Data/Datamining/Clustering/SOM.hs view
@@ -1,7 +1,7 @@ ------------------------------------------------------------------------ -- | -- Module : Data.Datamining.Clustering.SOM--- Copyright : (c) Amy de Buitléir 2012-2015+-- Copyright : (c) Amy de Buitléir 2012-2016 -- License : BSD-style -- Maintainer : amy@nualeargais.ie -- Stability : experimental
src/Data/Datamining/Clustering/SOMInternal.hs view
@@ -1,7 +1,7 @@ ------------------------------------------------------------------------ -- | -- Module : Data.Datamining.Clustering.SOMInternal--- Copyright : (c) Amy de Buitléir 2012-2015+-- Copyright : (c) Amy de Buitléir 2012-2016 -- License : BSD-style -- Maintainer : amy@nualeargais.ie -- Stability : experimental
src/Data/Datamining/Pattern.hs view
@@ -1,7 +1,7 @@ ------------------------------------------------------------------------ -- | -- Module : Data.Datamining.Pattern--- Copyright : (c) Amy de Buitléir 2012-2015+-- Copyright : (c) Amy de Buitléir 2012-2016 -- License : BSD-style -- Maintainer : amy@nualeargais.ie -- Stability : experimental
− test/Data/Datamining/Clustering/DSOMQC.hs
@@ -1,287 +0,0 @@---------------------------------------------------------------------------- |--- Module : Data.Datamining.Clustering.DSOMQC--- Copyright : (c) Amy de Buitléir 2012-2015--- License : BSD-style--- Maintainer : amy@nualeargais.ie--- Stability : experimental--- Portability : portable------ Tests-----------------------------------------------------------------------------{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE CPP #-}-{-# OPTIONS_GHC -fno-warn-type-defaults -fno-warn-orphans #-}--module Data.Datamining.Clustering.DSOMQC- (- test- ) where--import Data.Datamining.Pattern (euclideanDistanceSquared,- magnitudeSquared, adjustNum, absDifference)-import Data.Datamining.Clustering.Classifier(classify,- classifyAndTrain, differences, diffAndTrain, models,- numModels, train, trainBatch)-import Data.Datamining.Clustering.DSOMInternal--#if MIN_VERSION_base(4,8,0)-#else-import Control.Applicative-#endif--import Data.List (sort)-import Math.Geometry.Grid (size)-import Math.Geometry.Grid.Hexagonal (HexHexGrid, hexHexGrid)-import Math.Geometry.GridMap ((!), elems)-import Math.Geometry.GridMap.Lazy (LGridMap, lazyGridMap)-import Test.Framework as TF (Test, testGroup)-import Test.Framework.Providers.QuickCheck2 (testProperty)-import Test.QuickCheck ((==>), Gen, Arbitrary, arbitrary, choose,- Property, property, sized, suchThat, vectorOf, shrink)--positive :: (Num a, Ord a, Arbitrary a) => Gen a-positive = arbitrary `suchThat` (> 0)--data RougierArgs- = RougierArgs Double Double Double Double Double deriving Show--instance Arbitrary RougierArgs where- arbitrary = RougierArgs <$> choose (0,1) <*> choose (0,1)- <*> arbitrary <*> choose (0,1) <*> positive--prop_rougierFunction_zero_if_perfect_model_exists :: RougierArgs -> Property-prop_rougierFunction_zero_if_perfect_model_exists (RougierArgs r p _ diff dist) =- property $ rougierLearningFunction r p 0 diff dist == 0--prop_rougierFunction_r_if_bmu_is_bad_model :: RougierArgs -> Property-prop_rougierFunction_r_if_bmu_is_bad_model (RougierArgs r p _ _ _) =- property $ rougierLearningFunction r p 1 1 0 == r--prop_rougierFunction_r_in_bounds :: RougierArgs -> Property-prop_rougierFunction_r_in_bounds (RougierArgs r p bmuDiff diff dist) =- property $ 0 <= f && f <= 1- where f = rougierLearningFunction r p bmuDiff diff dist--prop_rougierFunction_r_if_inelastic :: RougierArgs -> Property-prop_rougierFunction_r_if_inelastic (RougierArgs r _ _ _ _) =- property $ rougierLearningFunction r 1.0 1.0 1.0 0 == r--fractionDiff :: [Double] -> [Double] -> Double-fractionDiff xs ys = if denom == 0 then 0 else d / denom- where d = sqrt $ euclideanDistanceSquared xs ys- denom = max xMag yMag- xMag = sqrt $ magnitudeSquared xs- yMag = sqrt $ magnitudeSquared ys--approxEqual :: [TestPattern] -> [TestPattern] -> Bool-approxEqual xs ys = fractionDiff xs' ys' <= 0.1- where xs' = map toDouble xs- ys' = map toDouble ys---- We need to ensure that the absolute value of the difference--- between any two test patterns is on the unit interval.--newtype TestPattern = TestPattern {toDouble :: Double}- deriving ( Eq, Ord, Show, Read)--instance Arbitrary TestPattern where- arbitrary = fmap TestPattern $ choose (0,1)- shrink (TestPattern x) =- [ TestPattern x' | x' <- shrink x, x' >= 0, x' <= 1]--testPatternDiff :: TestPattern -> TestPattern -> Double-testPatternDiff (TestPattern a) (TestPattern b) = absDifference a b--adjustTestPattern :: TestPattern -> Double -> TestPattern -> TestPattern-adjustTestPattern (TestPattern target) r (TestPattern x)- = TestPattern $ adjustNum target r x---- | A classifier and a training set. The training set will consist of--- @j@ vectors of equal length, where @j@ is the number of patterns--- the classifier can model. After running through the training set a--- few times, the classifier should be very accurate at identifying--- any of those @j@ vectors.-data DSOMTestData- = DSOMTestData- {- som1 :: DSOM (LGridMap HexHexGrid) Double (Int, Int) TestPattern,- params1 :: RougierArgs,- trainingSet1 :: [TestPattern]- }--instance Show DSOMTestData where- show s = "buildDSOMTestData " ++ show (size . gridMap . som1 $ s)- ++ " " ++ show (elems . gridMap . som1 $ s)- ++ " (" ++ show (params1 s) - ++ ") " ++ show (trainingSet1 s) --buildDSOMTestData- :: Int -> [TestPattern] -> RougierArgs -> [TestPattern] -> DSOMTestData-buildDSOMTestData len ps rp@(RougierArgs r p _ _ _) targets =- DSOMTestData s rp targets- where g = hexHexGrid len- gm = lazyGridMap g ps- fr = rougierLearningFunction r p- s = DSOM gm fr testPatternDiff adjustTestPattern---- | Generate a classifier and a training set. The training set will--- consist @j@ vectors of equal length, where @j@ is the number of--- patterns the classifier can model. After running through the--- training set a few times, the classifier should be very accurate at--- identifying any of those @j@ vectors.-sizedDSOMTestData :: Int -> Gen DSOMTestData-sizedDSOMTestData n = do- sideLength <- choose (1, min (n+1) 5) --avoid long tests- let tileCount = 3*sideLength*(sideLength-1) + 1- let numberOfPatterns = tileCount- ps <- vectorOf numberOfPatterns arbitrary- rp <- arbitrary- targets <- vectorOf numberOfPatterns arbitrary- return $ buildDSOMTestData sideLength ps rp targets--instance Arbitrary DSOMTestData where- arbitrary = sized sizedDSOMTestData---- | If we use a fixed learning rate of one (regardless of the distance--- from the BMU), and train a classifier once on one pattern, then all--- nodes should match the input vector.-prop_global_instant_training_works :: DSOMTestData -> Property-prop_global_instant_training_works (DSOMTestData s _ xs) =- property $ finalModels `approxEqual` expectedModels- where x = head xs- gm = toGridMap s :: LGridMap HexHexGrid TestPattern- f _ _ _ = 1- s2 = DSOM gm f testPatternDiff adjustTestPattern- s3 = train s2 x- finalModels = models s3 :: [TestPattern]- expectedModels = replicate (numModels s) x :: [TestPattern]--prop_training_works :: DSOMTestData -> Property-prop_training_works (DSOMTestData s _ xs) = errBefore /= 0 ==>- errAfter < errBefore- where (bmu, s') = classifyAndTrain s x- x = head xs- errBefore = testPatternDiff x (gridMap s ! bmu)- errAfter = testPatternDiff x (gridMap s' ! bmu)---- Invoking @diffAndTrain f s p@ should give identical results to--- @(p `classify` s, train s f p)@.-prop_classifyAndTrainEquiv :: DSOMTestData -> Property-prop_classifyAndTrainEquiv (DSOMTestData s _ ps) = property $- bmu == s `classify` p && gridMap s1 == gridMap s2- where p = head ps- (bmu, s1) = classifyAndTrain s p- s2 = train s p---- Invoking @diffAndTrain f s p@ should give identical results to--- @(s `diff` p, train s f p)@.-prop_diffAndTrainEquiv :: DSOMTestData -> Property-prop_diffAndTrainEquiv (DSOMTestData s _ ps) = property $- diffs == s `differences` p && gridMap s1 == gridMap s2- where p = head ps- (diffs, s1) = diffAndTrain s p- s2 = train s p---- Invoking @trainNeighbourhood s (classify s p) p@ should give--- identical results to @train s p@.-prop_trainNeighbourhoodEquiv :: DSOMTestData -> Property-prop_trainNeighbourhoodEquiv (DSOMTestData s _ ps) = property $- gridMap s1 == gridMap s2- where p = head ps- s1 = trainNeighbourhood s (classify s p) p- s2 = train s p---- | The training set consists of the same vectors in the same order,--- several times over. So the resulting classifications should consist--- of the same integers in the same order, over and over.-prop_batch_training_works :: DSOMTestData -> Property-prop_batch_training_works (DSOMTestData s _ xs) = property $- classifications == (concat . replicate 5) firstSet- where trainingSet = (concat . replicate 5) xs- s' = trainBatch s trainingSet- classifications = map (classify s') trainingSet- firstSet = take (length xs) classifications--data SpecialDSOMTestData- = SpecialDSOMTestData- {- som2 :: DSOM (LGridMap HexHexGrid) Double (Int, Int) TestPattern,- params2 :: Double,- trainingSet2 :: [TestPattern]- }--instance Show SpecialDSOMTestData where- show s = "buildDSOMTestData " ++ show (size . gridMap . som2 $ s)- ++ " " ++ show (elems . gridMap . som2 $ s)- ++ " (" ++ show (params2 s) - ++ ") " ++ show (trainingSet2 s) --stepFunction :: Double -> Double -> Double -> Double -> Double-stepFunction r _ _ d = if d == 0 then r else 0.0--buildSpecialDSOMTestData- :: Int -> [TestPattern] -> Double -> [TestPattern] -> SpecialDSOMTestData-buildSpecialDSOMTestData len ps r targets =- SpecialDSOMTestData s r targets- where g = hexHexGrid len- gm = lazyGridMap g ps- fr = stepFunction r- s = DSOM gm fr testPatternDiff adjustTestPattern---- | Generate a classifier and a training set. The training set will--- consist @j@ vectors of equal length, where @j@ is the number of--- patterns the classifier can model. After running through the--- training set a few times, the classifier should be very accurate at--- identifying any of those @j@ vectors.-sizedSpecialDSOMTestData :: Int -> Gen SpecialDSOMTestData-sizedSpecialDSOMTestData n = do- sideLength <- choose (1, min (n+1) 5) --avoid long tests- let tileCount = 3*sideLength*(sideLength-1) + 1- let ps = map TestPattern $ take tileCount [0,100..]- r <- choose (0.001, 1)- let targets = map TestPattern $ take tileCount [5,105..]- return $ buildSpecialDSOMTestData sideLength ps r targets--instance Arbitrary SpecialDSOMTestData where- arbitrary = sized sizedSpecialDSOMTestData---- | If we train a classifier once on a set of patterns, where the--- number of patterns in the set is equal to the number of nodes in--- the classifier, then the classifier should become a better--- representation of the training set. The initial models and training--- set are designed to ensure that a single node will NOT train to--- more than one pattern (which would render the test invalid).-prop_batch_training_works2 :: SpecialDSOMTestData -> Property-prop_batch_training_works2 (SpecialDSOMTestData s _ xs) =- errBefore /= 0 ==> errAfter < errBefore- where s' = trainBatch s xs- errBefore = euclideanDistanceSquared (map toDouble . sort $ xs) (map toDouble . sort . models $ s)- errAfter = euclideanDistanceSquared (map toDouble . sort $ xs) (map toDouble . sort . models $ s')--test :: Test-test = testGroup "QuickCheck Data.Datamining.Clustering.DSOM"- [- testProperty "prop_rougierFunction_zero_if_perfect_model_exists"- prop_rougierFunction_zero_if_perfect_model_exists,- testProperty "prop_rougierFunction_r_if_bmu_is_bad_model"- prop_rougierFunction_r_if_bmu_is_bad_model,- testProperty "prop_rougierFunction_r_if_inelastic"- prop_rougierFunction_r_if_inelastic,- testProperty "prop_rougierFunction_r_in_bounds"- prop_rougierFunction_r_in_bounds,- testProperty "prop_global_instant_training_works"- prop_global_instant_training_works,- testProperty "prop_training_works" prop_training_works,- testProperty "prop_classifyAndTrainEquiv"- prop_classifyAndTrainEquiv,- testProperty "prop_diffAndTrainEquiv" prop_diffAndTrainEquiv,- testProperty "prop_trainNeighbourhoodEquiv" prop_trainNeighbourhoodEquiv,- testProperty "prop_batch_training_works" prop_batch_training_works,- testProperty "prop_batch_training_works2"- prop_batch_training_works2- ]
− test/Data/Datamining/Clustering/SGMQC.hs
@@ -1,241 +0,0 @@---------------------------------------------------------------------------- |--- Module : Data.Datamining.Clustering.SGMQC--- Copyright : (c) Amy de Buitléir 2012-2015--- License : BSD-style--- Maintainer : amy@nualeargais.ie--- Stability : experimental--- Portability : portable------ Tests-----------------------------------------------------------------------------{-# LANGUAGE MultiParamTypeClasses, TypeFamilies, FlexibleInstances,- FlexibleContexts #-}-{-# OPTIONS_GHC -fno-warn-type-defaults -fno-warn-orphans #-}--module Data.Datamining.Clustering.SGMQC- (- test- ) where--import Data.Datamining.Pattern (adjustNum, absDifference)-import Data.Datamining.Clustering.SGMInternal-import Data.List ((\\), minimumBy)-import qualified Data.Map.Strict as M-import Data.Ord (comparing)-import Data.Word (Word16)-import System.Random (Random)-import Test.Framework as TF (Test, testGroup)-import Test.Framework.Providers.QuickCheck2 (testProperty)-import Test.QuickCheck ((==>), Gen, Arbitrary, Property, Positive,- arbitrary, shrink, choose, property, sized, suchThat, vectorOf,- getPositive)--newtype UnitInterval a = UnitInterval {getUnitInterval :: a}- deriving ( Eq, Ord, Show, Read)--instance Functor UnitInterval where- fmap f (UnitInterval x) = UnitInterval (f x)--instance (Num a, Ord a, Random a, Arbitrary a)- => Arbitrary (UnitInterval a) where- arbitrary = fmap UnitInterval $ choose (0,1)- shrink (UnitInterval x) =- [ UnitInterval x' | x' <- shrink x, x' >= 0, x' <= 1]--prop_Exponential_starts_at_r0- :: UnitInterval Double -> Positive Double -> Property-prop_Exponential_starts_at_r0 r0 d- = property $ abs (exponential r0' d' 0 - r0') < 0.01- where r0' = getUnitInterval r0- d' = getPositive d--prop_Exponential_ge_0- :: UnitInterval Double -> Positive Double -> Positive Int -> Property-prop_Exponential_ge_0 r0 d t = property $ exponential r0' d' t' >= 0- where r0' = getUnitInterval r0- d' = getPositive d- t' = getPositive t--positive :: (Num a, Ord a, Arbitrary a) => Gen a-positive = arbitrary `suchThat` (> 0)--data TestSGM = TestSGM (SGM Int Double Word16 Double) String--instance Show TestSGM where- show (TestSGM _ desc) = desc--buildTestSGM- :: Double -> Double -> Int -> Double -> Bool -> [Double] -> TestSGM-buildTestSGM r0 d maxSz dt ad ps = TestSGM s' desc- where lrf = exponential r0 d- s = makeSGM lrf maxSz dt ad absDifference adjustNum- desc = "buildTestSGM " ++ show r0 ++ " " ++ show d- ++ " " ++ show maxSz- ++ " " ++ show dt- ++ " " ++ show ad- ++ " " ++ show ps- s' = trainBatch s ps--sizedTestSGM :: Int -> Gen TestSGM-sizedTestSGM n = do- maxSz <- choose (1, n+1)- let numPatterns = n- r0 <- choose (0, 1)- d <- positive- dt <- choose (0, 1)- ad <- arbitrary- ps <- vectorOf numPatterns arbitrary- return $ buildTestSGM r0 d maxSz dt ad ps--instance Arbitrary TestSGM where- arbitrary = sized sizedTestSGM--prop_classify_chooses_best_fit :: TestSGM -> Double -> Property-prop_classify_chooses_best_fit (TestSGM s _) x- = property $ bmu == fst (minimumBy (comparing snd) diffs)- where (bmu, _, diffs, _) = trainAndClassify s x--prop_classify_never_creates_model :: TestSGM -> Double -> Property-prop_classify_never_creates_model (TestSGM s _) x- = not (isEmpty s) ==> bmu `elem` (labels s)- where (bmu, _, _) = classify s x--prop_trainNode_reduces_diff :: TestSGM -> Double -> Property-prop_trainNode_reduces_diff (TestSGM s _) x = not (isEmpty s) ==>- diffAfter < diffBefore || diffBefore == 0- || learningRate s (time s) < 1e-10- where (bmu, diffBefore, _) = classify s x- s2 = trainNode s bmu x- (_, diffAfter, _) = classify s2 x--prop_diff_lt_threshold_after_training :: TestSGM -> Double -> Property-prop_diff_lt_threshold_after_training (TestSGM s _) x =- numModels s < maxSize s ==> diffAfter < diffThreshold s- where (_, _, _, s') = trainAndClassify s x- (_, diffAfter, _) = classify s' x--prop_training_reduces_diff :: TestSGM -> Double -> Property-prop_training_reduces_diff (TestSGM s _) x = not (isEmpty s) ==>- diffAfter < diffBefore || diffBefore == 0- || learningRate s (time s) < 1e-10- where (_, diffBefore, _) = classify s x- s2 = train s x- (_, diffAfter, _) = classify s2 x---- TODO prop: map will never exceed maxSize--prop_train_only_modifies_one_model- :: TestSGM -> Double -> Property-prop_train_only_modifies_one_model (TestSGM s _) p- = numModels s < maxSize s ==> otherModelsBefore == otherModelsAfter- where (bmu, _, _, s2) = trainAndClassify s p- otherModelsBefore = M.delete bmu . M.map fst . toMap $ s- otherModelsAfter = M.delete bmu . M.map fst . toMap $ s2--prop_train_increments_counter :: TestSGM -> Double -> Property-prop_train_increments_counter (TestSGM s _) x- = numModels s < maxSize s ==> countAfter == countBefore + 1- -- We have to check if the SGM is full, otherwise we'll replace an- -- existing model (and its counter), which means that the total- -- count could change by an arbitrary amount.- where countBefore = time s- countAfter = time $ train s x---- | The training set consists of the same vectors in the same order,--- several times over. So the resulting classifications should consist--- of the same integers in the same order, over and over.-prop_batch_training_works :: TestSGM -> [Double] -> Property-prop_batch_training_works (TestSGM s _) ps- -- = maxSize s > length ps- -- ==> classifications == (concat . replicate 5) firstSet- = property $ classifications == (concat . replicate 5) firstSet- where trainingSet = (concat . replicate 5) ps- sRightSize = if maxSize s >= length ps- then s- else s { maxSize=length ps + 1}- s' = trainBatch sRightSize trainingSet- classifications = map (justBMU . classify s') trainingSet- justBMU = \(bmu, _, _) -> bmu- firstSet = take (length ps) classifications---- | WARNING: This can fail when two nodes are close enough in--- value so that after training they become identical.-prop_classification_is_consistent :: TestSGM -> Double -> Property-prop_classification_is_consistent (TestSGM s _) x- = property $ bmu == bmu'- where (bmu, _, _, s2) = trainAndClassify s x- (bmu', _, _) = classify s2 x--prop_classification_results_are_consistent- :: TestSGM -> Double -> Property-prop_classification_results_are_consistent (TestSGM s _) x- = property $ bmu == fst (minimumBy (comparing snd) diffs)- where (bmu, _, diffs, _) = trainAndClassify s x--prop_classification_results_are_consistent2- :: TestSGM -> Double -> Property-prop_classification_results_are_consistent2 (TestSGM s _) x- = property $ bmuDiff == snd (minimumBy (comparing snd) diffs)- where (_, bmuDiff, diffs, _) = trainAndClassify s x--prop_classification_stabilises :: TestSGM -> [Double] -> Property-prop_classification_stabilises (TestSGM s _) ps- = (not . null $ ps) && maxSize s > length ps ==> k2 == k1- where sStable = trainBatch s . concat . replicate 10 $ ps- (k1, _, _, sStable2) = trainAndClassify sStable (head ps)- sStable3 = trainBatch sStable2 ps- (k2, _, _) = classify sStable3 (head ps)--prop_models_not_deleted_unless_allowed- :: TestSGM -> Double -> Property-prop_models_not_deleted_unless_allowed (TestSGM s _) x =- (not . allowDeletion $ s) ==> null (labelsBefore \\ labelsAfter)- where labelsBefore = M.keys $ modelMap s- labelsAfter = M.keys $ modelMap s'- (_, _, _, s') = trainAndClassify s x--prop_models_not_deleted_unless_allowed2- :: TestSGM -> Double -> Property-prop_models_not_deleted_unless_allowed2 (TestSGM s _) x =- (not . allowDeletion $ s) ==> null (labelsBefore \\ labelsAfter)- where labelsBefore = M.keys $ modelMap s- labelsAfter = M.keys $ modelMap s'- s' = train s x--test :: Test-test = testGroup "QuickCheck Data.Datamining.Clustering.SGM"- [- testProperty "prop_Exponential_starts_at_r0"- prop_Exponential_starts_at_r0,- testProperty "prop_Exponential_ge_0"- prop_Exponential_ge_0,- testProperty "prop_classify_chooses_best_fit"- prop_classify_chooses_best_fit,- testProperty "prop_classify_never_creates_model"- prop_classify_never_creates_model,- testProperty "prop_trainNode_reduces_diff"- prop_trainNode_reduces_diff,- testProperty "prop_diff_lt_threshold_after_training"- prop_diff_lt_threshold_after_training,- testProperty "prop_training_reduces_diff"- prop_training_reduces_diff,- testProperty "prop_train_only_modifies_one_model"- prop_train_only_modifies_one_model,- testProperty "prop_train_increments_counter"- prop_train_increments_counter,- testProperty "prop_batch_training_works" prop_batch_training_works,- testProperty "prop_classification_is_consistent"- prop_classification_is_consistent,- testProperty "prop_classification_results_are_consistent"- prop_classification_results_are_consistent,- testProperty "prop_classification_results_are_consistent2"- prop_classification_results_are_consistent2,- testProperty "prop_classification_stabilises"- prop_classification_stabilises,- testProperty "prop_models_not_deleted_unless_allowed"- prop_models_not_deleted_unless_allowed,- testProperty "prop_models_not_deleted_unless_allowed2"- prop_models_not_deleted_unless_allowed2 - ]
− test/Data/Datamining/Clustering/SOMQC.hs
@@ -1,338 +0,0 @@---------------------------------------------------------------------------- |--- Module : Data.Datamining.Clustering.SOMQC--- Copyright : (c) Amy de Buitléir 2012-2015--- License : BSD-style--- Maintainer : amy@nualeargais.ie--- Stability : experimental--- Portability : portable------ Tests-----------------------------------------------------------------------------{-# LANGUAGE MultiParamTypeClasses, TypeFamilies, FlexibleInstances,- FlexibleContexts #-}-{-# OPTIONS_GHC -fno-warn-type-defaults -fno-warn-orphans #-}--module Data.Datamining.Clustering.SOMQC- (- test- ) where--import Data.Datamining.Pattern (euclideanDistanceSquared,- magnitudeSquared, adjustNum, absDifference)-import Data.Datamining.Clustering.Classifier(classify,- classifyAndTrain, reportAndTrain, differences, diffAndTrain, models,- numModels, train, trainBatch)-import Data.Datamining.Clustering.SOMInternal--import Data.List (sort)-import Math.Geometry.Grid (size)-import Math.Geometry.Grid.Hexagonal (HexHexGrid, hexHexGrid)-import Math.Geometry.GridMap ((!), elems)-import Math.Geometry.GridMap.Lazy (LGridMap, lazyGridMap)-import System.Random (Random)-import Test.Framework as TF (Test, testGroup)-import Test.Framework.Providers.QuickCheck2 (testProperty)-import Test.QuickCheck ((==>), Gen, Arbitrary, arbitrary, choose,- Property, property, sized, suchThat, vectorOf)--positive :: (Num a, Ord a, Arbitrary a) => Gen a-positive = arbitrary `suchThat` (> 0)--data DecayingGaussianParams a = DecayingGaussianParams a a a a a- deriving (Eq, Show)--instance- (Random a, Num a, Ord a, Arbitrary a)- => Arbitrary (DecayingGaussianParams a) where- arbitrary = do- r0 <- choose (0,1)- rf <- choose (0,r0)- w0 <- positive- wf <- choose (0,w0)- tf <- positive- return $ DecayingGaussianParams r0 rf w0 wf tf--prop_DecayingGaussian_starts_at_r0- :: DecayingGaussianParams Double -> Property-prop_DecayingGaussian_starts_at_r0 (DecayingGaussianParams r0 rf w0 wf tf)- = property $ abs ((decayingGaussian r0 rf w0 wf tf 0 0) - r0) < 0.01--prop_DecayingGaussian_starts_at_w0- :: DecayingGaussianParams Double -> Property-prop_DecayingGaussian_starts_at_w0 (DecayingGaussianParams r0 rf w0 wf tf)- = property $- decayingGaussian r0 rf w0 wf tf 0 inside >= r0 * exp (-0.5)- && decayingGaussian r0 rf w0 wf tf 0 outside < r0 * exp (-0.5)- where inside = w0 * 0.99999- outside = w0 * 1.00001--prop_DecayingGaussian_decays_to_rf- :: DecayingGaussianParams Double -> Property-prop_DecayingGaussian_decays_to_rf (DecayingGaussianParams r0 rf w0 wf tf)- = property $ abs ((decayingGaussian r0 rf w0 wf tf tf 0) - rf) < 0.01--prop_DecayingGaussian_shrinks_to_wf- :: DecayingGaussianParams Double -> Property-prop_DecayingGaussian_shrinks_to_wf (DecayingGaussianParams r0 rf w0 wf tf)- = property $- decayingGaussian r0 rf w0 wf tf tf inside >= rf * exp (-0.5)- && decayingGaussian r0 rf w0 wf tf tf outside < rf * exp (-0.5)- where inside = wf * 0.99999- outside = wf * 1.00001--fractionDiff :: [Double] -> [Double] -> Double-fractionDiff xs ys = if denom == 0 then 0 else d / denom- where d = sqrt $ euclideanDistanceSquared xs ys- denom = max xMag yMag- xMag = sqrt $ magnitudeSquared xs- yMag = sqrt $ magnitudeSquared ys--approxEqual :: [Double] -> [Double] -> Bool-approxEqual xs ys = fractionDiff xs ys <= 0.1---- | A classifier and a training set. The training set will consist of--- @j@ vectors of equal length, where @j@ is the number of patterns--- the classifier can model. After running through the training set a--- few times, the classifier should be very accurate at identifying--- any of those @j@ vectors.-data SOMTestData- = SOMTestData- {- som1 :: SOM Double Double (LGridMap HexHexGrid) Double (Int, Int) Double,- params1 :: DecayingGaussianParams Double,- trainingSet1 :: [Double]- }--instance Show SOMTestData where- show s = "buildSOMTestData " ++ show (size . gridMap . som1 $ s)- ++ " " ++ show (elems . gridMap . som1 $ s)- ++ " (" ++ show (params1 s) - ++ ") " ++ show (trainingSet1 s) --buildSOMTestData- :: Int -> [Double] -> DecayingGaussianParams Double- -> [Double] -> SOMTestData-buildSOMTestData len ps p@(DecayingGaussianParams r0 rf w0 wf tf) targets =- SOMTestData s p targets- where g = hexHexGrid len- gm = lazyGridMap g ps- fr = decayingGaussian r0 rf w0 wf tf- s = SOM gm fr absDifference adjustNum 0--sizedSOMTestData :: Int -> Gen SOMTestData-sizedSOMTestData n = do- sideLength <- choose (1, min (n+1) 5) --avoid long tests- let tileCount = 3*sideLength*(sideLength-1) + 1- let numberOfPatterns = tileCount- ps <- vectorOf numberOfPatterns arbitrary- r0 <- choose (0, 1)- rf <- choose (0, r0)- w0 <- choose (0, fromIntegral sideLength)- wf <- choose (0, w0)- tf <- choose (1, 10)- targets <- vectorOf numberOfPatterns arbitrary- return $ buildSOMTestData sideLength ps (DecayingGaussianParams r0 rf w0 wf tf) targets--instance Arbitrary SOMTestData where- arbitrary = sized sizedSOMTestData---- | If we use a fixed learning rate of one (regardless of the distance--- from the BMU), and train a classifier once on one pattern, then all--- nodes should match the input vector.-prop_global_instant_training_works :: SOMTestData -> Property-prop_global_instant_training_works (SOMTestData s _ xs) =- property $ finalModels `approxEqual` expectedModels- where x = head xs- gm = toGridMap s :: LGridMap HexHexGrid Double- f _ _ = 1- s2 = SOM gm f absDifference adjustNum 0- s3 = train s2 x- finalModels = models s3 :: [Double]- expectedModels = replicate (numModels s) x :: [Double]--prop_training_reduces_error :: SOMTestData -> Property-prop_training_reduces_error (SOMTestData s _ xs) = errBefore /= 0 ==>- errAfter < errBefore- where (bmu, s') = classifyAndTrain s x- x = head xs- errBefore = abs $ x - (gridMap s ! bmu)- errAfter = abs $ x - (gridMap s' ! bmu)---- Invoking @diffAndTrain f s p@ should give identical results to--- @(p `classify` s, train s f p)@.-prop_classifyAndTrainEquiv :: SOMTestData -> Property-prop_classifyAndTrainEquiv (SOMTestData s _ ps) = property $- bmu == s `classify` p && gridMap s1 == gridMap s2- where p = head ps- (bmu, s1) = classifyAndTrain s p- s2 = train s p---- Invoking @diffAndTrain f s p@ should give identical results to--- @(s `diff` p, train s f p)@.-prop_diffAndTrainEquiv :: SOMTestData -> Property-prop_diffAndTrainEquiv (SOMTestData s _ ps) = property $- diffs == s `differences` p && gridMap s1 == gridMap s2- where p = head ps- (diffs, s1) = diffAndTrain s p- s2 = train s p---- Invoking @trainNeighbourhood s (classify s p) p@ should give--- identical results to @train s p@.-prop_trainNeighbourhoodEquiv :: SOMTestData -> Property-prop_trainNeighbourhoodEquiv (SOMTestData s _ ps) = property $- gridMap s1 == gridMap s2- where p = head ps- s1 = trainNeighbourhood s (classify s p) p- s2 = train s p---- | The training set consists of the same vectors in the same order,--- several times over. So the resulting classifications should consist--- of the same integers in the same order, over and over.-prop_batch_training_works :: SOMTestData -> Property-prop_batch_training_works (SOMTestData s _ xs) = property $- classifications == (concat . replicate 5) firstSet- where trainingSet = (concat . replicate 5) xs- s' = trainBatch s trainingSet- classifications = map (classify s') trainingSet- firstSet = take (length xs) classifications---- | WARNING: This can fail when two nodes are close enough in--- value so that after training they become identical.--- This only happens rarely, so if the test fails, try again.-prop_classification_is_consistent- :: SOMTestData -> Property-prop_classification_is_consistent (SOMTestData s _ (x:_))- = property $ bmu == bmu'- where (bmu, _, s') = reportAndTrain s x- (bmu', _, _) = reportAndTrain s' x-prop_classification_is_consistent _ = error "Should not happen"---- | Same as SOMTestData, except that the initial models and training--- set are designed to ensure that a single node will NOT train to--- more than one pattern.-data SpecialSOMTestData- = SpecialSOMTestData- {- som2 :: SOM Int Int (LGridMap HexHexGrid) Double (Int, Int) Double,- params2 :: Double,- trainingSet2 :: [Double]- }--instance Show SpecialSOMTestData where- show s = "buildSpecialSOMTestData " ++ show (size . gridMap . som2 $ s)- ++ " " ++ show (elems . gridMap . som2 $ s)- ++ " " ++ show (params2 s) - ++ " " ++ show (trainingSet2 s) --buildSpecialSOMTestData- :: Int -> [Double] -> Double -> [Double] -> SpecialSOMTestData-buildSpecialSOMTestData len ps r targets =- SpecialSOMTestData s r targets- where g = hexHexGrid len- gm = lazyGridMap g ps- s = SOM gm (stepFunction r) absDifference adjustNum 0--sizedSpecialSOMTestData :: Int -> Gen SpecialSOMTestData-sizedSpecialSOMTestData n = do- sideLength <- choose (1, min (n+1) 5) --avoid long tests- let tileCount = 3*sideLength*(sideLength-1) + 1- let ps = take tileCount [0,100..]- r <- choose (0.001, 1)- let targets = take tileCount [5,105..]- return $ buildSpecialSOMTestData sideLength ps r targets--instance Arbitrary SpecialSOMTestData where- arbitrary = sized sizedSpecialSOMTestData---- | If we train a classifier once on a set of patterns, where the--- number of patterns in the set is equal to the number of nodes in--- the classifier, then the classifier should become a better--- representation of the training set. The initial models and training--- set are designed to ensure that a single node will NOT train to--- more than one pattern (which would render the test invalid).-prop_batch_training_works2 :: SpecialSOMTestData -> Property-prop_batch_training_works2 (SpecialSOMTestData s _ xs) =- errBefore /= 0 ==> errAfter < errBefore- where s' = trainBatch s xs- errBefore = euclideanDistanceSquared (sort xs) (sort (models s))- errAfter = euclideanDistanceSquared (sort xs) (sort (models s'))--data IncompleteSOMTestData- = IncompleteSOMTestData- {- som3 :: SOM Double Double (LGridMap HexHexGrid) Double (Int, Int) Double,- params3 :: DecayingGaussianParams Double,- trainingSet3 :: [Double]- }--instance Show IncompleteSOMTestData where- show s = "buildIncompleteSOMTestData " ++ show (size . gridMap . som3 $ s)- ++ " " ++ show (elems . gridMap . som3 $ s)- ++ " " ++ show (params3 s) - ++ " " ++ show (trainingSet3 s) --buildIncompleteSOMTestData- :: Int -> [Double] -> DecayingGaussianParams Double- -> [Double] -> IncompleteSOMTestData-buildIncompleteSOMTestData len ps p@(DecayingGaussianParams r0 rf w0 wf tf) targets =- IncompleteSOMTestData s p targets- where g = hexHexGrid len- gm = lazyGridMap g ps- fr = decayingGaussian r0 rf w0 wf tf- s = SOM gm fr absDifference adjustNum 0---- | Same as sizedSOMTestData, except some nodes don't have a value.-sizedIncompleteSOMTestData :: Int -> Gen IncompleteSOMTestData-sizedIncompleteSOMTestData n = do- sideLength <- choose (2, min (n+2) 5) --avoid long tests- let tileCount = 3*sideLength*(sideLength-1) + 1- numberOfPatterns <- choose (1,tileCount-1)- ps <- vectorOf numberOfPatterns arbitrary- r0 <- choose (0, 1)- rf <- choose (0, r0)- w0 <- choose (0, fromIntegral sideLength)- wf <- choose (0, w0)- tf <- choose (1, 10)- targets <- vectorOf numberOfPatterns arbitrary- return $ buildIncompleteSOMTestData sideLength ps (DecayingGaussianParams r0 rf w0 wf tf) targets--instance Arbitrary IncompleteSOMTestData where- arbitrary = sized sizedIncompleteSOMTestData--prop_can_train_incomplete_SOM :: IncompleteSOMTestData -> Property-prop_can_train_incomplete_SOM (IncompleteSOMTestData s _ xs) = errBefore /= 0 ==>- errAfter < errBefore- where (bmu, s') = classifyAndTrain s x- x = head xs- errBefore = abs $ x - (gridMap s ! bmu)- errAfter = abs $ x - (gridMap s' ! bmu)--test :: Test-test = testGroup "QuickCheck Data.Datamining.Clustering.SOM"- [- testProperty "prop_DecayingGaussian_starts_at_r0"- prop_DecayingGaussian_starts_at_r0,- testProperty "prop_DecayingGaussian_starts_at_w0"- prop_DecayingGaussian_starts_at_w0,- testProperty "prop_DecayingGaussian_decays_to_rf"- prop_DecayingGaussian_decays_to_rf,- testProperty "prop_DecayingGaussian_shrinks_to_wf"- prop_DecayingGaussian_shrinks_to_wf,- testProperty "prop_global_instant_training_works"- prop_global_instant_training_works,- testProperty "prop_training_reduces_error"- prop_training_reduces_error,- testProperty "prop_classifyAndTrainEquiv"- prop_classifyAndTrainEquiv,- testProperty "prop_diffAndTrainEquiv" prop_diffAndTrainEquiv,- testProperty "prop_trainNeighbourhoodEquiv" prop_trainNeighbourhoodEquiv,- testProperty "prop_batch_training_works" prop_batch_training_works,- testProperty "prop_classification_is_consistent"- prop_classification_is_consistent,- testProperty "prop_batch_training_works2"- prop_batch_training_works2,- testProperty "prop_can_train_incomplete_SOM"- prop_can_train_incomplete_SOM- ]
− test/Data/Datamining/PatternQC.hs
@@ -1,87 +0,0 @@---------------------------------------------------------------------------- |--- Module : Data.Datamining.PatternQC--- Copyright : (c) Amy de Buitléir 2012-2015--- License : BSD-style--- Maintainer : amy@nualeargais.ie--- Stability : experimental--- Portability : portable------ Tests-----------------------------------------------------------------------------{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE CPP #-}-{-# OPTIONS_GHC -fno-warn-type-defaults -fno-warn-orphans #-}--module Data.Datamining.PatternQC- (- test- ) where--import Data.Datamining.Pattern--import Test.Framework as TF (Test, testGroup)-import Test.Framework.Providers.QuickCheck2 (testProperty)-import Test.QuickCheck ((==>), Gen, Arbitrary, arbitrary, choose, - Property, property, sized, vector)--#if MIN_VERSION_base(4,8,0)-#else-import Control.Applicative-#endif--newtype UnitInterval = FromDouble Double deriving Show--instance Arbitrary UnitInterval where- arbitrary = FromDouble <$> choose (0,1)--prop_adjustVector_doesnt_choke_on_infinite_lists ::- [Double] -> UnitInterval -> Property-prop_adjustVector_doesnt_choke_on_infinite_lists xs (FromDouble d) = - property $ - length (adjustVector xs d [0,1..]) == length xs--data TwoVectorsSameLength = TwoVectorsSameLength [Double] [Double] - deriving Show--sizedTwoVectorsSameLength :: Int -> Gen TwoVectorsSameLength-sizedTwoVectorsSameLength n = - TwoVectorsSameLength <$> vector n <*> vector n--instance Arbitrary TwoVectorsSameLength where- arbitrary = sized sizedTwoVectorsSameLength--prop_zero_adjustment_is_no_adjustment :: - TwoVectorsSameLength -> Property-prop_zero_adjustment_is_no_adjustment (TwoVectorsSameLength xs ys) = - property $ adjustVector xs 0 ys == ys--prop_full_adjustment_gives_perfect_match :: - TwoVectorsSameLength -> Property-prop_full_adjustment_gives_perfect_match (TwoVectorsSameLength xs ys) = - property $ adjustVector xs 1 ys == xs--prop_adjustVector_improves_similarity :: - TwoVectorsSameLength -> UnitInterval -> Property-prop_adjustVector_improves_similarity - (TwoVectorsSameLength xs ys) (FromDouble a) = - a > 0 && a < 1 && not (null xs) ==> d2 < d1- where d1 = euclideanDistanceSquared xs ys- d2 = euclideanDistanceSquared xs ys'- ys' = adjustVector xs a ys--test :: Test-test = testGroup "QuickCheck Data.Datamining.Clustering.PatternQC"- [- testProperty "prop_adjustVector_doesnt_choke_on_infinite_lists"- prop_adjustVector_doesnt_choke_on_infinite_lists,- testProperty "prop_zero_adjustment_is_no_adjustment"- prop_zero_adjustment_is_no_adjustment,- testProperty "prop_full_adjustment_gives_perfect_match"- prop_full_adjustment_gives_perfect_match,- testProperty "prop_adjustVector_improves_similarity"- prop_adjustVector_improves_similarity- ]-
test/Main.hs view
@@ -1,7 +1,7 @@ ------------------------------------------------------------------------ -- | -- Module : Main--- Copyright : (c) Amy de Buitléir 2012-2015+-- Copyright : (c) Amy de Buitléir 2012-2016 -- License : BSD-style -- Maintainer : amy@nualeargais.ie -- Stability : experimental