Ticket #8800: 8800_functor_pushout_doc_and_fixes.patch

File 8800_functor_pushout_doc_and_fixes.patch, 157.2 KB (added by SimonKing, 10 years ago)

Full doctest coverage for sage.categories.functor and sage.categories.pushout. Various coercion bug fixes.

  • doc/en/reference/categories.rst

    # HG changeset patch
    # User Simon King <simon.king@nuigalway.ie>
    # Date 1279718741 -3600
    # Node ID 1a7c8feb901dd09ff8ee1d2fd34135c3e72665ad
    # Parent  b4e473888eb985231e9429a532c937ce0040b073
    #8800: Full doc test coverage of sage/categories/functor and sage/categories/pushout; fixing a multitude of bugs related with coercion. Putting it into the reference manual.
    
    diff -r b4e473888eb9 -r 1a7c8feb901d doc/en/reference/categories.rst
    a b  
    1313   sage/categories/homset
    1414   sage/categories/morphism
    1515   sage/categories/functor
     16   sage/categories/pushout
    1617
    1718Functorial constructions
    1819========================
  • doc/en/reference/coercion.rst

    diff -r b4e473888eb9 -r 1a7c8feb901d doc/en/reference/coercion.rst
    a b  
    586586    sage: CC.construction()
    587587    (AlgebraicClosureFunctor, Real Field with 53 bits of precision)
    588588    sage: RR.construction()
    589     (CompletionFunctor, Rational Field)
     589    (Completion[+Infinity], Rational Field)
    590590    sage: QQ.construction()
    591591    (FractionField, Integer Ring)
    592592    sage: ZZ.construction()  # None
    593593   
    594594    sage: Qp(5).construction()
    595     (CompletionFunctor, Rational Field)
    596     sage: QQ.completion(5, 100)
     595    (Completion[5], Rational Field)
     596    sage: QQ.completion(5, 100, {})
    597597    5-adic Field with capped relative precision 100
    598598    sage: c, R = RR.construction()
    599599    sage: a = CC.construction()[0]
     
    608608    (FractionField, Univariate Polynomial Ring in x over Complex Double Field),
    609609    (Poly[x], Complex Double Field),
    610610    (AlgebraicClosureFunctor, Real Double Field),
    611     (CompletionFunctor, Rational Field),
     611    (Completion[+Infinity], Rational Field),
    612612    (FractionField, Integer Ring)]
    613613
    614614Given Parents R and S, such that there is no coercion either from R to
  • sage/categories/functor.pyx

    diff -r b4e473888eb9 -r 1a7c8feb901d sage/categories/functor.pyx
    a b  
    99
    1010- Robert Bradshaw (2007-06-23): Pyrexify
    1111
    12 - Simon King (2010-04-30): more examples, several bug fixes, re-implementation of the default call method,
     12- Simon King (2010-04-30): more examples, several bug fixes,
     13  re-implementation of the default call method,
    1314  making functors applicable to morphisms (not only to objects)
    1415
    1516"""
     
    4445      Instead, one should implement three methods, which are composed in the
    4546      default call method:
    4647
    47       - ``_coerce_into_domain(self, x)``: Return an object of ``self``'s domain,
    48         corresponding to ``x``, or raise a ``TypeError``.
     48      - ``_coerce_into_domain(self, x)``: Return an object of ``self``'s
     49        domain, corresponding to ``x``, or raise a ``TypeError``.
    4950
    5051        - Default: Raise ``TypeError`` if ``x`` is not in ``self``'s domain.
    5152       
    52       - ``_apply_functor(self, x)``: Apply ``self`` to an object ``x`` of ``self``'s domain.
     53      - ``_apply_functor(self, x)``: Apply ``self`` to an object ``x`` of
     54        ``self``'s domain.
    5355
    5456        - Default: Conversion into ``self``'s codomain.
    5557
    56       - ``_apply_functor_to_morphism(self, f)``: Apply ``self`` to a morphism ``f`` in ``self``'s domain.
     58      - ``_apply_functor_to_morphism(self, f)``: Apply ``self`` to a morphism
     59        ``f`` in ``self``'s domain.
    5760        - Default: Return ``self(f.domain()).hom(f,self(f.codomain()))``.
    5861
    5962    EXAMPLES::
     
    7679        sage: is_Functor(I)
    7780        True
    7881
    79     Note that by default, an instance of the class Functor is coercion from the
    80     domain into the codomain. The above subclasses overloaded this behaviour. Here
    81     we illustrate the default::
     82    Note that by default, an instance of the class Functor is coercion
     83    from the domain into the codomain. The above subclasses overloaded
     84    this behaviour. Here we illustrate the default::
    8285
    8386        sage: from sage.categories.functor import Functor
    8487        sage: F = Functor(Rings(),Fields())
     
    8992        sage: F(GF(2))
    9093        Finite Field of size 2
    9194
    92     Functors are not only about the objects of a category, but also about their
    93     morphisms. We illustrate it, again, with the coercion functor from rings
    94     to fields.
     95    Functors are not only about the objects of a category, but also about
     96    their morphisms. We illustrate it, again, with the coercion functor
     97    from rings to fields.
    9598
    9699    ::
    97100
     
    108111          From: Fraction Field of Univariate Polynomial Ring in x over Integer Ring
    109112          To:   Fraction Field of Multivariate Polynomial Ring in a, b over Rational Field
    110113          Defn: x |--> a + b
     114        sage: F(f)(1/x)
     115        1/(a + b)
     116
     117    We can also apply a polynomial ring construction functor to our homomorphism. The
     118    result is a homomorphism that is defined on the base ring::
     119
     120        sage: F = QQ['t'].construction()[0]
     121        sage: F
     122        Poly[t]
     123        sage: F(f)
     124        Ring morphism:
     125          From: Univariate Polynomial Ring in t over Univariate Polynomial Ring in x over Integer Ring
     126          To:   Univariate Polynomial Ring in t over Multivariate Polynomial Ring in a, b over Rational Field
     127          Defn: Induced from base ring by
     128                Ring morphism:
     129                  From: Univariate Polynomial Ring in x over Integer Ring
     130                  To:   Multivariate Polynomial Ring in a, b over Rational Field
     131                  Defn: x |--> a + b
     132        sage: p = R1['t']('(-x^2 + x)*t^2 + (x^2 - x)*t - 4*x^2 - x + 1')
     133        sage: F(f)(p)
     134        (-a^2 - 2*a*b - b^2 + a + b)*t^2 + (a^2 + 2*a*b + b^2 - a - b)*t - 4*a^2 - 8*a*b - 4*b^2 - a - b + 1
    111135
    112136    """
    113137    def __init__(self, domain, codomain):
     
    133157       
    134158    def _apply_functor(self, x):
    135159        """
    136         Apply the functor to an object of ``self``'s domain
     160        Apply the functor to an object of ``self``'s domain.
    137161
    138162        NOTE:
    139163
     
    153177
    154178    def _apply_functor_to_morphism(self, f):
    155179        """
    156         Apply the functor to a morphism between two objects of ``self``'s domain
     180        Apply the functor to a morphism between two objects of ``self``'s domain.
    157181
    158182        NOTE:
    159183
    160         Each subclass of :class:`Functor` should overload this method. By default,
    161         this method coerces into the codomain, without checking whether the
    162         argument belongs to the domain.
     184        Each subclass of :class:`Functor` should overload this method. By
     185        default, this method coerces into the codomain, without checking
     186        whether the argument belongs to the domain.
    163187
    164188        TESTS::
    165189
     
    169193            sage: f = k.hom([-a-4])
    170194            sage: R.<t> = k[]
    171195            sage: fR = R.hom(f,R)
    172             sage: fF = F(fR); fF
     196            sage: fF = F(fR)         # indirect doctest
     197            sage: fF
    173198            Ring endomorphism of Fraction Field of Univariate Polynomial Ring in t over Finite Field in a of size 5^2
    174199              Defn: Induced from base ring by
    175200                    Ring endomorphism of Univariate Polynomial Ring in t over Finite Field in a of size 5^2
     
    187212
    188213    def _coerce_into_domain(self, x):
    189214        """
    190         Interprete the argument as an object of self's domain
     215        Interprete the argument as an object of self's domain.
    191216
    192217        NOTE:
    193218
    194         Each subclass of :class:`Functor` should overload this method. It should return
    195         an object of self's domain, and should raise a ``TypeError`` if this is impossible.
     219        A subclass of :class:`Functor` may overload this method. It should
     220        return an object of self's domain, and should raise a ``TypeError``
     221        if this is impossible.
    196222
    197         By default, the argument will not be changed, but a ``TypeError`` will be raised if
    198         the argument does not belong to the domain.
     223        By default, the argument will not be changed, but a ``TypeError``
     224        will be raised if the argument does not belong to the domain.
    199225
    200226        TEST::
    201227
     
    208234            ...
    209235            TypeError: x (=Integer Ring) is not in Category of fields
    210236
    211        
    212237        """
    213238        if not (x in  self.__domain):
    214239            raise TypeError, "x (=%s) is not in %s"%(x, self.__domain)
     
    229254        """
    230255        NOTE:
    231256
    232         Implement _coerce_into_domain and _apply_functor when subclassing Functor.
     257        Implement _coerce_into_domain, _apply_functor and
     258        _apply_functor_to_morphism when subclassing Functor.
    233259       
    234260        TESTS:
    235261 
     
    397423        """
    398424        NOTE:
    399425
    400         It is tested whether the second argument belongs to the class of forgetful functors
    401         and has the same domain and codomain as self. If the second argument is a functor
    402         of a different class but happens to be a forgetful functor, both arguments will
     426        It is tested whether the second argument belongs to the class
     427        of forgetful functors and has the same domain and codomain as
     428        self. If the second argument is a functor of a different class
     429        but happens to be a forgetful functor, both arguments will
    403430        still be considered as being *different*.
    404431
    405432        TEST::
    406433
    407434            sage: F1 = ForgetfulFunctor(FiniteFields(),Fields())
    408435
    409         This is to test against a bug occuring in a previous version (see ticket 8800)::
     436        This is to test against a bug occuring in a previous version
     437        (see ticket 8800)::
    410438
    411439            sage: F1 == QQ #indirect doctest
    412440            False
    413441
    414         We now compare with the fraction field functor, that has a different domain:
     442        We now compare with the fraction field functor, that has a
     443        different domain::
    415444       
    416445            sage: F2 = QQ.construction()[0]
    417446            sage: F1 == F2 #indirect doctest
    418447            False
    419448
    420449        """
    421         if not isinstance(other, self.__class__):
     450        from sage.categories.pushout import IdentityConstructionFunctor
     451        if not isinstance(other, (self.__class__,IdentityConstructionFunctor)):
    422452            return -1
    423453        if self.domain() == other.domain() and \
    424454           self.codomain() == other.codomain():
     
    445475        ...
    446476        TypeError: x (=Integer Ring) is not in Category of fields
    447477
     478    TESTS::
     479
     480        sage: R = IdentityFunctor(Rings())
     481        sage: P, _ = QQ['t'].construction()
     482        sage: R == P
     483        False
     484        sage: P == R
     485        False
     486        sage: R == QQ
     487        False
    448488    """
    449489    def __init__(self, C):
    450490        """
     
    485525   
    486526    def _apply_functor(self, x):
    487527        """
     528        Apply the functor to an object of ``self``'s domain.
     529       
    488530        TESTS::
    489531
    490532            sage: fields = Fields()
     
    533575
    534576    OUTPUT:
    535577
    536     A functor that returns the corresponding object of ``D`` for any element of ``C``,
    537     by forgetting the extra structure.
     578    A functor that returns the corresponding object of ``D`` for
     579    any element of ``C``, by forgetting the extra structure.
    538580
    539581    ASSUMPTION:
    540582
     
    567609    if not domain.is_subcategory(codomain):
    568610        raise ValueError, "Forgetful functor not supported for domain %s"%domain
    569611    return ForgetfulFunctor_generic(domain, codomain)
    570    
    571612
  • sage/categories/pushout.py

    diff -r b4e473888eb9 -r 1a7c8feb901d sage/categories/pushout.py
    a b  
    1 from functor import Functor
     1"""
     2Coercion via Construction Functors.
     3"""
     4from functor import Functor, IdentityFunctor_generic
    25from basic import *
    36
    47from sage.structure.parent import CoercionException
     
    69# TODO, think through the rankings, and override pushout where necessary.
    710
    811class ConstructionFunctor(Functor):
    9 
     12    """
     13    Base class for construction functors.
     14
     15    A construction functor is a functorial algebraic construction,
     16    such as the construction of a matrix ring over a given ring
     17    or the fraction field of a given ring.
     18
     19    In addition to the class :class:`~sage.categories.functor.Functor`,
     20    construction functors provide rules for combining and merging
     21    constructions. This is an important part of Sage's coercion model,
     22    namely the pushout of two constructions: When a polynomial ``p`` in
     23    a variable ``x`` with integer coefficients is added to a rational
     24    number ``q``, then Sage finds that the parents ``ZZ['x']`` and
     25    ``QQ`` are obtained from ``ZZ`` by applying a polynomial ring
     26    construction respectively the fraction field construction. Each
     27    construction functor has an attribute ``rank``, and the rank of
     28    the polynomial ring construction is higher than the rank of the
     29    fraction field construction. This means that the pushout of ``QQ``
     30    and ``ZZ['x']``, and thus a common parent in which ``p`` and ``q``
     31    can be added, is ``QQ['x']``, since the construction functor with
     32    a lower rank is applied first.
     33
     34    ::
     35
     36        sage: F1, R = QQ.construction()
     37        sage: F1
     38        FractionField
     39        sage: R
     40        Integer Ring
     41        sage: F2, R = (ZZ['x']).construction()
     42        sage: F2
     43        Poly[x]
     44        sage: R
     45        Integer Ring
     46        sage: F3 = F2.pushout(F1)
     47        sage: F3
     48        Poly[x](FractionField(...))
     49        sage: F3(R)
     50        Univariate Polynomial Ring in x over Rational Field
     51        sage: from sage.categories.pushout import pushout
     52        sage: P.<x> = ZZ[]
     53        sage: pushout(QQ,P)
     54        Univariate Polynomial Ring in x over Rational Field
     55        sage: ((x+1) + 1/2).parent()
     56        Univariate Polynomial Ring in x over Rational Field
     57
     58    When composing two construction functors, they are sometimes
     59    merged into one, as is the case in the Quotient construction::
     60
     61        sage: Q15, R = (ZZ.quo(15*ZZ)).construction()
     62        sage: Q15
     63        QuotientFunctor
     64        sage: Q35, R = (ZZ.quo(35*ZZ)).construction()
     65        sage: Q35
     66        QuotientFunctor
     67        sage: Q15.merge(Q35)
     68        QuotientFunctor
     69        sage: Q15.merge(Q35)(ZZ)
     70        Ring of integers modulo 5
     71
     72    Functors can not only be applied to objects, but also to morphisms in the
     73    respective categories. For example::
     74
     75        sage: P.<x,y> = ZZ[]
     76        sage: F = P.construction()[0]; F
     77        MPoly[x,y]
     78        sage: A.<a,b> = GF(5)[]
     79        sage: f = A.hom([a+b,a-b],A)
     80        sage: F(A)
     81        Multivariate Polynomial Ring in x, y over Multivariate Polynomial Ring in a, b over Finite Field of size 5
     82        sage: F(f)
     83        Ring endomorphism of Multivariate Polynomial Ring in x, y over Multivariate Polynomial Ring in a, b over Finite Field of size 5
     84          Defn: Induced from base ring by
     85                Ring endomorphism of Multivariate Polynomial Ring in a, b over Finite Field of size 5
     86                  Defn: a |--> a + b
     87                        b |--> a - b
     88        sage: F(f)(F(A)(x)*a)
     89        (a + b)*x
     90
     91    """
    1092    def __mul__(self, other):
     93        """
     94        Compose construction functors to a composit construction functor, unless one of them is the identity.
     95
     96        NOTE:
     97
     98        The product is in functorial notation, i.e., when applying the product to an object
     99        then the second factor is applied first.
     100
     101        TESTS::
     102
     103            sage: from sage.categories.pushout import IdentityConstructionFunctor
     104            sage: I = IdentityConstructionFunctor()
     105            sage: F = QQ.construction()[0]
     106            sage: P = ZZ['t'].construction()[0]
     107            sage: F*P
     108            FractionField(Poly[t](...))
     109            sage: P*F
     110            Poly[t](FractionField(...))
     111            sage: (F*P)(ZZ)
     112            Fraction Field of Univariate Polynomial Ring in t over Integer Ring
     113            sage: I*P is P
     114            True
     115            sage: F*I is F
     116            True
     117
     118        """
    11119        if not isinstance(self, ConstructionFunctor) and not isinstance(other, ConstructionFunctor):
    12120            raise CoercionException, "Non-constructive product"
     121        if isinstance(other,IdentityConstructionFunctor):
     122            return self
     123        if isinstance(self,IdentityConstructionFunctor):
     124            return other
    13125        return CompositeConstructionFunctor(other, self)
    14126       
    15127    def pushout(self, other):
     128        """
     129        Composition of two construction functors, ordered by their ranks.
     130
     131        NOTE:
     132       
     133        - This method seems not to be used in the coercion model.
     134
     135        - By default, the functor with smaller rank is applied first.
     136
     137        TESTS::
     138
     139            sage: F = QQ.construction()[0]
     140            sage: P = ZZ['t'].construction()[0]
     141            sage: F.pushout(P)
     142            Poly[t](FractionField(...))
     143            sage: P.pushout(F)
     144            Poly[t](FractionField(...))
     145
     146        """
    16147        if self.rank > other.rank:
    17148            return self * other
    18149        else:
     
    20151           
    21152    def __cmp__(self, other):
    22153        """
    23         Equality here means that they are mathematically equivalent, though they may have specific implementation data.
    24         See the \code{merge} function.
     154        Equality here means that they are mathematically equivalent, though they may have
     155        specific implementation data. This method will usually be overloaded in subclasses.
     156        by default, only the types of the functors are compared. Also see the \code{merge}
     157        function.
     158
     159        TESTS::
     160
     161            sage: from sage.categories.pushout import IdentityConstructionFunctor
     162            sage: I = IdentityConstructionFunctor()
     163            sage: F = QQ.construction()[0]
     164            sage: P = ZZ['t'].construction()[0]
     165            sage: I == F        # indirect doctest
     166            False
     167            sage: I == I        # indirect doctest
     168            True
     169
    25170        """
    26171        return cmp(type(self), type(other))
    27172       
    28173    def __str__(self):
     174        """
     175        NOTE:
     176
     177        By default, it returns the name of the construction functor's class.
     178        Usually, this method will be overloaded.
     179
     180        TEST::
     181
     182            sage: F = QQ.construction()[0]
     183            sage: F                  # indirect doctest
     184            FractionField
     185            sage: Q = ZZ.quo(2).construction()[0]
     186            sage: Q                  # indirect doctest
     187            QuotientFunctor
     188
     189        """
    29190        s = str(type(self))
    30191        import re
    31192        return re.sub("<.*'.*\.([^.]*)'>", "\\1", s)
    32193       
    33194    def __repr__(self):
     195        """
     196        NOTE:
     197
     198        By default, it returns the name of the construction functor's class.
     199        Usually, this method will be overloaded.
     200
     201        TEST::
     202
     203            sage: F = QQ.construction()[0]
     204            sage: F                  # indirect doctest
     205            FractionField
     206            sage: Q = ZZ.quo(2).construction()[0]
     207            sage: Q                  # indirect doctest
     208            QuotientFunctor
     209
     210        """
    34211        return str(self)
    35212       
    36213    def merge(self, other):
     214        """
     215        Merge ``self`` with another construction functor, or return None.
     216
     217        NOTE:
     218
     219        The default is to merge only if the two functors coincide. But this
     220        may be overloaded for subclasses, such as the quotient functor.
     221
     222        EXAMPLES::
     223
     224            sage: F = QQ.construction()[0]
     225            sage: P = ZZ['t'].construction()[0]
     226            sage: F.merge(F)
     227            FractionField
     228            sage: F.merge(P)
     229            sage: P.merge(F)
     230            sage: P.merge(P)
     231            Poly[t]
     232
     233        """
    37234        if self == other:
    38235            return self
    39236        else:
    40237            return None
    41238           
    42239    def commutes(self, other):
     240        """
     241        Determine whether ``self`` commutes with another construction functor.
     242
     243        NOTE:
     244
     245        By default, ``False`` is returned in all cases (even if the two
     246        functors are the same, since in this case :meth:`merge` will apply
     247        anyway). So far there is no construction functor that overloads
     248        this method. Anyway, this method only becomes relevant if two
     249        construction functors have the same rank.
     250
     251        EXAMPLES::
     252
     253            sage: F = QQ.construction()[0]
     254            sage: P = ZZ['t'].construction()[0]
     255            sage: F.commutes(P)
     256            False
     257            sage: P.commutes(F)
     258            False
     259            sage: F.commutes(F)
     260            False
     261       
     262        """
    43263        return False
    44264
    45265    def expand(self):
     266        """
     267        Decompose ``self`` into a list of construction functors.
     268
     269        NOTE:
     270
     271        The default is to return the list only containing ``self``.
     272
     273        EXAMPLE::
     274
     275            sage: F = QQ.construction()[0]
     276            sage: F.expand()
     277            [FractionField]
     278            sage: Q = ZZ.quo(2).construction()[0]
     279            sage: Q.expand()
     280            [QuotientFunctor]
     281            sage: P = ZZ['t'].construction()[0]
     282            sage: FP = F*P
     283            sage: FP.expand()
     284            [FractionField, Poly[t]]
     285
     286        """
    46287        return [self]
    47288
    48289       
    49290class CompositeConstructionFunctor(ConstructionFunctor):
    50291    """
    51     A Construction Functor composed by other Construction Functors
     292    A Construction Functor composed by other Construction Functors.
    52293
    53294    INPUT:
    54295
    55     ``F1,F2,...``: A list of Construction Functors. The result is the
     296    ``F1, F2,...``: A list of Construction Functors. The result is the
    56297    composition ``F1`` followed by ``F2`` followed by ...
    57298
    58299    EXAMPLES::
     
    61302        sage: F = CompositeConstructionFunctor(QQ.construction()[0],ZZ['x'].construction()[0],QQ.construction()[0],ZZ['y'].construction()[0])
    62303        sage: F
    63304        Poly[y](FractionField(Poly[x](FractionField(...))))
     305        sage: F == loads(dumps(F))
     306        True
    64307        sage: F == CompositeConstructionFunctor(*F.all)
    65308        True
    66309        sage: F(GF(2)['t'])
     
    92335
    93336    def _apply_functor_to_morphism(self, f):
    94337        """
     338        Apply the functor to an object of ``self``'s domain.
     339       
    95340        TESTS::
    96341
    97342            sage: from sage.categories.pushout import CompositeConstructionFunctor
    98343            sage: F = CompositeConstructionFunctor(QQ.construction()[0],ZZ['x'].construction()[0],QQ.construction()[0],ZZ['y'].construction()[0])
    99344            sage: R.<a,b> = QQ[]
    100345            sage: f = R.hom([a+b, a-b])
    101             sage: F(f) # indirect doctest
     346            sage: F(f)           # indirect doctest
    102347            Ring endomorphism of Univariate Polynomial Ring in y over Fraction Field of Univariate Polynomial Ring in x over Fraction Field of Multivariate Polynomial Ring in a, b over Rational Field
    103348              Defn: Induced from base ring by
    104349                    Ring endomorphism of Fraction Field of Univariate Polynomial Ring in x over Fraction Field of Multivariate Polynomial Ring in a, b over Rational Field
     
    116361
    117362    def _apply_functor(self, R):
    118363        """
     364        Apply the functor to an object of ``self``'s domain.
     365       
    119366        TESTS::
    120367       
    121368            sage: from sage.categories.pushout import CompositeConstructionFunctor
    122369            sage: F = CompositeConstructionFunctor(QQ.construction()[0],ZZ['x'].construction()[0],QQ.construction()[0],ZZ['y'].construction()[0])
    123370            sage: R.<a,b> = QQ[]
    124             sage: F(R) # indirect doctest
     371            sage: F(R)       # indirect doctest
    125372            Univariate Polynomial Ring in y over Fraction Field of Univariate Polynomial Ring in x over Fraction Field of Multivariate Polynomial Ring in a, b over Rational Field
    126373
    127374        """
     
    146393           
    147394    def __mul__(self, other):
    148395        """
    149         Convention: ``(F1*F2)(X) == F1(F2(X))``.
     396        Compose construction functors to a composit construction functor, unless one of them is the identity.
     397
     398        NOTE:
     399
     400        The product is in functorial notation, i.e., when applying the product to an object
     401        then the second factor is applied first.
    150402
    151403        EXAMPLES::
    152404
     
    159411        """
    160412        if isinstance(self, CompositeConstructionFunctor):
    161413            all = [other] + self.all
     414        elif isinstance(other,IdentityConstructionFunctor):
     415            return self
    162416        else:
    163417            all = other.all + [self]
    164418        return CompositeConstructionFunctor(*all)
     
    201455
    202456       
    203457class IdentityConstructionFunctor(ConstructionFunctor):
    204 
     458    """
     459    A construction functor that is the identity functor.
     460
     461    TESTS::
     462
     463        sage: from sage.categories.pushout import IdentityConstructionFunctor
     464        sage: I = IdentityConstructionFunctor()
     465        sage: I(RR) is RR
     466        True
     467        sage: I == loads(dumps(I))
     468        True
     469
     470    """
    205471    rank = -100
    206472
    207473    def __init__(self):
    208         Functor.__init__(self, Sets(), Sets())
    209     def _apply_functor(self, R):
    210         return R
     474        """
     475        TESTS::
     476
     477            sage: from sage.categories.pushout import IdentityConstructionFunctor
     478            sage: I = IdentityConstructionFunctor()
     479            sage: IdentityFunctor(Sets()) == I
     480            True
     481            sage: I(RR) is RR
     482            True
     483
     484        """
     485        ConstructionFunctor.__init__(self, Sets(), Sets())
     486
     487    def _apply_functor(self, x):
     488        """
     489        Return the argument unaltered.
     490       
     491        TESTS::
     492
     493            sage: from sage.categories.pushout import IdentityConstructionFunctor
     494            sage: I = IdentityConstructionFunctor()
     495            sage: I(RR) is RR      # indirect doctest
     496            True
     497        """
     498        return x
     499
     500    def _apply_functor_to_morphism(self, f):
     501        """
     502        Return the argument unaltered.
     503       
     504        TESTS::
     505
     506            sage: from sage.categories.pushout import IdentityConstructionFunctor
     507            sage: I = IdentityConstructionFunctor()
     508            sage: f = ZZ['t'].hom(['x'],QQ['x'])
     509            sage: I(f) is f      # indirect doctest
     510            True
     511        """
     512        return f
     513
     514    def __cmp__(self, other):
     515        """
     516        TESTS::
     517       
     518            sage: from sage.categories.pushout import IdentityConstructionFunctor
     519            sage: I = IdentityConstructionFunctor()
     520            sage: I == IdentityFunctor(Sets())     # indirect doctest
     521            True
     522            sage: I == QQ.construction()[0]
     523            False
     524
     525        """
     526        c = cmp(type(self),type(other))
     527        if c:
     528            from sage.categories.functor import IdentityFunctor_generic
     529            if isinstance(other,IdentityFunctor_generic):
     530               return 0
     531        return c
     532
    211533    def __mul__(self, other):
     534        """
     535        Compose construction functors to a composit construction functor, unless one of them is the identity.
     536
     537        NOTE:
     538
     539        The product is in functorial notation, i.e., when applying the product to an object
     540        then the second factor is applied first.
     541
     542        TESTS::
     543
     544            sage: from sage.categories.pushout import IdentityConstructionFunctor
     545            sage: I = IdentityConstructionFunctor()
     546            sage: F = QQ.construction()[0]
     547            sage: P = ZZ['t'].construction()[0]
     548            sage: I*F is F     # indirect doctest
     549            True
     550            sage: F*I is F
     551            True
     552            sage: I*P is P
     553            True
     554            sage: P*I is P
     555            True
     556
     557        """
    212558        if isinstance(self, IdentityConstructionFunctor):
    213559            return other
    214560        else:
    215561            return self
    216562
    217563
    218 
    219 
    220564class PolynomialFunctor(ConstructionFunctor):
    221 
     565    """
     566    Construction functor for univariate polynomial rings.
     567
     568    EXAMPLE:
     569
     570        sage: P = ZZ['t'].construction()[0]
     571        sage: P(GF(3))
     572        Univariate Polynomial Ring in t over Finite Field of size 3
     573        sage: P == loads(dumps(P))
     574        True
     575        sage: R.<x,y> = GF(5)[]
     576        sage: f = R.hom([x+2*y,3*x-y],R)
     577        sage: P(f)((x+y)*P(R).0)
     578        (-x + y)*t
     579
     580    """
    222581    rank = 9
    223582
    224583    def __init__(self, var, multi_variate=False):
     584        """
     585        TESTS::
     586
     587            sage: from sage.categories.pushout import PolynomialFunctor
     588            sage: P = PolynomialFunctor('x')
     589            sage: P(GF(3))
     590            Univariate Polynomial Ring in x over Finite Field of size 3
     591
     592        There is an optional parameter ``multi_variate``, but
     593        apparently it is not used::
     594
     595            sage: Q = PolynomialFunctor('x',multi_variate=True)
     596            sage: Q(ZZ)
     597            Univariate Polynomial Ring in x over Integer Ring
     598            sage: Q == P
     599            True
     600
     601        """
    225602        from rings import Rings
    226603        Functor.__init__(self, Rings(), Rings())
    227604        self.var = var
    228605        self.multi_variate = multi_variate
    229606
    230607    def _apply_functor(self, R):
     608        """
     609        Apply the functor to an object of ``self``'s domain.
     610       
     611        TEST::
     612
     613            sage: P = ZZ['x'].construction()[0]
     614            sage: P(GF(3))      # indirect doctest
     615            Univariate Polynomial Ring in x over Finite Field of size 3
     616
     617        """
    231618        from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
    232619        return PolynomialRing(R, self.var)
    233620
    234621    def __cmp__(self, other):
     622        """
     623        TESTS::
     624
     625            sage: from sage.categories.pushout import MultiPolynomialFunctor
     626            sage: Q = MultiPolynomialFunctor(('x',),'lex')
     627            sage: P = ZZ['x'].construction()[0]
     628            sage: P
     629            Poly[x]
     630            sage: Q
     631            MPoly[x]
     632            sage: P == Q
     633            True
     634            sage: P == loads(dumps(P))
     635            True
     636            sage: P == QQ.construction()[0]
     637            False
     638
     639        """
    235640        c = cmp(type(self), type(other))
    236641        if c == 0:
    237642            c = cmp(self.var, other.var)
     
    240645        return c
    241646
    242647    def merge(self, other):
     648        """
     649        Merge ``self`` with another construction functor, or return None.
     650       
     651        NOTE:
     652
     653        Internally, the merging is delegated to the merging of
     654        multipolynomial construction functors. But in effect,
     655        this does the same as the default implementation, that
     656        returns ``None`` unless the to-be-merged functors coincide.
     657
     658        EXAMPLE::
     659
     660            sage: P = ZZ['x'].construction()[0]
     661            sage: Q = ZZ['y','x'].construction()[0]
     662            sage: P.merge(Q)
     663            sage: P.merge(P) is P
     664            True
     665
     666        """
    243667        if isinstance(other, MultiPolynomialFunctor):
    244668            return other.merge(self)
    245669        elif self == other:
     
    248672            return None
    249673
    250674    def __str__(self):
     675        """
     676        TEST::
     677
     678            sage: P = ZZ['x'].construction()[0]
     679            sage: P       # indirect doctest
     680            Poly[x]
     681
     682        """
    251683        return "Poly[%s]" % self.var
    252684
    253685class MultiPolynomialFunctor(ConstructionFunctor):
    254686    """
    255687    A constructor for multivariate polynomial rings.
     688
     689    EXAMPLES::
     690
     691        sage: P.<x,y> = ZZ[]
     692        sage: F = P.construction()[0]; F
     693        MPoly[x,y]
     694        sage: A.<a,b> = GF(5)[]
     695        sage: F(A)
     696        Multivariate Polynomial Ring in x, y over Multivariate Polynomial Ring in a, b over Finite Field of size 5
     697        sage: f = A.hom([a+b,a-b],A)
     698        sage: F(f)
     699        Ring endomorphism of Multivariate Polynomial Ring in x, y over Multivariate Polynomial Ring in a, b over Finite Field of size 5
     700          Defn: Induced from base ring by
     701                Ring endomorphism of Multivariate Polynomial Ring in a, b over Finite Field of size 5
     702                  Defn: a |--> a + b
     703                        b |--> a - b
     704        sage: F(f)(F(A)(x)*a)
     705        (a + b)*x
     706
    256707    """
    257708   
    258709    rank = 9
    259710
    260711    def __init__(self, vars, term_order):
    261712        """
    262         EXAMPLES:
     713        EXAMPLES::
     714       
    263715            sage: F = sage.categories.pushout.MultiPolynomialFunctor(['x','y'], None)
    264716            sage: F
    265717            MPoly[x,y]
     
    274726
    275727    def _apply_functor(self, R):
    276728        """
    277         EXAMPLES:
     729        Apply the functor to an object of ``self``'s domain.
     730       
     731        EXAMPLES::
     732       
    278733            sage: R.<x,y,z> = QQ[]
    279734            sage: F = R.construction()[0]; F
    280735            MPoly[x,y,z]
    281736            sage: type(F)
    282737            <class 'sage.categories.pushout.MultiPolynomialFunctor'>
    283             sage: F(ZZ)
     738            sage: F(ZZ)          # indirect doctest
    284739            Multivariate Polynomial Ring in x, y, z over Integer Ring
    285             sage: F(RR)
     740            sage: F(RR)          # indirect doctest
    286741            Multivariate Polynomial Ring in x, y, z over Real Field with 53 bits of precision
    287742        """
    288743        from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
     
    290745
    291746    def __cmp__(self, other):
    292747        """
    293         EXAMPLES:
     748        EXAMPLES::
     749       
    294750            sage: F = ZZ['x,y,z'].construction()[0]
    295751            sage: G = QQ['x,y,z'].construction()[0]
    296752            sage: F == G
    297753            True
     754            sage: G == loads(dumps(G))
     755            True
    298756            sage: G = ZZ['x,y'].construction()[0]
    299757            sage: F == G
    300758            False
     
    311769        If two MPoly functors are given in a row, form a single MPoly functor
    312770        with all of the variables.
    313771       
    314         EXAMPLES:
     772        EXAMPLES::
     773       
    315774            sage: F = sage.categories.pushout.MultiPolynomialFunctor(['x','y'], None)
    316775            sage: G = sage.categories.pushout.MultiPolynomialFunctor(['t'], None)
    317776            sage: G*F
    318777            MPoly[x,y,t]
    319778        """
     779        if isinstance(other,IdentityConstructionFunctor):
     780            return self
    320781        if isinstance(other, MultiPolynomialFunctor):
    321782            if self.term_order != other.term_order:
    322783                raise CoercionException, "Incompatible term orders (%s,%s)." % (self.term_order, other.term_order)
     
    331792
    332793    def merge(self, other):
    333794        """
    334         EXAMPLES:
     795        Merge ``self`` with another construction functor, or return None.
     796       
     797        EXAMPLES::
     798       
    335799            sage: F = sage.categories.pushout.MultiPolynomialFunctor(['x','y'], None)
    336800            sage: G = sage.categories.pushout.MultiPolynomialFunctor(['t'], None)
    337801            sage: F.merge(G) is None
     
    346810
    347811    def expand(self):
    348812        """
    349         EXAMPLES:
     813        Decompose ``self`` into a list of construction functors.
     814       
     815        EXAMPLES::
     816       
    350817            sage: F = QQ['x,y,z,t'].construction()[0]; F
    351818            MPoly[x,y,z,t]
    352819            sage: F.expand()
    353820            [MPoly[t], MPoly[z], MPoly[y], MPoly[x]]
    354821           
    355         Now an actual use case:
     822        Now an actual use case::
     823       
    356824            sage: R.<x,y,z> = ZZ[]
    357825            sage: S.<z,t> = QQ[]
    358826            sage: x+t
     
    376844
    377845    def __str__(self):
    378846        """
    379         EXAMPLES:
     847        TEST::
     848       
    380849            sage: QQ['x,y,z,t'].construction()[0]
    381850            MPoly[x,y,z,t]
    382851        """
     
    386855
    387856class InfinitePolynomialFunctor(ConstructionFunctor):
    388857    """
    389     A Construction Functor for Infinite Polynomial Rings (see :mod:`~sage.rings.polynomial.infinite_polynomial_ring`)
     858    A Construction Functor for Infinite Polynomial Rings (see :mod:`~sage.rings.polynomial.infinite_polynomial_ring`).
    390859   
    391860    AUTHOR:
    392        -- Simon King
     861
     862    -- Simon King
    393863
    394864    This construction functor is used to provide uniqueness of infinite polynomial rings as parent structures.
    395865    As usual, the construction functor allows for constructing pushouts.
     
    443913        CoercionException: Overlapping variables (('a', 'b'),['a_3', 'a_1']) are incompatible
    444914
    445915    Since the construction functors are actually used to construct infinite polynomial rings, the following
    446     result is no surprise:
     916    result is no surprise::
    447917
    448918        sage: C.<a,b> = InfinitePolynomialRing(B); C
    449919        Infinite polynomial ring in a, b over Multivariate Polynomial Ring in x, y over Rational Field
     
    455925
    456926    `X` and `Y` have an overlapping generators `x_\\ast, y_\\ast`. Since the default lexicographic order is
    457927    used in both rings, it gives rise to isomorphic sub-monoids in both `X` and `Y`. They are merged in the
    458     pushout, which also yields a common parent for doing arithmetic.
     928    pushout, which also yields a common parent for doing arithmetic::
    459929
    460930        sage: P = sage.categories.pushout.pushout(Y,X); P
    461931        Infinite polynomial ring in w, x, y, z over Rational Field
     
    476946        """
    477947        TEST::
    478948
    479             sage: F = sage.categories.pushout.InfinitePolynomialFunctor(['a','b','x'],'degrevlex','sparse'); F # indirect doc test
     949            sage: F = sage.categories.pushout.InfinitePolynomialFunctor(['a','b','x'],'degrevlex','sparse'); F # indirect doctest
    480950            InfPoly{[a,b,x], "degrevlex", "sparse"}
    481951            sage: F == loads(dumps(F))
    482952            True
     
    490960        self._imple = implementation
    491961
    492962    def _apply_functor_to_morphism(self, f):
    493         raise NotImplementedError
     963        """
     964        Morphisms for inifinite polynomial rings are not implemented yet.
     965
     966        TEST::
     967
     968            sage: P.<x,y> = QQ[]
     969            sage: R.<alpha> = InfinitePolynomialRing(P)
     970            sage: f = P.hom([x+y,x-y],P)
     971            sage: R.construction()[0](f)     # indirect doctest
     972            Traceback (most recent call last):
     973            ...
     974            NotImplementedError: Morphisms for inifinite polynomial rings are not implemented yet.
     975           
     976        """
     977        raise NotImplementedError, "Morphisms for inifinite polynomial rings are not implemented yet."
    494978
    495979    def _apply_functor(self, R):
    496980        """
     981        Apply the functor to an object of ``self``'s domain.
     982       
    497983        TEST::
    498984
    499985            sage: F = sage.categories.pushout.InfinitePolynomialFunctor(['a','b','x'],'degrevlex','sparse'); F
    500986            InfPoly{[a,b,x], "degrevlex", "sparse"}
    501             sage: F(QQ['t']) # indirect doc test
     987            sage: F(QQ['t']) # indirect doctest
    502988            Infinite polynomial ring in a, b, x over Univariate Polynomial Ring in t over Rational Field
    503989
    504990        """
     
    509995        """
    510996        TEST::
    511997
    512             sage: F = sage.categories.pushout.InfinitePolynomialFunctor(['a','b','x'],'degrevlex','sparse'); F # indirect doc test
     998            sage: F = sage.categories.pushout.InfinitePolynomialFunctor(['a','b','x'],'degrevlex','sparse'); F # indirect doctest
    513999            InfPoly{[a,b,x], "degrevlex", "sparse"}
    5141000
    5151001        """
     
    5191005        """
    5201006        TEST::
    5211007
    522             sage: F = sage.categories.pushout.InfinitePolynomialFunctor(['a','b','x'],'degrevlex','sparse'); F # indirect doc test
     1008            sage: F = sage.categories.pushout.InfinitePolynomialFunctor(['a','b','x'],'degrevlex','sparse'); F # indirect doctest
    5231009            InfPoly{[a,b,x], "degrevlex", "sparse"}
    524             sage: F == loads(dumps(F)) # indirect doc test
     1010            sage: F == loads(dumps(F)) # indirect doctest
    5251011            True
    5261012            sage: F == sage.categories.pushout.InfinitePolynomialFunctor(['a','b','x'],'deglex','sparse')
    5271013            False
     
    5341020
    5351021    def __mul__(self, other):
    5361022        """
     1023        Compose construction functors to a composit construction functor, unless one of them is the identity.
     1024
     1025        NOTE:
     1026
     1027        The product is in functorial notation, i.e., when applying the product to an object
     1028        then the second factor is applied first.
     1029
    5371030        TESTS::
    5381031
    5391032            sage: F1 = QQ['a','x_2','x_1','y_3','y_2'].construction()[0]; F1
     
    5511044            InfPoly{[x,y], "degrevlex", "dense"}(FractionField(...))
    5521045
    5531046        """
     1047        if isinstance(other,IdentityConstructionFunctor):
     1048            return self
    5541049        if isinstance(other, self.__class__): #
    5551050            INT = set(self._gens).intersection(other._gens)
    5561051            if INT:
     
    6841179            if self._imple != other._imple:
    6851180                return InfinitePolynomialFunctor(self._gens, self._order, 'dense')
    6861181            return self
    687 ##         if isinstance(other, PolynomialFunctor) or isinstance(other, MultiPolynomialFunctor):
    688 ##             # For merging, we don't care about the orders
    689 ## ##            if isinstance(other, MultiPolynomialFunctor) and self._order!=other.term_order.name():
    690 ## ##                return None
    691 ##             # We only merge if other's variables can all be interpreted in self.
    692 ##             if isinstance(other, PolynomialFunctor):
    693 ##                 if other.var.count('_')!=1:
    694 ##                     return None
    695 ##                 g,n = other.var.split('_')
    696 ##                 if not ((g in self._gens) and n.isdigit()):
    697 ##                     return None
    698 ##                 # other merges into self!
    699 ##                 return self
    700 ##             # Now, other is MultiPolynomial
    701 ##             for v in other.vars:
    702 ##                 if v.count('_')!=1:
    703 ##                     return None
    704 ##                 g,n = v.split('_')
    705 ##                 if not ((g in self._gens) and n.isdigit()):
    706 ##                     return None
    707 ##             # other merges into self!
    708 ##             return self
    7091182        return None
    7101183
    7111184    def expand(self):
    7121185        """
    713         Decompose the functor `F` into sub-functors, whose product returns `F`
     1186        Decompose the functor `F` into sub-functors, whose product returns `F`.
    7141187
    7151188        EXAMPLES::
    7161189
     
    7351208
    7361209
    7371210class MatrixFunctor(ConstructionFunctor):
    738 
     1211    """
     1212    A construction functor for matrices over rings.
     1213
     1214    EXAMPLES::
     1215
     1216        sage: MS = MatrixSpace(ZZ,2, 3)
     1217        sage: F = MS.construction()[0]; F
     1218        MatrixFunctor
     1219        sage: MS = MatrixSpace(ZZ,2)
     1220        sage: F = MS.construction()[0]; F
     1221        MatrixFunctor
     1222        sage: P.<x,y> = QQ[]
     1223        sage: R = F(P); R
     1224        Full MatrixSpace of 2 by 2 dense matrices over Multivariate Polynomial Ring in x, y over Rational Field
     1225        sage: f = P.hom([x+y,x-y],P); F(f)
     1226        Ring endomorphism of Full MatrixSpace of 2 by 2 dense matrices over Multivariate Polynomial Ring in x, y over Rational Field
     1227          Defn: Induced from base ring by
     1228                Ring endomorphism of Multivariate Polynomial Ring in x, y over Rational Field
     1229                  Defn: x |--> x + y
     1230                        y |--> x - y
     1231        sage: M = R([x,y,x*y,x+y])
     1232        sage: F(f)(M)
     1233        [    x + y     x - y]
     1234        [x^2 - y^2       2*x]
     1235
     1236    """
    7391237    rank = 10
    7401238
    7411239    def __init__(self, nrows, ncols, is_sparse=False):
    742 #        if nrows == ncols:
    743 #            Functor.__init__(self, Rings(), RingModules()) # takes a base ring
    744 #        else:
    745 #            Functor.__init__(self, Rings(), MatrixAlgebras()) # takes a base ring
    746         # We must distinguish two cases:
    747         # If nrows=ncols, the result is a ring. Otherwise,
    748         # it is just a commutative additive group.
    749         if nrows==ncols:
    750             Functor.__init__(self, Rings(), Rings())
     1240        """
     1241        TEST::
     1242
     1243            sage: from sage.categories.pushout import MatrixFunctor
     1244            sage: F = MatrixFunctor(2,3)
     1245            sage: F == MatrixSpace(ZZ,2,3).construction()[0]
     1246            True
     1247            sage: F.codomain()
     1248            Category of commutative additive groups
     1249            sage: R = MatrixSpace(ZZ,2,2).construction()[0]
     1250            sage: R.codomain()
     1251            Category of rings
     1252            sage: F(ZZ)
     1253            Full MatrixSpace of 2 by 3 dense matrices over Integer Ring
     1254            sage: F(ZZ) in F.codomain()
     1255            True
     1256            sage: R(GF(2))
     1257            Full MatrixSpace of 2 by 2 dense matrices over Finite Field of size 2
     1258            sage: R(GF(2)) in R.codomain()
     1259            True
     1260        """
     1261        if nrows == ncols:
     1262            Functor.__init__(self, Rings(), Rings()) # Algebras() takes a base ring
    7511263        else:
    752             Functor.__init__(self,Rings(), CommutativeAdditiveGroups())
     1264            # Functor.__init__(self, Rings(), MatrixAlgebras()) # takes a base ring
     1265            Functor.__init__(self, Rings(), CommutativeAdditiveGroups()) # not a nice solution, but the best we can do.
    7531266        self.nrows = nrows
    7541267        self.ncols = ncols
    7551268        self.is_sparse = is_sparse
     1269
    7561270    def _apply_functor(self, R):
     1271        """
     1272        Apply the functor to an object of ``self``'s domain.
     1273       
     1274        TEST:
     1275
     1276        The following is a test against a bug discussed at ticket #8800
     1277
     1278            sage: F = MatrixSpace(ZZ,2,3).construction()[0]
     1279            sage: F(RR)         # indirect doctest
     1280            Full MatrixSpace of 2 by 3 dense matrices over Real Field with 53 bits of precision
     1281            sage: F(RR) in F.codomain()
     1282            True
     1283
     1284        """
    7571285        from sage.matrix.matrix_space import MatrixSpace
    7581286        return MatrixSpace(R, self.nrows, self.ncols, sparse=self.is_sparse)
     1287
    7591288    def __cmp__(self, other):
     1289        """
     1290        TEST::
     1291       
     1292            sage: F = MatrixSpace(ZZ,2,3).construction()[0]
     1293            sage: F == loads(dumps(F))
     1294            True
     1295            sage: F == MatrixSpace(ZZ,2,2).construction()[0]
     1296            False
     1297
     1298        """
    7601299        c = cmp(type(self), type(other))
    7611300        if c == 0:
    7621301            c = cmp((self.nrows, self.ncols), (other.nrows, other.ncols))
    7631302        return c
     1303
    7641304    def merge(self, other):
     1305        """
     1306        Merging is only happening if both functors are matrix functors of the same dimension.
     1307        The result is sparse if and only if both given functors are sparse.
     1308
     1309        EXAMPLE::
     1310
     1311            sage: F1 = MatrixSpace(ZZ,2,2).construction()[0]
     1312            sage: F2 = MatrixSpace(ZZ,2,3).construction()[0]
     1313            sage: F3 = MatrixSpace(ZZ,2,2,sparse=True).construction()[0]
     1314            sage: F1.merge(F2)
     1315            sage: F1.merge(F3)
     1316            MatrixFunctor
     1317            sage: F13 = F1.merge(F3)
     1318            sage: F13.is_sparse
     1319            False
     1320            sage: F1.is_sparse
     1321            False
     1322            sage: F3.is_sparse
     1323            True
     1324            sage: F3.merge(F3).is_sparse
     1325            True
     1326
     1327        """
    7651328        if self != other:
    7661329            return None
    7671330        else:
    7681331            return MatrixFunctor(self.nrows, self.ncols, self.is_sparse and other.is_sparse)
    7691332
    7701333class LaurentPolynomialFunctor(ConstructionFunctor):
    771 
     1334    """
     1335    Construction functor for Laurent polynomial rings.
     1336
     1337    EXAMPLES::
     1338
     1339        sage: L.<t> = LaurentPolynomialRing(ZZ)
     1340        sage: F = L.construction()[0]
     1341        sage: F
     1342        LaurentPolynomialFunctor
     1343        sage: F(QQ)
     1344        Univariate Laurent Polynomial Ring in t over Rational Field
     1345        sage: K.<x> = LaurentPolynomialRing(ZZ)
     1346        sage: F(K)
     1347        Univariate Laurent Polynomial Ring in t over Univariate Laurent Polynomial Ring in x over Integer Ring
     1348        sage: P.<x,y> = ZZ[]
     1349        sage: f = P.hom([x+2*y,3*x-y],P)
     1350        sage: F(f)
     1351        Ring endomorphism of Univariate Laurent Polynomial Ring in t over Multivariate Polynomial Ring in x, y over Integer Ring
     1352          Defn: Induced from base ring by
     1353                Ring endomorphism of Multivariate Polynomial Ring in x, y over Integer Ring
     1354                  Defn: x |--> x + 2*y
     1355                        y |--> 3*x - y
     1356        sage: F(f)(x*F(P).gen()^-2+y*F(P).gen()^3)
     1357        (3*x - y)*t^3 + (x + 2*y)*t^-2
     1358
     1359    """
    7721360    rank = 9
    7731361   
    7741362    def __init__(self, var, multi_variate=False):
     1363        """
     1364        INPUT:
     1365
     1366        - ``var``, a string or a list of strings
     1367        - ``multi_variate``, optional bool, default ``False`` if ``var`` is a string
     1368          and ``True`` otherwise: If ``True``, application to a Laurent polynomial
     1369          ring yields a multivariate Laurent polynomial ring.
     1370
     1371        TESTS::
     1372
     1373            sage: from sage.categories.pushout import LaurentPolynomialFunctor
     1374            sage: F1 = LaurentPolynomialFunctor('t')
     1375            sage: F2 = LaurentPolynomialFunctor('s', multi_variate=True)
     1376            sage: F3 = LaurentPolynomialFunctor(['s','t'])
     1377            sage: F1(F2(QQ))
     1378            Univariate Laurent Polynomial Ring in t over Univariate Laurent Polynomial Ring in s over Rational Field
     1379            sage: F2(F1(QQ))
     1380            Multivariate Laurent Polynomial Ring in t, s over Rational Field
     1381            sage: F3(QQ)
     1382            Multivariate Laurent Polynomial Ring in s, t over Rational Field
     1383
     1384        """
    7751385        Functor.__init__(self, Rings(), Rings())
     1386        if not isinstance(var, (basestring,tuple,list)):
     1387            raise TypeError, "variable name or list of variable names expected"
    7761388        self.var = var
    777         self.multi_variate = multi_variate
     1389        self.multi_variate = multi_variate or not isinstance(var, basestring)
     1390
    7781391    def _apply_functor(self, R):
     1392        """
     1393        Apply the functor to an object of ``self``'s domain.
     1394       
     1395        TESTS::
     1396
     1397            sage: from sage.categories.pushout import LaurentPolynomialFunctor
     1398            sage: F1 = LaurentPolynomialFunctor('t')
     1399            sage: F2 = LaurentPolynomialFunctor('s', multi_variate=True)
     1400            sage: F3 = LaurentPolynomialFunctor(['s','t'])
     1401            sage: F1(F2(QQ))          # indirect doctest
     1402            Univariate Laurent Polynomial Ring in t over Univariate Laurent Polynomial Ring in s over Rational Field
     1403            sage: F2(F1(QQ))
     1404            Multivariate Laurent Polynomial Ring in t, s over Rational Field
     1405            sage: F3(QQ)
     1406            Multivariate Laurent Polynomial Ring in s, t over Rational Field
     1407
     1408        """
    7791409        from sage.rings.polynomial.laurent_polynomial_ring import LaurentPolynomialRing, is_LaurentPolynomialRing
    7801410        if self.multi_variate and is_LaurentPolynomialRing(R):
    7811411            return LaurentPolynomialRing(R.base_ring(), (list(R.variable_names()) + [self.var]))
    7821412        else:
    7831413            from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
    7841414            return LaurentPolynomialRing(R, self.var)
     1415
    7851416    def __cmp__(self, other):
     1417        """
     1418        TESTS::
     1419
     1420            sage: from sage.categories.pushout import LaurentPolynomialFunctor
     1421            sage: F1 = LaurentPolynomialFunctor('t')
     1422            sage: F2 = LaurentPolynomialFunctor('t', multi_variate=True)
     1423            sage: F3 = LaurentPolynomialFunctor(['s','t'])
     1424            sage: F1 == F2
     1425            True
     1426            sage: F1 == loads(dumps(F1))
     1427            True
     1428            sage: F1 == F3
     1429            False
     1430            sage: F1 == QQ.construction()[0]
     1431            False
     1432
     1433        """
    7861434        c = cmp(type(self), type(other))
    7871435        if c == 0:
    7881436            c = cmp(self.var, other.var)
    7891437        return c
     1438
    7901439    def merge(self, other):
     1440        """
     1441        Two Laurent polynomial construction functors merge if the variable names coincide.
     1442        The result is multivariate if one of the arguments is multivariate.
     1443
     1444        EXAMPLE::
     1445
     1446            sage: from sage.categories.pushout import LaurentPolynomialFunctor
     1447            sage: F1 = LaurentPolynomialFunctor('t')
     1448            sage: F2 = LaurentPolynomialFunctor('t', multi_variate=True)
     1449            sage: F1.merge(F2)
     1450            LaurentPolynomialFunctor
     1451            sage: F1.merge(F2)(LaurentPolynomialRing(GF(2),'a'))
     1452            Multivariate Laurent Polynomial Ring in a, t over Finite Field of size 2
     1453            sage: F1.merge(F1)(LaurentPolynomialRing(GF(2),'a'))
     1454            Univariate Laurent Polynomial Ring in t over Univariate Laurent Polynomial Ring in a over Finite Field of size 2
     1455
     1456        """
    7911457        if self == other or isinstance(other, PolynomialFunctor) and self.var == other.var:
    7921458            return LaurentPolynomialFunctor(self.var, (self.multi_variate or other.multi_variate))
    7931459        else:
     
    7951461
    7961462       
    7971463class VectorFunctor(ConstructionFunctor):
    798 
    799     rank = 10 # ranking of functor, not rank of module
     1464    """
     1465    A construction functor for free modules over commutative rings.
     1466
     1467    EXAMPLE::
     1468
     1469        sage: F = (ZZ^3).construction()[0]
     1470        sage: F
     1471        VectorFunctor
     1472        sage: F(GF(2)['t'])
     1473        Ambient free module of rank 3 over the principal ideal domain Univariate Polynomial Ring in t over Finite Field of size 2 (using NTL)
     1474       
     1475
     1476    """
     1477    rank = 10 # ranking of functor, not rank of module.
     1478    # This coincides with the rank of the matrix construction functor, but this is OK since they can not both be applied in any order
    8001479
    8011480    def __init__(self, n, is_sparse=False, inner_product_matrix=None):
    802 #        Functor.__init__(self, Rings(), FreeModules()) # takes a base ring
    803         #This is a bad choice, since the input must be a commutative ring, and
    804         #the output belongs to the category of commutative additive groups
    805         #Functor.__init__(self, Objects(), Objects())
    806         Functor.__init__(self,CommutativeRings(),CommutativeAdditiveGroups())
     1481        """
     1482        INPUT:
     1483
     1484        - ``n``, the rank of the to-be-created modules (non-negative integer)
     1485        - ``is_sparse`` (optional bool, default ``False``), create sparse implementation of modules
     1486        - ``inner_product_matrix``: ``n`` by ``n`` matrix, used to compute inner products in the
     1487          to-be-created modules
     1488
     1489        TEST::
     1490
     1491            sage: from sage.categories.pushout import VectorFunctor
     1492            sage: F1 = VectorFunctor(3, inner_product_matrix = Matrix(3,3,range(9)))
     1493            sage: F1.domain()
     1494            Category of commutative rings
     1495            sage: F1.codomain()
     1496            Category of commutative additive groups
     1497            sage: M1 = F1(ZZ)
     1498            sage: M1.is_sparse()
     1499            False
     1500            sage: v = M1([3, 2, 1])
     1501            sage: v*Matrix(3,3,range(9))*v.column()
     1502            (96)
     1503            sage: v.inner_product(v)
     1504            96
     1505            sage: F2 = VectorFunctor(3, is_sparse=True)
     1506            sage: M2 = F2(QQ); M2; M2.is_sparse()
     1507            Sparse vector space of dimension 3 over Rational Field
     1508            True
     1509
     1510        """
     1511#        Functor.__init__(self, Rings(), FreeModules()) # FreeModules() takes a base ring
     1512#        Functor.__init__(self, Objects(), Objects())   # Object() makes no sence, since FreeModule raises an error, e.g., on Set(['a',1]).
     1513        ## FreeModule requires a commutative ring. Thus, we have
     1514        Functor.__init__(self, CommutativeRings(), CommutativeAdditiveGroups())
    8071515        self.n = n
    8081516        self.is_sparse = is_sparse
    8091517        self.inner_product_matrix = inner_product_matrix
     1518
    8101519    def _apply_functor(self, R):
     1520        """
     1521        Apply the functor to an object of ``self``'s domain.
     1522       
     1523        TESTS::
     1524
     1525            sage: from sage.categories.pushout import VectorFunctor
     1526            sage: F1 = VectorFunctor(3, inner_product_matrix = Matrix(3,3,range(9)))
     1527            sage: M1 = F1(ZZ)   # indirect doctest
     1528            sage: M1.is_sparse()
     1529            False
     1530            sage: v = M1([3, 2, 1])
     1531            sage: v*Matrix(3,3,range(9))*v.column()
     1532            (96)
     1533            sage: v.inner_product(v)
     1534            96
     1535            sage: F2 = VectorFunctor(3, is_sparse=True)
     1536            sage: M2 = F2(QQ); M2; M2.is_sparse()
     1537            Sparse vector space of dimension 3 over Rational Field
     1538            True
     1539            sage: v = M2([3, 2, 1])
     1540            sage: v.inner_product(v)
     1541            14
     1542
     1543        """
    8111544        from sage.modules.free_module import FreeModule
    8121545        return FreeModule(R, self.n, sparse=self.is_sparse, inner_product_matrix=self.inner_product_matrix)
     1546
     1547    def _apply_functor_to_morphism(self, f):
     1548        """
     1549        This is not implemented yet.
     1550
     1551        TEST::
     1552
     1553            sage: F = (ZZ^3).construction()[0]
     1554            sage: P.<x,y> = ZZ[]
     1555            sage: f = P.hom([x+2*y,3*x-y],P)
     1556            sage: F(f)       # indirect doctest
     1557            Traceback (most recent call last):
     1558            ...
     1559            NotImplementedError: Can not create induced morphisms of free modules yet
     1560        """
     1561        ## TODO: Implement this!
     1562        raise NotImplementedError, "Can not create induced morphisms of free modules yet"
     1563
    8131564    def __cmp__(self, other):
     1565        """
     1566        Only the rank of the to-be-created modules is compared, *not* the inner product matrix.
     1567
     1568        TESTS::
     1569
     1570            sage: from sage.categories.pushout import VectorFunctor
     1571            sage: F1 = VectorFunctor(3, inner_product_matrix = Matrix(3,3,range(9)))
     1572            sage: F2 = (ZZ^3).construction()[0]
     1573            sage: F1 == F2
     1574            True
     1575            sage: F1(QQ) == F2(QQ)
     1576            True
     1577            sage: F1(QQ).inner_product_matrix() == F2(QQ).inner_product_matrix()
     1578            False
     1579            sage: F1 == loads(dumps(F1))
     1580            True
     1581        """
    8141582        c = cmp(type(self), type(other))
    8151583        if c == 0:
    8161584            c = cmp(self.n, other.n)
    8171585        return c
     1586
    8181587    def merge(self, other):
     1588        """
     1589        Two constructors of free modules merge, if the module ranks coincide. If both
     1590        have explicitly given inner product matrices, they must coincide as well.
     1591
     1592        EXAMPLE:
     1593
     1594        Two modules without explicitly given inner product allow coercion::
     1595
     1596            sage: M1 = QQ^3
     1597            sage: P.<t> = ZZ[]
     1598            sage: M2 = FreeModule(P,3)
     1599            sage: M1([1,1/2,1/3]) + M2([t,t^2+t,3])     # indirect doctest
     1600            (t + 1, t^2 + t + 1/2, 10/3)
     1601
     1602        If only one summand has an explicit inner product, the result will be provided
     1603        with it::
     1604
     1605            sage: M3 = FreeModule(P,3, inner_product_matrix = Matrix(3,3,range(9)))
     1606            sage: M1([1,1/2,1/3]) + M3([t,t^2+t,3])
     1607            (t + 1, t^2 + t + 1/2, 10/3)
     1608            sage: (M1([1,1/2,1/3]) + M3([t,t^2+t,3])).parent().inner_product_matrix()
     1609            [0 1 2]
     1610            [3 4 5]
     1611            [6 7 8]
     1612
     1613        If both summands have an explicit inner product (even if it is the standard
     1614        inner product), then the products must coincide. The only difference between
     1615        ``M1`` and ``M4`` in the following example is the fact that the default
     1616        inner product was *explicitly* requested for ``M4``. It is therefore not
     1617        possible to coerce with a different inner product::
     1618
     1619            sage: M4 = FreeModule(QQ,3, inner_product_matrix = Matrix(3,3,1))
     1620            sage: M4 == M1
     1621            True
     1622            sage: M4.inner_product_matrix() == M1.inner_product_matrix()
     1623            True
     1624            sage: M4([1,1/2,1/3]) + M3([t,t^2+t,3])      # indirect doctest
     1625            Traceback (most recent call last):
     1626            ...
     1627            TypeError: unsupported operand parent(s) for '+': 'Ambient quadratic space of dimension 3 over Rational Field
     1628            Inner product matrix:
     1629            [1 0 0]
     1630            [0 1 0]
     1631            [0 0 1]' and 'Ambient free quadratic module of rank 3 over the integral domain Univariate Polynomial Ring in t over Integer Ring
     1632            Inner product matrix:
     1633            [0 1 2]
     1634            [3 4 5]
     1635            [6 7 8]'
     1636
     1637        """
    8191638        if self != other:
    8201639            return None
     1640        if self.inner_product_matrix is None:
     1641            return VectorFunctor(self.n, self.is_sparse and other.is_sparse, other.inner_product_matrix)
     1642        if other.inner_product_matrix is None:
     1643            return VectorFunctor(self.n, self.is_sparse and other.is_sparse, self.inner_product_matrix)
     1644        # At this point, we know that the user wants to take care of the inner product.
     1645        # So, we only merge if both coincide:
     1646        if self.inner_product_matrix != other.inner_product_matrix:
     1647            return None
    8211648        else:
    822             return VectorFunctor(self.n, self.is_sparse and other.is_sparse)
    823 
     1649            return VectorFunctor(self.n, self.is_sparse and other.is_sparse, self.inner_product_matrix)
    8241650
    8251651class SubspaceFunctor(ConstructionFunctor):
     1652    """
     1653    Constructing a subspace of an ambient free module, given by a basis.
     1654
     1655    NOTE:
     1656
     1657    This construction functor keeps track of the basis. It can only be applied
     1658    to free modules into which this basis coerces.
     1659
     1660    EXAMPLES::
     1661
     1662        sage: M = ZZ^3
     1663        sage: S = M.submodule([(1,2,3),(4,5,6)]); S
     1664        Free module of degree 3 and rank 2 over Integer Ring
     1665        Echelon basis matrix:
     1666        [1 2 3]
     1667        [0 3 6]
     1668        sage: F = S.construction()[0]
     1669        sage: F(GF(2)^3)
     1670        Vector space of degree 3 and dimension 2 over Finite Field of size 2
     1671        User basis matrix:
     1672        [1 0 1]
     1673        [0 1 0]
     1674
     1675    """
    8261676    rank = 11 # ranking of functor, not rank of module
     1677
    8271678    def __init__(self, basis):
    828 #        Functor.__init__(self, FreeModules(), FreeModules()) # takes a base ring
    829         #Functor.__init__(self, Objects(), Objects())
     1679        """
     1680        INPUT:
     1681
     1682        ``basis``: a list of elements of a free module.
     1683
     1684        TEST::
     1685
     1686            sage: from sage.categories.pushout import SubspaceFunctor
     1687            sage: M = ZZ^3
     1688            sage: F = SubspaceFunctor([M([1,2,3]),M([4,5,6])])
     1689            sage: F(GF(5)^3)
     1690            Vector space of degree 3 and dimension 2 over Finite Field of size 5
     1691            User basis matrix:
     1692            [1 2 3]
     1693            [4 0 1]
     1694        """
     1695##        Functor.__init__(self, FreeModules(), FreeModules()) # takes a base ring
     1696##        Functor.__init__(self, Objects(), Objects())   # is too general
    8301697        ## It seems that the category of commutative additive groups
    8311698        ## currently is the smallest base ring free category that
    8321699        ## contains in- and output
    833         Functor.__init__(self, CommutativeAdditiveGroups(),CommutativeAdditiveGroups())
     1700        Functor.__init__(self, CommutativeAdditiveGroups(), CommutativeAdditiveGroups())
    8341701        self.basis = basis
     1702
    8351703    def _apply_functor(self, ambient):
     1704        """
     1705        Apply the functor to an object of ``self``'s domain.
     1706       
     1707        TESTS::
     1708
     1709            sage: M = ZZ^3
     1710            sage: S = M.submodule([(1,2,3),(4,5,6)]); S
     1711            Free module of degree 3 and rank 2 over Integer Ring
     1712            Echelon basis matrix:
     1713            [1 2 3]
     1714            [0 3 6]
     1715            sage: F = S.construction()[0]
     1716            sage: F(GF(2)^3)    # indirect doctest
     1717            Vector space of degree 3 and dimension 2 over Finite Field of size 2
     1718            User basis matrix:
     1719            [1 0 1]
     1720            [0 1 0]
     1721        """
    8361722        return ambient.span_of_basis(self.basis)
     1723
     1724    def _apply_functor_to_morphism(self, f):
     1725        """
     1726        This is not implemented yet.
     1727
     1728        TEST::
     1729
     1730            sage: F = (ZZ^3).span([(1,2,3),(4,5,6)]).construction()[0]
     1731            sage: P.<x,y> = ZZ[]
     1732            sage: f = P.hom([x+2*y,3*x-y],P)
     1733            sage: F(f)      # indirect doctest
     1734            Traceback (most recent call last):
     1735            ...
     1736            NotImplementedError: Can not create morphisms of free sub-modules yet
     1737        """
     1738        raise NotImplementedError, "Can not create morphisms of free sub-modules yet"
     1739
    8371740    def __cmp__(self, other):
     1741        """
     1742        TEST::
     1743
     1744            sage: F1 = (GF(5)^3).span([(1,2,3),(4,5,6)]).construction()[0]
     1745            sage: F2 = (ZZ^3).span([(1,2,3),(4,5,6)]).construction()[0]
     1746            sage: F3 = (QQ^3).span([(1,2,3),(4,5,6)]).construction()[0]
     1747            sage: F4 = (ZZ^3).span([(1,0,-1),(0,1,2)]).construction()[0]
     1748            sage: F1 == loads(dumps(F1))
     1749            True
     1750
     1751        The ``span`` method automatically transforms the given basis into
     1752        echelon form. The bases look like that::
     1753
     1754            sage: F1.basis
     1755            [
     1756            (1, 0, 4),
     1757            (0, 1, 2)
     1758            ]
     1759            sage: F2.basis
     1760            [
     1761            (1, 2, 3),
     1762            (0, 3, 6)
     1763            ]
     1764            sage: F3.basis
     1765            [
     1766            (1, 0, -1),
     1767            (0, 1, 2)
     1768            ]
     1769            sage: F4.basis
     1770            [
     1771            (1, 0, -1),
     1772            (0, 1, 2)
     1773            ]
     1774
     1775
     1776        The basis of ``F2`` is modulo 5 different from the other bases.
     1777        So, we have::
     1778
     1779            sage: F1 != F2 != F3
     1780            True
     1781
     1782        The bases of ``F1``, ``F3`` and ``F4`` are the same modulo 5; however,
     1783        there is no coercion from ``QQ^3`` to ``GF(5)^3``. Therefore, we have::
     1784
     1785            sage: F1 == F3
     1786            False
     1787
     1788        But there are coercions from ``ZZ^3`` to ``QQ^3`` and ``GF(5)^3``, thus::
     1789
     1790            sage: F1 == F4 == F3
     1791            True
     1792
     1793        """
    8381794        c = cmp(type(self), type(other))
    8391795        if c == 0:
    8401796            c = cmp(self.basis, other.basis)
    8411797        return c
     1798
    8421799    def merge(self, other):
     1800        """
     1801        Two Subspace Functors are merged into a construction functor of the sum of two subspaces.
     1802
     1803        EXAMPLE::
     1804
     1805            sage: M = GF(5)^3
     1806            sage: S1 = M.submodule([(1,2,3),(4,5,6)])
     1807            sage: S2 = M.submodule([(2,2,3)])
     1808            sage: F1 = S1.construction()[0]
     1809            sage: F2 = S2.construction()[0]
     1810            sage: F1.merge(F2)
     1811            SubspaceFunctor
     1812            sage: F1.merge(F2)(GF(5)^3) == S1+S2
     1813            True
     1814            sage: F1.merge(F2)(GF(5)['t']^3)
     1815            Free module of degree 3 and rank 3 over Univariate Polynomial Ring in t over Finite Field of size 5
     1816            User basis matrix:
     1817            [1 0 0]
     1818            [0 1 0]
     1819            [0 0 1]
     1820
     1821        TEST::
     1822
     1823            sage: P.<t> = ZZ[]
     1824            sage: S1 = (ZZ^3).submodule([(1,2,3),(4,5,6)])
     1825            sage: S2 = (Frac(P)^3).submodule([(t,t^2,t^3+1),(4*t,0,1)])
     1826            sage: v = S1([0,3,6]) + S2([2,0,1/(2*t)]); v   # indirect doctest
     1827            (2, 3, (12*t + 1)/(2*t))
     1828            sage: v.parent()
     1829            Vector space of degree 3 and dimension 3 over Fraction Field of Univariate Polynomial Ring in t over Integer Ring
     1830            User basis matrix:
     1831            [1 0 0]
     1832            [0 1 0]
     1833            [0 0 1]
     1834
     1835        """
    8431836        if isinstance(other, SubspaceFunctor):
    844             return SubspaceFunctor(self.basis + other.basis) # TODO: remove linear dependencies
     1837            # in order to remove linear dependencies, and in
     1838            # order to test compatibility of the base rings,
     1839            # we try to construct a sample submodule
     1840            if not other.basis:
     1841                return self
     1842            if not self.basis:
     1843                return other
     1844            try:
     1845                P = pushout(self.basis[0].parent().ambient_module(),other.basis[0].parent().ambient_module())
     1846            except CoercionException:
     1847                return None
     1848            S = P.submodule(self.basis+other.basis).echelonized_basis()
     1849            return SubspaceFunctor(S)
    8451850        else:
    8461851            return None
    8471852
    848        
    8491853class FractionField(ConstructionFunctor):
    850    
     1854    """
     1855    Construction functor for fraction fields.
     1856
     1857    EXAMPLE::
     1858
     1859        sage: F = QQ.construction()[0]
     1860        sage: F(GF(5)) is GF(5)
     1861        True
     1862        sage: F(ZZ['t'])
     1863        Fraction Field of Univariate Polynomial Ring in t over Integer Ring
     1864        sage: P.<x,y> = QQ[]
     1865        sage: f = P.hom([x+2*y,3*x-y],P)
     1866        sage: F(f)
     1867        Ring endomorphism of Fraction Field of Multivariate Polynomial Ring in x, y over Rational Field
     1868          Defn: x |--> x + 2*y
     1869                y |--> 3*x - y
     1870        sage: F(f)(1/x)
     1871        1/(x + 2*y)
     1872        sage: F == loads(dumps(F))
     1873        True
     1874
     1875    """
    8511876    rank = 5
    8521877   
    8531878    def __init__(self):
     1879        """
     1880        TEST::
     1881
     1882            sage: from sage.categories.pushout import FractionField
     1883            sage: F = FractionField()
     1884            sage: F
     1885            FractionField
     1886            sage: F(ZZ['t'])
     1887            Fraction Field of Univariate Polynomial Ring in t over Integer Ring
     1888        """
    8541889        Functor.__init__(self, Rings(), Fields())
     1890
    8551891    def _apply_functor(self, R):
     1892        """
     1893        Apply the functor to an object of ``self``'s domain.
     1894       
     1895        TEST::
     1896
     1897            sage: F = QQ.construction()[0]
     1898            sage: F(GF(5)['t'])      # indirect doctest
     1899            Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5
     1900        """
    8561901        return R.fraction_field()
    8571902       
    858    
    859 class LocalizationFunctor(ConstructionFunctor):
    860    
    861     rank = 6
    862    
    863     def __init__(self, t):
    864         Functor.__init__(self, Rings(), Rings())
    865         self.t = t
    866     def _apply_functor(self, R):
    867         return R.localize(t)
    868     def __cmp__(self, other):
    869         c = cmp(type(self), type(other))
    870         if c == 0:
    871             c = cmp(self.t, other.t)
    872         return c
    873    
     1903
     1904# This isn't used anywhere in Sage, and so I remove it (Simon King, 2010-05)
     1905#
     1906#class LocalizationFunctor(ConstructionFunctor):
     1907#   
     1908#    rank = 6
     1909#   
     1910#    def __init__(self, t):
     1911#        Functor.__init__(self, Rings(), Rings())
     1912#        self.t = t
     1913#    def _apply_functor(self, R):
     1914#        return R.localize(t)
     1915#    def __cmp__(self, other):
     1916#        c = cmp(type(self), type(other))
     1917#        if c == 0:
     1918#            c = cmp(self.t, other.t)
     1919#        return c
    8741920   
    8751921class CompletionFunctor(ConstructionFunctor):
    876    
     1922    """
     1923    Completion of a ring with respect to a given prime (including infinity).
     1924
     1925    EXAMPLES::
     1926
     1927        sage: R = Zp(5)
     1928        sage: R
     1929        5-adic Ring with capped relative precision 20
     1930        sage: F1 = R.construction()[0]
     1931        sage: F1
     1932        Completion[5]
     1933        sage: F1(ZZ) is R
     1934        True
     1935        sage: F1(QQ)
     1936        5-adic Field with capped relative precision 20
     1937        sage: F2 = RR.construction()[0]
     1938        sage: F2
     1939        Completion[+Infinity]
     1940        sage: F2(QQ) is RR
     1941        True
     1942        sage: P.<x> = ZZ[]
     1943        sage: Px = P.completion(x) # currently the only implemented completion of P
     1944        sage: Px
     1945        Power Series Ring in x over Integer Ring
     1946        sage: F3 = Px.construction()[0]
     1947        sage: F3(GF(3)['x'])
     1948        Power Series Ring in x over Finite Field of size 3
     1949
     1950    TEST::
     1951
     1952        sage: R1.<a> = Zp(5,prec=20)[]
     1953        sage: R2 = Qp(5,prec=40)
     1954        sage: R2(1) + a
     1955        (1 + O(5^20))*a + (1 + O(5^40))
     1956        sage: 1/2 + a
     1957        (1 + O(5^20))*a + (3 + 2*5 + 2*5^2 + 2*5^3 + 2*5^4 + 2*5^5 + 2*5^6 + 2*5^7 + 2*5^8 + 2*5^9 + 2*5^10 + 2*5^11 + 2*5^12 + 2*5^13 + 2*5^14 + 2*5^15 + 2*5^16 + 2*5^17 + 2*5^18 + 2*5^19 + O(5^20))
     1958
     1959    """
    8771960    rank = 4
    878    
     1961
    8791962    def __init__(self, p, prec, extras=None):
     1963        """
     1964        INPUT:
     1965
     1966        - ``p``: A prime number, the generator of a univariate polynomial ring, or ``+Infinity``
     1967        - ``prec``: an integer, yielding the precision in bits. Note that
     1968          if ``p`` is prime then the ``prec`` is the *capped* precision,
     1969          while it is the *set* precision if ``p`` is ``+Infinity``.
     1970        - ``extras`` (optional dictionary): Information on how to print elements, etc.
     1971
     1972        TESTS::
     1973
     1974            sage: from sage.categories.pushout import CompletionFunctor
     1975            sage: F1 = CompletionFunctor(5,100)
     1976            sage: F1(QQ)
     1977            5-adic Field with capped relative precision 100
     1978            sage: F1(ZZ)
     1979            5-adic Ring with capped relative precision 100
     1980            sage: F2 = RR.construction()[0]
     1981            sage: F2
     1982            Completion[+Infinity]
     1983            sage: F2.extras
     1984            {'sci_not': False, 'rnd': 'RNDN'}
     1985
     1986        """
    8801987        Functor.__init__(self, Rings(), Rings())
    8811988        self.p = p
    8821989        self.prec = prec
    8831990        self.extras = extras
     1991
     1992    def __str__(self):
     1993        """
     1994        TEST::
     1995
     1996            sage: Zp(7).construction()  # indirect doctest
     1997            (Completion[7], Integer Ring)
     1998        """
     1999        return 'Completion[%s]'%repr(self.p)
     2000
    8842001    def _apply_functor(self, R):
    885         return R.completion(self.p, self.prec, self.extras)
     2002        """
     2003        Apply the functor to an object of ``self``'s domain.
     2004       
     2005        TEST::
     2006
     2007            sage: R = Zp(5)
     2008            sage: F1 = R.construction()[0]
     2009            sage: F1(ZZ) is R  # indirect doctest
     2010            True
     2011            sage: F1(QQ)
     2012            5-adic Field with capped relative precision 20
     2013
     2014        """
     2015        try:
     2016            if self.extras is None:
     2017                try:
     2018                    return R.completion(self.p, self.prec)
     2019                except TypeError:
     2020                    return R.completion(self.p, self.prec, {})
     2021            return R.completion(self.p, self.prec, self.extras)
     2022        except (NotImplementedError,AttributeError):
     2023            if R.construction() is None:
     2024                raise NotImplementedError, "Completion is not implemented for %s"%R.__class__
     2025            F, BR = R.construction()
     2026            M = self.merge(F) or F.merge(self)
     2027            if M is not None:
     2028                return M(BR)
     2029            if self.commutes(F) or F.commutes(self):
     2030                return F(self(BR))
     2031            raise NotImplementedError, "Don't know how to apply %s to %s"%(repr(self),repr(R))
     2032
    8862033    def __cmp__(self, other):
     2034        """
     2035        NOTE:
     2036
     2037        Only the prime used in the completion is relevant to comparison
     2038        of Completion functors, although the resulting rings also take
     2039        the precision into account.
     2040
     2041        TEST::
     2042
     2043            sage: R1 = Zp(5,prec=30)
     2044            sage: R2 = Zp(5,prec=40)
     2045            sage: F1 = R1.construction()[0]
     2046            sage: F2 = R2.construction()[0]
     2047            sage: F1 == loads(dumps(F1))    # indirect doctest
     2048            True
     2049            sage: F1==F2
     2050            True
     2051            sage: F1(QQ)==F2(QQ)
     2052            False
     2053            sage: R3 = Zp(7)
     2054            sage: F3 = R3.construction()[0]
     2055            sage: F1==F3
     2056            False
     2057        """
    8872058        c = cmp(type(self), type(other))
    8882059        if c == 0:
    8892060            c = cmp(self.p, other.p)
    8902061        return c
     2062
    8912063    def merge(self, other):
     2064        """
     2065        Two Completion functors are merged, if they are equal. If the precisions of
     2066        both functors coincide, then a Completion functor is returned that results
     2067        from updating the ``extras`` dictionary of ``self`` by ``other.extras``.
     2068        Otherwise, if the completion is at infinity then merging does not increase
     2069        the set precision, and if the completion is at a finite prime, merging
     2070        does not decrease the capped precision.
     2071
     2072        EXAMPLE::
     2073
     2074            sage: R1.<a> = Zp(5,prec=20)[]
     2075            sage: R2 = Qp(5,prec=40)
     2076            sage: R2(1)+a         # indirect doctest
     2077            (1 + O(5^20))*a + (1 + O(5^40))
     2078            sage: R3 = RealField(30)
     2079            sage: R4 = RealField(50)
     2080            sage: R3(1) + R4(1)   # indirect doctest
     2081            2.0000000
     2082            sage: (R3(1) + R4(1)).parent()
     2083            Real Field with 30 bits of precision
     2084
     2085        """
     2086        if self!=other:
     2087            return None
    8922088        if self.p == other.p:
     2089            from sage.all import Infinity
    8932090            if self.prec == other.prec:
    8942091                extras = self.extras.copy()
    8952092                extras.update(other.extras)
    8962093                return CompletionFunctor(self.p, self.prec, extras)
    897             elif self.prec < other.prec:
     2094            elif (self.p==Infinity and self.prec<other.prec) or (self.p<Infinity and self.prec>other.prec):
    8982095                return self
    8992096            else: # self.prec > other.prec
    9002097                return other
    9012098        else:
    9022099            return None
    903    
     2100##   Completion has a lower rank than FractionField
     2101##   and is thus applied first. However, fact is that
     2102##   both commute. This is used in the call method,
     2103##   since some fraction fields have no completion method
     2104##   implemented.
     2105
     2106    def commutes(self,other):
     2107        """
     2108        Completion commutes with fraction fields.
     2109
     2110        EXAMPLE::
     2111
     2112            sage: F1 = Qp(5).construction()[0]
     2113            sage: F2 = QQ.construction()[0]
     2114            sage: F1.commutes(F2)
     2115            True
     2116
     2117        TEST:
     2118
     2119        The fraction field ``R`` in the example below has no completion
     2120        method. But completion commutes with the fraction field functor,
     2121        and so it is tried internally whether applying the construction
     2122        functors in opposite order works. It does::
     2123
     2124            sage: P.<x> = ZZ[]
     2125            sage: C = P.completion(x).construction()[0]
     2126            sage: R = FractionField(P)
     2127            sage: hasattr(R,'completion')
     2128            False
     2129            sage: C(R) is Frac(C(P))
     2130            True
     2131            sage: F = R.construction()[0]
     2132            sage: (C*F)(ZZ['x']) is (F*C)(ZZ['x'])
     2133            True
     2134
     2135        """
     2136        return isinstance(other,(FractionField,CompletionFunctor))
    9042137   
    9052138class QuotientFunctor(ConstructionFunctor):
    906    
     2139    """
     2140    Construction functor for quotient rings.
     2141
     2142    NOTE:
     2143
     2144    The functor keeps track of variable names.
     2145
     2146    EXAMPLE::
     2147
     2148        sage: P.<x,y> = ZZ[]
     2149        sage: Q = P.quo([x^2+y^2]*P)
     2150        sage: F = Q.construction()[0]
     2151        sage: F(QQ['x','y'])
     2152        Quotient of Multivariate Polynomial Ring in x, y over Rational Field by the ideal (x^2 + y^2)
     2153        sage: F(QQ['x','y']) == QQ['x','y'].quo([x^2+y^2]*QQ['x','y'])
     2154        True
     2155        sage: F(QQ['x','y','z'])
     2156        Traceback (most recent call last):
     2157        ...
     2158        CoercionException: Can not apply this quotient functor to Multivariate Polynomial Ring in x, y, z over Rational Field
     2159        sage: F(QQ['y','z'])
     2160        Traceback (most recent call last):
     2161        ...
     2162        TypeError: not a constant polynomial
     2163    """
    9072164    rank = 7
    9082165   
    909     def __init__(self, I, as_field=False):
     2166    def __init__(self, I, names=None, as_field=False):
     2167        """
     2168        INPUT:
     2169
     2170        - ``I``, an ideal (the modulus)
     2171        - ``names`` (optional string or list of strings), the names for the quotient ring generators
     2172        - ``as_field`` (optional bool, default false), return the quotient ring as field (if available).
     2173
     2174        TESTS::
     2175
     2176            sage: from sage.categories.pushout import QuotientFunctor
     2177            sage: P.<t> = ZZ[]
     2178            sage: F = QuotientFunctor([5+t^2]*P)
     2179            sage: F(P)
     2180            Univariate Quotient Polynomial Ring in tbar over Integer Ring with modulus t^2 + 5
     2181            sage: F(QQ['t'])
     2182            Univariate Quotient Polynomial Ring in tbar over Rational Field with modulus t^2 + 5
     2183            sage: F = QuotientFunctor([5+t^2]*P,names='s')
     2184            sage: F(P)
     2185            Univariate Quotient Polynomial Ring in s over Integer Ring with modulus t^2 + 5
     2186            sage: F(QQ['t'])
     2187            Univariate Quotient Polynomial Ring in s over Rational Field with modulus t^2 + 5
     2188            sage: F = QuotientFunctor([5]*ZZ,as_field=True)
     2189            sage: F(ZZ)
     2190            Finite Field of size 5
     2191            sage: F = QuotientFunctor([5]*ZZ)
     2192            sage: F(ZZ)
     2193            Ring of integers modulo 5
     2194
     2195        """
    9102196        Functor.__init__(self, Rings(), Rings()) # much more general...
    9112197        self.I = I
     2198        if names is None:
     2199            self.names = None
     2200        elif isinstance(names, basestring):
     2201            self.names = (names,)
     2202        else:
     2203            self.names = tuple(names)
    9122204        self.as_field = as_field
     2205
    9132206    def _apply_functor(self, R):
     2207        """
     2208        Apply the functor to an object of ``self``'s domain.
     2209       
     2210        TESTS::
     2211
     2212            sage: P.<x,y> = ZZ[]
     2213            sage: Q = P.quo([2+x^2,3*x+y^2])
     2214            sage: F = Q.construction()[0]; F
     2215            QuotientFunctor
     2216            sage: F(QQ['x','y'])     # indirect doctest
     2217            Quotient of Multivariate Polynomial Ring in x, y over Rational Field by the ideal (x^2 + 2, y^2 + 3*x)
     2218
     2219        Note that the ``quo()`` method of a field returns the integer zero.
     2220        The quotient construction functor, when applied to a field, returns
     2221        the trivial ring::
     2222
     2223            sage: F = ZZ.quo([5]*ZZ).construction()[0]
     2224            sage: F(QQ) is Integers(1)
     2225            True
     2226            sage: QQ.quo(5) is int(0)
     2227            True
     2228
     2229        """
    9142230        I = self.I
     2231        from sage.all import QQ
     2232        if not I.is_zero():
     2233            from sage.rings.field import is_Field
     2234            if is_Field(R):
     2235                from sage.all import Integers
     2236                return Integers(1)
    9152237        if I.ring() != R:
    916             I.base_extend(R)
    917         Q = R.quo(I)
     2238            if I.ring().has_coerce_map_from(R):
     2239                R = I.ring()
     2240            else:
     2241                R = pushout(R,I.ring().base_ring())
     2242                I = [R(1)*t for t in I.gens()]*R
     2243        try:
     2244            Q = R.quo(I,names=self.names)
     2245        except IndexError: # That may happen!
     2246            raise CoercionException, "Can not apply this quotient functor to %s"%R
    9182247        if self.as_field and hasattr(Q, 'field'):
    9192248            Q = Q.field()
    9202249        return Q
     2250
    9212251    def __cmp__(self, other):
     2252        """
     2253        The types, the names and the moduli are compared.
     2254
     2255        TESTS::
     2256
     2257            sage: P.<x> = QQ[]
     2258            sage: F = P.quo([(x^2+1)^2*(x^2-3),(x^2+1)^2*(x^5+3)]).construction()[0]
     2259            sage: F == loads(dumps(F))
     2260            True
     2261            sage: P2.<x,y> = QQ[]
     2262            sage: F == P2.quo([(x^2+1)^2*(x^2-3),(x^2+1)^2*(x^5+3)]).construction()[0]
     2263            False
     2264            sage: P3.<x> = ZZ[]
     2265            sage: F == P3.quo([(x^2+1)^2*(x^2-3),(x^2+1)^2*(x^5+3)]).construction()[0]
     2266            True
     2267        """
    9222268        c = cmp(type(self), type(other))
    9232269        if c == 0:
     2270            c = cmp(self.names, other.names)
     2271        if c == 0:
    9242272            c = cmp(self.I, other.I)
    9252273        return c
     2274
    9262275    def merge(self, other):
     2276        """
     2277        Two quotient functors with coinciding names are merged by taking the gcd of their moduli.
     2278
     2279        EXAMPLE::
     2280
     2281            sage: P.<x> = QQ[]
     2282            sage: Q1 = P.quo([(x^2+1)^2*(x^2-3)])
     2283            sage: Q2 = P.quo([(x^2+1)^2*(x^5+3)])
     2284            sage: from sage.categories.pushout import pushout
     2285            sage: pushout(Q1,Q2)    # indirect doctest
     2286            Univariate Quotient Polynomial Ring in xbar over Rational Field with modulus x^4 + 2*x^2 + 1
     2287
     2288        The following was fixed in trac ticket #8800::
     2289
     2290            sage: pushout(GF(5), Integers(5))
     2291            Finite Field of size 5
     2292
     2293        """
     2294        if type(self)!=type(other):
     2295            return None
     2296        if self.names != other.names:
     2297            return None
    9272298        if self == other:
    928             return self
     2299            if self.as_field == other.as_field:
     2300                return self
     2301            return QuotientFunctor(self.I, names=self.names, as_field=True) # one of them yields a field!
    9292302        try:
    9302303            gcd = self.I + other.I
    9312304        except (TypeError, NotImplementedError):
    932             return None
     2305            try:
     2306                gcd = self.I.gcd(other.I)
     2307            except (TypeError, NotImplementedError):
     2308                return None
    9332309        if gcd.is_trivial() and not gcd.is_zero():
    9342310            # quotient by gcd would result in the trivial ring/group/...
    9352311            # Rather than create the zero ring, we claim they can't be merged
    9362312            # TODO: Perhaps this should be detected at a higher level...
    9372313            raise TypeError, "Trivial quotient intersection."
    938         return QuotientFunctor(gcd)
     2314        # GF(p) has a coercion from Integers(p). Hence, merging should
     2315        # yield a field if either self or other yields a field.
     2316        return QuotientFunctor(gcd, names=self.names, as_field=self.as_field or other.as_field)
    9392317
    9402318class AlgebraicExtensionFunctor(ConstructionFunctor):
    941    
     2319    """
     2320    Algebraic extension (univariate polynomial ring modulo principal ideal).
     2321
     2322    EXAMPLE::
     2323
     2324        sage: K.<a> = NumberField(x^3+x^2+1)
     2325        sage: F = K.construction()[0]
     2326        sage: F(ZZ['t'])
     2327        Univariate Quotient Polynomial Ring in a over Univariate Polynomial Ring in t over Integer Ring with modulus a^3 + a^2 + 1
     2328
     2329    Note that, even if a field is algebraically closed, the algebraic
     2330    extension will be constructed as the quotient of a univariate
     2331    polynomial ring::
     2332
     2333        sage: F(CC)
     2334        Univariate Quotient Polynomial Ring in a over Complex Field with 53 bits of precision with modulus a^3 + a^2 + 1.00000000000000
     2335        sage: F(RR)
     2336        Univariate Quotient Polynomial Ring in a over Real Field with 53 bits of precision with modulus a^3 + a^2 + 1.00000000000000
     2337
     2338    Note that the construction functor of a number field applied to
     2339    the integers returns an order (not necessarily maximal) of that
     2340    field, similar to the behaviour of ``ZZ.extension(...)``::
     2341
     2342        sage: F(ZZ)
     2343        Order in Number Field in a with defining polynomial x^3 + x^2 + 1
     2344
     2345    This also holds for non-absolute number fields::
     2346
     2347        sage: K.<a,b> = NumberField([x^3+x^2+1,x^2+x+1])
     2348        sage: F = K.construction()[0]
     2349        sage: O = F(ZZ); O
     2350        Relative Order in Number Field in a with defining polynomial x^3 + x^2 + 1 over its base field
     2351
     2352    Unfortunately, the relative number field is not a unique parent::
     2353
     2354        sage: O.ambient() is K
     2355        False
     2356        sage: O.ambient() == K
     2357        True
     2358
     2359    """
    9422360    rank = 3
    9432361   
    944     def __init__(self, poly, name, elt=None, embedding=None):
     2362    def __init__(self, polys, names, embeddings, cyclotomic=None):
     2363        """
     2364        INPUT:
     2365
     2366        - ``polys``: a list of polynomials
     2367        - ``names``: a list of strings of the same length as the
     2368          list ``polys``
     2369        - ``embeddings``: a list of approximate complex values,
     2370          determining an embedding of the generators into the
     2371          complex field, or ``None`` for each generator whose
     2372          embedding is not prescribed.
     2373        - ``cyclotomic``: optional integer. If it is provided,
     2374          application of the functor to the rational field yields
     2375          a cyclotomic field, rather than just a number field.
     2376
     2377        REMARK:
     2378
     2379        Currently, an embedding can only be provided for the last
     2380        generator, and only when the construction functor is applied
     2381        to the rational field. There will be no error when constructing
     2382        the functor, but when applying it.
     2383
     2384        TESTS::
     2385
     2386            sage: from sage.categories.pushout import AlgebraicExtensionFunctor
     2387            sage: P.<x> = ZZ[]
     2388            sage: F1 = AlgebraicExtensionFunctor([x^3 - x^2 + 1], ['a'], [None])
     2389            sage: F2 = AlgebraicExtensionFunctor([x^3 - x^2 + 1], ['a'], [0])
     2390            sage: F1==F2
     2391            False
     2392            sage: F1(QQ)
     2393            Number Field in a with defining polynomial x^3 - x^2 + 1
     2394            sage: F1(QQ).coerce_embedding()
     2395            sage: F2(QQ).coerce_embedding()
     2396            Generic morphism:
     2397              From: Number Field in a with defining polynomial x^3 - x^2 + 1
     2398              To:   Real Lazy Field
     2399              Defn: a -> -0.7548776662466928?
     2400            sage: F1(QQ)==F2(QQ)
     2401            False
     2402            sage: F1(GF(5))
     2403            Univariate Quotient Polynomial Ring in a over Finite Field of size 5 with modulus a^3 + 4*a^2 + 1
     2404            sage: F2(GF(5))
     2405            Traceback (most recent call last):
     2406            ...
     2407            NotImplementedError: ring extension with prescripted embedding is not implemented
     2408
     2409        When applying a number field constructor to the ring of
     2410        integers, an order (not necessarily maximal) of that field is
     2411        returned, similar to the behaviour of ``ZZ.extension``::
     2412
     2413            sage: F1(ZZ)
     2414            Order in Number Field in a with defining polynomial x^3 - x^2 + 1
     2415
     2416        The cyclotomic fields form a special case of number fields
     2417        with prescribed embeddings::
     2418
     2419            sage: C = CyclotomicField(8)
     2420            sage: F,R = C.construction()
     2421            sage: F
     2422            AlgebraicExtensionFunctor
     2423            sage: R
     2424            Rational Field
     2425            sage: F(R)
     2426            Cyclotomic Field of order 8 and degree 4
     2427            sage: F(ZZ)
     2428            Maximal Order in Cyclotomic Field of order 8 and degree 4
     2429
     2430        """
    9452431        Functor.__init__(self, Rings(), Rings())
    946         self.poly = poly
    947         self.name = name
    948         self.elt = elt
    949         self.embedding = embedding
     2432        if not (isinstance(polys,(list,tuple)) and isinstance(names,(list,tuple)) and isinstance(embeddings,(list,tuple))):
     2433            raise ValueError, "Arguments must be lists or tuples"
     2434        if not (len(names)==len(polys)==len(embeddings)):
     2435            raise ValueError, "The three arguments must be of the same length"
     2436        self.polys = list(polys)
     2437        self.names = list(names)
     2438        self.embeddings = list(embeddings)
     2439        self.cyclotomic = int(cyclotomic) if cyclotomic is not None else None
     2440
    9502441    def _apply_functor(self, R):
    951         return R.extension(self.poly, self.name, embedding=self.embedding)
     2442        """
     2443        Apply the functor to an object of ``self``'s domain.
     2444       
     2445        TESTS::
     2446
     2447            sage: K.<a>=NumberField(x^3+x^2+1)
     2448            sage: F = K.construction()[0]
     2449            sage: F(ZZ)       # indirect doctest
     2450            Order in Number Field in a with defining polynomial x^3 + x^2 + 1
     2451            sage: F(ZZ['t'])  # indirect doctest
     2452            Univariate Quotient Polynomial Ring in a over Univariate Polynomial Ring in t over Integer Ring with modulus a^3 + a^2 + 1
     2453            sage: F(RR)       # indirect doctest
     2454            Univariate Quotient Polynomial Ring in a over Real Field with 53 bits of precision with modulus a^3 + a^2 + 1.00000000000000
     2455        """
     2456        from sage.all import QQ, ZZ, CyclotomicField
     2457        if self.cyclotomic:
     2458            if R==QQ:
     2459                return CyclotomicField(self.cyclotomic)
     2460            if R==ZZ:
     2461                return CyclotomicField(self.cyclotomic).maximal_order()
     2462        if len(self.polys) == 1:
     2463            return R.extension(self.polys[0], self.names[0], embedding=self.embeddings[0])
     2464        return R.extension(self.polys, self.names, embedding=self.embeddings)
     2465
    9522466    def __cmp__(self, other):
     2467        """
     2468        TEST::
     2469
     2470            sage: K.<a>=NumberField(x^3+x^2+1)
     2471            sage: F = K.construction()[0]
     2472            sage: F == loads(dumps(F))
     2473            True
     2474        """
    9532475        c = cmp(type(self), type(other))
    9542476        if c == 0:
    955             c = cmp(self.poly, other.poly)
     2477            c = cmp(self.polys, other.polys)
    9562478        if c == 0:
    957             c = cmp(self.embedding, other.embedding)
     2479            c = cmp(self.embeddings, other.embeddings)
    9582480        return c
    9592481
     2482    def merge(self,other):
     2483        """
     2484        Merging with another :class:`AlgebraicExtensionFunctor`.
     2485
     2486        INPUT:
     2487
     2488        ``other`` -- Construction Functor.
     2489
     2490        OUTPUT:
     2491
     2492        - If ``self==other``, ``self`` is returned.
     2493        - If ``self`` and ``other`` are simple extensions
     2494          and both provide an embedding, then it is tested
     2495          whether one of the number fields provided by
     2496          the functors coerces into the other; the functor
     2497          associated with the target of the coercion is
     2498          returned. Otherwise, the construction functor
     2499          associated with the pushout of the codomains
     2500          of the two embeddings is returned, provided that
     2501          it is a number field.
     2502        - Otherwise, None is returned.
     2503         
     2504        REMARK:
     2505
     2506        Algebraic extension with embeddings currently only
     2507        works when applied to the rational field. This is
     2508        why we use the admittedly strange rule above for
     2509        merging.
     2510
     2511        TESTS::
     2512
     2513            sage: P.<x> = QQ[]
     2514            sage: L.<b> = NumberField(x^8-x^4+1, embedding=CDF.0)
     2515            sage: M1.<c1> = NumberField(x^2+x+1, embedding=b^4-1)
     2516            sage: M2.<c2> = NumberField(x^2+1, embedding=-b^6)
     2517            sage: M1.coerce_map_from(M2)
     2518            sage: M2.coerce_map_from(M1)
     2519            sage: c1+c2; parent(c1+c2)    #indirect doctest
     2520            -b^6 + b^4 - 1
     2521            Number Field in b with defining polynomial x^8 - x^4 + 1
     2522            sage: from sage.categories.pushout import pushout
     2523            sage: pushout(M1['x'],M2['x'])
     2524            Univariate Polynomial Ring in x over Number Field in b with defining polynomial x^8 - x^4 + 1
     2525
     2526        In the previous example, the number field ``L`` becomes the pushout
     2527        of ``M1`` and ``M2`` since both are provided with an embedding into
     2528        ``L``, *and* since ``L`` is a number field. If two number fields
     2529        are embedded into a field that is not a numberfield, no merging
     2530        occurs::
     2531
     2532            sage: K.<a> = NumberField(x^3-2, embedding=CDF(1/2*I*2^(1/3)*sqrt(3) - 1/2*2^(1/3)))
     2533            sage: L.<b> = NumberField(x^6-2, embedding=1.1)
     2534            sage: L.coerce_map_from(K)
     2535            sage: K.coerce_map_from(L)
     2536            sage: pushout(K,L)
     2537            Traceback (most recent call last):
     2538            ...
     2539            CoercionException: ('Ambiguous Base Extension', Number Field in a with defining polynomial x^3 - 2, Number Field in b with defining polynomial x^6 - 2)
     2540
     2541        """
     2542        if not isinstance(other,AlgebraicExtensionFunctor):
     2543            return None
     2544        if self == other:
     2545            return self
     2546        # This method is supposed to be used in pushout(),
     2547        # *after* expanding the functors. Hence, we can
     2548        # assume that both functors have a single variable.
     2549        # But for being on the safe side...:
     2550        if len(self.names)!=1 or len(other.names)!=1:
     2551            return None
     2552##       We don't accept a forgetful coercion, since, together
     2553##       with bidirectional coercions between two embedded
     2554##       number fields, it would yield to contradictions in
     2555##       the coercion system.
     2556#        if self.polys==other.polys and self.names==other.names:
     2557#            # We have a forgetful functor:
     2558#            if self.embeddings==[None]:
     2559#                return self
     2560#            if  other.embeddings==[None]:
     2561#                return other
     2562        # ... or we may use the given embeddings:
     2563        if self.embeddings!=[None] and other.embeddings!=[None]:
     2564            from sage.all import QQ
     2565            KS = self(QQ)
     2566            KO = other(QQ)
     2567            if KS.has_coerce_map_from(KO):
     2568                return self
     2569            if KO.has_coerce_map_from(KS):
     2570                return other
     2571            # nothing else helps, hence, we move to the pushout of the codomains of the embeddings
     2572            try:
     2573                P = pushout(self.embeddings[0].parent(), other.embeddings[0].parent())
     2574                from sage.rings.number_field.number_field import is_NumberField
     2575                if is_NumberField(P):
     2576                    return P.construction()[0]
     2577            except CoercionException:
     2578                return None
     2579
     2580    def __mul__(self, other):
     2581        """
     2582        Compose construction functors to a composit construction functor, unless one of them is the identity.
     2583
     2584        NOTE:
     2585
     2586        The product is in functorial notation, i.e., when applying the product to an object
     2587        then the second factor is applied first.
     2588
     2589        TESTS::
     2590
     2591            sage: P.<x> = QQ[]
     2592            sage: K.<a> = NumberField(x^3-5,embedding=0)
     2593            sage: L.<b> = K.extension(x^2+a)
     2594            sage: F,R = L.construction()
     2595            sage: prod(F.expand())(R) == L #indirect doctest
     2596            True
     2597
     2598        """
     2599        if isinstance(other,IdentityConstructionFunctor):
     2600            return self
     2601        if isinstance(other, AlgebraicExtensionFunctor):
     2602            if set(self.names).intersection(other.names):
     2603                raise CoercionException, "Overlapping names (%s,%s)" % (self.names, other.names)
     2604            return AlgebraicExtensionFunctor(self.polys+other.polys, self.names+other.names, self.embeddings+other.embeddings)
     2605        elif isinstance(other, CompositeConstructionFunctor) \
     2606              and isinstance(other.all[-1], AlgebraicExtensionFunctor):
     2607            return CompositeConstructionFunctor(other.all[:-1], self * other.all[-1])
     2608        else:
     2609            return CompositeConstructionFunctor(other, self)
     2610
     2611    def expand(self):
     2612        """
     2613        Decompose the functor `F` into sub-functors, whose product returns `F`.
     2614
     2615        EXAMPLES::
     2616
     2617            sage: P.<x> = QQ[]
     2618            sage: K.<a> = NumberField(x^3-5,embedding=0)
     2619            sage: L.<b> = K.extension(x^2+a)
     2620            sage: F,R = L.construction()
     2621            sage: prod(F.expand())(R) == L
     2622            True
     2623            sage: K = NumberField([x^2-2, x^2-3],'a')
     2624            sage: F, R = K.construction()
     2625            sage: F
     2626            AlgebraicExtensionFunctor
     2627            sage: L = F.expand(); L
     2628            [AlgebraicExtensionFunctor, AlgebraicExtensionFunctor]
     2629            sage: L[-1](QQ)
     2630            Number Field in a1 with defining polynomial x^2 - 3
     2631        """
     2632        if len(self.polys)==1:
     2633            return [self]
     2634        return [AlgebraicExtensionFunctor([self.polys[i]], [self.names[i]], [self.embeddings[i]]) for i in range(len(self.polys))]
     2635
    9602636class AlgebraicClosureFunctor(ConstructionFunctor):
    961 
     2637    """
     2638    Algebraic Closure.
     2639
     2640    EXAMPLE::
     2641
     2642        sage: F = CDF.construction()[0]
     2643        sage: F(QQ)
     2644        Algebraic Field
     2645        sage: F(RR)
     2646        Complex Field with 53 bits of precision
     2647        sage: F(F(QQ)) is F(QQ)
     2648        True
     2649
     2650    """
    9622651    rank = 3
    9632652
    9642653    def __init__(self):
     2654        """
     2655        TEST::
     2656
     2657            sage: from sage.categories.pushout import AlgebraicClosureFunctor
     2658            sage: F = AlgebraicClosureFunctor()
     2659            sage: F(QQ)
     2660            Algebraic Field
     2661            sage: F(RR)
     2662            Complex Field with 53 bits of precision
     2663            sage: F == loads(dumps(F))
     2664            True
     2665
     2666        """
    9652667        Functor.__init__(self, Rings(), Rings())
     2668
    9662669    def _apply_functor(self, R):
     2670        """
     2671        Apply the functor to an object of ``self``'s domain.
     2672       
     2673        TEST::
     2674
     2675            sage: F = CDF.construction()[0]
     2676            sage: F(QQ)       # indirect doctest
     2677            Algebraic Field
     2678        """
     2679        if hasattr(R,'construction'):
     2680            c = R.construction()
     2681            if c is not None and c[0]==self:
     2682                return R
    9672683        return R.algebraic_closure()
     2684
    9682685    def merge(self, other):
    969         # Algebraic Closure subsumes Algebraic Extension
    970         return self
     2686        """
     2687        Mathematically, Algebraic Closure subsumes Algebraic Extension.
     2688        However, it seems that people do want to work with algebraic
     2689        extensions of ``RR``. Therefore, we dont merge with algebraic extension.
     2690
     2691        TEST::
     2692
     2693            sage: K.<a>=NumberField(x^3+x^2+1)
     2694            sage: CDF.construction()[0].merge(K.construction()[0]) is None
     2695            True
     2696            sage: CDF.construction()[0].merge(CDF.construction()[0])
     2697            AlgebraicClosureFunctor
     2698
     2699        """
     2700        if self==other:
     2701            return self
     2702        return None
     2703        # Mathematically, Algebraic Closure subsumes Algebraic Extension.
     2704        # However, it seems that people do want to work with
     2705        # algebraic extensions of RR (namely RR/poly*RR). So, we don't do:
     2706        # if isinstance(other,AlgebraicExtensionFunctor):
     2707        #     return self
    9712708
    9722709class PermutationGroupFunctor(ConstructionFunctor):
    9732710
     
    9762713    def __init__(self, gens):
    9772714        """
    9782715        EXAMPLES::
    979            
     2716
    9802717            sage: from sage.categories.pushout import PermutationGroupFunctor
    9812718            sage: PF = PermutationGroupFunctor([PermutationGroupElement([(1,2)])]); PF
    9822719            PermutationGroupFunctor[(1,2)]
     
    9872724    def __repr__(self):
    9882725        """
    9892726        EXAMPLES::
    990        
     2727
    9912728            sage: P1 = PermutationGroup([[(1,2)]])
    9922729            sage: PF, P = P1.construction()
    9932730            sage: PF
    994             PermutationGroupFunctor[(1,2)]       
     2731            PermutationGroupFunctor[(1,2)]
    9952732        """
    9962733        return "PermutationGroupFunctor%s"%self.gens()
    9972734
    998     def _apply_functor(self, R):
     2735    def __call__(self, R):
    9992736        """
    10002737        EXAMPLES::
    10012738
     
    10172754            [(1,2)]
    10182755        """
    10192756        return self._gens
    1020    
     2757
    10212758    def merge(self, other):
    10222759        """
     2760        Merge ``self`` with another construction functor, or return None.
     2761       
    10232762        EXAMPLES::
    1024        
     2763
    10252764            sage: P1 = PermutationGroup([[(1,2)]])
    10262765            sage: PF1, P = P1.construction()
    10272766            sage: P2 = PermutationGroup([[(1,3)]])
     
    10322771        if self.__class__ != other.__class__:
    10332772            return None
    10342773        return PermutationGroupFunctor(self.gens() + other.gens())
    1035        
    1036 def BlackBoxConstructionFunctor(ConstructionFunctor):
    1037 
     2774
     2775class BlackBoxConstructionFunctor(ConstructionFunctor):
     2776    """
     2777    Construction functor obtained from any callable object.
     2778
     2779    EXAMPLES::
     2780
     2781        sage: from sage.categories.pushout import BlackBoxConstructionFunctor
     2782        sage: FG = BlackBoxConstructionFunctor(gap)
     2783        sage: FS = BlackBoxConstructionFunctor(singular)
     2784        sage: FG
     2785        BlackBoxConstructionFunctor
     2786        sage: FG(ZZ)
     2787        Integers
     2788        sage: FG(ZZ).parent()
     2789        Gap
     2790        sage: FS(QQ['t'])
     2791        //   characteristic : 0
     2792        //   number of vars : 1
     2793        //        block   1 : ordering lp
     2794        //                  : names    t
     2795        //        block   2 : ordering C
     2796        sage: FG == FS
     2797        False
     2798        sage: FG == loads(dumps(FG))
     2799        True
     2800    """
    10382801    rank = 100
    10392802
    10402803    def __init__(self, box):
     2804        """
     2805        TESTS::
     2806            sage: from sage.categories.pushout import BlackBoxConstructionFunctor
     2807            sage: FG = BlackBoxConstructionFunctor(gap)
     2808            sage: FM = BlackBoxConstructionFunctor(maxima)
     2809            sage: FM == FG
     2810            False
     2811            sage: FM == loads(dumps(FM))
     2812            True
     2813        """
     2814        ConstructionFunctor.__init__(self,Objects(),Objects())
    10412815        if not callable(box):
    10422816            raise TypeError, "input must be callable"
    10432817        self.box = box
     2818
    10442819    def _apply_functor(self, R):
    1045         return box(R)
     2820        """
     2821        Apply the functor to an object of ``self``'s domain.
     2822       
     2823        TESTS::
     2824
     2825            sage: from sage.categories.pushout import BlackBoxConstructionFunctor
     2826            sage: f = lambda x: x^2
     2827            sage: F = BlackBoxConstructionFunctor(f)
     2828            sage: F(ZZ)           # indirect doctest
     2829            Ambient free module of rank 2 over the principal ideal domain Integer Ring
     2830
     2831        """
     2832        return self.box(R)
     2833
    10462834    def __cmp__(self, other):
    1047         return self.box == other.box
    1048        
    1049        
     2835        """
     2836        TESTS::
     2837            sage: from sage.categories.pushout import BlackBoxConstructionFunctor
     2838            sage: FG = BlackBoxConstructionFunctor(gap)
     2839            sage: FM = BlackBoxConstructionFunctor(maxima)
     2840            sage: FM == FG       # indirect doctest
     2841            False
     2842            sage: FM == loads(dumps(FM))
     2843            True
     2844        """
     2845        c = cmp(type(self), type(other))
     2846        if c == 0:
     2847            c = cmp(self.box, other.box)
     2848        #return self.box == other.box
     2849        return c
     2850
    10502851def pushout(R, S):
    1051     """
     2852    r"""
    10522853    Given a pair of Objects R and S, try and construct a
    10532854    reasonable object $Y$ and return maps such that
    10542855    canonically $R \leftarrow Y \rightarrow S$.
    10552856   
    1056     ALGORITHM:
    1057        This incorporates the idea of functors discussed Sage Days 4.
    1058        Every object $R$ can be viewed as an initial object and
    1059        a series of functors (e.g. polynomial, quotient, extension,
    1060        completion, vector/matrix, etc.). Call the series of
    1061        increasingly-simple rings (with the associated functors)
    1062        the "tower" of $R$. The \code{construction} method is used to
    1063        create the tower.
    1064        
    1065        Given two objects $R$ and $S$, try and find a common initial
    1066        object $Z$. If the towers of $R$ and $S$ meet, let $Z$ be their
    1067        join. Otherwise, see if the top of one coerces naturally into
    1068        the other.
    1069        
    1070        Now we have an initial object and two \emph{ordered} lists of
    1071        functors to apply. We wish to merge these in an unambiguous order,
    1072        popping elements off the top of one or the other tower as we
    1073        apply them to $Z$.
    1074        
    1075        - If the functors are distinct types, there is an absolute ordering
    1076            given by the rank attribute. Use this.
    1077        - Otherwise:
    1078           - If the tops are equal, we (try to) merge them.
    1079           - If \emph{exactly} one occurs lower in the other tower
    1080               we may unambiguously apply the other (hoping for a later merge).
    1081           - If the tops commute, we can apply either first.
    1082           - Otherwise fail due to ambiguity.
     2857    ALGORITHM:
     2858   
     2859    This incorporates the idea of functors discussed Sage Days 4.
     2860    Every object $R$ can be viewed as an initial object and
     2861    a series of functors (e.g. polynomial, quotient, extension,
     2862    completion, vector/matrix, etc.). Call the series of
     2863    increasingly-simple rings (with the associated functors)
     2864    the "tower" of $R$. The \code{construction} method is used to
     2865    create the tower.
     2866
     2867    Given two objects $R$ and $S$, try and find a common initial
     2868    object $Z$. If the towers of $R$ and $S$ meet, let $Z$ be their
     2869    join. Otherwise, see if the top of one coerces naturally into
     2870    the other.
     2871
     2872    Now we have an initial object and two \emph{ordered} lists of
     2873    functors to apply. We wish to merge these in an unambiguous order,
     2874    popping elements off the top of one or the other tower as we
     2875    apply them to $Z$.
     2876
     2877    - If the functors are distinct types, there is an absolute ordering
     2878      given by the rank attribute. Use this.
     2879
     2880    - Otherwise:
     2881
     2882      - If the tops are equal, we (try to) merge them.
     2883
     2884      - If \emph{exactly} one occurs lower in the other tower
     2885        we may unambiguously apply the other (hoping for a later merge).
     2886
     2887      - If the tops commute, we can apply either first.
     2888
     2889      - Otherwise fail due to ambiguity.
    10832890             
    10842891    EXAMPLES:
    1085         Here our "towers" are $R = Complete_7(Frac(\Z)$ and $Frac(Poly_x(\Z))$, which give us $Frac(Poly_x(Complete_7(Frac(\Z)))$
    1086             sage: from sage.categories.pushout import pushout
    1087             sage: pushout(Qp(7), Frac(ZZ['x']))
    1088             Fraction Field of Univariate Polynomial Ring in x over 7-adic Field with capped relative precision 20
    1089            
    1090         Note we get the same thing with
    1091             sage: pushout(Zp(7), Frac(QQ['x']))
    1092             Fraction Field of Univariate Polynomial Ring in x over 7-adic Field with capped relative precision 20
    1093             sage: pushout(Zp(7)['x'], Frac(QQ['x']))
    1094             Fraction Field of Univariate Polynomial Ring in x over 7-adic Field with capped relative precision 20           
    1095 
    1096         Note that polynomial variable ordering must be unambiguously determined.
    1097             sage: pushout(ZZ['x,y,z'], QQ['w,z,t'])
    1098             Traceback (most recent call last):
    1099             ...
    1100             CoercionException: ('Ambiguous Base Extension', Multivariate Polynomial Ring in x, y, z over Integer Ring, Multivariate Polynomial Ring in w, z, t over Rational Field)
    1101             sage: pushout(ZZ['x,y,z'], QQ['w,x,z,t'])
    1102             Multivariate Polynomial Ring in w, x, y, z, t over Rational Field
    1103 
    1104         Some other examples
    1105             sage: pushout(Zp(7)['y'], Frac(QQ['t'])['x,y,z'])
    1106             Multivariate Polynomial Ring in x, y, z over Fraction Field of Univariate Polynomial Ring in t over 7-adic Field with capped relative precision 20
    1107             sage: pushout(ZZ['x,y,z'], Frac(ZZ['x'])['y'])
    1108             Multivariate Polynomial Ring in y, z over Fraction Field of Univariate Polynomial Ring in x over Integer Ring
    1109             sage: pushout(MatrixSpace(RDF, 2, 2), Frac(ZZ['x']))
    1110             Full MatrixSpace of 2 by 2 dense matrices over Fraction Field of Univariate Polynomial Ring in x over Real Double Field
    1111             sage: pushout(ZZ, MatrixSpace(ZZ[['x']], 3, 3))
    1112             Full MatrixSpace of 3 by 3 dense matrices over Power Series Ring in x over Integer Ring
    1113             sage: pushout(QQ['x,y'], ZZ[['x']])
    1114             Univariate Polynomial Ring in y over Power Series Ring in x over Rational Field
    1115             sage: pushout(Frac(ZZ['x']), QQ[['x']])
    1116             Laurent Series Ring in x over Rational Field
    1117 
    1118     AUTHORS:
    1119        -- Robert Bradshaw
     2892   
     2893    Here our "towers" are $R = Complete_7(Frac(\ZZ)$ and $Frac(Poly_x(\ZZ))$,
     2894    which give us $Frac(Poly_x(Complete_7(Frac(\ZZ)))$::
     2895
     2896        sage: from sage.categories.pushout import pushout
     2897        sage: pushout(Qp(7), Frac(ZZ['x']))
     2898        Fraction Field of Univariate Polynomial Ring in x over 7-adic Field with capped relative precision 20
     2899
     2900    Note we get the same thing with
     2901    ::
     2902   
     2903        sage: pushout(Zp(7), Frac(QQ['x']))
     2904        Fraction Field of Univariate Polynomial Ring in x over 7-adic Field with capped relative precision 20
     2905        sage: pushout(Zp(7)['x'], Frac(QQ['x']))
     2906        Fraction Field of Univariate Polynomial Ring in x over 7-adic Field with capped relative precision 20           
     2907
     2908    Note that polynomial variable ordering must be unambiguously determined.
     2909    ::
     2910   
     2911        sage: pushout(ZZ['x,y,z'], QQ['w,z,t'])
     2912        Traceback (most recent call last):
     2913        ...
     2914        CoercionException: ('Ambiguous Base Extension', Multivariate Polynomial Ring in x, y, z over Integer Ring, Multivariate Polynomial Ring in w, z, t over Rational Field)
     2915        sage: pushout(ZZ['x,y,z'], QQ['w,x,z,t'])
     2916        Multivariate Polynomial Ring in w, x, y, z, t over Rational Field
     2917
     2918    Some other examples::
     2919   
     2920        sage: pushout(Zp(7)['y'], Frac(QQ['t'])['x,y,z'])
     2921        Multivariate Polynomial Ring in x, y, z over Fraction Field of Univariate Polynomial Ring in t over 7-adic Field with capped relative precision 20
     2922        sage: pushout(ZZ['x,y,z'], Frac(ZZ['x'])['y'])
     2923        Multivariate Polynomial Ring in y, z over Fraction Field of Univariate Polynomial Ring in x over Integer Ring
     2924        sage: pushout(MatrixSpace(RDF, 2, 2), Frac(ZZ['x']))
     2925        Full MatrixSpace of 2 by 2 dense matrices over Fraction Field of Univariate Polynomial Ring in x over Real Double Field
     2926        sage: pushout(ZZ, MatrixSpace(ZZ[['x']], 3, 3))
     2927        Full MatrixSpace of 3 by 3 dense matrices over Power Series Ring in x over Integer Ring
     2928        sage: pushout(QQ['x,y'], ZZ[['x']])
     2929        Univariate Polynomial Ring in y over Power Series Ring in x over Rational Field
     2930        sage: pushout(Frac(ZZ['x']), QQ[['x']])
     2931        Laurent Series Ring in x over Rational Field
     2932
     2933    AUTHORS:
     2934   
     2935    -- Robert Bradshaw
    11202936    """
    11212937    if R is S or R == S:
    11222938        return R
     
    12183034                    elif Sc[-1] in Rc:
    12193035                        all = Rc.pop() * all
    12203036                    # If, perchance, the two functors commute, then we may do them in any order.
    1221                     elif Rc[-1].commutes(Sc[-1]):
     3037                    elif Rc[-1].commutes(Sc[-1]) or Sc[-1].commutes(Rc[-1]):
    12223038                        all = Sc.pop() * Rc.pop() * all
    12233039                    else:
    12243040                        # try and merge (default merge is failure for unequal functors)
     
    12443060
    12453061   
    12463062def pushout_lattice(R, S):
    1247     """
    1248     Given a pair of Objects R and S, try and construct a
     3063    r"""
     3064    Given a pair of Objects $R$ and $S$, try and construct a
    12493065    reasonable object $Y$ and return maps such that
    12503066    canonically $R \leftarrow Y \rightarrow S$.
    12513067   
    1252     ALGORITHM:
    1253        This is based on the model that arose from much discussion at Sage Days 4.
    1254        Going up the tower of constructions of $R$ and $S$ (e.g. the reals
    1255        come from the rationals come from the integers) try and find a
    1256        common parent, and then try and fill in a lattice with these
    1257        two towers as sides with the top as the common ancestor and
    1258        the bottom will be the desired ring.
     3068    ALGORITHM:
     3069   
     3070    This is based on the model that arose from much discussion at Sage Days 4.
     3071    Going up the tower of constructions of $R$ and $S$ (e.g. the reals
     3072    come from the rationals come from the integers) try and find a
     3073    common parent, and then try and fill in a lattice with these
     3074    two towers as sides with the top as the common ancestor and
     3075    the bottom will be the desired ring.
     3076
     3077    See the code for a specific worked-out example.
    12593078       
    1260        See the code for a specific worked-out example.
    1261        
    1262     EXAMPLES:
     3079    EXAMPLES::
     3080
    12633081        sage: from sage.categories.pushout import pushout_lattice
    12643082        sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x']))
    12653083        sage: A.codomain()
     
    12713089        Identity endomorphism of Full MatrixSpace of 3 by 3 dense matrices over Power Series Ring in x over Integer Ring
    12723090       
    12733091    AUTHOR:
    1274        -- Robert Bradshaw
     3092
     3093    - Robert Bradshaw
     3094
    12753095    """
    12763096    R_tower = construction_tower(R)
    12773097    S_tower = construction_tower(S)
     
    13573177                        lattice[i+1,j+1] = Rc[i](lattice[i,j+1])
    13583178                        Sc[j] = None # force us to use pre-applied Sc[i]
    13593179            except (AttributeError, NameError):
    1360                 print i, j
    1361                 pp(lattice)
     3180                # print i, j
     3181                # pp(lattice)
     3182                for i in range(100):
     3183                    for j in range(100):
     3184                        try:
     3185                            R = lattice[i,j]
     3186                            print i, j, R
     3187                        except KeyError:
     3188                            break
    13623189                raise CoercionException, "%s does not support %s" % (lattice[i,j], 'F')
    13633190           
    13643191    # If we are successful, we should have something that looks like this.
     
    13973224    return R_map, S_map
    13983225   
    13993226   
    1400 def pp(lattice):
     3227## def pp(lattice):
     3228##     """
     3229##     Used in debugging to print the current lattice.
     3230##     """
     3231##     for i in range(100):
     3232##         for j in range(100):
     3233##             try:
     3234##                 R = lattice[i,j]
     3235##                 print i, j, R
     3236##             except KeyError:
     3237##                 break
     3238
     3239def construction_tower(R):
    14013240    """
    1402     Used in debugging to print the current lattice.
     3241    An auxiliary function that is used in :func:`pushout` and :func:`pushout_lattice`.
     3242
     3243    INPUT:
     3244
     3245    An object
     3246
     3247    OUTPUT:
     3248
     3249    A constructive description of the object from scratch, by a list of pairs
     3250    of a construction functor and an object to which the construction functor
     3251    is to be applied. The first pair is formed by ``None`` and the given object.
     3252
     3253    EXAMPLE::
     3254
     3255        sage: from sage.categories.pushout import construction_tower
     3256        sage: construction_tower(MatrixSpace(FractionField(QQ['t']),2))
     3257        [(None, Full MatrixSpace of 2 by 2 dense matrices over Fraction Field of Univariate Polynomial Ring in t over Rational Field), (MatrixFunctor, Fraction Field of Univariate Polynomial Ring in t over Rational Field), (FractionField, Univariate Polynomial Ring in t over Rational Field), (Poly[t], Rational Field), (FractionField, Integer Ring)]
     3258
    14033259    """
    1404     for i in range(100):
    1405         for j in range(100):
    1406             try:
    1407                 R = lattice[i,j]
    1408                 print i, j, R
    1409             except KeyError:
    1410                 break
    1411 
    1412 def construction_tower(R):
    14133260    tower = [(None, R)]
    14143261    c = R.construction()
    14153262    while c is not None:
     
    14233270
    14243271
    14253272def type_to_parent(P):
     3273    """
     3274    An auxiliary function that is used in :func:`pushout`.
     3275
     3276    INPUT:
     3277
     3278    A type
     3279
     3280    OUTPUT:
     3281
     3282    A Sage parent structure corresponding to the given type
     3283
     3284    TEST::
     3285   
     3286        sage: from sage.categories.pushout import type_to_parent
     3287        sage: type_to_parent(int)
     3288        Integer Ring
     3289        sage: type_to_parent(float)
     3290        Real Double Field
     3291        sage: type_to_parent(complex)
     3292        Complex Double Field
     3293        sage: type_to_parent(list)
     3294        Traceback (most recent call last):
     3295        ...
     3296        TypeError: Not a scalar type.
     3297    """
    14263298    import sage.rings.all
    14273299    if P in [int, long]:
    14283300        return sage.rings.all.ZZ
  • sage/groups/perm_gps/permgroup.py

    diff -r b4e473888eb9 -r 1a7c8feb901d sage/groups/perm_gps/permgroup.py
    a b  
    341341        if gens is None:
    342342            self._gap_string = gap_group if isinstance(gap_group, str) else str(gap_group)
    343343            self._gens = self._gens_from_gap()
    344             return
     344            return None
    345345
    346346        gens = [self._element_class()(x, check=False).list() for x in gens]
    347347        self._deg = max([0]+[max(g) for g in gens])
     
    11111111        EXAMPLES::
    11121112       
    11131113            sage: G = PermutationGroup([[(1,2,3),(4,5)], [(1,2)]])
    1114             sage: G.random_element()
    1115             (1,2)(4,5)
     1114            sage: a = G.random_element()
     1115            sage: a in G
     1116            True
     1117            sage: a.parent() is G
     1118            True
     1119            sage: a^6
     1120            ()
    11161121        """
    11171122        current_randstate().set_seed_gap()
    11181123
  • sage/matrix/matrix0.pyx

    diff -r b4e473888eb9 -r 1a7c8feb901d sage/matrix/matrix0.pyx
    a b  
    37693769            [ 6 11]
    37703770            sage: parent(d)
    37713771            Full MatrixSpace of 2 by 2 dense matrices over Rational Field
    3772             sage: d = b*c; d
     3772            sage: d = b+c
    37733773            Traceback (most recent call last):
    37743774            ...
    3775             TypeError: unsupported operand parent(s) for '*': 'Full MatrixSpace of 2 by 2 dense matrices over Finite Field of size 7' and 'Full MatrixSpace of 2 by 2 dense matrices over Rational Field'
    3776             sage: d = b*c.change_ring(GF(7)); d
    3777             [2 3]
    3778             [6 4]
     3775            TypeError: unsupported operand parent(s) for '+': 'Full MatrixSpace of 2 by 2 dense matrices over Finite Field of size 7' and 'Full MatrixSpace of 2 by 2 dense matrices over Rational Field'
     3776            sage: d = b+c.change_ring(GF(7)); d
     3777            [0 2]
     3778            [4 6]
    37793779       
    37803780        EXAMPLE of matrix times matrix where one matrix is sparse and the
    37813781        other is dense (in such mixed cases, the result is always dense)::
  • sage/modules/free_module.py

    diff -r b4e473888eb9 -r 1a7c8feb901d sage/modules/free_module.py
    a b  
    136136
    137137- Niles Johnson (2010-08): Trac #3893: ``random_element()`` should pass on ``*args`` and ``**kwds``.
    138138
     139- Simon King (2010-12): Trac #8800: Fixing a bug in ``denominator()``.
     140
    139141"""
    140142
    141143###########################################################################
     
    349351        if not isinstance(sparse,bool):
    350352            raise TypeError, "Argument sparse (= %s) must be True or False" % sparse
    351353
    352         if not base_ring.is_commutative():
     354        if not (hasattr(base_ring,'is_commutative') and base_ring.is_commutative()):
    353355            raise TypeError, "The base_ring must be a commutative ring."
    354356
    355357        if not sparse and isinstance(base_ring,sage.rings.real_double.RealDoubleField_class):
     
    596598            (VectorFunctor, Multivariate Polynomial Ring in x0, x1, x2 over Rational Field)
    597599        """
    598600        from sage.categories.pushout import VectorFunctor
     601        if hasattr(self,'_inner_product_matrix'):
     602            return VectorFunctor(self.rank(), self.is_sparse(),self.inner_product_matrix()), self.base_ring()
    599603        return VectorFunctor(self.rank(), self.is_sparse()), self.base_ring()
    600604
    601605    # FIXME: what's the level of generality of FreeModuleHomspace?
     
    48914895       
    48924896        EXAMPLES::
    48934897       
    4894             sage: V = QQ^3                                                                        
    4895             sage: L = V.span([[1,1/2,1/3], [-1/5,2/3,3]],ZZ)                                      
    4896             sage: L                                                                               
    4897             Free module of degree 3 and rank 2 over Integer Ring                                 
    4898             Echelon basis matrix:                                                                 
    4899             [ 1/5 19/6 37/3]                                                                     
    4900             [   0 23/6 46/3]                                                                     
     4898            sage: V = QQ^3
     4899            sage: L = V.span([[1,1/2,1/3], [-1/5,2/3,3]],ZZ)
     4900            sage: L
     4901            Free module of degree 3 and rank 2 over Integer Ring
     4902            Echelon basis matrix:
     4903            [ 1/5 19/6 37/3]
     4904            [   0 23/6 46/3]
    49014905            sage: L._denominator(L.echelonized_basis_matrix().list())
    49024906            30
     4907
    49034908        """
    49044909        if len(B) == 0:
    49054910            return 1
    4906         d = sage.rings.integer.Integer(B[0].denominator())
     4911        d = sage.rings.integer.Integer((hasattr(B[0],'denominator') and B[0].denominator()) or 1)
    49074912        for x in B[1:]:
    4908             d = d.lcm(x.denominator())
     4913            d = d.lcm((hasattr(x,'denominator') and x.denominator()) or 1)
    49094914        return d
    49104915   
    49114916    def _repr_(self):
  • sage/modules/free_module_element.pyx

    diff -r b4e473888eb9 -r 1a7c8feb901d sage/modules/free_module_element.pyx
    a b  
    14981498            70
    14991499            sage: 2*5*7
    15001500            70
     1501
     1502        TESTS:
     1503
     1504        The following was fixed in trac ticket #8800::
     1505
     1506            sage: M = GF(5)^3
     1507            sage: v = M((4,0,2))
     1508            sage: v.denominator()
     1509            1
     1510
    15011511        """
    15021512        R = self.base_ring()
    15031513        if self.degree() == 0: return 1
    15041514        x = self.list()
    1505         d = x[0].denominator()
     1515        # it may be that the marks do not have a denominator!
     1516        d = x[0].denominator() if hasattr(x[0],'denominator') else 1
    15061517        for y in x:
    1507             d = d.lcm(y.denominator())
     1518            d = d.lcm(y.denominator()) if hasattr(y,'denominator') else d
    15081519        return d
    15091520       
    15101521    def dict(self, copy=True):
  • sage/rings/integer_ring.pyx

    diff -r b4e473888eb9 -r 1a7c8feb901d sage/rings/integer_ring.pyx
    a b  
    713713            Relative Order in Number Field in a with defining polynomial x^2 + 1 over its base field
    714714        """
    715715        if embedding is not None:
    716             raise NotImplementedError
     716            if embedding!=[None]*len(embedding):
     717                raise NotImplementedError
    717718        from sage.rings.number_field.order import EquationOrder
    718719        return EquationOrder(poly, names)
    719720
  • sage/rings/number_field/number_field.py

    diff -r b4e473888eb9 -r 1a7c8feb901d sage/rings/number_field/number_field.py
    a b  
    369369          To:   Number Field in b with defining polynomial x^6 - x^2 + 1/10
    370370          Defn: a -> b^2
    371371   
    372     The ``QuadraticField`` and
    373     ``CyclotomicField`` constructors create an embedding by
    374     default unless otherwise specified.
     372    The ``QuadraticField`` and ``CyclotomicField`` constructors
     373    create an embedding by default unless otherwise specified.
    375374   
    376375    ::
    377376   
     
    419418        sage: W.<a> = NumberField(x^2 + 1); W
    420419        Number Field in a with defining polynomial x^2 + 1 over its base field
    421420
     421    The following has been fixed in trac ticket #8800::
     422
     423        sage: P.<x> = QQ[]
     424        sage: K.<a> = NumberField(x^3-5,embedding=0)
     425        sage: L.<b> = K.extension(x^2+a)
     426        sage: F, R = L.construction()
     427        sage: F(R) == L    # indirect doctest
     428        True
     429
    422430    """
    423431    if name is None and names is None:
    424432        raise TypeError, "You must specify the name of the generator."
     
    426434        name = names
    427435
    428436    if isinstance(polynomial, (list, tuple)):
    429         return NumberFieldTower(polynomial, name)
     437        return NumberFieldTower(polynomial, name, embeddings=embedding)
    430438       
    431439    name = sage.structure.parent_gens.normalize_names(1, name)
    432440
     
    10241032        embedding = number_field_morphisms.create_embedding_from_approx(self, embedding)
    10251033        self._populate_coercion_lists_(embedding=embedding)
    10261034
     1035    def construction(self):
     1036        r"""
     1037        Construction of self
     1038
     1039        EXAMPLE::
     1040
     1041            sage: K.<a>=NumberField(x^3+x^2+1,embedding=CC.gen())
     1042            sage: F,R = K.construction()
     1043            sage: F
     1044            AlgebraicExtensionFunctor
     1045            sage: R
     1046            Rational Field
     1047            sage: F(R) == K
     1048            True
     1049
     1050        Note that, if a number field is provided with an embedding,
     1051        the construction functor applied to the rationals is not
     1052        necessarily identic with the number field. The reason is
     1053        that the construction functor uses a value for the embedding
     1054        that is equivalent, but not necessarily equal, to the one
     1055        provided in the definition of the number field::
     1056
     1057            sage: F(R) is K
     1058            False
     1059            sage: F.embeddings
     1060            [0.2327856159383841? + 0.7925519925154479?*I]
     1061
     1062        TEST::
     1063
     1064            sage: K.<a> = NumberField(x^3+x+1)
     1065            sage: R.<t> = ZZ[]
     1066            sage: a+t     # indirect doctest
     1067            t + a
     1068            sage: (a+t).parent()
     1069            Univariate Polynomial Ring in t over Number Field in a with defining polynomial x^3 + x + 1
     1070
     1071        The construction works for non-absolute number fields as well::
     1072
     1073            sage: K.<a,b,c>=NumberField([x^3+x^2+1,x^2+1,x^7+x+1])
     1074            sage: F,R = K.construction()
     1075            sage: F(R) == K
     1076            True
     1077
     1078        ::
     1079
     1080            sage: P.<x> = QQ[]
     1081            sage: K.<a> = NumberField(x^3-5,embedding=0)
     1082            sage: L.<b> = K.extension(x^2+a)
     1083            sage: a*b
     1084            a*b
     1085
     1086        """
     1087        from sage.categories.pushout import AlgebraicExtensionFunctor
     1088        from sage.all import QQ
     1089        if self.is_absolute():
     1090            return (AlgebraicExtensionFunctor([self.polynomial()], [self.variable_name()], [None if self.coerce_embedding() is None else self.coerce_embedding()(self.gen())]), QQ)
     1091        names = self.variable_names()
     1092        polys = []
     1093        embeddings = []
     1094        K = self
     1095        while (1):
     1096            if K.is_absolute():
     1097                break
     1098            polys.append(K.relative_polynomial())
     1099            embeddings.append(None if K.coerce_embedding() is None else K.coerce_embedding()(self.gen()))
     1100            K = K.base_field()
     1101        polys.append(K.relative_polynomial())
     1102        embeddings.append(None if K.coerce_embedding() is None else K.coerce_embedding()(K.gen()))
     1103        return (AlgebraicExtensionFunctor(polys, names, embeddings), QQ)
     1104
    10271105    def _element_constructor_(self, x):
    10281106        r"""
    10291107        Make x into an element of this number field, possibly not canonically.
     
    44224500            ...
    44234501            ValueError: Fractional ideal (5) is not a prime ideal
    44244502        """
     4503        from sage.rings.number_field.number_field_ideal import is_NumberFieldIdeal
     4504        if is_NumberFieldIdeal(prime) and prime.number_field() is not self:
     4505            raise ValueError, "%s is not an ideal of %s"%(prime,self)
    44254506        # This allows principal ideals to be specified using a generator:
    44264507        try:
    44274508            prime = self.ideal(prime)
    44284509        except TypeError:
    44294510            pass
    44304511
    4431         from sage.rings.number_field.number_field_ideal import is_NumberFieldIdeal
    44324512        if not is_NumberFieldIdeal(prime) or prime.number_field() is not self:
    44334513            raise ValueError, "%s is not an ideal of %s"%(prime,self)
    44344514        if check and not prime.is_prime():
     
    48804960        """
    48814961        Coerce a number field element x into this number field.
    48824962
    4883         In most cases this currently doesn't work (since it is
    4884         barely implemented) -- it only works for constants.
     4963        REMARK:
     4964
     4965        The name of this method was chosen for historical reasons.
     4966        In fact, what it does is not a coercion but a conversion.
    48854967
    48864968        INPUT:
    4887             x -- an element of some number field
    4888 
    4889         EXAMPLES:
     4969
     4970        ``x`` -- an element of some number field
     4971
     4972        ASSUMPTION:
     4973
     4974        ``x`` should be an element of a number field whose underlying
     4975        polynomial ring allows conversion into the polynomial ring of
     4976        ``self``.
     4977
     4978        Note that it is only tested that there is a method
     4979        ``x.polynomial()`` yielding an output that can be converted
     4980        into ``self.polynomial_ring()``.
     4981
     4982        OUTPUT:
     4983
     4984        An element of ``self`` corresponding to ``x``.
     4985
     4986        EXAMPLES::
     4987
    48904988            sage: K.<a> = NumberField(x^3 + 2)
    48914989            sage: L.<b> = NumberField(x^2 + 1)
    48924990            sage: K._coerce_from_other_number_field(L(2/3))
    4893             2/3       
    4894         """
    4895         f = x.polynomial()
    4896         if f.degree() <= 0:
    4897             return self._element_class(self, f[0])
    4898         # todo: more general coercion if embedding have been asserted
    4899         raise TypeError, "Cannot coerce element into this number field"
     4991            2/3
     4992
     4993        TESTS:
     4994
     4995        The following was fixed in trac ticket #8800::
     4996
     4997            sage: P.<x> = QQ[]
     4998            sage: K.<a> = NumberField(x^3-5,embedding=0)
     4999            sage: L.<b> = K.extension(x^2+a)
     5000            sage: F,R = L.construction()
     5001            sage: F(R) == L   #indirect doctest
     5002            True
     5003
     5004        """
     5005        f = self.polynomial_ring()(x.polynomial())
     5006        return self._element_class(self, f)
    49005007   
    49015008    def _coerce_non_number_field_element_in(self, x):
    49025009        """
     
    49855092
    49865093    def _coerce_map_from_(self, R):
    49875094        """
    4988         Canonical coercion of x into self.
    4989 
    4990         Currently integers, rationals, and this field itself coerce
    4991         canonically into this field.
     5095        Canonical coercion of a ring R into self.
     5096
     5097        Currently any ring coercing into the base ring canonically coerces
     5098        into this field, as well as orders in any number field coercing into
     5099        this field, and of course the field itself as well.
     5100
     5101        Two embedded number fields may mutually coerce into each other, if
     5102        the pushout of the two ambient fields exists and if it is possible
     5103        to construct an :class:`~sage.rings.number_field.number_field_morphisms.EmbeddedNumberFieldMorphism`.
    49925104
    49935105        EXAMPLES::
    49945106
     
    50045116            sage: S.coerce(y) is y
    50055117            True
    50065118
    5007         Fields with embeddings into an ambient field coerce naturally.
     5119        Fields with embeddings into an ambient field coerce naturally by the given embedding::
     5120
    50085121            sage: CyclotomicField(15).coerce(CyclotomicField(5).0 - 17/3)
    50095122            zeta15^3 - 17/3
    50105123            sage: K.<a> = CyclotomicField(16)
     
    50165129              To:   Number Field in a with defining polynomial x^2 + 3
    50175130              Defn: zeta3 -> 1/2*a - 1/2
    50185131
    5019         There are situations for which one might imagine canonical
    5020         coercion could make sense (at least after fixing choices), but
    5021         which aren't yet implemented:
     5132        Two embedded number fields with mutual coercions (testing against a
     5133        bug that was fixed in trac ticket #8800)::
     5134
     5135            sage: K.<r4> = NumberField(x^4-2)
     5136            sage: L1.<r2_1> = NumberField(x^2-2, embedding = r4**2)
     5137            sage: L2.<r2_2> = NumberField(x^2-2, embedding = -r4**2)
     5138            sage: r2_1+r2_2    # indirect doctest
     5139            0
     5140            sage: (r2_1+r2_2).parent() is L1
     5141            True
     5142            sage: (r2_2+r2_1).parent() is L2
     5143            True
     5144
     5145        Coercion of an order (testing against a bug that was fixed in
     5146        trac ticket #8800)::
     5147
     5148            sage: K.has_coerce_map_from(L1)
     5149            True
     5150            sage: L1.has_coerce_map_from(K)
     5151            False
     5152            sage: K.has_coerce_map_from(L1.maximal_order())
     5153            True
     5154            sage: L1.has_coerce_map_from(K.maximal_order())
     5155            False
     5156
     5157        There are situations for which one might imagine conversion
     5158        could make sense (at least after fixing choices), but of course
     5159        there will be no coercion from the Symbolic Ring to a Number Field::
     5160
    50225161            sage: K.<a> = QuadraticField(2)
    50235162            sage: K.coerce(sqrt(2))
    50245163            Traceback (most recent call last):
    50255164            ...
    50265165            TypeError: no canonical coercion from Symbolic Ring to Number Field in a with defining polynomial x^2 - 2
    50275166
    5028         TESTS:
     5167        TESTS::
     5168
    50295169            sage: K.<a> = NumberField(polygen(QQ)^3-2)
    50305170            sage: type(K.coerce_map_from(QQ))
    50315171            <type 'sage.structure.coerce_maps.DefaultConvertMap_unique'>
    50325172           
    5033         Make sure we still get our optimized morphisms for special fields:
     5173        Make sure we still get our optimized morphisms for special fields::
     5174
    50345175            sage: K.<a> = NumberField(polygen(QQ)^2-2)
    50355176            sage: type(K.coerce_map_from(QQ))
    50365177            <type 'sage.rings.number_field.number_field_element_quadratic.Q_to_quadratic_field_element'>
     5178
    50375179        """
    50385180        if R in [int, long, ZZ, QQ, self.base()]:
    50395181            return self._generic_convert_map(R)
    50405182        from sage.rings.number_field.order import is_NumberFieldOrder
    5041         if is_NumberFieldOrder(R) and R.number_field().has_coerce_map_from(self):
     5183        if is_NumberFieldOrder(R) and self.has_coerce_map_from(R.number_field()):
    50425184            return self._generic_convert_map(R)
    50435185        if is_NumberField(R) and R != QQ:
    50445186            if R.coerce_embedding() is not None:
     
    50475189                        from sage.categories.pushout import pushout
    50485190                        ambient_field = pushout(R.coerce_embedding().codomain(), self.coerce_embedding().codomain())
    50495191                        if ambient_field is not None:
     5192                            try:
     5193                                # the original ambient field
     5194                                return number_field_morphisms.EmbeddedNumberFieldMorphism(R, self, ambient_field)
     5195                            except ValueError: # no embedding found
     5196                                # there might be one in the alg. completion
     5197                                return number_field_morphisms.EmbeddedNumberFieldMorphism(R, self, ambient_field.algebraic_closure() if hasattr(ambient_field,'algebraic_closure') else ambient_field)
     5198                    except (ValueError, TypeError, sage.structure.coerce_exceptions.CoercionException),msg:
     5199                        # no success with the pushout
     5200                        try:
    50505201                            return number_field_morphisms.EmbeddedNumberFieldMorphism(R, self)
    5051                     except (TypeError, ValueError):
    5052                         pass
     5202                        except (TypeError, ValueError):
     5203                            pass
     5204                else:
     5205                    # R is embedded, self isn't. So, we could only have
     5206                    # the forgetful coercion. But this yields to non-commuting
     5207                    # coercions, as was pointed out at ticket #8800
     5208                    return None
    50535209
    50545210    def _magma_init_(self, magma):
    50555211        """
     
    65406696        """
    65416697        return NumberField_cyclotomic_v1, (self.__n, self.variable_name(), self.gen_embedding())
    65426698
     6699    def construction(self):
     6700        F,R = NumberField_generic.construction(self)
     6701        F.cyclotomic = self.__n
     6702        return F,R
     6703
    65436704    def _magma_init_(self, magma):
    65446705        """
    65456706        Function returning a string to create this cyclotomic field in
  • sage/rings/number_field/number_field_element.pyx

    diff -r b4e473888eb9 -r 1a7c8feb901d sage/rings/number_field/number_field_element.pyx
    a b  
    43154315            ...
    43164316            TypeError: Cannot coerce element into this number field
    43174317        """
     4318        from sage.all import parent
     4319        if not self.__K.has_coerce_map_from(parent(x)):
     4320            raise TypeError, "Cannot coerce element into this number field"
    43184321        return self.__W.coordinates(self.__to_V(self.__K(x)))
    43194322   
    43204323    def __cmp__(self, other):
  • sage/rings/number_field/number_field_ideal.py

    diff -r b4e473888eb9 -r 1a7c8feb901d sage/rings/number_field/number_field_ideal.py
    a b  
    241241            '\\left(17\\right)'
    242242        """
    243243        return '\\left(%s\\right)'%(", ".join(map(latex.latex, self._gens_repr())))
    244        
     244
    245245    def __cmp__(self, other):
    246246        """
    247247        Compare an ideal of a number field to something else.
    248248
     249        REMARK:
     250
     251        By default, comparing ideals is the same as comparing
     252        their generator list. But of course, different generators
     253        can give rise to the same ideal. And this can easily
     254        be detected using Hermite normal form.
     255
     256        Unfortunately, there is a difference between "cmp" and
     257        "==": In the first case, this method is directly called.
     258        In the second case, it is only called *after coercion*.
     259        However, we ensure that "cmp(I,J)==0" and "I==J" will
     260        always give the same answer for number field ideals.
     261
    249262        EXAMPLES::
    250263
    251264            sage: K.<a> = NumberField(x^2 + 3); K
     
    262275            True
    263276            sage: f[1][0] == GF(7)(5)
    264277            False
     278
     279        TESTS::
     280
     281            sage: L.<b> = NumberField(x^8-x^4+1)
     282            sage: F_2 = L.fractional_ideal(b^2-1)
     283            sage: F_4 = L.fractional_ideal(b^4-1)
     284            sage: F_2 == F_4
     285            True
     286
    265287        """
    266288        if not isinstance(other, NumberFieldIdeal):
     289            # this can only occur with cmp(,)
    267290            return cmp(type(self), type(other))
     291        if self.parent()!=other.parent():
     292            # again, this can only occur if cmp(,)
     293            # is called
     294            if self==other:
     295                return 0
     296            c = cmp(self.pari_hnf(), other.pari_hnf())
     297            if c: return c
     298            return cmp(self.parent(),other.parent())
     299        # We can now assume that both have the same parent,
     300        # even if originally cmp(,) was called.
    268301        return cmp(self.pari_hnf(), other.pari_hnf())
    269302
    270303    def coordinates(self, x):
  • sage/rings/number_field/number_field_morphisms.pyx

    diff -r b4e473888eb9 -r 1a7c8feb901d sage/rings/number_field/number_field_morphisms.pyx
    a b  
    109109    This allows one to go from one number field in another consistently,
    110110    assuming they both have specified embeddings into an ambient field
    111111    (by default it looks for an embedding into `\CC`).
     112
     113    EXAMPLES::
     114
     115        sage: K.<i> = NumberField(x^2+1,embedding=QQbar(I))
     116        sage: L.<i> = NumberField(x^2+1,embedding=-QQbar(I))
     117        sage: from sage.rings.number_field.number_field_morphisms import EmbeddedNumberFieldMorphism
     118        sage: EmbeddedNumberFieldMorphism(K,L,CDF)
     119        Generic morphism:
     120          From: Number Field in i with defining polynomial x^2 + 1
     121          To:   Number Field in i with defining polynomial x^2 + 1
     122          Defn: i -> -i
     123        sage: EmbeddedNumberFieldMorphism(K,L,QQbar)
     124        Generic morphism:
     125          From: Number Field in i with defining polynomial x^2 + 1
     126          To:   Number Field in i with defining polynomial x^2 + 1
     127          Defn: i -> -i
     128
    112129    """
    113130    cdef readonly ambient_field
    114131
     
    191208            sage: from sage.rings.number_field.number_field_morphisms import EmbeddedNumberFieldConversion
    192209            sage: K.<a> = NumberField(x^2-17, embedding=4.1)
    193210            sage: L.<b> = NumberField(x^4-17, embedding=2.0)
    194             sage: f = EmbeddedNumberFieldConversion(L, K)
    195             sage: f(b^2)
    196             a
    197             sage: f(L(a/2-11))
    198             1/2*a - 11
     211            sage: f = EmbeddedNumberFieldConversion(K, L)
     212            sage: f(a)
     213            b^2
     214            sage: f(K(b^2/2-11))
     215            1/2*b^2 - 11
    199216        """
    200217        if ambient_field is None:
    201218            from sage.rings.complex_double import CDF
     
    269286                return r
    270287    else:
    271288        # since things are inexact, try and pick the closest one
     289        # -- unless the ambient field is inexact and has no prec(),
     290        # which holds, e.g., for the symbolic ring
     291        if not hasattr(ambient_field,'prec'):
     292            return None
    272293        if max_prec is None:
    273294            max_prec = ambient_field.prec() * 32
    274295        while ambient_field.prec() < max_prec:
  • sage/rings/polynomial/polynomial_quotient_ring.py

    diff -r b4e473888eb9 -r 1a7c8feb901d sage/rings/polynomial/polynomial_quotient_ring.py
    a b  
    234234    def __reduce__(self):
    235235        return PolynomialQuotientRing_generic, (self.__ring, self.__polynomial, self.variable_names())
    236236
    237     def __call__(self, x):
     237    def _element_constructor_(self, x):
    238238        """
    239         Coerce x into this quotient ring. Anything that can be coerced into
    240         the polynomial ring can be coerced into the quotient.
     239        Convert x into this quotient ring. Anything that can be converted into
     240        the polynomial ring can be converted into the quotient.
    241241       
    242242        INPUT:
    243243       
    244244       
    245         -  ``x`` - object to be coerced
     245        -  ``x`` - object to be converted
    246246       
    247247       
    248         OUTPUT: an element obtained by coercing x into this ring.
     248        OUTPUT: an element obtained by converting x into this ring.
    249249       
    250250        EXAMPLES::
    251251       
     
    263263            alpha + 1
    264264            sage: S(S.gen()^10+1)
    265265            90*alpha^2 - 109*alpha + 28
     266
     267        TESTS:
     268
     269        Conversion should work even if there is no coercion.
     270        This was fixed in trac ticket #8800::
     271
     272            sage: P.<x> = QQ[]
     273            sage: Q1 = P.quo([(x^2+1)^2*(x^2-3)])
     274            sage: Q = P.quo([(x^2+1)^2])
     275            sage: Q1.has_coerce_map_from(Q)
     276            False
     277            sage: Q1(Q.gen())
     278            xbar
     279
    266280        """
    267281        if isinstance(x, PolynomialQuotientRingElement):
    268282            P = x.parent()
    269283            if P is self:
    270284                return x
    271             elif P == self:
    272                 return PolynomialQuotientRingElement(self, self.__ring(x.lift()), check=False)
     285            return PolynomialQuotientRingElement(self, self.__ring(x.lift()), check=False)
    273286        return PolynomialQuotientRingElement(
    274287                        self, self.__ring(x) , check=True)
    275288
     289    def _coerce_map_from_(self, R):
     290        """
     291        Anything coercing into ``self``'s polynomial ring coerces into ``self``.
     292        Any quotient polynomial ring whose polynomial ring coerces into
     293        ``self``'s polynomial ring and whose modulus is divided by the modulus
     294        of ``self`` coerces into ``self``.
     295
     296        AUTHOR:
     297
     298        - Simon King (2010-12): Trac ticket #8800
     299
     300        TESTS::
     301
     302            sage: P5.<x> = GF(5)[]
     303            sage: Q = P5.quo([(x^2+1)^2])
     304            sage: P.<x> = ZZ[]
     305            sage: Q1 = P.quo([(x^2+1)^2*(x^2-3)])
     306            sage: Q2 = P.quo([(x^2+1)^2*(x^5+3)])
     307            sage: Q.has_coerce_map_from(Q1)  #indirect doctest
     308            True
     309            sage: Q1.has_coerce_map_from(Q)
     310            False
     311            sage: Q1.has_coerce_map_from(Q2)
     312            False
     313
     314        """
     315        if self.__ring.has_coerce_map_from(R):
     316            return True
     317        if isinstance(R, PolynomialQuotientRing_generic):
     318            return self.__ring.has_coerce_map_from(R.polynomial_ring()) and self.__polynomial.divides(R.modulus())
     319
    276320    def _is_valid_homomorphism_(self, codomain, im_gens):
    277321        try:
    278322            # We need that elements of the base ring of the polynomial
     
    367411        return "Univariate Quotient Polynomial Ring in %s over %s with modulus %s"%(
    368412            self.variable_name(), self.base_ring(), self.modulus())
    369413
     414    def construction(self):
     415        """
     416        Functorial construction of ``self``
     417
     418        EXAMPLES::
     419
     420            sage: P.<t>=ZZ[]
     421            sage: Q = P.quo(5+t^2)
     422            sage: F, R = Q.construction()
     423            sage: F(R) == Q
     424            True
     425            sage: P.<t> = GF(3)[]
     426            sage: Q = P.quo([2+t^2])
     427            sage: F, R = Q.construction()
     428            sage: F(R) == Q
     429            True
     430
     431        AUTHOR:
     432
     433        -- Simon King (2010-05)
     434        """
     435        from sage.categories.pushout import QuotientFunctor
     436        return QuotientFunctor([self.modulus()]*self.base(),self.variable_names(),self.is_field()), self.base()
    370437
    371438    def base_ring(self):
    372439        r"""
  • sage/rings/qqbar.py

    diff -r b4e473888eb9 -r 1a7c8feb901d sage/rings/qqbar.py
    a b  
    848848        """
    849849        return self
    850850   
     851    def construction(self):
     852        """
     853        EXAMPLE::
     854
     855            sage: QQbar.construction()
     856            (AlgebraicClosureFunctor, Rational Field)
     857        """
     858        from sage.categories.pushout import AlgebraicClosureFunctor
     859        from sage.all import QQ
     860        return (AlgebraicClosureFunctor(), QQ)
     861
    851862    def gens(self):
    852863        return(QQbar_I, )
    853864
  • sage/rings/quotient_ring.py

    diff -r b4e473888eb9 -r 1a7c8feb901d sage/rings/quotient_ring.py
    a b  
    249249        from sage.categories.pushout import QuotientFunctor
    250250        # Is there a better generic way to distinguish between things like Z/pZ as a field and Z/pZ as a ring?
    251251        from sage.rings.field import Field
    252         return QuotientFunctor(self.__I, as_field=isinstance(self, Field)), self.__R
     252        try:
     253            names = self.variable_names()
     254        except ValueError:
     255            try:
     256                names = self.cover_ring().variable_names()
     257            except ValueError:
     258                names = None
     259        return QuotientFunctor(self.__I, names=names, as_field=isinstance(self, Field)), self.__R
    253260
    254261    def _repr_(self):
    255262        """
  • sage/rings/residue_field.pyx

    diff -r b4e473888eb9 -r 1a7c8feb901d sage/rings/residue_field.pyx
    a b  
    160160class ResidueFieldFactory(UniqueFactory):
    161161    """
    162162    A factory that returns the residue class field of a prime ideal p
    163     of the ring of integers of a number field, or of a polynomial ring over a finite field.
     163    of the ring of integers of a number field, or of a polynomial ring
     164    over a finite field.
    164165
    165166    INPUT:
    166167   
     
    296297       
    297298    def create_object(self, version, key, **kwds):
    298299        p, names, impl = key
     300        pring = p.ring()
    299301
    300         if p.ring() is ZZ:
     302        if pring is ZZ:
    301303            return ResidueFiniteField_prime_modn(p, names, p.gen(), None, None, None)
    302         if is_PolynomialRing(p.ring()):
    303             K = p.ring().fraction_field()
    304             Kbase = p.ring().base_ring()
     304        if is_PolynomialRing(pring):
     305            K = pring.fraction_field()
     306            Kbase = pring.base_ring()
    305307            f = p.gen()
    306308            if f.degree() == 1 and Kbase.is_prime_field() and (impl is None or impl == 'modn'):
    307309                return ResidueFiniteField_prime_modn(p, None, Kbase.order(), None, None, None)
     
    320322        if is_NumberFieldIdeal(p):
    321323            characteristic = p.smallest_integer()
    322324        else: # ideal of a function field
    323             characteristic = p.ring().base_ring().characteristic()
     325            characteristic = pring.base_ring().characteristic()
    324326        # Once we have function fields, we should probably have an if statement here.
    325         K = p.ring().fraction_field()
     327        K = pring.fraction_field()
    326328        #OK = K.maximal_order() # Need to change to p.order inside the __init__s for the residue fields.
    327329
    328330        U, to_vs, to_order = p._p_quotient(characteristic)
     
    454456
    455457    def _element_constructor_(self, x):
    456458        """
    457         This is called after x fails to coerce into the finite field (without the convert map from the number field).
     459        This is called after x fails to convert into ``self`` as
     460        abstract finite field (without considering the underlying
     461        number field).
    458462
    459         So the strategy is to try to coerce into the number field, and then use the convert map.
     463        So the strategy is to try to convert into the number field,
     464        and then proceed to the residue field.
     465
     466        NOTE:
     467
     468        The behaviour of this method was changed in trac ticket #8800.
     469        Before, an error was raised if there was no coercion. Now,
     470        a conversion is possible even when there is no coercion.
     471        This is like for different finite fields.
    460472
    461473        EXAMPLES::
    462474
     
    467479            sage: F = OK.residue_field(P)
    468480            sage: ResidueField_generic._element_constructor_(F, i)
    469481            8
     482
     483        With ticket #8800, we also have::
     484
    470485            sage: ResidueField_generic._element_constructor_(F, GF(13)(8))
    471             Traceback (most recent call last):
    472             ...
    473             TypeError: cannot coerce <type 'sage.rings.finite_rings.integer_mod.IntegerMod_int'>
     486            8
    474487
    475             #sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
    476             #sage: k.<a> = P.residue_field()
    477             #sage: ResidueField_generic._element_constructor_(k, t)
    478             #a
    479             #sage: ResidueField_generic._element_constructor_(k, GF(17)(4))
    480             #4
     488        Here is a test that was temporarily removed, but newly introduced
     489        in ticket #8800::
     490
     491            sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
     492            sage: k.<a> = P.residue_field()
     493            sage: k(t)
     494            a
     495            sage: k(GF(17)(4))
     496            4
     497
     498        In the remaining tests, we elaborate a bit more on the difference of
     499        coercion and conversion::
     500
     501            sage: K.<r4> = NumberField(x^4-2)
     502            sage: L.<r4> = NumberField(x^4-2, embedding=CDF.0)
     503            sage: FK = K.fractional_ideal(K.0)
     504            sage: FL = L.fractional_ideal(L.0)
     505
     506        There is no coercion from the embedded to the unembedded
     507        number field. Hence, the two fractional ideals are different.
     508        By consequence, the resulting residue fields are different::
     509
     510            sage: RL = ResidueField(FL)
     511            sage: RK = ResidueField(FK)
     512            sage: RK == RL
     513            False
     514
     515        Since ``RL`` is defined with the embedded number field ``L``, there
     516        is no coercion from the maximal order of ``K`` to ``RL``. However,
     517        conversion is possible::
     518
     519            sage: OK = K.maximal_order()
     520            sage: RL.has_coerce_map_from(OK)
     521            False
     522            sage: RL(OK.1)
     523            0
     524
    481525        """
    482526        K = OK = self.p.ring()
    483527        if OK.is_field():
     
    495539        elif K.has_coerce_map_from(R):
    496540            x = K(x)
    497541        else:
    498             raise TypeError, "cannot coerce %s"%type(x)               
     542            try:
     543                x = K(x)
     544            except (TypeError, ValueError):
     545                raise TypeError, "cannot coerce %s"%type(x)               
    499546        return self(x)
    500547
    501548    def _coerce_map_from_(self, R):
  • sage/rings/ring.pyx

    diff -r b4e473888eb9 -r 1a7c8feb901d sage/rings/ring.pyx
    a b  
    12451245        - ``poly`` -- A polynomial whose coefficients are coercible into self
    12461246        - ``name`` -- (optional) name for the root of f
    12471247           
     1248        NOTE:
     1249
     1250        Using this method on an algebraically complete field does *not*
     1251        return this field; the construction self[x] / (f(x)) is done
     1252        anyway.
     1253
    12481254        EXAMPLES::
    12491255       
    12501256            sage: R = QQ['x']
     
    12721278        if name is None:
    12731279            name = str(poly.parent().gen(0))
    12741280        if embedding is not None:
    1275             raise NotImplementedError
     1281            raise NotImplementedError, "ring extension with prescripted embedding is not implemented"
    12761282        R = self[name]
    12771283        I = R.ideal(R(poly.list()))
    12781284        return R.quotient(I, name)
  • sage/schemes/elliptic_curves/ell_local_data.py

    diff -r b4e473888eb9 -r 1a7c8feb901d sage/schemes/elliptic_curves/ell_local_data.py
    a b  
    634634        - ``cp`` (int) is the Tamagawa number
    635635
    636636
    637         EXAMPLES (this raised an type error in sage prior to 4.4.4, see ticket #7930) ::
     637        EXAMPLES (this raised a type error in sage prior to 4.4.4, see ticket #7930) ::
    638638
    639639            sage: E = EllipticCurve('99d1')
    640640                         
     
    651651
    652652        EXAMPLES:
    653653
    654         The following example shows that the bug at #9324 is fixed:
     654        The following example shows that the bug at #9324 is fixed::
    655655
    656656            sage: K.<a> = NumberField(x^2-x+6)
    657657            sage: E = EllipticCurve([0,0,0,-53160*a-43995,-5067640*a+19402006])
    658658            sage: E.conductor() # indirect doctest
    659659            Fractional ideal (18, 6*a)
    660660
    661        
    662 
    663661        """
    664662        E = self._curve
    665663        P = self._prime
     
    692690
    693691        pval = lambda x: x.valuation(prime)
    694692        pdiv = lambda x: x.is_zero() or pval(x) > 0
    695         pinv = lambda x: F.lift(~F(x))
    696         proot = lambda x,e: F.lift(F(x).nth_root(e, extend = False, all = True)[0])
    697         preduce = lambda x: F.lift(F(x))
     693        # Since ResidueField is cached in a way that
     694        # does not care much about embeddings of number
     695        # fields, it can happen that F.p.ring() is different
     696        # from K. This is a problem: If F.p.ring() has no
     697        # embedding but K has, then there is no coercion
     698        # from F.p.ring().maximal_order() to K. But it is
     699        # no problem to do an explicit conversion in that
     700        # case (Simon King, trac ticket #8800).
     701       
     702        from sage.categories.pushout import pushout, CoercionException
     703        try:
     704            if hasattr(F.p.ring(), 'maximal_order'): # it is not ZZ
     705                _tmp_ = pushout(F.p.ring().maximal_order(),K)
     706            pinv = lambda x: F.lift(~F(x))
     707            proot = lambda x,e: F.lift(F(x).nth_root(e, extend = False, all = True)[0])
     708            preduce = lambda x: F.lift(F(x))
     709        except CoercionException: # the pushout does not exist, we need conversion
     710            pinv = lambda x: K(F.lift(~F(x)))
     711            proot = lambda x,e: K(F.lift(F(x).nth_root(e, extend = False, all = True)[0]))
     712            preduce = lambda x: K(F.lift(F(x)))
    698713
    699714        def _pquadroots(a, b, c):
    700715            r"""
  • sage/schemes/elliptic_curves/ell_number_field.py

    diff -r b4e473888eb9 -r 1a7c8feb901d sage/schemes/elliptic_curves/ell_number_field.py
    a b  
    19081908
    19091909            sage: K.<i> = QuadraticField(-1)
    19101910            sage: E1 = EllipticCurve([i + 1, 0, 1, -240*i - 400, -2869*i - 2627])
    1911             sage: E1.conductor()                                                 
     1911            sage: E1.conductor()
    19121912            Fractional ideal (-7*i + 4)
    1913             sage: E2 = EllipticCurve([1+i,0,1,0,0])                             
    1914             sage: E2.conductor()                                                 
     1913            sage: E2 = EllipticCurve([1+i,0,1,0,0])
     1914            sage: E2.conductor()
    19151915            Fractional ideal (-7*i + 4)
    19161916            sage: E1.is_isogenous(E2)
    19171917            Traceback (most recent call last):
  • sage/structure/coerce.pyx

    diff -r b4e473888eb9 -r 1a7c8feb901d sage/structure/coerce.pyx
    a b  
    355355       
    356356            sage: import traceback
    357357            sage: cm.exception_stack()
    358             [(<class 'sage.structure.coerce_exceptions.CoercionException'>, CoercionException(AttributeError("'IdealMonoid_c_with_category' object has no attribute 'base_extend'",),), <traceback object at ...>), (<type 'exceptions.TypeError'>, TypeError("no common canonical parent for objects with parents: 'Rational Field' and 'Finite Field of size 3'",), <traceback object at ...>)]
     358            [(<type 'exceptions.TypeError'>, TypeError('No coercion from Rational Field to pushout Ring of integers modulo 1',), <traceback object at ...>), (<type 'exceptions.TypeError'>, TypeError("no common canonical parent for objects with parents: 'Rational Field' and 'Finite Field of size 3'",), <traceback object at ...>)]
    359359            sage: print ''.join(sum([traceback.format_exception(*info) for info in cm.exception_stack()], []))
    360360            Traceback (most recent call last):
    361361            ...
  • sage/structure/parent.pyx

    diff -r b4e473888eb9 -r 1a7c8feb901d sage/structure/parent.pyx
    a b  
    909909            mor = <map.Map>mor_ptr
    910910        else:
    911911            mor = <map.Map>self.convert_map_from(R)
    912            
     912
    913913        if mor is not None:
    914914            if no_extra_args:
    915915                return mor._call_(x)
     
    16491649        usually denotes a special relationship (e.g. sub-objects, choice of
    16501650        completion, etc.)
    16511651
    1652         EXAMPLES:
     1652        EXAMPLES::
     1653
     1654            sage: K.<a>=NumberField(x^3+x^2+1,embedding=1)
     1655            sage: K.coerce_embedding()
     1656            Generic morphism:
     1657              From: Number Field in a with defining polynomial x^3 + x^2 + 1
     1658              To:   Real Lazy Field
     1659              Defn: a -> -1.465571231876768?
     1660            sage: K.<a>=NumberField(x^3+x^2+1,embedding=CC.gen())
     1661            sage: K.coerce_embedding()
     1662            Generic morphism:
     1663              From: Number Field in a with defining polynomial x^3 + x^2 + 1
     1664              To:   Complex Lazy Field
     1665              Defn: a -> 0.2327856159383841? + 0.7925519925154479?*I
    16531666        """
    16541667        return self._embedding
    16551668           
     
    18081821            return self.coerce_map_from(S._type)
    18091822        if self._coerce_from_hash is None: # this is because parent.__init__() does not always get called
    18101823            self.init_coerce(False)
    1811         cdef object ret
     1824        #cdef object ret
    18121825        try:
    18131826            return self._coerce_from_hash[S]
    18141827        except KeyError: