コード例 #1
0
ファイル: trust.c プロジェクト: ohliumliu/gsl-playground
static int
trust_init(void *vstate, const gsl_vector *swts,
           gsl_multilarge_nlinear_fdf *fdf, const gsl_vector *x,
           gsl_vector *f, gsl_vector *g, gsl_matrix *JTJ)
{
  int status;
  trust_state_t *state = (trust_state_t *) vstate;
  const gsl_multilarge_nlinear_parameters *params = &(state->params);
  double Dx;

  /* evaluate function and Jacobian at x and apply weight transform */
  status = gsl_multilarge_nlinear_eval_f(fdf, x, swts, f);
  if (status)
   return status;

  /* compute g = J^T f and J^T J */
  status = gsl_multilarge_nlinear_eval_df(CblasTrans, x, f, f,
                                          swts, params->h_df, params->fdtype,
                                          fdf, g, JTJ, state->workn);
  if (status)
    return status;

  /* initialize diagonal scaling matrix D */
  if (JTJ != NULL)
    (params->scale->init)(JTJ, state->diag);
  else
    gsl_vector_set_all(state->diag, 1.0);

  /* compute initial trust region radius */
  Dx = trust_scaled_norm(state->diag, x);
  state->delta = 0.3 * GSL_MAX(1.0, Dx);

  /* initialize LM parameter */
  nielsen_init(JTJ, state->diag, &(state->mu), &(state->nu));

  /* initialize trust region method solver */
  {
    const gsl_multilarge_nlinear_trust_state trust_state = { x, f, g, JTJ, state->diag,
                                                             swts, &(state->mu), params,
                                                             state->solver_state, fdf,
                                                             &(state->avratio) };

    status = (params->trs->init)(&trust_state, state->trs_state);

    if (status)
      return status;
  }

  /* set default parameters */

  state->avratio = 0.0;

  return GSL_SUCCESS;
}
コード例 #2
0
ファイル: trust.c プロジェクト: ohliumliu/gsl-playground
static int
trust_iterate(void *vstate, const gsl_vector *swts,
              gsl_multilarge_nlinear_fdf *fdf, gsl_vector *x,
              gsl_vector *f, gsl_vector *g, gsl_matrix *JTJ,
              gsl_vector *dx)
{
  int status;
  trust_state_t *state = (trust_state_t *) vstate;
  const gsl_multilarge_nlinear_parameters *params = &(state->params);
  const gsl_multilarge_nlinear_trs *trs = params->trs;

  /* collect all state parameters needed by low level methods */
  const gsl_multilarge_nlinear_trust_state trust_state = { x, f, g, JTJ, state->diag,
                                                         swts, &(state->mu), params,
                                                         state->solver_state, fdf,
                                                         &(state->avratio) };

  gsl_vector *x_trial = state->x_trial;       /* trial x + dx */
  gsl_vector *f_trial = state->f_trial;       /* trial f(x + dx) */
  double rho;                                 /* ratio actual_reduction/predicted_reduction */
  int foundstep = 0;                          /* found step dx */
  int bad_steps = 0;                          /* consecutive rejected steps */

  /* initialize trust region subproblem with this Jacobian */
  status = (trs->preloop)(&trust_state, state->trs_state);
  if (status)
    return status;

  /* loop until we find an acceptable step dx */
  while (!foundstep)
    {
      /* calculate new step */
      status = (trs->step)(&trust_state, state->delta, dx, state->trs_state);

      /* occasionally the iterative methods (ie: CG Steihaug) can fail to find a step,
       * so in this case skip rho calculation and count it as a rejected step */

      if (status == GSL_SUCCESS)
        {
          /* compute x_trial = x + dx */
          trust_trial_step(x, dx, x_trial);

          /* compute f_trial = f(x + dx) */
          status = gsl_multilarge_nlinear_eval_f(fdf, x_trial, swts, f_trial);
          if (status)
            return status;

          /* check if step should be accepted or rejected */
          status = trust_eval_step(&trust_state, f_trial, dx, &rho, state);
          if (status == GSL_SUCCESS)
            foundstep = 1;

#if 0 /*XXX*/
          fprintf(stdout, "delta = %.12e |D dx| = %.12e |dx| = %.12e, dx0 = %.12e dx1 = %.12e |x_trial| = %.12e |f_trial| = %.12e rho = %.12e\n",
                  state->delta,
                  scaled_enorm(state->diag, dx),
                  gsl_blas_dnrm2(dx),
                  gsl_vector_get(dx, 0),
                  gsl_vector_get(dx, 1),
                  gsl_blas_dnrm2(x_trial),
                  gsl_blas_dnrm2(f_trial),
                  rho);
#endif
        }
      else
        {
          /* an iterative TRS method failed to find a step vector */
          rho = -1.0;
        }

      /*
       * update trust region radius: if rho is large,
       * then the quadratic model is a good approximation
       * to the objective function, enlarge trust region.
       * If rho is small (or negative), the model function
       * is a poor approximation so decrease trust region. This
       * can happen even if the step is accepted.
       */
      if (rho > 0.75)
        state->delta *= params->factor_up;
      else if (rho < 0.25)
        state->delta /= params->factor_down;

      if (foundstep)
        {
          /* step was accepted */

          /* update x <- x + dx */
          gsl_vector_memcpy(x, x_trial);

          /* update f <- f(x + dx) */
          gsl_vector_memcpy(f, f_trial);

          /* compute new g = J^T f and J^T J */
          status = gsl_multilarge_nlinear_eval_df(CblasTrans, x, f, f,
                                                  swts, params->h_df, params->fdtype,
                                                  fdf, g, JTJ, state->workn);
          if (status)
            return status;

          /* update scaling matrix D */
          if (JTJ != NULL)
            (params->scale->update)(JTJ, state->diag);

          /* step accepted, decrease LM parameter */
          nielsen_accept(rho, &(state->mu), &(state->nu));

          bad_steps = 0;
        }
      else
        {
          /* step rejected, increase LM parameter */
          nielsen_reject(&(state->mu), &(state->nu));

          /* if more than 15 consecutive rejected steps, report no progress */
          if (++bad_steps > 15)
            {
              return GSL_ENOPROG;
            }
        }
    }

  return GSL_SUCCESS;
} /* trust_iterate() */
コード例 #3
0
ファイル: cgst.c プロジェクト: gaponenko/gsl
static int
cgst_step(const void * vtrust_state, const double delta,
          gsl_vector * dx, void * vstate)
{
  int status;
  const gsl_multilarge_nlinear_trust_state *trust_state =
    (const gsl_multilarge_nlinear_trust_state *) vtrust_state;
  cgst_state_t *state = (cgst_state_t *) vstate;
  const gsl_vector * x = trust_state->x;
  const gsl_vector * f = trust_state->f;
  const gsl_vector * swts = trust_state->sqrt_wts;
  const gsl_vector * diag = trust_state->diag;
  const gsl_multilarge_nlinear_parameters * params = trust_state->params;
  gsl_multilarge_nlinear_fdf * fdf = trust_state->fdf;
  double alpha, beta, u;
  double norm_Jd;   /* || J D^{-1} d_i || */
  double norm_r;    /* || r_i || */
  double norm_rp1;  /* || r_{i+1} || */
  size_t i;

  /* Step 1 of [1], section 2; scale gradient as
   *
   * g~ = D^{-1} g
   *
   * for better numerical stability
   */

  for (i = 0; i < state->p; ++i)
    {
      double gi = gsl_vector_get(trust_state->g, i);
      double di = gsl_vector_get(trust_state->diag, i);

      gsl_vector_set(state->z, i, 0.0);
      gsl_vector_set(state->r, i, -gi / di);
      gsl_vector_set(state->d, i, -gi / di);
      gsl_vector_set(state->workp, i, gi / di);
    }

  /* compute || g~ || */
  state->norm_g = gsl_blas_dnrm2(state->workp);

  for (i = 0; i < state->cgmaxit; ++i)
    {
      /* workp := D^{-1} d_i */
      gsl_vector_memcpy(state->workp, state->d);
      gsl_vector_div(state->workp, trust_state->diag);

      /* workn := J D^{-1} d_i */
      status = gsl_multilarge_nlinear_eval_df(CblasNoTrans, x, f, state->workp,
                                              swts, params->h_df, params->fdtype,
                                              fdf, state->workn, NULL);
      if (status)
        return status;

      /* compute || J D^{-1} d_i || */
      norm_Jd = gsl_blas_dnrm2(state->workn);

      /* Step 2 of [1], section 2 */
      if (norm_Jd == 0.0)
        {
          double tau = cgst_calc_tau(state->z, state->d, delta);

          /* dx = z_i + tau*d_i */
          scaled_addition(1.0, state->z, tau, state->d, dx);
          gsl_vector_div(dx, diag);

          return GSL_SUCCESS;
        }

      /* Step 3 of [1], section 2 */

      norm_r = gsl_blas_dnrm2(state->r);
      u = norm_r / norm_Jd;
      alpha = u * u;

      /* workp <= z_{i+1} = z_i + alpha_i*d_i */
      scaled_addition(1.0, state->z, alpha, state->d, state->workp);

      u = gsl_blas_dnrm2(state->workp);
      if (u >= delta)
        {
          double tau = cgst_calc_tau(state->z, state->d, delta);

          /* dx = z_i + tau*d_i */
          scaled_addition(1.0, state->z, tau, state->d, dx);
          gsl_vector_div(dx, diag);

          return GSL_SUCCESS;
        }

      /* store z_{i+1} */
      gsl_vector_memcpy(state->z, state->workp);

      /* Step 4 of [1], section 2 */

      /* compute: workp := alpha B d_i = alpha D^{-1} J^T J D^{-1} d_i,
       * where J D^{-1} d_i is already stored in workn */
      status = gsl_multilarge_nlinear_eval_df(CblasTrans, x, f, state->workn,
                                              swts, params->h_df, params->fdtype,
                                              fdf, state->workp, NULL);
      if (status)
        return status;

      gsl_vector_div(state->workp, trust_state->diag);
      gsl_vector_scale(state->workp, alpha);

      /* r_{i+1} = r_i - alpha*B*d_i */
      gsl_vector_sub(state->r, state->workp);
      norm_rp1 = gsl_blas_dnrm2(state->r);

      u = norm_rp1 / state->norm_g;
      if (u < state->cgtol)
        {
          gsl_vector_memcpy(dx, state->z);
          gsl_vector_div(dx, diag);
          return GSL_SUCCESS;
        }

      /* Step 5 of [1], section 2 */

      /* compute u = ||r_{i+1}|| / || r_i|| */
      u = norm_rp1 / norm_r;
      beta = u * u;

      /* compute: d_{i+1} = rt_{i+1} + beta*d_i */
      scaled_addition(1.0, state->r, beta, state->d, state->d);
    }

  /* failed to converge, return current estimate */
  gsl_vector_memcpy(dx, state->z);
  gsl_vector_div(dx, diag);

  return GSL_EMAXITER;
}