# Ticket #10963: bla.py

File bla.py, 83.4 KB (added by , 8 years ago) |
---|

Line | |
---|---|

1 | """ |

2 | Coercion via Construction Functors |

3 | """ |

4 | from functor import Functor, IdentityFunctor_generic |

5 | from basic import * |

6 | |

7 | from sage.structure.parent import CoercionException |

8 | |

9 | # TODO, think through the rankings, and override pushout where necessary. |

10 | |

11 | class ConstructionFunctor(Functor): |

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 | def __mul__(self, other): |

73 | """ |

74 | Compose construction functors to a composit construction functor, unless one of them is the identity. |

75 | |

76 | NOTE: |

77 | |

78 | The product is in functorial notation, i.e., when applying the product to an object |

79 | then the second factor is applied first. |

80 | |

81 | TESTS:: |

82 | |

83 | sage: from sage.categories.pushout import IdentityConstructionFunctor |

84 | sage: I = IdentityConstructionFunctor() |

85 | sage: F = QQ.construction()[0] |

86 | sage: P = ZZ['t'].construction()[0] |

87 | sage: F*P |

88 | FractionField(Poly[t](...)) |

89 | sage: P*F |

90 | Poly[t](FractionField(...)) |

91 | sage: (F*P)(ZZ) |

92 | Fraction Field of Univariate Polynomial Ring in t over Integer Ring |

93 | sage: I*P is P |

94 | True |

95 | sage: F*I is F |

96 | True |

97 | |

98 | """ |

99 | if not isinstance(self, ConstructionFunctor) and not isinstance(other, ConstructionFunctor): |

100 | raise CoercionException, "Non-constructive product" |

101 | if isinstance(other,IdentityConstructionFunctor): |

102 | return self |

103 | if isinstance(self,IdentityConstructionFunctor): |

104 | return other |

105 | return CompositeConstructionFunctor(other, self) |

106 | |

107 | def pushout(self, other): |

108 | """ |

109 | Composition of two construction functors, ordered by their ranks. |

110 | |

111 | NOTE: |

112 | |

113 | - This method seems not to be used in the coercion model. |

114 | |

115 | - By default, the functor with smaller rank is applied first. |

116 | |

117 | TESTS:: |

118 | |

119 | sage: F = QQ.construction()[0] |

120 | sage: P = ZZ['t'].construction()[0] |

121 | sage: F.pushout(P) |

122 | Poly[t](FractionField(...)) |

123 | sage: P.pushout(F) |

124 | Poly[t](FractionField(...)) |

125 | |

126 | """ |

127 | if self.rank > other.rank: |

128 | return self * other |

129 | else: |

130 | return other * self |

131 | |

132 | def __cmp__(self, other): |

133 | """ |

134 | Equality here means that they are mathematically equivalent, though they may have |

135 | specific implementation data. This method will usually be overloaded in subclasses. |

136 | by default, only the types of the functors are compared. Also see the \code{merge} |

137 | function. |

138 | |

139 | TESTS:: |

140 | |

141 | sage: from sage.categories.pushout import IdentityConstructionFunctor |

142 | sage: I = IdentityConstructionFunctor() |

143 | sage: F = QQ.construction()[0] |

144 | sage: P = ZZ['t'].construction()[0] |

145 | sage: I == F # indirect doctest |

146 | False |

147 | sage: I == I # indirect doctest |

148 | True |

149 | |

150 | """ |

151 | return cmp(type(self), type(other)) |

152 | |

153 | def __str__(self): |

154 | """ |

155 | NOTE: |

156 | |

157 | By default, it returns the name of the construction functor's class. |

158 | Usually, this method will be overloaded. |

159 | |

160 | TEST:: |

161 | |

162 | sage: F = QQ.construction()[0] |

163 | sage: F # indirect doctest |

164 | FractionField |

165 | sage: Q = ZZ.quo(2).construction()[0] |

166 | sage: Q # indirect doctest |

167 | QuotientFunctor |

168 | |

169 | """ |

170 | s = str(type(self)) |

171 | import re |

172 | return re.sub("<.*'.*\.([^.]*)'>", "\\1", s) |

173 | |

174 | def __repr__(self): |

175 | """ |

176 | NOTE: |

177 | |

178 | By default, it returns the name of the construction functor's class. |

179 | Usually, this method will be overloaded. |

180 | |

181 | TEST:: |

182 | |

183 | sage: F = QQ.construction()[0] |

184 | sage: F # indirect doctest |

185 | FractionField |

186 | sage: Q = ZZ.quo(2).construction()[0] |

187 | sage: Q # indirect doctest |

188 | QuotientFunctor |

189 | |

190 | """ |

191 | return str(self) |

192 | |

193 | def merge(self, other): |

194 | """ |

195 | Merge ``self`` with another construction functor, or return None. |

196 | |

197 | NOTE: |

198 | |

199 | The default is to merge only if the two functors coincide. But this |

200 | may be overloaded for subclasses, such as the quotient functor. |

201 | |

202 | EXAMPLES:: |

203 | |

204 | sage: F = QQ.construction()[0] |

205 | sage: P = ZZ['t'].construction()[0] |

206 | sage: F.merge(F) |

207 | FractionField |

208 | sage: F.merge(P) |

209 | sage: P.merge(F) |

210 | sage: P.merge(P) |

211 | Poly[t] |

212 | |

213 | """ |

214 | if self == other: |

215 | return self |

216 | else: |

217 | return None |

218 | |

219 | def commutes(self, other): |

220 | """ |

221 | Determine whether ``self`` commutes with another construction functor. |

222 | |

223 | NOTE: |

224 | |

225 | By default, ``False`` is returned in all cases (even if the two |

226 | functors are the same, since in this case :meth:`merge` will apply |

227 | anyway). So far there is no construction functor that overloads |

228 | this method. Anyway, this method only becomes relevant if two |

229 | construction functors have the same rank. |

230 | |

231 | EXAMPLES:: |

232 | |

233 | sage: F = QQ.construction()[0] |

234 | sage: P = ZZ['t'].construction()[0] |

235 | sage: F.commutes(P) |

236 | False |

237 | sage: P.commutes(F) |

238 | False |

239 | sage: F.commutes(F) |

240 | False |

241 | |

242 | """ |

243 | return False |

244 | |

245 | def expand(self): |

246 | """ |

247 | Decompose ``self`` into a list of construction functors. |

248 | |

249 | NOTE: |

250 | |

251 | The default is to return the list only containing ``self``. |

252 | |

253 | EXAMPLE:: |

254 | |

255 | sage: F = QQ.construction()[0] |

256 | sage: F.expand() |

257 | [FractionField] |

258 | sage: Q = ZZ.quo(2).construction()[0] |

259 | sage: Q.expand() |

260 | [QuotientFunctor] |

261 | sage: P = ZZ['t'].construction()[0] |

262 | sage: FP = F*P |

263 | sage: FP.expand() |

264 | [FractionField, Poly[t]] |

265 | """ |

266 | return [self] |

267 | |

268 | |

269 | class CompositeConstructionFunctor(ConstructionFunctor): |

270 | """ |

271 | A Construction Functor composed by other Construction Functors. |

272 | |

273 | INPUT: |

274 | |

275 | ``F1, F2,...``: A list of Construction Functors. The result is the |

276 | composition ``F1`` followed by ``F2`` followed by ... |

277 | |

278 | EXAMPLES:: |

279 | |

280 | sage: from sage.categories.pushout import CompositeConstructionFunctor |

281 | sage: F = CompositeConstructionFunctor(QQ.construction()[0],ZZ['x'].construction()[0],QQ.construction()[0],ZZ['y'].construction()[0]) |

282 | sage: F |

283 | Poly[y](FractionField(Poly[x](FractionField(...)))) |

284 | sage: F == loads(dumps(F)) |

285 | True |

286 | sage: F == CompositeConstructionFunctor(*F.all) |

287 | True |

288 | sage: F(GF(2)['t']) |

289 | Univariate Polynomial Ring in y over Fraction Field of Univariate Polynomial Ring in x over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 2 (using NTL) |

290 | |

291 | """ |

