def generator_relations(self, K) :
        """
        An ideal `I` in the attach polynomial ring `R`, such that the ring of
        modular forms is a quotient of `R / I`. This ideal must be unique for `K`.
        
        INPUT:
            - `K`      -- A ring or module; The ring of Fourier coefficients.
        
        OUTPUT:
            An ideal in a polynomial ring.
            
        TESTS::
            sage: from hermitianmodularforms import *
            sage: HermitianModularFormD2_Gamma(-3).generator_relations(QQ)
            Ideal (0) of Multivariate Polynomial Ring in HE4, HE6, HE10, HE12, Hphi9 over Rational Field
            sage: HermitianModularFormD2_Gamma(-3).generator_relations(GF(2))
            Traceback (most recent call last):
            ...
            NotImplementedError: Only Fourier coefficients in a number fields are implemented.
        """
        if self.__D == -3 :
            if K is QQ or K in NumberFields() :
                R = PolynomialRing(K, self._generator_names(K))
                return R.ideal(0)

            raise NotImplementedError( "Only Fourier coefficients in a number fields are implemented." )
        
        raise NotImplementedError( "Discriminant %s is not implemented." % (self.__D,) )
class TestHomogeneousWieghts(unittest.TestCase):

  def setUp(self):
    self.poly_ring = PolynomialRing(QQ,"x",3);
    self.x = self.poly_ring.gens()[0];
    self.y = self.poly_ring.gens()[1];
    self.z = self.poly_ring.gens()[2];
  
  def test_homogenous(self):
    x = self.x
    y = self.y
    z = self.z
    divisor = x*y*z + x**3 + z**3
    wieghts = homogenous_wieghts(divisor)
    #Test this works with a homogenous divisor
    self.assertEquals(wieghts,[3,1,1,1]);
    
  def test_weighted_homogenous(self):
    x = self.x
    y = self.y
    z = self.z
    divisor = x**2*y-z**2
    wieghts = homogenous_wieghts(divisor)
    #Test this works with a weighted homogenous divisor
    self.assertEquals(wieghts,[4,1,2,2])
  
  def test_not_homogenous(self):
    x = self.x
    y = self.y
    z = self.z
    divisor = x**2*y-x**3 + z +y**2;
    self.assertRaises(NotWieghtHomogeneousException,homogenous_wieghts,divisor)
class TestMonomialsOfOrder(unittest.TestCase):
 
  def setUp(self):
    self.poly_ring = PolynomialRing(QQ,"x",3);
    self.x = self.poly_ring.gens()[0];
    self.y = self.poly_ring.gens()[1];
    self.z = self.poly_ring.gens()[2];
  
  def test_zero(self):
    mons = [mon for mon in monomials_of_order(0,self.poly_ring,[1,1,1])]
    self.assertEqual(mons,[self.poly_ring.one()])

  def test_homogeneous_3(self):
    x = self.x;
    y = self.y;
    z = self.z;
    true_mons = Set([x**3,y**3,z**3,x**2*y,x**2*z,y**2*x,y**2*z,z**2*x,z**2*y,x*y*z])
    mons = [mon for mon in monomials_of_order(3,self.poly_ring,[1,1,1])]
    self.assertEqual(true_mons,Set(mons))

  def test_non_homogeneous_4(self):
    x = self.x;
    y = self.y;
    z = self.z;
    true_mons = Set([x**4,x**2*y,x*z,y**2])
    mons = [mon for mon in monomials_of_order(4,self.poly_ring,[1,2,3])]
    self.assertEqual(true_mons,Set(mons))
def automorphy_factor_vector(p, a, c, k, chi, p_prec, var_prec, R):
    """
    EXAMPLES::
        
        sage: from sage.modular.pollack_stevens.families_util import automorphy_factor_vector
        sage: automorphy_factor_vector(3, 1, 3, 0, None, 4, 3, PowerSeriesRing(ZpCA(3), 'w'))
        [1 + O(3^20), O(3^21) + (3 + 3^2 + 2*3^3 + O(3^21))*w + (3^2 + 2*3^3 + O(3^22))*w^2, O(3^22) + (3^2 + 2*3^3 + O(3^22))*w + (2*3^2 + O(3^22))*w^2, O(3^22) + (3^2 + 3^3 + O(3^22))*w + (2*3^3 + O(3^23))*w^2]
    """
    S = PolynomialRing(R, 'z')
    z = S.gens()[0]
    w = R.gen()
    aut = S(1)
    for n in range(1, var_prec):
        LB = logpp_binom(n, p, p_prec)
        ta = ZZ(Qp(p, 2 * max(p_prec, var_prec)).teichmuller(a))
        arg = (a / ta - 1) / p + c / (p * ta) * z
        aut += LB(arg) * (w ** n)
    aut *= (ta ** k)
    if not (chi is None):
        aut *= chi(a)
    aut = aut.list()
    len_aut = len(aut)
    if len_aut == p_prec:
        return aut
    elif len_aut > p_prec:
        return aut[:p_prec]
    return aut + [R.zero_element()] * (p_prec - len_aut)
class TestWeightedMinDegree(unittest.TestCase):

  def setUp(self):
    self.poly_ring = PolynomialRing(QQ,"x",3);
    self.x = self.poly_ring.gens()[0];
    self.y = self.poly_ring.gens()[1];
    self.z = self.poly_ring.gens()[2];

  def test_zero(self):
    self.assertEqual(wieghted_min_degree(self.poly_ring.zero(),[1,1,1]),0);
  
  def test_homogeneous(self):
    x = self.x;
    y = self.y;
    z = self.z;
    f = x**4 + 4*y*z**3 - z**2;
    self.assertEqual(wieghted_min_degree(f,[1,1,1]),2);

  def test_non_homogeneous(self):
    x = self.x;
    y = self.y;
    z = self.z;
    f = x**4 + 4*y*z**3 - z**2;
    self.assertEqual(wieghted_min_degree(f,[2,1,2]),4);

  def test_negative_wieghts(self):
    x = self.x;
    y = self.y;
    z = self.z;
    f = x**4 + 4*y*z**3 - z**2;
    self.assertEqual(wieghted_min_degree(f,[-1,-1,1]),-4);
def rand_w_hom_divisor(n,degs=None,mon_num=None,var="z"):
  if degs==None:
    degs = [randrange(2,6) for _ in range(n)]
  deg = sum(degs)
  if mon_num==None:
    mon_num = randrange(2,8)
  poly_ring = PolynomialRing(QQ,n,var)
  div = poly_ring.zero()
  min_w = min(degs)
  for i in range(mon_num):
    expo = [0]*n
    cur_deg = 0
    while cur_deg!=deg:
      if cur_deg>deg:
        expo = [0]*n
        cur_deg = 0
      if deg-cur_deg<min_w:
        expo = [0]*n
        cur_deg = 0
      next_g = randrange(0,n)
      expo[next_g] += 1
      cur_deg += degs[next_g]
    coeff = randrange(-n,n)/n
    mon = poly_ring.one()
    for i,e in enumerate(expo):
      mon *= poly_ring.gens()[i]**e
    div += coeff*mon
  return div
Example #7
0
    def quantum_group(self, q=None, c=None):
        r"""
        Return the quantum group of ``self``.

        The corresponding quantum group is the
        :class:`~sage.algebras.lie_algebras.onsager.QuantumOnsagerAlgebra`.
        The parameter `c` must be such that `c(1) = 1`

        INPUT:

        - ``q`` -- (optional) the quantum parameter; the default
          is `q \in R(q)`, where `R` is the base ring of ``self``
        - ``c`` -- (optional) the parameter `c`; the default is ``q``

        EXAMPLES::

            sage: O = lie_algebras.OnsagerAlgebra(QQ)
            sage: Q = O.quantum_group()
            sage: Q
            q-Onsager algebra with c=q over Fraction Field of
             Univariate Polynomial Ring in q over Rational Field
        """
        if q is None:
            from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
            q = PolynomialRing(self.base_ring(), 'q').fraction_field().gen()
        if c is None:
            c = q
        else:
            c = q.parent()(c)
        return QuantumOnsagerAlgebra(self, q, c)
class TestConvertSymToPoly(unittest.TestCase):

  def setUp(self):
    self.poly_ring = PolynomialRing(QQ,"x",3);
    self.x = self.poly_ring.gens()[0];
    self.y = self.poly_ring.gens()[1];
    self.z = self.poly_ring.gens()[2];
    self.vars = var('x,y,z')
    
  def test_zero(self):
    zero = 0*self.vars[0]
    poly = convert_symbolic_to_polynomial(zero,self.poly_ring,self.vars)
    self.assertEqual(poly,self.poly_ring.zero())
    
  def test_convert(self):
    x = self.x
    y = self.y
    z = self.z
    sym_poly = 4*self.vars[0]**4 + self.vars[1]*self.vars[0]**12*self.vars[1]-self.vars[2]
    poly = convert_symbolic_to_polynomial(sym_poly,self.poly_ring,self.vars)
    self.assertEqual(poly,4*x**4+y*x**12*y-z)

  def test_convert_univarient(self):
    y = self.y
    sym_poly = 4*self.vars[1]**4 + self.vars[1]*self.vars[1]**12*self.vars[1]-self.vars[1]
    poly = convert_symbolic_to_polynomial(sym_poly,self.poly_ring,self.vars)
    self.assertEqual(poly,4*y**4+y*y**12*y-y)

  def test_convert_partial(self):
    y = self.y
    z = self.z
    sym_poly = 4*self.vars[2]**4 + self.vars[1]*self.vars[1]**12*self.vars[1]-self.vars[1]
    poly = convert_symbolic_to_polynomial(sym_poly,self.poly_ring,self.vars)
    self.assertEqual(poly,4*z**4+y*y**12*y-y)
Example #9
0
    def genus(self):
        """
        Return the genus of this function field
        For now, the genus is computed using singular

        EXAMPLES::

            sage: K.<x> = FunctionField(QQ); R.<y> = K[]
            sage: L.<y> = K.extension(y^3 - (x^3 + 2*x*y + 1/x))
            sage: L.genus()
            3
        """
        # unfortunately singular can not compute the genus with the polynomial_ring()._singular_
        # object because genus method only accepts a ring of transdental degree 2 over a prime field
        # not a ring of transdental degree 1 over a rational function field of one variable

        if is_RationalFunctionField(self._base_field) and self._base_field.constant_field().is_prime_field():

            #Making the auxiliary ring which only has polynomials with integral coefficients.
            tmpAuxRing = PolynomialRing(self._base_field.constant_field(), str(self._base_field.gen())+','+str(self._ring.gen()))
            intMinPoly, d = self._make_monic_integral(self._polynomial)
            curveIdeal = tmpAuxRing.ideal(intMinPoly)

            singular.lib('normal.lib') #loading genus method in singular
            return int(curveIdeal._singular_().genus())

        else:
            raise NotImplementedError("Computation of genus over this rational function field not implemented yet")
    def _roots_univariate_polynomial(self, p, ring=None, multiplicities=None, algorithm=None):
        r"""
        Return a list of pairs ``(root,multiplicity)`` of roots of the polynomial ``p``.

        If the argument ``multiplicities`` is set to ``False`` then return the
        list of roots.

        .. SEEALSO::

            :meth:`_factor_univariate_polynomial`

        EXAMPLES::

            sage: R.<x> = PolynomialRing(GF(5),'x')
            sage: K = GF(5).algebraic_closure('t')

            sage: sorted((x^6 - 1).roots(K,multiplicities=False))
            [1, 4, 2*t2 + 1, 2*t2 + 2, 3*t2 + 3, 3*t2 + 4]
            sage: ((K.gen(2)*x - K.gen(3))**2).roots(K)
            [(3*t6^5 + 2*t6^4 + 2*t6^2 + 3, 2)]

            sage: for _ in range(10):
            ....:     p = R.random_element(degree=randint(2,8))
            ....:     for r in p.roots(K, multiplicities=False):
            ....:         assert p(r).is_zero(), "r={} is not a root of p={}".format(r,p)

        """
        from sage.arith.all import lcm
        from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing

        # first build a polynomial over some finite field
        coeffs = [v.as_finite_field_element(minimal=True) for v in p.list()]
        l = lcm([c[0].degree() for c in coeffs])
        F, phi = self.subfield(l)
        P = p.parent().change_ring(F)

        new_coeffs = [self.inclusion(c[0].degree(), l)(c[1]) for c in coeffs]

        polys = [(g,m,l,phi) for g,m in P(new_coeffs).factor()]
        roots = []    # a list of pair (root,multiplicity)
        while polys:
            g,m,l,phi = polys.pop()
        
            if g.degree() == 1: # found a root
                r = phi(-g.constant_coefficient())
                roots.append((r,m))
            else: # look at the extension of degree g.degree() which contains at
                  # least one root of g
                ll = l * g.degree()
                psi = self.inclusion(l, ll)
                FF, pphi = self.subfield(ll)
                # note: there is no coercion from the l-th subfield to the ll-th
                # subfield. The line below does the conversion manually.
                g = PolynomialRing(FF, 'x')([psi(_) for _ in g])
                polys.extend((gg,m,ll,pphi) for gg,_ in g.factor())

        if multiplicities:
            return roots
        else:
            return [r[0] for r in roots]
def whitney_divisor(var=None):
  if var:
    poly_ring = PolynomialRing(QQ,3,var)
  else:
    poly_ring = PolynomialRing(QQ,3,"xyz")
  gens = poly_ring.gens()
  return gens[0]**2*gens[1]-gens[2]**2
Example #12
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
Example #13
0
 def _interpolate(evaluation, num_of_var, order):
     if num_of_var == 0 or order == 0:
         return evaluation[0]
     base_field = polynomial_ring.base_ring()
     q = base_field.cardinality()
     n_by_q = q**(num_of_var - 1)
     d = min(order + 1, q)
     multipoint_evaluation_list = []
     uni_poly_ring = PolynomialRing(base_field, 'x')
     base_field_zero = base_field.zero()
     for k in range(n_by_q):
         iterator = iter(base_field)
         points = []
         for i in range(d):
             xcoordinate = next(iterator)
             points.append((xcoordinate, evaluation[k + i * n_by_q]))
         polyVector = uni_poly_ring.lagrange_polynomial(
             points).coefficients(sparse=False)
         if len(polyVector) < d:
             # adding zeros to represet a (d-1) degree polynomial
             polyVector += [base_field_zero] * (d - len(polyVector))
         multipoint_evaluation_list.append(polyVector)
     poly = polynomial_ring.zero()
     z = 1
     x = polynomial_ring.gen(num_of_var - 1)
     for k in range(d):  # computing the polynomial
         poly = poly + z * _interpolate([multipoint_evaluation_list[i][k]
                                         for i in range(n_by_q)], num_of_var - 1, order - k)
         z *= x
     return poly
def braid_divisor(n,var="z"):
  poly_ring = PolynomialRing(QQ,n,var)
  div = poly_ring.one()
  gens = poly_ring.gens()
  for i in range(n):
    for j in range(i+1,n):
      div *= (gens[i]-gens[j])
  return div
def breiskorn_pham_divisor(n,var="z"):
  poly_ring = PolynomialRing(QQ,n,var)
  for i,g in enumerate(poly_ring.gens()):
    if i==0:
      div = g**3
    else:
      div += g**2
  return div
Example #16
0
def comp_prod(P, Q):
    n = Q.degree()
    K = P.base_ring()
    A = PolynomialRing(K, 'X')
    X = A.gen()
    AA = PolynomialRing(K, 'Y,Z')
    Y, Z = AA.gens()
    return P(Y).resultant(AA(Y**n * Q(Z/Y)), Y)(1,X)
Example #17
0
 def eu(p):
     """
     local euler factor
     """
     f = rho.local_factor(p)
     co = [ZZ(round(x)) for x in f.coeffs()]
     R = PolynomialRing(QQ, "T")
     T = R.gens()[0]
     return sum( co[n] * T**n for n in range(len(co)))
 def test_p_module_n_crossing(self):
   #Make sure this doesnt throw an error - fix bug
   for i in range(4,5):
     p_ring = PolynomialRing(QQ,i,"z")
     crossing = p_ring.one()
     for g in p_ring.gens():
       crossing *= g
     logdf = LogarithmicDifferentialForms(crossing)
     logdf.p_module(i-1)
Example #19
0
def BezoutianQuadraticForm(f, g):
    r"""
    Compute the Bezoutian of two polynomials defined over a common base ring.  This is defined by

    .. MATH::

        {\rm Bez}(f, g) := \frac{f(x) g(y) - f(y) g(x)}{y - x}

    and has size defined by the maximum of the degrees of `f` and `g`.

    INPUT:

    - `f`, `g` -- polynomials in `R[x]`, for some ring `R`

    OUTPUT:

    a quadratic form over `R`

    EXAMPLES::

        sage: R = PolynomialRing(ZZ, 'x')
        sage: f = R([1,2,3])
        sage: g = R([2,5])
        sage: Q = BezoutianQuadraticForm(f, g) ; Q
        Quadratic form in 2 variables over Integer Ring with coefficients:
        [ 1 -12 ]
        [ * -15 ]

    AUTHORS:

    - Fernando Rodriguez-Villegas, Jonathan Hanke -- added on 11/9/2008

    """
    ## Check that f and g are polynomials with a common base ring
    if not is_Polynomial(f) or not is_Polynomial(g):
        raise TypeError("Oops!  One of your inputs is not a polynomial. =(")
    if f.base_ring() != g.base_ring():                   ## TO DO:  Change this to allow coercion!
        raise TypeError("Oops!  These polynomials are not defined over the same coefficient ring.")

    ## Initialize the quadratic form
    R = f.base_ring()
    P = PolynomialRing(R, ['x','y'])
    a, b = P.gens()
    n = max(f.degree(), g.degree())
    Q = QuadraticForm(R, n)

    ## Set the coefficients of Bezoutian
    bez_poly = (f(a) * g(b) - f(b) * g(a)) // (b - a)    ## Truncated (exact) division here
    for i in range(n):
        for j in range(i, n):
            if i == j:
                Q[i,j] = bez_poly.coefficient({a:i,b:j})
            else:
                Q[i,j] = bez_poly.coefficient({a:i,b:j}) * 2

    return Q
