def _vect_elim_fct(basis, place=None, dim=None, infolevel=0, residue_fct=None): r""" Find a relation between vectors raising the valuation. INPUT: - ``basis`` -- a list of length ``d`` of vectors over a valued fields, or of iterables with values in a valued field. The elements should be iterable at least up to index ``dim-1``. All elements should have valuation 0, and the valuation 0 part of the first ``(d-1)`` elements of the basis should be linearly independent. - ``dim`` (default: length of the basis) -- the dimension of the vector space to consider; it should be at least ``d``. - ``place`` (default: None) -- the point at which to evaluate the valuation; not supported over all fields OUTPUT: A list ``alpha`` of ``d`` elements of the base field such that ``alpha[0]*basis[0] + ... + alpha[d-1]*basis[d-1]`` has positive valuation, or `None` if no such relation exists. Under the assumptions, it is guaranteed that ``alpha[d-1] == 1``. EXAMPLES:: # TODO: Add examples with plain vectors? sage: from ore_algebra.tools import _vect_elim_fct sage: k.<q> = LaurentSeriesRing(QQ) sage: V.<t> = PolynomialRing(k) sage: b = [V(1),V(1+q*t)] sage: v = _vect_elim_fct(b); print(v) (-1, 1) sage: v[0]*b[0] + v[1]*b[1] q*t sage: v = _vect_elim_fct([V(1),V(t)]); print(v) None Beware of unexpected results if ``dim`` is not properly set or obviously guessable. sage: V.<t> = PolynomialRing(k) sage: v = _vect_elim_fct([t+q]); print(v) (1) sage: v = _vect_elim_fct([t+q],2); print(v) None Over the rationals, we can work over different places: sage: P.<q> = PolynomialRing(QQ) sage: k = P.fraction_field() sage: V.<t> = PolynomialRing(k) sage: b = [V(1),V(1+q*t)] sage: v = _vect_elim_fct(b) sage: print(v) (-1, 1) sage: v[0]*b[0] + v[1]*b[1] q*t sage: v = _vect_elim_fct(b, place=1+q) sage: print(v) None """ # Helpers print1 = print if infolevel >= 1 else lambda *a, **k: None print2 = print if infolevel >= 2 else lambda *a, **k: None print3 = print if infolevel >= 3 else lambda *a, **k: None d = len(basis) if dim is None: dim = d if residue_fct is None: residue_fct = _residue M = Matrix([[residue_fct(basis[i][j], place) for j in range(dim)] for i in range(d)]) print2(" [elim_fct] Matrix:") print2(M) K = M.left_kernel().basis() if K: return (1 / K[0][-1]) * K[0] else: return None
def basis_for_p_cokernel(S, C, p): r""" Return a basis for the group of ideals supported on ``S`` (mod ``p``'th-powers) whose class in the class group ``C`` is a ``p``'th power, together with a function which takes the ``S``-exponents of such an ideal and returns its coordinates on this basis. INPUT: - ``S`` (list) -- a list of prime ideals in a number field ``K``. - ``C`` (class group) -- the ideal class group of ``K``. - ``p`` (prime) -- a prime number. OUTPUT: (tuple) (``b``, ``f``) where - ``b`` is a list of ideals which is a basis for the group of ideals supported on ``S`` (modulo ``p``'th powers) whose ideal class is a ``p``'th power; - ``f`` is a function which takes such an ideal and returns its coordinates with respect to this basis. EXAMPLES:: sage: from sage.rings.number_field.selmer_group import basis_for_p_cokernel sage: K.<a> = NumberField(x^2 - x + 58) sage: S = K.ideal(30).support(); S [Fractional ideal (2, a), Fractional ideal (2, a + 1), Fractional ideal (3, a + 1), Fractional ideal (5, a + 1), Fractional ideal (5, a + 3)] sage: C = K.class_group() sage: C.gens_orders() (6, 2) sage: [C(P).exponents() for P in S] [(5, 0), (1, 0), (3, 1), (1, 1), (5, 1)] sage: b, f = basis_for_p_cokernel(S, C, 2); b [Fractional ideal (2), Fractional ideal (15, a + 13), Fractional ideal (5)] sage: b, f = basis_for_p_cokernel(S, C, 3); b [Fractional ideal (50, a + 18), Fractional ideal (10, a + 3), Fractional ideal (3, a + 1), Fractional ideal (5)] sage: b, f = basis_for_p_cokernel(S, C, 5); b [Fractional ideal (2, a), Fractional ideal (2, a + 1), Fractional ideal (3, a + 1), Fractional ideal (5, a + 1), Fractional ideal (5, a + 3)] """ from sage.matrix.constructor import Matrix M = Matrix(GF(p), [_coords_in_C_mod_p(P, C, p) for P in S]) k = M.left_kernel() bas = [prod([P ** bj.lift() for P, bj in zip(S, b.list())], C.number_field().ideal(1)) for b in k.basis()] return bas, k.coordinate_vector