def coset_leader(C, v): """ The vector v represents a received word, so should be in the same ambient space V as C. Returns an element of the syndrome of v of lowest weight. EXAMPLES: sage: C = HammingCode(2,GF(3)); C Linear code of length 4, dimension 2 over Finite Field of size 3 sage: V = VectorSpace(GF(3), 4) sage: v = V([0, 2, 0, 1]) sage: from sage.coding.decoder import coset_leader sage: coset_leader(C, v) ((0, 0, 1, 0), 1) sage: coset_leader(C, v)[0]-v in C True """ coset = [[c+v, hamming_weight(c+v)] for c in C] wts = [x[1] for x in coset] min_wt = min(wts) s = C[0] # initializing w = hamming_weight(v) # initializing for x in coset: if x[1]==min_wt: w = x[1] s = x[0] break return s,w
def coset_leader(C, v): """ The vector v represents a received word, so should be in the same ambient space V as C. Returns an element of the syndrome of v of lowest weight. EXAMPLES: sage: C = HammingCode(2,GF(3)); C Linear code of length 4, dimension 2 over Finite Field of size 3 sage: V = VectorSpace(GF(3), 4) sage: v = V([0, 2, 0, 1]) sage: from sage.coding.decoder import coset_leader sage: coset_leader(C, v) ((0, 0, 1, 0), 1) sage: coset_leader(C, v)[0]-v in C True """ coset = [[c + v, hamming_weight(c + v)] for c in C] wts = [x[1] for x in coset] min_wt = min(wts) s = C[0] # initializing w = hamming_weight(v) # initializing for x in coset: if x[1] == min_wt: w = x[1] s = x[0] break return s, w
def decode(C, v, algorithm="syndrome"): """ The vector v represents a received word, so should be in the same ambient space V as C. Returns an element in C which is closest to v in the Hamming metric. Methods implemented include "nearest neighbor" (essentially a brute force search) and "syndrome". EXAMPLES: sage: C = HammingCode(2,GF(3)) sage: V = VectorSpace(GF(3), 4) sage: v = V([0, 2, 0, 1]) sage: v in C False sage: from sage.coding.decoder import decode sage: c = decode(C, v);c (0, 2, 2, 1) sage: c in C True sage: c = decode(C, v, algorithm="nearest neighbor");c (0, 2, 2, 1) sage: C = HammingCode(3,GF(3)); C Linear code of length 13, dimension 10 over Finite Field of size 3 sage: V = VectorSpace(GF(3), 13) sage: v = V([2]+[0]*12) sage: decode(C, v) # long time (9s on sage.math, 2011) (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) """ V = C.ambient_space() if not(type(v)==list): v = v.list() v = V(v) if algorithm=="nearest neighbor": diffs = [[c-v,hamming_weight(c-v)] for c in C] diffs.sort(lambda x,y: x[1]-y[1]) return diffs[0][0]+v if algorithm=="syndrome": return -V(syndrome(C, v)[0])+v
def decode(C, v, algorithm="syndrome"): """ The vector v represents a received word, so should be in the same ambient space V as C. Returns an element in C which is closest to v in the Hamming metric. Methods implemented include "nearest neighbor" (essentially a brute force search) and "syndrome". EXAMPLES: sage: C = HammingCode(2,GF(3)) sage: V = VectorSpace(GF(3), 4) sage: v = V([0, 2, 0, 1]) sage: v in C False sage: from sage.coding.decoder import decode sage: c = decode(C, v);c (0, 2, 2, 1) sage: c in C True sage: c = decode(C, v, algorithm="nearest neighbor");c (0, 2, 2, 1) sage: C = HammingCode(3,GF(3)); C Linear code of length 13, dimension 10 over Finite Field of size 3 sage: V = VectorSpace(GF(3), 13) sage: v = V([2]+[0]*12) sage: decode(C, v) # long time (9s on sage.math, 2011) (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) """ V = C.ambient_space() if not (type(v) == list): v = v.list() v = V(v) if algorithm == "nearest neighbor": diffs = [[c - v, hamming_weight(c - v)] for c in C] diffs.sort(lambda x, y: x[1] - y[1]) return diffs[0][0] + v if algorithm == "syndrome": return -V(syndrome(C, v)[0]) + v
def syndrome(C, v): """ The vector v represents a received word, so should be in the same ambient space V as C. Returns the elements in V (including v) which belong to the syndrome of v (ie, the coset v+C, sorted by weight). EXAMPLES: sage: C = HammingCode(2,GF(3)); C Linear code of length 4, dimension 2 over Finite Field of size 3 sage: V = VectorSpace(GF(3), 4) sage: v = V([0, 2, 0, 1]) sage: from sage.coding.decoder import syndrome sage: syndrome(C, v) [(0, 0, 1, 0), (0, 2, 0, 1), (2, 0, 0, 2), (1, 1, 0, 0), (2, 2, 2, 0), (1, 0, 2, 1), (0, 1, 2, 2), (1, 2, 1, 2), (2, 1, 1, 1)] """ V = C.ambient_space() if not(type(v)==list): v = v.list() v = V(v) coset = [[c+v,hamming_weight(c+v)] for c in C] coset.sort(lambda x,y: x[1]-y[1]) return [x[0] for x in coset]
def syndrome(C, v): """ The vector v represents a received word, so should be in the same ambient space V as C. Returns the elements in V (including v) which belong to the syndrome of v (ie, the coset v+C, sorted by weight). EXAMPLES: sage: C = HammingCode(2,GF(3)); C Linear code of length 4, dimension 2 over Finite Field of size 3 sage: V = VectorSpace(GF(3), 4) sage: v = V([0, 2, 0, 1]) sage: from sage.coding.decoder import syndrome sage: syndrome(C, v) [(0, 0, 1, 0), (0, 2, 0, 1), (2, 0, 0, 2), (1, 1, 0, 0), (2, 2, 2, 0), (1, 0, 2, 1), (0, 1, 2, 2), (1, 2, 1, 2), (2, 1, 1, 1)] """ V = C.ambient_space() if not (type(v) == list): v = v.list() v = V(v) coset = [[c + v, hamming_weight(c + v)] for c in C] coset.sort(lambda x, y: x[1] - y[1]) return [x[0] for x in coset]
def is_block_design(self): """ Returns a pair True, pars if the incidence structure is a t-design, for some t, where pars is the list of parameters [t, v, k, lmbda]. The largest possible t is returned, provided t=10. EXAMPLES:: sage: BD = IncidenceStructure(range(7),[[0,1,2],[0,3,4],[0,5,6],[1,3,5],[1,4,6],[2,3,6],[2,4,5]]) sage: BD.is_block_design() (True, [2, 7, 3, 1]) sage: BD.block_design_checker(2, 7, 3, 1) True sage: BD = WittDesign(9) # requires optional gap package 'design' sage: BD.is_block_design() # requires optional gap package 'design' (True, [2, 9, 3, 1]) sage: BD = WittDesign(12) # requires optional gap package 'design' sage: BD.is_block_design() # requires optional gap package 'design' (True, [5, 12, 6, 1]) sage: BD = AffineGeometryDesign(3, 1, GF(2)) sage: BD.is_block_design() (True, [2, 8, 2, 2]) """ from sage.combinat.designs.incidence_structures import coordinatewise_product from sage.combinat.combinat import unordered_tuples, combinations from sage.coding.linear_code import hamming_weight A = self.incidence_matrix() v = len(self.points()) b = len(self.blocks()) k = sum(A.columns()[0]) rowsA = A.rows() VS = rowsA[0].parent() r = sum(rowsA[0]) for i in range(b): if not (sum(A.columns()[i]) == k): return False for i in range(v): if not (sum(A.rows()[i]) == r): return False t_found_yet = False lambdas = [] for t in range(2, min(v, 11)): #print t L1 = combinations(range(v), t) L2 = [[rowsA[i] for i in L] for L in L1] #print t,len(L2) lmbda = hamming_weight(VS(coordinatewise_product(L2[0]))) lambdas.append(lmbda) pars = [t, v, k, lmbda] #print pars for ell in L2: a = hamming_weight(VS(coordinatewise_product(ell))) if not (a == lmbda) or a == 0: if not (t_found_yet): pars = [t - 1, v, k, lambdas[t - 3]] return False, pars else: #print pars, lambdas pars = [t - 1, v, k, lambdas[t - 3]] return True, pars t_found_yet = True pars = [t - 1, v, k, lambdas[t - 3]] return True, pars
def is_block_design(self): """ Returns a pair True, pars if the incidence structure is a t-design, for some t, where pars is the list of parameters [t, v, k, lmbda]. The largest possible t is returned, provided t=10. EXAMPLES:: sage: BD = IncidenceStructure(range(7),[[0,1,2],[0,3,4],[0,5,6],[1,3,5],[1,4,6],[2,3,6],[2,4,5]]) sage: BD.is_block_design() (True, [2, 7, 3, 1]) sage: BD.block_design_checker(2, 7, 3, 1) True sage: BD = WittDesign(9) # requires optional gap package 'design' sage: BD.is_block_design() # requires optional gap package 'design' (True, [2, 9, 3, 1]) sage: BD = WittDesign(12) # requires optional gap package 'design' sage: BD.is_block_design() # requires optional gap package 'design' (True, [5, 12, 6, 1]) sage: BD = AffineGeometryDesign(3, 1, GF(2)) sage: BD.is_block_design() (True, [2, 8, 2, 2]) """ from sage.combinat.designs.incidence_structures import coordinatewise_product from sage.combinat.combinat import unordered_tuples, combinations from sage.coding.linear_code import hamming_weight A = self.incidence_matrix() v = len(self.points()) b = len(self.blocks()) k = sum(A.columns()[0]) rowsA = A.rows() VS = rowsA[0].parent() r = sum(rowsA[0]) for i in range(b): if not (sum(A.columns()[i]) == k): return False for i in range(v): if not (sum(A.rows()[i]) == r): return False t_found_yet = False lambdas = [] for t in range(2, min(v, 11)): # print t L1 = combinations(range(v), t) L2 = [[rowsA[i] for i in L] for L in L1] # print t,len(L2) lmbda = hamming_weight(VS(coordinatewise_product(L2[0]))) lambdas.append(lmbda) pars = [t, v, k, lmbda] # print pars for ell in L2: a = hamming_weight(VS(coordinatewise_product(ell))) if not (a == lmbda) or a == 0: if not (t_found_yet): pars = [t - 1, v, k, lambdas[t - 3]] return False, pars else: # print pars, lambdas pars = [t - 1, v, k, lambdas[t - 3]] return True, pars t_found_yet = True pars = [t - 1, v, k, lambdas[t - 3]] return True, pars