Example #20
0
def _eta_relations_helper(eta1, eta2, degree, qexp_terms, labels, verbose):
    r"""
    Helper function used by eta_poly_relations. Finds a basis for the
    space of linear relations between the first qexp_terms of the
    `q`-expansions of the monomials
    `\eta_1^i * \eta_2^j` for `0 \le i,j < degree`,
    and calculates a Groebner basis for the ideal generated by these
    relations.

    Liable to return meaningless results if qexp_terms isn't at least
    `1 + d*(m_1,m_2)` where

    .. math::

       m_i = min(0, {\text degree of the pole of $\eta_i$ at $\infty$})

    as then 1 will be in the ideal.

    EXAMPLE::

        sage: from sage.modular.etaproducts import _eta_relations_helper
        sage: r,s = EtaGroup(4).basis()
        sage: _eta_relations_helper(r,s,4,100,['a','b'],False)
        [a*b - a + 16]
        sage: _eta_relations_helper(EtaProduct(26, {2:2,13:2,26:-2,1:-2}),EtaProduct(26, {2:4,13:2,26:-4,1:-2}),3,12,['a','b'],False) # not enough terms, will return rubbish
        [1]
    """

    indices = [(i,j) for j in range(degree) for i in range(degree)]
    inf = CuspFamily(eta1.level(), 1)

    pole_at_infinity = -(min([0, eta1.order_at_cusp(inf)]) + min([0,eta2.order_at_cusp(inf)]))*degree
    if verbose: print "Trying all coefficients from q^%s to q^%s inclusive" % (-pole_at_infinity, -pole_at_infinity + qexp_terms - 1)

    rows = []
    for j in xrange(qexp_terms):
        rows.append([])
    for i in indices:
        func = (eta1**i[0]*eta2**i[1]).qexp(qexp_terms)
        for j in xrange(qexp_terms):
            rows[j].append(func[j - pole_at_infinity])
    M = matrix(rows)
    V = M.right_kernel()
    if V.dimension() == 0:
        if verbose: print "No polynomial relation of order %s valid for %s terms" % (degree, qexp_terms)
        return None
    if V.dimension() >= 1:
        #print "Found relation: "
        R = PolynomialRing(QQ, 2, labels)
        x,y = R.gens()
        relations = []
        for c in V.basis():
            relations.append(sum( [ c[v] * x**indices[v][0] * y**indices[v][1] for v in xrange(len(indices))]))
            #print relations[-1], " = 0"
        id = R.ideal(relations)
        return id.groebner_basis()
Example #21
0
def new_automorphy_factor_vector(p, a, c, k, chi, p_prec, var_prec, R):
    #if not R.is_capped_relative():
    #    Rcr =
    if p_prec > R.precision_cap():
        raise ValueError("Specified p-adic precision, p_prec, should be at most that of R.")
    S = PolynomialRing(R, 'z')
    z = S.gens()[0]
    w = R.gen()
    aut = S(R1, p_prec)
    ta = R.teichmuller(R(a, p_prec))
 def generator_relations(self, K) :
     r"""
     An ideal `I` in a polynomial ring `R`, such that the associated ring
     is `R / I`. This ideal must be unique for `K`. 
     """
     if K is QQ or K in NumberFields() :
         R = PolynomialRing(K, self._generator_names(K))
         return R.ideal(0)
         
     raise NotImplementedError
 def generator_relations(self, K) :
     r"""
     An ideal I in a polynomial ring R, such that the associated module
     is (R / I)_1. 
     """
     if K is QQ or K in NumberFields() :
         R = PolynomialRing(K, self._generator_names(K))
         return R.ideal(0)
         
     raise NotImplementedError
    def _roots_univariate_polynomial(self, p, ring=None, multiplicities=None, algorithm=None):
        r"""
        Return a list of pairs ``(root,multiplicity)`` of roots of the polynomial ``p``.

        If the argument ``multiplicities`` is set to ``False`` then return the
        list of roots.

        .. SEEALSO::

            :meth:`_factor_univariate_polynomial`

        EXAMPLES::

            sage: R.<x> = PolynomialRing(GF(5),'x')
            sage: K = GF(5).algebraic_closure('t')

            sage: sorted((x^6 - 1).roots(K,multiplicities=False))
            [1, 4, 2*t2 + 1, 2*t2 + 2, 3*t2 + 3, 3*t2 + 4]
            sage: ((K.gen(2)*x - K.gen(3))**2).roots(K)
            [(3*t6^5 + 2*t6^4 + 2*t6^2 + 3, 2)]

            sage: for _ in xrange(10):
            ....:     p = R.random_element(degree=randint(2,8))
            ....:     for r in p.roots(K, multiplicities=False):
            ....:         assert p(r).is_zero()

        """
        from sage.rings.arith import lcm
        from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing

        # first build a polynomial over some finite field
        coeffs = [v.as_finite_field_element(minimal=True) for v in p.list()]
        l = lcm([c[0].degree() for c in coeffs])
        F, phi = self.subfield(l)
        P = p.parent().change_ring(F)

        new_coeffs = [self.inclusion(c[0].degree(), l)(c[1]) for c in coeffs]

        roots = []    # a list of pair (root,multiplicity)
        for g, m in P(new_coeffs).factor():
            if g.degree() == 1:
                r = phi(-g.constant_coefficient())
                roots.append((r,m))
            else:
                ll = l * g.degree()
                psi = self.inclusion(l, ll)
                FF, pphi = self.subfield(ll)
                gg = PolynomialRing(FF, 'x')(map(psi, g))
                for r, _ in gg.roots():  # note: we know that multiplicity is 1
                    roots.append((pphi(r), m))

        if multiplicities:
            return roots
        else:
            return [r[0] for r in roots]
Example #25
0
    def from_recurrence(cls, coefficients, values):
        """
    Create a C-finite sequence given the coefficients $c$ and starting values $a$
    of a homogenous linear recurrence.

    .. MATH::
    
        a_{n+d} = c_0a_n + c_1a_{n+1} + \cdots + c_{d-1}a_{n+d-1}, \quad d\ge0.

    INPUT:

    - ``coefficients`` -- a list of rationals

    - ``values`` -- start values, a list of rationals

    OUTPUT:

    - A CFiniteSequence object

    EXAMPLES::

        sage: R.<x> = QQ[]
        sage: CFiniteSequence.from_recurrence([1,1],[0,1])   # Fibonacci numbers
        C-finite sequence, generated by x/(-x^2 - x + 1)
        sage: CFiniteSequence.from_recurrence([-1,2],[0,1])    # natural numbers
        C-finite sequence, generated by x/(x^2 - 2*x + 1)
        sage: r = CFiniteSequence.from_recurrence([-1],[1])
        sage: s = CFiniteSequence.from_recurrence([-1],[1,-1])
        sage: r == s
        True
        sage: r = CFiniteSequence(x^3/(1-x-x^2))
        sage: s = CFiniteSequence.from_recurrence([1,1],[0,0,0,1,1])
        sage: r == s
        True
        sage: CFiniteSequence.from_recurrence(1,1)
        Traceback (most recent call last):
        ...
        ValueError: Wrong type for recurrence coefficient list.
        """

        if not isinstance(coefficients, list):
            raise ValueError("Wrong type for recurrence coefficient list.")
        if not isinstance(values, list):
            raise ValueError("Wrong type for recurrence start value list.")
        deg = len(coefficients)

        co = coefficients[::-1]
        co.extend([0] * (len(values) - deg))
        R = PolynomialRing(QQ, 'x')
        x = R.gen()
        den = -1 + sum([x ** (n + 1) * co[n] for n in range(deg)])
        num = -values[0] + sum([x ** n * (-values[n] + sum([values[k] * co[n - 1 - k] for k in range(n)])) for n in range(1, len(values))])
        return cls(num / den)
Example #26
0
            def expand(self, n, alphabet='x'):
                r"""
                Expands the quasi-symmetric function written in the monomial basis in
                `n` variables.

                INPUT:

                - ``n`` -- an integer
                - ``alphabet`` -- (default:'x') a string

                OUTPUT:

                - The quasi-symmetric function ``self`` expressed in the ``n`` variables
                  described by ``alphabet``.

                .. TODO:: accept an *alphabet* as input

                EXAMPLES::

                    sage: M = QuasiSymmetricFunctions(QQ).Monomial()
                    sage: M[4,2].expand(3)
                    x0^4*x1^2 + x0^4*x2^2 + x1^4*x2^2

                One can use a different set of variable by using the
                optional argument ``alphabet``::

                    sage: M=QuasiSymmetricFunctions(QQ).Monomial()
                    sage: M[2,1,1].expand(4,alphabet='y')
                    y0^2*y1*y2 + y0^2*y1*y3 + y0^2*y2*y3 + y1^2*y2*y3

                TESTS::

                    sage: (3*M([])).expand(2)
                    3
                    sage: M[4,2].expand(0)
                    0
                    sage: M([]).expand(0)
                    1
                """
                from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
                M = self.parent()
                P = PolynomialRing(M.base_ring(), n, alphabet)
                x = P.gens()
                def on_basis(comp, i):
                    if not comp:
                        return P.one()
                    elif len(comp) > i:
                        return P.zero()
                    else:
                        return x[i-1]**comp[-1] * on_basis(comp[:-1], i-1) + \
                                                  on_basis(comp,      i-1)
                return M._apply_module_morphism(self, lambda comp: on_basis(comp,n),
                                                codomain = P)
Example #27
0
 def Fourier_coefficients( self, det_list):
     fcs = DB.find( { 'owner_id': self.__id,
                      'data_type': 'fc',
                      'det': { '$in': [ str(d) for d in det_list]}
                      })
     P = PolynomialRing( self.__field, names = 'x,y')
     loc = P.gens_dict()
     loc.update ( self.__field.gens_dict())
     return dict( (Integer(fcd['det']),
                   dict( (tuple( eval(f)), sage_eval( fcd['data'][f], locals = loc))
                         for f in fcd['data'] ))
                  for fcd in fcs)
Example #28
0
    def mutate_initial(self, k):
        r"""
        Mutate ``self`` in direction `k` at the initial cluster.

        INPUT:
        - ``k`` -- integer in between 0 and ``self.rk``
        """
        n = self.rk

        if k not in xrange(n):
            raise ValueError('Cannot mutate in direction %s, please try a value between 0 and %s.'%(str(k),str(n-1)))

        #modify self._path_dict using Nakanishi-Zelevinsky (4.1) and self._F_poly_dict using CA-IV (6.21)
        new_path_dict = dict()
        new_F_dict = dict()
        new_path_dict[tuple(identity_matrix(n).column(k))] = []
        new_F_dict[tuple(identity_matrix(n).column(k))] = self._U(1)

        poly_ring = PolynomialRing(ZZ,'u')
        h_subs_tuple = tuple([poly_ring.gen(0)**(-1) if j==k else poly_ring.gen(0)**max(-self._B0[k][j],0) for j in xrange(n)])
        F_subs_tuple = tuple([self._U.gen(k)**(-1) if j==k else self._U.gen(j)*self._U.gen(k)**max(-self._B0[k][j],0)*(1+self._U.gen(k))**(self._B0[k][j]) for j in xrange(n)])

        for g_vect in self._path_dict:
            #compute new path
            path = self._path_dict[g_vect]
            if g_vect == tuple(identity_matrix(n).column(k)):
                new_path = [k]
            elif path != []:
                if path[0] != k:
                    new_path = [k] + path
                else:
                    new_path = path[1:]
            else:
                new_path = []

            #compute new g-vector
            new_g_vect = vector(g_vect) - 2*g_vect[k]*identity_matrix(n).column(k)
            for i in xrange(n):
                new_g_vect += max(sign(g_vect[k])*self._B0[i,k],0)*g_vect[k]*identity_matrix(n).column(i)
            new_path_dict[tuple(new_g_vect)] = new_path

            #compute new F-polynomial
            h = 0
            trop = tropical_evaluation(self._F_poly_dict[g_vect](h_subs_tuple))
            if trop != 1:
                h = trop.denominator().exponents()[0]-trop.numerator().exponents()[0]
            new_F_dict[tuple(new_g_vect)] = self._F_poly_dict[g_vect](F_subs_tuple)*self._U.gen(k)**h*(self._U.gen(k)+1)**g_vect[k]

        self._path_dict = new_path_dict
        self._F_poly_dict = new_F_dict

        self._B0.mutate(k)
Example #29
0
def logp(p, p_prec):
    """
    Returns the (integral) power series for log_p(1+z) as a polynomial in y over the rationals of degree < p_prec.
    
    EXAMPLES::
        
        sage: from sage.modular.pollack_stevens.families_util import logp
        sage: logp(11, 5)
        -1/4*y^4 + 1/3*y^3 - 1/2*y^2 + y
    """
    SS = PolynomialRing(QQ, 'y')
    y = SS.gen()
    return sum([((-1) ** (m - 1)) * (y ** m) / m for m in range(1, p_prec)])
Example #30
0
def DuadicCodeOddPair(F,S1,S2):
    """
    Constructs the "odd pair" of duadic codes associated to the
    "splitting" S1, S2 of n.

    .. warning::

       Maybe the splitting should be associated to a sum of
       q-cyclotomic cosets mod n, where q is a *prime*.

    EXAMPLES::

        sage: from sage.coding.code_constructions import _is_a_splitting
        sage: n = 11; q = 3
        sage: C = Zmod(n).cyclotomic_cosets(q); C
        [[0], [1, 3, 4, 5, 9], [2, 6, 7, 8, 10]]
        sage: S1 = C[1]
        sage: S2 = C[2]
        sage: _is_a_splitting(S1,S2,11)
        True
        sage: codes.DuadicCodeOddPair(GF(q),S1,S2)
        ([11, 6] Cyclic Code over GF(3),
         [11, 6] Cyclic Code over GF(3))

    This is consistent with Theorem 6.1.3 in [HP2003]_.
    """
    from .cyclic_code import CyclicCode
    n = len(S1) + len(S2) + 1
    if not _is_a_splitting(S1,S2,n):
        raise TypeError("%s, %s must be a splitting of %s."%(S1,S2,n))
    q = F.order()
    k = Mod(q,n).multiplicative_order()
    FF = GF(q**k,"z")
    z = FF.gen()
    zeta = z**((q**k-1)/n)
    P1 = PolynomialRing(FF,"x")
    x = P1.gen()
    g1 = prod([x-zeta**i for i in S1+[0]])
    g2 = prod([x-zeta**i for i in S2+[0]])
    j = sum([x**i/n for i in range(n)])
    P2 = PolynomialRing(F,"x")
    x = P2.gen()
    coeffs1 = [_lift2smallest_field(c)[0] for c in (g1+j).coefficients(sparse=False)]
    coeffs2 = [_lift2smallest_field(c)[0] for c in (g2+j).coefficients(sparse=False)]
    gg1 = P2(coeffs1)
    gg2 = P2(coeffs2)
    gg1 = gcd(gg1, x**n - 1)
    gg2 = gcd(gg2, x**n - 1)
    C1 = CyclicCode(length = n, generator_pol = gg1)
    C2 = CyclicCode(length = n, generator_pol = gg2)
    return C1,C2
Example #31
0
    def __init__(self, code, polynomial_ring=None):
        r"""
        TESTS:

        If ``code`` is not a Reed-Muller code, an error is raised::

            sage: C  = codes.random_linear_code(GF(11), 10, 4)
            sage: codes.encoders.ReedMullerPolynomialEncoder(C)
            Traceback (most recent call last):
            ...
            ValueError: the code has to be a Reed-Muller code

        If the polynomial ring passed is not according to the requirement (over a different field or different number of variables) then an error is raised::

            sage: F=GF(59)
            sage: R.<x,y,z,w>=F[]
            sage: C=codes.ReedMullerCode(F, 2, 3)
            sage: E=codes.encoders.ReedMullerPolynomialEncoder(C, R)
            Traceback (most recent call last):
            ...
            ValueError: The Polynomial ring should be on Finite Field of size 59 and should have 3 variables
        """
        if not (isinstance(code, QAryReedMullerCode)
                or isinstance(code, BinaryReedMullerCode)):
            raise ValueError("the code has to be a Reed-Muller code")
        super(ReedMullerPolynomialEncoder, self).__init__(code)
        if polynomial_ring is None:
            self._polynomial_ring = PolynomialRing(code.base_field(),
                                                   code.number_of_variables(),
                                                   'x')
        else:
            if (polynomial_ring.base_ring()
                    == code.base_field()) and (len(
                        polynomial_ring.variable_names())
                                               == code.number_of_variables()):
                self._polynomial_ring = polynomial_ring
            else:
                raise ValueError(
                    "The Polynomial ring should be on %s and should have %s variables"
                    % (code.base_field(), code.number_of_variables()))
Example #32
0
def DuadicCodeEvenPair(F, S1, S2):
    r"""
    Constructs the "even pair" of duadic codes associated to the
    "splitting" (see the docstring for ``_is_a_splitting``
    for the definition) S1, S2 of n.

    .. warning::

       Maybe the splitting should be associated to a sum of
       q-cyclotomic cosets mod n, where q is a *prime*.

    EXAMPLES::

        sage: from sage.coding.code_constructions import _is_a_splitting
        sage: n = 11; q = 3
        sage: C = Zmod(n).cyclotomic_cosets(q); C
        [[0], [1, 3, 4, 5, 9], [2, 6, 7, 8, 10]]
        sage: S1 = C[1]
        sage: S2 = C[2]
        sage: _is_a_splitting(S1,S2,11)
        True
        sage: codes.DuadicCodeEvenPair(GF(q),S1,S2)
        ([11, 5] Cyclic Code over GF(3),
         [11, 5] Cyclic Code over GF(3))
    """
    from .cyclic_code import CyclicCode
    n = len(S1) + len(S2) + 1
    if not _is_a_splitting(S1, S2, n):
        raise TypeError("%s, %s must be a splitting of %s." % (S1, S2, n))
    q = F.order()
    k = Mod(q, n).multiplicative_order()
    FF = GF(q**k, "z")
    z = FF.gen()
    zeta = z**((q**k - 1) / n)
    P1 = PolynomialRing(FF, "x")
    x = P1.gen()
    g1 = prod([x - zeta**i for i in S1 + [0]])
    g2 = prod([x - zeta**i for i in S2 + [0]])
    P2 = PolynomialRing(F, "x")
    x = P2.gen()
    gg1 = P2(
        [_lift2smallest_field(c)[0] for c in g1.coefficients(sparse=False)])
    gg2 = P2(
        [_lift2smallest_field(c)[0] for c in g2.coefficients(sparse=False)])
    C1 = CyclicCode(length=n, generator_pol=gg1)
    C2 = CyclicCode(length=n, generator_pol=gg2)
    return C1, C2
