Actual source code: bqnls.c

  1: #include <../src/tao/bound/impls/bqnk/bqnk.h>

  3: static const char *BNK_AS[64] = {"none", "bertsekas"};

  5: static PetscErrorCode TaoBQNLSComputeHessian(Tao tao)
  6: {
  7:   TAO_BNK  *bnk  = (TAO_BNK *)tao->data;
  8:   TAO_BQNK *bqnk = (TAO_BQNK *)bnk->ctx;
  9:   PetscReal gnorm2, delta;

 11:   PetscFunctionBegin;
 12:   /* Compute the initial scaling and update the approximation */
 13:   gnorm2 = bnk->gnorm * bnk->gnorm;
 14:   if (gnorm2 == 0.0) gnorm2 = PETSC_MACHINE_EPSILON;
 15:   if (bnk->f == 0.0) delta = 2.0 / gnorm2;
 16:   else delta = 2.0 * PetscAbsScalar(bnk->f) / gnorm2;
 17:   PetscCall(MatLMVMSymBroydenSetDelta(bqnk->B, delta));
 18:   PetscCall(MatLMVMUpdate(bqnk->B, tao->solution, bnk->unprojected_gradient));
 19:   PetscFunctionReturn(PETSC_SUCCESS);
 20: }

 22: static PetscErrorCode TaoBQNLSComputeStep(Tao tao, PetscBool shift, KSPConvergedReason *ksp_reason, PetscInt *step_type)
 23: {
 24:   TAO_BNK  *bnk  = (TAO_BNK *)tao->data;
 25:   TAO_BQNK *bqnk = (TAO_BQNK *)bnk->ctx;
 26:   PetscInt  nupdates;

 28:   PetscFunctionBegin;
 29:   PetscCall(MatSolve(bqnk->B, tao->gradient, tao->stepdirection));
 30:   PetscCall(VecScale(tao->stepdirection, -1.0));
 31:   PetscCall(TaoBNKBoundStep(tao, bnk->as_type, tao->stepdirection));
 32:   *ksp_reason = KSP_CONVERGED_ATOL;
 33:   PetscCall(MatLMVMGetUpdateCount(bqnk->B, &nupdates));
 34:   if (nupdates == 0) *step_type = BNK_SCALED_GRADIENT;
 35:   else *step_type = BNK_BFGS;
 36:   PetscFunctionReturn(PETSC_SUCCESS);
 37: }

 39: static PetscErrorCode TaoSetFromOptions_BQNLS(Tao tao, PetscOptionItems *PetscOptionsObject)
 40: {
 41:   TAO_BNK  *bnk  = (TAO_BNK *)tao->data;
 42:   TAO_BQNK *bqnk = (TAO_BQNK *)bnk->ctx;
 43:   PetscBool is_set, is_spd;

 45:   PetscFunctionBegin;
 46:   PetscOptionsHeadBegin(PetscOptionsObject, "Quasi-Newton-Krylov method for bound constrained optimization");
 47:   PetscCall(PetscOptionsEList("-tao_bnk_as_type", "active set estimation method", "", BNK_AS, BNK_AS_TYPES, BNK_AS[bnk->as_type], &bnk->as_type, NULL));
 48:   PetscCall(PetscOptionsReal("-tao_bnk_epsilon", "(developer) tolerance used when computing actual and predicted reduction", "", bnk->epsilon, &bnk->epsilon, NULL));
 49:   PetscCall(PetscOptionsReal("-tao_bnk_as_tol", "(developer) initial tolerance used when estimating actively bounded variables", "", bnk->as_tol, &bnk->as_tol, NULL));
 50:   PetscCall(PetscOptionsReal("-tao_bnk_as_step", "(developer) step length used when estimating actively bounded variables", "", bnk->as_step, &bnk->as_step, NULL));
 51:   PetscCall(PetscOptionsInt("-tao_bnk_max_cg_its", "number of BNCG iterations to take for each Newton step", "", bnk->max_cg_its, &bnk->max_cg_its, NULL));
 52:   PetscOptionsHeadEnd();

 54:   PetscCall(TaoSetOptionsPrefix(bnk->bncg, ((PetscObject)tao)->prefix));
 55:   PetscCall(TaoAppendOptionsPrefix(bnk->bncg, "tao_bnk_"));
 56:   PetscCall(TaoSetFromOptions(bnk->bncg));

 58:   PetscCall(MatSetOptionsPrefix(bqnk->B, ((PetscObject)tao)->prefix));
 59:   PetscCall(MatAppendOptionsPrefix(bqnk->B, "tao_bqnls_"));
 60:   PetscCall(MatSetFromOptions(bqnk->B));
 61:   PetscCall(MatIsSPDKnown(bqnk->B, &is_set, &is_spd));
 62:   PetscCheck(is_set && is_spd, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_INCOMP, "LMVM matrix must be symmetric positive-definite");
 63:   PetscFunctionReturn(PETSC_SUCCESS);
 64: }

 66: /*MC
 67:   TAOBQNLS - Bounded Quasi-Newton Line Search method for nonlinear minimization with bound
 68:              constraints. This method approximates the action of the inverse-Hessian with a
 69:              limited memory quasi-Newton formula. The quasi-Newton matrix and its options are
 70:              accessible via the prefix `-tao_bqnls_`

 72:   Options Database Keys:
 73: + -tao_bnk_max_cg_its - maximum number of bounded conjugate-gradient iterations taken in each Newton loop
 74: . -tao_bnk_as_type - active-set estimation method ("none", "bertsekas")
 75: . -tao_bnk_epsilon - (developer) tolerance for small pred/actual ratios that trigger automatic step acceptance
 76: . -tao_bnk_as_tol - (developer) initial tolerance used in estimating bounded active variables (-as_type bertsekas)
 77: - -tao_bnk_as_step - (developer) trial step length used in estimating bounded active variables (-as_type bertsekas)

 79:   Level: beginner

 81: .seealso: `TAOBNK`
 82: M*/
 83: PETSC_EXTERN PetscErrorCode TaoCreate_BQNLS(Tao tao)
 84: {
 85:   TAO_BNK  *bnk;
 86:   TAO_BQNK *bqnk;

 88:   PetscFunctionBegin;
 89:   PetscCall(TaoCreate_BQNK(tao));
 90:   tao->ops->setfromoptions = TaoSetFromOptions_BQNLS;

 92:   bnk                 = (TAO_BNK *)tao->data;
 93:   bnk->update_type    = BNK_UPDATE_STEP;
 94:   bnk->computehessian = TaoBQNLSComputeHessian;
 95:   bnk->computestep    = TaoBQNLSComputeStep;

 97:   bqnk        = (TAO_BQNK *)bnk->ctx;
 98:   bqnk->solve = TaoSolve_BNLS;
 99:   PetscCall(MatSetType(bqnk->B, MATLMVMBFGS));
100:   PetscFunctionReturn(PETSC_SUCCESS);
101: }