packages feed

dawg-ord 0.5.0.0 → 0.5.0.1

raw patch · 2 files changed

+136/−1 lines, 2 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

Files

dawg-ord.cabal view
@@ -1,5 +1,5 @@ name:               dawg-ord-version:            0.5.0.0+version:            0.5.0.1 synopsis:           Directed acyclic word graphs description:     The library implements /directed acyclic word graphs/ (DAWGs) internally@@ -64,6 +64,8 @@         tests     main-is:         test.hs+    other-modules:+        Ord     build-depends:         dawg-ord       , base                    >= 4        && < 5
+ tests/Ord.hs view
@@ -0,0 +1,133 @@+{-# LANGUAGE FlexibleContexts #-}+++-- | Tests for the "Data.DAWG.Ord" module.+++module Ord where+++import qualified Control.Monad.State.Strict as E+import qualified Data.Set as S+import qualified Data.Map.Strict as M++import           Test.Tasty+import qualified Test.Tasty.SmallCheck as SC+import qualified Test.SmallCheck.Series as SC+import qualified Test.Tasty.QuickCheck as QC+import           Test.Tasty.HUnit++import qualified Data.DAWG.Ord as D+++tests :: TestTree+tests = testGroup "Tests" [properties, unitTests]+++properties :: TestTree+properties = testGroup "Properties" [scProps, qcProps]+++scProps = testGroup "(checked by SmallCheck)"+    [ SC.testProperty "id == assocs . fromList (up to order)" $+        \xs -> M.fromList (D.assocs (D.fromList xs))+            == M.fromList (xs :: [(String, Int)])+    , SC.testProperty+        "Number of states and transitions in a \"full\" langauge" $+          SC.changeDepth (+1) $ \n k ->+            let dawg = D.fromLang (genFull n k)+            in  D.numStates dawg == SC.getNonNegative k + 1 &&+                D.numEdges  dawg ==+                    SC.getPositive n * SC.getNonNegative k+    , SC.testProperty "Actual number of transitions == D.numEdges" $+        \xs -> let dawg = D.fromList (xs :: [(String, Int)])+                in S.size (walk dawg) == D.numEdges dawg+    , SC.testProperty "Actual number of states == D.numStates" $+        \xs -> let dawg = D.fromList (xs :: [(String, Int)])+                in D.numStates dawg ==+                    S.size (states (D.root dawg) (walk dawg))+    ]+++qcProps = testGroup "(checked by QuickCheck)"+    [ QC.testProperty "id == assocs . fromList (up to order)" $+        \xs -> M.fromList (D.assocs (D.fromList xs))+            == M.fromList (xs :: [(String, Int)])+    , QC.testProperty "Actual number of transitions == D.numEdges" $+        \xs -> let dawg = D.fromList (xs :: [(String, Int)])+                in S.size (walk dawg) == D.numEdges dawg+    , QC.testProperty "Actual number of states == D.numStates" $+        \xs -> let dawg = D.fromList (xs :: [(String, Int)])+                in D.numStates dawg ==+                    S.size (states (D.root dawg) (walk dawg))+    ]+++unitTests = testGroup "Unit tests"+    [ testCase "Size of a DAWG build from sample data" $ do+        let dawg = D.fromList dataSet1+        D.numStates dawg @?= 11+        D.numEdges dawg @?= 12+    ]+++---------------------------------------------------------------------+-- Sample Data+---------------------------------------------------------------------+++-- | Sample dataset no. 1.  See also `unitTests`.+dataSet1 :: [(String, Int)]+dataSet1 =+    [ ("asdf", 1)+    , ("asd", 1)+    , ("adf", 1)+    , ("df", 1)+    , ("asdfg", 3)+    , ("sdfg", 3) ]+++---------------------------------------------------------------------+-- Utils+---------------------------------------------------------------------+++-- | Generate a \"full\" language of words of length `k` over+-- an alphabet of size `n`.+genFull :: SC.Positive Int -> SC.NonNegative Int -> [[Int]]+genFull (SC.Positive n) (SC.NonNegative k) =+    genLang n k+  where+    genLang n 0 = [[]]+    genLang n k =+        [ x:xs+        | xs <- genLang n (k - 1)+        , x <- [1 .. n]]+++-- | Traverse the automaton and collect all the transitions.+walk :: Ord a => D.DAWG a b -> S.Set (D.ID, a, D.ID)+walk dawg =+    flip E.execState S.empty $+        flip E.evalStateT S.empty $+            doit (D.root dawg)+  where+    -- The embedded state serves to store the resulting set of+    -- transitions; the surface state serves to keep track of+    -- already visited nodes.+    doit i = do+        b <- E.gets $ S.member i+        E.when (not b) $ do+            E.modify $ S.insert i+            E.forM_ (D.edges i dawg) $ \(x, j) -> do+                E.lift . E.modify $ S.insert (i, x, j)+--                 E.lift . E.modify $ S.insert (i, j)+                doit j+++-- | Compute the set of states given the set of transitions and+-- the root ID.  It works under the assumption that all states+-- are reachable from the start state.+states :: Ord a => a -> S.Set (a, b, a) -> S.Set a+states rootID edgeSet = S.fromList $ rootID : concat+    [[i, j] | (i, _, j) <- S.toList edgeSet]