292 | |

293 | def __init__(self, *args): |

294 | """ |

295 | TESTS:: |

296 | |

297 | sage: from sage.categories.pushout import CompositeConstructionFunctor |

298 | sage: F = CompositeConstructionFunctor(QQ.construction()[0],ZZ['x'].construction()[0],QQ.construction()[0],ZZ['y'].construction()[0]) |

299 | sage: F |

300 | Poly[y](FractionField(Poly[x](FractionField(...)))) |

301 | sage: F == CompositeConstructionFunctor(*F.all) |

302 | True |

303 | |

304 | """ |

305 | |

306 | def _apply_functor_to_morphism(self, f): |

307 | """ |

308 | Apply the functor to an object of ``self``'s domain. |

309 | |

310 | TESTS:: |

311 | |

312 | sage: from sage.categories.pushout import CompositeConstructionFunctor |

313 | sage: F = CompositeConstructionFunctor(QQ.construction()[0],ZZ['x'].construction()[0],QQ.construction()[0],ZZ['y'].construction()[0]) |

314 | sage: R.<a,b> = QQ[] |

315 | sage: f = R.hom([a+b, a-b]) |

316 | sage: F(f) # indirect doctest |

317 | Ring ... |

318 | """ |

319 | |

320 | def _apply_functor(self, R): |

321 | """ |

322 | Apply the functor to an object of ``self``'s domain. |

323 | |

324 | TESTS:: |

325 | |

326 | sage: from sage.categories.pushout import CompositeConstructionFunctor |

327 | |

328 | sage: R.<a,b> = QQ[] |

329 | sage: F(R) # indirect doctest |

330 | 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 |

331 | |

332 | """ |

333 | for c in self.all: |

334 | R = c(R) |

335 | return R |

336 | |

337 | def __cmp__(self, other): |

338 | """ |

339 | TESTS:: |

340 | |

341 | sage: from sage.categories.pushout import CompositeConstructionFunctor |

342 | |

343 | sage: F == loads(dumps(F)) # indirect doctest |

344 | True |

345 | |

346 | """ |

347 | if isinstance(other, CompositeConstructionFunctor): |

348 | return cmp(self.all, other.all) |

349 | else: |

350 | return cmp(type(self), type(other)) |

351 | |

352 | def __mul__(self, other): |

353 | """ |

354 | Compose construction functors to a composit construction functor, unless one of them is the identity. |

355 | |

356 | NOTE: |

357 | |

358 | The product is in functorial notation, i.e., when applying the product to an object |

359 | then the second factor is applied first. |

360 | |

361 | EXAMPLES:: |

362 | |

363 | sage: from sage.categories.pushout import CompositeConstructionFunctor |

364 | sage: F1 = CompositeConstructionFunctor(QQ.construction()[0],ZZ['x'].construction()[0]) |

365 | sage: F2 = CompositeConstructionFunctor(QQ.construction()[0],ZZ['y'].construction()[0]) |

366 | sage: F1*F2 |

367 | Poly[x](FractionField(Poly[y](FractionField(...)))) |

368 | |

369 | """ |

370 | if isinstance(self, CompositeConstructionFunctor): |

371 | all = [other] + self.all |

372 | elif isinstance(other,IdentityConstructionFunctor): |

373 | return self |

374 | else: |

375 | all = other.all + [self] |

376 | return CompositeConstructionFunctor(*all) |

377 | |

378 | def __str__(self): |

379 | """ |

380 | TESTS:: |

381 | |

382 | sage: from sage.categories.pushout import CompositeConstructionFunctor |

383 | |

384 | sage: F # indirect doctest |

385 | Poly[y](FractionField(Poly[x](FractionField(...)))) |

386 | |

387 | """ |

388 | s = "..." |

389 | for c in self.all: |

390 | s = "%s(%s)" % (c,s) |

391 | return s |

392 | |

393 | def expand(self): |

394 | """ |

395 | Return expansion of a CompositeConstructionFunctor. |

396 | |

397 | NOTE: |

398 | |

399 | The product over the list of components, as returned by |

400 | the ``expand()`` method, is equal to ``self``. |

401 | |

402 | EXAMPLES:: |

403 | |

404 | sage: from sage.categories.pushout import CompositeConstructionFunctor |

405 | |

406 | sage: F |

407 | Poly[y](FractionField(Poly[x](FractionField(...)))) |

408 | sage: prod(F.expand()) == F |

409 | True |

410 | |

411 | """ |

412 | return list(reversed(self.all)) |

413 | |

414 | |

415 | class IdentityConstructionFunctor(ConstructionFunctor): |

416 | """ |

417 | A construction functor that is the identity functor. |

418 | |

419 | TESTS:: |

420 | |

421 | sage: from sage.categories.pushout import IdentityConstructionFunctor |

422 | sage: I = IdentityConstructionFunctor() |

423 | """ |

424 | rank = -100 |

425 | |

426 | def __init__(self): |

427 | """ |

428 | TESTS:: |

429 | |

430 | sage: from sage.categories.pushout import IdentityConstructionFunctor |

431 | sage: I = IdentityConstructionFunctor() |

432 | sage: IdentityFunctor(Sets()) == I |

433 | True |

434 | sage: I(RR) is RR |

435 | True |

436 | |

437 | """ |

438 | ConstructionFunctor.__init__(self, Sets(), Sets()) |

439 | |

440 | def _apply_functor(self, x): |

441 | """ |

442 | Return the argument unaltered. |

443 | |

444 | TESTS:: |

445 | |

446 | sage: from sage.categories.pushout import IdentityConstructionFunctor |

447 | sage: I = IdentityConstructionFunctor() |

448 | sage: I(RR) is RR # indirect doctest |

449 | True |

450 | """ |

451 | return x |

452 | |

453 | def _apply_functor_to_morphism(self, f): |

454 | """ |

455 | Return the argument unaltered. |

456 | |

457 | TESTS:: |

458 | |

459 | sage: from sage.categories.pushout import IdentityConstructionFunctor |

460 | sage: I = IdentityConstructionFunctor() |

461 | sage: f = ZZ['t'].hom(['x'],QQ['x']) |

462 | """ |

463 | return f |

464 | |

465 | def __cmp__(self, other): |

466 | """ |

467 | TESTS:: |

468 | |

469 | sage: from sage.categories.pushout import IdentityConstructionFunctor |

470 | sage: I = IdentityConstructionFunctor() |

471 | sage: I == IdentityFunctor(Sets()) # indirect doctest |

472 | True |

473 | sage: I == QQ.construction()[0] |

474 | False |

475 | |

476 | """ |

477 | |

478 | def __mul__(self, other): |

479 | """ |

480 | Compose construction functors to a composit construction functor, unless one of them is the identity. |

481 | |

482 | NOTE: |

483 | |

484 | The product is in functorial notation, i.e., when applying the product to an object |

485 | then the second factor is applied first. |

486 | |

487 | TESTS:: |

488 | |

489 | sage: from sage.categories.pushout import IdentityConstructionFunctor |

490 | sage: I = IdentityConstructionFunctor() |

491 | sage: F = QQ.construction()[0] |

492 | sage: P = ZZ['t'].construction()[0] |

493 | sage: I*F is F # indirect doctest |

494 | True |

495 | sage: F*I is F |

496 | True |

497 | sage: I*P is P |

498 | True |

499 | sage: P*I is P |

500 | True |

501 | |

502 | """ |

503 | if isinstance(self, IdentityConstructionFunctor): |

504 | return other |

505 | else: |

506 | return self |

507 | |

508 | |

509 | class PolynomialFunctor(ConstructionFunctor): |

