def _null_linear_combination(zeta, alpha, j, p, theminpoly): """ Return linear combination coefficients of tau_i = z_i * alpha[j], which is congruent to 0 modulo theminpoly and pIp. alpha is a module. zeta_{j+1} = {z in zeta_j | z * alpha[j] (mod theminpoly) = 0 (mod pIp)} """ n = theminpoly.degree() l = len(zeta) assert n == len(alpha.basis) alpha_basis = [tuple(b) for b in alpha.get_rationals()] alpha_mat = matrix.createMatrix(n, alpha_basis, coeff_ring=Q) alpha_poly = alpha.get_polynomials() taus = [] for i in range(l): tau_i = zeta[i] * alpha_poly[j] % theminpoly taus.append(tuple(_coeff_list(tau_i, n))) tau_mat = matrix.createMatrix(n, l, taus, coeff_ring=Q) xi = alpha_mat.inverseImage(tau_mat) field_p = finitefield.FinitePrimeField.getInstance(p) xi_p = xi.map(field_p.createElement) return xi_p.kernel() # linear combination of tau_i's
def toMatrix(self, as_column=False): """ toMatrix(as_column): convert to Matrix representation. If as_column is True, return column matrix, otherwise row matrix. """ import nzmath.matrix as matrix if as_column: return matrix.createMatrix(len(self), 1, self.compo) else: return matrix.createMatrix(1, len(self), self.compo)
def testDeterminant(self): """ Every test method have name prefixed with 'test'. """ invertible = _matrix.createMatrix( 2, [self.F7.createElement(c) for c in [2, 5, 3, 1]]) noninvertible = _matrix.createMatrix( 2, [self.F7.createElement(c) for c in [2, 6, 6, 4]]) # asserting something self.assertEqual(self.F7.one, invertible.determinant()) # asserting equality self.assertEqual(self.F7.zero, noninvertible.determinant())
def testInverse(self): """ Every test method have name prefixed with 'test'. """ invertible = _matrix.createMatrix( 2, [self.F7.createElement(c) for c in [2, 5, 3, 1]]) inverse = _matrix.createMatrix( 2, [self.F7.createElement(c) for c in [1, 2, 4, 2]]) noninvertible = _matrix.createMatrix( 2, [self.F7.createElement(c) for c in [2, 6, 3, 2]]) # asserting something self.assertEqual(inverse, invertible.inverse()) # asserting equality self.assertRaises(_matrix.NoInverse, noninvertible.inverse)
def __add__(self, other): """ Return sum of two modules. """ denominator = gcd.lcm(self.denominator, other.denominator) row = self.dimension assert row == other.dimension column = self.rank + other.rank mat = matrix.createMatrix(row, column) adjust = denominator // self.denominator for i, base in enumerate(self.basis): mat.setColumn(i + 1, [c * adjust for c in base]) adjust = denominator // other.denominator for i, base in enumerate(other.basis): mat.setColumn(self.rank + i + 1, [c * adjust for c in base]) # Hermite normal form hnf = mat.hermiteNormalForm() # The hnf returned by the hermiteNormalForm method may have columns # of zeros, and they are not needed. zerovec = vector.Vector([0] * hnf.row) while hnf.row < hnf.column or hnf[1] == zerovec: hnf.deleteColumn(1) omega = [] for j in range(1, hnf.column + 1): omega.append(list(hnf[j])) return ModuleWithDenominator(omega, denominator)
def testGetRing(self): invertible = _matrix.createMatrix( 2, [self.F7.createElement(c) for c in [2, 5, 3, 1]]) self.assertTrue(invertible.getRing()) M2F7 = _matrix.MatrixRing.getInstance(2, self.F7) self.assertEqual(M2F7, invertible.getRing()) M3F7 = _matrix.MatrixRing.getInstance(3, self.F7) self.assertNotEqual(M3F7, invertible.getRing())
def field_discriminant(self): """ Return the (field) discriminant of self (using round2 module) """ if not hasattr(self, "discriminant"): int_basis, self.discriminant = round2.round2(self.polynomial) self.integer_basis = matrix.createMatrix( self.degree, [vector.Vector(int_basis[j]) for j in range(len(int_basis))]) return self.discriminant
def field_discriminant(self): """ Return the (field) discriminant of self (using round2 module) """ if not hasattr(self, "discriminant"): int_basis, self.discriminant = round2.round2(self.polynomial) self.integer_basis = matrix.createMatrix( self.degree, [vector.Vector(int_basis[j]) for j in range( len(int_basis))]) return self.discriminant
def disc(A): """ Compute the discriminant of a_i, where A=[a_1,...,a_n] """ n = A[0].degree list = [] for i in range(n): for j in range(n): s = A[i] * A[j] list.append(s.trace()) M = matrix.createMatrix(n, n, list) return M.determinant()
def __init__(self, coefficient, polynomial): """ """ self.coeff = coefficient self.degree = len(coefficient) List = [] for i in range(self.degree): stbasis = [0] * self.degree stbasis[i] = 1 List.append(stbasis) List.append([-polynomial[i] for i in range(self.degree)]) for l in range(self.degree - 2): basis1 = [] basis = [] for j in range(self.degree): if j == 0: basis1.append(0) if j < self.degree - 1: basis1.append(List[l + self.degree][j]) elif j == self.degree - 1: basis2 = [ List[l + self.degree][j] * -polynomial[k] for k in range(self.degree) ] for i in range(self.degree): basis.append(basis1[i] + basis2[i]) List.append(basis) Matrix = [] flag = 0 for i in range(self.degree): basis3 = [] for j in range(self.degree): basis3.append([self.coeff[j] * k for k in List[j + flag]]) for l in range(self.degree): t = 0 for m in range(self.degree): t += basis3[m][l] Matrix.append(t) flag += 1 self.matrix = matrix.createMatrix(self.degree, self.degree, Matrix) self.polynomial = polynomial self.field = NumberField(self.polynomial)
def __init__(self, coefficient, polynomial): """ """ self.coeff = coefficient self.degree = len(coefficient) List = [] for i in range(self.degree): stbasis = [0] * self.degree stbasis[i] = 1 List.append(stbasis) List.append([- polynomial[i] for i in range(self.degree)]) for l in range(self.degree - 2): basis1 = [] basis = [] for j in range(self.degree): if j == 0: basis1.append(0) if j < self.degree - 1: basis1.append(List[l + self.degree][j]) elif j == self.degree - 1: basis2 = [List[l + self.degree][j] * - polynomial[k] for k in range(self.degree)] for i in range(self.degree): basis.append(basis1[i] + basis2[i]) List.append(basis) Matrix = [] flag = 0 for i in range(self.degree): basis3 = [] for j in range(self.degree): basis3.append([self.coeff[j] * k for k in List[j+flag]]) for l in range(self.degree): t = 0 for m in range(self.degree): t += basis3[m][l] Matrix.append(t) flag += 1 self.matrix = matrix.createMatrix(self.degree, self.degree, Matrix) self.polynomial = polynomial self.field = NumberField(self.polynomial)
def testMul(self): v1 = vector.Vector([1,2,3]) import nzmath.matrix as matrix m1 = matrix.createMatrix(2,3,[1,0,1,0,1,0]) assert m1*v1 == vector.Vector([4,2])
def testLLL(self): basis = matrix.createMatrix(3, 3, [1, 2, 3, 6, 2, 5, 0, -1, 2]) #qForm = matrix.createMatrix(3,3,[7,3,0,2,6,0,2,1,2]) #L = lattice.Lattice(basis, qForm) assert lattice.LLL(basis)
def affine_multiple_method(lhs, field): """ Find and return a root of the equation lhs = 0 by brute force search in the given field. If there is no root in the field, ValueError is raised. The first argument lhs is a univariate polynomial with coefficients in a finite field. The second argument field is an extension field of the field of coefficients of lhs. Affine multiple A(X) is $\sum_{i=0}^{n} a_i X^{q^i} - a$ for some a_i's and a in the coefficient field of lhs, which is a multiple of the lhs. """ polynomial_ring = lhs.getRing() coeff_field = lhs.getCoefficientRing() q = card(coeff_field) n = lhs.degree() # residues = [x, x^q, x^{q^2}, ..., x^{q^{n-1}}] residues = [lhs.mod(polynomial_ring.one.term_mul((1, 1)))] # x for i in range(1, n): residues.append(pow(residues[-1], q, lhs)) # x^{q^i} # find a linear relation among residues and a constant coeff_matrix = matrix.createMatrix(n, n, [coeff_field.zero] * (n**2), coeff_field) for j, residue in enumerate(residues): for i in range(residue.degree() + 1): coeff_matrix[i + 1, j + 1] = residue[i] constant_components = [coeff_field.one] + [coeff_field.zero] * (n - 1) constant_vector = vector.Vector(constant_components) try: relation_vector, kernel = coeff_matrix.solve(constant_vector) for j in range(n, 0, -1): if relation_vector[j]: constant = relation_vector[j].inverse() relation = [constant * c for c in relation_vector] break except matrix.NoInverseImage: kernel_matrix = coeff_matrix.kernel() relation_vector = kernel_matrix[1] assert type(relation_vector) is vector.Vector for j in range(n, 0, -1): if relation_vector[j]: normalizer = relation_vector[j].inverse() relation = [normalizer * c for c in relation_vector] constant = coeff_field.zero break # define L(X) = A(X) + constant coeffs = {} for i, relation_i in enumerate(relation): coeffs[q**i] = relation_i linearized = uniutil.polynomial(coeffs, coeff_field) # Fq basis [1, X, ..., X^{s-1}] qbasis = [1] root = field.createElement(field.char) s = arith1.log(card(field), q) qbasis += [root**i for i in range(1, s)] # represent L as Matrix lmat = matrix.createMatrix(s, s, field.basefield) for j, base in enumerate(qbasis): imagei = linearized(base) if imagei.getRing() == field.basefield: lmat[1, j + 1] = imagei else: for i, coeff in imagei.rep.iterterms(): if coeff: lmat[i + 1, j + 1] = coeff # solve L(X) = the constant constant_components = [constant] + [coeff_field.zero] * (s - 1) constant_vector = vector.Vector(constant_components) solution, kernel = lmat.solve(constant_vector) assert lmat * solution == constant_vector solutions = [solution] for v in kernel: for i in range(card(field.basefield)): solutions.append(solution + i * v) # roots of A(X) contains the solutions of lhs = 0 for t in bigrange.multirange([(card(field.basefield),)] * len(kernel)): affine_root_vector = solution for i, ti in enumerate(t): affine_root_vector += ti * kernel[i] affine_root = field.zero for i, ai in enumerate(affine_root_vector): affine_root += ai * qbasis[i] if not lhs(affine_root): return affine_root raise ValueError("no root found")
def POLRED(self): """ Given a polynomial f i.e. a field self, output some polynomials defining subfield of self, where self is a field defined by f. Algorithm 4.4.11 in Cohen's book. """ n = self.degree appr = self.getConj() #Step 1. Basis = self.integer_ring() BaseList = [] for i in range(n): AlgInt = MatAlgNumber(Basis[i].compo, self.polynomial) BaseList.append(AlgInt) #Step 2. traces = [] if self.signature()[1] == 0: for i in range(n): for j in range(n): s = BaseList[i]*BaseList[j] traces.append(s.trace()) else: sigma = self.getConj() f = [] for i in range(n): f.append(zpoly(Basis[i])) for i in range(n): for j in range(n): m = 0 + 0j for k in range(n): m += f[i](sigma[k])*f[j](sigma[k].conjugate()) traces.append(m.real) #Step 3. M = matrix.createMatrix(n, n, traces) S = matrix.unitMatrix(n) L = lattice.LLL(S, M)[0] #Step 4. Ch_Basis = [] for i in range(n): base_cor = changetype(0, self.polynomial).ch_matrix() for v in range(n): base_cor += BaseList[v]*L.compo[v][i] Ch_Basis.append(base_cor) C = [] a = Ch_Basis[0] for i in range(n): coeff = Ch_Basis[i].ch_basic().getCharPoly() C.append(zpoly(coeff)) #Step 5. P = [] for i in range(n): diff_C = C[i].differentiate() gcd_C = C[i].subresultant_gcd(diff_C) P.append(C[i].exact_division(gcd_C)) return P
def testRMul(self): v1 = vector.Vector([1,2,3]) import nzmath.matrix as matrix m1 = matrix.createMatrix(3,2,[1,1,0,1,0,1]) assert v1*m1 == vector.Vector([1,6])
def affine_multiple_method(lhs, field): """ Find and return a root of the equation lhs = 0 by brute force search in the given field. If there is no root in the field, ValueError is raised. The first argument lhs is a univariate polynomial with coefficients in a finite field. The second argument field is an extension field of the field of coefficients of lhs. Affine multiple A(X) is $\sum_{i=0}^{n} a_i X^{q^i} - a$ for some a_i's and a in the coefficient field of lhs, which is a multiple of the lhs. """ polynomial_ring = lhs.getRing() coeff_field = lhs.getCoefficientRing() q = card(coeff_field) n = lhs.degree() # residues = [x, x^q, x^{q^2}, ..., x^{q^{n-1}}] residues = [lhs.mod(polynomial_ring.one.term_mul((1, 1)))] # x for i in range(1, n): residues.append(pow(residues[-1], q, lhs)) # x^{q^i} # find a linear relation among residues and a constant coeff_matrix = matrix.createMatrix(n, n, [coeff_field.zero] * (n**2), coeff_field) for j, residue in enumerate(residues): for i in range(residue.degree() + 1): coeff_matrix[i + 1, j + 1] = residue[i] constant_components = [coeff_field.one] + [coeff_field.zero] * (n - 1) constant_vector = vector.Vector(constant_components) try: relation_vector, kernel = coeff_matrix.solve(constant_vector) for j in range(n, 0, -1): if relation_vector[j]: constant = relation_vector[j].inverse() relation = [constant * c for c in relation_vector] break except matrix.NoInverseImage: kernel_matrix = coeff_matrix.kernel() relation_vector = kernel_matrix[1] assert type(relation_vector) is vector.Vector for j in range(n, 0, -1): if relation_vector[j]: normalizer = relation_vector[j].inverse() relation = [normalizer * c for c in relation_vector] constant = coeff_field.zero break # define L(X) = A(X) + constant coeffs = {} for i, relation_i in enumerate(relation): coeffs[q**i] = relation_i linearized = uniutil.polynomial(coeffs, coeff_field) # Fq basis [1, X, ..., X^{s-1}] qbasis = [1] root = field.createElement(field.char) s = arith1.log(card(field), q) qbasis += [root**i for i in range(1, s)] # represent L as Matrix lmat = matrix.createMatrix(s, s, field.basefield) for j, base in enumerate(qbasis): imagei = linearized(base) if imagei.getRing() == field.basefield: lmat[1, j + 1] = imagei else: for i, coeff in imagei.rep.iterterms(): if coeff: lmat[i + 1, j + 1] = coeff # solve L(X) = the constant constant_components = [constant] + [coeff_field.zero] * (s - 1) constant_vector = vector.Vector(constant_components) solution, kernel = lmat.solve(constant_vector) assert lmat * solution == constant_vector solutions = [solution] for v in kernel: for i in range(card(field.basefield)): solutions.append(solution + i * v) # roots of A(X) contains the solutions of lhs = 0 for t in bigrange.multirange([(card(field.basefield), )] * len(kernel)): affine_root_vector = solution for i, ti in enumerate(t): affine_root_vector += ti * kernel[i] affine_root = field.zero for i, ai in enumerate(affine_root_vector): affine_root += ai * qbasis[i] if not lhs(affine_root): return affine_root raise ValueError("no root found")
def POLRED(self): """ Given a polynomial f i.e. a field self, output some polynomials defining subfield of self, where self is a field defined by f. Algorithm 4.4.11 in Cohen's book. """ n = self.degree appr = self.getConj() #Step 1. Basis = self.integer_ring() BaseList = [] for i in range(n): AlgInt = MatAlgNumber(Basis[i].compo, self.polynomial) BaseList.append(AlgInt) #Step 2. traces = [] if self.signature()[1] == 0: for i in range(n): for j in range(n): s = BaseList[i] * BaseList[j] traces.append(s.trace()) else: sigma = self.getConj() f = [] for i in range(n): f.append(zpoly(Basis[i])) for i in range(n): for j in range(n): m = 0 + 0j for k in range(n): m += f[i](sigma[k]) * f[j](sigma[k].conjugate()) traces.append(m.real) #Step 3. M = matrix.createMatrix(n, n, traces) S = matrix.unitMatrix(n) L = lattice.LLL(S, M)[0] #Step 4. Ch_Basis = [] for i in range(n): base_cor = changetype(0, self.polynomial).ch_matrix() for v in range(n): base_cor += BaseList[v] * L.compo[v][i] Ch_Basis.append(base_cor) C = [] a = Ch_Basis[0] for i in range(n): coeff = Ch_Basis[i].ch_basic().getCharPoly() C.append(zpoly(coeff)) #Step 5. P = [] for i in range(n): diff_C = C[i].differentiate() gcd_C = C[i].subresultant_gcd(diff_C) P.append(C[i].exact_division(gcd_C)) return P