| 496 | def _basis_over_QQ(self, ops, r, integral=False, bound=10): |
| 497 | """ |
| 498 | |
| 499 | """ |
| 500 | assert len(ops) >= r, "len of ops must be at least r" |
| 501 | |
| 502 | from sage.rings.all import ZZ, QQ |
| 503 | from random import randrange |
| 504 | from sage.modules.all import span, vector |
| 505 | from sage.matrix.all import matrix |
| 506 | |
| 507 | |
| 508 | if r == 0: |
| 509 | return [], matrix(QQ,0,0), vector(QQ,0) |
| 510 | |
| 511 | tm = verbose("Computing Hecke matrices...") |
| 512 | M = self.module() |
| 513 | if integral: |
| 514 | T = [M.integral_hecke_matrix(k) for k in ops] |
| 515 | else: |
| 516 | T = [self.hecke_operator(k).matrix() for k in ops] |
| 517 | verbose("Done computing all Hecke matrices", tm) |
| 518 | n = M.rank() |
| 519 | v = vector(QQ, [ZZ.random_element(-bound,bound) for _ in range(n)]) |
| 520 | while True: |
| 521 | tm = verbose("Computing images of random vector...") |
| 522 | # Apply Hecke operators to v |
| 523 | Z = matrix([v*t for t in T]) |
| 524 | tm = verbose("Done computing the images", tm) |
| 525 | |
| 526 | p = ZZ(randrange(1000,20000)).next_prime() |
| 527 | Z, d = Z._clear_denom() |
| 528 | Zmod = Z._reduce(p) |
| 529 | rr = Zmod.rank() |
| 530 | verbose("Got rank (mod %s) = %s"%(p,rr),tm) |
| 531 | |
| 532 | assert rr <= r, "bug in _basis_over_QQ, since we must have rr <= r" |
| 533 | if rr >= r: break |
| 534 | |
| 535 | # Change 1 random entry, and try again |
| 536 | v[randrange(n)] += ZZ.random_element() |
| 537 | # end while |
| 538 | |
| 539 | return Zmod.transpose().pivots(), Z, d*v |
| 540 | |
| 541 | def _discriminant(self, ops, r): |
| 542 | r""" |
| 543 | Return the discriminant of this Hecke algebra, assuming it is |
| 544 | generated over ZZ by the Hecke operators `T_n` with `n` in ops |
| 545 | and that the rank of this Hecke algebra is `r` as a |
| 546 | `\ZZ`-module. |
| 547 | |
| 548 | INPUT: |
| 549 | |
| 550 | - ``ops`` -- list of positive integers |
| 551 | |
| 552 | - ``r`` -- nonnegative integer (the rank) |
| 553 | """ |
| 554 | from sage.rings.all import ZZ, QQ |
| 555 | from sage.matrix.all import matrix |
| 556 | from random import randrange |
| 557 | |
| 558 | F, A, _ = self._basis_over_QQ(ops, r) |
| 559 | tm = verbose("start computing ZZ module...") |
| 560 | d1 = A.row_module(ZZ).basis_matrix().determinant() |
| 561 | verbose('done!', tm) |
| 562 | d2 = A.matrix_from_rows(F).determinant() |
| 563 | T = [self.hecke_matrix(ops[n]) for n in F] |
| 564 | |
| 565 | m = len(F) |
| 566 | B = matrix(QQ, m) |
| 567 | for i in range(m): |
| 568 | for j in range(i,m): |
| 569 | tr = (T[i]*T[j]).trace() |
| 570 | B[i,j] = tr |
| 571 | if i != j: |
| 572 | B[j,i] = tr |
| 573 | d3 = B.determinant() |
| 574 | |
| 575 | return ZZ(d3 / (d2/d1)**2) |
| 576 | |
| 577 | def _index_in_saturation_naive(self, ops, r): |
| 578 | from sage.rings.all import ZZ |
| 579 | from sage.modules.all import span |
| 580 | |
| 581 | M = self.module() |
| 582 | V = ZZ**(M.rank()**2) |
| 583 | T = [V(M.integral_hecke_matrix(n).list()) for n in ops] |
| 584 | S = span(T,ZZ) |
| 585 | return S.index_in_saturation() |
| 586 | |
| 587 | def _index_in_saturation(self, ops, r, bound=10): |
| 588 | from sage.rings.all import ZZ, QQ |
| 589 | from sage.matrix.all import matrix |
| 590 | from sage.modules.all import span |
| 591 | from random import randrange |
| 592 | |
| 593 | M = self.module() |
| 594 | T = [M.integral_hecke_matrix(k) for k in ops] |
| 595 | W = None |
| 596 | F = None |
| 597 | while True: |
| 598 | F0, A, v = self._basis_over_QQ(ops, r, integral=True, bound=bound) |
| 599 | if F is not None and F0 != F: |
| 600 | continue |
| 601 | F = F0 |
| 602 | tm = verbose("start computing ZZ module...") |
| 603 | B = A.row_module(ZZ) |
| 604 | X = B.span_of_basis(A.matrix_from_rows(F).rows()) |
| 605 | C = B.saturation() |
| 606 | Q = C/B |
| 607 | if len(Q.gens()) == 0: |
| 608 | # easy special case |
| 609 | return (ZZ**len(F))/(ZZ**len(F)) |
| 610 | fail = False |
| 611 | W0 = span([X.coordinate_vector(g.lift()) for g in Q.gens()], ZZ) + ZZ**r |
| 612 | if W is None: |
| 613 | W = W0 |
| 614 | else: |
| 615 | W = W.intersection(W0) |
| 616 | Z = [] |
| 617 | for z in W.basis(): |
| 618 | a = sum([z[i]*T[F[i]] for i in range(len(z))]) |
| 619 | if a.denominator() != 1: |
| 620 | fail = True |
| 621 | break |
| 622 | Z.append(a) |
| 623 | if not fail: |
| 624 | S = span([v*a for a in Z], ZZ) |
| 625 | return (S+B) / B |
| 626 | |
| 627 | |