Esempio n. 1
0
opk_vmlmb_t*
opk_new_vmlmb_optimizer(const opk_vmlmb_options_t* opts,
                        opk_vspace_t* space,
                        opk_lnsrch_t* lnsrch,
                        opk_convexset_t* box)
{
  opk_vmlmb_options_t options;
  opk_vmlmb_t* opt;
  size_t s_offset, y_offset, alpha_offset, rho_offset, size;
  opk_index_t k, m;

  /* Check options. */
  if (opts == NULL) {
    /* Use default options. */
    opk_get_vmlmb_default_options(&options);
    opts = &options;
  }
  if (opk_check_vmlmb_options(opts) != OPK_SUCCESS) {
    errno = EINVAL;
    return NULL;
  }
  m = opts->mem;

  /* Check other input arguments for errors. */
  if (space == NULL) {
    errno = EFAULT;
    return NULL;
  }
  if (space->size < 1 || m < 1) {
    errno = EINVAL;
    return NULL;
  }
  if (m > space->size) {
    m = space->size;
  }
  if (box != NULL && box->space != space) {
    errno = EINVAL;
    return NULL;
  }

  /* Allocate enough memory for the workspace and its arrays. */
  s_offset = ROUND_UP(sizeof(opk_vmlmb_t), sizeof(opk_vector_t*));
  y_offset = s_offset + m*sizeof(opk_vector_t*);
  alpha_offset = ROUND_UP(y_offset + m*sizeof(opk_vector_t*), sizeof(double));
  rho_offset = alpha_offset + m*sizeof(double);
  size = rho_offset + m*sizeof(double);
  opt = (opk_vmlmb_t*)opk_allocate_object(finalize_vmlmb, size);
  if (opt == NULL) {
    return NULL;
  }
  opt->s           = ADDRESS(opk_vector_t*, opt,     s_offset);
  opt->y           = ADDRESS(opk_vector_t*, opt,     y_offset);
  opt->alpha       = ADDRESS(double,        opt, alpha_offset);
  opt->rho         = ADDRESS(double,        opt,   rho_offset);
  opt->m           = m;
  opt->gamma       = 1.0;
  opt->delta       = opts->delta;
  opt->epsilon     = opts->epsilon;
  opt->grtol       = opts->grtol;
  opt->gatol       = opts->gatol;
  opt->stpmin      = opts->stpmin;
  opt->stpmax      = opts->stpmax;
  opt->save_memory = opts->save_memory;
  if (box == NULL) {
    opt->method = OPK_LBFGS;
  } else if (opts->blmvm) {
    /* For the BLMVM method, the scratch vector is used to store the
       projected gradient. */
    opt->method = OPK_BLMVM;
    opt->gp = opk_vcreate(space);
    if (opt->gp == NULL) {
      goto error;
    }
  } else {
    opt->method = OPK_VMLMB;
  }

  /* Allocate work vectors.  If saving memory, x0 and g0 will be weak
     references to one of the saved vectors in the LBFGS operator. */
  for (k = 0; k < m; ++k) {
    opt->s[k] = opk_vcreate(space);
    if (opt->s[k] == NULL) {
      goto error;
    }
    opt->y[k] = opk_vcreate(space);
    if (opt->y[k] == NULL) {
      goto error;
    }
  }
  opt->vspace = OPK_HOLD_VSPACE(space);
  if (lnsrch != NULL) {
    opt->lnsrch = OPK_HOLD_LNSRCH(lnsrch);
  } else {
    if (box != NULL) {
      opt->lnsrch = opk_lnsrch_new_backtrack(SFTOL, SAMIN);
    } else {
      opt->lnsrch = opk_lnsrch_new_csrch(SFTOL, SGTOL, SXTOL);
    }
    if (opt->lnsrch == NULL) {
      goto error;
    }
  }
  if (! opt->save_memory) {
    opt->x0 = opk_vcreate(space);
    if (opt->x0 == NULL) {
      goto error;
    }
    opt->g0 = opk_vcreate(space);
    if (opt->g0 == NULL) {
      goto error;
    }
  }
  opt->d = opk_vcreate(space);
  if (opt->d == NULL) {
    goto error;
  }
  if (box != NULL) {
    opt->box = OPK_HOLD_CONVEXSET(box);
    opt->w = opk_vcreate(space);
    if (opt->w == NULL) {
      goto error;
    }
  }

  /* Enforce calling opk_vmlmb_start and return the optimizer. */
  failure(opt, OPK_NOT_STARTED);
  return opt;

 error:
  OPK_DROP(opt);
  return NULL;
}
Esempio n. 2
0
opk_vmlmn_t*
opk_new_vmlmn_optimizer(opk_vspace_t* space,
                        opk_index_t m,
                        unsigned int flags,
                        opk_bound_t* xl,
                        opk_bound_t* xu,
                        opk_lnsrch_t* lnsrch)
{
  opk_vmlmn_t* opt;
  size_t s_offset, y_offset, beta_offset, rho_offset, size;
  opk_index_t k;
  int bounds;

  /* Check the input arguments for errors. */
  if (space == NULL) {
    errno = EFAULT;
    return NULL;
  }
  if (space->size < 1 || m < 1) {
    errno = EINVAL;
    return NULL;
  }
  if (m > space->size) {
    m = space->size;
  }
  bounds = 0;
  if (xl != NULL) {
    if (xl->owner != space) {
      errno = EINVAL;
      return NULL;
    }
    if (xl->type == OPK_BOUND_SCALAR) {
      bounds += 1;
    } else if (xl->type == OPK_BOUND_VECTOR) {
      bounds += 2;
    } else {
      /* Discard unused bound. */
      xl = NULL;
    }
  }
  if (xu != NULL) {
    if (xu->owner != space) {
      errno = EINVAL;
      return NULL;
    }
    if (xu->type == OPK_BOUND_SCALAR) {
      bounds += 3;
    } else if (xu->type == OPK_BOUND_VECTOR) {
      bounds += 6;
    } else {
      /* Discard unused bound. */
      xu = NULL;
    }
  }

  /* Allocate enough memory for the workspace and its arrays. */
  s_offset = ROUND_UP(sizeof(opk_vmlmn_t), sizeof(opk_vector_t*));
  y_offset = s_offset + m*sizeof(opk_vector_t*);
  beta_offset = ROUND_UP(y_offset + m*sizeof(opk_vector_t*), sizeof(double));
  rho_offset = beta_offset + m*sizeof(double);
  size = rho_offset + m*sizeof(double);
  opt = (opk_vmlmn_t*)opk_allocate_object(finalize_vmlmn, size);
  if (opt == NULL) {
    return NULL;
  }
  opt->s      = ADDRESS(opk_vector_t*, opt,    s_offset);
  opt->y      = ADDRESS(opk_vector_t*, opt,    y_offset);
  opt->beta   = ADDRESS(double,        opt, beta_offset);
  opt->rho    = ADDRESS(double,        opt,  rho_offset);
  opt->m      = m;
  opt->gamma  = 1.0;
  opt->bounds = bounds;
  opt->flags  = flags;
  if (opt->bounds == 0) {
    opt->method = OPK_LBFGS;
  } else if ((flags & OPK_EMULATE_BLMVM) != 0) {
    /* For the BLMVM method, the scratch vector is used to store the
       projected gradient. */
    opt->method = OPK_BLMVM;
    opt->tmp = opk_vcreate(space);
    if (opt->tmp == NULL) {
      goto error;
    }
  } else {
    opt->method = OPK_VMLMN;
  }
  opk_set_vmlmn_options(opt, NULL);

  /* Allocate work vectors.  If saving memory, x0 and g0 will be weak
     references to one of the saved vectors in the LBFGS operator. */
  for (k = 0; k < m; ++k) {
    opt->s[k] = opk_vcreate(space);
    if (opt->s[k] == NULL) {
      goto error;
    }
    opt->y[k] = opk_vcreate(space);
    if (opt->y[k] == NULL) {
      goto error;
    }
  }
  opt->vspace = OPK_HOLD_VSPACE(space);
  if (lnsrch != NULL) {
    opt->lnsrch = OPK_HOLD_LNSRCH(lnsrch);
  } else {
    if (bounds != 0) {
      opt->lnsrch = opk_lnsrch_new_backtrack(SFTOL, SAMIN);
    } else {
      opt->lnsrch = opk_lnsrch_new_csrch(SFTOL, SGTOL, SXTOL);
    }
    if (opt->lnsrch == NULL) {
      goto error;
    }
  }
  if (xl != NULL) {
    opt->xl = OPK_HOLD_BOUND(xl);
  }
  if (xu != NULL) {
    opt->xu = OPK_HOLD_BOUND(xu);
  }
#if ! SAVE_MEMORY
  opt->x0 = opk_vcreate(space);
  if (opt->x0 == NULL) {
    goto error;
  }
  opt->g0 = opk_vcreate(space);
  if (opt->g0 == NULL) {
    goto error;
  }
#endif
  opt->d = opk_vcreate(space);
  if (opt->d == NULL) {
    goto error;
  }
  if (opt->bounds != 0) {
    opt->w = opk_vcreate(space);
    if (opt->w == NULL) {
      goto error;
    }
  }

  /* Enforce calling opk_vmlmn_start and return the optimizer. */
  failure(opt, OPK_NOT_STARTED);
  return opt;

 error:
  OPK_DROP(opt);
  return NULL;
}