Example #33
0
    def polynomial_ring(self, names='E2, E4, E6'):
        r"""
        Return a multivariate polynomial ring isomorphic to the given graded
        quasimodular forms ring.

        In the case of the full modular group, this
        ring is `R[E_2, E_4, E_6]` where `E_2`, `E_4` and `E_6` have degrees 2,
        4 and 6 respectively.

        INPUT:

        - ``names`` (str, default: ``'E2, E4, E6'``) -- a list or tuple of names
          (strings), or a comma separated string. Correspond to the names of the
          variables.

        OUTPUT: A multivariate polynomial ring in the variables ``names``

        EXAMPLES:

            sage: QM = QuasiModularForms(1)
            sage: P.<E2, E4, E6> = QM.polynomial_ring(); P
            Multivariate Polynomial Ring in E2, E4, E6 over Rational Field
            sage: E2.degree()
            2
            sage: E4.degree()
            4
            sage: E6.degree()
            6
            sage: P.<x, y, z, w> = QQ[]
            sage: QM.from_polynomial(x+y+z+w)
            Traceback (most recent call last):
            ...
            ValueError: the number of variables (4) of the given polynomial cannot exceed the number of generators (3) of the quasimodular forms ring
        """
        return PolynomialRing(
            self.base_ring(),
            3,
            names,
            order=TermOrder('wdeglex', [ZZ(2), ZZ(4), ZZ(6)]))
Example #34
0
    def __init__(self, field = None):
        """
        Create a shrinking generator cryptosystem.

        INPUT: A string monoid over a binary alphabet.

        OUTPUT:

        EXAMPLES::

            sage: E = ShrinkingGeneratorCryptosystem()
            sage: E
            Shrinking generator cryptosystem over Finite Field of size 2
        """
        if field is None:
           field = FiniteField(2)
        if field.cardinality() != 2:
            raise NotImplementedError("Not yet implemented.")
        S = BinaryStrings()
        P = PolynomialRing(field, 'x')
        SymmetricKeyCryptosystem.__init__(self, S, S, None)
        self._field = field
Example #35
0
    def defining_polynomial(self, i, j, u=None):
        r"""
        Return the defining polynomial of ``i`` and ``j``.

        The defining polynomial is given by:

        .. MATH::

            T_{ij}(u) = \delta_{ij} u^{\ell} + \sum_{k=1}^{\ell} t_{ij}^{(k)}
            u^{\ell-k}.

        EXAMPLES::

            sage: Y = Yangian(QQ, 3, 5)
            sage: Y.defining_polynomial(3, 2)
            t(1)[3,2]*u^4 + t(2)[3,2]*u^3 + t(3)[3,2]*u^2 + t(4)[3,2]*u + t(5)[3,2]
            sage: Y.defining_polynomial(1, 1)
            u^5 + t(1)[1,1]*u^4 + t(2)[1,1]*u^3 + t(3)[1,1]*u^2 + t(4)[1,1]*u + t(5)[1,1]
        """
        if u is None:
            u = PolynomialRing(self.base_ring(), 'u').gen(0)
        ell = self._level
        return sum(self.gen(k, i, j) * u**(ell - k) for k in range(ell + 1))
Example #36
0
    def ring(self):
        """
        Create, return and cache a polynomial ring for S-box
        polynomials.

        EXAMPLE::

            sage: S = mq.SBox(7,6,0,4,2,5,1,3)
            sage: S.ring()
            Multivariate Polynomial Ring in x0, x1, x2, y0, y1, y2 over Finite Field of size 2
        """
        try:
            return self._ring
        except AttributeError:
            pass

        m = self.m
        n = self.n

        X = range(m)
        Y = range(n)
        self._ring = PolynomialRing(self._F, m+n, ["x%d"%i for i in X] + ["y%d"%i for i in Y])
        return self._ring
Example #37
0
    def _init_ring(self, term_order):
        r"""
        Construct the ambient polynomial ring.

        INPUT:

        - ``term_order`` -- string. The order of the variables, for
          example ``'neglex'`` and ``'degrevlex'``.

        OUTPUT:

        A polynomial ring with the given term order.

        .. NOTE::

            Reverse lexicographic ordering is equivalent to negative
            lexicographic order with the reversed list of
            variables. We are using the latter in the implementation
            of the Hosten/Sturmfels algorithm.

        EXAMPLES::

            sage: A = matrix([[1,1,1],[0,1,2]])
            sage: IA = ToricIdeal(A)
            sage: R = IA._init_ring('neglex');  R
            Multivariate Polynomial Ring in z0, z1, z2 over Rational Field
            sage: R.term_order()
            Negative lexicographic term order
            sage: R.inject_variables()
            Defining z0, z1, z2
            sage: z0 < z1 and z1 < z2
            True
        """
        return PolynomialRing(self._base_ring,
                              self._names,
                              self.nvariables(),
                              order=term_order)
Example #38
0
def DuadicCodeEvenPair(F,S1,S2):
    r"""
    Constructs the "even pair" of duadic codes associated to the
    "splitting" (see the docstring for ``is_a_splitting``
    for the definition) S1, S2 of n.

    .. warning::

       Maybe the splitting should be associated to a sum of
       q-cyclotomic cosets mod n, where q is a *prime*.

    EXAMPLES::

        sage: from sage.coding.code_constructions import is_a_splitting
        sage: n = 11; q = 3
        sage: C = cyclotomic_cosets(q,n); C
        [[0], [1, 3, 4, 5, 9], [2, 6, 7, 8, 10]]
        sage: S1 = C[1]
        sage: S2 = C[2]
        sage: is_a_splitting(S1,S2,11)
        (True, 2)
        sage: codes.DuadicCodeEvenPair(GF(q),S1,S2)
        (Linear code of length 11, dimension 5 over Finite Field of size 3,
         Linear code of length 11, dimension 5 over Finite Field of size 3)
    """
    n = max(S1+S2)+1
    if not(is_a_splitting(S1,S2,n)):
        raise TypeError, "%s, %s must be a splitting of %s."%(S1,S2,n)
    q = F.order()
    k = Mod(q,n).multiplicative_order()
    FF = GF(q**k,"z")
    z = FF.gen()
    zeta = z**((q**k-1)/n)
    P1 = PolynomialRing(FF,"x")
    x = P1.gen()
    g1 = prod([x-zeta**i for i in S1+[0]])
    g2 = prod([x-zeta**i for i in S2+[0]])
    P2 = PolynomialRing(F,"x")
    x = P2.gen()
    gg1 = P2([lift2smallest_field(c)[0] for c in g1.coeffs()])
    gg2 = P2([lift2smallest_field(c)[0] for c in g2.coeffs()])
    C1 = CyclicCodeFromGeneratingPolynomial(n,gg1)
    C2 = CyclicCodeFromGeneratingPolynomial(n,gg2)
    return C1,C2
Example #39
0
    def cardinality(self):
        """
        Return the cardinality of the point set.

        OUTPUT:

        Integer. The number of points.

        EXAMPLES::

            sage: fan = NormalFan(ReflexivePolytope(2, 0))
            sage: X.<u,v,w> = ToricVariety(fan, base_ring=GF(7))
            sage: Y = X.subscheme(u^3 + v^3 + w^3 + u*v*w)
            sage: point_set = Y.point_set()
            sage: list(point_set)
            [[0 : 1 : 3],
             [1 : 0 : 3],
             [1 : 3 : 0],
             [1 : 1 : 6],
             [1 : 1 : 4],
             [1 : 3 : 2],
             [1 : 3 : 5]]
            sage: ffe = point_set._enumerator()
            sage: ffe.cardinality()
            7
        """
        n = 0
        for cone, nonzero_coordinates, cokernel in self.ambient.cone_points_iter(
        ):
            R = PolynomialRing(self.ambient.ring, cokernel.ngens(), 't')
            inhomogeneous = self.inhomogeneous_equations(
                R, nonzero_coordinates, cokernel)
            for log_t in self.solutions(inhomogeneous,
                                        map(range, cokernel.invariants())):
                n += 1
        return n
    def eval_method(self, tgt):
        if utilities.is_QQi(self.Scalars) and isinstance(
                tgt, ComplexBallField):
            ZZn = PolynomialRing(ZZ, 'n')
            re_im = [(ZZn([c.real()
                           for c in pol]), ZZn([c.imag() for c in pol]))
                     for pol in self.coeff]
            if utilities.has_new_ComplexBall_constructor():

                def ev(point):
                    return [
                        ComplexBall(tgt, re(point), im(point))
                        for re, im in re_im
                    ]
            else:

                def ev(point):
                    return [tgt(re(point), im(point)) for re, im in re_im]
        else:

            def ev(point):
                return [tgt(pol(point)) for pol in self.coeff]

        return ev
 def __init__(self, R, n, r, inert=0):
     names = ["x%s%s" % (i, j) for i in range(r) for j in range(n)] + [
         "theta%s%s" % (i, j) for i in range(inert) for j in range(n)
     ]
     P = PolynomialRing(R, n * (r + inert), names)
     self._n = n
     self._r = r
     self._inert = inert
     vars = P.gens()
     self._P = P
     self._R = R
     self._Q = PolynomialRing(QQ, 'q', r)
     self._grading_set = cartesian_product([ZZ for i in range(r)])
     self._hilbert_parent = PolynomialRing(ZZ, r, 'q')
     self._vars = matrix([[vars[i * n + j] for j in range(n)]
                          for i in range(r + inert)])
     self._X = matrix([[vars[i * n + j] for j in range(n)]
                       for i in range(r)])
     self._Theta = matrix([[vars[i * n + j] for j in range(n)]
                           for i in range(r, r + inert)])
     Parent.__init__(self,
                     facade=(P, ),
                     category=Algebras(QQ).Commutative())
Example #42
0
 def __init__(self, collection, name):
     dct = {'collection': collection, 'name': name}
     smple = find_sample(dct)
     assert smple, '%s: sample does not exist' % dct
     self.__collection = collection
     self.__name = name
     weight = smple.get('weight')
     field = smple.get('field')
     fcs = smple.get('Fourier_coefficients')
     evs = smple.get('eigenvalues')
     self.__weight = Integer(weight) if weight else weight
     R = PolynomialRing(IntegerRing(), name='x')
     self.__field = sage_eval(field,
                              locals=R.gens_dict()) if field else field
     loc_f = self.__field.gens_dict()
     P = PolynomialRing(self.__field, names='x,y')
     loc = P.gens_dict()
     loc.update(loc_f)
     self.__fcs = dict((tuple(eval(f)), sage_eval(fcs[f], locals=loc))
                       for f in fcs) if fcs else fcs
     loc = self.field().gens_dict()
     self.__evs = dict( (eval(l), sage_eval( evs[l], locals=loc_f)) for l in evs)\
         if evs else evs
     self.__explicit_formula = smple.get('explicit_formula')
    def Chow_form(self):
        r"""
        Returns the Chow form associated to this subscheme.

        For a `k`-dimensional subvariety of `\mathbb{P}^N` of degree `D`.
        The `(N-k-1)`-dimensional projective linear subspaces of `\mathbb{P}^N`
        meeting `X` form a hypersurface in the Grassmannian `G(N-k-1,N)`.
        The homogeneous form of degree `D` defining this hypersurface in Plucker
        coordinates is called the Chow form of `X`.

        The base ring needs to be a number field, finite field, or `\QQbar`.

        ALGORITHM:

        For a `k`-dimension subscheme `X` consider the `k+1` linear forms
        `l_i = u_{i0}x_0 + \cdots + u_{in}x_n`. Let `J` be the ideal in the
        polynomial ring `K[x_i,u_{ij}]` defined by the equations of `X` and the `l_i`.
        Let `J'` be the saturation of `J` with respect to the irrelevant ideal of
        the ambient projective space of `X`. The elimination ideal `I = J' \cap K[u_{ij}]`
        is a principal ideal, let `R` be its generator. The Chow form is obtained by
        writing `R` as a polynomial in Plucker coordinates (i.e. bracket polynomials).
        [DalbecSturmfels]_.

        OUTPUT: a homogeneous polynomial.

        REFERENCES:

        .. [DalbecSturmfels] J. Dalbec and B. Sturmfels. Invariant methods in discrete and computational geometry,
           chapter Introduction to Chow forms, pages 37-58. Springer Netherlands, 1994.

        EXAMPLES::

            sage: P.<x0,x1,x2,x3> = ProjectiveSpace(GF(17), 3)
            sage: X = P.subscheme([x3+x1,x2-x0,x2-x3])
            sage: X.Chow_form()
            t0 - t1 + t2 + t3

        ::

            sage: P.<x0,x1,x2,x3> = ProjectiveSpace(QQ,3)
            sage: X = P.subscheme([x3^2 -101*x1^2 - 3*x2*x0])
            sage: X.Chow_form()
            t0^2 - 101*t2^2 - 3*t1*t3

        ::

            sage: P.<x0,x1,x2,x3>=ProjectiveSpace(QQ,3)
            sage: X = P.subscheme([x0*x2-x1^2, x0*x3-x1*x2, x1*x3-x2^2])
            sage: Ch = X.Chow_form(); Ch
            t2^3 + 2*t2^2*t3 + t2*t3^2 - 3*t1*t2*t4 - t1*t3*t4 + t0*t4^2 + t1^2*t5
            sage: Y = P.subscheme_from_Chow_form(Ch, 1); Y
            Closed subscheme of Projective Space of dimension 3 over Rational Field
            defined by:
              x2^2*x3 - x1*x3^2,
              -x2^3 + x0*x3^2,
              -x2^2*x3 + x1*x3^2,
              x1*x2*x3 - x0*x3^2,
              3*x1*x2^2 - 3*x0*x2*x3,
              -2*x1^2*x3 + 2*x0*x2*x3,
              -3*x1^2*x2 + 3*x0*x1*x3,
              x1^3 - x0^2*x3,
              x2^3 - x1*x2*x3,
              -3*x1*x2^2 + 2*x1^2*x3 + x0*x2*x3,
              2*x0*x2^2 - 2*x0*x1*x3,
              3*x1^2*x2 - 2*x0*x2^2 - x0*x1*x3,
              -x0*x1*x2 + x0^2*x3,
              -x0*x1^2 + x0^2*x2,
              -x1^3 + x0*x1*x2,
              x0*x1^2 - x0^2*x2
            sage: I = Y.defining_ideal()
            sage: I.saturation(I.ring().ideal(list(I.ring().gens())))[0]
            Ideal (x2^2 - x1*x3, x1*x2 - x0*x3, x1^2 - x0*x2) of Multivariate
            Polynomial Ring in x0, x1, x2, x3 over Rational Field
        """
        I = self.defining_ideal()
        P = self.ambient_space()
        R = P.coordinate_ring()
        N = P.dimension() + 1
        d = self.dimension()
        # create the ring for the generic linear hyperplanes
        # u0x0 + u1x1 + ...
        SS = PolynomialRing(R.base_ring(), 'u', N * (d + 1), order='lex')
        vars = SS.variable_names() + R.variable_names()
        S = PolynomialRing(R.base_ring(), vars, order='lex')
        n = S.ngens()
        newcoords = [S.gen(n - N + t) for t in range(N)]
        # map the generators of the subscheme into the ring with the hyperplane variables
        phi = R.hom(newcoords, S)
        phi(self.defining_polynomials()[0])
        # create the dim(X)+1 linear hyperplanes
        l = []
        for i in range(d + 1):
            t = 0
            for j in range(N):
                t += S.gen(N * i + j) * newcoords[j]
            l.append(t)
        # intersect the hyperplanes with X
        J = phi(I) + S.ideal(l)
        # saturate the ideal with respect to the irrelevant ideal
        J2 = J.saturation(S.ideal([phi(u) for u in R.gens()]))[0]
        # eliminate the original variables to be left with the hyperplane coefficients 'u'
        E = J2.elimination_ideal(newcoords)
        # create the plucker coordinates
        D = binomial(N, N - d - 1)  #number of plucker coordinates
        tvars = [str('t') + str(i) for i in range(D)]  #plucker coordinates
        T = PolynomialRing(R.base_ring(),
                           tvars + list(S.variable_names()),
                           order='lex')
        L = []
        coeffs = [
            T.gen(i) for i in range(0 + len(tvars),
                                    N * (d + 1) + len(tvars))
        ]
        M = matrix(T, d + 1, N, coeffs)
        i = 0
        for c in M.minors(d + 1):
            L.append(T.gen(i) - c)
            i += 1
        # create the ideal that we can use for eliminating to get a polynomial
        # in the plucker coordinates (brackets)
        br = T.ideal(L)
        # create a mapping into a polynomial ring over the plucker coordinates
        # and the hyperplane coefficients
        psi = S.hom(coeffs + [0 for _ in range(N)], T)
        E2 = T.ideal([psi(u) for u in E.gens()] + br)
        # eliminate the hyperplane coefficients
        CH = E2.elimination_ideal(coeffs)
        # CH should be a principal ideal, but because of the relations among
        # the plucker coordinates, the elimination will probably have several generators

        # get the relations among the plucker coordinates
        rel = br.elimination_ideal(coeffs)
        # reduce CH with respect to the relations
        reduced = []
        for f in CH.gens():
            reduced.append(f.reduce(rel))
        # find the principal generator

        # polynomial ring in just the plucker coordinates
        T2 = PolynomialRing(R.base_ring(), tvars)
        alp = T.hom(tvars + (N * (d + 1) + N) * [0], T2)
        # get the degrees of the reduced generators of CH
        degs = [u.degree() for u in reduced]
        mind = max(degs)
        # need the smallest degree form that did not reduce to 0
        for d in degs:
            if d < mind and d > 0:
                mind = d
        ind = degs.index(mind)
        CF = reduced[ind]  #this should be the Chow form of X
        # check that it is correct (i.e., it is a principal generator for CH + the relations)
        rel2 = rel + [CF]
        assert all(f in rel2
                   for f in CH.gens()), "did not find a principal generator"
        return alp(CF)
