// Intrinsics used by code from paper 13: // _Searching for linear codes with large minimum distance_, by Markus Grassl // Section 2: Computing the minimum weight // Subsection 2.1: General linear codes intrinsic WorkFactor(F::FldFin, n::RngIntElt, k::RngIntElt, d::RngIntElt, ranks::[RngIntElt]) -> RngIntElt { Computes the max. number of codewords considered in Magma's algorithm to compute the minimum weight of linear codes. } w := 0; repeat w +:= 1; lb := &+[ w + 1 - (k - x) : x in ranks | w + x - k ge 0 ]; until lb ge Minimum(d, n - k + 1) or w ge k; w0 := w; vprintf Code: "maximal weight: %o\n", w0; ranks_used := [ x : x in ranks | x ge k - w0 ]; vprintf Code: "relative ranks used: %o\n", ranks_used; work := 0; for w := 1 to w0 do work +:= #ranks_used*Binomial(k, w)*(#F - 1)^(w - 1); lb := &+[ w + 1 - (k - x) : x in ranks_used | x ge k - w ]; vprintf Code: "w=%o: lower bound: %o, count: %o=2^%o\n", w, lb, work, Ilog2(work); end for; return work; end intrinsic; // Subsection 2.2: Cyclic codes intrinsic CyclicWorkFactor(F::FldFin, n::RngIntElt, k::RngIntElt, d::RngIntElt) -> RngIntElt { Computes the max. number of codewords considered in Magma's algorithm to compute the minimum weight of a cyclic code. } w0 := Floor(d*k/n); vprintf Code: "maximal weight: %o\n", w0; work := 0; w := 0; lb := 1; repeat w +:= 1; work +:= Binomial(k, w)*(#F - 1)^(w - 1); lb := Ceiling(n/k*(w + 1)); vprintf Code: "w=%o: lower bound: %o, count: %o=2^%o\n", w, lb, work, Ilog2(work); until lb ge Minimum(d, n - k + 1) or w ge k; return work; end intrinsic; // Subsection 2.3: The MacWilliams transform intrinsic new_MinimumWeight(C::Code) -> RngIntElt { Computes the minimum distance of the code either by Magma's internal algorithm or via the weight distribution } F := Alphabet(C); n := Length(C); k := Dimension(C); if not assigned C`MinimumWeight then work_wd := #F^Minimum(k, n - k); if IsCyclic(C) then work := CyclicWorkFactor(F, n, k, n - k + 1); else ranks := [ k : i in [1..n-k-1 by k] ] cat [ n mod k ]; work := WorkFactor(F, n, k, n - k + 1, ranks); end if; if work_wd lt work then vprint Code: "using the weight distribution"; wd := WeightDistribution(C); end if; end if; return MinimumWeight(C); end intrinsic; // Section 4: Searching for good codes // Subsection 4.1: Cyclic codes intrinsic AllCyclicCodes(F::FldFin, n::RngIntElt) -> SetEnum { Returns the set of all cyclic codes of length n over F } P := PolynomialRing(F); L_f := { f[1] : f in Factorisation(P.1^n - 1) }; if #L_f gt 16 then printf "WARNING: there are 2^%o codes\n", #L_f; end if; L_c := { CyclicCode(n, &*y) : y in Subsets(L_f) }; return L_c; end intrinsic; intrinsic CyclicSubcodes(C::Code) -> SetEnum { Returns the set of all maximal proper cyclic subcodes of C } if Dimension(C) eq 0 then return {}; else n := Length(C); g := GeneratorPolynomial(C); g0 := Parent(g).1^n - 1; g1 := g0 div g; L_c := { CyclicCode(n, g*f[1]) : f in Factorisation(g1) }; return L_c; end if; end intrinsic; intrinsic CyclicSupercodes(C::Code) -> SetEnum { Returns the set of all cyclic codes for which C is a maximal proper subcode } n := Length(C); if Dimension(C) eq n then return {}; else g := GeneratorPolynomial(C); L_c := { CyclicCode(n, g div f[1]) : f in Factorisation(g) }; return L_c; end if; end intrinsic; // Subsection 4.2: Other techniques intrinsic TestConstructionY1(C::Code, w::RngIntElt) -> Code { Searches for a non-zero codeword of weight at most w in the dual code of C. If such a word exists, Construction Y1 is applied to C, else the code C is returned. } D := Dual(C); if VerifyMinimumWeightUpperBound(D,w) then v := D`MinimumWeightUpperBoundWord; C1 := ShortenCode(C, Support(v)); else C1 := C; end if; return C1; end intrinsic;