21 using std::scientific;
47 stream <<
"Starting linear OEM inversion:" << endl << endl;
49 stream << setw(6) <<
"Step";
50 stream << setw(15) <<
" Chi^2 ";
51 stream << setw(15) <<
" Chi^2_x ";
52 stream << setw(15) <<
" Chi^2_y ";
72 stream << setw(5) << step_number <<
" ";
74 stream << setw(15) << cost;
75 stream << setw(15) << cost_x;
76 stream << setw(15) << cost_y;
109 stream <<
"Starting OEM inversion: " << endl << endl;
110 stream <<
"\tMethod: Gauss-Newton" << endl;
111 stream <<
"\tStop criterion: " << tol << endl;
112 stream <<
"\tMax. iterations: " << max_iter << endl << endl;
114 stream << setw(6) <<
"Step";
115 stream << setw(15) <<
" Chi^2 ";
116 stream << setw(15) <<
" Chi^2_x ";
117 stream << setw(15) <<
" Chi^2_y ";
118 stream << setw(15) <<
" d_i^2 ";
140 stream << setw(5) << step_number <<
" ";
141 stream << scientific;
142 stream << setw(15) << cost;
143 stream << setw(15) << cost_x;
144 stream << setw(15) << cost_y;
146 stream << setw(15) <<
"";
148 stream << setw(15) << di2;
171 stream <<
"\tConverged: YES";
172 else if ( iter == max_iter )
174 stream <<
"\tConverged: NO" << endl;
175 stream <<
"\tMaximum no. of iterations was reached.";
177 stream << endl << endl;
192 stream <<
"Starting OEM inversion: " << endl << endl;
193 stream <<
" Method: Levenberg-Marquardt " << endl;
194 stream <<
" Stop criterion: " << tol << endl;
195 stream <<
" Max. iterations: " << max_iter << endl << endl;
197 stream << setw(6) <<
"Step";
198 stream << setw(15) <<
" Chi^2 ";
199 stream << setw(15) <<
" Chi^2_x ";
200 stream << setw(15) <<
" Chi^2_y ";
201 stream << setw(9) <<
" gamma ";
202 stream << setw(15) <<
" d_i^2 ";
213 stream << setw(6) <<
"";
214 stream << scientific;
215 stream << setw(15) << cost;
216 stream << setw(15) << cost_x;
217 stream << setw(15) << cost_y;
218 stream.unsetf(ios_base::floatfield);
219 stream << setw(9) << gamma;
242 stream << setw(6) << step_number;
243 stream << scientific;
244 stream << setw(15) << cost;
245 stream << setw(15) << cost_x;
246 stream << setw(15) << cost_y;
247 stream.unsetf(ios_base::floatfield);
248 stream << setw(9) << gamma;
249 stream << scientific;
250 stream << setw(15) << di2;
278 stream << endl <<
"Finished Levenberg-Marquardt iterations:" << endl;
280 stream <<
"\t Converged: YES" << endl;
281 else if ( gamma == gamma_max )
283 stream <<
"\t Converged: NO" << endl;
284 stream <<
"\t Iteration aborted because gamma > gamma_max.";
286 else if ( iter == max_iter )
288 stream <<
"\t Converged: NO" << endl;
289 stream <<
"\t Iteration aborted because maximum no. of iterations was reached.";
293 stream <<
"\t Chi^2: " << cost << endl;
294 stream <<
"\t Chi^2_x: " << cost_x << endl;
295 stream <<
"\t Chi^2_y: " << cost_y << endl;
296 stream << endl << endl << endl;
318 template <
typename Se_t>
327 mult( tmp, SeInv, dy );
355 mult( tmp, SxInv, dx );
391 for (
Index j = 0; j < n; j++)
393 A(
i,j) = B(
i,j) * b[
i] * b[j];
421 for (
Index j = 0; j < n; j++)
423 A(
i,j) = B(
i,j) * b[j];
451 for (
Index j = 0; j < n; j++)
453 A(
i,j) = B(
i,j) * b[
i];
485 :
J(J_), SeInv(SeInv_), SxInv(SxInv_), x_norm()
490 assert(
is_size( SeInv_, m, m ) );
496 matrices_set =
false;
522 matrices_set =
false;
565 t1 = timer.add_timer(
"State vector computation" );
567 t2 = timer.add_timer(
"Matrix multiplication");
568 t3 = timer.add_timer(
"Linear system solving");
570 if (!(matrices_set || gain_set))
575 mult( tmp_nn_1, tmp_nm_1,
J);
587 ludcmp( LU, indx, tmp_nn_1 );
598 mult( tmp_n_1, tmp_nm_1, tmp_m_1 );
609 mult( x, G, tmp_m_1 );
645 compute_gain_matrix();
653 void LinearOEM::compute_gain_matrix()
658 t1 = timer.add_timer(
"Gain Matrix Computation" );
659 t2 = timer.add_timer(
"Matrix Matrix Mult.");
660 t3 = timer.add_timer(
"Linear System" );
665 tmp_nn_2.resize(
n,
n );
671 mult( tmp_nn_1, tmp_nm_1,
J);
683 ludcmp( LU, indx, tmp_nn_1 );
702 mult( G, tmp_nn_2, tmp_nm_1 );
708 matrices_set =
false;
720 void LinearOEM::compute_averaging_kernel(
MatrixView A )
729 compute_gain_matrix( );
849 const bool& verbose )
855 assert( xa.
nelem() == n );
856 assert( x_norm.
nelem() == 0 || x_norm.
nelem() == n );
857 assert( y.
nelem() == m );
858 assert( (SeInv.
ncols() == m) && (SeInv.
nrows() == m) );
859 assert( (SxInv.
ncols() == n) && (SxInv.
nrows() == n) );
861 LinearOEM
oem( J, SeInv, xa, SxInv );
863 if ( x_norm.
nelem() == n )
864 oem.set_x_norm( x_norm );
873 oem.compute( x, G, y, yf );
874 oem.compute_fit( yf, cost_x, cost_y, x, y, F );
879 log_step_li( cout, 1, cost_y+cost_x, cost_x, cost_y );
884 return oem.get_error();
928 template<
typename Se_t,
typename Sx_t>
929 NonLinearOEM<Se_t, Sx_t>::NonLinearOEM(
const Se_t &SeInv_,
934 : SeInv(SeInv_), SxInv(SxInv_), xa(xa_),
F(F_), method(method_)
940 assert( xa_.
nelem() ==
n );
941 assert( (SeInv_.
ncols() == m) && (SeInv_.
nrows() == m) );
942 assert( (SxInv_.
ncols() ==
n) && (SxInv_.
nrows() ==
n) );
960 matrices_set =
false;
984 template<
typename Se_t,
typename Sx_t>
995 template<
typename Se_t,
typename Sx_t>
1016 template<
typename Se_t,
typename Sx_t>
1022 if (method == GAUSS_NEWTON)
1024 gauss_newton( x, y, verbose );
1026 else if (method == LEVENBERG_MARQUARDT)
1028 levenberg_marquardt( x, y, verbose );
1032 cout << timer << endl;
1047 template<
typename Se_t,
typename Sx_t>
1054 if (method == GAUSS_NEWTON)
1056 gauss_newton( x, y, verbose );
1058 else if (method == LEVENBERG_MARQUARDT)
1060 levenberg_marquardt( x, y, verbose );
1063 compute_gain_matrix( x );
1067 cout << timer << endl;
1084 template<
typename Se_t,
typename Sx_t>
1085 void NonLinearOEM<Se_t, Sx_t>::gauss_newton(
Vector &x,
1090 Index t1, t2, t3, t4;
1091 t1 = timer.add_timer(
"Gauss-Newton Iteration" );
1092 t2 = timer.add_timer(
"Matrix Matrix Mult." );
1093 t3 = timer.add_timer(
"Linear System" );
1094 t4 = timer.add_timer(
"Jacobian Evaluation" );
1099 cost_x = 0.0; cost_y = 0.0;
1115 while ( (!conv) && (iter < max_iter) )
1123 F.evaluate_jacobian( yi,
J, x);
1136 mult( tmp_nn_1, tmp_nm_1,
J );
1151 mult( tmp_n_2, SxInv, tmp_n_1 );
1159 mult( tmp_n_1, tmp_nm_1, tmp_m_1 );
1171 log_step_gn( cout, iter, cost_x + cost_y, cost_x, cost_y, di2 );
1174 solve(
dx, tmp_nn_1, tmp_n_1 );
1193 if ( iter == max_iter )
1233 template<
typename Se_t,
typename Sx_t>
1234 void NonLinearOEM<Se_t, Sx_t>::levenberg_marquardt(
Vector &x,
1239 Index t1, t2, t3, t4;
1240 t1 = timer.add_timer(
"Levenberg-Marquardt Iteration" );
1241 t2 = timer.add_timer(
"Matrix Matrix Mult." );
1242 t3 = timer.add_timer(
"Linear System" );
1243 t4 = timer.add_timer(
"Jacobian Evaluation" );
1261 while ( (!conv) && (iter < max_iter) && (gamma <= ga_max) )
1268 F.evaluate_jacobian( yi,
J, x);
1280 mult( tmp_nn_1, tmp_nm_1,
J );
1285 mult( tmp_n_2, SxInv, tmp_n_1 );
1289 mult( tmp_n_1, tmp_nm_1, tmp_m_1 );
1299 cost_old = cost_y + cost_x;
1302 log_step_gn( cout, iter, cost_x + cost_y, cost_x, cost_y, di2 );
1304 bool found_x =
false;
1308 tmp_nn_2 *= ( 1.0 + gamma );
1309 tmp_nn_2 += tmp_nn_1;
1320 solve(
dx, tmp_nn_2, tmp_n_1 );
1335 F.evaluate( yi, xnew );
1348 cost = cost_x + cost_y;
1352 if (cost < cost_old)
1355 if ( gamma >= (ga_threshold * ga_decrease))
1356 gamma /= ga_decrease;
1369 if ( gamma < ga_threshold )
1370 gamma = ga_threshold;
1373 if ( gamma < ga_max )
1375 gamma *= ga_increase;
1382 gamma = ga_max + 1.0;
1403 if ( iter == max_iter )
1405 if ( gamma >= ga_max )
1413 cost = cost_x + cost_y;
1415 gamma, ga_max, iter, max_iter );
1429 template<
typename Se_t,
typename Sx_t>
1430 Index NonLinearOEM<Se_t, Sx_t>::compute_fit(
Vector &yf,
1435 F.evaluate( yf, x );
1460 template<
typename Se_t,
typename Sx_t>
1461 Index NonLinearOEM<Se_t, Sx_t>::compute_fit(
Vector &yf,
1470 F.evaluate( yf, x );
1491 template<
typename Se_t,
typename Sx_t>
1492 void NonLinearOEM<Se_t, Sx_t>::compute_gain_matrix(
ConstVectorView x )
1494 Index t1, t2, t3, t4;
1495 t1 = timer.add_timer(
"Gain Matrix Computation" );
1496 t2 = timer.add_timer(
"Matrix Matrix Mult." );
1497 t3 = timer.add_timer(
"Linear System" );
1498 t4 = timer.add_timer(
"Jacobian Evaluation" );
1504 F.evaluate_jacobian( tmp_m_1,
J, x);
1515 mult( tmp_nn_1, tmp_nm_1,
J );
1527 inv( tmp_nn_2, tmp_nn_1 );
1531 mult( G, tmp_nn_2, tmp_nm_1 );
1544 template <
typename Se_t,
typename Sx_t>
1545 void NonLinearOEM<Se_t,Sx_t>::compute_averaging_kernel(
MatrixView A,
1548 assert( A.
ncols() ==
n );
1549 assert( A.
nrows() ==
n );
1554 compute_gain_matrix( x );
1602 template <
typename Se_t,
typename Sx_t>
1616 const Index max_iter,
1624 assert( xa.
nelem() == n );
1625 assert( x_norm.
nelem() == 0 || x_norm.
nelem() == n );
1626 assert( y.
nelem() == m );
1627 assert( (SeInv.ncols() == m) && (SeInv.nrows() == m) );
1628 assert( (SxInv.ncols() == n) && (SxInv.nrows() == n) );
1630 NonLinearOEM<Se_t, Sx_t>
1631 oem( SeInv, xa, SxInv, F, GAUSS_NEWTON);
1632 oem.tolerance( tol );
1633 oem.maximum_iterations( max_iter );
1635 if ( x_norm.
nelem() == n )
1636 oem.set_x_norm( x_norm );
1638 oem.compute( x, G, y, verbose );
1639 oem.compute_fit( yf, cost_x, cost_y, x, y );
1641 J = oem.get_jacobian();
1644 iter = oem.iterations();
1646 return oem.get_error();
1702 template <
typename Se_t,
typename Sx_t>
1730 assert( xa.
nelem() == n );
1731 assert( x_norm.
nelem() == 0 || x_norm.
nelem() == n );
1732 assert( y.
nelem() == m );
1733 assert( (SeInv.ncols() == m) && (SeInv.nrows() == m) );
1734 assert( (SxInv.ncols() == n) && (SxInv.nrows() == n) );
1736 NonLinearOEM<Se_t, Sx_t>
1737 oem( SeInv, xa, SxInv, F, LEVENBERG_MARQUARDT);
1738 oem.tolerance( tol );
1739 oem.maximum_iterations( max_iter );
1740 oem.gamma_start( gamma_start );
1741 oem.gamma_decrease( gamma_decrease );
1742 oem.gamma_increase( gamma_increase );
1743 oem.gamma_max( gamma_max );
1744 oem.gamma_threshold( gamma_threshold );
1746 if ( x_norm.
nelem() == n )
1747 oem.set_x_norm( x_norm );
1749 oem.compute( x, G, y, verbose );
1750 oem.compute_fit( yf, cost_x, cost_y, x, y );
1752 J = oem.get_jacobian();
1754 iter = oem.iterations();
1756 return oem.get_error();
1802 assert( x.
nelem() == n );
1803 assert( xa.
nelem() == n );
1804 assert( y.
nelem() == m );
1806 assert( (Se.
ncols() == m) && (Se.
nrows() == m) );
1807 assert( (Sx.
ncols() == n) && (Sx.
nrows() == n) );
1811 Matrix tmp_mm(m,m), tmp_mm2(m,m);
1815 mult( tmp_mm, K, tmp_nm);
1819 inv( tmp_mm2, tmp_mm );
1820 mult( G, tmp_nm, tmp_mm2 );
1824 mult( x, G, tmp_m );
1863 Matrix Ki(m,
n), SxKiT(m,
n), KiSxKiT(m, m);
1864 Vector xi(
n), yi(m), tm(m), tm2(m), tn(
n), yi_old(m);
1867 bool converged =
false;
1872 while ((!converged) && (iter < max_iter))
1876 K.evaluate_jacobian( yi, Ki, x );
1883 solve( tm, Se, yi_old );
1884 mult( tm2, KiSxKiT, tm );
1886 solve( tm, Se, tm2);
1888 if ( fabs( di2 ) < tol * (
Numeric)
n )
1896 mult( KiSxKiT, Ki, SxKiT );
1907 solve( tm2, KiSxKiT, tm );
1908 mult( x, SxKiT, tm2 );
1952 Matrix Ki(m,
n), KiTSeInvKi(
n,
n), KiTSeInv(m,
n), SeInv(m,m), SxInv(
n,
n);
1953 Vector xi(
n),
dx(
n), dx_old(
n), yi(m), tm(m), tn(
n), sInvDx(
n);
1956 bool converged =
false;
1966 while ((!converged) && (iter < max_iter))
1970 K.evaluate_jacobian( yi, Ki, x );
1972 mult( KiTSeInvKi, KiTSeInv, Ki );
1973 KiTSeInvKi += SxInv;
1983 mult( tn, KiTSeInv, tm );
1992 mult( sInvDx, KiTSeInv, tm );
1993 mult( tn, SxInv, dx_old );
1999 if ( di2 <= tol * (
Numeric) m )
void separator(ostream &stream, Index length)
bool oem_gauss_newton_m_form(VectorView x, ConstVectorView y, ConstVectorView xa, ForwardModel &K, ConstMatrixView Se, ConstMatrixView Sx, Numeric tol, Index max_iter)
Non-linear OEM using Gauss-Newton method.
INDEX Index
The type to use for all integer numbers and indices.
void log_init_gn(ostream &stream, Numeric tol, Index max_iter)
Initial log message, Gauss-Newton.
Index oem_levenberg_marquardt(Vector &x, Matrix &G, Matrix &J, Vector &yf, Numeric &cost_y, Numeric &cost_x, Index &iter, ForwardModel &F, ConstVectorView xa, ConstVectorView x_norm, ConstVectorView y, const Se_t &SeInv, const Sx_t &SxInv, Index max_iter, Numeric tol, Numeric gamma_start, Numeric gamma_decrease, Numeric gamma_increase, Numeric gamma_max, Numeric gamma_threshold, bool verbose)
Non-linear OEM using Levenberg-Marquardt method.
void oem_linear_mform(VectorView x, MatrixView G, ConstVectorView xa, ConstVectorView yf, ConstVectorView y, ConstMatrixView K, ConstMatrixView Se, ConstMatrixView Sx)
Linear OEM, m-form.
Index oem_linear_nform(Vector &x, Matrix &G, Matrix &J, Vector &yf, Numeric &cost_y, Numeric &cost_x, ForwardModel &F, ConstVectorView xa, ConstVectorView x_norm, ConstVectorView y, ConstMatrixView SeInv, ConstMatrixView SxInv, const Numeric &cost_start, const bool &verbose)
Linear OEM, n-form.
void scale_rows(MatrixView A, ConstMatrixView B, ConstVectorView b)
Scale rows.
void lubacksub(VectorView x, ConstMatrixView LU, ConstVectorView b, const ArrayOfIndex &indx)
LU backsubstitution.
void log_finalize_gn(ostream &stream, bool converged, Index iter, Index max_iter)
Final log message, Gauss-Newton.
void oem_cost_x(Numeric &cost_x, ConstVectorView x, ConstVectorView xa, ConstMatrixView SxInv, const Numeric &normfac)
Calculation of x-part of cost function.
void mult_outer(MatrixView A, ConstMatrixView B, ConstVectorView b)
Multiply matrix element-wise by outer product of vector.
void log_step_gn(ostream &stream, Index step_number, Numeric cost, Numeric cost_x, Numeric cost_y, Numeric di2)
Step log message, Gauss-Newton.
void log_gamma_step_lm(ostream &stream, Numeric cost, Numeric cost_x, Numeric cost_y, Numeric gamma)
Linear algebra functions.
invlib::Vector< ArtsVector > Vector
invlib wrapper type for ARTS vectors.
void oem_cost_y(Numeric &cost_y, ConstVectorView y, ConstVectorView yf, Se_t SeInv, const Numeric &normfac)
Calculation of y-part of cost function.
void scale_columns(MatrixView A, ConstMatrixView B, ConstVectorView b)
Scale columns.
Index nelem() const
Returns the number of elements.
void log_init_li(ostream &stream)
Initial log message, linear.
Array< Index > ArrayOfIndex
An array of Index.
Index ncols() const
Returns the number of columns.
The global header file for ARTS.
NUMERIC Numeric
The type to use for all floating point numbers.
void log_finalize_lm(ostream &stream, bool converged, Numeric cost, Numeric cost_x, Numeric cost_y, Numeric gamma, Numeric gamma_max, Index iter, Index max_iter)
Final log message, Levenberg-Marquardt.
void log_init_lm(ostream &stream, Numeric tol, Index max_iter)
Initial log message, Levenberg-Marquardt.
void log_finalize_li(ostream &stream)
Final log message, linear.
void mult(ComplexVectorView y, const ConstComplexMatrixView &M, const ConstComplexVectorView &x)
Matrix-Vector Multiplication.
Header file for logic.cc.
Vector compute(const Numeric p, const Numeric t, const Numeric xco2, const Numeric xh2o, const ConstVectorView invcm_grid, const Numeric stotmax, const calctype type)
ConstComplexMatrixView transpose(ConstComplexMatrixView m)
Const version of transpose.
void log_step_lm(ostream &stream, Index step_number, Numeric cost, Numeric cost_x, Numeric cost_y, Numeric gamma, Numeric di2)
Step log message, Levenberg-Marquardt.
void inv(MatrixView Ainv, ConstMatrixView A)
Matrix Inverse.
A constant view of a Vector.
A constant view of a Matrix.
bool is_size(ConstVectorView x, const Index &n)
Verifies that the size of x is l.
Header file for helper functions for OpenMP.
bool oem_gauss_newton_n_form(VectorView x, ConstVectorView y, ConstVectorView xa, ForwardModel &K, ConstMatrixView Se, ConstMatrixView Sx, Numeric tol, Index max_iter)
Non-linear OEM using Gauss-Newton method.
Index oem_gauss_newton(Vector &x, Matrix &G, Matrix &J, Vector &yf, Numeric &cost_y, Numeric &cost_x, Index &iter, ForwardModel &F, ConstVectorView xa, ConstVectorView x_norm, ConstVectorView y, const Se_t &SeInv, const Sx_t &SxInv, const Index max_iter, const Numeric tol, bool verbose)
Gauss-Newton non-linear OEM using precomputed inverses, n-form.
void solve(VectorView w, const CovarianceMatrix &A, ConstVectorView v)
void log_step_li(ostream &stream, Index step_number, Numeric cost, Numeric cost_x, Numeric cost_y)
Step log message, linear.
void ludcmp(Matrix &LU, ArrayOfIndex &indx, ConstMatrixView A)
LU decomposition.
invlib::Matrix< ArtsMatrix > Matrix
invlib wrapper type for ARTS matrices.
Index nrows() const
Returns the number of rows.