Example #44
0
def Min(Fun, p, ubRes, conj, all_orbits=False):
    r"""
    Local loop for Affine_minimal, where we check minimality at the prime p.

    First we bound the possible k in our transformations A = zp^k + b.
    See Theorems 3.3.2 and 3.3.3 in [Molnar]_.

    INPUT:

    - ``Fun`` -- a dynamical system on projective space

    - ``p`` - a prime

    - ``ubRes`` -- integer, the upper bound needed for Th. 3.3.3 in [Molnar]_

    - ``conj`` -- a 2x2 matrix keeping track of the conjugation

    - ``all_orbits`` -- boolean; whether or not to use ``==`` in the
      inequalities to find all orbits

    OUTPUT:

    - boolean -- ``True`` if ``Fun`` is minimal at ``p``, ``False`` otherwise

    - a dynamical system on projective space minimal at ``p``

    EXAMPLES::

        sage: P.<x,y> = ProjectiveSpace(QQ, 1)
        sage: f = DynamicalSystem_projective([149*x^2 + 39*x*y + y^2, -8*x^2 + 137*x*y + 33*y^2])
        sage: from sage.dynamics.arithmetic_dynamics.endPN_minimal_model import Min
        sage: Min(f, 3, -27000000, matrix(QQ,[[1, 0],[0, 1]]))
        [
        Dynamical System of Projective Space of dimension 1 over Rational Field
          Defn: Defined on coordinates by sending (x : y) to
                (157*x^2 + 72*x*y + 3*y^2 : -24*x^2 + 121*x*y + 54*y^2)        ,
        <BLANKLINE>
        [3 1]
        [0 1]
        ]
    """
    d = Fun.degree()
    AffFun = Fun.dehomogenize(1)
    R = AffFun.coordinate_ring()
    if R.is_field():
        #want the polynomial ring not the fraction field
        R = R.ring()
    F = R(AffFun[0].numerator())
    G = R(AffFun[0].denominator())
    dG = G.degree()
    # all_orbits scales bounds for >= and <= if searching for orbits instead of min model
    if dG > (d + 1) / 2:
        lowerBound = (-2 * (G[dG]).valuation(p) /
                      (2 * dG - d + 1) + 1).floor() - int(all_orbits)
    else:
        lowerBound = (-2 * (F[d]).valuation(p) /
                      (d - 1) + 1).floor() - int(all_orbits)
    upperBound = 2 * (ubRes.valuation(p)) + int(all_orbits)

    if upperBound < lowerBound:
        # There are no possible transformations to reduce the resultant.
        if not all_orbits:
            return [Fun, conj]
        return []
    # Looping over each possible k, we search for transformations to reduce
    # the resultant of F/G
    all_found = []
    k = lowerBound
    Qb = PolynomialRing(QQ, 'b')
    b = Qb.gen(0)
    Q = PolynomialRing(Qb, 'z')
    z = Q.gen(0)
    while k <= upperBound:
        A = (p**k) * z + b
        Ft = Q(F(A) - b * G(A))
        Gt = Q((p**k) * G(A))
        Fcoeffs = Ft.coefficients(sparse=False)
        Gcoeffs = Gt.coefficients(sparse=False)
        coeffs = Fcoeffs + Gcoeffs
        RHS = (d + 1) * k / 2
        # If there is some b such that Res(phi^A) < Res(phi), we must have
        # ord_p(c) > RHS for each c in coeffs.
        # Make sure constant coefficients in coeffs satisfy the inequality.
        if all(
                QQ(c).valuation(p) > RHS - int(all_orbits) for c in coeffs
                if c.degree() == 0):
            # Constant coefficients in coeffs have large enough valuation, so
            # check the rest. We start by checking if simply picking b=0 works.
            if all(c(0).valuation(p) > RHS - int(all_orbits) for c in coeffs):
                # A = z*p^k satisfies the inequalities, and F/G is not minimal
                # "Conjugating by", p,"^", k, "*z +", 0
                newconj = matrix(QQ, 2, 2, [p**k, 0, 0, 1])
                minFun = Fun.conjugate(newconj)
                minFun.normalize_coordinates()
                if not all_orbits:
                    return [minFun, conj * newconj]
                all_found.append([p, k, 0])

            # Otherwise we search if any value of b will work. We start by
            # finding a minimum bound on the valuation of b that is necessary.
            # See Theorem 3.3.5 in [Molnar, M.Sc. thesis].
            bval = max(
                bCheck(coeff, RHS, p, b) for coeff in coeffs
                if coeff.degree() > 0)

            # We scale the coefficients in coeffs, so that we may assume
            # ord_p(b) is at least 0
            scaledCoeffs = [coeff(b * (p**bval)) for coeff in coeffs]

            # We now scale the inequalities, ord_p(coeff) > RHS, so that
            # coeff is in ZZ[b]
            scale = QQ(max(coeff.denominator() for coeff in scaledCoeffs))
            normalizedCoeffs = [coeff * scale for coeff in scaledCoeffs]
            scaleRHS = RHS + scale.valuation(p)

            # We now search for integers that satisfy the inequality
            # ord_p(coeff) > RHS. See Lemma 3.3.6 in [Molnar, M.Sc. thesis].
            bound = (scaleRHS + 1 - int(all_orbits)).floor()
            all_blift = blift(normalizedCoeffs,
                              bound,
                              p,
                              k,
                              all_orbits=all_orbits)

            # If bool is true after lifting, we have a solution b, and F/G
            # is not minimal.
            for boolval, sol in all_blift:
                if boolval:
                    #Rescale, conjugate and return new map
                    bsol = QQ(sol * (p**bval))
                    #only add 'minimal orbit element'
                    while bsol.abs() >= p**k:
                        if bsol < 0:
                            bsol += p**k
                        else:
                            bsol -= p**k
                    #"Conjugating by ", p,"^", k, "*z +", bsol
                    newconj = matrix(QQ, 2, 2, [p**k, bsol, 0, 1])
                    minFun = Fun.conjugate(newconj)

                    minFun.normalize_coordinates()
                    if not all_orbits:
                        return [minFun, conj * newconj]
                    if [p, k, bsol] not in all_found:
                        all_found.append([p, k, bsol])
        k = k + 1
    if not all_orbits:
        return [Fun, conj]
    return all_found
Example #45
0
def blift(LF, Li, p, k, S=None, all_orbits=False):
    r"""
    Search for a solution to the given list of inequalities.

    If found, lift the solution to
    an appropriate valuation. See Lemma 3.3.6 in [Molnar]_

    INPUT:

    - ``LF`` -- a list of integer polynomials in one variable (the normalized coefficients)

    - ``Li`` -- an integer, the bound on coefficients

    - ``p`` -- a prime

    - ``k`` -- the scaling factor that makes the solution a ``p``-adic integer

    - ``S`` -- polynomial ring to use

    - ``all_orbits`` -- boolean; whether or not to use ``==`` in the
      inequalities to find all orbits

    OUTPUT:

    - boolean -- whether or not the lift is successful

    - integer -- the lift

    EXAMPLES::

        sage: R.<b> = PolynomialRing(QQ)
        sage: from sage.dynamics.arithmetic_dynamics.endPN_minimal_model import blift
        sage: blift([8*b^3 + 12*b^2 + 6*b + 1, 48*b^2 + 483*b + 117, 72*b + 1341,\
        ....: -24*b^2 + 411*b + 99, -144*b + 1233, -216*b], 2, 3, 2)
        [[True, 4]]
    """

    P = LF[0].parent()
    #Determine which inequalities are trivial, and scale the rest, so that we only lift
    #as many times as needed.
    keepScaledIneqs = [scale(P(coeff), Li, p) for coeff in LF if coeff != 0]
    keptVals = [i[2] for i in keepScaledIneqs if i[0]]
    if keptVals != []:
        #Determine the valuation to lift until.
        liftval = max(keptVals)
    else:
        #All inequalities are satisfied.
        if all_orbits:
            return [[True, t] for t in range(p)]
        return [[True, 1]]
    if S is None:
        S = PolynomialRing(Zmod(p), 'b')
    keptScaledIneqs = [S(i[1]) for i in keepScaledIneqs if i[0]]
    #We need a solution for each polynomial on the left hand side of the inequalities,
    #so we need only find a solution for their gcd.
    g = gcd(keptScaledIneqs)
    rts = g.roots(multiplicities=False)
    good = []
    for r in rts:
        #Recursively try to lift each root
        r_initial = QQ(r)
        newInput = P([r_initial, p])
        LG = [F(newInput) for F in LF]
        new_good = blift(LG, Li, p, k, S=S)
        for lift, lifted in new_good:
            if lift:
                #Lift successful.
                if not all_orbits:
                    return [[True, r_initial + p * lifted]]

                #only need up to SL(2,ZZ) equivalence
                #this helps control the size of the resulting coefficients
                if r_initial + p * lifted < p**k:
                    good.append([True, r_initial + p * lifted])
                else:
                    new_r = r_initial + p * lifted - p**k
                    while new_r > p**k:
                        new_r -= p**k
                    if [True, new_r] not in good:
                        good.append([True, new_r])
    if good:
        return good
    #Lift non successful.
    return [[False, 0]]
Example #46
0
def LaurentPolynomialRing(base_ring, *args, **kwds):
    r"""
    Return the globally unique univariate or multivariate Laurent polynomial
    ring with given properties and variable name or names.

    There are four ways to call the Laurent polynomial ring constructor:

    1. ``LaurentPolynomialRing(base_ring, name,    sparse=False)``
    2. ``LaurentPolynomialRing(base_ring, names,   order='degrevlex')``
    3. ``LaurentPolynomialRing(base_ring, name, n, order='degrevlex')``
    4. ``LaurentPolynomialRing(base_ring, n, name, order='degrevlex')``

    The optional arguments sparse and order *must* be explicitly
    named, and the other arguments must be given positionally.

    INPUT:

    - ``base_ring`` -- a commutative ring
    - ``name`` -- a string
    - ``names`` -- a list or tuple of names, or a comma separated string
    - ``n`` -- a positive integer
    - ``sparse`` -- bool (default: False), whether or not elements are sparse
    - ``order`` -- string or
      :class:`~sage.rings.polynomial.term_order.TermOrder`, e.g.,

        - ``'degrevlex'`` (default) -- degree reverse lexicographic
        - ``'lex'`` -- lexicographic
        - ``'deglex'`` -- degree lexicographic
        - ``TermOrder('deglex',3) + TermOrder('deglex',3)`` -- block ordering

    OUTPUT:

    ``LaurentPolynomialRing(base_ring, name, sparse=False)`` returns a
    univariate Laurent polynomial ring; all other input formats return a
    multivariate Laurent polynomial ring.

    UNIQUENESS and IMMUTABILITY: In Sage there is exactly one
    single-variate Laurent polynomial ring over each base ring in each choice
    of variable and sparseness.  There is also exactly one multivariate
    Laurent polynomial ring over each base ring for each choice of names of
    variables and term order.

    ::

        sage: R.<x,y> = LaurentPolynomialRing(QQ,2); R
        Multivariate Laurent Polynomial Ring in x, y over Rational Field
        sage: f = x^2 - 2*y^-2

    You can't just globally change the names of those variables.
    This is because objects all over Sage could have pointers to
    that polynomial ring.

    ::

        sage: R._assign_names(['z','w'])
        Traceback (most recent call last):
        ...
        ValueError: variable names cannot be changed after object creation.


    EXAMPLES:

    1. ``LaurentPolynomialRing(base_ring, name, sparse=False)``

       ::

           sage: LaurentPolynomialRing(QQ, 'w')
           Univariate Laurent Polynomial Ring in w over Rational Field

       Use the diamond brackets notation to make the variable
       ready for use after you define the ring::

           sage: R.<w> = LaurentPolynomialRing(QQ)
           sage: (1 + w)^3
           1 + 3*w + 3*w^2 + w^3

       You must specify a name::

           sage: LaurentPolynomialRing(QQ)
           Traceback (most recent call last):
           ...
           TypeError: you must specify the names of the variables

           sage: R.<abc> = LaurentPolynomialRing(QQ, sparse=True); R
           Univariate Laurent Polynomial Ring in abc over Rational Field

           sage: R.<w> = LaurentPolynomialRing(PolynomialRing(GF(7),'k')); R
           Univariate Laurent Polynomial Ring in w over Univariate Polynomial Ring in k over Finite Field of size 7

       Rings with different variables are different::

           sage: LaurentPolynomialRing(QQ, 'x') == LaurentPolynomialRing(QQ, 'y')
           False

    2. ``LaurentPolynomialRing(base_ring, names,   order='degrevlex')``

       ::

           sage: R = LaurentPolynomialRing(QQ, 'a,b,c'); R
           Multivariate Laurent Polynomial Ring in a, b, c over Rational Field

           sage: S = LaurentPolynomialRing(QQ, ['a','b','c']); S
           Multivariate Laurent Polynomial Ring in a, b, c over Rational Field

           sage: T = LaurentPolynomialRing(QQ, ('a','b','c')); T
           Multivariate Laurent Polynomial Ring in a, b, c over Rational Field

       All three rings are identical.

       ::

           sage: (R is S) and  (S is T)
           True

       There is a unique Laurent polynomial ring with each term order::

           sage: R = LaurentPolynomialRing(QQ, 'x,y,z', order='degrevlex'); R
           Multivariate Laurent Polynomial Ring in x, y, z over Rational Field
           sage: S = LaurentPolynomialRing(QQ, 'x,y,z', order='invlex'); S
           Multivariate Laurent Polynomial Ring in x, y, z over Rational Field
           sage: S is LaurentPolynomialRing(QQ, 'x,y,z', order='invlex')
           True
           sage: R == S
           False


    3. ``LaurentPolynomialRing(base_ring, name, n, order='degrevlex')``

       If you specify a single name as a string and a number of
       variables, then variables labeled with numbers are created.

       ::

           sage: LaurentPolynomialRing(QQ, 'x', 10)
           Multivariate Laurent Polynomial Ring in x0, x1, x2, x3, x4, x5, x6, x7, x8, x9 over Rational Field

           sage: LaurentPolynomialRing(GF(7), 'y', 5)
           Multivariate Laurent Polynomial Ring in y0, y1, y2, y3, y4 over Finite Field of size 7

           sage: LaurentPolynomialRing(QQ, 'y', 3, sparse=True)
           Multivariate Laurent Polynomial Ring in y0, y1, y2 over Rational Field

       By calling the
       :meth:`~sage.structure.category_object.CategoryObject.inject_variables`
       method, all those variable names are available for interactive use::

           sage: R = LaurentPolynomialRing(GF(7),15,'w'); R
           Multivariate Laurent Polynomial Ring in w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14 over Finite Field of size 7
           sage: R.inject_variables()
           Defining w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14
           sage: (w0 + 2*w8 + w13)^2
           w0^2 + 4*w0*w8 + 4*w8^2 + 2*w0*w13 + 4*w8*w13 + w13^2
    """
    from sage.rings.polynomial.polynomial_ring import is_PolynomialRing
    from sage.rings.polynomial.multi_polynomial_ring_generic import is_MPolynomialRing

    R = PolynomialRing(base_ring, *args, **kwds)
    if R in _cache:
        return _cache[R]  # put () here to re-enable weakrefs

    if is_PolynomialRing(R):
        # univariate case
        P = LaurentPolynomialRing_univariate(R)
    else:
        assert is_MPolynomialRing(R)
        P = LaurentPolynomialRing_mpair(R)

    _cache[R] = P
    return P
Example #47
0
def enumerate_totallyreal_fields_rel(F, m, B, a = [], verbose=0, return_seqs=False):
    r"""
    This function enumerates (primitive) totally real field extensions of
    degree `m>1` of the totally real field F with discriminant `d \leq B`;
    optionally one can specify the first few coefficients, where the sequence ``a``
    corresponds to a polynomial by

    ::

        a[d]*x^n + ... + a[0]*x^(n-d)

    if ``length(a) = d+1``, so in particular always ``a[d] = 1``.
    If verbose == 1 (or 2), then print to the screen (really) verbosely; if
    verbose is a string, then print verbosely to the file specified by verbose.
    If return_seqs, then return the polynomials as sequences (for easier
    exporting to a file).

    NOTE:
    This is guaranteed to give all primitive such fields, and
    seems in practice to give many imprimitive ones.

    INPUT:

    - ``F`` -- number field, the base field
    - ``m`` -- integer, the degree
    - ``B`` -- integer, the discriminant bound
    - ``a`` -- list (default: []), the coefficient list to begin with
    - ``verbose`` -- boolean or string (default: 0)
    - ``return_seqs`` -- boolean (default: False)

    OUTPUT:

    the list of fields with entries [d,fabs,f], where
    d is the discriminant, fabs is an absolute defining polynomial,
    and f is a defining polynomial relative to F,
    sorted by discriminant.

    EXAMPLES::

        sage: ZZx = ZZ['x']
        sage: F.<t> = NumberField(x^2-2)
        sage: enumerate_totallyreal_fields_rel(F, 2, 2000)
        [[1600, x^4 - 6*x^2 + 4, xF^2 + xF - 1]]

    AUTHORS:

    - John Voight (2007-11-01)
    """

    if not isinstance(m, Integer):
        try:
            m = Integer(m)
        except TypeError:
            raise TypeError, "cannot coerce m (= %s) to an integer" % m
    if (m < 1):
        raise ValueError, "m must be at least 1."

    n = F.degree()*m

    # Initialize
    T = tr_data_rel(F,m,B,a)
    S = []
    Srel = []
    dB_odlyzko = odlyzko_bound_totallyreal(n)
    dB = math.ceil(40000*dB_odlyzko**n)
    counts = [0,0,0,0]

    # Trivial case
    if m == 1:
        g = pari(F.defining_polynomial()).reverse().Vec()
        if return_seqs:
            return [[0,0,0,0],[1,g,[-1,1]]]
        else:
            return [[1,pari('x-1'),g]]

    if verbose:
        saveout = sys.stdout
        if type(verbose) == str:
            fsock = open(verbose, 'w')
            sys.stdout = fsock
        # Else, print to screen
    f_out = [0]*m + [1]
    if verbose == 2:
        T.incr(f_out,verbose)
    else:
        T.incr(f_out)

    Fx = PolynomialRing(F, 'xF')

    nfF = pari(str(F.defining_polynomial()).replace('x', str(F.primitive_element()) ) )
    parit = pari(str(F.primitive_element()))

    while f_out[m] != 0:
        counts[0] += 1
        if verbose:
            print "==>", f_out,

        f_str = ''
        for i in range(len(f_out)):
            f_str += '(' + str(f_out[i]) + ')*x^' + str(i)
            if i < len(f_out)-1:
                f_str += '+'
        nf = pari(f_str)
        if nf.poldegree('t') == 0:
            nf = nf.subst('x', 'x-t')
        nf = nf.polresultant(nfF, parit)
        d = nf.poldisc()
        counts[0] += 1
        if d > 0 and nf.polsturm_full() == n:
            da = int_has_small_square_divisor(Integer(d))
            if d > dB or d <= B*da:
                counts[1] += 1
                if nf.polisirreducible():
                    counts[2] += 1
                    [zk,d] = nf.nfbasis_d()

                    if d <= B:
                        if verbose:
                            print "has discriminant", d,

                        # Find a minimal lattice element
                        counts[3] += 1
                        ng = pari([nf,zk]).polredabs()

                        # Check if K is contained in the list.
                        found = False
                        ind = bisect.bisect_left(S, [d,ng])
                        while ind < len(S) and S[ind][0] == d:
                            if S[ind][1] == ng:
                                if verbose:
                                    print "but is not new"
                                found = True
                                break
                            ind += 1
                        if not found:
                            if verbose:
                                print "and is new!"
                            S.insert(ind, [d,ng])
                            Srel.insert(ind, Fx(f_out))
                    else:
                        if verbose:
                            print "has discriminant", abs(d), "> B"
                else:
                    if verbose:
                        print "is not absolutely irreducible"
            else:
                if verbose:
                    print "has discriminant", abs(d), "with no large enough square divisor"
        else:
            if verbose:
                if d == 0:
                    print "is not squarefree"
                else:
                    print "is not totally real"
        if verbose == 2:
            T.incr(f_out,verbose=verbose)
        else:
            T.incr(f_out)

    # In the application of Smyth's theorem above, we exclude finitely
    # many possibilities which we must now throw back in.
    if m == 2:
        if Fx([-1,1,1]).is_irreducible():
            K = F.extension(Fx([-1,1,1]), 'tK')
            Kabs = K.absolute_field('tKabs')
            Kabs_pari = pari(Kabs.defining_polynomial())
            d = K.absolute_discriminant()
            if abs(d) <= B:
                ng = Kabs_pari.polredabs()
                ind = bisect.bisect_left(S, [d,ng])
                S.insert(ind, [d,ng])
                Srel.insert(ind, Fx([-1,1,1]))
        elif F.degree() == 2:
            for ff in [[1,-7,13,-7,1],[1,-8,14,-7,1]]:
                f = Fx(ff).factor()[0][0]
                K = F.extension(f, 'tK')
                Kabs = K.absolute_field('tKabs')
                Kabs_pari = pari(Kabs.defining_polynomial())
                d = K.absolute_discriminant()
                if abs(d) <= B:
                    ng = Kabs_pari.polredabs()
                    ind = bisect.bisect_left(S, [d,ng])
                    S.insert(ind, [d,ng])
                    Srel.insert(ind, f)
    elif m == 3:
        if Fx([-1,6,-5,1]).is_irreducible():
            K = F.extension(Fx([-1,6,-5,1]), 'tK')
            Kabs = K.absolute_field('tKabs')
            Kabs_pari = pari(Kabs.defining_polynomial())
            d = K.absolute_discriminant()
            if abs(d) <= B:
                ng = Kabs_pari.polredabs()
                ind = bisect.bisect_left(S, [d,ng])
                S.insert(ind, [d,ng])
                Srel.insert(ind, Fx([-1,6,-5,1]))

    # Now check for isomorphic fields
    S = [[S[i][0],S[i][1],Srel[i]] for i in range(len(S))]
    weed_fields(S)

    # Output.
    if verbose:
        print "="*80
        print "Polynomials tested:", counts[0]
        print "Irreducible polynomials:", counts[1]
        print "Polynomials with nfdisc <= B:", counts[2]
        for i in range(len(S)):
            print S[i]
        if type(verbose) == str:
            fsock.close()
        sys.stdout = saveout

    if return_seqs:
        return [counts,[[s[0],s[1].reverse().Vec(),s[2].coeffs()] for s in S]]
    else:
        return S
