# 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
|
|
275 | 275 | element, ``right``. If the quotient is `R/I`, the division is |
276 | 276 | carried out in `R` and then reduced to `R/I`. |
277 | 277 | |
278 | | TODO: This is not implemented in general -- see the first 'test' |
279 | | below for an illustration. |
| 278 | EXAMPLES:: |
280 | 279 | |
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:: |
282 | 300 | |
283 | 301 | sage: R.<x,y> = QQ[]; S.<a,b> = R.quo(x^2 + y^2); type(a) |
284 | 302 | <class 'sage.rings.quotient_ring_element.QuotientRingElement'> |
285 | 303 | sage: a / S(2) |
286 | 304 | 1/2*a |
287 | | |
288 | | TESTS:: |
289 | | |
290 | 305 | 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]) |
291 | 327 | Traceback (most recent call last): |
292 | 328 | ... |
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. |
302 | 330 | """ |
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]) |
306 | 365 | |
307 | 366 | def __int__(self): |
308 | 367 | """ |
… |
… |
|
413 | 472 | |
414 | 473 | sage: S(2/3).__invert__() |
415 | 474 | 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 | |
416 | 479 | sage: a.__invert__() |
417 | 480 | Traceback (most recent call last): |
418 | 481 | ... |
… |
… |
|
421 | 484 | try: |
422 | 485 | inv = self.__rep.inverse_mod(self.parent().defining_ideal()) |
423 | 486 | except NotImplementedError: |
424 | | if self.__rep.is_unit(): |
425 | | inv = self.__rep.__invert__() |
426 | | else: |
427 | | raise |
| 487 | return self.parent()(1)/self |
428 | 488 | return QuotientRingElement(self.parent(), inv) |
429 | 489 | |
430 | 490 | def __float__(self): |
diff -r d1fa413c3709 -r 2c42ec3e656b sage/structure/coerce.pyx
a
|
b
|
|
1344 | 1344 | if is_Ring(S): |
1345 | 1345 | try: |
1346 | 1346 | K = S._pseudo_fraction_field() |
1347 | | except (TypeError, AttributeError): |
| 1347 | except (TypeError, AttributeError, NotImplementedError): |
1348 | 1348 | K = None |
1349 | 1349 | elif PY_TYPE_CHECK(S, Parent): |
1350 | 1350 | K = S |