g6k.lll(0, n) # Run a progressive sieve, to get an initial database saturating the 4/3 *gh^2 ball. # This makes the final computation saturating a larger ball faster than directly # running such a large sieve. # # G6K will use a database of size db_size_base * db_size_base^dim with default values # db_size_base = sqrt(4./3) and db_size_factor = 3.2 # # The sieve stops when a # 0.5 * saturation_ratio * saturation_radius^(dim/2) # # distinct vectors (modulo negation) of length less than saturation_radius have # been found g6k.initialize_local(0, n / 2, n) while g6k.l > 0: # Extend the lift context to the left g6k.extend_left(1) # Sieve g6k() # Increase db_size, saturation radius and saturation ratio to find almost all # the desired vectors. # We need to increase db_size to at least # 0.5 * saturation_ratio * saturation_radius^(dim/2) # # for this to be possible, but a significant margin is recommended with g6k.temp_params(saturation_ratio=.95, saturation_radius=1.7,
def __call__(cls, M, predicate, invalidate_cache=lambda: None, preproc_offset=20, threads=1, ph=0, **kwds): # TODO bkz_sieve would be neater here if preproc_offset and M.d >= 40: bkz_res = usvp_pred_bkz_enum_solve( M, predicate, block_size=max(M.d - preproc_offset, 2), max_loops=8, threads=threads, invalidate_cache=invalidate_cache, ) ntests = bkz_res.ntests if bkz_res.success: # this might be enough return bkz_res else: bkz_res = None ntests = 0 from fpylll import IntegerMatrix # reduce size of entries B = IntegerMatrix(M.B.nrows, M.B.ncols) for i in range(M.B.nrows): for j in range(M.B.ncols): B[i, j] = M.B[i, j] // 2**ph params = SieverParams(reserved_n=M.d, otf_lift=False, threads=threads) g6k = Siever(B, params) tracer = SieveTreeTracer(g6k, root_label="sieve", start_clocks=True) g6k.initialize_local(0, M.d // 2, M.d) while g6k.l: g6k.extend_left() with tracer.context("sieve"): try: g6k() except SaturationError: pass # fill the database with g6k.temp_params(**kwds): g6k() invalidate_cache() found, solution = False, None with tracer.context("check"): for v in g6k.itervalues(): # heuristic: v has very small entries ntests += 1 if predicate(v, standard_basis=False): found = True solution = tuple( [int(v_) for v_ in g6k.M.B.multiply_left(v)]) break tracer.exit() cputime = tracer.trace.data[ "cputime"] + bkz_res.cputime if bkz_res else 0 walltime = tracer.trace.data[ "walltime"] + bkz_res.walltime if bkz_res else 0 b0, b0e = M.get_r_exp(0, 0) return USVPPredSolverResults( success=found, ntests=ntests, solution=solution, b0=b0**(0.5) * 2**(b0e / 2.0), cputime=cputime, walltime=walltime, data=tracer.trace, )