private static readonly double LM_USERTOL = 30*LM_MACHEP; /* users are recommened to require this */ /* If the above values do not work, the following seem good for an x86: LM_MACHEP .555e-16 LM_DWARF 9.9e-324 LM_SQRT_DWARF 1.0e-160 LM_SQRT_GIANT 1.0e150 LM_USER_TOL 1.0e-14 The following values should work on any machine: LM_MACHEP 1.02e-16 LM_DWARF 1.00e-38 LM_SQRT_DWARF 3.834e-20 LM_SQRT_GIANT 1.0304e19 LM_USER_TOL 1.0e-14 */ public static void lm_initialize_control( lm_control_type control ) { control.maxcall = 100; control.epsilon = LM_USERTOL; control.stepbound = 100; control.ftol = LM_USERTOL; control.xtol = LM_USERTOL; control.gtol = LM_USERTOL; }
public static void lm_minimize( int m_dat, int n_par, double[] par, evaluate_delegate evaluate, printout_delegate printout, object data, lm_control_type control ) { /*** allocate work space. ***/ double[] fvec, diag, fjac, qtf, wa1, wa2, wa3, wa4; int []ipvt; int n = n_par; int m = m_dat; fvec = new double[m]; diag = new double[n]; qtf = new double[n]; fjac = new double[n*m]; wa1 = new double[n]; wa2 = new double[n]; wa3 = new double[n]; wa4 = new double[m]; ipvt = new int[m]; /*** perform fit. ***/ control.info = 0; control.nfev = 0; /* this goes through the modified legacy interface: */ lm_lmdif( m, n, par, fvec, control.ftol, control.xtol, control.gtol, control.maxcall * (n + 1), control.epsilon, diag, 1, control.stepbound, ref control.info, ref control.nfev, fjac, ipvt, qtf, wa1, wa2, wa3, wa4, evaluate, printout, data ); if ( printout != null ) printout(n, par, m, fvec, data, -1, 0, control.nfev); control.fnorm = lm_enorm(m, fvec); if ( control.info < 0 ) control.info = 10; /*** clean up. ***/ } /*** lm_minimize. ***/
public static void demo() { // data and pameter arrays: int m_dat = 15; int n_p = 3; double[] t = { .07, .13, .19, .26, .32, .38, .44, .51, .57, .63, .69, .76, .82, .88, .94 }; double[] y = { .24, .35, .43, .49, .55, .61, .66, .71, .75, .79, .83, .87, .90, .94, .97 }; double[] p = { 1.0, 1.0, 1.0 }; // use any starting value, but not { 0,0,0 } // auxiliary settings: lm_control_type control = new lm_control_type(); lm_data_type_default data = new lm_data_type_default(); lm_initialize_control( control ); data.f = my_fit_function; data.tvec = t; data.yvec = y; // perform the fit: Console.Write( "modify or replace lm_print_default for less verbous fitting\n" ); lm_minimize( m_dat, n_p, p, lm_evaluate_default, lm_print_default, data, control ); // print results: Console.Write( "status: {0} after {1} evaluations\n", lm_shortmsg[control.info], control.nfev ); }