Example #48
0
artin_location = ("limbo", "artrep20130430")
galois_group_location = ("limbo", "nfgal20130430")

from type_generation import String, Array, Dict, Int, Anything, Float

from standard_types import PolynomialAsString, PermutationAsList,\
    TooLargeInt, LabelString, FiniteSequence, FiniteSet, PrimeIndexedSequence, AlgebraicNumberPolynomialString, \
    PolynomialAsString, AlgebraicNumberString_Root, PolynomialAsSequenceInt, PolynomialAsSequenceTooLargeInt

from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
from sage.rings.rational_field import QQ
from sage.rings.integer_ring import ZZ

Polynomial_X_QQ_AsString = PolynomialAsString(
    PolynomialRing(QQ, "x", sparse=False))
Polynomial_X_ZZ_AsString = PolynomialAsString(
    PolynomialRing(ZZ, "x", sparse=False))
Polynomial_a_ZZ_AsString = PolynomialAsString(
    PolynomialRing(ZZ, "a", sparse=False))

from bind_collection import bind_collection

Dokchitser_AlgebraicNumber_MinPol = PolynomialAsString(
    PolynomialRing(PolynomialRing(ZZ, "x", sparse=False), "a", sparse=False))
Dokchitser_AlgebraicNumber_Root = AlgebraicNumberString_Root


class Dokchitser_AlgorithmLabel(LabelString):
    pass

Example #49
0
        def q_dimension(self, q=None, prec=None, use_product=False):
            r"""
            Return the `q`-dimension of ``self``.

            Let `B(\lambda)` denote a highest weight crystal. Recall that
            the degree of the `\mu`-weight space of `B(\lambda)` (under
            the principal gradation) is equal to
            `\langle \rho^{\vee}, \lambda - \mu \rangle` where
            `\langle \rho^{\vee}, \alpha_i \rangle = 1` for all `i \in I`
            (in particular, take `\rho^{\vee} = \sum_{i \in I} h_i`).

            The `q`-dimension of a highest weight crystal `B(\lambda)` is
            defined as

            .. MATH::

                \dim_q B(\lambda) := \sum_{j \geq 0} \dim(B_j) q^j,

            where `B_j` denotes the degree `j` portion of `B(\lambda)`. This
            can be expressed as the product

            .. MATH::

                \dim_q B(\lambda) = \prod_{\alpha^{\vee} \in \Delta_+^{\vee}}
                \left( \frac{1 - q^{\langle \lambda + \rho, \alpha^{\vee}
                \rangle}}{1 - q^{\langle \rho, \alpha^{\vee} \rangle}}
                \right)^{\mathrm{mult}\, \alpha},

            where `\Delta_+^{\vee}` denotes the set of positive coroots.
            Taking the limit as `q \to 1` gives the dimension of `B(\lambda)`.
            For more information, see [Ka1990]_ Section 10.10.

            INPUT:

            - ``q`` -- the (generic) parameter `q`

            - ``prec`` -- (default: ``None``) The precision of the power
              series ring to use if the crystal is not known to be finite
              (i.e. the number of terms returned).
              If ``None``, then the result is returned as a lazy power series.

            - ``use_product`` -- (default: ``False``) if we have a finite
              crystal and ``True``, use the product formula

            EXAMPLES::

                sage: C = crystals.Tableaux(['A',2], shape=[2,1])
                sage: qdim = C.q_dimension(); qdim
                q^4 + 2*q^3 + 2*q^2 + 2*q + 1
                sage: qdim(1)
                8
                sage: len(C) == qdim(1)
                True
                sage: C.q_dimension(use_product=True) == qdim
                True
                sage: C.q_dimension(prec=20)
                q^4 + 2*q^3 + 2*q^2 + 2*q + 1
                sage: C.q_dimension(prec=2)
                2*q + 1

                sage: R.<t> = QQ[]
                sage: C.q_dimension(q=t^2)
                t^8 + 2*t^6 + 2*t^4 + 2*t^2 + 1

                sage: C = crystals.Tableaux(['A',2], shape=[5,2])
                sage: C.q_dimension()
                q^10 + 2*q^9 + 4*q^8 + 5*q^7 + 6*q^6 + 6*q^5
                 + 6*q^4 + 5*q^3 + 4*q^2 + 2*q + 1

                sage: C = crystals.Tableaux(['B',2], shape=[2,1])
                sage: qdim = C.q_dimension(); qdim
                q^10 + 2*q^9 + 3*q^8 + 4*q^7 + 5*q^6 + 5*q^5
                 + 5*q^4 + 4*q^3 + 3*q^2 + 2*q + 1
                sage: qdim == C.q_dimension(use_product=True)
                True

                sage: C = crystals.Tableaux(['D',4], shape=[2,1])
                sage: C.q_dimension()
                q^16 + 2*q^15 + 4*q^14 + 7*q^13 + 10*q^12 + 13*q^11
                 + 16*q^10 + 18*q^9 + 18*q^8 + 18*q^7 + 16*q^6 + 13*q^5
                 + 10*q^4 + 7*q^3 + 4*q^2 + 2*q + 1

            We check with a finite tensor product::

                sage: TP = crystals.TensorProduct(C, C)
                sage: TP.cardinality()
                25600
                sage: qdim = TP.q_dimension(use_product=True); qdim # long time
                q^32 + 2*q^31 + 8*q^30 + 15*q^29 + 34*q^28 + 63*q^27 + 110*q^26
                 + 175*q^25 + 276*q^24 + 389*q^23 + 550*q^22 + 725*q^21
                 + 930*q^20 + 1131*q^19 + 1362*q^18 + 1548*q^17 + 1736*q^16
                 + 1858*q^15 + 1947*q^14 + 1944*q^13 + 1918*q^12 + 1777*q^11
                 + 1628*q^10 + 1407*q^9 + 1186*q^8 + 928*q^7 + 720*q^6
                 + 498*q^5 + 342*q^4 + 201*q^3 + 117*q^2 + 48*q + 26
                sage: qdim(1) # long time
                25600
                sage: TP.q_dimension() == qdim # long time
                True

            The `q`-dimensions of infinite crystals are returned
            as formal power series::

                sage: C = crystals.LSPaths(['A',2,1], [1,0,0])
                sage: C.q_dimension(prec=5)
                1 + q + 2*q^2 + 2*q^3 + 4*q^4 + O(q^5)
                sage: C.q_dimension(prec=10)
                1 + q + 2*q^2 + 2*q^3 + 4*q^4 + 5*q^5 + 7*q^6
                 + 9*q^7 + 13*q^8 + 16*q^9 + O(q^10)
                sage: qdim = C.q_dimension(); qdim
                1 + q + 2*q^2 + 2*q^3 + 4*q^4 + 5*q^5 + 7*q^6
                 + 9*q^7 + 13*q^8 + 16*q^9 + 22*q^10 + O(x^11)
                sage: qdim.compute_coefficients(15)
                sage: qdim
                1 + q + 2*q^2 + 2*q^3 + 4*q^4 + 5*q^5 + 7*q^6
                 + 9*q^7 + 13*q^8 + 16*q^9 + 22*q^10 + 27*q^11
                 + 36*q^12 + 44*q^13 + 57*q^14 + 70*q^15 + O(x^16)

            """
            from sage.rings.all import ZZ
            WLR = self.weight_lattice_realization()
            I = self.index_set()
            mg = self.highest_weight_vectors()
            max_deg = float('inf') if prec is None else prec - 1

            def iter_by_deg(gens):
                next = set(gens)
                deg = -1
                while next and deg < max_deg:
                    deg += 1
                    yield len(next)
                    todo = next
                    next = set([])
                    while todo:
                        x = todo.pop()
                        for i in I:
                            y = x.f(i)
                            if y is not None:
                                next.add(y)
                # def iter_by_deg

            from sage.categories.finite_crystals import FiniteCrystals
            if self in FiniteCrystals():
                if q is None:
                    from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
                    q = PolynomialRing(ZZ, 'q').gen(0)

                if use_product:
                    # Since we are in the classical case, all roots occur with multiplicity 1
                    pos_coroots = [
                        x.associated_coroot() for x in WLR.positive_roots()
                    ]
                    rho = WLR.rho()
                    P = q.parent()
                    ret = P.zero()
                    for v in self.highest_weight_vectors():
                        hw = v.weight()
                        ret += P.prod((1 - q**(rho + hw).scalar(ac)) /
                                      (1 - q**rho.scalar(ac))
                                      for ac in pos_coroots)
                    # We do a cast since the result would otherwise live in the fraction field
                    return P(ret)

            elif prec is None:
                # If we're here, we may not be a finite crystal.
                # In fact, we're probably infinite.
                from sage.combinat.species.series import LazyPowerSeriesRing
                if q is None:
                    P = LazyPowerSeriesRing(ZZ, names='q')
                else:
                    P = q.parent()
                if not isinstance(P, LazyPowerSeriesRing):
                    raise TypeError(
                        "the parent of q must be a lazy power series ring")
                ret = P(iter_by_deg(mg))
                ret.compute_coefficients(10)
                return ret

            from sage.rings.power_series_ring import PowerSeriesRing, PowerSeriesRing_generic
            if q is None:
                q = PowerSeriesRing(ZZ, 'q', default_prec=prec).gen(0)
            P = q.parent()
            ret = P.sum(c * q**deg for deg, c in enumerate(iter_by_deg(mg)))
            if ret.degree() == max_deg and isinstance(P,
                                                      PowerSeriesRing_generic):
                ret = P(ret, prec)
            return ret
Example #50
0
    def create_key_and_extra_args(self,
                                  order,
                                  name=None,
                                  modulus=None,
                                  names=None,
                                  impl=None,
                                  proof=None,
                                  check_irreducible=True,
                                  prefix=None,
                                  repr=None,
                                  elem_cache=None,
                                  **kwds):
        """
        EXAMPLES::

            sage: GF.create_key_and_extra_args(9, 'a')
            ((9, ('a',), x^2 + 2*x + 2, 'givaro', 3, 2, True, None, 'poly', True), {})

        We do not take invalid keyword arguments and raise a value error
        to better ensure uniqueness::

            sage: GF.create_key_and_extra_args(9, 'a', foo='value')
            Traceback (most recent call last):
            ...
            TypeError: create_key_and_extra_args() got an unexpected keyword argument 'foo'

        Moreover, ``repr`` and ``elem_cache`` are ignored when not
        using givaro::

            sage: GF.create_key_and_extra_args(16, 'a', impl='ntl', repr='poly')
            ((16, ('a',), x^4 + x + 1, 'ntl', 2, 4, True, None, None, None), {})
            sage: GF.create_key_and_extra_args(16, 'a', impl='ntl', elem_cache=False)
            ((16, ('a',), x^4 + x + 1, 'ntl', 2, 4, True, None, None, None), {})
            sage: GF(16, impl='ntl') is GF(16, impl='ntl', repr='foo')
            True

        We handle extra arguments for the givaro finite field and
        create unique objects for their defaults::

            sage: GF(25, impl='givaro') is GF(25, impl='givaro', repr='poly')
            True
            sage: GF(25, impl='givaro') is GF(25, impl='givaro', elem_cache=True)
            True
            sage: GF(625, impl='givaro') is GF(625, impl='givaro', elem_cache=False)
            True

        We explicitly take ``structure``, ``implementation`` and ``prec`` attributes
        for compatibility with :class:`~sage.categories.pushout.AlgebraicExtensionFunctor`
        but we ignore them as they are not used, see :trac:`21433`::

            sage: GF.create_key_and_extra_args(9, 'a', structure=None)
            ((9, ('a',), x^2 + 2*x + 2, 'givaro', 3, 2, True, None, 'poly', True), {})
        """
        import sage.arith.all
        from sage.structure.proof.all import WithProof, arithmetic
        if proof is None:
            proof = arithmetic()
        for key, val in kwds.items():
            if key not in ['structure', 'implementation', 'prec', 'embedding']:
                raise TypeError(
                    "create_key_and_extra_args() got an unexpected keyword argument '%s'"
                    % key)
            if not (val is None
                    or isinstance(val, list) and all(c is None for c in val)):
                raise NotImplementedError(
                    "ring extension with prescribed %s is not implemented" %
                    key)
        with WithProof('arithmetic', proof):
            order = Integer(order)
            if order <= 1:
                raise ValueError(
                    "the order of a finite field must be at least 2")

            if order.is_prime():
                p = order
                n = Integer(1)
                if impl is None:
                    impl = 'modn'
                name = ('x', )  # Ignore name
                # Every polynomial of degree 1 is irreducible
                check_irreducible = False
            elif order.is_prime_power():
                if names is not None:
                    name = names
                if name is not None:
                    name = normalize_names(1, name)

                p, n = order.factor()[0]
                if name is None:
                    if prefix is None:
                        prefix = 'z'
                    name = prefix + str(n)
                    if modulus is not None:
                        raise ValueError(
                            "no modulus may be specified if variable name not given"
                        )
                    # Fpbar will have a strong reference, since algebraic_closure caches its results,
                    # and the coefficients of modulus lie in GF(p)
                    Fpbar = GF(p).algebraic_closure(prefix)
                    # This will give a Conway polynomial if p,n is small enough to be in the database
                    # and a pseudo-Conway polynomial if it's not.
                    modulus = Fpbar._get_polynomial(n)
                    check_irreducible = False

                if impl is None:
                    if order < zech_log_bound:
                        impl = 'givaro'
                    elif p == 2:
                        impl = 'ntl'
                    else:
                        impl = 'pari_ffelt'
            else:
                raise ValueError(
                    "the order of a finite field must be a prime power")

            # Determine modulus.
            # For the 'modn' implementation, we use the following
            # optimization which we also need to avoid an infinite loop:
            # a modulus of None is a shorthand for x-1.
            if modulus is not None or impl != 'modn':
                R = PolynomialRing(FiniteField(p), 'x')
                if modulus is None:
                    modulus = R.irreducible_element(n)
                if isinstance(modulus, str):
                    # A string specifies an algorithm to find a suitable modulus.
                    modulus = R.irreducible_element(n, algorithm=modulus)
                else:
                    if sage.rings.polynomial.polynomial_element.is_Polynomial(
                            modulus):
                        modulus = modulus.change_variable_name('x')
                    modulus = R(modulus).monic()

                    if modulus.degree() != n:
                        raise ValueError(
                            "the degree of the modulus does not equal the degree of the field"
                        )
                    if check_irreducible and not modulus.is_irreducible():
                        raise ValueError(
                            "finite field modulus must be irreducible but it is not"
                        )
                # If modulus is x - 1 for impl="modn", set it to None
                if impl == 'modn' and modulus[0] == -1:
                    modulus = None

            # Check extra arguments for givaro and setup their defaults
            # TODO: ntl takes a repr, but ignores it
            if impl == 'givaro':
                if repr is None:
                    repr = 'poly'
                if elem_cache is None:
                    elem_cache = (order < 500)
            else:
                # This has the effect of ignoring these keywords
                repr = None
                elem_cache = None

            return (order, name, modulus, impl, p, n, proof, prefix, repr,
                    elem_cache), {}
