def _check_H(p, H, field, gamma_mul): """ If H express the prime ideal, return (H, f), where f: residual degree. Else return some column of M_1 (not (1,0,..,0)^t). """ F_p = finitefield.FinitePrimeField(p) if H == None: f = field.degree else: f = H.row - H.column # rank(A), A.column # CCANT Algo 6.2.9 step 10-11 # step 10 B = matrix.unitMatrix(f, F_p) M_basis = [] for j in range(1, f + 1): alpha_pow = _pow_by_base_mul(B[j], p, gamma_mul, f) alpha_pow -= B[j] M_basis.append(alpha_pow) M_1 = matrix.FieldMatrix(f, f, M_basis).kernel() # step 11 if M_1.column > 1: # dim(M_1) > 1 return M_1[M_1.column] else: H_simple = _two_element_repr_prime_ideal( p, H.map(lambda x: x.getResidue()), field, f) p_alg = algfield.BasicAlgNumber([[p] + [0] * (field.degree - 1), 1], field.polynomial) sol = module.Ideal_with_generator([p_alg, H_simple]) return (sol, f)
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( range(1, n + 1), 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 _matrix_mul_by_base_mul(self, other, base_mul, max_j=False): """ return self * other with respect to basis (gamma_i), where self, other are matrix. (base_mul)_ij express gamma_i gamma_j """ n = base_mul.row sol = [] for k1 in range(1, self.column + 1): for k2 in range(1, other.column + 1): sol_ele = _vect_mul_by_base_mul( self[k1], other[k2], base_mul, max_j) sol.append(sol_ele) return matrix.FieldMatrix(n, len(sol), sol)
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 _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 _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