def __init__(self, A): """Create new BKZ object. :param A: an integer matrix, a GSO object or an LLL object """ BKZBase.__init__(self, A)
def svp_preprocessing(self, kappa, block_size, params, tracer=dummy_tracer, trials=0): clean = True BKZBase.svp_preprocessing(self, kappa, block_size, params, tracer=tracer) if trials == 0: return clean last_preproc = 2 * (block_size / 6) + trials + min(trials, 5) last_preproc = min(last_preproc, block_size - 10) preprocs = [last_preproc] while last_preproc > 30: last_preproc -= 8 preprocs = [last_preproc] + preprocs for preproc in preprocs: prepar = params.__class__(block_size=preproc, flags=BKZ.BOUNDED_LLL) clean &= self.tour(prepar, kappa, kappa + block_size, tracer=tracer) return clean
def __init__(self, A): """Create new BKZ object. :param A: an integer matrix, a GSO object or an LLL object """ BKZBase.__init__(self, A) self.M.discover_all_rows() # TODO: this belongs in __call__ (?)
def __init__(self, A, preproc_decider): """Create new BKZ object. :param A: an integer matrix, a GSO object or an LLL object """ BKZBase.__init__(self, A) self.M.discover_all_rows() # TODO: this belongs in __call__ (?) self.preproc_decider = preproc_decider self.last_pruning = AUTO_MAX_BLOCK_SIZE * [None]
def __init__(self, A, tuners=None, recycle=True): """Construct a new instance of the BKZ algorithm. :param A: an integer matrix, a GSO object or an LLL object """ BKZBase.__init__(self, A) self.recycle = recycle self.tuners = YOLO_MAX_BLOCK_SIZE * [None] if tuners is None: for i in range(YOLO_MAX_BLOCK_SIZE): self.tuners[i] = Tuner(i, self.tuners) else: self.tuners = tuners
def svp_preprocessing(self, kappa, block_size, param, stats): clean = True clean &= BKZBase.svp_preprocessing(self, kappa, block_size, param, stats) if block_size < AUTO_MIN_BLOCK_SIZE: preprocessing_block_sizes = param.strategies[ block_size].preprocessing_block_sizes else: preprocessing_block_sizes = [ self.preproc_decider.decide(block_size) ] if preprocessing_block_sizes[0] <= 2: return 2 for preproc in preprocessing_block_sizes: prepar = param.__class__(block_size=preproc, strategies=param.strategies, flags=BKZ.GH_BND) clean &= self.tour(prepar, kappa, kappa + block_size) try: return preprocessing_block_sizes[-1] except: return 0
def svp_preprocessing(self, kappa, block_size, param, stats): clean = True clean &= BKZBase.svp_preprocessing(self, kappa, block_size, param, stats) for preproc in param.strategies[block_size].preprocessing_block_sizes: prepar = param.__class__(block_size=preproc, strategies=param.strategies, flags=BKZ.GH_BND) clean &= self.tour(prepar, kappa, kappa + block_size) return clean
def test_bkz_postprocessing(): A = IntegerMatrix.random(20, "qary", bits=20, k=10, int_type="long") LLL.reduction(A) bkz = BKZ(A) bkz.M.update_gso() tracer = BKZTreeTracer(bkz) solution = (2, 2, 0, 3, 4, 5, 7) v = A.multiply_left(solution, 3) bkz.svp_postprocessing(3, len(solution), solution, tracer) w = tuple(A[3]) assert v == w solution = (2, 1, 0, 3, 4, 5, 7) v = A.multiply_left(solution, 3) bkz.svp_postprocessing(3, len(solution), solution, tracer) w = tuple(A[3]) assert v == w
def svp_preprocessing(self, kappa, block_size, param, tracer=dummy_tracer): clean = True clean &= BKZBase.svp_preprocessing(self, kappa, block_size, param, tracer) for preproc in param.strategies[block_size].preprocessing_block_sizes: prepar = param.__class__(block_size=preproc, strategies=param.strategies, flags=BKZ.GH_BND) clean &= self.tour(prepar, kappa, kappa + block_size, tracer=tracer) return clean
def svp_preprocessing(self, kappa, block_size, param, tracer=dummy_tracer): """ Run sequential BKZ 2.0 preprocessing. :param kappa: current index :param block_size: block size :param params: BKZ parameters :param tracer: object for maintaining statistics """ clean = True clean &= BKZ1.svp_preprocessing(self, kappa, block_size, param, tracer) for preproc in param.strategies[block_size].preprocessing_block_sizes: prepar = param.__class__(block_size=preproc, strategies=param.strategies, flags=BKZ.GH_BND) clean &= BKZ2.tour(self, prepar, kappa, kappa + block_size) return clean
def svp_preprocessing(self, kappa, block_size, param, tracer=dummy_tracer): clean = True clean &= BKZBase.svp_preprocessing(self, kappa, block_size, param, tracer) for preproc in param.strategies[block_size].preprocessing_block_sizes: prepar = param.__class__(block_size=preproc, strategies=param.strategies, flags=BKZ.GH_BND) clean &= self.tour(prepar, kappa, kappa + block_size, tracer=tracer) # clean up the GSO which is left in a messy state by postprocessing # TODO the C++ version doesn't seem to require this call self.lll_obj.size_reduction(kappa, kappa + block_size, kappa) return clean
def approx_svp_time(seed, params, return_queue=None, progressive=False): """Run Approx-SVP_{1.05} reduction on ``A`` using ``params``. :param seed: random seed for matrix creation :param params: BKZ preprocessing parameters, preprocessing block size is ignored :param return_queue: if not ``None``, the result is put on this queue. :param progressive: run Progressive-BKZ """ from chal import load_svp_challenge from fpylll.algorithms.bkz import BKZReduction as BKZBase FPLLL.set_random_seed(seed) A = load_svp_challenge(params.block_size, seed=seed) M = GSO.Mat(A) M.update_gso() gh = gaussian_heuristic(M.r()) target_norm = 1.05**2 * gh nodes_per_second = 2.0 * 10**9 / 100.0 self = BKZ2(M) tracer = BKZTreeTracer(self, start_clocks=True) rerandomize = False preproc_cost = None with tracer.context(("tour", 0)): while M.get_r(0, 0) > target_norm: with tracer.context("preprocessing"): if rerandomize: self.randomize_block( 1, params.block_size, density=params.rerandomization_density, tracer=tracer) with tracer.context("reduction"): BKZBase.svp_preprocessing(self, 0, params.block_size, params, tracer) # LLL preproc = round(0.9878 * params.block_size - 24.12) # curve fitted to chal.py output prepar = params.__class__(block_size=preproc, strategies=params.strategies, flags=BKZ.GH_BND) self.tour(prepar, 0, params.block_size, tracer=tracer) if preproc_cost is None: preproc_cost = float( tracer.trace.find("preprocessing")["walltime"]) preproc_cost *= nodes_per_second with tracer.context("pruner"): step_target = M.get_r(0, 0) * 0.99 if progressive else target_norm pruner = Pruning.Pruner(step_target, preproc_cost, [M.r()], target=1, metric=Pruning.EXPECTED_SOLUTIONS) coefficients = pruner.optimize_coefficients([1.] * M.d) try: enum_obj = Enumeration(self.M) with tracer.context("enumeration", enum_obj=enum_obj, full=True): max_dist, solution = enum_obj.enumerate( 0, params.block_size, target_norm, 0, pruning=coefficients)[0] with tracer.context("postprocessing"): self.svp_postprocessing(0, params.block_size, solution, tracer=tracer) rerandomize = False except EnumerationError: rerandomize = True self.M.update_gso() logger.debug("r_0: %7.2f, target: %7.2f, preproc: %3d" % (log(M.get_r(0, 0), 2), log(target_norm, 2), preproc)) tracer.exit() tracer.trace.data["|A_0|"] = A[0].norm() tracer.trace.data["preprocessing_block_size"] = preproc if return_queue: return_queue.put(tracer.trace) else: return tracer.trace