Skip to content

Commit f54a30a

Browse files
committed
Trac #40513, #40514: Allow zero code and add intersection method
1 parent 858268b commit f54a30a

File tree

1 file changed

+94
-35
lines changed

1 file changed

+94
-35
lines changed

src/sage/coding/linear_code.py

Lines changed: 94 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -80,17 +80,17 @@ class should inherit from this class. Also ``AbstractLinearCode`` should never
8080
sage: G = MS([[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]])
8181
sage: C = LinearCode(G)
8282
sage: C.basis()
83-
[(1, 1, 1, 0, 0, 0, 0),
84-
(1, 0, 0, 1, 1, 0, 0),
85-
(0, 1, 0, 1, 0, 1, 0),
86-
(1, 1, 0, 1, 0, 0, 1)]
83+
[(1, 0, 0, 0, 0, 1, 1),
84+
(0, 1, 0, 0, 1, 0, 1),
85+
(0, 0, 1, 0, 1, 1, 0),
86+
(0, 0, 0, 1, 1, 1, 1)]
8787
sage: c = C.basis()[1]
8888
sage: c in C
8989
True
9090
sage: c.nonzero_positions()
91-
[0, 3, 4]
91+
[1, 4, 6]
9292
sage: c.support()
93-
[0, 3, 4]
93+
[1, 4, 6]
9494
sage: c.parent()
9595
Vector space of dimension 7 over Finite Field of size 2
9696
@@ -1441,7 +1441,7 @@ def _minimum_weight_codeword(self, algorithm=None):
14411441
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]])
14421442
sage: C = LinearCode(G)
14431443
sage: C._minimum_weight_codeword() # needs sage.libs.gap
1444-
(0, 1, 0, 1, 0, 1, 0)
1444+
(0, 0, 1, 0, 1, 1, 0)
14451445
14461446
TESTS:
14471447
@@ -2314,35 +2314,43 @@ def __init__(self, generator, d=None):
23142314
23152315
sage: G = matrix(GF(2), [[0,0,0]])
23162316
sage: C = LinearCode(G)
2317-
Traceback (most recent call last):
2318-
...
2319-
ValueError: this linear code contains no nonzero vector
2317+
sage: C
2318+
[3, 0] linear code over GF(2)
2319+
sage: C.dimension()
2320+
0
23202321
"""
23212322

2322-
base_ring = generator.base_ring()
2323+
from sage.matrix.constructor import matrix
2324+
2325+
if isinstance(generator, AbstractLinearCode):
2326+
generator = generator.generator_matrix()
2327+
2328+
if hasattr(generator, 'basis'):
2329+
if generator.dimension() == 0:
2330+
G = matrix(generator.base_ring(), 0, generator.ambient_space().dimension())
2331+
else:
2332+
G = matrix(generator.basis())
2333+
else:
2334+
G = generator
2335+
2336+
base_ring = G.base_ring()
23232337
if not base_ring.is_field():
23242338
raise ValueError("'generator' must be defined on a field (not a ring)")
23252339

2326-
try:
2327-
basis = None
2328-
if hasattr(generator, "nrows"): # generator matrix case
2329-
if generator.rank() < generator.nrows():
2330-
basis = generator.row_space().basis()
2331-
else:
2332-
basis = generator.basis() # vector space etc. case
2333-
if basis is not None:
2334-
from sage.matrix.constructor import matrix
2335-
generator = matrix(base_ring, basis)
2336-
if generator.nrows() == 0:
2337-
raise ValueError("this linear code contains no nonzero vector")
2338-
except AttributeError:
2339-
# Assume input is an AbstractLinearCode, extract its generator matrix
2340-
generator = generator.generator_matrix()
2340+
if G.is_zero() or G.nrows() == 0:
2341+
super().__init__(base_ring, G.ncols(), "GeneratorMatrix", "Syndrome")
2342+
self._dimension = 0
2343+
self._generator_matrix = matrix(base_ring, 0, self.length())
2344+
self._minimum_distance = d
2345+
return
23412346

2342-
super().__init__(base_ring, generator.ncols(),
2347+
G_echelon = G.echelon_form()
2348+
generator_matrix = G_echelon.matrix_from_rows([i for i, r in enumerate(G_echelon) if not r.is_zero()])
2349+
2350+
super().__init__(base_ring, generator_matrix.ncols(),
23432351
"GeneratorMatrix", "Syndrome")
2344-
self._generator_matrix = generator
2345-
self._dimension = generator.rank()
2352+
self._generator_matrix = generator_matrix
2353+
self._dimension = self._generator_matrix.rank()
23462354
self._minimum_distance = d
23472355

23482356
def __hash__(self):
@@ -2382,7 +2390,58 @@ def _latex_(self):
23822390
"""
23832391
return "[%s, %s]\\textnormal{ Linear code over }%s"\
23842392
% (self.length(), self.dimension(), self.base_ring()._latex_())
2393+
2394+
def intersection(self, other):
2395+
"""
2396+
Return the intersection of this linear code with another.
2397+
2398+
The intersection of two linear codes C1 and C2 is the set of all
2399+
codewords that are in both C1 and C2. It is also a linear code.
2400+
2401+
This is computed using the identity:
2402+
C1 ∩ C2 = (C1_dual + C2_dual)_dual
2403+
2404+
INPUT:
2405+
- ``other`` -- a linear code.
2406+
2407+
OUTPUT:
2408+
- a linear code, the intersection of self and other.
2409+
2410+
EXAMPLES:
2411+
sage: F = GF(2)
2412+
sage: G1 = matrix(F, [[1,1,0,0], [0,0,1,1]])
2413+
sage: C1 = LinearCode(G1)
2414+
sage: G2 = matrix(F, [[1,0,1,0], [0,1,0,1]])
2415+
sage: C2 = LinearCode(G2)
2416+
sage: C_int = C1.intersection(C2)
2417+
sage: C_int
2418+
[4, 1] linear code over GF(2)
2419+
sage: c = vector(F, (1,1,1,1))
2420+
sage: c in C_int
2421+
True
2422+
2423+
# Test intersection with the zero code
2424+
sage: C_zero = LinearCode(matrix(F, [[0,0,0,0]]))
2425+
sage: C1.intersection(C_zero)
2426+
[4, 0] linear code over GF(2)
2427+
"""
2428+
if not isinstance(other, AbstractLinearCode):
2429+
raise TypeError("Intersection is only defined between linear codes.")
2430+
if self.base_field() != other.base_field():
2431+
raise TypeError("Codes must be over the same base field.")
2432+
if self.length() != other.length():
2433+
raise ValueError("Codes must have the same length.")
2434+
2435+
C1_dual = self.dual_code()
2436+
C2_dual = other.dual_code()
2437+
2438+
G1d = C1_dual.generator_matrix()
2439+
G2d = C2_dual.generator_matrix()
2440+
G_sum = G1d.stack(G2d)
2441+
sum_of_duals = LinearCode(G_sum)
23852442