Example #51
0
        def __getitem__(self, arg):
            """
            Extend this ring by one or several elements to create a polynomial
            ring, a power series ring, or an algebraic extension.

            This is a convenience method intended primarily for interactive
            use.

            .. SEEALSO::

                :func:`~sage.rings.polynomial.polynomial_ring_constructor.PolynomialRing`,
                :func:`~sage.rings.power_series_ring.PowerSeriesRing`,
                :meth:`~sage.rings.ring.Ring.extension`,
                :meth:`sage.rings.integer_ring.IntegerRing_class.__getitem__`,
                :meth:`sage.rings.matrix_space.MatrixSpace.__getitem__`,
                :meth:`sage.structure.parent.Parent.__getitem__`

            EXAMPLES:

            We create several polynomial rings::

                sage: ZZ['x']
                Univariate Polynomial Ring in x over Integer Ring
                sage: QQ['x']
                Univariate Polynomial Ring in x over Rational Field
                sage: GF(17)['abc']
                Univariate Polynomial Ring in abc over Finite Field of size 17
                sage: GF(17)['a,b,c']
                Multivariate Polynomial Ring in a, b, c over Finite Field of size 17
                sage: GF(17)['a']['b']
                Univariate Polynomial Ring in b over Univariate Polynomial Ring in a over Finite Field of size 17

            We can create skew polynomial rings::

                sage: k.<t> = GF(5^3)
                sage: Frob = k.frobenius_endomorphism()
                sage: k['x',Frob]
                Skew Polynomial Ring in x over Finite Field in t of size 5^3 twisted by t |--> t^5

            We can also create power series rings by using double brackets::

                sage: QQ[['t']]
                Power Series Ring in t over Rational Field
                sage: ZZ[['W']]
                Power Series Ring in W over Integer Ring

                sage: ZZ[['x,y,z']]
                Multivariate Power Series Ring in x, y, z over Integer Ring
                sage: ZZ[['x','T']]
                Multivariate Power Series Ring in x, T over Integer Ring

            Use :func:`~sage.rings.fraction_field.Frac` or
            :meth:`~sage.rings.ring.CommutativeRing.fraction_field` to obtain
            the fields of rational functions and Laurent series::

                sage: Frac(QQ['t'])
                Fraction Field of Univariate Polynomial Ring in t over Rational Field
                sage: Frac(QQ[['t']])
                Laurent Series Ring in t over Rational Field
                sage: QQ[['t']].fraction_field()
                Laurent Series Ring in t over Rational Field

            Note that the same syntax can be used to create number fields::

                sage: QQ[I]
                Number Field in I with defining polynomial x^2 + 1
                sage: QQ[I].coerce_embedding()
                Generic morphism:
                 From: Number Field in I with defining polynomial x^2 + 1
                 To:   Complex Lazy Field
                 Defn: I -> 1*I

            ::

                sage: QQ[sqrt(2)]
                Number Field in sqrt2 with defining polynomial x^2 - 2
                sage: QQ[sqrt(2)].coerce_embedding()
                Generic morphism:
                 From: Number Field in sqrt2 with defining polynomial x^2 - 2
                 To:   Real Lazy Field
                 Defn: sqrt2 -> 1.414213562373095?

            ::

                sage: QQ[sqrt(2),sqrt(3)]
                Number Field in sqrt2 with defining polynomial x^2 - 2 over its base field

            and orders in number fields::

                sage: ZZ[I]
                Order in Number Field in I with defining polynomial x^2 + 1
                sage: ZZ[sqrt(5)]
                Order in Number Field in sqrt5 with defining polynomial x^2 - 5
                sage: ZZ[sqrt(2)+sqrt(3)]
                Order in Number Field in a with defining polynomial x^4 - 10*x^2 + 1

            Embeddings are found for simple extensions (when that makes sense)::

                sage: QQi.<i> = QuadraticField(-1, 'i')
                sage: QQ[i].coerce_embedding()
                Generic morphism:
                  From: Number Field in i with defining polynomial x^2 + 1
                  To:   Complex Lazy Field
                  Defn: i -> 1*I

            TESTS:

            A few corner cases::

                sage: QQ[()]
                Multivariate Polynomial Ring in no variables over Rational Field

                sage: QQ[[]]
                Traceback (most recent call last):
                ...
                TypeError: power series rings must have at least one variable

            These kind of expressions do not work::

                sage: QQ['a,b','c']
                Traceback (most recent call last):
                ...
                ValueError: variable name 'a,b' is not alphanumeric
                sage: QQ[['a,b','c']]
                Traceback (most recent call last):
                ...
                ValueError: variable name 'a,b' is not alphanumeric

                sage: QQ[[['x']]]
                Traceback (most recent call last):
                ...
                TypeError: expected R[...] or R[[...]], not R[[[...]]]

            Extension towers are built as follows and use distinct generator names::

                sage: K = QQ[2^(1/3), 2^(1/2), 3^(1/3)]
                sage: K
                Number Field in a with defining polynomial x^3 - 2 over its base field
                sage: K.base_field()
                Number Field in sqrt2 with defining polynomial x^2 - 2 over its base field
                sage: K.base_field().base_field()
                Number Field in b with defining polynomial x^3 - 3

            Embeddings::

                sage: QQ[I](I.pyobject())
                I
                sage: a = 10^100; expr = (2*a + sqrt(2))/(2*a^2-1)
                sage: QQ[expr].coerce_embedding() is None
                False
                sage: QQ[sqrt(5)].gen() > 0
                True
                sage: expr = sqrt(2) + I*(cos(pi/4, hold=True) - sqrt(2)/2)
                sage: QQ[expr].coerce_embedding()
                Generic morphism:
                  From: Number Field in a with defining polynomial x^2 - 2
                  To:   Real Lazy Field
                  Defn: a -> 1.414213562373095?
            """
            def normalize_arg(arg):
                if isinstance(arg, (tuple, list)):
                    # Allowing arbitrary iterables would create confusion, but we
                    # may want to support a few more.
                    return tuple(arg)
                elif isinstance(arg, str):
                    return tuple(arg.split(','))
                else:
                    return (arg,)

            # 1. If arg is a list, try to return a power series ring.

            if isinstance(arg, list):
                if arg == []:
                    raise TypeError("power series rings must have at least one variable")
                elif len(arg) == 1:
                    # R[["a,b"]], R[[(a,b)]]...
                    if isinstance(arg[0], list):
                        raise TypeError("expected R[...] or R[[...]], not R[[[...]]]")
                    elts = normalize_arg(arg[0])
                else:
                    elts = normalize_arg(arg)
                from sage.rings.power_series_ring import PowerSeriesRing
                return PowerSeriesRing(self, elts)

            if isinstance(arg, tuple):
                from sage.categories.morphism import Morphism
                if len(arg) == 2 and isinstance(arg[1], Morphism):
                   from sage.rings.polynomial.skew_polynomial_ring_constructor import SkewPolynomialRing
                   return SkewPolynomialRing(self, arg[1], names=arg[0])

            # 2. Otherwise, if all specified elements are algebraic, try to
            #    return an algebraic extension

            elts = normalize_arg(arg)

            try:
                minpolys = [a.minpoly() for a in elts]
            except (AttributeError, NotImplementedError, ValueError, TypeError):
                minpolys = None

            if minpolys:
                # how to pass in names?
                names = tuple(_gen_names(elts))
                if len(elts) == 1:
                    from sage.rings.all import CIF, CLF, RIF, RLF
                    elt = elts[0]
                    try:
                        iv = CIF(elt)
                    except (TypeError, ValueError):
                        emb = None
                    else:
                        # First try creating an ANRoot manually, because
                        # extension(..., embedding=CLF(expr)) (or
                        # ...QQbar(expr)) would normalize the expression in
                        # QQbar, which currently is VERY slow in many cases.
                        # This may fail when minpoly has close roots or elt is
                        # a complicated symbolic expression.
                        # TODO: Rewrite using #19362 and/or #17886 and/or
                        # #15600 once those issues are solved.
                        from sage.rings.qqbar import AlgebraicNumber, ANRoot
                        try:
                            elt = AlgebraicNumber(ANRoot(minpolys[0], iv))
                        except ValueError:
                            pass
                        # Force a real embedding when possible, to get the
                        # right ordered ring structure.
                        if (iv.imag().is_zero() or iv.imag().contains_zero()
                                                   and elt.imag().is_zero()):
                            emb = RLF(elt)
                        else:
                            emb = CLF(elt)
                        return self.extension(minpolys[0], names[0], embedding=emb)
                try:
                    # Doing the extension all at once is best, if possible...
                    return self.extension(minpolys, names)
                except (TypeError, ValueError):
                    # ...but we can also construct it iteratively
                    return reduce(lambda R, ext: R.extension(*ext), zip(minpolys, names), self)

            # 2. Otherwise, try to return a polynomial ring

            from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
            return PolynomialRing(self, elts)
    def _forward_image(self, f, check=True):
        r"""
        Compute the forward image of this subscheme by the morphism ``f``.

        The forward image is computed through elimination and ``f`` must be
        a morphism for this to be well defined.
        In particular, let $X = V(h_1,\ldots, h_t)$ and define the ideal
        $I = (h_1,\ldots,h_t,y_0-f_0(\bar{x}), \ldots, y_n-f_n(\bar{x}))$.
        Then the elimination ideal $I_{n+1} = I \cap K[y_0,\ldots,y_n]$ is a homogeneous
        ideal and $self(X) = V(I_{n+1})$.

        INPUT:

        - ``f`` -- a map whose domain contains ``self``

        - ``check`` -- Boolean, if `False` no input checking is done

        OUTPUT:

         - a subscheme in the codomain of ``f``.

        EXAMPLES::

            sage: PS.<x,y,z> = ProjectiveSpace(QQ, 2)
            sage: H = End(PS)
            sage: f = H([x^2, y^2-2*z^2, z^2])
            sage: X = PS.subscheme(y-2*z)
            sage: X._forward_image(f)
            Closed subscheme of Projective Space of dimension 2 over Rational Field
            defined by:
              y - 2*z

        ::

            sage: set_verbose(None)
            sage: PS.<x,y,z,w> = ProjectiveSpace(ZZ, 3)
            sage: H = End(PS)
            sage: f = H([y^2, x^2, w^2, z^2])
            sage: X = PS.subscheme([z^2+y*w, x-w])
            sage: f(X)
            Closed subscheme of Projective Space of dimension 3 over Integer Ring
            defined by:
              y - z,
              x*z - w^2

        ::

            sage: PS.<x,y,z,w> = ProjectiveSpace(CC, 3)
            sage: H = End(PS)
            sage: f = H([x^2 + y^2, y^2, z^2-y^2, w^2])
            sage: X = PS.subscheme([z-2*w])
            sage: f(X)
            Closed subscheme of Projective Space of dimension 3 over Complex Field
            with 53 bits of precision defined by:
              y + z + (-4.00000000000000)*w

        ::

            sage: R.<t> = PolynomialRing(QQ)
            sage: P.<x,y,z> = ProjectiveSpace(FractionField(R), 2)
            sage: H = End(P)
            sage: f = H([x^2 + 2*y*z, t^2*y^2, z^2])
            sage: f([t^2*y-z])
            Closed subscheme of Projective Space of dimension 2 over Fraction Field
            of Univariate Polynomial Ring in t over Rational Field defined by:
              y + (-1/t^2)*z

        ::

            sage: set_verbose(-1)
            sage: PS.<x,y,z> = ProjectiveSpace(Qp(3), 2)
            sage: H = End(PS)
            sage: f = H([x^2,2*y^2,z^2])
            sage: X = PS.subscheme([2*x-y,z])
            sage: f(X)
            Closed subscheme of Projective Space of dimension 2 over 3-adic Field
            with capped relative precision 20 defined by:
              z,
              x + (1 + 3^2 + 3^4 + 3^6 + 3^8 + 3^10 + 3^12 + 3^14 + 3^16 + 3^18 +
            O(3^20))*y

        ::

            sage: R.<y0,y1,y2,y3> = PolynomialRing(QQ)
            sage: P.<x,y,z> = ProjectiveSpace(FractionField(R), 2)
            sage: H = End(P)
            sage: f = H([y0*x^2+y1*z^2, y2*y^2+y3*z^2, z^2])
            sage: X = P.subscheme(x*z)
            sage: X._forward_image(f)
            Closed subscheme of Projective Space of dimension 2 over Fraction Field
            of Multivariate Polynomial Ring in y0, y1, y2, y3 over Rational Field
            defined by:
              x*z + (-y1)*z^2

            ::

            sage: P2.<x,y,z> = ProjectiveSpace(QQ, 2)
            sage: P5.<z0,z1,z2,z3,z4,z5> = ProjectiveSpace(QQ, 5)
            sage: H = Hom(P2, P5)
            sage: f = H([x^2,x*y,x*z,y^2,y*z,z^2]) #Veronese map
            sage: X = P2.subscheme([])
            sage: f(X)
            Closed subscheme of Projective Space of dimension 5 over Rational Field
            defined by:
              -z4^2 + z3*z5,
              -z2*z4 + z1*z5,
              -z2*z3 + z1*z4,
              -z2^2 + z0*z5,
              -z1*z2 + z0*z4,
              -z1^2 + z0*z3

            ::

            sage: P2.<x,y,z>=ProjectiveSpace(QQ, 2)
            sage: P3.<u,v,w,t>=ProjectiveSpace(QQ, 3)
            sage: H = Hom(P2, P3)
            sage: X = P2.subscheme([x-y,x-z])
            sage: f = H([x^2,y^2,z^2,x*y])
            sage: f(X)
            Closed subscheme of Projective Space of dimension 3 over Rational Field
            defined by:
              w - t,
              v - t,
              u - t

            ::

            sage: P1.<u,v> = ProjectiveSpace(QQ, 1)
            sage: P2.<x,y,z> = ProjectiveSpace(QQ, 2)
            sage: H = Hom(P2,P1)
            sage: f = H([x^2,y*z])
            sage: X = P2.subscheme([x-y])
            sage: f(X)
            Traceback (most recent call last):
            ...
            TypeError: map must be a morphism

            ::

            sage: PS.<x,y,z> = ProjectiveSpace(ZZ, 2)
            sage: H = End(PS)
            sage: f = H([x^3, x*y^2, x*z^2])
            sage: X = PS.subscheme([x-y])
            sage: X._forward_image(f)
            Traceback (most recent call last):
            ...
            TypeError: map must be a morphism

        ::

            sage: PS.<x,y,z> = ProjectiveSpace(QQ, 2)
            sage: P1.<u,v> = ProjectiveSpace(QQ, 1)
            sage: Y = P1.subscheme([u-v])
            sage: H = End(PS)
            sage: f = H([x^2, y^2, z^2])
            sage: Y._forward_image(f)
            Traceback (most recent call last):
            ...
            TypeError: subscheme must be in ambient space of domain of map
        """
        dom = f.domain()
        codom = f.codomain()
        if check:
            if not f.is_morphism():
                raise TypeError("map must be a morphism")
            if self.ambient_space() != dom:
                raise TypeError(
                    "subscheme must be in ambient space of domain of map")
        CR_dom = dom.coordinate_ring()
        CR_codom = codom.coordinate_ring()
        n = CR_dom.ngens()
        m = CR_codom.ngens()
        #can't call eliminate if the base ring is polynomial so we do it ourselves
        #with a lex ordering
        R = PolynomialRing(f.base_ring(), n + m, 'tempvar', order='lex')
        Rvars = R.gens()[0:n]
        phi = CR_dom.hom(Rvars, R)
        zero = n * [0]
        psi = R.hom(zero + list(CR_codom.gens()), CR_codom)
        #set up ideal
        L = R.ideal([phi(t) for t in self.defining_polynomials()] +
                    [R.gen(n + i) - phi(f[i]) for i in range(m)])
        G = L.groebner_basis()  #eliminate
        newL = []
        #get only the elimination ideal portion
        for i in range(len(G) - 1, 0, -1):
            v = G[i].variables()
            if all(Rvars[j] not in v for j in range(n)):
                newL.append(psi(G[i]))
        return (codom.subscheme(newL))
    def dual(self):
        r"""
        Return the projective dual of the given subscheme of projective space.

        INPUT:

        - ``X`` -- A subscheme of projective space. At present, ``X`` is
          required to be an irreducible and reduced hypersurface defined
          over `\QQ` or a finite field.

        OUTPUT:

        - The dual of ``X`` as a subscheme of the dual projective space.

        EXAMPLES:

        The dual of a smooth conic in the plane is also a smooth conic::

            sage: R.<x, y, z> = QQ[]
            sage: P.<x, y, z> = ProjectiveSpace(2, QQ)
            sage: I = R.ideal(x^2 + y^2 + z^2)
            sage: X = P.subscheme(I)
            sage: X.dual()
            Closed subscheme of Projective Space of dimension 2 over Rational Field defined by:
              y0^2 + y1^2 + y2^2

        The dual of the twisted cubic curve in projective 3-space is a singular
        quartic surface. In the following example, we compute the dual of this
        surface, which by double duality is equal to the twisted cubic itself.
        The output is the twisted cubic as an intersection of three quadrics::

            sage: R.<x, y, z, w> = QQ[]
            sage: P.<x, y, z, w> = ProjectiveSpace(3, QQ)
            sage: I = R.ideal(y^2*z^2 - 4*x*z^3 - 4*y^3*w + 18*x*y*z*w - 27*x^2*w^2)
            sage: X = P.subscheme(I)
            sage: X.dual()
            Closed subscheme of Projective Space of dimension 3 over
            Rational Field defined by:
              y2^2 - y1*y3,
              y1*y2 - y0*y3,
              y1^2 - y0*y2

        The singular locus of the quartic surface in the last example
        is itself supported on a twisted cubic::

            sage: X.Jacobian().radical()
            Ideal (z^2 - 3*y*w, y*z - 9*x*w, y^2 - 3*x*z) of Multivariate
            Polynomial Ring in x, y, z, w over Rational Field

        An example over a finite field::

            sage: R = PolynomialRing(GF(61), 'a,b,c')
            sage: P.<a, b, c> = ProjectiveSpace(2, R.base_ring())
            sage: X = P.subscheme(R.ideal(a*a+2*b*b+3*c*c))
            sage: X.dual()
            Closed subscheme of Projective Space of dimension 2 over
            Finite Field of size 61 defined by:
            y0^2 - 30*y1^2 - 20*y2^2

        TESTS::

            sage: R = PolynomialRing(Qp(3), 'a,b,c')
            sage: P.<a, b, c> = ProjectiveSpace(2, R.base_ring())
            sage: X = P.subscheme(R.ideal(a*a+2*b*b+3*c*c))
            sage: X.dual()
            Traceback (most recent call last):
            ...
            NotImplementedError: base ring must be QQ or a finite field
        """
        from sage.libs.singular.function_factory import ff

        K = self.base_ring()
        if not (is_RationalField(K) or is_FiniteField(K)):
            raise NotImplementedError("base ring must be QQ or a finite field")
        I = self.defining_ideal()
        m = I.ngens()
        n = I.ring().ngens() - 1
        if (m != 1 or (n < 1) or I.is_zero() or I.is_trivial()
                or not I.is_prime()):
            raise NotImplementedError("At the present, the method is only"
                                      " implemented for irreducible and"
                                      " reduced hypersurfaces and the given"
                                      " list of generators for the ideal must"
                                      " have exactly one element.")
        R = PolynomialRing(K, 'x', n + 1)
        from sage.schemes.projective.projective_space import ProjectiveSpace
        Pd = ProjectiveSpace(n, K, 'y')
        Rd = Pd.coordinate_ring()
        x = R.variable_names()
        y = Rd.variable_names()
        S = PolynomialRing(K, x + y + ('t', ))
        if S.has_coerce_map_from(I.ring()):
            T = PolynomialRing(K, 'w', n + 1)
            I_S = (I.change_ring(T)).change_ring(S)
        else:
            I_S = I.change_ring(S)
        f_S = I_S.gens()[0]
        z = S.gens()
        J = I_S
        for i in range(n + 1):
            J = J + S.ideal(z[-1] * f_S.derivative(z[i]) - z[i + n + 1])

        sat = ff.elim__lib.sat

        max_ideal = S.ideal(z[n + 1:2 * n + 2])
        J_sat_gens = sat(J, max_ideal)[0]
        J_sat = S.ideal(J_sat_gens)
        L = J_sat.elimination_ideal(z[0:n + 1] + (z[-1], ))
        return Pd.subscheme(L.change_ring(Rd))