510 | """ |

511 | Construction functor for univariate polynomial rings. |

512 | |

513 | EXAMPLE:: |

514 | |

515 | sage: P = ZZ['t'].construction()[0] |

516 | sage: P(GF(3)) |

517 | Univariate Polynomial Ring in t over Finite Field of size 3 |

518 | sage: P == loads(dumps(P)) |

519 | True |

520 | sage: R.<x,y> = GF(5)[] |

521 | sage: f = R.hom([x+2*y,3*x-y],R) |

522 | sage: P(f)((x+y)*P(R).0) |

523 | (-x + y)*t |

524 | |

525 | By trac ticket #9944, the construction functor distinguishes sparse and |

526 | dense polynomial rings. Before, the following example failed:: |

527 | |

528 | sage: R.<x> = PolynomialRing(GF(5), sparse=True) |

529 | sage: F,B = R.construction() |

530 | sage: F(B) is R |

531 | True |

532 | sage: S.<x> = PolynomialRing(ZZ) |

533 | sage: R.has_coerce_map_from(S) |

534 | False |

535 | sage: S.has_coerce_map_from(R) |

536 | False |

537 | sage: S.0 + R.0 |

538 | 2*x |

539 | sage: 1+1 |

540 | 2 |

541 | sage: 1+1 |

542 | 2 |

543 | """ |

544 | rank = 9 |

545 | |

546 | def __init__(self, var, multi_variate=False, sparse=False): |

547 | """ |

548 | TESTS:: |

549 | |

550 | sage: from sage.categories.pushout import PolynomialFunctor |

551 | sage: P = PolynomialFunctor('x') |

552 | sage: P(GF(3)) |

553 | Univariate Polynomial Ring in x over Finite Field of size 3 |

554 | |

555 | There is an optional parameter ``multi_variate``, but |

556 | apparently it is not used:: |

557 | |

558 | sage: Q = PolynomialFunctor('x',multi_variate=True) |

559 | sage: Q(ZZ) |

560 | Univariate Polynomial Ring in x over Integer Ring |

561 | sage: Q == P |

562 | True |

563 | |

564 | """ |

565 | from rings import Rings |

566 | Functor.__init__(self, Rings(), Rings()) |

567 | self.var = var |

568 | self.multi_variate = multi_variate |

569 | self.sparse = sparse |

570 | |

571 | def _apply_functor(self, R): |

572 | """ |

573 | Apply the functor to an object of ``self``'s domain. |

574 | |

575 | TEST:: |

576 | |

577 | sage: P = ZZ['x'].construction()[0] |

578 | sage: P(GF(3)) # indirect doctest |

579 | Univariate Polynomial Ring in x over Finite Field of size 3 |

580 | |

581 | """ |

582 | from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing |

583 | return PolynomialRing(R, self.var, sparse=self.sparse) |

584 | |

585 | def __cmp__(self, other): |

586 | """ |

587 | TESTS:: |

588 | |

589 | sage: from sage.categories.pushout import MultiPolynomialFunctor |

590 | sage: Q = MultiPolynomialFunctor(('x',),'lex') |

591 | sage: P = ZZ['x'].construction()[0] |

592 | sage: P |

593 | Poly[x] |

594 | sage: Q |

595 | MPoly[x] |

596 | sage: P == Q |

597 | True |

598 | sage: P == loads(dumps(P)) |

599 | True |

600 | sage: P == QQ.construction()[0] |

601 | False |

602 | """ |

603 | |

604 | def merge(self, other): |

605 | """ |

606 | EXAMPLE:: |

607 | |

608 | sage: P = ZZ['x'].construction()[0] |

609 | sage: Q = ZZ['y','x'].construction()[0] |

610 | sage: P.merge(Q) |

611 | sage: P.merge(P) is P |

612 | True |

613 | |

614 | """ |

615 | if isinstance(other, MultiPolynomialFunctor): |

616 | return other.merge(self) |

617 | elif self == other: |

618 | # i.e., they only differ in sparsity |

619 | if not self.sparse: |

620 | return self |

621 | return other |

622 | else: |

623 | return None |

624 | |

625 | def __str__(self): |

626 | """ |

627 | TEST:: |

628 | |

629 | sage: P = ZZ['x'].construction()[0] |

630 | sage: P # indirect doctest |

631 | Poly[x] |

632 | |

633 | """ |

634 | return "Poly[%s]" % self.var |

635 | |

636 | class MultiPolynomialFunctor(ConstructionFunctor): |

637 | """ |

638 | A constructor for multivariate polynomial rings. |

639 | |

640 | EXAMPLES:: |

641 | |

642 | sage: P.<x,y> = ZZ[] |

643 | sage: F = P.construction()[0]; F |

644 | MPoly[x,y] |

645 | sage: A.<a,b> = GF(5)[] |

646 | sage: F(A) |

647 | Multivariate Polynomial Ring in x, y over Multivariate Polynomial Ring in a, b over Finite Field of size 5 |

648 | sage: f = A.hom([a+b,a-b],A) |

649 | sage: F(f) |

650 | Ring endomorphism of Multivariate Polynomial Ring in x, y over Multivariate Polynomial Ring in a, b over Finite Field of size 5 |

651 | Defn: Induced from base ring by |

652 | Ring endomorphism of Multivariate Polynomial Ring in a, b over Finite Field of size 5 |

653 | Defn: a |--> a + b |

654 | b |--> a - b |

655 | sage: F(f)(F(A)(x)*a) |

656 | (a + b)*x |

657 | |

658 | """ |

659 | |

660 | rank = 9 |

661 | |

662 | def __init__(self, vars, term_order): |

663 | """ |

664 | EXAMPLES:: |

665 | |

666 | sage: F = sage.categories.pushout.MultiPolynomialFunctor(['x','y'], None) |

667 | sage: F(CC) |

668 | Multivariate Polynomial Ring in x, y over Complex Field with 53 bits of precision |

669 | """ |

670 | Functor.__init__(self, Rings(), Rings()) |

671 | self.vars = vars |

672 | self.term_order = term_order |

673 | |

674 | def _apply_functor(self, R): |

675 | """ |

676 | Apply the functor to an object of ``self``'s domain. |

677 | |

678 | EXAMPLES:: |

679 | |

680 | sage: R.<x,y,z> = QQ[] |

681 | sage: F = R.construction()[0]; F |

682 | MPoly[x,y,z] |

683 | sage: F(RR) # indirect doctest |

684 | Multivariate Polynomial Ring in x, y, z over Real Field with 53 bits of precision |

685 | sage: F(RR) # indirect doctest |

686 | Multivariate Polynomial Ring in x, y, z over Real Field with 53 bits of precision |

687 | sage: F(RR) # indirect doctest |

688 | Multivariate Polynomial Ring in x, y, z over Real Field with 53 bits of precision |

689 | sage: F(RR) # indirect doctest |

690 | Multivariate Polynomial Ring in x, y, z over Real Field with 53 bits of precision |

691 | sage: F(RR) # indirect doctest |

692 | Multivariate Polynomial Ring in x, y, z over Real Field with 53 bits of precision |

693 | """ |

694 | from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing |

695 | return PolynomialRing(R, self.vars) |

696 | |

697 | def __cmp__(self, other): |

698 | """ |

699 | EXAMPLES:: |

700 | |

701 | sage: F = ZZ['x,y,z'].construction()[0] |

702 | sage: G = QQ['x,y,z'].construction()[0] |

703 | sage: F == G |

704 | True |

705 | sage: G == loads(dumps(G)) |

706 | True |

707 | sage: G = ZZ['x,y'].construction()[0] |

708 | sage: F == G |

709 | False |

710 | """ |

711 | c = cmp(type(self), type(other)) |

712 | if c == 0: |

713 | c = cmp(self.vars, other.vars) or cmp(self.term_order, other.term_order) |

714 | elif isinstance(other, PolynomialFunctor): |

715 | c = cmp(self.vars, (other.var,)) |

716 | return c |

717 | |

718 | def __mul__(self, other): |

