1 #include <petsc/private/taoimpl.h> /*I "petsctao.h" I*/ 2 3 /*@ 4 TaoSetInitialVector - Sets the initial guess for the solve 5 6 Logically collective on Tao 7 8 Input Parameters: 9 + tao - the Tao context 10 - x0 - the initial guess 11 12 Level: beginner 13 .seealso: TaoCreate(), TaoSolve() 14 @*/ 15 16 PetscErrorCode TaoSetInitialVector(Tao tao, Vec x0) 17 { 18 PetscErrorCode ierr; 19 20 PetscFunctionBegin; 21 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 22 if (x0) { 23 PetscValidHeaderSpecific(x0,VEC_CLASSID,2); 24 PetscObjectReference((PetscObject)x0); 25 } 26 ierr = VecDestroy(&tao->solution);CHKERRQ(ierr); 27 tao->solution = x0; 28 PetscFunctionReturn(0); 29 } 30 31 /*@ 32 TaoComputeGradient - Computes the gradient of the objective function 33 34 Collective on Tao 35 36 Input Parameters: 37 + tao - the Tao context 38 - X - input vector 39 40 Output Parameter: 41 . G - gradient vector 42 43 Notes: 44 TaoComputeGradient() is typically used within minimization implementations, 45 so most users would not generally call this routine themselves. 46 47 Level: advanced 48 49 .seealso: TaoComputeObjective(), TaoComputeObjectiveAndGradient(), TaoSetGradientRoutine() 50 @*/ 51 PetscErrorCode TaoComputeGradient(Tao tao, Vec X, Vec G) 52 { 53 PetscErrorCode ierr; 54 PetscReal dummy; 55 56 PetscFunctionBegin; 57 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 58 PetscValidHeaderSpecific(X,VEC_CLASSID,2); 59 PetscValidHeaderSpecific(G,VEC_CLASSID,2); 60 PetscCheckSameComm(tao,1,X,2); 61 PetscCheckSameComm(tao,1,G,3); 62 ierr = VecLockPush(X);CHKERRQ(ierr); 63 if (tao->ops->computegradient) { 64 ierr = PetscLogEventBegin(Tao_GradientEval,tao,X,G,NULL);CHKERRQ(ierr); 65 PetscStackPush("Tao user gradient evaluation routine"); 66 ierr = (*tao->ops->computegradient)(tao,X,G,tao->user_gradP);CHKERRQ(ierr); 67 PetscStackPop; 68 ierr = PetscLogEventEnd(Tao_GradientEval,tao,X,G,NULL);CHKERRQ(ierr); 69 tao->ngrads++; 70 } else if (tao->ops->computeobjectiveandgradient) { 71 ierr = PetscLogEventBegin(Tao_ObjGradientEval,tao,X,G,NULL);CHKERRQ(ierr); 72 PetscStackPush("Tao user objective/gradient evaluation routine"); 73 ierr = (*tao->ops->computeobjectiveandgradient)(tao,X,&dummy,G,tao->user_objgradP);CHKERRQ(ierr); 74 PetscStackPop; 75 ierr = PetscLogEventEnd(Tao_ObjGradientEval,tao,X,G,NULL);CHKERRQ(ierr); 76 tao->nfuncgrads++; 77 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"TaoSetGradientRoutine() has not been called"); 78 ierr = VecLockPop(X);CHKERRQ(ierr); 79 PetscFunctionReturn(0); 80 } 81 82 /*@ 83 TaoComputeObjective - Computes the objective function value at a given point 84 85 Collective on Tao 86 87 Input Parameters: 88 + tao - the Tao context 89 - X - input vector 90 91 Output Parameter: 92 . f - Objective value at X 93 94 Notes: 95 TaoComputeObjective() is typically used within minimization implementations, 96 so most users would not generally call this routine themselves. 97 98 Level: advanced 99 100 .seealso: TaoComputeGradient(), TaoComputeObjectiveAndGradient(), TaoSetObjectiveRoutine() 101 @*/ 102 PetscErrorCode TaoComputeObjective(Tao tao, Vec X, PetscReal *f) 103 { 104 PetscErrorCode ierr; 105 Vec temp; 106 107 PetscFunctionBegin; 108 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 109 PetscValidHeaderSpecific(X,VEC_CLASSID,2); 110 PetscCheckSameComm(tao,1,X,2); 111 ierr = VecLockPush(X);CHKERRQ(ierr); 112 if (tao->ops->computeobjective) { 113 ierr = PetscLogEventBegin(Tao_ObjectiveEval,tao,X,NULL,NULL);CHKERRQ(ierr); 114 PetscStackPush("Tao user objective evaluation routine"); 115 ierr = (*tao->ops->computeobjective)(tao,X,f,tao->user_objP);CHKERRQ(ierr); 116 PetscStackPop; 117 ierr = PetscLogEventEnd(Tao_ObjectiveEval,tao,X,NULL,NULL);CHKERRQ(ierr); 118 tao->nfuncs++; 119 } else if (tao->ops->computeobjectiveandgradient) { 120 ierr = PetscInfo(tao,"Duplicating variable vector in order to call func/grad routine\n");CHKERRQ(ierr); 121 ierr = VecDuplicate(X,&temp);CHKERRQ(ierr); 122 ierr = PetscLogEventBegin(Tao_ObjGradientEval,tao,X,NULL,NULL);CHKERRQ(ierr); 123 PetscStackPush("Tao user objective/gradient evaluation routine"); 124 ierr = (*tao->ops->computeobjectiveandgradient)(tao,X,f,temp,tao->user_objgradP);CHKERRQ(ierr); 125 PetscStackPop; 126 ierr = PetscLogEventEnd(Tao_ObjGradientEval,tao,X,NULL,NULL);CHKERRQ(ierr); 127 ierr = VecDestroy(&temp);CHKERRQ(ierr); 128 tao->nfuncgrads++; 129 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"TaoSetObjectiveRoutine() has not been called"); 130 ierr = PetscInfo1(tao,"TAO Function evaluation: %20.19e\n",(double)(*f));CHKERRQ(ierr); 131 ierr = VecLockPop(X);CHKERRQ(ierr); 132 PetscFunctionReturn(0); 133 } 134 135 /*@ 136 TaoComputeObjectiveAndGradient - Computes the objective function value at a given point 137 138 Collective on Tao 139 140 Input Parameters: 141 + tao - the Tao context 142 - X - input vector 143 144 Output Parameter: 145 + f - Objective value at X 146 - g - Gradient vector at X 147 148 Notes: 149 TaoComputeObjectiveAndGradient() is typically used within minimization implementations, 150 so most users would not generally call this routine themselves. 151 152 Level: advanced 153 154 .seealso: TaoComputeGradient(), TaoComputeObjectiveAndGradient(), TaoSetObjectiveRoutine() 155 @*/ 156 PetscErrorCode TaoComputeObjectiveAndGradient(Tao tao, Vec X, PetscReal *f, Vec G) 157 { 158 PetscErrorCode ierr; 159 160 PetscFunctionBegin; 161 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 162 PetscValidHeaderSpecific(X,VEC_CLASSID,2); 163 PetscValidHeaderSpecific(G,VEC_CLASSID,4); 164 PetscCheckSameComm(tao,1,X,2); 165 PetscCheckSameComm(tao,1,G,4); 166 ierr = VecLockPush(X);CHKERRQ(ierr); 167 if (tao->ops->computeobjectiveandgradient) { 168 ierr = PetscLogEventBegin(Tao_ObjGradientEval,tao,X,G,NULL);CHKERRQ(ierr); 169 if (tao->ops->computegradient == TaoDefaultComputeGradient) { 170 ierr = TaoComputeObjective(tao,X,f);CHKERRQ(ierr); 171 ierr = TaoDefaultComputeGradient(tao,X,G,NULL);CHKERRQ(ierr); 172 } else { 173 PetscStackPush("Tao user objective/gradient evaluation routine"); 174 ierr = (*tao->ops->computeobjectiveandgradient)(tao,X,f,G,tao->user_objgradP);CHKERRQ(ierr); 175 PetscStackPop; 176 } 177 ierr = PetscLogEventEnd(Tao_ObjGradientEval,tao,X,G,NULL);CHKERRQ(ierr); 178 tao->nfuncgrads++; 179 } else if (tao->ops->computeobjective && tao->ops->computegradient) { 180 ierr = PetscLogEventBegin(Tao_ObjectiveEval,tao,X,NULL,NULL);CHKERRQ(ierr); 181 PetscStackPush("Tao user objective evaluation routine"); 182 ierr = (*tao->ops->computeobjective)(tao,X,f,tao->user_objP);CHKERRQ(ierr); 183 PetscStackPop; 184 ierr = PetscLogEventEnd(Tao_ObjectiveEval,tao,X,NULL,NULL);CHKERRQ(ierr); 185 tao->nfuncs++; 186 ierr = PetscLogEventBegin(Tao_GradientEval,tao,X,G,NULL);CHKERRQ(ierr); 187 PetscStackPush("Tao user gradient evaluation routine"); 188 ierr = (*tao->ops->computegradient)(tao,X,G,tao->user_gradP);CHKERRQ(ierr); 189 PetscStackPop; 190 ierr = PetscLogEventEnd(Tao_GradientEval,tao,X,G,NULL);CHKERRQ(ierr); 191 tao->ngrads++; 192 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"TaoSetObjectiveRoutine() or TaoSetGradientRoutine() not set"); 193 ierr = PetscInfo1(tao,"TAO Function evaluation: %20.19e\n",(double)(*f));CHKERRQ(ierr); 194 ierr = VecLockPop(X);CHKERRQ(ierr); 195 PetscFunctionReturn(0); 196 } 197 198 /*@C 199 TaoSetObjectiveRoutine - Sets the function evaluation routine for minimization 200 201 Logically collective on Tao 202 203 Input Parameter: 204 + tao - the Tao context 205 . func - the objective function 206 - ctx - [optional] user-defined context for private data for the function evaluation 207 routine (may be NULL) 208 209 Calling sequence of func: 210 $ func (Tao tao, Vec x, PetscReal *f, void *ctx); 211 212 + x - input vector 213 . f - function value 214 - ctx - [optional] user-defined function context 215 216 Level: beginner 217 218 .seealso: TaoSetGradientRoutine(), TaoSetHessianRoutine() TaoSetObjectiveAndGradientRoutine() 219 @*/ 220 PetscErrorCode TaoSetObjectiveRoutine(Tao tao, PetscErrorCode (*func)(Tao, Vec, PetscReal*,void*),void *ctx) 221 { 222 PetscFunctionBegin; 223 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 224 tao->user_objP = ctx; 225 tao->ops->computeobjective = func; 226 PetscFunctionReturn(0); 227 } 228 229 /*@C 230 TaoSetSeparableObjectiveRoutine - Sets the function evaluation routine for least-square applications 231 232 Logically collective on Tao 233 234 Input Parameter: 235 + tao - the Tao context 236 . func - the objective function evaluation routine 237 - ctx - [optional] user-defined context for private data for the function evaluation 238 routine (may be NULL) 239 240 Calling sequence of func: 241 $ func (Tao tao, Vec x, Vec f, void *ctx); 242 243 + x - input vector 244 . f - function value vector 245 - ctx - [optional] user-defined function context 246 247 Level: beginner 248 249 .seealso: TaoSetObjectiveRoutine(), TaoSetJacobianRoutine() 250 @*/ 251 PetscErrorCode TaoSetSeparableObjectiveRoutine(Tao tao, Vec sepobj, PetscErrorCode (*func)(Tao, Vec, Vec, void*),void *ctx) 252 { 253 PetscFunctionBegin; 254 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 255 PetscValidHeaderSpecific(sepobj, VEC_CLASSID,2); 256 tao->user_sepobjP = ctx; 257 tao->sep_objective = sepobj; 258 tao->ops->computeseparableobjective = func; 259 PetscFunctionReturn(0); 260 } 261 262 /*@ 263 TaoSetSeparableObjectiveWeights - Give weights for the separable objective values. A vector can be used if only diagonal terms are used, otherwise a matrix can be give. If this function is not used, or if sigma_v and sigma_w are both NULL, then the default identity matrix will be used for weights. 264 265 Collective on Tao 266 267 Input Parameters: 268 + tao - the Tao context 269 . sigma_v - vector of weights (diagonal terms only) 270 . n - the number of weights (if using off-diagonal) 271 . rows - index list of rows for sigma_w 272 . cols - index list of columns for sigma_w 273 - vals - array of weights 274 275 276 277 Note: Either sigma_v or sigma_w (or both) should be NULL 278 279 Level: intermediate 280 281 .seealso: TaoSetSeparableObjectiveRoutine() 282 @*/ 283 PetscErrorCode TaoSetSeparableObjectiveWeights(Tao tao, Vec sigma_v, PetscInt n, PetscInt *rows, PetscInt *cols, PetscReal *vals) 284 { 285 PetscErrorCode ierr; 286 PetscInt i; 287 PetscFunctionBegin; 288 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 289 ierr = VecDestroy(&tao->sep_weights_v);CHKERRQ(ierr); 290 tao->sep_weights_v=sigma_v; 291 if (sigma_v) { 292 ierr = PetscObjectReference((PetscObject)sigma_v);CHKERRQ(ierr); 293 } 294 if (vals) { 295 if (tao->sep_weights_n) { 296 ierr = PetscFree(tao->sep_weights_rows);CHKERRQ(ierr); 297 ierr = PetscFree(tao->sep_weights_cols);CHKERRQ(ierr); 298 ierr = PetscFree(tao->sep_weights_w);CHKERRQ(ierr); 299 } 300 ierr = PetscMalloc1(n,&tao->sep_weights_rows);CHKERRQ(ierr); 301 ierr = PetscMalloc1(n,&tao->sep_weights_cols);CHKERRQ(ierr); 302 ierr = PetscMalloc1(n,&tao->sep_weights_w);CHKERRQ(ierr); 303 tao->sep_weights_n=n; 304 for (i=0;i<n;i++) { 305 tao->sep_weights_rows[i]=rows[i]; 306 tao->sep_weights_cols[i]=cols[i]; 307 tao->sep_weights_w[i]=vals[i]; 308 } 309 } else { 310 tao->sep_weights_n=0; 311 tao->sep_weights_rows=0; 312 tao->sep_weights_cols=0; 313 } 314 PetscFunctionReturn(0); 315 } 316 /*@ 317 TaoComputeSeparableObjective - Computes a separable objective function vector at a given point (for least-square applications) 318 319 Collective on Tao 320 321 Input Parameters: 322 + tao - the Tao context 323 - X - input vector 324 325 Output Parameter: 326 . f - Objective vector at X 327 328 Notes: 329 TaoComputeSeparableObjective() is typically used within minimization implementations, 330 so most users would not generally call this routine themselves. 331 332 Level: advanced 333 334 .seealso: TaoSetSeparableObjectiveRoutine() 335 @*/ 336 PetscErrorCode TaoComputeSeparableObjective(Tao tao, Vec X, Vec F) 337 { 338 PetscErrorCode ierr; 339 340 PetscFunctionBegin; 341 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 342 PetscValidHeaderSpecific(X,VEC_CLASSID,2); 343 PetscValidHeaderSpecific(F,VEC_CLASSID,3); 344 PetscCheckSameComm(tao,1,X,2); 345 PetscCheckSameComm(tao,1,F,3); 346 if (tao->ops->computeseparableobjective) { 347 ierr = PetscLogEventBegin(Tao_ObjectiveEval,tao,X,NULL,NULL);CHKERRQ(ierr); 348 PetscStackPush("Tao user separable objective evaluation routine"); 349 ierr = (*tao->ops->computeseparableobjective)(tao,X,F,tao->user_sepobjP);CHKERRQ(ierr); 350 PetscStackPop; 351 ierr = PetscLogEventEnd(Tao_ObjectiveEval,tao,X,NULL,NULL);CHKERRQ(ierr); 352 tao->nfuncs++; 353 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"TaoSetSeparableObjectiveRoutine() has not been called"); 354 ierr = PetscInfo(tao,"TAO separable function evaluation.\n");CHKERRQ(ierr); 355 PetscFunctionReturn(0); 356 } 357 358 /*@C 359 TaoSetGradientRoutine - Sets the gradient evaluation routine for minimization 360 361 Logically collective on Tao 362 363 Input Parameter: 364 + tao - the Tao context 365 . func - the gradient function 366 - ctx - [optional] user-defined context for private data for the gradient evaluation 367 routine (may be NULL) 368 369 Calling sequence of func: 370 $ func (Tao tao, Vec x, Vec g, void *ctx); 371 372 + x - input vector 373 . g - gradient value (output) 374 - ctx - [optional] user-defined function context 375 376 Level: beginner 377 378 .seealso: TaoSetObjectiveRoutine(), TaoSetHessianRoutine() TaoSetObjectiveAndGradientRoutine() 379 @*/ 380 PetscErrorCode TaoSetGradientRoutine(Tao tao, PetscErrorCode (*func)(Tao, Vec, Vec, void*),void *ctx) 381 { 382 PetscFunctionBegin; 383 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 384 tao->user_gradP = ctx; 385 tao->ops->computegradient = func; 386 PetscFunctionReturn(0); 387 } 388 389 /*@C 390 TaoSetObjectiveAndGradientRoutine - Sets a combined objective function and gradient evaluation routine for minimization 391 392 Logically collective on Tao 393 394 Input Parameter: 395 + tao - the Tao context 396 . func - the gradient function 397 - ctx - [optional] user-defined context for private data for the gradient evaluation 398 routine (may be NULL) 399 400 Calling sequence of func: 401 $ func (Tao tao, Vec x, PetscReal *f, Vec g, void *ctx); 402 403 + x - input vector 404 . f - objective value (output) 405 . g - gradient value (output) 406 - ctx - [optional] user-defined function context 407 408 Level: beginner 409 410 .seealso: TaoSetObjectiveRoutine(), TaoSetHessianRoutine() TaoSetObjectiveAndGradientRoutine() 411 @*/ 412 PetscErrorCode TaoSetObjectiveAndGradientRoutine(Tao tao, PetscErrorCode (*func)(Tao, Vec, PetscReal *, Vec, void*), void *ctx) 413 { 414 PetscFunctionBegin; 415 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 416 tao->user_objgradP = ctx; 417 tao->ops->computeobjectiveandgradient = func; 418 PetscFunctionReturn(0); 419 } 420 421 /*@ 422 TaoIsObjectiveDefined -- Checks to see if the user has 423 declared an objective-only routine. Useful for determining when 424 it is appropriate to call TaoComputeObjective() or 425 TaoComputeObjectiveAndGradient() 426 427 Collective on Tao 428 429 Input Parameter: 430 + tao - the Tao context 431 - ctx - PETSC_TRUE if objective function routine is set by user, 432 PETSC_FALSE otherwise 433 Level: developer 434 435 .seealso: TaoSetObjectiveRoutine(), TaoIsGradientDefined(), TaoIsObjectiveAndGradientDefined() 436 @*/ 437 PetscErrorCode TaoIsObjectiveDefined(Tao tao, PetscBool *flg) 438 { 439 PetscFunctionBegin; 440 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 441 if (tao->ops->computeobjective == 0) *flg = PETSC_FALSE; 442 else *flg = PETSC_TRUE; 443 PetscFunctionReturn(0); 444 } 445 446 /*@ 447 TaoIsGradientDefined -- Checks to see if the user has 448 declared an objective-only routine. Useful for determining when 449 it is appropriate to call TaoComputeGradient() or 450 TaoComputeGradientAndGradient() 451 452 Not Collective 453 454 Input Parameter: 455 + tao - the Tao context 456 - ctx - PETSC_TRUE if gradient routine is set by user, PETSC_FALSE otherwise 457 Level: developer 458 459 .seealso: TaoSetGradientRoutine(), TaoIsObjectiveDefined(), TaoIsObjectiveAndGradientDefined() 460 @*/ 461 PetscErrorCode TaoIsGradientDefined(Tao tao, PetscBool *flg) 462 { 463 PetscFunctionBegin; 464 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 465 if (tao->ops->computegradient == 0) *flg = PETSC_FALSE; 466 else *flg = PETSC_TRUE; 467 PetscFunctionReturn(0); 468 } 469 470 /*@ 471 TaoIsObjectiveAndGradientDefined -- Checks to see if the user has 472 declared a joint objective/gradient routine. Useful for determining when 473 it is appropriate to call TaoComputeObjective() or 474 TaoComputeObjectiveAndGradient() 475 476 Not Collective 477 478 Input Parameter: 479 + tao - the Tao context 480 - ctx - PETSC_TRUE if objective/gradient routine is set by user, PETSC_FALSE otherwise 481 Level: developer 482 483 .seealso: TaoSetObjectiveAndGradientRoutine(), TaoIsObjectiveDefined(), TaoIsGradientDefined() 484 @*/ 485 PetscErrorCode TaoIsObjectiveAndGradientDefined(Tao tao, PetscBool *flg) 486 { 487 PetscFunctionBegin; 488 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 489 if (tao->ops->computeobjectiveandgradient == 0) *flg = PETSC_FALSE; 490 else *flg = PETSC_TRUE; 491 PetscFunctionReturn(0); 492 } 493