Exemple #1
0
            def sage_ideal(vars, eqns):

                polynomialRing = PolynomialRing(RationalField(),
                                                vars,
                                                order='lex')

                return Ideal(polynomialRing, [sage_eqn(eqn) for eqn in eqns])
Exemple #2
0
def conv(N):
    file = "data/%s" % N
    if not os.path.exists(file):
        raise RuntimeError, "Data for level %s does not exist." % N

    F = open(file).read()
    i = F.find(":=")
    if i == -1:
        raise RuntimeError, "Syntax error in file for level %s." % N
    F = F[i + 2:]
    TRANS = [("[*", "["), ("*]", "]"), ("<","["), (">","]"), \
             (";",""), ("\n",""), ("^","**")]
    for z, w in TRANS:
        F = F.replace(z, w)
    X = []
    # Define x so the eval below works.
    R = PolynomialRing(RationalField())
    x = R.gen()
    print "starting eval."
    #print "F = ", F
    for f in eval(F):
        print "creating object from f=", f[:4]
        cp = {}
        disc = 0
        for z in f[5]:
            g = R(z[1])
            disc = GCD(disc, g.discriminant())
            cp[z[0]] = g
        X.append(ModularForm(f[0], f[1], f[2], f[3], f[4], cp, disc))
    return X
Exemple #3
0
    def __init_extra__(self):
        """
        Sets up the coercions between the different bases

        EXAMPLES::

            sage: Sym = SymmetricFunctions(QQ) # indirect doctest
            sage: s = Sym.s(); p = Sym.p()
            sage: f = s.coerce_map_from(p); f
            Generic morphism:
              From: Symmetric Functions over Rational Field in the powersum basis
              To:   Symmetric Functions over Rational Field in the Schur basis
            sage: p.an_element()
            2*p[] + 2*p[1] + 3*p[2]
            sage: f(p.an_element())
            2*s[] + 2*s[1] - 3*s[1, 1] + 3*s[2]
            sage: f(p.an_element()) == p.an_element()
            True

        """
        #powersum   = self.powersum  ()
        #complete   = self.complete  ()
        #elementary = self.elementary()
        #schur      = self.schur     ()
        #monomial   = self.monomial  ()

        iso = self.register_isomorphism

        from sage.combinat.sf.classical import conversion_functions

        for (basis1_name, basis2_name) in conversion_functions:
            basis1 = getattr(self, basis1_name)()
            basis2 = getattr(self, basis2_name)()
            on_basis = SymmetricaConversionOnBasis(
                t=conversion_functions[basis1_name, basis2_name],
                domain=basis1,
                codomain=basis2)
            from sage.rings.rational_field import RationalField
            if basis2_name != "powersum" or self._base.has_coerce_map_from(
                    RationalField()):
                iso(basis1._module_morphism(on_basis, codomain=basis2))
            else:
                # Don't register conversions to powersums as coercions,
                # unless the base ring is a `\QQ`-algebra
                # (otherwise the coercion graph loses commutativity).
                iso(basis1._module_morphism(on_basis, codomain=basis2),
                    only_conversion=True)
Exemple #4
0
    def antipode_by_coercion(self, element):
        r"""
        The antipode of ``element`` via coercion to and from the power-sum
        basis or the Schur basis (depending on whether the power sums really
        form a basis over the given ground ring).

        INPUT:

        - ``element`` -- element in a basis of the ring of symmetric functions

        EXAMPLES::

            sage: Sym = SymmetricFunctions(QQ)
            sage: m = Sym.monomial()
            sage: m[3,2].antipode()
            m[3, 2] + 2*m[5]
            sage: m.antipode_by_coercion(m[3,2])
            m[3, 2] + 2*m[5]

            sage: Sym = SymmetricFunctions(ZZ)
            sage: m = Sym.monomial()
            sage: m[3,2].antipode()
            m[3, 2] + 2*m[5]
            sage: m.antipode_by_coercion(m[3,2])
            m[3, 2] + 2*m[5]

        .. TODO::

            Is there a not too difficult way to get the power-sum computations
            to work over any ring, not just one with coercion from `\QQ`?
        """
        from sage.rings.rational_field import RationalField
        if self.has_coerce_map_from(RationalField()):
            p = self.realization_of().powersum()
            return self(p.antipode(p(element)))

        s = self.realization_of().schur()
        return self(s.antipode(s(element)))