719 | """ |

720 | If two MPoly functors are given in a row, form a single MPoly functor |

721 | with all of the variables. |

722 | |

723 | EXAMPLES:: |

724 | |

725 | sage: F = sage.categories.pushout.MultiPolynomialFunctor(['x','y'], None) |

726 | sage: G = sage.categories.pushout.MultiPolynomialFunctor(['t'], None) |

727 | sage: G*F |

728 | MPoly[x,y,t] |

729 | """ |

730 | if isinstance(other,IdentityConstructionFunctor): |

731 | return self |

732 | if isinstance(other, MultiPolynomialFunctor): |

733 | if self.term_order != other.term_order: |

734 | raise CoercionException, "Incompatible term orders (%s,%s)." % (self.term_order, other.term_order) |

735 | if set(self.vars).intersection(other.vars): |

736 | raise CoercionException, "Overlapping variables (%s,%s)" % (self.vars, other.vars) |

737 | return MultiPolynomialFunctor(other.vars + self.vars, self.term_order) |

738 | elif isinstance(other, CompositeConstructionFunctor) \ |

739 | and isinstance(other.all[-1], MultiPolynomialFunctor): |

740 | return CompositeConstructionFunctor(other.all[:-1], self * other.all[-1]) |

741 | else: |

742 | return CompositeConstructionFunctor(other, self) |

743 | |

744 | def merge(self, other): |

745 | """ |

746 | Merge ``self`` with another construction functor, or return None. |

747 | |

748 | EXAMPLES:: |

749 | |

750 | sage: F = sage.categories.pushout.MultiPolynomialFunctor(['x','y'], None) |

751 | sage: G = sage.categories.pushout.MultiPolynomialFunctor(['t'], None) |

752 | sage: F.merge(G) is None |

753 | True |

754 | sage: F.merge(F) |

755 | MPoly[x,y] |

756 | """ |

757 | if self == other: |

758 | return self |

759 | else: |

760 | return None |

761 | |

762 | def expand(self): |

763 | """ |

764 | Decompose ``self`` into a list of construction functors. |

765 | |

766 | EXAMPLES:: |

767 | |

768 | sage: F = QQ['x,y,z,t'].construction()[0]; F |

769 | MPoly[x,y,z,t] |

770 | sage: F.expand() |

771 | [MPoly[t], MPoly[z], MPoly[y], MPoly[x]] |

772 | |

773 | Now an actual use case:: |

774 | |

775 | sage: R.<x,y,z> = ZZ[] |

776 | sage: S.<z,t> = QQ[] |

777 | sage: x+t |

778 | x + t |

779 | sage: parent(x+t) |

780 | Multivariate Polynomial Ring in x, y, z, t over Rational Field |

781 | sage: T.<y,s> = QQ[] |

782 | sage: x + s |

783 | Traceback (most recent call last): |

784 | ... |

785 | TypeError: unsupported operand parent(s) for '+': 'Multivariate Polynomial Ring in x, y, z over Integer Ring' and 'Multivariate Polynomial Ring in y, s over Rational Field' |

786 | sage: R = PolynomialRing(ZZ, 'x', 500) |

787 | sage: S = PolynomialRing(GF(5), 'x', 200) |

788 | sage: R.gen(0) + S.gen(0) |

789 | 2*x0 |

790 | """ |

791 | if len(self.vars) <= 1: |

792 | return [self] |

793 | else: |

794 | return [MultiPolynomialFunctor((x,), self.term_order) for x in reversed(self.vars)] |

795 | |

796 | def __str__(self): |

797 | """ |

798 | TEST:: |

799 | |

800 | sage: QQ['x,y,z,t'].construction()[0] |

801 | MPoly[x,y,z,t] |

802 | """ |

803 | return "MPoly[%s]" % ','.join(self.vars) |

804 | |

805 | |

806 | |

807 | class InfinitePolynomialFunctor(ConstructionFunctor): |

808 | """ |

809 | A Construction Functor for Infinite Polynomial Rings (see :mod:`~sage.rings.polynomial.infinite_polynomial_ring`). |

810 | |

811 | AUTHOR: |

812 | |

813 | -- Simon King |

814 | |

815 | This construction functor is used to provide uniqueness of infinite polynomial rings as parent structures. |

816 | As usual, the construction functor allows for constructing pushouts. |

817 | |

818 | Another purpose is to avoid name conflicts of variables of the to-be-constructed infinite polynomial ring with |

819 | variables of the base ring, and moreover to keep the internal structure of an Infinite Polynomial Ring as simple |

820 | as possible: If variables `v_1,...,v_n` of the given base ring generate an *ordered* sub-monoid of the monomials |

821 | of the ambient Infinite Polynomial Ring, then they are removed from the base ring and merged with the generators |

822 | of the ambient ring. However, if the orders don't match, an error is raised, since there was a name conflict |

823 | without merging. |

824 | |

825 | EXAMPLES:: |

826 | |

827 | sage: A.<a,b> = InfinitePolynomialRing(ZZ['t']) |

828 | sage: A.construction() |

829 | [InfPoly{[a,b], "lex", "dense"}, |

830 | Univariate Polynomial Ring in t over Integer Ring] |

831 | sage: type(_[0]) |

832 | <class 'sage.categories.pushout.InfinitePolynomialFunctor'> |

833 | sage: B.<x,y,a_3,a_1> = PolynomialRing(QQ, order='lex') |

834 | sage: B.construction() |

835 | (MPoly[x,y,a_3,a_1], Rational Field) |

836 | sage: A.construction()[0]*B.construction()[0] |

837 | InfPoly{[a,b], "lex", "dense"}(MPoly[x,y](...)) |

838 | |

839 | Apparently the variables `a_1,a_3` of the polynomial ring are merged with the variables |

840 | `a_0, a_1, a_2, ...` of the infinite polynomial ring; indeed, they form an ordered sub-structure. |

841 | However, if the polynomial ring was given a different ordering, merging would not be allowed, |

842 | resulting in a name conflict:: |

843 | |

844 | sage: A.construction()[0]*PolynomialRing(QQ,names=['x','y','a_3','a_1']).construction()[0] |

845 | Traceback (most recent call last): |

846 | ... |

847 | CoercionException: Incompatible term orders lex, degrevlex |

848 | |

849 | In an infinite polynomial ring with generator `a_\\ast`, the variable `a_3` will always be greater |

850 | than the variable `a_1`. Hence, the orders are incompatible in the next example as well:: |

851 | |

852 | sage: A.construction()[0]*PolynomialRing(QQ,names=['x','y','a_1','a_3'], order='lex').construction()[0] |

853 | Traceback (most recent call last): |

854 | ... |

855 | CoercionException: Overlapping variables (('a', 'b'),['a_1', 'a_3']) are incompatible |

856 | |

857 | Another requirement is that after merging the order of the remaining variables must be unique. |

858 | This is not the case in the following example, since it is not clear whether the variables `x,y` |

859 | should be greater or smaller than the variables `b_\\ast`:: |

860 | |

861 | sage: A.construction()[0]*PolynomialRing(QQ,names=['a_3','a_1','x','y'], order='lex').construction()[0] |

862 | Traceback (most recent call last): |

863 | ... |

864 | CoercionException: Overlapping variables (('a', 'b'),['a_3', 'a_1']) are incompatible |

865 | |

866 | Since the construction functors are actually used to construct infinite polynomial rings, the following |

867 | result is no surprise:: |

868 | |

869 | sage: C.<a,b> = InfinitePolynomialRing(B); C |

870 | Infinite polynomial ring in a, b over Multivariate Polynomial Ring in x, y over Rational Field |

871 | |

872 | There is also an overlap in the next example:: |

873 | |

874 | sage: X.<w,x,y> = InfinitePolynomialRing(ZZ) |

875 | sage: Y.<x,y,z> = InfinitePolynomialRing(QQ) |

876 | |

877 | `X` and `Y` have an overlapping generators `x_\\ast, y_\\ast`. Since the default lexicographic order is |

878 | used in both rings, it gives rise to isomorphic sub-monoids in both `X` and `Y`. They are merged in the |

879 | pushout, which also yields a common parent for doing arithmetic:: |

880 | |

881 | sage: P = sage.categories.pushout.pushout(Y,X); P |

882 | Infinite polynomial ring in w, x, y, z over Rational Field |

883 | sage: w[2]+z[3] |

884 | w_2 + z_3 |

885 | sage: _.parent() is P |

886 | True |

887 | """ |

