ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
least_absolute_deviations.cc
Go to the documentation of this file.
1 // Copyright (c) 2018, ETH Zurich and UNC Chapel Hill.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //
7 // * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 //
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 //
14 // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of
15 // its contributors may be used to endorse or promote products derived
16 // from this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
22 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 // POSSIBILITY OF SUCH DAMAGE.
29 //
30 // Author: Johannes L. Schoenberger (jsch-at-demuc-dot-de)
31 
33 
34 #include <Eigen/SparseCholesky>
35 
36 namespace colmap {
37 namespace {
38 
39 Eigen::VectorXd Shrinkage(const Eigen::VectorXd& a, const double kappa) {
40  const Eigen::VectorXd a_plus_kappa = a.array() + kappa;
41  const Eigen::VectorXd a_minus_kappa = a.array() - kappa;
42  return a_plus_kappa.cwiseMin(0) + a_minus_kappa.cwiseMax(0);
43 }
44 
45 } // namespace
46 
48  const Eigen::SparseMatrix<double>& A,
49  const Eigen::VectorXd& b,
50  Eigen::VectorXd* x) {
51  CHECK_NOTNULL(x);
52  CHECK_GT(options.rho, 0);
53  CHECK_GT(options.alpha, 0);
54  CHECK_GT(options.max_num_iterations, 0);
55  CHECK_GE(options.absolute_tolerance, 0);
56  CHECK_GE(options.relative_tolerance, 0);
57 
58  Eigen::SimplicialLLT<Eigen::SparseMatrix<double>> linear_solver;
59  linear_solver.compute(A.transpose() * A);
60 
61  Eigen::VectorXd z = Eigen::VectorXd::Zero(A.rows());
62  Eigen::VectorXd z_old(A.rows());
63  Eigen::VectorXd u = Eigen::VectorXd::Zero(A.rows());
64 
65  Eigen::VectorXd Ax(A.rows());
66  Eigen::VectorXd Ax_hat(A.rows());
67 
68  const double b_norm = b.norm();
69  const double eps_pri_threshold =
70  std::sqrt(A.rows()) * options.absolute_tolerance;
71  const double eps_dual_threshold =
72  std::sqrt(A.cols()) * options.absolute_tolerance;
73 
74  for (int i = 0; i < options.max_num_iterations; ++i) {
75  *x = linear_solver.solve(A.transpose() * (b + z - u));
76  if (linear_solver.info() != Eigen::Success) {
77  return false;
78  }
79 
80  Ax = A * *x;
81  Ax_hat = options.alpha * Ax + (1 - options.alpha) * (z + b);
82 
83  z_old = z;
84  z = Shrinkage(Ax_hat - b + u, 1 / options.rho);
85 
86  u += Ax_hat - z - b;
87 
88  const double r_norm = (Ax - z - b).norm();
89  const double s_norm = (-options.rho * A.transpose() * (z - z_old)).norm();
90  const double eps_pri =
91  eps_pri_threshold + options.relative_tolerance *
92  std::max(b_norm, std::max(Ax.norm(), z.norm()));
93  const double eps_dual =
94  eps_dual_threshold +
95  options.relative_tolerance * (options.rho * A.transpose() * u).norm();
96 
97  if (r_norm < eps_pri && s_norm < eps_dual) {
98  break;
99  }
100  }
101 
102  return true;
103 }
104 
105 } // namespace colmap
a[190]
normal_z x
normal_z z
bool SolveLeastAbsoluteDeviations(const LeastAbsoluteDeviationsOptions &options, const Eigen::SparseMatrix< double > &A, const Eigen::VectorXd &b, Eigen::VectorXd *x)