2443+
return sum_of_duals.dual_code()
2444+
23862445
def generator_matrix(self, encoder_name=None, **kwargs):
23872446
r"""
23882447
Return a generator matrix of ``self``.
@@ -2401,8 +2460,8 @@ def generator_matrix(self, encoder_name=None, **kwargs):
24012460
sage: G = matrix(GF(3),2,[1,-1,1,-1,1,1])
24022461
sage: code = LinearCode(G)
24032462
sage: code.generator_matrix()
2404-
[1 2 1]
2405-
[2 1 1]
2463+
[1 2 0]
2464+
[0 0 1]
24062465
"""
24072466
if encoder_name is None or encoder_name == 'GeneratorMatrix':
24082467
g = self._generator_matrix
@@ -2493,10 +2552,10 @@ def generator_matrix(self):
24932552
sage: C = LinearCode(G)
24942553
sage: E = codes.encoders.LinearCodeGeneratorMatrixEncoder(C)
24952554
sage: E.generator_matrix()
2496-
[1 1 1 0 0 0 0]
2497-
[1 0 0 1 1 0 0]
2498-
[0 1 0 1 0 1 0]
2499-
[1 1 0 1 0 0 1]
2555+
[1 0 0 0 0 1 1]
2556+
[0 1 0 0 1 0 1]
2557+
[0 0 1 0 1 1 0]
2558+
[0 0 0 1 1 1 1]
25002559
"""
25012560
g = self.code().generator_matrix()
25022561
g.set_immutable()

0 commit comments

Comments
 (0)