888 | |

889 | def __init__(self, gens, order, implementation): |

890 | """ |

891 | TEST:: |

892 | |

893 | sage: 1+1 |

894 | 2 |

895 | sage: 1+1 |

896 | 2 |

897 | """ |

898 | |

899 | def _apply_functor_to_morphism(self, f): |

900 | """ |

901 | Morphisms for inifinite polynomial rings are not implemented yet. |

902 | |

903 | TEST:: |

904 | |

905 | sage: P.<x,y> = QQ[] |

906 | sage: R.<alpha> = InfinitePolynomialRing(P) |

907 | sage: 1+1 |

908 | 2 |

909 | sage: 1+1 |

910 | 2 |

911 | sage: 1+1 |

912 | 2 |

913 | """ |

914 | |

915 | def _apply_functor(self, R): |

916 | """ |

917 | Apply the functor to an object of ``self``'s domain. |

918 | |

919 | TEST:: |

920 | |

921 | sage: F = sage.categories.pushout.InfinitePolynomialFunctor(['a','b','x'],'degrevlex','sparse'); F |

922 | InfPoly{[a,b,x], "degrevlex", "sparse"} |

923 | sage: F(QQ['t']) # indirect doctest |

924 | Infinite polynomial ring in a, b, x over Univariate Polynomial Ring in t over Rational Field |

925 | |

926 | """ |

927 | from sage.rings.polynomial.infinite_polynomial_ring import InfinitePolynomialRing |

928 | return InfinitePolynomialRing(R, self._gens, order=self._order, implementation=self._imple) |

929 | |

930 | def __str__(self): |

931 | """ |

932 | TEST:: |

933 | |

934 | sage: F = sage.categories.pushout.InfinitePolynomialFunctor(['a','b','x'],'degrevlex','sparse'); F # indirect doctest |

935 | InfPoly{[a,b,x], "degrevlex", "sparse"} |

936 | |

937 | """ |

938 | return 'InfPoly{[%s], "%s", "%s"}'%(','.join(self._gens), self._order, self._imple) |

939 | |

940 | def __cmp__(self, other): |

941 | """ |

942 | TEST:: |

943 | |

944 | sage: F = sage.categories.pushout.InfinitePolynomialFunctor(['a','b','x'],'degrevlex','sparse'); F # indirect doctest |

945 | InfPoly{[a,b,x], "degrevlex", "sparse"} |

946 | sage: F == sage.categories.pushout.InfinitePolynomialFunctor(['a','b','x'],'deglex','sparse') |

947 | False |

948 | |

949 | """ |

950 | c = cmp(type(self), type(other)) |

951 | if c == 0: |

952 | c = cmp(self._gens, other._gens) or cmp(self._order, other._order) or cmp(self._imple, other._imple) |

953 | return c |

954 | |

955 | def __mul__(self, other): |

956 | """ |

957 | |

958 | |

959 | NOTE: |

960 | |

961 | The product is in functorial notation, i.e., when applying the product to an object |

962 | then the second factor is applied first. |

963 | |

964 | TESTS:: |

965 | |

966 | sage: F1 = QQ['a','x_2','x_1','y_3','y_2'].construction()[0]; F1 |

967 | MPoly[a,x_2,x_1,y_3,y_2] |

968 | sage: F2 = InfinitePolynomialRing(QQ, ['x','y'],order='degrevlex').construction()[0]; F2 |

969 | InfPoly{[x,y], "degrevlex", "dense"} |

970 | sage: F3 = InfinitePolynomialRing(QQ, ['x','y'],order='degrevlex',implementation='sparse').construction()[0]; F3 |

971 | InfPoly{[x,y], "degrevlex", "sparse"} |

972 | sage: F2*F1 |

973 | InfPoly{[x,y], "degrevlex", "dense"}(Poly[a](...)) |

974 | sage: F3*F1 |

975 | InfPoly{[x,y], "degrevlex", "sparse"}(Poly[a](...)) |

976 | sage: F4 = sage.categories.pushout.FractionField() |

977 | sage: F2*F4 |

978 | InfPoly{[x,y], "degrevlex", "dense"}(FractionField(...)) |

979 | |

980 | """ |

981 | if isinstance(other,IdentityConstructionFunctor): |

982 | return self |

983 | if isinstance(other, self.__class__): # |

984 | INT = set(self._gens).intersection(other._gens) |

985 | if INT: |

986 | # if there is overlap of generators, it must only be at the ends, so that |

987 | # the resulting order after the merging is unique |

988 | if other._gens[-len(INT):] != self._gens[:len(INT)]: |

989 | raise CoercionException, "Overlapping variables (%s,%s) are incompatible" % (self._gens, other._gens) |

990 | OUTGENS = list(other._gens) + list(self._gens[len(INT):]) |

991 | else: |

992 | OUTGENS = list(other._gens) + list(self._gens) |

993 | # the orders must coincide |

994 | if self._order != other._order: |

995 | return CompositeConstructionFunctor(other, self) |

996 | # the implementations must coincide |

997 | if self._imple != other._imple: |

998 | return CompositeConstructionFunctor(other, self) |

999 | return InfinitePolynomialFunctor(OUTGENS, self._order, self._imple) |

1000 | |

1001 | # Polynomial Constructor |

1002 | # Idea: We merge into self, if the polynomial functor really provides a substructure, |

1003 | # even respecting the order. Note that, if the pushout is computed, only *one* variable |

1004 | # will occur in the polynomial constructor. Hence, any order is fine, which is exactly |

1005 | # what we need in order to have coercion maps for different orderings. |

1006 | if isinstance(other, MultiPolynomialFunctor) or isinstance(other, PolynomialFunctor): |

1007 | if isinstance(other, MultiPolynomialFunctor): |

1008 | othervars = other.vars |

1009 | else: |

1010 | othervars = [other.var] |

1011 | OverlappingGens = [] ## Generator names of variable names of the MultiPolynomialFunctor |

1012 | ## that can be interpreted as variables in self |

1013 | OverlappingVars = [] ## The variable names of the MultiPolynomialFunctor |

1014 | ## that can be interpreted as variables in self |

1015 | RemainingVars = [x for x in othervars] |

1016 | IsOverlap = False |

1017 | BadOverlap = False |

1018 | for x in othervars: |

1019 | if x.count('_') == 1: |

1020 | g,n = x.split('_') |

1021 | if n.isdigit(): |

1022 | if g.isalnum(): # we can interprete x in any InfinitePolynomialRing |

1023 | if g in self._gens: # we can interprete x in self, hence, we will not use it as a variable anymore. |

1024 | RemainingVars.pop(RemainingVars.index(x)) |

1025 | IsOverlap = True # some variables of other can be interpreted in self. |

1026 | if OverlappingVars: |

1027 | # Is OverlappingVars in the right order? |

1028 | g0,n0 = OverlappingVars[-1].split('_') |

1029 | i = self._gens.index(g) |

1030 | i0 = self._gens.index(g0) |

1031 | if i<i0: # wrong order |

1032 | BadOverlap = True |

1033 | if i==i0 and int(n)>int(n0): # wrong order |

1034 | BadOverlap = True |

1035 | OverlappingVars.append(x) |

1036 | else: |

1037 | if IsOverlap: # The overlap must be on the right end of the variable list |

1038 | BadOverlap = True |

1039 | else: |

1040 | if IsOverlap: # The overlap must be on the right end of the variable list |

1041 | BadOverlap = True |

