Ticket #9500: trac_9500.patch

File trac_9500.patch, 5.3 KB (added by was, 13 years ago)
  • sage/rings/quotient_ring_element.py

    # HG changeset patch
    # User William Stein <wstein@gmail.com>
    # Date 1277358107 25200
    # Node ID 2c42ec3e656bfe866674e11c3de9dd6ac3518b04
    # Parent  d1fa413c3709bfbebc9a284d39432f0ab210f032
    trac 9500: implement inversion of elements in a (more) general quotient ring
    
    diff -r d1fa413c3709 -r 2c42ec3e656b sage/rings/quotient_ring_element.py
    a b  
    275275        element, ``right``. If the quotient is `R/I`, the division is
    276276        carried out in `R` and then reduced to `R/I`.
    277277
    278         TODO: This is not implemented in general -- see the first 'test'
    279         below for an illustration.
     278        EXAMPLES::
    280279
    281         EXAMPLES::
     280            sage: R.<x,y> = QQ[]
     281            sage: I = R.ideal([x^2 + 1, y^3 - 2])
     282            sage: S.<i,cuberoot> = R.quotient(I)
     283            sage: 1/(1+i)
     284            -1/2*i + 1/2
     285
     286        Confirm via symbolic computation::
     287       
     288            sage: 1/(1+sqrt(-1))
     289            -1/2*I + 1/2
     290
     291        Another more complicated quotient::
     292       
     293            sage: b = 1/(i+cuberoot); b
     294            1/5*i*cuberoot^2 - 2/5*i*cuberoot + 2/5*cuberoot^2 - 1/5*i + 1/5*cuberoot - 2/5
     295            sage: b*(i+cuberoot)
     296            1
     297
     298
     299        Another really easy example::
    282300       
    283301            sage: R.<x,y> = QQ[]; S.<a,b> = R.quo(x^2 + y^2); type(a)
    284302            <class 'sage.rings.quotient_ring_element.QuotientRingElement'>
    285303            sage: a / S(2)
    286304            1/2*a
    287        
    288         TESTS::
    289        
    290305            sage: (a*b)._div_(b)
     306            a
     307
     308        An example in which we try to divide in a ring that is not a
     309        field::
     310
     311            sage: R.<x,y> = QQ[]
     312            sage: I = R.ideal([x^2 - 1, y^3 - 2])
     313            sage: S.<a,cuberoot> = R.quotient(I)
     314            sage: 1/cuberoot
     315            1/2*cuberoot^2
     316            sage: 1/a
     317            a
     318
     319        An example over a polynomial ring over a polynomial ring,
     320        which doesn't work (yet; obviously, this could be made to work
     321        by converting to a single polynomial quotient ring
     322        internally)::
     323
     324            sage: R.<x> = QQ[]
     325            sage: S.<y,z> = R[]
     326            sage: Z.<ybar,zbar> = S.quotient([y^2 - 2, z^2 - 3])
    291327            Traceback (most recent call last):
    292328            ...
    293             NotImplementedError
    294             sage: a._div_(S(2))
    295             1/2*a
    296             sage: S(2).is_unit()
    297             True
    298             sage: a.is_unit()
    299             Traceback (most recent call last):
    300             ...
    301             NotImplementedError
     329            TypeError: Can only reduce polynomials over fields.
    302330        """
    303         if not right.is_unit():
    304             raise ZeroDivisionError
    305         return self._mul_(right.__invert__())
     331        # Special case: if self==0 (and right is nonzero), just return self.
     332        if not self:
     333            if not right: raise ZeroDivisionError
     334            return self
     335
     336        # We are computing L/R modulo the ideal.
     337        (L, R) = (self.__rep, right.__rep)
     338        P  = self.parent()
     339        I = P.defining_ideal()
     340       
     341        if not hasattr(I, 'groebner_basis'):
     342            # Try something very naive -- somebody will improve this
     343            # in the future.
     344            try:
     345                return L * R.inverse_mod(I)
     346            except NotImplementedError:
     347                if R.is_unit():
     348                    return L * R.__invert__()
     349                else:
     350                    raise
     351
     352        # Now the parent is a polynomial ring, so we have an algorithm
     353        # at our disposal.
     354
     355        # Our algorithm is to write L in terms of R and a Groebner
     356        # basis for the defining ideal.  We compute a Groebner basis
     357        # here explicitly purely for efficiency reasons, since it
     358        # makes the implicit Groebner basis computation of [R]+B
     359        # that is done in the lift command below faster.
     360        B  = I.groebner_basis()
     361        XY = L.lift([R] + B)
     362        if XY == [0]*len(XY):
     363            raise NotImplementedError
     364        return P(XY[0])
    306365
    307366    def __int__(self):
    308367        """
     
    413472
    414473            sage: S(2/3).__invert__()
    415474            3/2
     475
     476        Note that a is not invertible as an element of R, and
     477        extending the base field is implemented yet::
     478       
    416479            sage: a.__invert__()
    417480            Traceback (most recent call last):
    418481            ...
     
    421484        try:
    422485            inv = self.__rep.inverse_mod(self.parent().defining_ideal())
    423486        except NotImplementedError:
    424             if self.__rep.is_unit():
    425                 inv = self.__rep.__invert__()
    426             else:
    427                 raise
     487            return self.parent()(1)/self
    428488        return QuotientRingElement(self.parent(), inv)
    429489
    430490    def __float__(self):
  • sage/structure/coerce.pyx

    diff -r d1fa413c3709 -r 2c42ec3e656b sage/structure/coerce.pyx
    a b  
    13441344            if is_Ring(S):
    13451345                try:
    13461346                    K = S._pseudo_fraction_field()
    1347                 except (TypeError, AttributeError):
     1347                except (TypeError, AttributeError, NotImplementedError):
    13481348                    K = None
    13491349            elif PY_TYPE_CHECK(S, Parent):
    13501350                K = S