Example #54
0
            def expand(self, n, letter='x'):
                r"""
                Expand ``self`` written in the `\mathbf{w}` basis in `n^2`
                commuting variables which satisfy the relation
                `x_{ij} x_{ik} = 0` for all `i`, `j`, and `k`.

                The expansion of an element of the `\mathbf{w}` basis is
                given by equations (26) and (55) in [HNT06]_.

                INPUT:

                - ``n`` -- an integer
                - ``letter`` -- (default: ``'x'``) a string

                OUTPUT:

                - The symmetric function of ``self`` expressed in the ``n*n``
                  non-commuting variables described by ``letter``.

                REFERENCES:

                .. [HNT06] \F. Hivert, J.-C. Novelli, J.-Y. Thibon.
                   *Commutative combinatorial Hopf algebras*. (2006).
                   :arxiv:`0605262v1`.

                EXAMPLES::

                    sage: w = SymmetricFunctionsNonCommutingVariables(QQ).dual().w()
                    sage: w[[1,3],[2]].expand(4)
                    x02*x11*x20 + x03*x11*x30 + x03*x22*x30 + x13*x22*x31

                One can use a different set of variable by using the
                optional argument ``letter``::

                    sage: w[[1,3],[2]].expand(3, letter='y')
                    y02*y11*y20
                """
                from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
                from sage.combinat.permutation import Permutations

                m = self.parent()
                names = ['{}{}{}'.format(letter, i, j) for i in range(n) for j in range(n)]
                R = PolynomialRing(m.base_ring(), n*n, names)
                x = [[R.gens()[i*n+j] for j in range(n)] for i in range(n)]
                I = R.ideal([x[i][j]*x[i][k] for j in range(n) for k in range(n) for i in range(n)])
                Q = R.quotient(I, names)
                x = [[Q.gens()[i*n+j] for j in range(n)] for i in range(n)]
                P = SetPartitions()

                def on_basis(A):
                    k = A.size()
                    ret = R.zero()
                    if n < k:
                        return ret

                    for p in Permutations(k):
                        if P(p.to_cycles()) == A:
                            # -1 for indexing
                            ret += R.sum(prod(x[I[i]][I[p[i]-1]] for i in range(k))
                                         for I in Subsets(range(n), k))
                    return ret

                return m._apply_module_morphism(self, on_basis, codomain=R)