1042 | else: |

1043 | if IsOverlap: # The overlap must be on the right end of the variable list |

1044 | BadOverlap = True |

1045 | else: |

1046 | if IsOverlap: # The overlap must be on the right end of the variable list |

1047 | BadOverlap = True |

1048 | |

1049 | if BadOverlap: # the overlapping variables appear in the wrong order |

1050 | raise CoercionException, "Overlapping variables (%s,%s) are incompatible" % (self._gens, OverlappingVars) |

1051 | if len(OverlappingVars)>1: # multivariate, hence, the term order matters |

1052 | if other.term_order.name()!=self._order: |

1053 | raise CoercionException, "Incompatible term orders %s, %s" % (self._order, other.term_order.name()) |

1054 | # ok, the overlap is fine, we will return something. |

1055 | if RemainingVars: # we can only partially merge other into self |

1056 | if len(RemainingVars)>1: |

1057 | return CompositeConstructionFunctor(MultiPolynomialFunctor(RemainingVars,term_order=other.term_order), self) |

1058 | return CompositeConstructionFunctor(PolynomialFunctor(RemainingVars[0]), self) |

1059 | return self |

1060 | return CompositeConstructionFunctor(other, self) |

1061 | |

1062 | def merge(self,other): |

1063 | """ |

1064 | Merge two construction functors of infinite polynomial rings, regardless of monomial order and implementation. |

1065 | |

1066 | The purpose is to have a pushout (and thus, arithmetic) even in cases when the parents are isomorphic as |

1067 | rings, but not as ordered rings. |

1068 | |

1069 | EXAMPLES:: |

1070 | |

1071 | sage: X.<x,y> = InfinitePolynomialRing(QQ,implementation='sparse') |

1072 | sage: Y.<x,y> = InfinitePolynomialRing(QQ,order='degrevlex') |

1073 | sage: X.construction() |

1074 | [InfPoly{[x,y], "lex", "sparse"}, Rational Field] |

1075 | sage: Y.construction() |

1076 | [InfPoly{[x,y], "degrevlex", "dense"}, Rational Field] |

1077 | sage: Y.construction()[0].merge(Y.construction()[0]) |

1078 | InfPoly{[x,y], "degrevlex", "dense"} |

1079 | sage: y[3] + X(x[2]) |

1080 | x_2 + y_3 |

1081 | sage: _.parent().construction() |

1082 | [InfPoly{[x,y], "degrevlex", "dense"}, Rational Field] |

1083 | |

1084 | """ |

1085 | # Merging is only done if the ranks of self and other are the same. |

1086 | # It may happen that other is a substructure of self up to the monomial order |

1087 | # and the implementation. And this is when we want to merge, in order to |

1088 | # provide multiplication for rings with different term orderings. |

1089 | if not isinstance(other, InfinitePolynomialFunctor): |

1090 | return None |

1091 | if set(other._gens).issubset(self._gens): |

1092 | return self |

1093 | return None |

1094 | try: |

1095 | OUT = self*other |

1096 | # The following happens if "other" has the same order type etc. |

1097 | if not isinstance(OUT, CompositeConstructionFunctor): |

1098 | return OUT |

1099 | except CoercionException: |

1100 | pass |

1101 | if isinstance(other,InfinitePolynomialFunctor): |

1102 | # We don't require that the orders coincide. This is a difference to self*other |

1103 | # We only merge if other's generators are an ordered subset of self's generators |

1104 | for g in other._gens: |

1105 | if g not in self._gens: |

1106 | return None |

1107 | # The sequence of variables is part of the ordering. It must coincide in both rings |

1108 | Ind = [self._gens.index(g) for g in other._gens] |

1109 | if sorted(Ind)!=Ind: |

1110 | return None |

1111 | # OK, other merges into self. Now, chose the default dense implementation, |

1112 | # unless both functors refer to the sparse implementation |

1113 | if self._imple != other._imple: |

1114 | return InfinitePolynomialFunctor(self._gens, self._order, 'dense') |

1115 | return self |

1116 | return None |

1117 | |

1118 | def expand(self): |

1119 | """ |

1120 | Decompose the functor `F` into sub-functors, whose product returns `F`. |

1121 | |

1122 | EXAMPLES:: |

1123 | |

1124 | sage: F = InfinitePolynomialRing(QQ, ['x','y'],order='degrevlex').construction()[0]; F |

1125 | InfPoly{[x,y], "degrevlex", "dense"} |

1126 | sage: F.expand() |

1127 | [InfPoly{[y], "degrevlex", "dense"}, InfPoly{[x], "degrevlex", "dense"}] |

1128 | sage: F = InfinitePolynomialRing(QQ, ['x','y','z'],order='degrevlex').construction()[0]; F |

1129 | InfPoly{[x,y,z], "degrevlex", "dense"} |

1130 | sage: F.expand() |

1131 | [InfPoly{[z], "degrevlex", "dense"}, |

1132 | InfPoly{[y], "degrevlex", "dense"}, |

1133 | InfPoly{[x], "degrevlex", "dense"}] |

1134 | sage: prod(F.expand())==F |

1135 | True |

1136 | |

1137 | """ |

1138 | if len(self._gens)==1: |

1139 | return [self] |

1140 | return [InfinitePolynomialFunctor((x,), self._order, self._imple) for x in reversed(self._gens)] |

1141 | |

1142 | |

1143 | |

1144 | class MatrixFunctor(ConstructionFunctor): |

1145 | """ |

1146 | A construction functor for matrices over rings. |

1147 | |

1148 | EXAMPLES:: |

1149 | |

1150 | sage: MS = MatrixSpace(ZZ,2, 3) |

1151 | sage: F = MS.construction()[0]; F |

1152 | MatrixFunctor |

1153 | sage: MS = MatrixSpace(ZZ,2) |

1154 | sage: F = MS.construction()[0]; F |

1155 | MatrixFunctor |

1156 | sage: P.<x,y> = QQ[] |

1157 | sage: R = F(P); R |

1158 | Full MatrixSpace of 2 by 2 dense matrices over Multivariate Polynomial Ring in x, y over Rational Field |

1159 | sage: f = P.hom([x+y,x-y],P); F(f) |

1160 | Ring endomorphism of Full MatrixSpace of 2 by 2 dense matrices over Multivariate Polynomial Ring in x, y over Rational Field |

1161 | Defn: Induced from base ring by |

1162 | Ring endomorphism of Multivariate Polynomial Ring in x, y over Rational Field |

1163 | Defn: x |--> x + y |

1164 | y |--> x - y |

1165 | sage: M = R([x,y,x*y,x+y]) |

1166 | sage: F(f)(M) |

1167 | [ x + y x - y] |

1168 | [x^2 - y^2 2*x] |

1169 | |

1170 | """ |

1171 | rank = 10 |

1172 | |

1173 | def __init__(self, nrows, ncols, is_sparse=False): |

1174 | """ |

1175 | TEST:: |

1176 | |

1177 | sage: from sage.categories.pushout import MatrixFunctor |

1178 | sage: F = MatrixFunctor(2,3) |

1179 | sage: F == MatrixSpace(ZZ,2,3).construction()[0] |

1180 | True |

1181 | sage: F.codomain() |

1182 | Category of commutative additive groups |

1183 | sage: R = MatrixSpace(ZZ,2,2).construction()[0] |

1184 | sage: R.codomain() |

1185 | Category of rings |

1186 | sage: F(ZZ) |

1187 | Full MatrixSpace of 2 by 3 dense matrices over Integer Ring |

1188 | sage: F(ZZ) in F.codomain() |

1189 | True |

1190 | sage: R(GF(2)) |

1191 | Full MatrixSpace of 2 by 2 dense matrices over Finite Field of size 2 |

1192 | sage: R(GF(2)) in R.codomain() |

1193 | True |

1194 | """ |

1195 | if nrows == ncols: |

1196 | Functor.__init__(self, Rings(), Rings()) # Algebras() takes a base ring |

