77 lines
2.6 KiB
Haskell
77 lines
2.6 KiB
Haskell
module GF2test (run) where
|
|
|
|
import Data.Bits (xor)
|
|
import Data.List (foldl')
|
|
import Test.HUnit
|
|
|
|
import LinearAlgebra.GF2
|
|
( fromBools
|
|
, gaussianEliminationAllMasks
|
|
, maskToIndicesInt
|
|
)
|
|
|
|
-- XOR of the rows selected by a mask
|
|
xorSelected :: [Integer] -> [Int] -> Integer
|
|
xorSelected rows idxs = foldl' xor 0 [ rows !! i | i <- idxs ]
|
|
|
|
run :: IO ()
|
|
run = do
|
|
putStrLn "GF2 Gaussian elimination test"
|
|
|
|
-- one dependency: rows 0, 1 and 3 XOR to zero
|
|
let rowsBits =
|
|
map fromBools
|
|
[ [True, False, True]
|
|
, [False, True, True]
|
|
, [True, True, True]
|
|
, [True, True, False]
|
|
]
|
|
masks = gaussianEliminationAllMasks rowsBits
|
|
|
|
assertEqual "expected exactly one dependency" 1 (length masks)
|
|
assertEqual "expected rows 0,1,3" [[0,1,3]] (map maskToIndicesInt masks)
|
|
|
|
-- no dependency case: the three rows are independent
|
|
let rowsBits2 =
|
|
map fromBools
|
|
[ [True, False, True]
|
|
, [False, True, True]
|
|
, [True, True, True]
|
|
]
|
|
|
|
assertEqual "Expected no dependency" [] (gaussianEliminationAllMasks rowsBits2)
|
|
|
|
-- several dependencies: 5 rows of rank 2 give a null space of dimension 3
|
|
let rowsBits3 =
|
|
map fromBools
|
|
[ [True, False, True] -- a
|
|
, [False, True, True] -- b
|
|
, [True, True, False] -- a xor b
|
|
, [True, False, True] -- a again
|
|
, [False, False, False] -- zero row
|
|
]
|
|
masks3 = gaussianEliminationAllMasks rowsBits3
|
|
idxs3 = map maskToIndicesInt masks3
|
|
|
|
assertEqual "expected rows - rank = 3 dependencies" 3 (length masks3)
|
|
assertBool "every dependency must XOR to zero"
|
|
(all (\ix -> xorSelected rowsBits3 ix == 0) idxs3)
|
|
assertBool "no dependency may be empty" (all (not . null) idxs3)
|
|
assertBool "the zero row (index 4) must be a dependency on its own" ([4] `elem` idxs3)
|
|
|
|
-- the dependencies must be linearly independent (distinct and non-zero masks)
|
|
assertEqual "dependencies must be pairwise distinct" (length masks3) (length (dedup masks3))
|
|
|
|
-- a repeated row is a dependency of size two
|
|
let rowsBits4 = map fromBools [ [True, False], [False, True], [True, False] ]
|
|
assertEqual "duplicate row dependency" [[0,2]]
|
|
(map maskToIndicesInt (gaussianEliminationAllMasks rowsBits4))
|
|
|
|
-- empty input
|
|
assertEqual "no rows, no dependency" [] (gaussianEliminationAllMasks [])
|
|
|
|
putStrLn "GF2 test done."
|
|
where
|
|
dedup [] = []
|
|
dedup (x : xs) = x : dedup (filter (/= x) xs)
|