def good_primes(B): r""" Given the bound, returns the primes whose product is greater than ``B`` and which would take the least amount of time to run the main sieve algorithm Complexity of finding points modulo primes is assumed to be N^2 * P_max^{N}. Complexity of lifting points and the LLL() function is assumed to be close to (dim_max^5) * (alpha / P_max)^dim_scheme. where alpha is the product of all primes, P_max is the largest prime in the list, dim_max is the max dimension of all components, and N is the dimension of the ambient space. """ M = dict() # stores optimal list of primes, corresponding to list size small_primes = sufficient_primes(B) max_length = len(small_primes) M[max_length] = small_primes current_count = max_length - 1 dim = X.ambient_space().dimension() while current_count > 1: current_list = [] # stores prime which are bigger than least updated_list = [] best_list = [] least = (RR(B)**(1.00 / current_count)).floor() for i in range(current_count): current_list.append(next_prime(least)) least = current_list[-1] # improving list of primes by taking primes less than least # this part of algorithm is used to centralize primes around `least` prod_prime = prod(current_list) least = current_list[0] while least != 2 and prod_prime > B and len( updated_list) < current_count: best_list = updated_list + current_list[:current_count - len(updated_list)] updated_list.append(previous_prime(least)) least = updated_list[-1] removed_prime = current_list[current_count - len(updated_list)] prod_prime = (prod_prime * least) / removed_prime M[current_count] = sorted(best_list) current_count = current_count - 1 best_size = 2 best_time = (dim**2) * M[2][-1]**(dim) + ( dim_max**5 * (prod(M[2]) / M[2][-1])**dim_scheme) for i in range(2, max_length + 1): current_time = (dim**2) * M[i][-1]**(dim) + ( dim_max**5 * (prod(M[i]) / M[i][-1])**dim_scheme) if current_time < best_time: best_size = i best_time = current_time return M[best_size]
def det_given_divisor(A, d, proof=True, stabilize=2): """ Given a divisor d of the determinant of A, compute the determinant of A. INPUT: - ``A`` -- a square integer matrix - ``d`` -- a nonzero integer that is assumed to divide the determinant of A - ``proof`` -- bool (default: True) compute det modulo enough primes so that the determinant is computed provably correctly (via the Hadamard bound). It would be VERY hard for ``det()`` to fail even with proof=False. - ``stabilize`` -- int (default: 2) if proof = False, then compute the determinant modulo `p` until ``stabilize`` successive modulo determinant computations stabilize. OUTPUT: integer -- determinant EXAMPLES:: sage: import sage.matrix.matrix_integer_dense_hnf as matrix_integer_dense_hnf sage: a = matrix(ZZ,3,[-1, -1, -1, -20, 4, 1, -1, 1, 2]) sage: matrix_integer_dense_hnf.det_given_divisor(a, 3) -30 sage: matrix_integer_dense_hnf.det_given_divisor(a, 3, proof=False) -30 sage: matrix_integer_dense_hnf.det_given_divisor(a, 3, proof=False, stabilize=1) -30 sage: a.det() -30 Here we illustrate proof=False giving a wrong answer:: sage: p = matrix_integer_dense_hnf.max_det_prime(2) sage: q = previous_prime(p) sage: a = matrix(ZZ, 2, [p, 0, 0, q]) sage: p * q 70368442188091 sage: matrix_integer_dense_hnf.det_given_divisor(a, 1, proof=False, stabilize=2) 0 This still works, because we do not work modulo primes that divide the determinant bound, which is found using a p-adic algorithm:: sage: a.det(proof=False, stabilize=2) 70368442188091 3 primes is enough:: sage: matrix_integer_dense_hnf.det_given_divisor(a, 1, proof=False, stabilize=3) 70368442188091 sage: matrix_integer_dense_hnf.det_given_divisor(a, 1, proof=False, stabilize=5) 70368442188091 sage: matrix_integer_dense_hnf.det_given_divisor(a, 1, proof=True) 70368442188091 TESTS:: sage: m = diagonal_matrix(ZZ, 68, [2]*66 + [1,1]) sage: m.det() 73786976294838206464 """ p = max_det_prime(A.nrows()) z_mod = [] moduli = [] assert d != 0 z_so_far = 1 N_so_far = 1 if proof: N = 1 B = (2 * 10**A.hadamard_bound()) // d + 1 dd = d # bad verbose statement, since computing the log overflows! est = int(RR(B).log() / RR(p).log()) + 1 cnt = 1 verbose("Multimodular det -- need to use about %s primes." % est, level=1) while N < B: if d % p != 0: tm = cputime() dd, z_so_far, N_so_far = det_from_modp_and_divisor( A, d, p, z_mod, moduli, z_so_far, N_so_far) N *= p verbose( "computed det mod p=%s which is %s (of about %s)" % (p, cnt, est), tm) p = previous_prime(p) cnt += 1 return dd else: val = [] while True: if d % p: tm = cputime() dd, z_so_far, N_so_far = det_from_modp_and_divisor( A, d, p, z_mod, moduli, z_so_far, N_so_far) verbose("computed det mod %s" % p, tm) val.append(dd) if len(val) >= stabilize and len(set(val[-stabilize:])) == 1: return val[-1] p = previous_prime(p)
def det_given_divisor(A, d, proof=True, stabilize=2): """ Given a divisor d of the determinant of A, compute the determinant of A. INPUT: - ``A`` -- a square integer matrix - ``d`` -- a nonzero integer that is assumed to divide the determinant of A - ``proof`` -- bool (default: True) compute det modulo enough primes so that the determinant is computed provably correctly (via the Hadamard bound). It would be VERY hard for ``det()`` to fail even with proof=False. - ``stabilize`` -- int (default: 2) if proof = False, then compute the determinant modulo `p` until ``stabilize`` successive modulo determinant computations stabilize. OUTPUT: integer -- determinant EXAMPLES:: sage: import sage.matrix.matrix_integer_dense_hnf as matrix_integer_dense_hnf sage: a = matrix(ZZ,3,[-1, -1, -1, -20, 4, 1, -1, 1, 2]) sage: matrix_integer_dense_hnf.det_given_divisor(a, 3) -30 sage: matrix_integer_dense_hnf.det_given_divisor(a, 3, proof=False) -30 sage: matrix_integer_dense_hnf.det_given_divisor(a, 3, proof=False, stabilize=1) -30 sage: a.det() -30 Here we illustrate proof=False giving a wrong answer:: sage: p = matrix_integer_dense_hnf.max_det_prime(2) sage: q = previous_prime(p) sage: a = matrix(ZZ, 2, [p, 0, 0, q]) sage: p * q 70368442188091 sage: matrix_integer_dense_hnf.det_given_divisor(a, 1, proof=False, stabilize=2) 0 This still works, because we don't work modulo primes that divide the determinant bound, which is found using a p-adic algorithm:: sage: a.det(proof=False, stabilize=2) 70368442188091 3 primes is enough:: sage: matrix_integer_dense_hnf.det_given_divisor(a, 1, proof=False, stabilize=3) 70368442188091 sage: matrix_integer_dense_hnf.det_given_divisor(a, 1, proof=False, stabilize=5) 70368442188091 sage: matrix_integer_dense_hnf.det_given_divisor(a, 1, proof=True) 70368442188091 TESTS:: sage: m = diagonal_matrix(ZZ, 68, [2]*66 + [1,1]) sage: m.det() 73786976294838206464 """ p = max_det_prime(A.nrows()) z_mod = [] moduli = [] assert d != 0 z_so_far = 1 N_so_far = 1 if proof: N = 1 B = (2 * 10**A.hadamard_bound()) // d + 1 dd = d # bad verbose statement, since computing the log overflows! est = int(RR(B).log() / RR(p).log()) + 1 cnt = 1 verbose("Multimodular det -- need to use about %s primes."%est, level=1) while N < B: if d % p != 0: tm = cputime() dd, z_so_far, N_so_far = det_from_modp_and_divisor(A, d, p, z_mod, moduli, z_so_far, N_so_far) N *= p verbose("computed det mod p=%s which is %s (of about %s)"%(p, cnt, est), tm) p = previous_prime(p) cnt += 1 return dd else: val = [] while True: if d % p != 0: tm = cputime() dd, z_so_far, N_so_far = det_from_modp_and_divisor(A, d, p, z_mod, moduli, z_so_far, N_so_far) verbose("computed det mod %s"%p, tm) val.append(dd) if len(val) >= stabilize and len(set(val[-stabilize:])) == 1: return val[-1] p = previous_prime(p)