Exemple #5
0
def experiment():
    rank = 5
    level = 4
    num_points = 11

    client = cbc.CBClient()
    liealg = cbd.TypeALieAlgebra(rank, store_fusion=True, exact=True)
    rays = []
    wts = []
    ranks = []
    for wt in liealg.get_weights(level):
        if wt == tuple([0 for x in range(0, rank)]):
            continue
        cbb = cbd.SymmetricConformalBlocksBundle(client, liealg, wt,
                                                 num_points, level)
        if cbb.get_rank() == 0:
            continue
        divisor = cbb.get_symmetrized_divisor()
        if divisor == [
                sage.Rational(0) for x in range(0, num_points // 2 - 1)
        ]:
            continue
        rays = rays + [divisor]
        wts = wts + [wt]
        ranks = ranks + [cbb.get_rank()]
        #print(wt, cbb.get_rank(), divisor)

    p = Polyhedron(rays=rays, base_ring=RationalField(), backend="cdd")
    extremal_rays = [list(v.vector()) for v in p.Vrepresentation()]
    c = Cone(p)
    print("Extremal rays:")
    for i in range(0, len(rays)):
        ray = rays[i]
        wt = wts[i]
        rk = ranks[i]
        if ray in extremal_rays:
            print(rk, wt, ray)
Exemple #6
0
import sage.combinat.skew_partition
import sage.libs.symmetrica.all as symmetrica  # used in eval()

from sage.rings.integer_ring import IntegerRing
from sage.rings.rational_field import RationalField

import hall_littlewood
import sfa
import llt
import macdonald
import jack
import orthotriang
import kschur

ZZ = IntegerRing()
QQ = RationalField()

translate = {
    'monomial': 'MONOMIAL',
    'homogeneous': 'HOMSYM',
    'powersum': 'POWSYM',
    'elementary': 'ELMSYM',
    'Schur': 'SCHUR'
}

conversion_functions = {}


def init():
    """
    Set up the conversion functions between the classical bases.
Exemple #7
0
    def _precompute(self, n):
        """
        Compute the transition matrices between ``self`` and its dual basis for
        the homogeneous component of size `n`. The result is not returned,
        but stored in the cache.

        INPUT:

        - ``n`` -- nonnegative integer

        EXAMPLES::

            sage: e = SymmetricFunctions(QQ['t']).elementary()
            sage: f = e.dual_basis()
            sage: f._precompute(0)
            sage: f._precompute(1)
            sage: f._precompute(2)
            sage: l = lambda c: [ (i[0],[j for j in sorted(i[1].items())]) for i in sorted(c.items())]
            sage: l(f._to_self_cache) # note: this may depend on possible previous computations!
            [([], [([], 1)]), ([1], [([1], 1)]), ([1, 1], [([1, 1], 2), ([2], 1)]), ([2], [([1, 1], 1), ([2], 1)])]
            sage: l(f._from_self_cache)
            [([], [([], 1)]), ([1], [([1], 1)]), ([1, 1], [([1, 1], 1), ([2], -1)]), ([2], [([1, 1], -1), ([2], 2)])]
            sage: f._transition_matrices[2]
            [1 1]
            [1 2]
            sage: f._inverse_transition_matrices[2]
            [ 2 -1]
            [-1  1]
        """
        base_ring = self.base_ring()
        zero = base_ring.zero()

        # Handle the n == 0 and n == 1 cases separately
        if n == 0 or n == 1:
            part = sage.combinat.partition.Partition([1]*n)
            self._to_self_cache[ part ] = { part: base_ring.one() }
            self._from_self_cache[ part ] = { part: base_ring.one() }
            self._transition_matrices[n] = matrix(base_ring, [[1]])
            self._inverse_transition_matrices[n] = matrix(base_ring, [[1]])
            return

        partitions_n = sage.combinat.partition.Partitions_n(n).list()

        # We now get separated into two cases, depending on whether we can
        # use the power-sum basis to compute the matrix, or we have to use
        # the Schur basis.

        from sage.rings.rational_field import RationalField
        if (not base_ring.has_coerce_map_from(RationalField())) and self._scalar == sage.combinat.sf.sfa.zee:
            # This is the case when (due to the base ring not being a
            # \mathbb{Q}-algebra) we cannot use the power-sum basis,
            # but (due to zee being the standard zee function) we can
            # use the Schur basis.

            schur = self._sym.schur()

            # Get all the basis elements of the n^th homogeneous component
            # of the dual basis and express them in the Schur basis
            d = {}
            for part in partitions_n:
                d[part] = schur(self._dual_basis(part))._monomial_coefficients

            # This contains the data for the transition matrix from the
            # dual basis to self.
            transition_matrix_n = matrix(base_ring, len(partitions_n), len(partitions_n))

            # This first section calculates how the basis elements of the
            # dual basis are expressed in terms of self's basis.

            # For every partition p of size n, compute self(p) in
            # terms of the dual basis using the scalar product.
            i = 0
            for s_part in partitions_n:
                # s_part corresponds to self(dual_basis(part))
                # s_mcs  corresponds to self(dual_basis(part))._monomial_coefficients
                s_mcs = {}

                # We need to compute the scalar product of d[s_part] and
                # all of the d[p_part]'s
                j = 0
                for p_part in partitions_n:
                    # Compute the scalar product of d[s_part] and d[p_part]
                    sp = zero
                    for ds_part in d[s_part]:
                        if ds_part in d[p_part]:
                            sp += d[s_part][ds_part]*d[p_part][ds_part]
                    if sp != zero:
                        s_mcs[p_part] = sp
                        transition_matrix_n[i,j] = sp

                    j += 1

                self._to_self_cache[ s_part ] = s_mcs
                i += 1

        else:
            # Now the other case. Note that just being in this case doesn't
            # guarantee that we can use the power-sum basis, but we can at
            # least try.

            # Get all the basis elements of the n^th homogeneous component
            # of the dual basis and express them in the power-sum basis
            d = {}
            for part in partitions_n:
                d[part] = self._p(self._dual_basis(part))._monomial_coefficients

            # This contains the data for the transition matrix from the
            # dual basis to self.
            transition_matrix_n = matrix(base_ring, len(partitions_n), len(partitions_n))

            # This first section calculates how the basis elements of the
            # dual basis are expressed in terms of self's basis.

            # For every partition p of size n, compute self(p) in
            # terms of the dual basis using the scalar product.
            i = 0
            for s_part in partitions_n:
                # s_part corresponds to self(dual_basis(part))
                # s_mcs  corresponds to self(dual_basis(part))._monomial_coefficients
                s_mcs = {}

                # We need to compute the scalar product of d[s_part] and
                # all of the d[p_part]'s
                j = 0
                for p_part in partitions_n:
                    # Compute the scalar product of d[s_part] and d[p_part]
                    sp = zero
                    for ds_part in d[s_part]:
                        if ds_part in d[p_part]:
                            sp += d[s_part][ds_part]*d[p_part][ds_part]*self._scalar(ds_part)
                    if sp != zero:
                        s_mcs[p_part] = sp
                        transition_matrix_n[i,j] = sp

                    j += 1

                self._to_self_cache[ s_part ] = s_mcs
                i += 1

        # Save the transition matrix
        self._transition_matrices[n] = transition_matrix_n

        # This second section calculates how the basis elements of
        # self expand in terms of the dual basis.  We do this by
        # computing the inverse of the matrix obtained above.
        inverse_transition = ~transition_matrix_n

        for i in range(len(partitions_n)):
            d_mcs = {}
            for j in range(len(partitions_n)):
                if inverse_transition[i,j] != zero:
                    d_mcs[ partitions_n[j] ] = inverse_transition[i,j]

            self._from_self_cache[ partitions_n[i] ] = d_mcs

        self._inverse_transition_matrices[n] = inverse_transition
Exemple #8
0
def splitting_field(poly,
                    name,
                    map=False,
                    degree_multiple=None,
                    abort_degree=None,
                    simplify=True,
                    simplify_all=False):
    r"""
    Compute the splitting field of a given polynomial, defined over a
    number field.

    INPUT:

    - ``poly`` -- a monic polynomial over a number field

    - ``name`` -- a variable name for the number field

    - ``map`` -- (default: ``False``) also return an embedding of
      ``poly`` into the resulting field. Note that computing this
      embedding might be expensive.

    - ``degree_multiple`` -- a multiple of the absolute degree of
      the splitting field.  If ``degree_multiple`` equals the actual
      degree, this can enormously speed up the computation.

    - ``abort_degree`` -- abort by raising a :class:`SplittingFieldAbort`
      if it can be determined that the absolute degree of the splitting
      field is strictly larger than ``abort_degree``.

    - ``simplify`` -- (default: ``True``) during the algorithm, try
      to find a simpler defining polynomial for the intermediate
      number fields using PARI's ``polred()``.  This usually speeds
      up the computation but can also considerably slow it down.
      Try and see what works best in the given situation.

    - ``simplify_all`` -- (default: ``False``) If ``True``, simplify
      intermediate fields and also the resulting number field.

    OUTPUT:

    If ``map`` is ``False``, the splitting field as an absolute number
    field.  If ``map`` is ``True``, a tuple ``(K, phi)`` where ``phi``
    is an embedding of the base field in ``K``.

    EXAMPLES::

        sage: R.<x> = PolynomialRing(QQ)
        sage: K.<a> = (x^3 + 2).splitting_field(); K
        Number Field in a with defining polynomial x^6 + 3*x^5 + 6*x^4 + 11*x^3 + 12*x^2 - 3*x + 1
        sage: K.<a> = (x^3 - 3*x + 1).splitting_field(); K
        Number Field in a with defining polynomial x^3 - 3*x + 1

    The ``simplify`` and ``simplify_all`` flags usually yield
    fields defined by polynomials with smaller coefficients.
    By default, ``simplify`` is True and ``simplify_all`` is False.

    ::

        sage: (x^4 - x + 1).splitting_field('a', simplify=False)
        Number Field in a with defining polynomial x^24 - 2780*x^22 + 2*x^21 + 3527512*x^20 - 2876*x^19 - 2701391985*x^18 + 945948*x^17 + 1390511639677*x^16 + 736757420*x^15 - 506816498313560*x^14 - 822702898220*x^13 + 134120588299548463*x^12 + 362240696528256*x^11 - 25964582366880639486*x^10 - 91743672243419990*x^9 + 3649429473447308439427*x^8 + 14310332927134072336*x^7 - 363192569823568746892571*x^6 - 1353403793640477725898*x^5 + 24293393281774560140427565*x^4 + 70673814899934142357628*x^3 - 980621447508959243128437933*x^2 - 1539841440617805445432660*x + 18065914012013502602456565991
        sage: (x^4 - x + 1).splitting_field('a', simplify=True)
        Number Field in a with defining polynomial x^24 + 8*x^23 - 32*x^22 - 310*x^21 + 540*x^20 + 4688*x^19 - 6813*x^18 - 32380*x^17 + 49525*x^16 + 102460*x^15 - 129944*x^14 - 287884*x^13 + 372727*x^12 + 150624*x^11 - 110530*x^10 - 566926*x^9 + 1062759*x^8 - 779940*x^7 + 863493*x^6 - 1623578*x^5 + 1759513*x^4 - 955624*x^3 + 459975*x^2 - 141948*x + 53919
        sage: (x^4 - x + 1).splitting_field('a', simplify_all=True)
        Number Field in a with defining polynomial x^24 - 3*x^23 + 2*x^22 - x^20 + 4*x^19 + 32*x^18 - 35*x^17 - 92*x^16 + 49*x^15 + 163*x^14 - 15*x^13 - 194*x^12 - 15*x^11 + 163*x^10 + 49*x^9 - 92*x^8 - 35*x^7 + 32*x^6 + 4*x^5 - x^4 + 2*x^2 - 3*x + 1

    Reducible polynomials also work::

        sage: pol = (x^4 - 1)*(x^2 + 1/2)*(x^2 + 1/3)
        sage: pol.splitting_field('a', simplify_all=True)
        Number Field in a with defining polynomial x^8 - x^4 + 1

    Relative situation::

        sage: R.<x> = PolynomialRing(QQ)
        sage: K.<a> = NumberField(x^3 + 2)
        sage: S.<t> = PolynomialRing(K)
        sage: L.<b> = (t^2 - a).splitting_field()
        sage: L
        Number Field in b with defining polynomial t^6 + 2

    With ``map=True``, we also get the embedding of the base field
    into the splitting field::

        sage: L.<b>, phi = (t^2 - a).splitting_field(map=True)
        sage: phi
        Ring morphism:
          From: Number Field in a with defining polynomial x^3 + 2
          To:   Number Field in b with defining polynomial t^6 + 2
          Defn: a |--> b^2
        sage: (x^4 - x + 1).splitting_field('a', simplify_all=True, map=True)[1]
        Ring morphism:
          From: Rational Field
          To:   Number Field in a with defining polynomial x^24 - 3*x^23 + 2*x^22 - x^20 + 4*x^19 + 32*x^18 - 35*x^17 - 92*x^16 + 49*x^15 + 163*x^14 - 15*x^13 - 194*x^12 - 15*x^11 + 163*x^10 + 49*x^9 - 92*x^8 - 35*x^7 + 32*x^6 + 4*x^5 - x^4 + 2*x^2 - 3*x + 1
          Defn: 1 |--> 1

    We can enable verbose messages::

        sage: from sage.misc.verbose import set_verbose
        sage: set_verbose(2)
        sage: K.<a> = (x^3 - x + 1).splitting_field()
        verbose 1 (...: splitting_field.py, splitting_field) Starting field: y
        verbose 1 (...: splitting_field.py, splitting_field) SplittingData to factor: [(3, 0)]
        verbose 2 (...: splitting_field.py, splitting_field) Done factoring (time = ...)
        verbose 1 (...: splitting_field.py, splitting_field) SplittingData to handle: [(2, 2), (3, 3)]
        verbose 1 (...: splitting_field.py, splitting_field) Bounds for absolute degree: [6, 6]
        verbose 2 (...: splitting_field.py, splitting_field) Handling polynomial x^2 + 23
        verbose 1 (...: splitting_field.py, splitting_field) New field before simplifying: x^2 + 23 (time = ...)
        verbose 1 (...: splitting_field.py, splitting_field) New field: y^2 - y + 6 (time = ...)
        verbose 2 (...: splitting_field.py, splitting_field) Converted polynomials to new field (time = ...)
        verbose 1 (...: splitting_field.py, splitting_field) SplittingData to factor: []
        verbose 2 (...: splitting_field.py, splitting_field) Done factoring (time = ...)
        verbose 1 (...: splitting_field.py, splitting_field) SplittingData to handle: [(3, 3)]
        verbose 1 (...: splitting_field.py, splitting_field) Bounds for absolute degree: [6, 6]
        verbose 2 (...: splitting_field.py, splitting_field) Handling polynomial x^3 - x + 1
        verbose 1 (...: splitting_field.py, splitting_field) New field: y^6 + 3*y^5 + 19*y^4 + 35*y^3 + 127*y^2 + 73*y + 271 (time = ...)
        sage: set_verbose(0)

    Try all Galois groups in degree 4. We use a quadratic base field
    such that ``polgalois()`` cannot be used::

        sage: R.<x> = PolynomialRing(QuadraticField(-11))
        sage: C2C2pol = x^4 - 10*x^2 + 1
        sage: C2C2pol.splitting_field('x')
        Number Field in x with defining polynomial x^8 + 24*x^6 + 608*x^4 + 9792*x^2 + 53824
        sage: C4pol = x^4 + x^3 + x^2 + x + 1
        sage: C4pol.splitting_field('x')
        Number Field in x with defining polynomial x^8 - x^7 - 2*x^6 + 5*x^5 + x^4 + 15*x^3 - 18*x^2 - 27*x + 81
        sage: D8pol = x^4 - 2
        sage: D8pol.splitting_field('x')
        Number Field in x with defining polynomial x^16 + 8*x^15 + 68*x^14 + 336*x^13 + 1514*x^12 + 5080*x^11 + 14912*x^10 + 35048*x^9 + 64959*x^8 + 93416*x^7 + 88216*x^6 + 41608*x^5 - 25586*x^4 - 60048*x^3 - 16628*x^2 + 12008*x + 34961
        sage: A4pol = x^4 - 4*x^3 + 14*x^2 - 28*x + 21
        sage: A4pol.splitting_field('x')
        Number Field in x with defining polynomial x^24 - 20*x^23 + 290*x^22 - 3048*x^21 + 26147*x^20 - 186132*x^19 + 1130626*x^18 - 5913784*x^17 + 26899345*x^16 - 106792132*x^15 + 371066538*x^14 - 1127792656*x^13 + 2991524876*x^12 - 6888328132*x^11 + 13655960064*x^10 - 23000783036*x^9 + 32244796382*x^8 - 36347834476*x^7 + 30850889884*x^6 - 16707053128*x^5 + 1896946429*x^4 + 4832907884*x^3 - 3038258802*x^2 - 200383596*x + 593179173
        sage: S4pol = x^4 + x + 1
        sage: S4pol.splitting_field('x')
        Number Field in x with defining polynomial x^48 ...

    Some bigger examples::

        sage: R.<x> = PolynomialRing(QQ)
        sage: pol15 = chebyshev_T(31, x) - 1    # 2^30*(x-1)*minpoly(cos(2*pi/31))^2
        sage: pol15.splitting_field('a')
        Number Field in a with defining polynomial x^15 - x^14 - 14*x^13 + 13*x^12 + 78*x^11 - 66*x^10 - 220*x^9 + 165*x^8 + 330*x^7 - 210*x^6 - 252*x^5 + 126*x^4 + 84*x^3 - 28*x^2 - 8*x + 1
        sage: pol48 = x^6 - 4*x^4 + 12*x^2 - 12
        sage: pol48.splitting_field('a')
        Number Field in a with defining polynomial x^48 ...

    If you somehow know the degree of the field in advance, you
    should add a ``degree_multiple`` argument.  This can speed up the
    computation, in particular for polynomials of degree >= 12 or
    for relative extensions::

        sage: pol15.splitting_field('a', degree_multiple=15)
        Number Field in a with defining polynomial x^15 + x^14 - 14*x^13 - 13*x^12 + 78*x^11 + 66*x^10 - 220*x^9 - 165*x^8 + 330*x^7 + 210*x^6 - 252*x^5 - 126*x^4 + 84*x^3 + 28*x^2 - 8*x - 1

    A value for ``degree_multiple`` which isn't actually a
    multiple of the absolute degree of the splitting field can
    either result in a wrong answer or the following exception::

        sage: pol48.splitting_field('a', degree_multiple=20)
        Traceback (most recent call last):
        ...
        ValueError: inconsistent degree_multiple in splitting_field()

    Compute the Galois closure as the splitting field of the defining polynomial::

        sage: R.<x> = PolynomialRing(QQ)
        sage: pol48 = x^6 - 4*x^4 + 12*x^2 - 12
        sage: K.<a> = NumberField(pol48)
        sage: L.<b> = pol48.change_ring(K).splitting_field()
        sage: L
        Number Field in b with defining polynomial x^48 ...

    Try all Galois groups over `\QQ` in degree 5 except for `S_5`
    (the latter is infeasible with the current implementation)::

        sage: C5pol = x^5 + x^4 - 4*x^3 - 3*x^2 + 3*x + 1
        sage: C5pol.splitting_field('x')
        Number Field in x with defining polynomial x^5 + x^4 - 4*x^3 - 3*x^2 + 3*x + 1
        sage: D10pol = x^5 - x^4 - 5*x^3 + 4*x^2 + 3*x - 1
        sage: D10pol.splitting_field('x')
        Number Field in x with defining polynomial x^10 - 28*x^8 + 216*x^6 - 681*x^4 + 902*x^2 - 401
        sage: AGL_1_5pol = x^5 - 2
        sage: AGL_1_5pol.splitting_field('x')
        Number Field in x with defining polynomial x^20 + 10*x^19 + 55*x^18 + 210*x^17 + 595*x^16 + 1300*x^15 + 2250*x^14 + 3130*x^13 + 3585*x^12 + 3500*x^11 + 2965*x^10 + 2250*x^9 + 1625*x^8 + 1150*x^7 + 750*x^6 + 400*x^5 + 275*x^4 + 100*x^3 + 75*x^2 + 25
        sage: A5pol = x^5 - x^4 + 2*x^2 - 2*x + 2
        sage: A5pol.splitting_field('x')
        Number Field in x with defining polynomial x^60 ...

    We can use the ``abort_degree`` option if we don't want to compute
    fields of too large degree (this can be used to check whether the
    splitting field has small degree)::

        sage: (x^5+x+3).splitting_field('b', abort_degree=119)
        Traceback (most recent call last):
        ...
        SplittingFieldAbort: degree of splitting field equals 120
        sage: (x^10+x+3).splitting_field('b', abort_degree=60)  # long time (10s on sage.math, 2014)
        Traceback (most recent call last):
        ...
        SplittingFieldAbort: degree of splitting field is a multiple of 180

    Use the ``degree_divisor`` attribute to recover the divisor of the
    degree of the splitting field or ``degree_multiple`` to recover a
    multiple::

        sage: from sage.rings.number_field.splitting_field import SplittingFieldAbort
        sage: try:  # long time (4s on sage.math, 2014)
        ....:     (x^8+x+1).splitting_field('b', abort_degree=60, simplify=False)
        ....: except SplittingFieldAbort as e:
        ....:     print(e.degree_divisor)
        ....:     print(e.degree_multiple)
        120
        1440

    TESTS::

        sage: from sage.rings.number_field.splitting_field import splitting_field
        sage: splitting_field(polygen(QQ), name='x', map=True, simplify_all=True)
        (Number Field in x with defining polynomial x, Ring morphism:
          From: Rational Field
          To:   Number Field in x with defining polynomial x
          Defn: 1 |--> 1)
    """
    from sage.misc.all import cputime
    from sage.misc.verbose import verbose

    degree_multiple = Integer(degree_multiple or 0)
    abort_degree = Integer(abort_degree or 0)

    # Kpol = PARI polynomial in y defining the extension found so far
    F = poly.base_ring()
    if is_RationalField(F):
        Kpol = pari("'y")
    else:
        Kpol = F.pari_polynomial("y")
    # Fgen = the generator of F as element of Q[y]/Kpol
    # (only needed if map=True)
    if map:
        Fgen = F.gen().__pari__()
    verbose("Starting field: %s" % Kpol)

    # L and Lred are lists of SplittingData.
    # L contains polynomials which are irreducible over K,
    # Lred contains polynomials which need to be factored.
    L = []
    Lred = [SplittingData(poly._pari_with_name(), degree_multiple)]

    # Main loop, handle polynomials one by one
    while True:
        # Absolute degree of current field K
        absolute_degree = Integer(Kpol.poldegree())

        # Compute minimum relative degree of splitting field
        rel_degree_divisor = Integer(1)
        for splitting in L:
            rel_degree_divisor = rel_degree_divisor.lcm(splitting.poldegree())

        # Check for early aborts
        abort_rel_degree = abort_degree // absolute_degree
        if abort_rel_degree and rel_degree_divisor > abort_rel_degree:
            raise SplittingFieldAbort(absolute_degree * rel_degree_divisor,
                                      degree_multiple)

        # First, factor polynomials in Lred and store the result in L
        verbose("SplittingData to factor: %s" %
                [s._repr_tuple() for s in Lred])
        t = cputime()
        for splitting in Lred:
            m = splitting.dm.gcd(degree_multiple).gcd(
                factorial(splitting.poldegree()))
            if m == 1:
                continue
            factors = Kpol.nffactor(splitting.pol)[0]
            for q in factors:
                d = q.poldegree()
                fac = factorial(d)
                # Multiple of the degree of the splitting field of q,
                # note that the degree equals fac iff the Galois group is S_n.
                mq = m.gcd(fac)
                if mq == 1:
                    continue
                # Multiple of the degree of the splitting field of q
                # over the field defined by adding square root of the
                # discriminant.
                # If the Galois group is contained in A_n, then mq_alt is
                # also the degree multiple over the current field K.
                # Here, we have equality if the Galois group is A_n.
                mq_alt = mq.gcd(fac // 2)

                # If we are over Q, then use PARI's polgalois() to compute
                # these degrees exactly.
                if absolute_degree == 1:
                    try:
                        G = q.polgalois()
                    except PariError:
                        pass
                    else:
                        mq = Integer(G[0])
                        mq_alt = mq // 2 if (G[1] == -1) else mq

                # In degree 4, use the cubic resolvent to refine the
                # degree bounds.
                if d == 4 and mq >= 12:  # mq equals 12 or 24
                    # Compute cubic resolvent
                    a0, a1, a2, a3, a4 = (q / q.pollead()).Vecrev()
                    assert a4 == 1
                    cubicpol = pari([
                        4 * a0 * a2 - a1 * a1 - a0 * a3 * a3, a1 * a3 - 4 * a0,
                        -a2, 1
                    ]).Polrev()
                    cubicfactors = Kpol.nffactor(cubicpol)[0]
                    if len(cubicfactors) == 1:  # A4 or S4
                        # After adding a root of the cubic resolvent,
                        # the degree of the extension defined by q
                        # is a factor 3 smaller.
                        L.append(SplittingData(cubicpol, 3))
                        rel_degree_divisor = rel_degree_divisor.lcm(3)
                        mq = mq // 3  # 4 or 8
                        mq_alt = 4
                    elif len(cubicfactors) == 2:  # C4 or D8
                        # The irreducible degree 2 factor is
                        # equivalent to x^2 - q.poldisc().
                        discpol = cubicfactors[1]
                        L.append(SplittingData(discpol, 2))
                        mq = mq_alt = 4
                    else:  # C2 x C2
                        mq = mq_alt = 4

                if mq > mq_alt >= 3:
                    # Add quadratic resolvent x^2 - D to decrease
                    # the degree multiple by a factor 2.
                    discpol = pari([-q.poldisc(), 0, 1]).Polrev()
                    discfactors = Kpol.nffactor(discpol)[0]
                    if len(discfactors) == 1:
                        # Discriminant is not a square
                        L.append(SplittingData(discpol, 2))
                        rel_degree_divisor = rel_degree_divisor.lcm(2)
                    mq = mq_alt

                L.append(SplittingData(q, mq))
                rel_degree_divisor = rel_degree_divisor.lcm(q.poldegree())
                if abort_rel_degree and rel_degree_divisor > abort_rel_degree:
                    raise SplittingFieldAbort(
                        absolute_degree * rel_degree_divisor, degree_multiple)
        verbose("Done factoring", t, level=2)

        if len(L) == 0:  # Nothing left to do
            break

        # Recompute absolute degree multiple
        new_degree_multiple = absolute_degree
        for splitting in L:
            new_degree_multiple *= splitting.dm
        degree_multiple = new_degree_multiple.gcd(degree_multiple)

        # Absolute degree divisor
        degree_divisor = rel_degree_divisor * absolute_degree

        # Sort according to degree to handle low degrees first
        L.sort(key=lambda x: x.key())
        verbose("SplittingData to handle: %s" % [s._repr_tuple() for s in L])
        verbose("Bounds for absolute degree: [%s, %s]" %
                (degree_divisor, degree_multiple))

        # Check consistency
        if degree_multiple % degree_divisor != 0:
            raise ValueError(
                "inconsistent degree_multiple in splitting_field()")
        for splitting in L:
            # The degree of the splitting field must be a multiple of
            # the degree of the polynomial. Only do this check for
            # SplittingData with minimal dm, because the higher dm are
            # defined as relative degree over the splitting field of
            # the polynomials with lesser dm.
            if splitting.dm > L[0].dm:
                break
            if splitting.dm % splitting.poldegree() != 0:
                raise ValueError(
                    "inconsistent degree_multiple in splitting_field()")

        # Add a root of f = L[0] to construct the field N = K[x]/f(x)
        splitting = L[0]
        f = splitting.pol
        verbose("Handling polynomial %s" % (f.lift()), level=2)
        t = cputime()
        Npol, KtoN, k = Kpol.rnfequation(f, flag=1)

        # Make Npol monic integral primitive, store in Mpol
        # (after this, we don't need Npol anymore, only Mpol)
        Mdiv = pari(1)
        Mpol = Npol
        while True:
            denom = Integer(Mpol.pollead())
            if denom == 1:
                break
            denom = pari(denom.factor().radical_value())
            Mpol = (Mpol * (denom**Mpol.poldegree())).subst(
                "x",
                pari([0, 1 / denom]).Polrev("x"))
            Mpol /= Mpol.content()
            Mdiv *= denom

        # We are finished for sure if we hit the degree bound
        finished = (Mpol.poldegree() >= degree_multiple)

        if simplify_all or (simplify and not finished):
            # Find a simpler defining polynomial Lpol for Mpol
            verbose("New field before simplifying: %s" % Mpol, t)
            t = cputime()
            M = Mpol.polred(flag=3)
            n = len(M[0]) - 1
            Lpol = M[1][n].change_variable_name("y")
            LtoM = M[0][n].change_variable_name("y").Mod(
                Mpol.change_variable_name("y"))
            MtoL = LtoM.modreverse()
        else:
            # Lpol = Mpol
            Lpol = Mpol.change_variable_name("y")
            MtoL = pari("'y")

        NtoL = MtoL / Mdiv
        KtoL = KtoN.lift().subst("x", NtoL).Mod(Lpol)
        Kpol = Lpol  # New Kpol (for next iteration)
        verbose("New field: %s" % Kpol, t)
        if map:
            t = cputime()
            Fgen = Fgen.lift().subst("y", KtoL)
            verbose("Computed generator of F in K", t, level=2)
        if finished:
            break

        t = cputime()

        # Convert f and elements of L from K to L and store in L
        # (if the polynomial is certain to remain irreducible) or Lred.
        Lold = L[1:]
        L = []
        Lred = []

        # First add f divided by the linear factor we obtained,
        # mg is the new degree multiple.
        mg = splitting.dm // f.poldegree()
        if mg > 1:
            g = [c.subst("y", KtoL).Mod(Lpol) for c in f.Vecrev().lift()]
            g = pari(g).Polrev()
            g /= pari([k * KtoL - NtoL, 1]).Polrev()  # divide linear factor
            Lred.append(SplittingData(g, mg))

        for splitting in Lold:
            g = [c.subst("y", KtoL) for c in splitting.pol.Vecrev().lift()]
            g = pari(g).Polrev()
            mg = splitting.dm
            if Integer(g.poldegree()).gcd(
                    f.poldegree()) == 1:  # linearly disjoint fields
                L.append(SplittingData(g, mg))
            else:
                Lred.append(SplittingData(g, mg))
        verbose("Converted polynomials to new field", t, level=2)

    # Convert Kpol to Sage and construct the absolute number field
    Kpol = PolynomialRing(RationalField(),
                          name=poly.variable_name())(Kpol / Kpol.pollead())
    K = NumberField(Kpol, name)
    if map:
        return K, F.hom(Fgen, K)
    else:
        return K
Exemple #9
0
def _solve_two_equations(eqn1, eqn2, x_val, y_val):
    """
    Given two polynomial equations with rational coefficients in 'x' and 'y'
    and real intervals for x and y to isolate a solution to the system of
    equations, return the number field generated by x and the value of y in
    that number field. If y is not contained in the number field generated
    by x, return None.
    """

    # Ring we work in Q[x][y]
    Rx = PolynomialRing(RationalField(), 'x')
    R = PolynomialRing(Rx, 'y')
    Reqn1 = R(eqn1)

    # Compute the resultant in Q[x]
    resultant = Reqn1.resultant(R(eqn2))

    # Factorize the resultant. Find the unique factor that has the given value
    # for x as a root.
    def eval_factor_res(p):
        """
        Evaluation method for the factors of the resultant. Apply polynomial
        to the given interval for x.
        """
        return p(x_val)

    resultant_factor = _find_unique_good_factor(resultant, eval_factor_res)

    resultant_factor = Rx(resultant_factor)

    # The number field generated by x.
    #
    # (The embedding passed to the NumberField is a real number, so sage
    # will raise an exception if the resultant_factor has no real roots.
    # However, such a factor should not make it through
    #    _find_unique_good_factor)

    result_number_field = NumberField(resultant_factor,
                                      'x',
                                      embedding=x_val.center())

    # Get one of the equations and think of it as an element in NumberField[y]
    yEqn = Reqn1.change_ring(result_number_field)

    # Factorize that equation over the NumberField. Find the unique factor
    # such that the given value y is a root when setting x to the given value
    # for x.
    def eval_factor_yEqn(p):
        """
        Evaluation method for the factors of the equation factored over the
        number field. We take the factor and turn it into a polynomial in
        Q[x][y]. We then put in the given intervals for x and y.
        """

        lift = p.map_coefficients(lambda c: c.lift('x'), Rx)
        return lift.substitute(x=x_val, y=y_val)

    yEqn_factor = _find_unique_good_factor(yEqn, eval_factor_yEqn)

    # If the equation for y in x is not of degree 1, then y is in a field
    # extension of the number field generated by x.
    # Bail if this happens.
    if not yEqn_factor.degree() == 1:
        return None

    # The equation of y is of the form
    #     linear_term * y + constant_term = 0
    constant_term, linear_term = yEqn_factor.coefficients(sparse=False)

    # Thus, y is given by - constant_term / linear_term
    return result_number_field, -constant_term / linear_term
Exemple #10
0
from lxml.etree import tostring

import qmt
import sage.all

hack = c.Converter()

hack.register_to_python_name("http://python.org/", "Python", "list",
                             lambda *args: list(args))
hack.register_to_python_class(om.OMString, lambda s: s.string)
hack.register_to_python_class(om.OMInteger, lambda i: i.integer)

from sage.rings.rational_field import RationalField
hack.register_to_python_name("http://python.org/", "sage.rings.rational_field",
                             "RationalField", RationalField())

from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
hack.register_to_python_name(
    "http://python.org/", "sage.rings.polynomial.polynomial_ring_constructor",
    "PolynomialRing", PolynomialRing)


def run(query, host="127.0.0.1", port=26134):
    """ Evaluates a query on a MitM server """
    xml = encoder.encode_xml(query.getQuery())

    client = None
    result = None
    try:
        client = SCSCPCLI(host, port=port)
Exemple #11
0
def find_monomials(polynomial,
                   poly_degree,
                   r,
                   s,
                   form="list",
                   sort_type="zero",
                   early_finish=True,
                   rolling_output=True,
                   out_file=None):
    """This function finds all monomials that, in relation to the given monomial, fit
	   the criteria of the problem.

	   ***ATTENTION: DESPITE THE VARIABLE DECLARATIONS AT THE BEGINNING OF THE FUNCTION,
	   THIS FUNCTION WILL NOT WORK CORRECTLY IF ALL VARIABLES IN THE INPUT POLYNOMIAL
	   HAVE NOT ALREADY BEEN DECLARED.***

		Args:
		    polynomial(symb exp): The polynomial to which monomials will be matched.
		    poly_degree(int): The degree of the input polynomial.
		    r(int): The r value for the input polynomial.
		    s(int): The s value for the input polynomial.
		    form(str): If form is "list", the function will return a list of monomials.
			       If form is "tup", the function will return a list of tuples with
			       the form: (monomial, coefficient).
		    sort_type(str): If sort_type is "zero", monomials are sorted by distance of
				    the coefficient from zero. If sort type is "value", monomials
				    are sorted by the coefficient's value.
		Returns:
		    monomials(list): Returns either a list of monomials or a list of tuples depending
				     on the value of form. Sorted by value or distance from zero of
				     coefficients depending on the value of sort_type. If there are
				     no working monomials, the function returns an empty list.
	"""

    if out_file != None:
        try:
            file = open(out_file, "w+")
        except:
            out_file = None
            print "File failed to open, printing to stdout..."
            print
    #Double check that variables are declared to prevent errors when forming monomials.
    for num in xrange(1, r + 1):
        var("x" + str(num))
    for num in xrange(1, s + 1):
        var("y" + str(num))

# Declare ring as R
    ringlists = ring_lists(r, s)
    R, ringlists[1] = PolynomialRing(RationalField(), r + s,
                                     ringlists[0]).objgens()

    #Monomials must be checked against the expanded monomial
    # polynomial_expanded = polynomial.expand() #--- This was the old way
    polynomial_expanded = type_change(polynomial, ring=R)
    """This variable will be used to create a monomial "template" with all the essential
	   variables and variables in place of exponent values.
	"""
    test_monomial = create_template_monomial(r, s)
    """This block creates a list of placeholders for x and y variable exponents in the order
	   they appear.
	"""

    list_of_both_powers = create_power_list(r, s)
    """This block finds all possible exponent combinations for x and y variables
	   in a list form, then finds all possible permutations of that list.
	"""

    list_of_power_values = create_power_values(r, s, poly_degree)
    """Now, every list of exponent possibilites is subbed into the monomial template,
	   then checked against the expanded polynomial. If it is present in the expanded
	   form, it is added to the final list.
	"""
    workable_monomials = []
    for power_values in list_of_power_values:
        for power_set in multiset_permutations(power_values):
            temp_test_monomial = test_monomial
            power_set = list(power_set)
            if r > 0 and s > 0:
                testing_list = check_monomial_rs(r, s, power_set,
                                                 temp_test_monomial,
                                                 list_of_both_powers,
                                                 polynomial_expanded, R)
            elif r > 0 and s == 0:
                testing_list = check_monomial_r(r, s, power_set,
                                                temp_test_monomial,
                                                list_of_both_powers,
                                                polynomial_expanded, R)
            elif r == 0 and s > 0:
                testing_list = check_monomial_s(r, s, power_set,
                                                temp_test_monomial,
                                                list_of_both_powers,
                                                polynomial_expanded, R)
            else:
                raise ValueError(
                    "Invalid r and s inputs. r and s may not be bellow zero and may not both be zero"
                )

            if testing_list[0] == 1:
                workable_monomials.append(
                    (testing_list[2] * testing_list[1], int(testing_list[2])))
                if rolling_output == True:
                    if out_file != None:
                        file.write(str(testing_list[2] * testing_list[1]))
                        file.write("\n")
                    else:
                        print testing_list[2] * testing_list[1]
                #The following block tests to see if the function can finish early
                if early_finish == True:
                    fin = 1
                    for fac in list(factor(int(testing_list[2]))):
                        if r + s > 9:
                            prime_range = xrange(-5, 6)
                        else:
                            prime_range = xrange(-3, 4)
                        if fac[0] not in prime_range:
                            fin = 0
                    if fin == 1:
                        if form == "list":
                            for i in xrange(0, len(workable_monomials)):
                                workable_monomials[i] = workable_monomials[i][
                                    0]
                        return workable_monomials

    #Changes output depending on preferences set at the outset.
    if len(workable_monomials) > 0:
        if sort_type == "zero":
            workable_monomials = sorted(workable_monomials,
                                        key=lambda tup: abs(tup[1]))
        else:
            workable_monomials = sorted(workable_monomials,
                                        key=lambda tup: tup[1])

    if form == "list":
        for i in xrange(0, len(workable_monomials)):
            workable_monomials[i] = workable_monomials[i][0]

    return workable_monomials