def test_to_str_default(self): """Test representation as string to print it.""" matr_values = [ 0b111111111111, 0b011111111111, 0b001111111111, 0b000111111111, 0b000011111111, 0b000001111111, 0b000000111111, 0b000000011111, 0b000000001111, 0b000000000111, 0b000000000011, 0b000000000001 ] matr_str = ( '111111111111\n' '011111111111\n' '001111111111\n' '000111111111\n' '000011111111\n' '000001111111\n' '000000111111\n' '000000011111\n' '000000001111\n' '000000000111\n' '000000000011\n' '000000000001') self.assertEqual( str(matrix.Matrix(matr_values, 12)), matr_str) self.assertEqual( str(matrix.Matrix()), '')
def test_echelon_form(self): """Test evaluating of matrix echelon form.""" matr_max_rank_echelon = [ 0b1000, 0b0111, 0b0011, 0b0001, ] matr_non_max_rank1_echelon = [ 0b10010, 0b01110, 0b00101, 0b00000, ] matr_non_max_rank2_echelon = [ 0b10010, 0b01110, 0b00101, 0b00011, 0b00001, 0b00000, 0b00000, ] self.assertEqual(matrix.Matrix(self.matr_upper, 4).echelon_form, matrix.Matrix(self.matr_upper, 4)) self.assertEqual(matrix.Matrix(self.matr_max_rank, 4).echelon_form, matrix.Matrix(matr_max_rank_echelon, 4)) self.assertEqual(matrix.Matrix(self.matr_non_max_rank1, 5).echelon_form, matrix.Matrix(matr_non_max_rank1_echelon, 5)) self.assertEqual(matrix.Matrix(self.matr_non_max_rank2, 5).echelon_form, matrix.Matrix(matr_non_max_rank2_echelon, 5)) self.assertEqual(matrix.Matrix().echelon_form, matrix.Matrix())
def test_setitem(self): """Test setting the item.""" matr_values = [ 0b11110000101, 0b01100001001, 0b00011100101, 0b10100101001, ] matr = matrix.Matrix(matr_values, ncolumns=11) matr[0] = 0 self.assertEqual([x.value for x in matr], [0] + matr_values[1:]) matr = matrix.Matrix(matr_values, ncolumns=11) matr[0] = Vector(0b11, 3) self.assertEqual([x.value for x in matr], [0b011] + matr_values[1:]) matr = matrix.Matrix(matr_values, ncolumns=11) matr[0] = '1011' self.assertEqual([x.value for x in matr], [0b1011] + matr_values[1:]) matr = matrix.Matrix(matr_values, ncolumns=11) matr[0] = (1, 0, '11', '001', True) self.assertEqual([x.value for x in matr], [0b10110011] + matr_values[1:]) matr = matrix.Matrix(matr_values, ncolumns=11) matr[2] = 0 self.assertEqual([x.value for x in matr], matr_values[:2] + [0] + matr_values[3:]) matr[-2] = 0 self.assertEqual([x.value for x in matr], matr_values[:2] + [0] + matr_values[3:])
def test_to_latex_str(self): """Test representation Matrix object as LaTeX string.""" matr_values = [ 0b111111111111, 0b011111111111, 0b001111111111, 0b000111111111, 0b000011111111, 0b000001111111, 0b000000111111, 0b000000011111, 0b000000001111, 0b000000000111, 0b000000000011, ] matr_str = ( '1&1&1&1&1&1&1&1&1&1&1&1\\\\\n' '0&1&1&1&1&1&1&1&1&1&1&1\\\\\n' '0&0&1&1&1&1&1&1&1&1&1&1\\\\\n' '0&0&0&1&1&1&1&1&1&1&1&1\\\\\n' '0&0&0&0&1&1&1&1&1&1&1&1\\\\\n' '0&0&0&0&0&1&1&1&1&1&1&1\\\\\n' '0&0&0&0&0&0&1&1&1&1&1&1\\\\\n' '0&0&0&0&0&0&0&1&1&1&1&1\\\\\n' '0&0&0&0&0&0&0&0&1&1&1&1\\\\\n' '0&0&0&0&0&0&0&0&0&1&1&1\\\\\n' '0&0&0&0&0&0&0&0&0&0&1&1') matr = matrix.Matrix(matr_values, 12) self.assertEqual(matr.to_latex_str(), matr_str) self.assertEqual(matrix.Matrix().to_latex_str(), '')
def test_rank(self): """Test evaluating of matrix rank.""" self.assertEqual(matrix.Matrix(self.matr_upper, 4).rank, 4) self.assertEqual(matrix.Matrix(self.matr_max_rank, 4).rank, 4) self.assertEqual(matrix.Matrix(self.matr_non_max_rank1, 5).rank, 3) self.assertEqual(matrix.Matrix(self.matr_non_max_rank2, 5).rank, 5) self.assertEqual(matrix.Matrix().rank, 0)
def test_is_max_rank(self): """Test check if matrix has maximal rank.""" self.assertTrue(matrix.Matrix(self.matr_upper, 4).is_max_rank()) self.assertTrue(matrix.Matrix(self.matr_max_rank, 4).is_max_rank()) self.assertFalse(matrix.Matrix(self.matr_non_max_rank1, 5).is_max_rank()) self.assertTrue(matrix.Matrix(self.matr_non_max_rank2, 5).is_max_rank()) self.assertTrue(matrix.Matrix().is_max_rank)
def test_to_str(self): """Test representation as customisable string.""" matr_values = [ 0b111111111111, 0b011111111111, 0b001111111111, 0b000111111111, 0b000011111111, 0b000001111111, 0b000000111111, 0b000000011111, 0b000000001111, 0b000000000111, 0b000000000011, 0b000000000001 ] matr_str = ( '111111111111\n' '011111111111\n' '001111111111\n' '000111111111\n' '000011111111\n' '000001111111\n' '000000111111\n' '000000011111\n' '000000001111\n' '000000000111\n' '000000000011\n' '000000000001') matr_str_numbered = ( ' 0: 111111111111\n' ' 1: 011111111111\n' ' 2: 001111111111\n' ' 3: 000111111111\n' ' 4: 000011111111\n' ' 5: 000001111111\n' ' 6: 000000111111\n' ' 7: 000000011111\n' ' 8: 000000001111\n' ' 9: 000000000111\n' '10: 000000000011\n' '11: 000000000001') self.assertEqual( matrix.Matrix(matr_values, 12).to_str(), matr_str) self.assertEqual( matrix.Matrix(matr_values, 12).to_str(zerofillers='*'), matr_str.replace('0', '*')) self.assertEqual( matrix.Matrix(matr_values, 12).to_str(onefillers='*'), matr_str.replace('1', '*')) self.assertEqual( matrix.Matrix().to_str(onefillers='*'), '') self.assertEqual( matrix.Matrix(matr_values, 12).to_str(numbered=True), matr_str_numbered)
def test_iterator(self): """Test iteration over matrix rows.""" self.assertEqual(list(matrix.Matrix()), []) self.assertTrue(list(matrix.Matrix([0b1], ncolumns=1)), [Vector(0b1, 1)]) self.assertTrue(list(matrix.Matrix( [0b0011, 0b1010, 0b0111], ncolumns=4)), [Vector(0b0011, 4), Vector(0b1010, 4), Vector(0b0111, 4)])
def test_diagonal_form(self): """Test evaluating of matrix diagonal form.""" matr_non_max_rank1_diagonal = [ 0b10010, 0b01011, 0b00101, 0b00000, ] matr_non_max_rank2_diagonal = [ 0b10000, 0b01000, 0b00100, 0b00010, 0b00001, 0b00000, 0b00000, ] self.assertTrue( matrix.Matrix(self.matr_upper, 4).diagonal_form.is_identity()) self.assertTrue( matrix.Matrix(self.matr_max_rank, 4).diagonal_form.is_identity()) self.assertEqual(matrix.Matrix(self.matr_non_max_rank1, 5).diagonal_form, matrix.Matrix(matr_non_max_rank1_diagonal, 5)) self.assertEqual(matrix.Matrix(self.matr_non_max_rank2, 5).diagonal_form, matrix.Matrix(matr_non_max_rank2_diagonal, 5)) self.assertEqual(matrix.Matrix().diagonal_form, matrix.Matrix())
def test_submatrix(self): """Test choice submatrix.""" matr_values = [ 0b111111111111, 0b011111111111, 0b001111111111, 0b000111111111, 0b000011111111, 0b000001111111, 0b000000111111, 0b000000011111, 0b000000001111, 0b000000000111, 0b000000000011, ] submatr_values = [ 0b1111111, 0b1111111, 0b0111111, 0b0111111, 0b0011111, 0b0001111, 0b0001111, 0b0001111, 0b0000111, 0b0000011, 0b0000001, ] submatr_values2 = [ 0b1111111111, 0b1111111011, 0b0111111011, 0b0111111011, 0b0011111011, 0b0001111011, 0b0001111010, 0b0001111010, 0b0000111010, 0b0000011000, 0b0000001000, ] matr = matrix.Matrix(matr_values, 12) self.assertEqual(matr.submatrix([1, 3, 4, 7, 8, 9, -1]), matrix.Matrix(submatr_values, 7)) self.assertEqual(matr.submatrix(), matr) self.assertEqual(matr.submatrix([1, 3, 4, 7, 8, 9, -1, 12, 20, 17]), matrix.Matrix(submatr_values2, 10)) self.assertEqual(matrix.Matrix().submatrix([0, 7, 8]), matrix.Matrix())
def test_generate_permutation(self): """Test generating permutation matrix.""" perm_matrix = [ 0b10000000, 0b00010000, 0b00000010, 0b01000000, 0b00000100, 0b00001000, 0b00100000, 0b00000001, ] self.assertEqual(matrix.permutation([]), matrix.Matrix()) perm = matrix.permutation([0, 3, 6, 1, 5, 4, 2, 7]) self.assertEqual(perm, matrix.Matrix(perm_matrix, 8)) perm = matrix.permutation([0, 3, 6, 1, 5, 4, 2, 7], by_rows=True) self.assertEqual(perm, matrix.Matrix(perm_matrix, 8).transpose())
def test_is_zero(self): """Test matrix comparing with zero.""" matr_values = [ 0b111111111111, 0b011111111111, 0b001111111111, 0b000111111111, 0b000011111111, 0b000001111111, 0b000000111111, 0b000000011111, 0b000000001111, 0b000000000111, 0b000000000011, ] self.assertFalse(matrix.Matrix(matr_values, 12).is_zero()) self.assertTrue(matrix.Matrix([0] * 15, 12).is_zero()) self.assertTrue(matrix.Matrix().is_zero())
def test_make_copy(self): """Test make copy of Matrix object.""" matr_values = [ 0b111111111111, 0b011111111111, 0b001111111111, 0b000111111111, 0b000011111111, 0b000001111111, 0b000000111111, 0b000000011111, 0b000000001111, 0b000000000111, 0b000000000011, ] matr = matrix.Matrix(matr_values, 12) self.assertEqual(matr.copy(), matr) self.assertEqual(matrix.Matrix().copy(), matrix.Matrix())
def test_to_str_repr(self): """Test representation as string.""" matr_values = [ 0b111111111111, 0b011111111111, 0b001111111111, 0b000111111111, 0b000011111111, 0b000001111111, 0b000000111111, 0b000000011111, 0b000000001111, 0b000000000111, 0b000000000011, 0b000000000001 ] matr_str = ( 'Matrix(shapes=(12, 12), [' '0: 1111...1111, ' '1: 0111...1111, ' '..., ' '11: 0000...0001])') matr_str8 = ( 'Matrix(shapes=(12, 8), [' '0: 11111111, ' '1: 11111111, ' '..., ' '11: 00000001])') matr_str48 = ( 'Matrix(shapes=(3, 8), [' '0: 11111111, ' '1: 11111111, ' '2: 11111111])') self.assertEqual( repr(matrix.Matrix(matr_values, 12)), matr_str) self.assertEqual( repr(matrix.Matrix(matr_values, 8)), matr_str8) self.assertEqual( repr(matrix.Matrix(matr_values, 8)[:3]), matr_str48) self.assertEqual( repr(matrix.Matrix()), 'Matrix(shapes=(0, 0), [])')
def test_is_identity(self): """Test matrix comparing with identity matrix.""" matr_values = [ 0b111111111111, 0b011111111111, 0b001111111111, 0b000111111111, 0b000011111111, 0b000001111111, 0b000000111111, 0b000000011111, 0b000000001111, 0b000000000111, 0b000000000011, ] self.assertFalse(matrix.Matrix(matr_values, 12).is_identity()) self.assertTrue( matrix.Matrix([1 << (11 - i) for i in range(12)], 12).is_identity()) self.assertFalse(matrix.Matrix().is_identity())
def puncture(generator, columns=None, remove_zeroes=False): """Return generator matrix of punctured code. Punctured code is code obtaining by set the positions with indexes from `ncolumns` of every codeword to zero. Punctured code is NOT subcode of original code! """ if not columns: columns = [] mask = vector.from_support_supplement(generator.ncolumns, columns) puncture_matrix = matrix.Matrix(((row * mask).value for row in generator), generator.ncolumns).diagonal_form if remove_zeroes: return matrix.Matrix( (row.value for row in puncture_matrix if row.value), generator.ncolumns).submatrix( columns=(i for i in range(generator.ncolumns) if i not in columns)) return matrix.Matrix((row.value for row in puncture_matrix if row.value), generator.ncolumns)
def test_solving_linear_equation(self): """Test solving of linear equation.""" vec = Vector(0b1010, 4) matr_max_rank = matrix.Matrix(self.matr_max_rank, 4) fundamental, vec_solve = matr_max_rank.solve(vec) self.assertFalse(fundamental) self.assertEqual( matr_max_rank * matrix.from_vectors([vec_solve]).transpose(), matrix.from_vectors([vec]).transpose()) vec = Vector(0b1010, 4) matr_non_max_rank1 = matrix.Matrix(self.matr_non_max_rank1, 5) fundamental, vec_solve = matr_non_max_rank1.solve(vec) self.assertFalse(fundamental) self.assertFalse(vec_solve) vec = Vector(0b1110, 4) fundamental, vec_solve = matr_non_max_rank1.solve(vec) self.assertEqual(fundamental, matrix.Matrix([0b11010, 0b01101], 5)) self.assertEqual( matr_non_max_rank1 * matrix.from_vectors([vec_solve]).transpose(), matrix.from_vectors([vec]).transpose())
def test_init_by_integers(self): """Init by list of integers.""" matr = matrix.Matrix((0, 0b0011, 0b1011)) self.assertEqual(matr.shapes, (0, 0)) self.assertEqual(list(matr), []) matr = matrix.Matrix((0, 0b0011, 0b1011), ncolumns=2) self.assertEqual(matr.shapes, (3, 2)) self.assertEqual(list(matr), [Vector(0, 2), Vector(0b0011, 2), Vector(0b1011, 2)]) matr = matrix.Matrix((0, 0b0011, 0b1011), ncolumns=4) self.assertEqual(matr.shapes, (3, 4)) self.assertEqual(list(matr), [Vector(0, 4), Vector(0b0011, 4), Vector(0b1011, 4)]) matr = matrix.Matrix((0, 0b0011, 0b1011), ncolumns=10) self.assertEqual(matr.shapes, (3, 10)) self.assertEqual(list(matr), [Vector(0, 10), Vector(0b0011, 10), Vector(0b1011, 10)])
def test_equality(self): """Test matrix's equality.""" matr_values = [ 0b11110000101, 0b01100001001, 0b00011100101, 0b10100101001, ] matr = matrix.Matrix(matr_values, ncolumns=11) self.assertEqual(matr, matrix.Matrix(matr_values, ncolumns=11)) self.assertNotEqual(matr, matrix.Matrix()) self.assertEqual(matrix.Matrix(), matrix.Matrix()) matr[0] = 0 self.assertNotEqual(matrix.Matrix(matr_values, ncolumns=11), matr) self.assertNotEqual(matrix.Matrix(matr_values, ncolumns=11), matrix.Matrix([0b11, 0b01], 2))
def test_shapes(self): """Test get shapes.""" matr_values = [ 0b111111111111, 0b011111111111, 0b001111111111, 0b000111111111, 0b000011111111, 0b000001111111, 0b000000111111, 0b000000011111, 0b000000001111, 0b000000000111, 0b000000000011, ] matr = matrix.Matrix(matr_values, 12) self.assertEqual(matr.shapes, (11, 12)) self.assertEqual(matr.nrows, 11) self.assertEqual(matr.ncolumns, 12) matr_empty = matrix.Matrix() self.assertEqual(matr_empty.shapes, (0, 0)) self.assertEqual(matr_empty.ncolumns, 0) self.assertEqual(matr_empty.nrows, 0)
def truncate(generator, columns=None, remove_zeroes=False): """Return generator matrix of truncated code. Truncated code is code obtaining by choose codewords which have coordinates with indexes from `columns` is zero. Unlike the punctured code truncated code is a subcode of original code. NOTE! If remove_zeroes is set to True the truncated codes would not be a subcode of the original code. """ if not columns: columns = [] mask = vector.from_support(generator.ncolumns, columns) trunc = matrix.Matrix( (row.value for row in generator.gaussian_elimination(columns) if not (row * mask).value), generator.ncolumns).echelon_form trunc = matrix.Matrix((row.value for row in trunc if row.value), generator.ncolumns) if remove_zeroes: return trunc.submatrix(columns=(i for i in range(generator.ncolumns) if i not in columns)) return trunc
def test_gaussian_elimination(self): """Test evaluating of Gaussian elimination.""" matr_gauss_full_non_sort = [ 0b01011, 0b00101, 0b10010, 0b00000, ] matr_gauss_full_sort = [ 0b10010, 0b01011, 0b00101, 0b00000, ] matr_gauss_partial_non_sort = [ 0b11100, 0b00101, 0b10010, 0b00000, ] matr_gauss_partial_sort = [ 0b11100, 0b10010, 0b00101, 0b00000, ] matr = matrix.Matrix(self.matr_non_max_rank1, 5) self.assertEqual(matr.gaussian_elimination(), matrix.Matrix(matr_gauss_full_sort, 5)) self.assertEqual(matr.gaussian_elimination(sort=False), matrix.Matrix(matr_gauss_full_non_sort, 5)) self.assertEqual(matr.gaussian_elimination([1, 3, 4], sort=False), matrix.Matrix(matr_gauss_partial_non_sort, 5)) self.assertEqual(matr.gaussian_elimination([1, 3, 4]), matrix.Matrix(matr_gauss_partial_sort, 5)) self.assertEqual(matr.gaussian_elimination([1, 3, 4, -1, 7, 9, 10]), matrix.Matrix(matr_gauss_partial_sort, 5)) self.assertEqual(matr.gaussian_elimination([1, 3, 4, 4]), matrix.Matrix(matr_gauss_partial_sort, 5)) self.assertEqual(matrix.Matrix().gaussian_elimination(), matrix.Matrix())
def test_transpose(self): """Test matrix transposition.""" matr_values = [ 0b111111111111, 0b011111111111, 0b001111111111, 0b000111111111, 0b000011111111, 0b000001111111, 0b000000111111, 0b000000011111, 0b000000001111, 0b000000000111, 0b000000000011, ] transpose_values = [ 0b10000000000, 0b11000000000, 0b11100000000, 0b11110000000, 0b11111000000, 0b11111100000, 0b11111110000, 0b11111111000, 0b11111111100, 0b11111111110, 0b11111111111, 0b11111111111 ] matr = matrix.Matrix(matr_values, 12) self.assertEqual(matr.transpose(), matrix.Matrix(transpose_values, 11)) self.assertEqual(matr.transpose().transpose(), matr) self.assertEqual(matrix.Matrix().transpose(), matrix.Matrix()) self.assertEqual(matr.T, matr.transpose())
def generator(param_r, param_m): """Make Reed-Muller RM(r,m) generator matrix.""" param_m = max(0, param_m) monoms = [] for i, j in ((1 << (param_m - p - 1), 1 << p) for p in range(param_m)): monoms.append( vector.Vector(int(('0' * i + '1' * i) * j, 2), 1 << param_m)) gen_matrix = [vector.Vector(int('1' * (1 << param_m), 2), 1 << param_m)] for i in range(1, param_r + 1): if i == 1: curr_layer = [(i, monoms[i]) for i in range(len(monoms))] gen_matrix += [monoms[i] for i in range(len(monoms))] continue next_layer = [] for max_monom, row in curr_layer: for j in range(max_monom + 1, param_m): next_layer.append((j, row * monoms[j])) gen_matrix.append(next_layer[-1][1]) curr_layer = next_layer return matrix.Matrix((row.value for row in gen_matrix), 1 << param_m)
def attack(self, generator): rm_subcode_basis = matrix.Matrix() rm_subcode_dim = 0 for i in range(self.r): rm_subcode_dim += self.binomial_coef(self.m, i) while rm_subcode_basis.nrows < rm_subcode_dim: min_weight_codeword = self.min_weight_sample(generator) shortened_g = tools.truncate(generator, min_weight_codeword) inner_sets = self.decompose_inner_sets(shortened_g) f_vecs = [ vector.from_support(2**self.m, min_weight_codeword + s) for s in inner_sets ] rm_subcode_basis = tools.union(rm_subcode_basis, matrix.from_vectors(f_vecs)) return rm_subcode_basis
def test_getitem(self): """Test getting the item.""" matr = matrix.Matrix( [ 0b11110000101, 0b01100001001, 0b00011100101, 0b10100101001, ], ncolumns=11) self.assertIsInstance(matr[2], Vector) self.assertEqual(matr[2], Vector(0b00011100101, 11)) self.assertEqual(matr[-2], Vector(0b00011100101, 11)) self.assertIsInstance(matr[0:4:2], matrix.Matrix) self.assertEqual(list(matr[0:4:2]), [Vector(0b11110000101, 11), Vector(0b00011100101, 11)]) self.assertIsInstance(matr[::-1], matrix.Matrix) self.assertEqual(list(matr[::-1]), [Vector(0b10100101001, 11), Vector(0b00011100101, 11), Vector(0b01100001001, 11), Vector(0b11110000101, 11)])
def attack(self, pub_key): B = matrix.Matrix() B_size = 0 for i in range(self.r): B_size += binom(self.m, i) codeword_support_list = [] while B.nrows < B_size: codeword_support = self \ ._gauss_codeword_support(pub_key, codeword_support_list) codeword_support_list.append(codeword_support) pub_key_truncated = tools.truncate(pub_key, codeword_support) inner_sets = self._decompose_inner_sets(pub_key_truncated) f_vecs = [ vector.from_support(2**self.m, codeword_support + s) for s in inner_sets ] B = tools.union(B, matrix.from_vectors(f_vecs)) return B
def test_othogonal(self): """Test evaluating of maximal orthogonal matrix.""" matr_upper_ort = matrix.Matrix(self.matr_upper, 4).orthogonal self.assertTrue(matr_upper_ort.is_zero()) self.assertTrue( (matrix.Matrix(self.matr_upper, 4) * matr_upper_ort.T).is_zero()) matr_max_rank = matrix.Matrix(self.matr_max_rank, 4) matr_max_rank_ort = matr_max_rank.orthogonal self.assertTrue(matr_max_rank_ort.is_zero()) self.assertTrue((matr_max_rank * matr_max_rank_ort.T).is_zero()) matr_non_max_rank1 = matrix.Matrix(self.matr_non_max_rank1, 5) matr_non_max_rank1_ort = matr_non_max_rank1.orthogonal self.assertEqual( matr_non_max_rank1_ort.shapes, (matr_non_max_rank1.ncolumns - matr_non_max_rank1.rank, matr_non_max_rank1.ncolumns)) self.assertTrue( (matr_non_max_rank1 * matr_non_max_rank1_ort.T).is_zero()) matr_non_max_rank2 = matrix.Matrix(self.matr_non_max_rank2, 5) matr_non_max_rank2_ort = matr_non_max_rank2.orthogonal self.assertTrue(matr_non_max_rank2_ort.is_zero()) self.assertTrue( (matr_non_max_rank2 * matr_non_max_rank2_ort.T).is_zero()) self.assertEqual(matrix.Matrix().orthogonal, matrix.Matrix())
def make_generator(mat): """Return the generator matrix from general matrix `mat`.""" return matrix.Matrix((row.value for row in mat.diagonal_form if row.value), mat.ncolumns)
def iter_codewords(generator): """Iterate over all codewords of code.""" for i in range(1 << generator.nrows): yield (matrix.Matrix([i], generator.nrows) * generator)[0]