1197 | else: |

1198 | # Functor.__init__(self, Rings(), MatrixAlgebras()) # takes a base ring |

1199 | Functor.__init__(self, Rings(), CommutativeAdditiveGroups()) # not a nice solution, but the best we can do. |

1200 | self.nrows = nrows |

1201 | self.ncols = ncols |

1202 | self.is_sparse = is_sparse |

1203 | |

1204 | def _apply_functor(self, R): |

1205 | """ |

1206 | Apply the functor to an object of ``self``'s domain. |

1207 | |

1208 | TEST: |

1209 | |

1210 | The following is a test against a bug discussed at ticket #8800 |

1211 | |

1212 | sage: F = MatrixSpace(ZZ,2,3).construction()[0] |

1213 | sage: F(RR) # indirect doctest |

1214 | Full MatrixSpace of 2 by 3 dense matrices over Real Field with 53 bits of precision |

1215 | sage: F(RR) in F.codomain() |

1216 | True |

1217 | |

1218 | """ |

1219 | from sage.matrix.matrix_space import MatrixSpace |

1220 | return MatrixSpace(R, self.nrows, self.ncols, sparse=self.is_sparse) |

1221 | |

1222 | def __cmp__(self, other): |

1223 | """ |

1224 | TEST:: |

1225 | |

1226 | sage: F = MatrixSpace(ZZ,2,3).construction()[0] |

1227 | sage: F == loads(dumps(F)) |

1228 | True |

1229 | sage: F == MatrixSpace(ZZ,2,2).construction()[0] |

1230 | False |

1231 | |

1232 | """ |

1233 | c = cmp(type(self), type(other)) |

1234 | if c == 0: |

1235 | c = cmp((self.nrows, self.ncols), (other.nrows, other.ncols)) |

1236 | return c |

1237 | |

1238 | def merge(self, other): |

1239 | """ |

1240 | Merging is only happening if both functors are matrix functors of the same dimension. |

1241 | The result is sparse if and only if both given functors are sparse. |

1242 | |

1243 | EXAMPLE:: |

1244 | |

1245 | sage: F1 = MatrixSpace(ZZ,2,2).construction()[0] |

1246 | sage: F2 = MatrixSpace(ZZ,2,3).construction()[0] |

1247 | sage: F3 = MatrixSpace(ZZ,2,2,sparse=True).construction()[0] |

1248 | sage: F1.merge(F2) |

1249 | sage: F1.merge(F3) |

1250 | MatrixFunctor |

1251 | sage: F13 = F1.merge(F3) |

1252 | sage: F13.is_sparse |

1253 | False |

1254 | sage: F1.is_sparse |

1255 | False |

1256 | sage: F3.is_sparse |

1257 | True |

1258 | sage: F3.merge(F3).is_sparse |

1259 | True |

1260 | |

1261 | """ |

1262 | if self != other: |

1263 | return None |

1264 | else: |

1265 | return MatrixFunctor(self.nrows, self.ncols, self.is_sparse and other.is_sparse) |

1266 | |

1267 | class LaurentPolynomialFunctor(ConstructionFunctor): |

1268 | """ |

1269 | Construction functor for Laurent polynomial rings. |

1270 | |

1271 | EXAMPLES:: |

1272 | |

1273 | sage: L.<t> = LaurentPolynomialRing(ZZ) |

1274 | sage: F = L.construction()[0] |

1275 | sage: F |

1276 | LaurentPolynomialFunctor |

1277 | sage: F(QQ) |

1278 | Univariate Laurent Polynomial Ring in t over Rational Field |

1279 | sage: K.<x> = LaurentPolynomialRing(ZZ) |

1280 | sage: F(K) |

1281 | Univariate Laurent Polynomial Ring in t over Univariate Laurent Polynomial Ring in x over Integer Ring |

1282 | sage: P.<x,y> = ZZ[] |

1283 | sage: f = P.hom([x+2*y,3*x-y],P) |

1284 | sage: F(f) |

1285 | Ring endomorphism of Univariate Laurent Polynomial Ring in t over Multivariate Polynomial Ring in x, y over Integer Ring |

1286 | Defn: Induced from base ring by |

1287 | Ring endomorphism of Multivariate Polynomial Ring in x, y over Integer Ring |

1288 | Defn: x |--> x + 2*y |

1289 | y |--> 3*x - y |

1290 | sage: F(f)(x*F(P).gen()^-2+y*F(P).gen()^3) |

1291 | (3*x - y)*t^3 + (x + 2*y)*t^-2 |

1292 | |

1293 | """ |

1294 | rank = 9 |

1295 | |

1296 | def __init__(self, var, multi_variate=False): |

1297 | """ |

1298 | INPUT: |

1299 | |

1300 | - ``var``, a string or a list of strings |

1301 | - ``multi_variate``, optional bool, default ``False`` if ``var`` is a string |

1302 | and ``True`` otherwise: If ``True``, application to a Laurent polynomial |

1303 | ring yields a multivariate Laurent polynomial ring. |

1304 | |

1305 | TESTS:: |

1306 | |

1307 | sage: from sage.categories.pushout import LaurentPolynomialFunctor |

1308 | sage: F1 = LaurentPolynomialFunctor('t') |

1309 | sage: F2 = LaurentPolynomialFunctor('s', multi_variate=True) |

1310 | sage: F3 = LaurentPolynomialFunctor(['s','t']) |

1311 | sage: F1(F2(QQ)) |

1312 | Univariate Laurent Polynomial Ring in t over Univariate Laurent Polynomial Ring in s over Rational Field |

1313 | sage: F2(F1(QQ)) |

1314 | Multivariate Laurent Polynomial Ring in t, s over Rational Field |

1315 | sage: F3(QQ) |

1316 | Multivariate Laurent Polynomial Ring in s, t over Rational Field |

1317 | |

1318 | """ |

1319 | Functor.__init__(self, Rings(), Rings()) |

1320 | if not isinstance(var, (basestring,tuple,list)): |

1321 | raise TypeError, "variable name or list of variable names expected" |

1322 | self.var = var |

1323 | self.multi_variate = multi_variate or not isinstance(var, basestring) |

1324 | |

1325 | def __cmp__(self, other): |

1326 | """ |

1327 | TESTS:: |

1328 | |

1329 | sage: from sage.categories.pushout import LaurentPolynomialFunctor |

1330 | sage: F1 = LaurentPolynomialFunctor('t') |

1331 | sage: F2 = LaurentPolynomialFunctor('t', multi_variate=True) |

1332 | sage: F3 = LaurentPolynomialFunctor(['s','t']) |

1333 | sage: F1 == F2 |

1334 | True |

1335 | sage: F1 == loads(dumps(F1)) |

1336 | True |

1337 | sage: F1 == F3 |

1338 | False |

1339 | sage: F1 == QQ.construction()[0] |

1340 | False |

1341 | |

1342 | """ |

1343 | c = cmp(type(self), type(other)) |

1344 | if c == 0: |

1345 | c = cmp(self.var, other.var) |

1346 | return c |

1347 | |

1348 | def merge(self, other): |

1349 | """ |

1350 | Two Laurent polynomial construction functors merge if the variable names coincide. |

1351 | The result is multivariate if one of the arguments is multivariate. |

1352 | |

1353 | EXAMPLE:: |

1354 | |

1355 | sage: from sage.categories.pushout import LaurentPolynomialFunctor |

1356 | sage: F1 = LaurentPolynomialFunctor('t') |

1357 | sage: F2 = LaurentPolynomialFunctor('t', multi_variate=True) |

1358 | sage: F1.merge(F2) |

1359 | LaurentPolynomialFunctor |

1360 | sage: F1.merge(F2)(LaurentPolynomialRing(GF(2),'a')) |

1361 | Multivariate Laurent Polynomial Ring in a, t over Finite Field of size 2 |

1362 | sage: F1.merge(F1)(LaurentPolynomialRing(GF(2),'a')) |

1363 | Univariate Laurent Polynomial Ring in t over Univariate Laurent Polynomial Ring in a over Finite Field of size 2 |

1364 | |

1365 | """ |