Example #55
0
    def __init__(self, F, m, B, a=None):
        r"""
        Initialization routine (constructor).

        INPUT:

        - ``F`` -- number field, the base field
        - ``m`` -- integer, the relative degree
        - ``B`` -- integer, the discriminant bound
        - ``a`` -- list (default: []), the coefficient list to begin with,
          corresponding to ``a[len(a)]*x^n + ... + a[0]x^(n-len(a))``.

        OUTPUT:

        the data initialized to begin enumeration of totally real fields
        with base field F, degree n, discriminant bounded by B, and starting
        with coefficients a.

        EXAMPLES::

            sage: F.<t> = NumberField(x^2-2)
            sage: T = sage.rings.number_field.totallyreal_rel.tr_data_rel(F, 2, 2000)
        """
        if a is None:  # don't make the stupid noob mistake of putting a=[]
            a = []     # in the function signature above.

        # Initialize constants.
        self.m = m
        d = F.degree()
        self.d = d
        self.n = m*d
        self.B = B
        self.gamma = hermite_constant(self.n-self.d)

        self.F = F
        self.Z_F = F.maximal_order()
        self.Foo = F.real_embeddings()
        self.dF = abs(F.disc())
        self.Fx = PolynomialRing(F, 'xF')

        self.beta = [[]]*m
        self.gnk = [[]]*m

        self.trace_elts = []

        Z_Fbasis = self.Z_F.basis()

        # Initialize variables.
        if a == []:
            # No starting input, all polynomials will be found; initialize to zero.
            self.a = [0]*m + [1]
            self.amaxvals = [[]]*m
            anm1s = [[i] for i in range(0,m//2+1)]
            for i in range(1,self.d):
                for j in range(len(anm1s)):
                    anm1s[j] = [ anm1s[j] + [i] for i in range(m)]
                anm1s = sum(anm1s, [])
            anm1s = [sum([Z_Fbasis[i]*a[i] for i in range(self.d)]) for a in anm1s]
            # Minimize trace in class.
            import numpy
            for i in range(len(anm1s)):
                Q = [ [ v(m*x) for v in self.Foo] + [0] for x in Z_Fbasis] + [[v(anm1s[i]) for v in self.Foo] + [10**6]]
                pari_string = '['+';'.join([','.join(["%s"%ii for ii in row]) for row in zip(*Q)])+']'
                adj = pari(pari_string).qflll()[self.d]
                anm1s[i] += sum([m*Z_Fbasis[ii]*int(adj[ii])//int(adj[self.d]) for ii in range(self.d)])

            self.amaxvals[m-1] = anm1s
            self.a[m-1] = self.amaxvals[m-1].pop()
            self.k = m-2

            bl = math.ceil(1.7719*self.n)
            br = max([1./m*(am1**2).trace() + \
                            self.gamma*(1./(m**d)*self.B/self.dF)**(1./(self.n-d)) for am1 in anm1s])
            br = math.floor(br)
            T2s = self.F._positive_integral_elements_with_trace([bl,br])
            self.trace_elts.append([bl,br,T2s])

        elif len(a) <= m+1:
            # First few coefficients have been specified.
            # The value of k is the largest index of the coefficients of a which is
            # currently unknown; e.g., if k == -1, then we can iterate
            # over polynomials, and if k == n-1, then we have finished iterating.
            if a[len(a)-1] != 1:
                raise ValueError, "a[len(a)-1](=%s) must be 1 so polynomial is monic"%a[len(a)-1]

            raise NotImplementedError, "These have not been checked."

            k = m-len(a)
            self.k = k
            a = [0]*(k+1) + a
            self.amaxvals = [[]]*m
            for i in range(0,n+1):
                self.a[i] = a[i]

            # Bounds come from an application of Lagrange multipliers in degrees 2,3.
            self.b_lower = [-1./m*(v(self.a[m-1]) +
                              (m-1.)*math.sqrt(v(self.a[m-1])**2 - 2.*(1+1./(m-1))*v(self.a[m-2]))) for v in self.Foo]
            self.b_upper = [-1./m*(v(self.a[m-1]) -
                              (m-1.)*math.sqrt(v(self.a[m-1])**2 - 2.*(1+1./(m-1))*v(self.a[m-2]))) for v in self.Foo]
            if k < m-2:
                bminmax = [lagrange_degree_3(n,v(self.a[m-1]),v(self.a[m-2]),v(self.a[m-3])) for v in self.Foo]
                self.b_lower = bminmax[0]
                self.b_upper = bminmax[1]

            # Annoying, but must reverse coefficients for numpy.
            gnk = [binomial(j,k+2)*a[j] for j in range(k+2,n+1)]
            self.beta[k+1] = [[self.b_lower] + numpy.roots([v(gnk[i]) for i in range(len(gnk))].reverse()).tolist().sort() + [self.b_upper] for v in self.Foo]

            # Now to really initialize gnk.
            self.gnk[k+1] = [[0] + [binomial(j,k+1)*v(a[j]) for j in range (k+2,m+1)] for v in self.Foo]
        else:
            # Bad input!
            raise ValueError, "a has length %s > m+1"%len(a)
Example #56
0
class PetersonPolynomials(SageObject):
    """
    A class that computes the Peterson polynomials and their expression as
    Dickson polynomials.
    """
    def __init__(self, p, n):
        """
        TESTS::

            sage: from yacop.modules.dickson import PetersonPolynomials
            sage: P=PetersonPolynomials(3,2) ; P
            Peterson element factory for prime 3, index 2
            sage: for idx in range(20):
            ....:     print("%-3d : %s" % (idx,P.omega(idx)))
            0   : 1
            1   : x1^2 + x2^2
            2   : x1^4 + x1^2*x2^2 + x2^4
            3   : x1^6 + x1^4*x2^2 + x1^2*x2^4 + x2^6
            4   : x1^6*x2^2 + x1^4*x2^4 + x1^2*x2^6
            5   : -x1^10 + x1^6*x2^4 + x1^4*x2^6 - x2^10
            6   : x1^12 - x1^10*x2^2 + x1^6*x2^6 - x1^2*x2^10 + x2^12
            7   : x1^12*x2^2 - x1^10*x2^4 - x1^4*x2^10 + x1^2*x2^12
            8   : x1^12*x2^4 - x1^10*x2^6 - x1^6*x2^10 + x1^4*x2^12
            9   : x1^18 + x1^12*x2^6 + x1^6*x2^12 + x2^18
            10  : x1^18*x2^2 + x1^10*x2^10 + x1^2*x2^18
            11  : x1^18*x2^4 - x1^12*x2^10 - x1^10*x2^12 + x1^4*x2^18
            12  : x1^18*x2^6 + x1^12*x2^12 + x1^6*x2^18
            13  : 0
            14  : x1^28 - x1^18*x2^10 - x1^10*x2^18 + x2^28
            15  : -x1^30 + x1^28*x2^2 + x1^18*x2^12 + x1^12*x2^18 + x1^2*x2^28 - x2^30
            16  : -x1^30*x2^2 + x1^28*x2^4 + x1^4*x2^28 - x1^2*x2^30
            17  : -x1^30*x2^4 + x1^28*x2^6 + x1^6*x2^28 - x1^4*x2^30
            18  : x1^36 - x1^30*x2^6 + x1^18*x2^18 - x1^6*x2^30 + x2^36
            19  : x1^36*x2^2 - x1^28*x2^10 - x1^10*x2^28 + x1^2*x2^36

        """
        from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
        from yacop.modules.classifying_spaces import BZpGeneric
        from sage.categories.tensor import tensor

        self.p = p
        self.n = n
        self.B = BZpGeneric(p)
        factors = tuple([
            self.B,
        ] * n)
        self.BT = tensor(factors)
        self.tc = self.BT.tensor_constructor(factors)
        deg = -1
        fac = 2  # if p>2 else 1
        self.b = self.B.monomial(fac * deg)
        self.binv = self.B.monomial(-fac * deg)
        self.bt = tensor([
            self.b,
        ] * n)
        self.bti = tensor([
            self.binv,
        ] * n)
        self.P = SteenrodAlgebra(p, generic=True).P
        self.Q = PolynomialRing(
            GF(p),
            ["x%d" % (i + 1) for i in range(n)] + [
                "t",
            ],
        )

    def _repr_(self):
        return "Peterson element factory for prime %d, index %d" % (self.p,
                                                                    self.n)

    @cached_method
    def dicksons(self):
        """
        TESTS::

            sage: from yacop.modules.dickson import PetersonPolynomials
            sage: P=PetersonPolynomials(2,3)
            sage: for p in P.dicksons():
            ....:     print(p)
            x1^4*x2^2*x3 + x1^2*x2^4*x3 + x1^4*x2*x3^2 + x1*x2^4*x3^2 + x1^2*x2*x3^4 + x1*x2^2*x3^4
            x1^4*x2^2 + x1^2*x2^4 + x1^4*x2*x3 + x1*x2^4*x3 + x1^4*x3^2 + x1^2*x2^2*x3^2 + x2^4*x3^2 + x1^2*x3^4 + x1*x2*x3^4 + x2^2*x3^4
            x1^4 + x1^2*x2^2 + x2^4 + x1^2*x2*x3 + x1*x2^2*x3 + x1^2*x3^2 + x1*x2*x3^2 + x2^2*x3^2 + x3^4
            sage: P=PetersonPolynomials(5,2)
            sage: for p in P.dicksons():
            ....:     print(p)
            x1^20*x2^4 + x1^16*x2^8 + x1^12*x2^12 + x1^8*x2^16 + x1^4*x2^20
            x1^20 + x1^16*x2^4 + x1^12*x2^8 + x1^8*x2^12 + x1^4*x2^16 + x2^20

        """
        xi = self.Q.gens()[:-1]
        t = self.Q.gens()[self.n]
        pol = self.Q.prod(t + self.Q.sum(a * x for (a, x) in zip(cf, xi))
                          for cf in GF(self.p)**self.n)
        return [
            pol.coefficient(t**(self.p**i)) * (-1)**(self.n - i)
            for i in range(self.n)
        ]

    def is_invariant(self, qelem):
        """
        TESTS::

            sage: from yacop.modules.dickson import PetersonPolynomials
            sage: P=PetersonPolynomials(2,3)
            sage: [P.is_invariant(d) for d in P.dicksons()]
            [True, True, True]
            sage: [(n,P.is_invariant(P.omega(n))) for n in range(10)]
            [(0, True),
             (1, False),
             (2, False),
             (3, False),
             (4, True),
             (5, False),
             (6, True),
             (7, True),
             (8, True),
             (9, False)]

        """
        if self.n == 1:
            return True
        Q = self.Q
        x1, x2 = Q.gens()[0:2]
        # we already know the element is symmetric in the variables
        # so we only check invariance under x1 -> x1+x2
        return (qelem - qelem.subs({x1: x1 + x2})).is_zero()  #

    def toQ(self, x):
        return self.Q.sum(cf *
                          self.Q.prod(a**(e >> 1)
                                      for (a, e) in zip(self.Q.gens(), expo))
                          for (expo, cf) in x)

    def opelem(self, op):
        return self.toQ((op * self.bt) * self.bti)

    def opconjelem(self, op):
        return self.toQ((op % self.bt) * self.bti)

    @cached_method
    def omega(self, n):
        return self._omega_fast(n)

    def _omega_safe(self, n):
        return self.opelem(self.P(n).antipode())

    def _omega_exponents(self, sum, len):
        if len == 1:
            cf = self.gamma(sum)
            if cf:
                yield (
                    cf,
                    [
                        sum,
                    ],
                )
            return
        if len > 1:
            for smd in range(sum + 1):
                cf = self.gamma(smd)
                if cf:
                    for (c, x) in self._omega_exponents(sum - smd, len - 1):
                        yield (
                            cf * c,
                            [
                                smd,
                            ] + x,
                        )

    def _omega_fast(self, n):
        """
        TESTS::

            sage: from yacop.modules.dickson import PetersonPolynomials
            sage: P=PetersonPolynomials(5,3)
            sage: for n in range(25,31):
            ....:     assert P._omega_safe(n) == P._omega_fast(n)
            sage: P=PetersonPolynomials(2,4)
            sage: for n in range(10,13):
            ....:     assert P._omega_safe(n) == P._omega_fast(n)

        """
        from sage.combinat.integer_vector_weighted import WeightedIntegerVectors
        from sage.misc.misc_c import prod

        pmo = self.p - 1
        ans = []
        for (cf, expos) in self._omega_exponents(n, self.n):
            if 0 == cf % self.p:
                continue
            ans.append(cf *
                       self.Q.prod(a**(pmo * e)
                                   for (a, e) in zip(self.Q.gens(), expos)))
        return self.Q.sum(ans)

    @staticmethod
    def _milnor_basis(p, n):
        from sage.algebras.steenrod.steenrod_algebra_bases import milnor_basis

        if p == 2:
            for x in milnor_basis(n, 2):
                yield x
        else:
            for (x, y) in milnor_basis(n, p):
                if len(x) == 0:
                    yield y

    def gamma(self, n):
        """
        the gamma(n) in the definition of omega(n)
        """
        return binom_modp(self.p, -(self.p - 1) * n, n)

    @staticmethod
    def decompose(p, n):
        """
        Decompose a omega_n into a product of Dicksonians
        """

        inv = p**(p - 2)
        tdeg = 2 * (p - 1) if p > 2 else 1
        pmo = p - 1
        # FIXME: why does this not depend on the generic/non-generic flag for p=2?
        for expos in PetersonPolynomials._milnor_basis(p, tdeg * n):
            sum = 0
            cf = 1
            for a in expos:
                sum += a
                cf *= binom_modp(p, sum, a)
                if 0 == cf:
                    break
            if 0 == cf:
                continue
            cf *= binom_modp(p, -n * pmo, sum)
            if 0 != cf:
                yield [cf, expos]
Example #57
0
def count(arg,
          ehrhart_polynomial=False,
          multivariate_generating_function=False,
          raw_output=False,
          verbose=False,
          **kwds):
    r"""
    Call to the program count from LattE integrale

    INPUT:

    - ``arg`` -- a cdd or LattE description string

    - ``ehrhart_polynomial``, ``multivariate_generating_function``  -- to
      compute Ehrhart polynomial or multivariate generating function instead of
      just counting points

    - ``raw_output`` -- if ``True`` then return directly the output string from LattE

    - For all other options of the count program, consult the LattE manual

    OUTPUT:

    Either a string (if ``raw_output`` if set to ``True``) or an integer (when
    counting points), or a polynomial (if ``ehrhart_polynomial`` is set to
    ``True``) or a multivariate THING (if ``multivariate_generating_function``
    is set to ``True``)

    EXAMPLES::

        sage: from sage.interfaces.latte import count    # optional - latte_int
        sage: P = 2 * polytopes.cube()

    Counting integer points from either the H or V representation::

        sage: count(P.cdd_Hrepresentation(), cdd=True)   # optional - latte_int
        125
        sage: count(P.cdd_Vrepresentation(), cdd=True)   # optional - latte_int
        125

    Ehrhart polynomial::

        sage: count(P.cdd_Hrepresentation(), cdd=True, ehrhart_polynomial=True)  # optional - latte_int
        64*t^3 + 48*t^2 + 12*t + 1

    Multivariate generating function currently only work with ``raw_output=True``::

        sage: opts = {'cdd': True,
        ....:         'multivariate_generating_function': True,
        ....:         'raw_output': True}
        sage: cddin = P.cdd_Hrepresentation()
        sage: print(count(cddin, **opts))  # optional - latte_int
        x[0]^2*x[1]^(-2)*x[2]^(-2)/((1-x[1])*(1-x[2])*(1-x[0]^(-1)))
         + x[0]^(-2)*x[1]^(-2)*x[2]^(-2)/((1-x[1])*(1-x[2])*(1-x[0]))
         + x[0]^2*x[1]^(-2)*x[2]^2/((1-x[1])*(1-x[0]^(-1))*(1-x[2]^(-1)))
         + x[0]^(-2)*x[1]^(-2)*x[2]^2/((1-x[1])*(1-x[0])*(1-x[2]^(-1)))
         + x[0]^2*x[1]^2*x[2]^(-2)/((1-x[2])*(1-x[0]^(-1))*(1-x[1]^(-1)))
         + x[0]^(-2)*x[1]^2*x[2]^(-2)/((1-x[2])*(1-x[0])*(1-x[1]^(-1)))
         + x[0]^2*x[1]^2*x[2]^2/((1-x[0]^(-1))*(1-x[1]^(-1))*(1-x[2]^(-1)))
         + x[0]^(-2)*x[1]^2*x[2]^2/((1-x[0])*(1-x[1]^(-1))*(1-x[2]^(-1)))

    TESTS:

    Testing raw output::

        sage: from sage.interfaces.latte import count   # optional - latte_int
        sage: P = polytopes.cuboctahedron()
        sage: cddin = P.cdd_Vrepresentation()
        sage: count(cddin, cdd=True, raw_output=True)  # optional - latte_int
        '19'
        sage: count(cddin, cdd=True, raw_output=True, ehrhart_polynomial=True) # optional - latte_int
        ' + 1 * t^0 + 10/3 * t^1 + 8 * t^2 + 20/3 * t^3'
        sage: count(cddin, cdd=True, raw_output=True, multivariate_generating_function=True) # optional - latte_int
        'x[0]^(-1)*x[1]^(-1)/((1-x[0]*x[2])*(1-x[0]^(-1)*x[1])*...x[0]^(-1)*x[2]^(-1)))\n'

    Testing the ``verbose`` option::

        sage: n = count(cddin, cdd=True, verbose=True, raw_output=True)  # optional - latte_int
        This is LattE integrale ...
        ...
        Invocation: count '--redundancy-check=none' --cdd /dev/stdin
        ...
        Total Unimodular Cones: ...
        Maximum number of simplicial cones in memory at once: ...
        <BLANKLINE>
        ****  The number of lattice points is:   ****
        Total time: ... sec

    Trivial input for which LattE's preprocessor does all the work::

        sage: P = Polyhedron(vertices=[[0,0,0]])
        sage: cddin = P.cdd_Hrepresentation()
        sage: count(cddin, cdd=True, raw_output=False)  # optional - latte_int
        1

    """
    # Check that LattE is present
    Latte().require()

    args = ['count']
    if ehrhart_polynomial and multivariate_generating_function:
        raise ValueError
    if ehrhart_polynomial:
        args.append('--ehrhart-polynomial')
    elif multivariate_generating_function:
        args.append('--multivariate-generating-function')

    if 'redundancy_check' not in kwds:
        args.append('--redundancy-check=none')

    for key, value in kwds.items():
        if value is None or value is False:
            continue

        key = key.replace('_', '-')
        if value is True:
            args.append('--{}'.format(key))
        else:
            args.append('--{}={}'.format(key, value))

    if multivariate_generating_function:
        from sage.misc.temporary_file import tmp_filename
        filename = tmp_filename()
        with open(filename, 'w') as f:
            f.write(arg)
        args += [filename]
    else:
        args += ['/dev/stdin']

    # The cwd argument is needed because latte
    # always produces diagnostic output files.
    latte_proc = Popen(args,
                       stdin=PIPE,
                       stdout=PIPE,
                       stderr=(None if verbose else PIPE),
                       cwd=str(SAGE_TMP))

    ans, err = latte_proc.communicate(arg)
    ret_code = latte_proc.poll()
    if ret_code:
        if err is None:
            err = ", see error message above"
        else:
            err = ":\n" + err
        raise RuntimeError(
            "LattE integrale program failed (exit code {})".format(ret_code) +
            err.strip())

    if ehrhart_polynomial:
        ans = ans.splitlines()[-2]
        if raw_output:
            return ans
        else:
            from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
            from sage.rings.rational_field import QQ
            R = PolynomialRing(QQ, 't')
            return R(ans)
    elif multivariate_generating_function:
        with open(filename + '.rat') as f:
            ans = f.read()
        if raw_output:
            return ans
        else:
            raise NotImplementedError(
                "there is no Sage object to handle multivariate series from LattE, use raw_output=True"
            )
    else:
        if ans:  # Sometimes (when LattE's preproc does the work), no output appears on stdout.
            ans = ans.splitlines()[-1]
        if not ans:
            # opening a file is slow (30e-6s), so we read the file
            # numOfLatticePoints only in case of a IndexError above
            with open(SAGE_TMP + '/numOfLatticePoints', 'r') as f:
                ans = f.read()

        if raw_output:
            return ans
        else:
            return Integer(ans)
    def gcd(self, other, algorithm=None):
        """
        Return the gcd of this polynomial and ``other``

        INPUT:

        - ``other`` -- a polynomial defined over the same ring as this
          polynomial.

        ALGORITHM:

        Two algorithms are provided:

        - ``generic``: Uses the generic implementation, which depends on the
          base ring being a UFD or a field.
        - ``dense``: The polynomials are converted to the dense representation,
          their gcd is computed and is converted back to the sparse
          representation.

        Default is ``dense`` for polynomials over ZZ and ``generic`` in the
        other cases.

        EXAMPLES::

            sage: R.<x> = PolynomialRing(ZZ,sparse=True)
            sage: p = x^6 + 7*x^5 + 8*x^4 + 6*x^3 + 2*x^2 + x + 2
            sage: q = 2*x^4 - x^3 - 2*x^2 - 4*x - 1
            sage: gcd(p,q)
            x^2 + x + 1
            sage: gcd(p, q, algorithm = "dense")
            x^2 + x + 1
            sage: gcd(p, q, algorithm = "generic")
            x^2 + x + 1
            sage: gcd(p, q, algorithm = "foobar")
            Traceback (most recent call last):
            ...
            ValueError: Unknown algorithm 'foobar'

        TESTS:

        Check that :trac:`19676` is fixed::

            sage: S.<y> = R[]
            sage: x.gcd(y)
            1
            sage: (6*x).gcd(9)
            3
        """

        from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
        from sage.arith.all import lcm

        if algorithm is None:
            if self.base_ring() == ZZ:
                algorithm = "dense"
            else:
                algorithm = "generic"
        if algorithm == "dense":
            S = self.parent()
            # FLINT is faster but a bug makes the conversion extremely slow,
            # so NTL is used in those cases where the conversion is too slow. Cf
            # <https://groups.google.com/d/msg/sage-devel/6qhW90dgd1k/Hoq3N7fWe4QJ>
            sd = self.degree()
            od = other.degree()
            if max(sd,od)<100 or \
               min(len(self.__coeffs)/sd, len(other.__coeffs)/od)>.06:
                implementation = "FLINT"
            else:
                implementation = "NTL"
            D = PolynomialRing(S.base_ring(),
                               'x',
                               implementation=implementation)
            g = D(self).gcd(D(other))
            return S(g)
        elif algorithm == "generic":
            return Polynomial.gcd(self, other)
        else:
            raise ValueError("Unknown algorithm '%s'" % algorithm)
Example #59
0
class PseudoConwayLattice(WithEqualityById, SageObject):
    r"""
    A pseudo-Conway lattice over a given finite prime field.

    The Conway polynomial `f_n` of degree `n` over `\Bold{F}_p` is
    defined by the following four conditions:

    - `f_n` is irreducible.

    - In the quotient field `\Bold{F}_p[x]/(f_n)`, the element
      `x\bmod f_n` generates the multiplicative group.

    - The minimal polynomial of `(x\bmod f_n)^{\frac{p^n-1}{p^m-1}}`
      equals the Conway polynomial `f_m`, for every divisor `m` of
      `n`.

    - `f_n` is lexicographically least among all such polynomials,
      under a certain ordering.

    The final condition is needed only in order to make the Conway
    polynomial unique.  We define a pseudo-Conway lattice to be any
    family of polynomials, indexed by the positive integers,
    satisfying the first three conditions.

    INPUT:

    - ``p`` -- prime number

    - ``use_database`` -- boolean.  If ``True``, use actual Conway
      polynomials whenever they are available in the database.  If
      ``False``, always compute pseudo-Conway polynomials.

    EXAMPLES::

        sage: from sage.rings.finite_rings.conway_polynomials import PseudoConwayLattice
        sage: PCL = PseudoConwayLattice(2, use_database=False)
        sage: PCL.polynomial(3)
        x^3 + x + 1

    TESTS::

        sage: from sage.rings.finite_rings.conway_polynomials import PseudoConwayLattice
        sage: PCL = PseudoConwayLattice(3)
        sage: hash(PCL)  # random
        8738829832350

        sage: from sage.rings.finite_rings.conway_polynomials import PseudoConwayLattice
        sage: PseudoConwayLattice(3) == PseudoConwayLattice(3)
        False
        sage: PseudoConwayLattice(3) != PseudoConwayLattice(3)
        True
        sage: P = PseudoConwayLattice(5)
        sage: P == P
        True
        sage: P != P
        False
    """
    def __init__(self, p, use_database=True):
        """
        TESTS::

            sage: from sage.rings.finite_rings.conway_polynomials import PseudoConwayLattice
            sage: PCL = PseudoConwayLattice(3)
            sage: PCL.polynomial(3)
            x^3 + 2*x + 1

            sage: PCL = PseudoConwayLattice(5, use_database=False)
            sage: PCL.polynomial(12)
            x^12 + 4*x^11 + 2*x^10 + 4*x^9 + 2*x^8 + 2*x^7 + 4*x^6 + x^5 + 2*x^4 + 2*x^2 + x + 2
            sage: PCL.polynomial(6)
            x^6 + x^5 + 4*x^4 + 3*x^3 + 3*x^2 + 2*x + 2
            sage: PCL.polynomial(11)
            x^11 + x^6 + 3*x^3 + 4*x + 3
        """
        self.p = p
        from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
        self.ring = PolynomialRing(FiniteField(p), 'x')
        if use_database:
            C = sage.databases.conway.ConwayPolynomials()
            self.nodes = {
                n: self.ring(C.polynomial(p, n))
                for n in C.degrees(p)
            }
        else:
            self.nodes = {}

    def polynomial(self, n):
        r"""
        Return the pseudo-Conway polynomial of degree `n` in this
        lattice.

        INPUT:

        - ``n`` -- positive integer

        OUTPUT:

        - a pseudo-Conway polynomial of degree `n` for the prime `p`.

        ALGORITHM:

        Uses an algorithm described in [HL1999]_, modified to find
        pseudo-Conway polynomials rather than Conway polynomials.  The
        major difference is that we stop as soon as we find a
        primitive polynomial.

        EXAMPLES::

            sage: from sage.rings.finite_rings.conway_polynomials import PseudoConwayLattice
            sage: PCL = PseudoConwayLattice(2, use_database=False)
            sage: PCL.polynomial(3)
            x^3 + x + 1
            sage: PCL.polynomial(4)
            x^4 + x^3 + 1
            sage: PCL.polynomial(60)
            x^60 + x^59 + x^58 + x^55 + x^54 + x^53 + x^52 + x^51 + x^48 + x^46 + x^45 + x^42 + x^41 + x^39 + x^38 + x^37 + x^35 + x^32 + x^31 + x^30 + x^28 + x^24 + x^22 + x^21 + x^18 + x^17 + x^16 + x^15 + x^14 + x^10 + x^8 + x^7 + x^5 + x^3 + x^2 + x + 1
        """
        if n in self.nodes:
            return self.nodes[n]

        p = self.p
        n = Integer(n)

        if n == 1:
            f = self.ring.gen() - FiniteField(p).multiplicative_generator()
            self.nodes[1] = f
            return f

        # Work in an arbitrary field K of order p**n.
        K = FiniteField(p**n, names='a')

        # TODO: something like the following
        # gcds = [n.gcd(d) for d in self.nodes.keys()]
        # xi = { m: (...) for m in gcds }
        xi = {
            q: self.polynomial(n // q).any_root(K,
                                                -n // q,
                                                assume_squarefree=True)
            for q in n.prime_divisors()
        }

        # The following is needed to ensure that in the concrete instantiation
        # of the "new" extension all previous choices are compatible.
        _frobenius_shift(K, xi)

        # Construct a compatible element having order the lcm of orders
        q, x = xi.popitem()
        v = p**(n // q) - 1
        for q, xitem in xi.items():
            w = p**(n // q) - 1
            g, alpha, beta = v.xgcd(w)
            x = x**beta * xitem**alpha
            v = v.lcm(w)

        r = p**n - 1
        # Get the missing part of the order to be primitive
        g = r // v
        # Iterate through g-th roots of x until a primitive one is found
        z = x.nth_root(g)
        root = K.multiplicative_generator()**v
        while z.multiplicative_order() != r:
            z *= root
        # The following should work but tries to create a huge list
        # whose length overflows Python's ints for large parameters
        #Z = x.nth_root(g, all=True)
        #for z in Z:
        #    if z.multiplicative_order() == r:
        #         break
        f = z.minimal_polynomial()
        self.nodes[n] = f
        return f

    def check_consistency(self, n):
        """
        Check that the pseudo-Conway polynomials of degree dividing
        `n` in this lattice satisfy the required compatibility
        conditions.

        EXAMPLES::

            sage: from sage.rings.finite_rings.conway_polynomials import PseudoConwayLattice
            sage: PCL = PseudoConwayLattice(2, use_database=False)
            sage: PCL.check_consistency(6)
            sage: PCL.check_consistency(60)  # long time
        """
        p = self.p
        K = FiniteField(p**n, modulus=self.polynomial(n), names='a')
        a = K.gen()
        for m in n.divisors():
            assert (a**((p**n - 1) //
                        (p**m - 1))).minimal_polynomial() == self.polynomial(m)
Example #60
0
    def local_coordinates(self, pt, n):
        r"""
        Return local coordinates to precision n at the given point.

            Behaviour is flaky - some choices of `n` are worst that
            others.

        INPUT:

        -  ``pt`` - an F-rational point on X which is not a
           point of ramification for the projection (x,y) - x.

        -  ``n`` - the number of terms desired

        OUTPUT: x = x0 + t y = y0 + power series in t

        EXAMPLES::

            sage: F = GF(5)
            sage: pt = (2,3)
            sage: R = PolynomialRing(F,2, names = ['x','y'])
            sage: x,y = R.gens()
            sage: f = y^2-x^9-x
            sage: C = Curve(f)
            sage: C.local_coordinates(pt, 9)
            [t + 2, -2*t^12 - 2*t^11 + 2*t^9 + t^8 - 2*t^7 - 2*t^6 - 2*t^4 + t^3 - 2*t^2 - 2]
        """
        f = self.defining_polynomial()
        R = f.parent()
        F = self.base_ring()
        p = F.characteristic()
        x0 = F(pt[0])
        y0 = F(pt[1])
        astr = ["a" + str(i) for i in range(1, 2 * n)]
        x, y = R.gens()
        R0 = PolynomialRing(F, 2 * n + 2, names=[str(x), str(y), "t"] + astr)
        vars0 = R0.gens()
        t = vars0[2]
        yt = y0 * t**0 + add(
            [vars0[i] * t**(i - 2) for i in range(3, 2 * n + 2)])
        xt = x0 + t
        ft = f(xt, yt)
        S = singular
        S.eval('ring s = ' + str(p) + ',' + str(R0.gens()) + ',lp;')
        S.eval('poly f = ' + str(ft) + ';')
        c = S('coeffs(%s, t)' % ft)
        N = int(c.size())
        b = ["%s[%s,1]," % (c.name(), i) for i in range(2, N / 2 - 4)]
        b = ''.join(b)
        b = b[:len(b) - 1]  # to cut off the trailing comma
        cmd = 'ideal I = ' + b
        S.eval(cmd)
        S.eval('short=0')  # print using *'s and ^'s.
        c = S.eval('slimgb(I)')
        d = c.split("=")
        d = d[1:]
        d[len(d) - 1] += "\n"
        e = [x[:x.index("\n")] for x in d]
        vals = []
        for x in e:
            for y in vars0:
                if str(y) in x:
                    if len(x.replace(str(y), "")) != 0:
                        i = x.find("-")
                        if i > 0:
                            vals.append(
                                [eval(x[1:i]), x[:i],
                                 F(eval(x[i + 1:]))])
                        i = x.find("+")
                        if i > 0:
                            vals.append(
                                [eval(x[1:i]), x[:i], -F(eval(x[i + 1:]))])
                    else:
                        vals.append([eval(str(y)[1:]), str(y), F(0)])
        vals.sort()
        k = len(vals)
        v = [x0 + t, y0 + add([vals[i][2] * t**(i + 1) for i in range(k)])]
        return v