def _algnumber_list_to_matrix(omega, field): """ [omega_i] -> matrix (w.r.t. theta) """ vect = [] for omega_i in omega: vect_i = _algnumber_to_vector(omega_i, field) vect.append(vector.Vector(vect_i)) return matrix.Matrix(omega[0].degree, len(omega), vect)
def _scalar_mul(self, other): """ return other * self, assuming other is a scalar (i.e. an element of self.number_field) """ # use other is an element of higher or lower degree number field ? #if other.getRing() != self.number_field: # raise NotImplementedError( # "other is not a element of number field") if not isinstance(other, BasicAlgNumber): try: other = other.ch_basic() except: raise NotImplementedError( "other is not an element of a number field") # represent other with respect to self.base other_repr, pseudo_other_denom = _toIntegerMatrix( self.base.inverse(vector.Vector(other.coeff))) other_repr = other_repr[1] # compute mul using self.base's multiplication base_mul = self._base_multiplication() n = self.number_field.degree mat_repr = [] for k in range(1, self.mat_repr.column + 1): mat_repr_ele = vector.Vector([0] * n) for i1 in range(1, n + 1): for i2 in range(1, n + 1): mat_repr_ele += self.mat_repr[ i1, k] * other_repr[i2] * _symmetric_element( i1, i2, base_mul) mat_repr.append(mat_repr_ele) mat_repr, denom, numer = _toIntegerMatrix( matrix.FieldMatrix(n, len(mat_repr), mat_repr), 1) denom = self.denominator * pseudo_other_denom * other.denom * denom gcds = gcd.gcd(denom, numer) if gcds != 1: denom = ring.exact_division(denom, gcds) numer = ring.exact_division(numer, gcds) if numer != 1: mat_repr = numer * mat_repr else: mat_repr = mat_repr return self.__class__([mat_repr, denom], self.number_field, self.base)
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 testCreateMatrix(self): Q = rational.theRationalField mat1 = createMatrix(2, 3, [[2, 3, 4], [5, 6, 7]]) self.assertEqual(mat1.coeff_ring, Int) mat2 = createMatrix(2, 3, [[2, 3, 4], [5, 6, 7]], Q) self.assertEqual(mat2.coeff_ring, Q) mat3 = createMatrix(3, [(1, 2, 3), (4, 5, 6), (7, 8, 9)], Q) self.assertTrue(mat3.row == mat3.column) self.assertTrue(mat3.__class__, FieldSquareMatrix) mat4 = createMatrix(2, [vector.Vector([1, 4]), vector.Vector([6, 8])]) self.assertEqual(mat4.coeff_ring, Int) mat5 = createMatrix(5, 6, Int) self.assertTrue(mat5 == 0) mat6 = createMatrix(1, 4) self.assertTrue(mat6 == 0) mat7 = createMatrix(3, Q) self.assertTrue(mat7.row == mat7.column) self.assertTrue(mat7 == 0) self.assertEqual(mat7.coeff_ring, Q) mat8 = createMatrix(7) self.assertTrue(mat8 == 0)
def _substitution_by_base_mul(P, ele, base_mul, one_gamma, max_j=False): """ return P(ele) with respect to basis (gamma_i), where P is a polynomial, ele is a vector w.r.t. gamma_i. (base_mul)_ij express gamma_i * gamma_j This function uses digital method (Horner method). """ coeff = reversed(P.sorted) mul = lambda x, y: _vect_mul_by_base_mul(x, y, base_mul, max_j) return algorithm.digital_method( coeff, ele, lambda x, y: x + y, mul, lambda a, x: a * x, algorithm.powering_func(one_gamma, mul), vector.Vector([base_mul.coeff_ring.zero] * base_mul.row), one_gamma)
def _vect_mul_by_base_mul(self, other, base_mul, max_j=False): """ return self * other with respect to basis (gamma_i), where self, other are vector. (base_mul)_ij express gamma_i gamma_j """ n = base_mul.row sol_val = vector.Vector([0] * n) for i1 in range(1, n + 1): for i2 in range(1, n + 1): if not max_j: sol_val += self[i1] * other[ i2] * module._symmetric_element(i1, i2, base_mul) else: sol_val += self[i1] * other[ i2] * _mul_place(i1, i2, base_mul, max_j) return sol_val
def testHermiteNormalForm(self): already = createMatrix(4, 3, [1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1]) h = already.hermiteNormalForm() self.assertEqual(h, already) lessrank = createMatrix(2, 3, [1, 0, 0, 0, 1, 0]) h = lessrank.hermiteNormalForm() self.assertEqual(h.row, lessrank.row) self.assertEqual(h.column, lessrank.column) zerovec = vector.Vector([0, 0]) self.assertEqual(zerovec, h.getColumn(1)) square = createMatrix(3, 3, [1, 0, 0, 0, 1, 1, 0, 1, 1]) h = square.hermiteNormalForm() self.assertEqual(h.row, square.row) self.assertEqual(h.column, square.column) hermite = createMatrix(3, 3, [0, 1, 0, 0, 0, 1, 0, 0, 1]) self.assertEqual(hermite, h)
def _base_multiplication(base, number_field): """ return [base[i] * base[j]] (as a numberfield element) this is a precomputation for computing _module_mul """ n = number_field.degree polynomial = number_field.polynomial base_int, base_denom = _toIntegerMatrix(base) base_alg = [BasicAlgNumber([base_int[j], 1], polynomial) for j in range(1, n + 1)] base_ij_list = [] for j in range(n): for i in range(j + 1): base_ij = base_alg[i] * base_alg[j] base_ij_list.append( vector.Vector([base_ij.coeff[k] * rational.Rational(1, base_denom ** 2) for k in range(n)])) base_ij = base.inverse( matrix.FieldMatrix(n, len(base_ij_list), base_ij_list)) return base_ij
def _splitting_squarefree(p, H, base_multiply, A, gamma_mul, alpha): """ split squarefree part """ F_p = finitefield.FinitePrimeField(p) if H == None: n = base_multiply.row f = n H_new = matrix.zeroMatrix(n, 1, F_p) else: n = H.row f = n - H.column H_new = H.copy() # step 12 one_gamma = vector.Vector([F_p.one] + [F_p.zero] * (f - 1)) # w.r.t. gamma_1 minpoly_matrix_alpha = matrix.FieldMatrix(f, 2, [one_gamma, alpha]) ker = minpoly_matrix_alpha.kernel() alpha_pow = alpha while ker == None: alpha_pow = _vect_mul_by_base_mul(alpha_pow, alpha, gamma_mul, f) minpoly_matrix_alpha.extendColumn(alpha_pow) ker = minpoly_matrix_alpha.kernel() minpoly_alpha = uniutil.FinitePrimeFieldPolynomial(enumerate(ker[1].compo), F_p) # step 13 m_list = minpoly_alpha.factor() # step 14 L = [] for (m_s, i) in m_list: M_s = H_new.copy() beta_s_gamma = _substitution_by_base_mul(m_s, alpha, gamma_mul, one_gamma, f) # beta_s_gamma (w.r.t. gamma) -> beta_s (w.r.t. omega) beta_s = A * beta_s_gamma omega_beta_s = _matrix_mul_by_base_mul(matrix.unitMatrix(n, F_p), beta_s.toMatrix(True), base_multiply) M_s.extendColumn(omega_beta_s) L.append(M_s.image()) return L
def _HNF_solve(self, other): """ return X over coeff_ring s.t. self * X = other, where self is HNF, other is vector """ if self.row != len(other): raise vector.VectorSizeError() n = self.column zero = self.coeff_ring.zero X = vector.Vector([zero] * n) # search non-zero entry for i in range(1, self.row + 1)[::-1]: if self[i, n] != zero: break if other[i] != zero: return False else: return X # solve HNF system (only integral solution) for j in range(1, n + 1)[::-1]: sum_i = other[i] for k in range(j + 1, n + 1): sum_i -= X[k] * self[i, k] try: X[j] = ring.exact_division(sum_i, self[i, j]) except ValueError: # division is not exact return False ii = i i -= 1 for i in range(1, ii)[::-1]: if j != 1 and self[i, j - 1] != zero: break sum_i = X[j] * self[i, j] for k in range(j + 1, n + 1): sum_i += X[k] * self[i, k] if sum_i != other[i]: return False if i == 0: break return X
def represent_element(self, other): """ represent other as a linear combination with generators of self if other not in self, return False Note that we do not assume self.mat_repr is HNF """ #if other not in self.number_field: # return False theta_repr = (self.base * self.mat_repr) theta_repr.toFieldMatrix() pseudo_vect_repr = theta_repr.inverseImage( vector.Vector(other.coeff)) pseudo_vect_repr = pseudo_vect_repr[1] gcd_self_other = gcd.gcd(self.denominator, other.denom) multiply_numerator = self.denominator // gcd_self_other multiply_denominator = other.denom // gcd_self_other def getNumerator_and_Denominator(ele): """ get the pair of numerator and denominator of ele """ if rational.isIntegerObject(ele): return (ele, 1) else: # rational return (ele.numerator, ele.denominator) list_repr = [] for j in range(1, len(pseudo_vect_repr) + 1): try: numer, denom = getNumerator_and_Denominator( pseudo_vect_repr[j]) list_repr_ele = ring.exact_division( numer * multiply_numerator, denom * multiply_denominator) list_repr.append(list_repr_ele) except ValueError: # division is not exact return False return list_repr
def _module_mul(self, other): """ return self * other as the multiplication of modules """ #if self.number_field != other.number_field: # raise NotImplementedError if self.base != other.base: new_self = self.change_base_module(other.base) else: new_self = self.copy() base_mul = other._base_multiplication() n = self.number_field.degree new_mat_repr = [] for k1 in range(1, new_self.mat_repr.column + 1): for k2 in range(1, other.mat_repr.column + 1): new_mat_repr_ele = vector.Vector([0] * n) for i1 in range(1, n + 1): for i2 in range(1, n + 1): new_mat_repr_ele += new_self.mat_repr[ i1, k1] * other.mat_repr[i2, k2] * _symmetric_element( i1, i2, base_mul) new_mat_repr.append(new_mat_repr_ele) new_mat_repr, denom, numer = _toIntegerMatrix( matrix.FieldMatrix(n, len(new_mat_repr), new_mat_repr), 1) denom = new_self.denominator * other.denominator * denom gcds = gcd.gcd(denom, numer) if gcds != 1: denom = ring.exact_division(denom, gcds) numer = ring.exact_division(numer, gcds) if numer != 1: mat_repr = numer * new_mat_repr else: mat_repr = new_mat_repr sol = self.__class__([mat_repr, denom], self.number_field, other.base) sol.toHNF() return sol
def change_base_module(self, other_base): """ change base_module to other_base_module (i.e. represent with respect to base_module) """ if self.base == other_base: return self n = self.number_field.degree if isinstance(other_base, list): other_base = matrix.FieldSquareMatrix( n, [vector.Vector(other_base[i]) for i in range(n)]) else: # matrix repr other_base = other_base.copy() tr_base_mat, tr_base_denom = _toIntegerMatrix( other_base.inverse(self.base)) denom = tr_base_denom * self.denominator mat_repr, numer = _toIntegerMatrix(tr_base_mat * self.mat_repr, 2) d = gcd.gcd(denom, numer) if d != 1: denom = ring.exact_division(denom, d) numer = ring.exact_division(numer, d) if numer != 1: mat_repr = numer * mat_repr return self.__class__([mat_repr, denom], self.number_field, other_base)
def _div_mod_pO(self, other, base_multiply, p): """ ideal division modulo pO by using base_multiply """ n = other.row m = other.column F_p = finitefield.FinitePrimeField(p) #Algo 2.3.7 if self == None: self_new = matrix.zeroMatrix(n, F_p) r = 0 else: self_new = self r = self.column if r == m: return matrix.unitMatrix(n, F_p) # if r > m, raise NoInverseImage error X = matrix.Subspace.fromMatrix(other.inverseImage(self_new)) B = X.supplementBasis() other_self = other * B # first r columns are self, others are supplement other_self.toFieldMatrix() gamma_part = other_self.subMatrix(list(range(1, n + 1)), list(range(r + 1, m + 1))) omega_gamma = other_self.inverseImage( _matrix_mul_by_base_mul(matrix.unitMatrix(n, F_p), gamma_part, base_multiply)) vect_list = [] for k in range(1, n + 1): vect = vector.Vector([F_p.zero] * ((m - r)**2)) for i in range(1, m - r + 1): for j in range(1, m - r + 1): vect[(m - r) * (i - 1) + j] = _mul_place( k, i, omega_gamma, m - r)[j + r] vect_list.append(vect) return matrix.FieldMatrix((m - r)**2, n, vect_list).kernel()
def to_HNFRepresentation(self): """ Transform self to the corresponding ideal as HNF representation """ int_ring = self.number_field.integer_ring() n = self.number_field.degree polynomial = self.number_field.polynomial k = len(self.generator) # separate coeff and denom for generators and base gen_denom = reduce(gcd.lcm, (self.generator[j].denom for j in range(k))) gen_list = [gen_denom * self.generator[j] for j in range(k)] base_int, base_denom = _toIntegerMatrix(int_ring) base_alg = [ BasicAlgNumber([base_int[j], 1], polynomial) for j in range(1, n + 1) ] repr_mat_list = [] for gen in gen_list: for base in base_alg: new_gen = gen * base repr_mat_list.append( vector.Vector([new_gen.coeff[j] for j in range(n)])) mat_repr = matrix.RingMatrix(n, n * k, repr_mat_list) new_mat_repr, numer = _toIntegerMatrix(mat_repr, 2) denom = gen_denom * base_denom denom_gcd = gcd.gcd(numer, denom) if denom_gcd != 1: denom = ring.exact_division(denom, denom_gcd) numer = ring.exact_division(numer, denom_gcd) if numer != 1: new_mat_repr = numer * new_mat_repr else: new_mat_repr = mat_repr return Ideal([new_mat_repr, denom], self.number_field)
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 testGetColumn(self): col1 = vector.Vector([-12, -1, 0]) self.assertEqual(col1, a4.getColumn(2)) col2 = vector.Vector([1, 3]) self.assertEqual(col2, b1.getColumn(1))
def testVectorMul(self): mul = vector.Vector([9, 19]) self.assertEqual(mul, b1 * v1)
def testGetitem(self): self.assertEqual(2, a1[1, 2]) self.assertEqual(-2, b2[2, 2]) self.assertRaises(IndexError, a1.__getitem__, "wrong") self.assertEqual(vector.Vector([21, 1, 0]), a4[1])
def testGetItem(self): v1 = vector.Vector([1,2,3]) assert v1[1] == 1
def testSetItem(self): v1 = vector.Vector([1,2,3]) v1[3] = 99 assert v1[3] == 99
def testLen(self): v1 = vector.Vector([1,2,3]) assert len(v1) == 3
def relationLattice(self): """ Return relation lattice basis as column vector matrix for generator. If B[j]=transpose(b[1,j],b[2,j],..,b[l,j]), it satisfies that product(generator[i]**b[i,j])=1 for each j. """ if not hasattr(self, "relation"): l = len(self.generator) b = matrix.RingSquareMatrix(l) H1 = [(self.identity(), vector.Vector([0] * l))] H2 = list(H1) m = 1 a_baby_s, giant_s = list(H1), list(H2) pro_I1, pro_I2, pro_diag = 1, 1, 1 e_vec = [] g_gen = [] for i in range(1, l + 1): e_i = vector.Vector([0] * l) e_i[i] = 1 e_vec.append(e_i) g_gen.append(self.generator[i - 1]) for j in range(1, l + 1): e = 1 baby_s = list(a_baby_s) baby_e = GroupElement(g_gen[j - 1]) giant_e = GroupElement(g_gen[j - 1]) flag = False while not flag: for (g_g, v) in giant_s: for (g_b, w) in baby_s: if g_g.ope(giant_e) == g_b: b[j] = v + w + (e * (e + 1) >> 1) * e_vec[j - 1] flag = True break if flag: break if flag: break for (g_a, v_a) in a_baby_s: baby_s.append( (g_a.ope(baby_e), v_a - e * e_vec[j - 1])) e += 1 baby_e = baby_e.ope(g_gen[j - 1]) giant_e = giant_e.ope(baby_e) if (j < l) and (b[j, j] > 1): pro_diag *= b[j, j] pro_diag_root = math.sqrt(pro_diag) if (b[j, j] * pro_I1) <= pro_diag_root or j == 1: temp = list(H1) for (g, v) in temp: g_j_inv = g_gen[j - 1].inverse() H1_1 = GroupElement(g) for x in range(1, b[j, j]): H1_1 = H1_1.ope(g_j_inv) H1.append((H1_1, v + x * e_vec[j - 1])) pro_I1 *= b[j, j] else: if m > 1: temp = list(H2) for (g, v) in temp: H2_1 = GroupElement(g) for x in range(1, b[m, m]): H2_1 = H2_1.ope(g_gen[m - 1]) H2.append((H2_1, v + x * e_vec[m - 1])) pro_I2 *= b[m, m] m = j s = int(math.ceil(pro_diag_root / pro_I1)) if len(H2) > 1: t = int(math.ceil(pro_diag_root / pro_I2)) else: t = 1 a_baby_s, giant_s = list(H1), list(H2) g_m_inv = g_gen[m - 1].inverse() for (h1, v) in H1: H1_1 = GroupElement(h1) for r in range(1, s): H1_1 = H1_1.ope(g_m_inv) a_baby_s.append((H1_1, v + r * e_vec[m - 1])) g_m_s = g_gen[m - 1].ope2(s) for (h2, v) in H2: H2_1 = GroupElement(h2) for q in range(1, t): H2_1 = H2_1.ope(g_m_s) giant_s.append((H2_1, v + (q * s) * e_vec[m - 1])) self.relation = b return self.relation
def testComplex(self): cv1 = vector.Vector([1, 0+1j]) cv2 = vector.Vector([0-1j, 1]) self.assertEqual(0+2j, vector.innerProduct(cv1, cv2)) self.assertEqual(0-2j, vector.innerProduct(cv2, cv1))
def testAdd(self): v1 = vector.Vector([1,2,3]) v2 = vector.Vector([0,-2,2]) assert v1+v2 == vector.Vector([1,0,5])
def testReals(self): rv1 = vector.Vector([0, 2, 0]) rv2 = vector.Vector([2, 0, -9]) self.assertEqual(0, vector.innerProduct(rv1, rv2))
def testIterator(self): v = vector.Vector([2, 0, -9]) l = list(v) self.assertEqual(3, len(l), str(l))
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 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 testIndexOfNoneZero(self): v = vector.Vector([0,2,0]) assert v.indexOfNoneZero() == 2