Blame multifit/lmiterate.c

Packit 67cb25
static int
Packit 67cb25
iterate (void *vstate, const gsl_vector * swts,
Packit 67cb25
         gsl_multifit_function_fdf * fdf, gsl_vector * x,
Packit 67cb25
         gsl_vector * f, gsl_vector * dx, int scale)
Packit 67cb25
{
Packit 67cb25
  lmder_state_t *state = (lmder_state_t *) vstate;
Packit 67cb25
Packit 67cb25
  gsl_matrix *r = state->r;
Packit 67cb25
  gsl_vector *tau = state->tau;
Packit 67cb25
  gsl_vector *diag = state->diag;
Packit 67cb25
  gsl_vector *qtf = state->qtf;
Packit 67cb25
  gsl_vector *x_trial = state->x_trial;
Packit 67cb25
  gsl_vector *f_trial = state->f_trial;
Packit 67cb25
  gsl_vector *rptdx = state->rptdx;
Packit 67cb25
  gsl_vector *newton = state->newton;
Packit 67cb25
  gsl_vector *gradient = state->gradient;
Packit 67cb25
  gsl_vector *sdiag = state->sdiag;
Packit 67cb25
  gsl_vector *w = state->w;
Packit 67cb25
  gsl_vector *work1 = state->work1;
Packit 67cb25
  gsl_permutation *perm = state->perm;
Packit 67cb25
Packit 67cb25
  double prered, actred;
Packit 67cb25
  double pnorm, fnorm1, fnorm1p, gnorm;
Packit 67cb25
  double ratio;
Packit 67cb25
  double dirder;
Packit 67cb25
Packit 67cb25
  int iter = 0;
Packit 67cb25
Packit 67cb25
  double p1 = 0.1, p25 = 0.25, p5 = 0.5, p75 = 0.75, p0001 = 0.0001;
Packit 67cb25
Packit 67cb25
  if (state->fnorm == 0.0) 
Packit 67cb25
    {
Packit 67cb25
      return GSL_SUCCESS;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  /* Compute norm of scaled gradient */
Packit 67cb25
Packit 67cb25
  compute_gradient_direction (r, perm, qtf, diag, gradient);
Packit 67cb25
Packit 67cb25
  { 
Packit 67cb25
    size_t iamax = gsl_blas_idamax (gradient);
Packit 67cb25
Packit 67cb25
    gnorm = fabs(gsl_vector_get (gradient, iamax) / state->fnorm);
Packit 67cb25
  }
Packit 67cb25
Packit 67cb25
  /* Determine the Levenberg-Marquardt parameter */
Packit 67cb25
Packit 67cb25
lm_iteration:
Packit 67cb25
  
Packit 67cb25
  iter++ ;
Packit 67cb25
Packit 67cb25
  {
Packit 67cb25
    int status = lmpar (r, perm, qtf, diag, state->delta, &(state->par), newton, gradient, sdiag, dx, w);
Packit 67cb25
    if (status)
Packit 67cb25
      return status;
Packit 67cb25
  }
Packit 67cb25
Packit 67cb25
  /* Take a trial step */
Packit 67cb25
Packit 67cb25
  gsl_vector_scale (dx, -1.0); /* reverse the step to go downhill */
Packit 67cb25
Packit 67cb25
  compute_trial_step (x, dx, state->x_trial);
Packit 67cb25
Packit 67cb25
  pnorm = scaled_enorm (diag, dx);
Packit 67cb25
Packit 67cb25
  if (state->iter == 1)
Packit 67cb25
    {
Packit 67cb25
      if (pnorm < state->delta)
Packit 67cb25
        {
Packit 67cb25
#ifdef DEBUG
Packit 67cb25
          printf("set delta = pnorm = %g\n" , pnorm);
Packit 67cb25
#endif
Packit 67cb25
          state->delta = pnorm;
Packit 67cb25
        }
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  /* Evaluate function at x + p */
Packit 67cb25
  /* return immediately if evaluation raised error */
Packit 67cb25
  {
Packit 67cb25
    int status = gsl_multifit_eval_wf (fdf, x_trial, swts, f_trial);
Packit 67cb25
    if (status)
Packit 67cb25
      return status;
Packit 67cb25
  }
Packit 67cb25
Packit 67cb25
  fnorm1 = enorm (f_trial);
Packit 67cb25
Packit 67cb25
  /* Compute the scaled actual reduction */
Packit 67cb25
Packit 67cb25
  actred = compute_actual_reduction (state->fnorm, fnorm1);
Packit 67cb25
Packit 67cb25
#ifdef DEBUG
Packit 67cb25
  printf("lmiterate: fnorm = %g fnorm1 = %g  actred = %g\n", state->fnorm, fnorm1, actred);
Packit 67cb25
  printf("r = "); gsl_matrix_fprintf(stdout, r, "%g");
Packit 67cb25
  printf("perm = "); gsl_permutation_fprintf(stdout, perm, "%d");
Packit 67cb25
  printf("dx = "); gsl_vector_fprintf(stdout, dx, "%g");
Packit 67cb25
#endif
Packit 67cb25
Packit 67cb25
  /* Compute rptdx = R P^T dx, noting that |J dx| = |R P^T dx| */
Packit 67cb25
Packit 67cb25
  compute_rptdx (r, perm, dx, rptdx);
Packit 67cb25
Packit 67cb25
#ifdef DEBUG
Packit 67cb25
  printf("rptdx = "); gsl_vector_fprintf(stdout, rptdx, "%g");
Packit 67cb25
#endif
Packit 67cb25
Packit 67cb25
  fnorm1p = enorm (rptdx);
Packit 67cb25
Packit 67cb25
  /* Compute the scaled predicted reduction = |J dx|^2 + 2 par |D dx|^2 */
Packit 67cb25
Packit 67cb25
  { 
Packit 67cb25
    double t1 = fnorm1p / state->fnorm;
Packit 67cb25
    double t2 = (sqrt(state->par) * pnorm) / state->fnorm;
Packit 67cb25
    
Packit 67cb25
    prered = t1 * t1 + t2 * t2 / p5;
Packit 67cb25
    dirder = -(t1 * t1 + t2 * t2);
Packit 67cb25
  }
Packit 67cb25
Packit 67cb25
  /* compute the ratio of the actual to predicted reduction */
Packit 67cb25
Packit 67cb25
  if (prered > 0)
Packit 67cb25
    {
Packit 67cb25
      ratio = actred / prered;
Packit 67cb25
    }
Packit 67cb25
  else
Packit 67cb25
    {
Packit 67cb25
      ratio = 0;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
#ifdef DEBUG
Packit 67cb25
  printf("lmiterate: prered = %g dirder = %g ratio = %g\n", prered, dirder,ratio);
Packit 67cb25
#endif
Packit 67cb25
Packit 67cb25
Packit 67cb25
  /* update the step bound */
Packit 67cb25
Packit 67cb25
  if (ratio > p25)
Packit 67cb25
    {
Packit 67cb25
#ifdef DEBUG
Packit 67cb25
      printf("ratio > p25\n");
Packit 67cb25
#endif
Packit 67cb25
      if (state->par == 0 || ratio >= p75)
Packit 67cb25
        {
Packit 67cb25
          state->delta = pnorm / p5;
Packit 67cb25
          state->par *= p5;
Packit 67cb25
#ifdef DEBUG
Packit 67cb25
          printf("updated step bounds: delta = %g, par = %g\n", state->delta, state->par);
Packit 67cb25
#endif
Packit 67cb25
        }
Packit 67cb25
    }
Packit 67cb25
  else
Packit 67cb25
    {
Packit 67cb25
      double temp = (actred >= 0) ? p5 : p5*dirder / (dirder + p5 * actred);
Packit 67cb25
Packit 67cb25
#ifdef DEBUG
Packit 67cb25
      printf("ratio < p25\n");
Packit 67cb25
#endif
Packit 67cb25
Packit 67cb25
      if (p1 * fnorm1 >= state->fnorm || temp < p1 ) 
Packit 67cb25
        {
Packit 67cb25
          temp = p1;
Packit 67cb25
        }
Packit 67cb25
Packit 67cb25
      state->delta = temp * GSL_MIN_DBL (state->delta, pnorm/p1);
Packit 67cb25
Packit 67cb25
      state->par /= temp;
Packit 67cb25
#ifdef DEBUG
Packit 67cb25
      printf("updated step bounds: delta = %g, par = %g\n", state->delta, state->par);
Packit 67cb25
#endif
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
Packit 67cb25
  /* test for successful iteration, termination and stringent tolerances */
Packit 67cb25
Packit 67cb25
  if (ratio >= p0001)
Packit 67cb25
    {
Packit 67cb25
      gsl_vector_memcpy (x, x_trial);
Packit 67cb25
      gsl_vector_memcpy (f, f_trial);
Packit 67cb25
Packit 67cb25
      /* return immediately if evaluation raised error */
Packit 67cb25
      {
Packit 67cb25
        int status;
Packit 67cb25
Packit 67cb25
        /* compute Jacobian at new x and store in state->r */
Packit 67cb25
        if (fdf->df)
Packit 67cb25
          status = gsl_multifit_eval_wdf (fdf, x_trial, swts, r);
Packit 67cb25
        else
Packit 67cb25
          status = gsl_multifit_fdfsolver_dif_df(x_trial, swts, fdf, f_trial, r);
Packit 67cb25
Packit 67cb25
        if (status)
Packit 67cb25
          return status;
Packit 67cb25
      }
Packit 67cb25
Packit 67cb25
      /* wa2_j  = diag_j * x_j */
Packit 67cb25
      state->xnorm = scaled_enorm(diag, x);
Packit 67cb25
      state->fnorm = fnorm1;
Packit 67cb25
      state->iter++;
Packit 67cb25
Packit 67cb25
      /* Rescale if necessary */
Packit 67cb25
Packit 67cb25
      if (scale)
Packit 67cb25
        {
Packit 67cb25
          update_diag (r, diag);
Packit 67cb25
        }
Packit 67cb25
Packit 67cb25
      /* compute J = Q R P^T and qtf = Q^T f */
Packit 67cb25
      {
Packit 67cb25
        int signum;
Packit 67cb25
Packit 67cb25
        gsl_matrix_memcpy(state->J, r);
Packit 67cb25
        gsl_linalg_QRPT_decomp (r, tau, perm, &signum, work1);
Packit 67cb25
        gsl_vector_memcpy (qtf, f);
Packit 67cb25
        gsl_linalg_QR_QTvec (r, tau, qtf);
Packit 67cb25
      }
Packit 67cb25
      
Packit 67cb25
      return GSL_SUCCESS;
Packit 67cb25
    }
Packit 67cb25
  else if (fabs(actred) <= GSL_DBL_EPSILON  && prered <= GSL_DBL_EPSILON 
Packit 67cb25
           && p5 * ratio <= 1.0)
Packit 67cb25
    {
Packit 67cb25
      return GSL_ETOLF ;
Packit 67cb25
    }
Packit 67cb25
  else if (state->delta <= GSL_DBL_EPSILON * state->xnorm)
Packit 67cb25
    {
Packit 67cb25
      return GSL_ETOLX;
Packit 67cb25
    }
Packit 67cb25
  else if (gnorm <= GSL_DBL_EPSILON)
Packit 67cb25
    {
Packit 67cb25
      return GSL_ETOLG;
Packit 67cb25
    }
Packit 67cb25
  else if (iter < 10)
Packit 67cb25
    {
Packit 67cb25
      /* Repeat inner loop if unsuccessful */
Packit 67cb25
      goto lm_iteration;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  return GSL_ENOPROG;
Packit 67cb25
}