MCPcopy Create free account
hub / github.com/ComputationalRobotics/XM-code / L1Solver

Class L1Solver

deps/glomap/glomap/math/l1_solver.h:31–111  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

29
30template <class MatrixType>
31class L1Solver {
32 public:
33 L1Solver(const L1SolverOptions& options, const MatrixType& mat)
34 : options_(options), a_(mat) {
35 // Pre-compute the sparsity pattern.
36 const MatrixType spd_mat = a_.transpose() * a_;
37 linear_solver_.compute(spd_mat);
38 }
39
40 void Solve(const Eigen::VectorXd& rhs, Eigen::VectorXd* solution) {
41 Eigen::VectorXd& x = *solution;
42 Eigen::VectorXd z(a_.rows()), u(a_.rows());
43 z.setZero();
44 u.setZero();
45
46 Eigen::VectorXd a_times_x(a_.rows()), z_old(z.size()), ax_hat(a_.rows());
47 // Precompute some convergence terms.
48 const double rhs_norm = rhs.norm();
49 const double primal_abs_tolerance_eps =
50 std::sqrt(a_.rows()) * options_.absolute_tolerance;
51 const double dual_abs_tolerance_eps =
52 std::sqrt(a_.cols()) * options_.absolute_tolerance;
53
54 const std::string row_format =
55 " % 4d % 4.4e % 4.4e % 4.4e % 4.4e";
56 for (int i = 0; i < options_.max_num_iterations; i++) {
57 // Update x.
58 x.noalias() = linear_solver_.solve(a_.transpose() * (rhs + z - u));
59 if (linear_solver_.info() != Eigen::Success) {
60 LOG(ERROR) << "L1 Minimization failed. Could not solve the sparse "
61 "linear system with Cholesky Decomposition";
62 return;
63 }
64
65 a_times_x.noalias() = a_ * x;
66 ax_hat.noalias() = options_.alpha * a_times_x;
67 ax_hat.noalias() += (1.0 - options_.alpha) * (z + rhs);
68
69 // Update z and set z_old.
70 std::swap(z, z_old);
71 z.noalias() = Shrinkage(ax_hat - rhs + u, 1.0 / options_.rho);
72
73 // Update u.
74 u.noalias() += ax_hat - z - rhs;
75
76 // Compute the convergence terms.
77 const double r_norm = (a_times_x - z - rhs).norm();
78 const double s_norm =
79 (-options_.rho * a_.transpose() * (z - z_old)).norm();
80 const double max_norm = std::max({a_times_x.norm(), z.norm(), rhs_norm});
81 const double primal_eps =
82 primal_abs_tolerance_eps + options_.relative_tolerance * max_norm;
83 const double dual_eps = dual_abs_tolerance_eps +
84 options_.relative_tolerance *
85 (options_.rho * a_.transpose() * u).norm();
86
87 // Determine if the minimizer has converged.
88 if (r_norm < primal_eps && s_norm < dual_eps) {

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected