24 : num_a_(f.number_of_a()),
25 num_b_(f.number_of_b()),
26 num_e_(f.number_of_e()),
27 num_nz_(f.residual_indices().num_non_zero()),
28 size_a_(f.index_a(num_a_)),
29 size_b_(f.index_b(num_b_)),
30 size_c_(f.number_of_params_c()),
31 size_e_(f.index_e(num_e_)),
45 weights_(f.has_weights() ? num_e_ : 0, 1.0),
122 <<
" RMS error = "<< std::setprecision(6)<< std::setw(12)<<std::sqrt(sqr_error/
e_.
size())
123 <<
" mu = "<<std::setprecision(6)<< std::setw(12) <<mu<<
" nu = "<< nu << std::endl;
202 da = Sa_svd->
solve(sea);
204 da = Sa_cholesky.
solve(sea);
232 da = Sa_svd.
solve(sea);
235 da = Sa_cholesky.
solve(sea);
243 double sqr_delta = da.squared_magnitude();
244 sqr_delta += db.squared_magnitude();
246 if (sqr_delta <
xtol*
xtol*sqr_params) {
254 f_->
f(new_a,new_b,new_c,new_e);
264 double new_sqr_error = new_e.squared_magnitude();
266 double dF = sqr_error - new_sqr_error;
270 if (dF>0.0 && dL>0.0) {
271 double tmp = 2.0*dF/dL-1.0;
272 mu *=
std::max(1.0/3.0, 1.0 - tmp*tmp*tmp);
279 sqr_error = new_sqr_error;
287 std::cout <<
" RMS error = "<< std::setprecision(6)
288 << std::setw(12) << std::sqrt(sqr_error/
e_.
size())
289 <<
" mu = " << std::setprecision(6) << std::setw(12) << mu
290 <<
" nu = " << nu << std::endl;
321 std::cerr <<
"vnl_sparse_lm: Number of unknowns("<<
size_a_+
size_b_<<
')' 322 <<
" greater than number of data ("<<
size_e_<<
")\n";
328 std::cerr <<
"vnl_sparse_lm: Input vector \"a\" length ("<<a.
size()<<
')' 329 <<
" not equal to num parameters in \"a\" ("<<
size_a_<<
")\n";
335 std::cerr <<
"vnl_sparse_lm: Input vector \"b\" length ("<<b.
size()<<
')' 336 <<
" not equal to num parameters in \"b\" ("<<
size_b_<<
")\n";
342 std::cerr <<
"vnl_sparse_lm: Input vector \"c\" length ("<<c.
size()<<
')' 343 <<
" not equal to num parameters in \"c\" ("<<
size_c_<<
")\n";
359 for (
int i=0; i<
num_a_; ++i)
362 U_[i].set_size(ai_size,ai_size);
368 for (
auto & r_itr : row)
370 const unsigned int j = r_itr.second;
371 const unsigned int k = r_itr.first;
374 A_[k].set_size(eij_size, ai_size);
375 B_[k].set_size(eij_size, bj_size);
377 W_[k].set_size(ai_size, bj_size);
378 Y_[k].set_size(ai_size, bj_size);
381 for (
int j=0; j<
num_b_; ++j)
384 V_[j].set_size(bj_size,bj_size);
387 inv_V_[j].set_size(bj_size,bj_size);
424 for (
auto & r_itr : row)
426 unsigned int j = r_itr.second;
427 unsigned int k = r_itr.first;;
457 for (
int i=0; i<
num_a_; ++i) {
459 for (
unsigned int ii=0; ii<Ui.
rows(); ++ii)
460 diag_UVT[z++] = Ui(ii,ii);
462 for (
int j=0; j<
num_b_; ++j) {
464 for (
unsigned int ii=0; ii<Vj.
rows(); ++ii)
465 diag_UVT[z++] = Vj(ii,ii);
467 for (
int ii=0; ii<
size_c_; ++ii)
468 diag_UVT[z++] =
T_(ii,ii);
478 for (
int i=0; i<
num_a_; ++i) {
480 for (
unsigned int ii=0; ii<Ui.
rows(); ++ii)
481 Ui(ii,ii) = diag[z++];
483 for (
int j=0; j<
num_b_; ++j) {
485 for (
unsigned int ii=0; ii<Vj.
rows(); ++ii)
486 Vj(ii,ii) = diag[z++];
488 for (
int ii=0; ii<
size_c_; ++ii)
489 T_(ii,ii) = diag[z++];
499 for (
int j=0; j<
num_b_; ++j) {
509 inv_Vj = Vj_cholesky.
inverse();
512 for (
auto & c_itr : col)
514 unsigned int k = c_itr.first;
515 Y_[k] =
W_[k]*inv_Vj;
529 for (
int i=0; i<
num_a_; ++i)
538 for (
auto & ri : row_i)
540 unsigned int j = ri.second;
541 unsigned int k = ri.first;
549 for (
int h=i+1; h<
num_a_; ++h)
556 bool row_done =
false;
557 for (
auto ri = row_i.begin(), rh = row_h.begin();
558 ri != row_i.end() && rh != row_h.end(); ++ri, ++rh)
560 while (!row_done && ri->second != rh->second)
562 while (!row_done && ri->second < rh->second)
563 row_done = (++ri == row_i.end());
564 while (!row_done && rh->second < ri->second)
565 row_done = (++rh == row_h.end());
585 for (
int i=0; i<
num_a_; ++i)
590 for (
int k=0; k<
num_a_; ++k)
608 for (
int j=0; j<
num_b_; ++j)
615 for (
auto & c_itr : col)
617 unsigned int k = c_itr.first;
618 unsigned int i = c_itr.second;
632 for (
int i=0; i<
num_a_; ++i)
639 for (
int j=0; j<
num_b_; ++j)
649 dc[0] = sec[0] / Sc(0,0);
659 dc = Sc_svd.
solve(sec);
662 dc = Sc_cholesky.
solve(sec);
676 for (
int i=0; i<
num_a_; ++i)
683 for (
auto & ri : row_i)
685 unsigned int k = ri.first;
703 for (
int i=0; i<
num_a_; ++i)
710 for (
auto & ri : row_i)
712 unsigned int k = ri.first;
721 for (
int h=i+1; h<
num_a_; ++h)
727 bool row_done =
false;
728 for (
auto ri = row_i.begin(), rh = row_h.begin();
729 ri != row_i.end() && rh != row_h.end(); ++ri, ++rh)
731 while (!row_done && ri->second != rh->second)
733 while (!row_done && ri->second < rh->second)
734 row_done = (++ri == row_i.end());
735 while (!row_done && rh->second < ri->second)
736 row_done = (++rh == row_h.end());
760 for (
int j=0; j<
num_b_; ++j)
768 for (
auto & c_itr : col)
770 unsigned int k = c_itr.first;
771 unsigned int i = c_itr.second;
792 #define whoami "vnl_sparse_lm" 797 s << (
whoami ": OIOIOI -- failure in leastsquares function\n");
800 s << (
whoami ": OIOIOI -- lmdif dodgy input\n");
803 s << (
whoami ": converged to ftol\n");
806 s << (
whoami ": converged to xtol\n");
809 s << (
whoami ": converged nicely\n");
812 s << (
whoami ": converged via gtol\n");
815 s << (
whoami ": too many iterations\n");
818 s << (
whoami ": ftol is too small. no further reduction in the sum of squares is possible.\n");
821 s << (
whoami ": xtol is too small. no further improvement in the approximate solution x is possible.\n");
824 s << (
whoami ": gtol is too small. f(a,b) is orthogonal to the columns of the jacobian to machine precision.\n");
827 s << (
whoami ": OIOIOI: unkown info code from lmder.\n");
832 <<
num_evaluations_ <<
" evaluations, "<< num_e <<
" residuals. RMS error start/end " unsigned int number_of_params_a(int i) const
Return the number of parameters of a_j.
unsigned int cols() const
Return the number of columns.
unsigned int index_a(int i) const
return the index of aj in a.
unsigned int number_of_b() const
Return the number of subsets in b.
void compute_normal_equations()
compute the blocks making up the the normal equations: Jt J d = Jt e.
Abstract base for sparse least squares functions.
std::vector< vnl_matrix< double > > inv_V_
Sparse Levenberg Marquardt nonlinear least squares.
Compressed Row Storage (CRS) indexing.
const vnl_crs_index & residual_indices() const
Return a const reference to the residual indexer.
unsigned int number_of_residuals(int k) const
Return the number of residuals in the kth residual vector.
unsigned int index_b(int j) const
return the index of bj in b.
VNL_EXPORT T dot_product(m const &, m const &)
static void dec_X_by_AB(vnl_matrix< double > &X, const vnl_matrix< double > &A, const vnl_matrix< double > &B)
Compute $X -= A B$.
vnl_matrix< T > transpose() const
Return transpose.
vnl_sparse_lst_sqr_function * f_
the function to minimize.
void compute_Ma(const vnl_matrix< double > &H)
compute Ma.
void compute_sea(vnl_vector< double > const &dc, vnl_vector< double > &sea)
compute sea using ea, Z, dc, Y, and eb.
vnl_vector using user-supplied storage
vnl_vector using user-supplied storage.
vnl_matrix< T > extract(unsigned r, unsigned c, unsigned top=0, unsigned left=0) const
Extract a sub-matrix of size r x c, starting at (top,left).
static void AB(vnl_matrix< double > &out, const vnl_matrix< double > &A, const vnl_matrix< double > &B)
Compute AxB.
void allocate_matrices()
allocate matrix memory by setting all the matrix sizes.
void solve_dc(vnl_vector< double > &dc)
solve for dc.
unsigned int number_of_a() const
Return the number of subsets in a.
virtual void compute_weights(vnl_vector< double > const &a, vnl_vector< double > const &b, vnl_vector< double > const &c, vnl_vector< double > const &f, vnl_vector< double > &weights)
If using weighted least squares, compute the weights for each i and j.
std::vector< vnl_matrix< double > > W_
vnl_vector< double > extract_diagonal() const
extract the vector on the diagonal of Jt J.
vnl_matrix< double > inverse() const
vnl_matrix< double > inv_covar_
int rank_deficiency() const
A Success/failure flag.
void compute_Z_Sa(vnl_matrix< double > &Sa)
compute Z and Sa.
static void inc_X_by_AtB(vnl_matrix< double > &X, const vnl_matrix< double > &A, const vnl_matrix< double > &B)
Compute $X += A^\top B$.
void set_diagonal(const vnl_vector< double > &diag)
set the vector on the diagonal of Jt J.
double get_end_error() const
Return the best error that was achieved by the last minimization, corresponding to the returned x.
Decomposition of symmetric matrix.
void compute_invV_Y()
compute all inv(Vi) and Yij.
size_t size() const
Return the length, number of elements, dimension of this vector.
std::vector< vnl_matrix< double > > B_
std::vector< vnl_matrix< double > > C_
T const * data_block() const
Access the contiguous block storing the elements in the vector. O(1).
unsigned int index_e(int k) const
return the index of ek in e.
Decomposition of symmetric matrix.
Abstract base for sparse least squares functions.
static void inc_X_by_ABt(vnl_matrix< double > &X, const vnl_matrix< double > &A, const vnl_matrix< double > &B)
Compute $X += A B^\top$.
vnl_matrix< T > inverse() const
double epsfcn
Step length for FD Jacobian.
vnl_vector< double > solve(vnl_vector< double > const &b) const
Solve LS problem M x = b.
double ftol
Termination tolerance on F (sum of squared residuals)
static void AtB(vnl_matrix< double > &out, const vnl_matrix< double > &A, const vnl_matrix< double > &B)
Compute $A^\top B$.
abs_t squared_magnitude() const
Return sum of squares of elements.
std::vector< vnl_matrix< double > > Ma_
bool has_weights() const
Return true if the derived class has indicated that.
virtual void trace(int iteration, vnl_vector< double > const &a, vnl_vector< double > const &b, vnl_vector< double > const &c, vnl_vector< double > const &e)
Called after each LM iteration to print debugging etc.
sparse_vector sparse_row(int i) const
returns row i as a vector of index-column pairs.
vnl_matrix< double > const & get_JtJ()
Return J'*J computed at last minimum.
vnl_matrix< T > solve(vnl_matrix< T > const &B) const
Solve the matrix equation M X = B, returning X.
~vnl_sparse_lm() override
Destructor.
Collection of C-style matrix functions.
sparse_vector sparse_col(int j) const
returns column j as a vector of index-row pairs.
void compute_Mb()
compute Mb.
void backsolve_db(vnl_vector< double > const &da, vnl_vector< double > const &dc, vnl_vector< double > &db)
back solve to find db using da and dc.
vnl_sparse_lm(vnl_sparse_lst_sqr_function &f)
Initialize with the function object that is to be minimized.
std::vector< vnl_matrix< double > > Mb_
static void inc_X_by_AB(vnl_matrix< double > &X, const vnl_matrix< double > &A, const vnl_matrix< double > &B)
Compute $X += A B$.
std::vector< vnl_matrix< double > > A_
Storage for each of the Jacobians A_ij, B_ij, and C_ij.
virtual void jac_blocks(vnl_vector< double > const &a, vnl_vector< double > const &b, vnl_vector< double > const &c, std::vector< vnl_matrix< double > > &A, std::vector< vnl_matrix< double > > &B, std::vector< vnl_matrix< double > > &C)
Compute the sparse Jacobian in block form.
static void Ab(vnl_vector< double > &out, const vnl_matrix< double > &A, const vnl_vector< double > &b)
Compute $A b$ for vector b. out may not be b.
double gtol
Termination tolerance on Grad(F)' * F = 0.
static void dec_X_by_AtB(vnl_matrix< double > &X, const vnl_matrix< double > &A, const vnl_matrix< double > &B)
Compute $X -= A^\top B$.
virtual void fd_jac_blocks(vnl_vector< double > const &a, vnl_vector< double > const &b, vnl_vector< double > const &c, std::vector< vnl_matrix< double > > &A, std::vector< vnl_matrix< double > > &B, std::vector< vnl_matrix< double > > &C, double stepsize)
Compute the sparse Jacobian in block form using a finite difference approximation.
std::vector< vnl_matrix< double > > V_
vnl_matrix & fill(T const &)
Sets all elements of matrix to specified value, and returns "*this".
void swap(vnl_vector< T > &that)
Set this to that and that to this.
std::vector< vnl_matrix< double > > R_
vnl_vector & fill(T const &v)
Set all values to v.
double tau_
used to compute the initial damping.
unsigned int number_of_e() const
Return the number of residual vectors.
void diagnose_outcome() const
Provide an ASCII diagnosis of the last minimization on std::ostream.
vnl_decnum max(vnl_decnum const &x, vnl_decnum const &y)
Represents the configuration of a sparse matrix but not the data.
virtual void apply_weights(vnl_vector< double > const &weights, vnl_vector< double > &f)
If using weighted least squares, apply the weights to residuals f.
double xtol
Termination tolerance on X (solution vector)
std::vector< vnl_matrix< double > > Y_
unsigned int rows() const
Return the number of rows.
Holds the singular value decomposition of a vnl_matrix.
std::vector< vnl_matrix< double > > Q_
double get_start_error() const
Return the error of the function when it was evaluated at the start point of the last minimization.
virtual void f(vnl_vector< double > const &a, vnl_vector< double > const &b, vnl_vector< double > const &c, vnl_vector< double > &f)
Compute all residuals.
std::vector< idx_pair > sparse_vector
unsigned int number_of_params_b(int j) const
Return the number of parameters of b_i.
abs_t inf_norm() const
Return largest absolute element value.
long maxfev
Termination maximum number of iterations.
void compute_Sa_sea(vnl_matrix< double > &Sa, vnl_vector< double > &sea)
compute Sa and sea.
std::vector< vnl_matrix< double > > Z_
bool set_size(unsigned r, unsigned c)
Resize to r rows by c columns. Old data lost.
static void inc_X_by_AtA(vnl_matrix< double > &X, const vnl_matrix< double > &A)
Compute $ X += A^\top A$.
Holds the singular value decomposition of a vnl_matrix.
bool has_gradient() const
Return true if the derived class has indicated that gradf has been implemented.
vnl_matrix< T > & update(vnl_matrix< T > const &, unsigned top=0, unsigned left=0)
Set values of this matrix to those of M, starting at [top,left].
vnl_vector< double > weights_
void init(vnl_sparse_lst_sqr_function *f)
bool check_vector_sizes(vnl_vector< double > const &a, vnl_vector< double > const &b, vnl_vector< double > const &c)
check vector sizes and verify that they match the problem size.
ReturnCodes failure_code_
vnl_diag_matrix< singval_t > & W()
Get at DiagMatrix (q.v.) of singular values, sorted from largest to smallest.
static void dec_X_by_ABt(vnl_matrix< double > &X, const vnl_matrix< double > &A, const vnl_matrix< double > &B)
Compute $X -= A B^\top$.
bool minimize(vnl_vector< double > &a, vnl_vector< double > &b, vnl_vector< double > &c, bool use_gradient=true, bool use_weights=true)
Minimize the function supplied in the constructor until convergence or failure.
std::vector< vnl_matrix< double > > U_
Storage for normal equation blocks.