Copyright | (c) Wanja Chresta 2018 |
---|---|
License | GPL-3 |
Maintainer | wanja dot hs at chrummibei dot ch |
Stability | experimental |
Portability | POSIX |
Safe Haskell | None |
Language | Haskell2010 |
Math.Algebra.Code.Linear
Contents
Description
Naive implementation of coding theory linear codes and error correcting codes
over arbitrary fields, including finite fields. Goes well with the
HaskellForMath
library and its finite field implementations in
Math.Algebra.Field
. To use extension fields (fields of prime power, i.e.
\( F_{p^k} \) with \(k>1\), use one of the exported finite fields in
Math.Algebra.Field.Extension like F16
and its generator a16
.
As theoretical basis, Introduction to Coding Theory by Yehuda Lindell is used. It can be found at http://u.cs.biu.ac.il/~lindell/89-662/coding_theory-lecture-notes.pdf
Usage
>>> :set -XDataKinds >>> c <- randomIO :: IO (LinearCode 7 4 F5) >>> c [7,4]_5-Code >>> generatorMatrix c ( 1 0 1 0 0 2 0 ) ( 0 2 0 0 1 2 0 ) ( 0 1 0 1 0 1 0 ) ( 1 0 0 0 0 1 1 ) >>> e1 :: Vector 4 F5 ( 1 0 0 0 ) >>> v = encode c e1 >>> v ( 1 0 1 0 0 2 0 ) >>> 2 ^* e4 :: Vector 7 F3 ( 0 0 0 2 0 0 0 ) >>> vWithError = v + 2 ^* e4 >>> vWithError ( 1 0 1 2 0 2 0 ) >>> isCodeword c v True >>> isCodeword c vWithError False >>> decode c vWithError Just ( 1 0 2 2 2 2 0 )
Notice, the returned vector is NOT the one without error. The reason for this is that a random code most likely does not have a distance >2 which would be needed to correct one error. Let's try with a hamming code
>>> c = hamming :: BinaryCode 7 4 >>> generatorMatrix c ( 1 1 0 1 0 0 0 ) ( 1 0 1 0 1 0 0 ) ( 0 1 1 0 0 1 0 ) ( 1 1 1 0 0 0 1 ) >>> v = encode c e2 >>> vWithError = v + e3 >>> Just v' = decode c vWithError >>> v' == v True
- data LinearCode (n :: Nat) (k :: Nat) (f :: *) = LinearCode {
- generatorMatrix :: Generator n k f
- checkMatrix :: CheckMatrix n k f
- distance :: Maybe Int
- syndromeTable :: SyndromeTable n k f
- type Generator (n :: Nat) (k :: Nat) = Matrix k n
- type CheckMatrix (n :: Nat) (k :: Nat) = Matrix (n - k) n
- codeFromA :: forall k n f. (KnownNat n, KnownNat k, k <= n, Eq f, FinSet f, Num f, Ord f) => Matrix k (n - k) f -> LinearCode n k f
- codeFromAD :: forall k n f. (KnownNat n, KnownNat k, k <= n, Eq f, FinSet f, Num f, Ord f) => Maybe Int -> Matrix k (n - k) f -> LinearCode n k f
- standardForm :: forall n k f. (Eq f, Fractional f, KnownNat n, KnownNat k, k <= n) => Generator n k f -> Generator n k f
- standardFormGenerator :: forall n k f. (Eq f, Fractional f, KnownNat n, KnownNat k, k <= n) => LinearCode n k f -> Generator n k f
- type Vector = Matrix 1
- encode :: forall n k f. Num f => LinearCode n k f -> Vector k f -> Vector n f
- isCodeword :: forall n k f. (Eq f, Num f, KnownNat n, KnownNat k, k <= n) => LinearCode n k f -> Vector n f -> Bool
- hasError :: forall n k f. (Eq f, Num f, KnownNat n, KnownNat k, k <= n) => LinearCode n k f -> Vector n f -> Bool
- weight :: forall f m. (Eq f, Num f, Functor m, Foldable m) => m f -> Int
- codewords :: forall n k f. (KnownNat n, KnownNat k, k <= n, Num f, Eq f, FinSet f) => LinearCode n k f -> [Vector n f]
- allVectors :: forall n f. (KnownNat n, FinSet f, Num f, Eq f) => [Vector n f]
- fullVectors :: forall n f. (KnownNat n, FinSet f, Num f, Eq f) => [Vector n f]
- hammingWords :: forall n f. (KnownNat n, FinSet f, Num f, Eq f) => Int -> [Vector n f]
- lighterWords :: forall n f. (KnownNat n, FinSet f, Num f, Eq f) => Int -> [Vector n f]
- syndrome :: forall n k f. Num f => LinearCode n k f -> Vector n f -> Syndrome n k f
- decode :: forall n k f. (KnownNat n, KnownNat k, k <= n, Ord f, Num f) => LinearCode n k f -> Vector n f -> Maybe (Vector n f)
- syndromeDecode :: forall n k f. (KnownNat n, KnownNat k, k <= n, Ord f, Num f) => LinearCode n k f -> Vector n f -> Maybe (Vector n f)
- calcSyndromeTable :: forall n k f. (KnownNat n, KnownNat k, k <= n, Eq f, FinSet f, Num f, Ord f) => LinearCode n k f -> SyndromeTable n k f
- recalcSyndromeTable :: forall n k f. (KnownNat n, KnownNat k, k <= n, Eq f, FinSet f, Num f, Ord f) => LinearCode n k f -> LinearCode n k f
- type SyndromeTable n k f = Map (Syndrome n k f) (Vector n f)
- dualCode :: forall n k f. (KnownNat n, KnownNat k, k <= n, Eq f, FinSet f, Num f, Ord f) => LinearCode n k f -> LinearCode n (n - k) f
- dualCodeD :: forall n k f. (KnownNat n, KnownNat k, k <= n, Eq f, FinSet f, Num f, Ord f) => Maybe Int -> LinearCode n k f -> LinearCode n (n - k) f
- permuteCode :: forall n k f. (KnownNat n, KnownNat k, k <= n, Eq f, FinSet f, Num f, Ord f) => LinearCode n k f -> Matrix n n f -> LinearCode n k f
- extendCode :: forall n k f r. (KnownNat n, KnownNat k, KnownNat r, k <= n, 1 <= r, k <= (n + r), Num f, Ord f, FinSet f) => LinearCode n k f -> LinearCode (n + r) k f
- trivialCode :: forall n k f. (KnownNat n, KnownNat k, k <= n, Eq f, FinSet f, Num f, Ord f) => LinearCode n k f
- simplex :: forall k p s. (KnownNat s, KnownNat k, IntegerAsType p, 1 <= (s ^ k), k <= (s ^ k), (1 + k) <= (s ^ k), Size (Fp p) ~ s) => LinearCode ((s ^ k) - 1) k (Fp p)
- hamming :: (KnownNat m, 2 <= m, m <= (2 ^ m), (1 + m) <= (2 ^ m)) => LinearCode ((2 ^ m) - 1) (((2 ^ m) - m) - 1) F2
- golay :: LinearCode 23 12 F2
- type BinaryCode n k = LinearCode n k F2
- randomPermMatrix :: forall g n r. (KnownNat n, Num r, RandomGen g) => g -> (Matrix n n r, g)
- codeLength :: forall n k f. KnownNat n => LinearCode n k f -> Int
- rank :: forall n k f. KnownNat k => LinearCode n k f -> Int
- eVec :: forall n f. (KnownNat n, Num f) => Int -> Vector n f
- e1 :: forall n f. (KnownNat n, Num f) => Vector n f
- e2 :: forall n f. (KnownNat n, Num f) => Vector n f
- e3 :: forall n f. (KnownNat n, Num f) => Vector n f
- e4 :: forall n f. (KnownNat n, Num f) => Vector n f
- e5 :: forall n f. (KnownNat n, Num f) => Vector n f
- e6 :: forall n f. (KnownNat n, Num f) => Vector n f
- e7 :: forall n f. (KnownNat n, Num f) => Vector n f
- e8 :: forall n f. (KnownNat n, Num f) => Vector n f
- e9 :: forall n f. (KnownNat n, Num f) => Vector n f
- e10 :: forall n f. (KnownNat n, Num f) => Vector n f
- char :: forall c f. (KnownNat c, c ~ Characteristic f) => Proxy f -> Int
- matrix :: forall m n a. (KnownNat m, KnownNat n) => ((Int, Int) -> a) -> Matrix (m :: Nat) (n :: Nat) a
- zero :: forall m n a. (Num a, KnownNat n, KnownNat m) => Matrix m n a
- transpose :: forall m n a. Matrix m n a -> Matrix n m a
- fromList :: forall m n a. (KnownNat m, KnownNat n) => [a] -> Matrix m n a
- fromLists :: forall m n a. (KnownNat m, KnownNat n) => [[a]] -> Matrix m n a
- type F2 = Fp T2
- type F3 = Fp T3
- type F5 = Fp T5
- type F7 = Fp T7
- type F11 = Fp T11
- type F4 = ExtensionField F2 ConwayF4
- type F8 = ExtensionField F2 ConwayF8
- type F16 = ExtensionField F2 ConwayF16
- type F9 = ExtensionField F3 ConwayF9
Documentation
data LinearCode (n :: Nat) (k :: Nat) (f :: *) Source #
A \([n,k]\)-Linear code over the field f
. The code parameters f
,n
and
k
are carried on the type level.
A linear code is a subspace C
of \(f^n\) generated by the generator matrix.
Constructors
LinearCode | |
Fields
|
Instances
(KnownNat n, KnownNat k, (<=) k n, Eq f, FinSet f, Num f, Ord f) => Bounded (LinearCode n k f) Source # | |
(Eq f, Fractional f, KnownNat n, KnownNat k, (<=) k n) => Eq (LinearCode n k f) Source # | |
(KnownNat n, KnownNat k, KnownNat (Characteristic f)) => Show (LinearCode n k f) Source # | |
(KnownNat n, KnownNat k, (<=) k n, Eq f, FinSet f, Num f, Ord f, Random f) => Random (LinearCode n k f) Source # | |
type Generator (n :: Nat) (k :: Nat) = Matrix k n Source #
A Generator
is the generator matrix of a linear code, not necessarily
in standard form.
type CheckMatrix (n :: Nat) (k :: Nat) = Matrix (n - k) n Source #
A CheckMatrix
or parity matrix is the dual of a Generator
. It can
be used to check if a word is a valid code word for the code. Also,
\[ \forall v \in f^k: cG \cdot H^\top = 0 \]
i.e. the code is generated by the kernel of a check matrix.
Arguments
:: (KnownNat n, KnownNat k, k <= n, Eq f, FinSet f, Num f, Ord f) | |
=> Matrix k (n - k) f | Elements of A where top-left is (1,1) and bottom right (k,n-k) |
-> LinearCode n k f |
Generate a linear \( [n,k]_q \)-Code over the field f
with the
generator in standard form (I|A)
, where the given function generates
the \( k \times (n-k) \)-matrix A.
The distance is unknown for this code and thus decoding algorithms may
be very inefficient.
Arguments
:: (KnownNat n, KnownNat k, k <= n, Eq f, FinSet f, Num f, Ord f) | |
=> Maybe Int | Distance of the code. Give Nothing if it is unknown |
-> Matrix k (n - k) f | Elements of A where top-left is (1,1) and bottom right (k,n-k) |
-> LinearCode n k f |
Generate a linear \( [n,k,d]_q \)-Code over the field f
with the
generator in standard form (I|A)
, where the given function generates
the \( k \times (n-k) \)-matrix A.
standardForm :: forall n k f. (Eq f, Fractional f, KnownNat n, KnownNat k, k <= n) => Generator n k f -> Generator n k f Source #
standardFormGenerator :: forall n k f. (Eq f, Fractional f, KnownNat n, KnownNat k, k <= n) => LinearCode n k f -> Generator n k f Source #
The standard from generator of a linear code. Uses standardForm
to
calculate a standard form generator.
Code-Vectors and codewords
encode :: forall n k f. Num f => LinearCode n k f -> Vector k f -> Vector n f Source #
Get the codeword generated by the given k-sized vector.
isCodeword :: forall n k f. (Eq f, Num f, KnownNat n, KnownNat k, k <= n) => LinearCode n k f -> Vector n f -> Bool Source #
Check if the given candidate code word is a valid code word for the given linear code. If not, the party check failed.
hasError :: forall n k f. (Eq f, Num f, KnownNat n, KnownNat k, k <= n) => LinearCode n k f -> Vector n f -> Bool Source #
Check if the given candidate code word has errors, i.e. if some element
changed during transmission. This is equivalent with not
isCodeword
weight :: forall f m. (Eq f, Num f, Functor m, Foldable m) => m f -> Int Source #
The hamming weight of a Vector is an Int
between 0 and n
codewords :: forall n k f. (KnownNat n, KnownNat k, k <= n, Num f, Eq f, FinSet f) => LinearCode n k f -> [Vector n f] Source #
A list of all codewords
allVectors :: forall n f. (KnownNat n, FinSet f, Num f, Eq f) => [Vector n f] Source #
List all vectors of length n over field f
fullVectors :: forall n f. (KnownNat n, FinSet f, Num f, Eq f) => [Vector n f] Source #
List all vectors of length n with non-zero elements over field f
hammingWords :: forall n f. (KnownNat n, FinSet f, Num f, Eq f) => Int -> [Vector n f] Source #
List of all words with given hamming weight
lighterWords :: forall n f. (KnownNat n, FinSet f, Num f, Eq f) => Int -> [Vector n f] Source #
List of all words with (non-zero) hamming weight smaller than a given boundary
Decoding
syndrome :: forall n k f. Num f => LinearCode n k f -> Vector n f -> Syndrome n k f Source #
Give the syndrome of a word for the given code. This is 0 if the word is a valid code word.
decode :: forall n k f. (KnownNat n, KnownNat k, k <= n, Ord f, Num f) => LinearCode n k f -> Vector n f -> Maybe (Vector n f) Source #
Synonym for syndromeDecoding, an inefficient decoding algorithm that works for all linear codes.
syndromeDecode :: forall n k f. (KnownNat n, KnownNat k, k <= n, Ord f, Num f) => LinearCode n k f -> Vector n f -> Maybe (Vector n f) Source #
Uses the exponential-time syndrome decoding algorithm for general codes. c.f: https://en.wikipedia.org/wiki/Decoding_methods#Syndrome_decoding
calcSyndromeTable :: forall n k f. (KnownNat n, KnownNat k, k <= n, Eq f, FinSet f, Num f, Ord f) => LinearCode n k f -> SyndromeTable n k f Source #
Return a syndrome table for the given linear code. If the distance is not
known (i.e. minDist
c
= Nothing) this is very inefficient.
recalcSyndromeTable :: forall n k f. (KnownNat n, KnownNat k, k <= n, Eq f, FinSet f, Num f, Ord f) => LinearCode n k f -> LinearCode n k f Source #
Replace the syndromeTable
of a code with a newly calculated syndrome
table for the (current) generator. Useful to get a syndrome table for
transformed codes when the table cannot be transformed, too.
type SyndromeTable n k f = Map (Syndrome n k f) (Vector n f) Source #
A syndrome table is a map from syndromes to their minimal weight
representative. Every vector v
has a syndrome \( S(v) \). This table
reverses the syndrome function S
and chooses the vector with the smallest
hamming weight from it's image. This is a lookup table for syndrome
decoding.
Code transformers
dualCode :: forall n k f. (KnownNat n, KnownNat k, k <= n, Eq f, FinSet f, Num f, Ord f) => LinearCode n k f -> LinearCode n (n - k) f Source #
The dual code is the code generated by the check matrix
This drops already calculated syndromeTables.
Arguments
:: (KnownNat n, KnownNat k, k <= n, Eq f, FinSet f, Num f, Ord f) | |
=> Maybe Int | The distance of the new code (if known) or Nothing |
-> LinearCode n k f | |
-> LinearCode n (n - k) f |
The dual code is the code generated by the check matrix.
This drops already calculated syndromeTables.
permuteCode :: forall n k f. (KnownNat n, KnownNat k, k <= n, Eq f, FinSet f, Num f, Ord f) => LinearCode n k f -> Matrix n n f -> LinearCode n k f Source #
Permute the rows of a code with a permutation matrix. The given permutation matrix must be a valid permutation matrix; this is not checked. This effectively multiplies the generator and check matrix from the right. Te distance of the resulting code stays the same.
This drops already calculated syndromeTables.
extendCode :: forall n k f r. (KnownNat n, KnownNat k, KnownNat r, k <= n, 1 <= r, k <= (n + r), Num f, Ord f, FinSet f) => LinearCode n k f -> LinearCode (n + r) k f Source #
Extend the given code \( c \) by zero-columns. Vectors \( v_{ext} \in c_{ext} \) have the form \( v = (v_1, \dots , v_n, 0, \dots, 0) \) . The distance of the extended code stays the same. This drops a calculated syndromeTable and makes it necessary to recalculate it if it's accessed.
Special codes and their generators
trivialCode :: forall n k f. (KnownNat n, KnownNat k, k <= n, Eq f, FinSet f, Num f, Ord f) => LinearCode n k f Source #
The trivial code is the identity code where the parity bits are all zero.
simplex :: forall k p s. (KnownNat s, KnownNat k, IntegerAsType p, 1 <= (s ^ k), k <= (s ^ k), (1 + k) <= (s ^ k), Size (Fp p) ~ s) => LinearCode ((s ^ k) - 1) k (Fp p) Source #
A simplex code is a code generated by all possible codewords consisting of 0's and 1's except the zero vector.
hamming :: (KnownNat m, 2 <= m, m <= (2 ^ m), (1 + m) <= (2 ^ m)) => LinearCode ((2 ^ m) - 1) (((2 ^ m) - m) - 1) F2 Source #
The Hamming(7,4)-code. It is a [7,4,3]_2 code
golay :: LinearCode 23 12 F2 Source #
The _Golay_-code is a perfect [24,12,7]-code. It is the only other non-trivial perfect code and the only perfect code that is able to correct 3 errors.
Syndrome decoding on this code takes a very, very long time.
type BinaryCode n k = LinearCode n k F2 Source #
A binary code is a linear code over the field GF(2)
Helper functions
randomPermMatrix :: forall g n r. (KnownNat n, Num r, RandomGen g) => g -> (Matrix n n r, g) Source #
A random permutation matrix
codeLength :: forall n k f. KnownNat n => LinearCode n k f -> Int Source #
Convenience function to extract the length n
from the type level
rank :: forall n k f. KnownNat k => LinearCode n k f -> Int Source #
Convenience function to extract the rank k
from the type level.
eVec :: forall n f. (KnownNat n, Num f) => Int -> Vector n f Source #
Standard base vector [0..0,1,0..0] for any field. Parameter must be >=1
char :: forall c f. (KnownNat c, c ~ Characteristic f) => Proxy f -> Int Source #
Characteristic of a field. It takes a finite field type in the proxy
value and gives the characteristic. This is done using type families
To support new finite field types, you need to add a type instance
for the type family Characteristic
.
Reexported matrix functions from Math.Algebra.Matrix
matrix :: forall m n a. (KnownNat m, KnownNat n) => ((Int, Int) -> a) -> Matrix (m :: Nat) (n :: Nat) a Source #
O(rows*cols). Generate a matrix from a generator function.
| The elements are 1-indexed, i.e. top-left element is (1,1)
.
zero :: forall m n a. (Num a, KnownNat n, KnownNat m) => Matrix m n a Source #
O(rows*cols). The zero matrix
transpose :: forall m n a. Matrix m n a -> Matrix n m a Source #
O(rows*cols). The transpose of a matrix.
fromList :: forall m n a. (KnownNat m, KnownNat n) => [a] -> Matrix m n a Source #
Create a matrix from a list of elements.
The list must have exactly length n*m
. This is checked or else an
exception is thrown.
fromLists :: forall m n a. (KnownNat m, KnownNat n) => [[a]] -> Matrix m n a Source #
Create a matrix from a list of rows. The list must have exactly m
lists of length n
. An exception is thrown otherwise.