@@ -943,13 +943,13 @@ def add_decoder(self, name, decoder):
943
943
944
944
sage: C.add_decoder("MyDecoder", MyDecoder)
945
945
sage: C.decoders_available()
946
- ['MyDecoder', 'Syndrome', 'NearestNeighbor']
946
+ ['MyDecoder', 'InformationSet', ' Syndrome', 'NearestNeighbor']
947
947
948
948
We can verify that any new code will not know MyDecoder::
949
949
950
950
sage: C2 = codes.HammingCode(3, GF(3))
951
951
sage: C2.decoders_available()
952
- ['Syndrome', 'NearestNeighbor']
952
+ ['InformationSet', ' Syndrome', 'NearestNeighbor']
953
953
954
954
TESTS:
955
955
@@ -1649,7 +1649,7 @@ def decode_to_code(self, word, decoder_name=None, **kwargs):
1649
1649
It is possible to manually choose the decoder amongst the list of the available ones::
1650
1650
1651
1651
sage: C.decoders_available()
1652
- ['Syndrome', 'NearestNeighbor']
1652
+ ['InformationSet', ' Syndrome', 'NearestNeighbor']
1653
1653
sage: C.decode_to_code(w_err, 'NearestNeighbor')
1654
1654
(1, 1, 0, 0, 1, 1, 0)
1655
1655
"""
@@ -1686,7 +1686,7 @@ def decode_to_message(self, word, decoder_name=None, **kwargs):
1686
1686
It is possible to manually choose the decoder amongst the list of the available ones::
1687
1687
1688
1688
sage: C.decoders_available()
1689
- ['Syndrome', 'NearestNeighbor']
1689
+ ['InformationSet', ' Syndrome', 'NearestNeighbor']
1690
1690
sage: C.decode_to_message(word, 'NearestNeighbor')
1691
1691
(0, 1, 1, 0)
1692
1692
"""
@@ -1726,7 +1726,7 @@ def decoder(self, decoder_name=None, **kwargs):
1726
1726
an exception will be raised::
1727
1727
1728
1728
sage: C.decoders_available()
1729
- ['Syndrome', 'NearestNeighbor']
1729
+ ['InformationSet', ' Syndrome', 'NearestNeighbor']
1730
1730
sage: C.decoder('Try')
1731
1731
Traceback (most recent call last):
1732
1732
...
@@ -1755,10 +1755,11 @@ def decoders_available(self, classes=False):
1755
1755
sage: G = Matrix(GF(2), [[1,1,1,0,0,0,0],[1,0,0,1,1,0,0],[0,1,0,1,0,1,0],[1,1,0,1,0,0,1]])
1756
1756
sage: C = LinearCode(G)
1757
1757
sage: C.decoders_available()
1758
- ['Syndrome', 'NearestNeighbor']
1758
+ ['InformationSet', ' Syndrome', 'NearestNeighbor']
1759
1759
1760
1760
sage: C.decoders_available(True)
1761
- {'NearestNeighbor': <class 'sage.coding.linear_code.LinearCodeNearestNeighborDecoder'>,
1761
+ {'InformationSet': <class 'sage.coding.linear_code.LinearCodeInformationSetDecoder'>,
1762
+ 'NearestNeighbor': <class 'sage.coding.linear_code.LinearCodeNearestNeighborDecoder'>,
1762
1763
'Syndrome': <class 'sage.coding.linear_code.LinearCodeSyndromeDecoder'>}
1763
1764
"""
1764
1765
if classes == True :
@@ -3008,9 +3009,10 @@ def random_element(self, *args, **kwds):
3008
3009
True
3009
3010
3010
3011
"""
3011
- V = self .ambient_space ()
3012
- S = V .subspace (self .basis ())
3013
- c = S .random_element (* args , ** kwds )
3012
+ E = self .encoder ()
3013
+ M = E .message_space ()
3014
+ m = M .random_element (* args , ** kwds )
3015
+ c = E .encode (m )
3014
3016
c .set_immutable ()
3015
3017
return c
3016
3018
@@ -4532,6 +4534,192 @@ def decoding_radius(self):
4532
4534
"""
4533
4535
return (self .code ().minimum_distance ()- 1 ) // 2
4534
4536
4537
+
4538
+
4539
+
4540
+
4541
+
4542
+
4543
+
4544
+
4545
+
4546
+ class LinearCodeInformationSetDecoder (Decoder ):
4547
+ r"""
4548
+ Construct a decoder for Linear Codes. This decoder use the probabilistic
4549
+ information set decoding algorithm. Details follow.
4550
+
4551
+ This decoder is based on the Lee-Brickell refinement of the information set
4552
+ decoding algorithm, as described in [P10]:
4553
+
4554
+ Let `p` and `w` be integers, such that `0\leq p\leq w`, let
4555
+ `y` be a vector over some vector space `GF(q)^{n}` and let `C` be
4556
+ a `[n, k]`-linear code over `GF(q)`.
4557
+ Let `G` be a generator matrix of `C`, and `G_{I}` a matrix formed by
4558
+ the columns of `G` indexed by `I`.
4559
+ To correct exactly `w` errors in `y`, proceed as follows:
4560
+
4561
+ 1. Choose a information set `I` of `C`.
4562
+ 2. Compute `yc = y - y_{I}\times G^{-1} \times G`
4563
+ 3. Consider every size-`p` subset of `I` `\{a_1, \dots, a_p\}`.
4564
+ For each `m= (m_1, \dots, m_p) \in GF(q)^{p}`, compute
4565
+ the error vector `e = yc - \sum_{i=1}^{p} m_i\times g_{a_i}`,
4566
+ 4. If `e` has a Hamming weight of `w`, it's the right error vector,
4567
+ thus return `y-e`.
4568
+ Else, go back to 1.
4569
+
4570
+
4571
+
4572
+ REFERENCES:
4573
+
4574
+ - [P10] Christiane Peters, Information-set decoding for linear codes over Fq, 2010
4575
+
4576
+ INPUT:
4577
+
4578
+ - ``code`` -- A code associated to this decoder
4579
+ """
4580
+
4581
+ def __init__ (self , code ):
4582
+ r"""
4583
+ EXAMPLES::
4584
+
4585
+ sage: G = Matrix(GF(2), [[1,1,1,0,0,0,0],[1,0,0,1,1,0,0],[0,1,0,1,0,1,0],[1,1,0,1,0,0,1]])
4586
+ sage: C = LinearCode(G)
4587
+ sage: D = codes.decoders.LinearCodeInformationSetDecoder(C)
4588
+ sage: D
4589
+ Information set decoder for Linear code of length 7, dimension 4 over Finite Field of size 2
4590
+ """
4591
+ super (LinearCodeInformationSetDecoder , self ).__init__ (code , code .ambient_space (), \
4592
+ code ._default_encoder_name )
4593
+
4594
+ def __eq__ (self , other ):
4595
+ r"""
4596
+ Tests equality between LinearCodeInformationSetDecoder objects.
4597
+
4598
+ EXAMPLES::
4599
+
4600
+ sage: G = Matrix(GF(2), [[1,1,1,0,0,0,0],[1,0,0,1,1,0,0],[0,1,0,1,0,1,0],[1,1,0,1,0,0,1]])
4601
+ sage: D1 = codes.decoders.LinearCodeInformationSetDecoder(LinearCode(G))
4602
+ sage: D2 = codes.decoders.LinearCodeInformationSetDecoder(LinearCode(G))
4603
+ sage: D1 == D2
4604
+ True
4605
+ """
4606
+ return isinstance (other , LinearCodeInformationSetDecoder )\
4607
+ and self .code () == other .code ()
4608
+
4609
+ def _repr_ (self ):
4610
+ r"""
4611
+ Returns a string representation of ``self``.
4612
+
4613
+ EXAMPLES::
4614
+
4615
+ sage: G = Matrix(GF(2), [[1,1,1,0,0,0,0],[1,0,0,1,1,0,0],[0,1,0,1,0,1,0],[1,1,0,1,0,0,1]])
4616
+ sage: C = LinearCode(G)
4617
+ sage: D = codes.decoders.LinearCodeInformationSetDecoder(C)
4618
+ sage: D
4619
+ Information set decoder for Linear code of length 7, dimension 4 over Finite Field of size 2
4620
+ """
4621
+ return "Information set decoder for %s" % self .code ()
4622
+
4623
+ def _latex_ (self ):
4624
+ r"""
4625
+ Returns a latex representation of ``self``.
4626
+
4627
+ EXAMPLES::
4628
+
4629
+ sage: G = Matrix(GF(2), [[1,1,1,0,0,0,0],[1,0,0,1,1,0,0],[0,1,0,1,0,1,0],[1,1,0,1,0,0,1]])
4630
+ sage: C = LinearCode(G)
4631
+ sage: D = codes.decoders.LinearCodeInformationSetDecoder(C)
4632
+ sage: latex(D)
4633
+ \textnormal{Information set decoder for }[7, 4]\textnormal{ Linear code over }\Bold{F}_{2}
4634
+ """
4635
+ return "\\ textnormal{Information set decoder for }%s" % self .code ()._latex_ ()
4636
+
4637
+ def decode_to_code (self , r , p , w ):
4638
+ r"""
4639
+ Decodes ``r`` to an element in the associated code of ``self``.
4640
+
4641
+ One has to provide ``w``, the number of errors which ``r`` contains.
4642
+
4643
+ INPUT:
4644
+
4645
+ - ``r`` -- a received word, i.e. a vector in the ambient space of
4646
+ :meth:`decoder.Decoder.code`.
4647
+
4648
+ - ``p`` -- the window size parameter, i.e. an integer smaller than ``w``.
4649
+
4650
+ - ``w`` -- the number of errors, i.e. an integer smaller than
4651
+ :meth:`sage.coding.decoder.Decoder.code`'s length.
4652
+
4653
+ OUTPUT:
4654
+
4655
+ - a codeword of the associated code of ``self``
4656
+
4657
+ EXAMPLES::
4658
+
4659
+ sage: C = codes.RandomLinearCode(10, 5, GF(2))
4660
+ sage: D = C.decoder('InformationSet')
4661
+ sage: c = C.random_element()
4662
+ sage: Chan = channels.StaticErrorRateChannel(C.ambient_space(), 3)
4663
+ sage: y = Chan(c)
4664
+ sage: c == D.decode_to_code(y, 2, 3)
4665
+ True
4666
+ """
4667
+ from sage .matrix .constructor import column_matrix
4668
+ C = self .code ()
4669
+ n , k = C .length (), C .dimension ()
4670
+ if not isinstance (p , (Integer , int )) or p < 0 :
4671
+ raise ValueError ("The window size parameter has to be either a positive Sage integer or a Python int" )
4672
+ if not isinstance (w , (Integer , int )) or w < 0 :
4673
+ raise ValueError ("The provided number of errors has to be either a positive Sage integer or a Python int" )
4674
+ if p > w :
4675
+ raise ValueError ("The window size parameter has to be at most the provided number of errors" )
4676
+ if w > n :
4677
+ raise ValueError ("The provided number of errors has to be at most the code's length" )
4678
+ if w == 0 :
4679
+ return r
4680
+ F = C .base_ring ()
4681
+ one = F .one ()
4682
+ G = C .generator_matrix ()
4683
+ columns = G .columns ()
4684
+ l = F .list ()
4685
+ #We define an iterator over the possible information sets
4686
+ I = iter (Subsets (range (n ), k ))
4687
+ while (True ):
4688
+ try :
4689
+ information_set = list (I .next ())
4690
+ columns = [G .column (i ) for i in information_set ]
4691
+ Gi = column_matrix (columns )
4692
+ try :
4693
+ Gi_G = Gi .inverse () * G
4694
+ rc = copy (r )
4695
+ #At every iteration, we will need the row corresponding
4696
+ #to the index where Gi_G's i-th column has a one.
4697
+ #We store this in a dictionary to save later computation.
4698
+ gs = dict ()
4699
+ for i in information_set :
4700
+ gs [i ] = Gi_G .row (list (Gi_G .column (i )).index (one ))
4701
+
4702
+ m = iter (VectorSpace (F , p ))
4703
+ for i in Subsets (information_set , p ):
4704
+ ind = 0
4705
+ v = vector (F , n )
4706
+ while (True ):
4707
+ try :
4708
+ j = m .next ()
4709
+ v += j [ind ] * gs [i [ind ]]
4710
+ if (rc - v ).hamming_weight () == w :
4711
+ return r - (rc - v )
4712
+ ind = (ind + 1 ) % p
4713
+ except StopIteration :
4714
+ break
4715
+ except ZeroDivisionError :
4716
+ #in that case Gi was not invertible
4717
+ #thus I was not an information set
4718
+ pass
4719
+ except StopIteration :
4720
+ raise DecodingError
4721
+
4722
+
4535
4723
####################### registration ###############################
4536
4724
4537
4725
LinearCode ._registered_encoders ["GeneratorMatrix" ] = LinearCodeGeneratorMatrixEncoder
@@ -4540,3 +4728,5 @@ def decoding_radius(self):
4540
4728
LinearCodeSyndromeDecoder ._decoder_type = {"hard-decision" , "unique" , "dynamic" }
4541
4729
LinearCode ._registered_decoders ["NearestNeighbor" ] = LinearCodeNearestNeighborDecoder
4542
4730
LinearCodeNearestNeighborDecoder ._decoder_type = {"hard-decision" , "unique" , "always-succeed" , "complete" }
4731
+ LinearCode ._registered_decoders ["InformationSet" ] = LinearCodeInformationSetDecoder
4732
+ LinearCodeNearestNeighborDecoder ._decoder_type = {"hard-decision" , "unique" , "always-succeed" , "complete" }
0 commit comments