/* Example programs from the book Scientific and Engineering Programming in C++: An Introduction with Advanced Techniques and Examples, Addison-Wesley, 1994. (c) COPYRIGHT INTERNATIONAL BUSINESS MACHINES CORPORATION 1994. ALL RIGHTS RESERVED. See README file for further details. */ #include "SciEng/NumericalLimits.h" template LevenbergMarquardtHessian:: LevenbergMarquardtHessian( Subscript nparms ) : LapackUnfactored< BlasRectLURep >(nparms,nparms), // square system for normal equations. b(nparms), the_chi2(NumericalLimits::maximum) { } template void LevenbergMarquardtHessian::doMarquardt(Range factor){ for (int i = 0; i < shape(0); i++){ (*this)(i,i) *= factor; } } template ConcreteBlas2d outer_product(const Array1d& lhs, const Array1d& rhs){ Subscript nrows = lhs.numElts(); Subscript ncols = rhs.numElts(); ConcreteBlas2d result(nrows, ncols); for(int i = 0; i < nrows; i++) { for(int j = 0; j < ncols; j++) { result(i,j) = lhs(i) * rhs(j); } } return result; } /* We minimize over \vec{a} \sigma_{i=1}^{N} \rho\left ( \frac{y_i - y(x_i;\vec{a})}{\sigma_i} \right ) */ #include "Vector/FormedArithmetic.h" template LevenbergMarquardtHessian:: LevenbergMarquardtHessian( const PhysicalData& the_data, const DataModel& the_model ): LapackUnfactored< BlasRectLURep >( the_model.parameters().numElts(),the_model.parameters().numElts() // square system for normal equations. ), b(the_model.parameters().numElts()), the_chi2(NumericalLimits::maximum) { Browser coordinates = the_data.coordinates(); // x_i Browser data = the_data.values(); // y_i Browser sigma = the_data.sigmas(); // sigma_i the_chi2 = 0.; // Temps. BlasRectLURep::Unfactored& alpha = rep(); alpha = 0.; FormedArithmetic1d beta(the_model.parameters().numElts()); beta = 0.; FormedArithmetic1d dy_da(the_model.parameters().numElts()); Range delta_i; while( coordinates.more() && data.more() && sigma.more() ){ Range the_sigma_i = sigma(); BasePtr< TaylorCoefficient1d > the_model_i = the_model(coordinates()); dy_da = the_model_i->gradient(); delta_i = ( data() - the_model_i->value() ) / the_sigma_i; the_chi2 += delta_i * delta_i * 0.5; // Numerical Recipes 14.6.3 beta -= delta_i * dy_da / the_sigma_i; alpha += outer_product(dy_da, dy_da) / (the_sigma_i * the_sigma_i); coordinates.next(); data.next(); sigma.next(); } b = beta; }