1366 | if self == other or isinstance(other, PolynomialFunctor) and self.var == other.var: |

1367 | return LaurentPolynomialFunctor(self.var, (self.multi_variate or other.multi_variate)) |

1368 | else: |

1369 | return None |

1370 | |

1371 | |

1372 | class VectorFunctor(ConstructionFunctor): |

1373 | """ |

1374 | A construction functor for free modules over commutative rings. |

1375 | |

1376 | EXAMPLE:: |

1377 | |

1378 | sage: F = (ZZ^3).construction()[0] |

1379 | sage: F |

1380 | VectorFunctor |

1381 | sage: F(GF(2)['t']) |

1382 | Ambient free module of rank 3 over the principal ideal domain Univariate Polynomial Ring in t over Finite Field of size 2 (using NTL) |

1383 | |

1384 | |

1385 | """ |

1386 | rank = 10 # ranking of functor, not rank of module. |

1387 | # This coincides with the rank of the matrix construction functor, but this is OK since they can not both be applied in any order |

1388 | |

1389 | |

1390 | def pushout_lattice(R, S): |

1391 | r""" |

1392 | Given a pair of Objects $R$ and $S$, try and construct a |

1393 | reasonable object $Y$ and return maps such that |

1394 | canonically $R \leftarrow Y \rightarrow S$. |

1395 | |

1396 | ALGORITHM: |

1397 | |

1398 | This is based on the model that arose from much discussion at Sage Days 4. |

1399 | Going up the tower of constructions of $R$ and $S$ (e.g. the reals |

1400 | come from the rationals come from the integers) try and find a |

1401 | common parent, and then try and fill in a lattice with these |

1402 | two towers as sides with the top as the common ancestor and |

1403 | the bottom will be the desired ring. |

1404 | |

1405 | See the code for a specific worked-out example. |

1406 | |

1407 | EXAMPLES:: |

1408 | |

1409 | sage: from sage.categories.pushout import pushout_lattice |

1410 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1411 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1412 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1413 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1414 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1415 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1416 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1417 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1418 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1419 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1420 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1421 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1422 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1423 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1424 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1425 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1426 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1427 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1428 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1429 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1430 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1431 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1432 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1433 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1434 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1435 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1436 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1437 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1438 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1439 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1440 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1441 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1442 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1443 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1444 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1445 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1446 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1447 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1448 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1449 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1450 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1451 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1452 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1453 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1454 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1455 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1456 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1457 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1458 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1459 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1460 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1461 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1462 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1463 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1464 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1465 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1466 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1467 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1468 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1469 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1470 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1471 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1472 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1473 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1474 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1475 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1476 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1477 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1478 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1479 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1480 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1481 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1482 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1483 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1484 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1485 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1486 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1487 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1488 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1489 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1490 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1491 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1492 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1493 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1494 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1495 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1496 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1497 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1498 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1499 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1500 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1501 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1502 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1503 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1504 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1505 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1506 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1507 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1508 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1509 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1510 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1511 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1512 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1513 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1514 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1515 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1516 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1517 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1518 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1519 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1520 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1521 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1522 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1523 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1524 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1525 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1526 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1527 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1528 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1529 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1530 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1531 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1532 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1533 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1534 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1535 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1536 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1537 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1538 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1539 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1540 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1541 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1542 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1543 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1544 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1545 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1546 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1547 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1548 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1549 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1550 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1551 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1552 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1553 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1554 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1555 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1556 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1557 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1558 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1559 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1560 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1561 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1562 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1563 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1564 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1565 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1566 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1567 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1568 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1569 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1570 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1571 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1572 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1573 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1574 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1575 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1576 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1577 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1578 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1579 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1580 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1581 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1582 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1583 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1584 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1585 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1586 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1587 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1588 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1589 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1590 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1591 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1592 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1593 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1594 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1595 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1596 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1597 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1598 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1599 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1600 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1601 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1602 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1603 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1604 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1605 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1606 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1607 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1608 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1609 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1610 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1611 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1612 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1613 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1614 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1615 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1616 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1617 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1618 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1619 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1620 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1621 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1622 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1623 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1624 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1625 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1626 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1627 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1628 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1629 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1630 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1631 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1632 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1633 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1634 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1635 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1636 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1637 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1638 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1639 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1640 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1641 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1642 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1643 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1644 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1645 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1646 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1647 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1648 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1649 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1650 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1651 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1652 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1653 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1654 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1655 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1656 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1657 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1658 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1659 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1660 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1661 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1662 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1663 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1664 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1665 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1666 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1667 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1668 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1669 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1670 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1671 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1672 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1673 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1674 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1675 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1676 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1677 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1678 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1679 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1680 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1681 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1682 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1683 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1684 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1685 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1686 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1687 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1688 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1689 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1690 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1691 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1692 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1693 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1694 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1695 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1696 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1697 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1698 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1699 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1700 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1701 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1702 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1703 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1704 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1705 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1706 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1707 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1708 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1709 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1710 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1711 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1712 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1713 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1714 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1715 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1716 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1717 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1718 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1719 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1720 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1721 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1722 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1723 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1724 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1725 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1726 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1727 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1728 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1729 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1730 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1731 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1732 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1733 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1734 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1735 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1736 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1737 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1738 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1739 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1740 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1741 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1742 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1743 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1744 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1745 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1746 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1747 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1748 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1749 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1750 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1751 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1752 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1753 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1754 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1755 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1756 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1757 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1758 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1759 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1760 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1761 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1762 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1763 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1764 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1765 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1766 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1767 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1768 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1769 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1770 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1771 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1772 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1773 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1774 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1775 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1776 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1777 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1778 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1779 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1780 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1781 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1782 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1783 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1784 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1785 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1786 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1787 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1788 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1789 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1790 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1791 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1792 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1793 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1794 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1795 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1796 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1797 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1798 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1799 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1800 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1801 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1802 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1803 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1804 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1805 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1806 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1807 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1808 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1809 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1810 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1811 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1812 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1813 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1814 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1815 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1816 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1817 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1818 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1819 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1820 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1821 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1822 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1823 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1824 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1825 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1826 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1827 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1828 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1829 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1830 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1831 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1832 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1833 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1834 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1835 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1836 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1837 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1838 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1839 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1840 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1841 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1842 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1843 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1844 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1845 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1846 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1847 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1848 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1849 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1850 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1851 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1852 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1853 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1854 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1855 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1856 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1857 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1858 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1859 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1860 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1861 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1862 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1863 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1864 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1865 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1866 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1867 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1868 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1869 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1870 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1871 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1872 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1873 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1874 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1875 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1876 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1877 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1878 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1879 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1880 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1881 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1882 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1883 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1884 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1885 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1886 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1887 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1888 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1889 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1890 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1891 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1892 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1893 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1894 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1895 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1896 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1897 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1898 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1899 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1900 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1901 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1902 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1903 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1904 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1905 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1906 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1907 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1908 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1909 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1910 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1911 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1912 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1913 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1914 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1915 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1916 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1917 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1918 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1919 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1920 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1921 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1922 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1923 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1924 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1925 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1926 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1927 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1928 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1929 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1930 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1931 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1932 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1933 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1934 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1935 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1936 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1937 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1938 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1939 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1940 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1941 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1942 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1943 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1944 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1945 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1946 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1947 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1948 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1949 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1950 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1951 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1952 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1953 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1954 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1955 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1956 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1957 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1958 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1959 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1960 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1961 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1962 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1963 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1964 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1965 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1966 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1967 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1968 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1969 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1970 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1971 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1972 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1973 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1974 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1975 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1976 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1977 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1978 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1979 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1980 | sage: A, B = pushout_lattice(Qp(7), Frac(ZZ['x'])) |

1981 | """ |