template <typename FT> void EnumerationDyn<FT>::reset(enumf cur_dist, int cur_depth) { // FPLLL_TRACE("Reset level " << cur_depth); int new_dim = cur_depth + 1; vector<enumxt> partial_sol(d - cur_depth - 1); for (int i = cur_depth + 1; i < d; ++i) partial_sol[i - cur_depth - 1] = x[i]; FT new_dist = 0.0; for (int i = 0; i < new_dim; i++) new_dist.add(new_dist, _gso.get_r_exp(i, i)); FastEvaluator<FT> new_evaluator; Enumeration<FT> enumobj(_gso, new_evaluator, _max_indices); enumobj.enumerate(0, d, new_dist, 0, target, partial_sol, pruning_bounds, false, true); if (!new_evaluator.empty()) { FT sol_dist2 = new_evaluator.begin()->first; sol_dist2.mul_2si(sol_dist2, -new_evaluator.normExp); enumf sol_dist = sol_dist2.get_d(); // FPLLL_TRACE("Recovering sub-solution at level: " << cur_depth <<" soldist: " << sol_dist); if (sol_dist + cur_dist < partdistbounds[0]) { // FPLLL_TRACE("Saving it."); for (int i = 0; i < new_dim; ++i) x[i] = new_evaluator.begin()->second[i].get_d(); process_solution(sol_dist + cur_dist); } } }
static bool enumerate_svp(int d, MatGSO<Integer, Float> &gso, Float &max_dist, Evaluator<Float> &evaluator, const vector<enumf> &pruning, int flags) { Enumeration<Float> enumobj(gso, evaluator); bool dual = (flags & SVP_DUAL); if (d == 1 || !pruning.empty() || dual) { enumobj.enumerate(0, d, max_dist, 0, vector<Float>(), vector<enumxt>(), pruning, dual); } else { Enumerator enumerator(d, gso.get_mu_matrix(), gso.get_r_matrix()); while (enumerator.enum_next(max_dist)) { if (flags & SVP_VERBOSE) { evaluator.new_sol_flag = false; cerr << enumerator.get_sub_tree(); if (evaluator.eval_mode != EVALMODE_SV) cerr << " (count=2*" << evaluator.sol_count << ")"; } /* Enumerates short vectors only in enumerator.get_sub_tree() (about maxVolume iterations or less) */ enumobj.enumerate(0, d, max_dist, 0, FloatVect(), enumerator.get_sub_tree(), pruning); if (flags & SVP_VERBOSE) { cerr << "\r" << (char)27 << "[K"; if (evaluator.eval_mode == EVALMODE_SV && evaluator.new_sol_flag) cerr << "Solution norm^2=" << evaluator.last_partial_dist << " value=" << evaluator.sol_coord << endl; } } } return !evaluator.sol_coord.empty(); }
int closest_vector(IntMatrix &b, const IntVect &int_target, IntVect &sol_coord, int method, int flags) { // d = lattice dimension (note that it might decrease during preprocessing) int d = b.get_rows(); // n = dimension of the space int n = b.get_cols(); FPLLL_CHECK(d > 0 && n > 0, "closestVector: empty matrix"); FPLLL_CHECK(d <= n, "closestVector: number of vectors > size of the vectors"); // Sets the floating-point precision // Error bounds on GSO are valid if prec >= minprec double rho; int min_prec = gso_min_prec(rho, d, LLL_DEF_DELTA, LLL_DEF_ETA); int prec = max(53, min_prec + 10); int old_prec = Float::set_prec(prec); // Allocates space for vectors and matrices in constructors IntMatrix empty_mat; MatGSO<Integer, Float> gso(b, empty_mat, empty_mat, GSO_INT_GRAM); FloatVect target_coord; Float max_dist; Integer itmp1; // Computes the Gram-Schmidt orthogonalization in floating-point gso.update_gso(); gen_zero_vect(sol_coord, d); /* Applies Babai's algorithm. Because we use fp, it might be necessary to do it several times (if ||target|| >> ||b_i||) */ FloatMatrix float_matrix(d, n); FloatVect target(n), babai_sol; IntVect int_new_target = int_target; for (int i = 0; i < d; i++) for (int j = 0; j < n; j++) float_matrix(i, j).set_z(b(i, j)); for (int loop_idx = 0;; loop_idx++) { if (loop_idx >= 0x100 && ((loop_idx & (loop_idx - 1)) == 0)) FPLLL_INFO("warning: possible infinite loop in Babai's algorithm"); for (int i = 0; i < n; i++) { target[i].set_z(int_new_target[i]); } babai(float_matrix, gso.get_mu_matrix(), gso.get_r_matrix(), target, babai_sol); int idx; for (idx = 0; idx < d && babai_sol[idx] >= -1 && babai_sol[idx] <= 1; idx++) { } if (idx == d) break; for (int i = 0; i < d; i++) { itmp1.set_f(babai_sol[i]); sol_coord[i].add(sol_coord[i], itmp1); for (int j = 0; j < n; j++) int_new_target[j].submul(itmp1, b(i, j)); } } // FPLLL_TRACE("BabaiSol=" << sol_coord); get_gscoords(float_matrix, gso.get_mu_matrix(), gso.get_r_matrix(), target, target_coord); /* Computes a very large bound to make the algorithm work until the first solution is found */ max_dist = 0.0; for (int i = 1; i < d; i++) { // get_r_exp(i, i) = r(i, i) because gso is initialized without GSO_ROW_EXPO max_dist.add(max_dist, gso.get_r_exp(i, i)); } vector<int> max_indices; if (method & CVPM_PROVED) { // For Exact CVP, we need to reset enum below depth with maximal r_i max_indices = vector<int>(d); int cur, max_index, previous_max_index; previous_max_index = max_index = d-1; Float max_val; while (max_index > 0) { max_val = gso.get_r_exp(max_index, max_index); for (cur = previous_max_index - 1 ; cur >= 0 ; --cur) { if (max_val <= gso.get_r_exp(cur, cur)) { max_val = gso.get_r_exp(cur, cur); max_index = cur; } } for (cur = max_index ; cur < previous_max_index ; ++cur) max_indices[cur] = max_index; max_indices[previous_max_index] = previous_max_index; previous_max_index = max_index; --max_index; } } FPLLL_TRACE("max_indices " << max_indices); FastEvaluator<Float> evaluator(n, gso.get_mu_matrix(), gso.get_r_matrix(), EVALMODE_CV); // Main loop of the enumeration Enumeration<Float> enumobj(gso, evaluator, max_indices); enumobj.enumerate(0, d, max_dist, 0, target_coord); int result = RED_ENUM_FAILURE; if (!evaluator.sol_coord.empty()) { FPLLL_TRACE("evaluator.sol_coord=" << evaluator.sol_coord); if (flags & CVP_VERBOSE) FPLLL_INFO("max_dist=" << max_dist); for (int i = 0; i < d; i++) { itmp1.set_f(evaluator.sol_coord[i]); sol_coord[i].add(sol_coord[i], itmp1); } result = RED_SUCCESS; } Float::set_prec(old_prec); return result; }