1aaa7dc30SBarry Smith #include <../src/tao/unconstrained/impls/neldermead/neldermead.h> 2aaa7dc30SBarry Smith #include <petscvec.h> 3a7e14dcfSSatish Balay 440244768SBarry Smith /*------------------------------------------------------------*/ 540244768SBarry Smith static PetscErrorCode NelderMeadSort(TAO_NelderMead *nm) 640244768SBarry Smith { 740244768SBarry Smith PetscReal *values = nm->f_values; 840244768SBarry Smith PetscInt *indices = nm->indices; 940244768SBarry Smith PetscInt dim = nm->N+1; 1040244768SBarry Smith PetscInt i,j,index; 1140244768SBarry Smith PetscReal val; 1240244768SBarry Smith 1340244768SBarry Smith PetscFunctionBegin; 1440244768SBarry Smith for (i=1;i<dim;i++) { 1540244768SBarry Smith index = indices[i]; 1640244768SBarry Smith val = values[index]; 1740244768SBarry Smith for (j=i-1; j>=0 && values[indices[j]] > val; j--) { 1840244768SBarry Smith indices[j+1] = indices[j]; 1940244768SBarry Smith } 2040244768SBarry Smith indices[j+1] = index; 2140244768SBarry Smith } 2240244768SBarry Smith PetscFunctionReturn(0); 2340244768SBarry Smith } 2440244768SBarry Smith 2540244768SBarry Smith /*------------------------------------------------------------*/ 2640244768SBarry Smith static PetscErrorCode NelderMeadReplace(TAO_NelderMead *nm, PetscInt index, Vec Xmu, PetscReal f) 2740244768SBarry Smith { 2840244768SBarry Smith PetscFunctionBegin; 2940244768SBarry Smith /* Add new vector's fraction of average */ 309566063dSJacob Faibussowitsch PetscCall(VecAXPY(nm->Xbar,nm->oneOverN,Xmu)); 319566063dSJacob Faibussowitsch PetscCall(VecCopy(Xmu,nm->simplex[index])); 3240244768SBarry Smith nm->f_values[index] = f; 3340244768SBarry Smith 349566063dSJacob Faibussowitsch PetscCall(NelderMeadSort(nm)); 3540244768SBarry Smith 3640244768SBarry Smith /* Subtract last vector from average */ 379566063dSJacob Faibussowitsch PetscCall(VecAXPY(nm->Xbar,-nm->oneOverN,nm->simplex[nm->indices[nm->N]])); 3840244768SBarry Smith PetscFunctionReturn(0); 3940244768SBarry Smith } 4040244768SBarry Smith 41a7e14dcfSSatish Balay /* ---------------------------------------------------------- */ 42441846f8SBarry Smith static PetscErrorCode TaoSetUp_NM(Tao tao) 43a7e14dcfSSatish Balay { 44a7e14dcfSSatish Balay TAO_NelderMead *nm = (TAO_NelderMead *)tao->data; 4553506e15SBarry Smith PetscInt n; 46a7e14dcfSSatish Balay 47a7e14dcfSSatish Balay PetscFunctionBegin; 489566063dSJacob Faibussowitsch PetscCall(VecGetSize(tao->solution,&n)); 4953506e15SBarry Smith nm->N = n; 5053506e15SBarry Smith nm->oneOverN = 1.0/n; 519566063dSJacob Faibussowitsch PetscCall(VecDuplicateVecs(tao->solution,nm->N+1,&nm->simplex)); 529566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nm->N+1,&nm->f_values)); 539566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nm->N+1,&nm->indices)); 549566063dSJacob Faibussowitsch PetscCall(VecDuplicate(tao->solution,&nm->Xbar)); 559566063dSJacob Faibussowitsch PetscCall(VecDuplicate(tao->solution,&nm->Xmur)); 569566063dSJacob Faibussowitsch PetscCall(VecDuplicate(tao->solution,&nm->Xmue)); 579566063dSJacob Faibussowitsch PetscCall(VecDuplicate(tao->solution,&nm->Xmuc)); 58a7e14dcfSSatish Balay 5983c8fe1dSLisandro Dalcin tao->gradient=NULL; 60a7e14dcfSSatish Balay tao->step=0; 61a7e14dcfSSatish Balay PetscFunctionReturn(0); 62a7e14dcfSSatish Balay } 63a7e14dcfSSatish Balay 64a7e14dcfSSatish Balay /* ---------------------------------------------------------- */ 6540244768SBarry Smith static PetscErrorCode TaoDestroy_NM(Tao tao) 66a7e14dcfSSatish Balay { 67a7e14dcfSSatish Balay TAO_NelderMead *nm = (TAO_NelderMead*)tao->data; 6853506e15SBarry Smith 69a7e14dcfSSatish Balay PetscFunctionBegin; 70a7e14dcfSSatish Balay if (tao->setupcalled) { 719566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(nm->N+1,&nm->simplex)); 729566063dSJacob Faibussowitsch PetscCall(VecDestroy(&nm->Xmuc)); 739566063dSJacob Faibussowitsch PetscCall(VecDestroy(&nm->Xmue)); 749566063dSJacob Faibussowitsch PetscCall(VecDestroy(&nm->Xmur)); 759566063dSJacob Faibussowitsch PetscCall(VecDestroy(&nm->Xbar)); 76a7e14dcfSSatish Balay } 779566063dSJacob Faibussowitsch PetscCall(PetscFree(nm->indices)); 789566063dSJacob Faibussowitsch PetscCall(PetscFree(nm->f_values)); 799566063dSJacob Faibussowitsch PetscCall(PetscFree(tao->data)); 80a7e14dcfSSatish Balay PetscFunctionReturn(0); 81a7e14dcfSSatish Balay } 82a7e14dcfSSatish Balay 83a7e14dcfSSatish Balay /*------------------------------------------------------------*/ 8440244768SBarry Smith static PetscErrorCode TaoSetFromOptions_NM(PetscOptionItems *PetscOptionsObject,Tao tao) 85a7e14dcfSSatish Balay { 86a7e14dcfSSatish Balay TAO_NelderMead *nm = (TAO_NelderMead*)tao->data; 87a7e14dcfSSatish Balay 88a7e14dcfSSatish Balay PetscFunctionBegin; 89d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject,"Nelder-Mead options"); 909566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-tao_nm_lamda","initial step length","",nm->lamda,&nm->lamda,NULL)); 919566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-tao_nm_mu","mu","",nm->mu_oc,&nm->mu_oc,NULL)); 92a7e14dcfSSatish Balay nm->mu_ic = -nm->mu_oc; 93a7e14dcfSSatish Balay nm->mu_r = nm->mu_oc*2.0; 94a7e14dcfSSatish Balay nm->mu_e = nm->mu_oc*4.0; 95d0609cedSBarry Smith PetscOptionsHeadEnd(); 96a7e14dcfSSatish Balay PetscFunctionReturn(0); 97a7e14dcfSSatish Balay } 98a7e14dcfSSatish Balay 99a7e14dcfSSatish Balay /*------------------------------------------------------------*/ 10040244768SBarry Smith static PetscErrorCode TaoView_NM(Tao tao,PetscViewer viewer) 101a7e14dcfSSatish Balay { 102a7e14dcfSSatish Balay TAO_NelderMead *nm = (TAO_NelderMead*)tao->data; 103a7e14dcfSSatish Balay PetscBool isascii; 104a7e14dcfSSatish Balay 105a7e14dcfSSatish Balay PetscFunctionBegin; 1069566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii)); 107a7e14dcfSSatish Balay if (isascii) { 1089566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 109*63a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"expansions: %" PetscInt_FMT "\n",nm->nexpand)); 110*63a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"reflections: %" PetscInt_FMT "\n",nm->nreflect)); 111*63a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"inside contractions: %" PetscInt_FMT "\n",nm->nincontract)); 112*63a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"outside contractionss: %" PetscInt_FMT "\n",nm->noutcontract)); 113*63a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"Shrink steps: %" PetscInt_FMT "\n",nm->nshrink)); 1149566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 115a7e14dcfSSatish Balay } 116a7e14dcfSSatish Balay PetscFunctionReturn(0); 117a7e14dcfSSatish Balay } 118a7e14dcfSSatish Balay 119a7e14dcfSSatish Balay /*------------------------------------------------------------*/ 12040244768SBarry Smith static PetscErrorCode TaoSolve_NM(Tao tao) 121a7e14dcfSSatish Balay { 122a7e14dcfSSatish Balay TAO_NelderMead *nm = (TAO_NelderMead*)tao->data; 123a7e14dcfSSatish Balay PetscReal *x; 1248931d482SJason Sarich PetscInt i; 125a7e14dcfSSatish Balay Vec Xmur=nm->Xmur, Xmue=nm->Xmue, Xmuc=nm->Xmuc, Xbar=nm->Xbar; 126a7e14dcfSSatish Balay PetscReal fr,fe,fc; 127a7e14dcfSSatish Balay PetscInt shrink; 128a7e14dcfSSatish Balay PetscInt low,high; 129a7e14dcfSSatish Balay 130a7e14dcfSSatish Balay PetscFunctionBegin; 131a7e14dcfSSatish Balay nm->nshrink = 0; 132a7e14dcfSSatish Balay nm->nreflect = 0; 133a7e14dcfSSatish Balay nm->nincontract = 0; 134a7e14dcfSSatish Balay nm->noutcontract = 0; 135a7e14dcfSSatish Balay nm->nexpand = 0; 136a7e14dcfSSatish Balay 137a7e14dcfSSatish Balay if (tao->XL || tao->XU || tao->ops->computebounds) { 1389566063dSJacob Faibussowitsch PetscCall(PetscInfo(tao,"WARNING: Variable bounds have been set but will be ignored by NelderMead algorithm\n")); 139a7e14dcfSSatish Balay } 140a7e14dcfSSatish Balay 1419566063dSJacob Faibussowitsch PetscCall(VecCopy(tao->solution,nm->simplex[0])); 1429566063dSJacob Faibussowitsch PetscCall(TaoComputeObjective(tao,nm->simplex[0],&nm->f_values[0])); 143a7e14dcfSSatish Balay nm->indices[0]=0; 144a7e14dcfSSatish Balay for (i=1;i<nm->N+1;i++) { 1459566063dSJacob Faibussowitsch PetscCall(VecCopy(tao->solution,nm->simplex[i])); 1469566063dSJacob Faibussowitsch PetscCall(VecGetOwnershipRange(nm->simplex[i],&low,&high)); 147a7e14dcfSSatish Balay if (i-1 >= low && i-1 < high) { 1489566063dSJacob Faibussowitsch PetscCall(VecGetArray(nm->simplex[i],&x)); 149a7e14dcfSSatish Balay x[i-1-low] += nm->lamda; 1509566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(nm->simplex[i],&x)); 151a7e14dcfSSatish Balay } 152a7e14dcfSSatish Balay 1539566063dSJacob Faibussowitsch PetscCall(TaoComputeObjective(tao,nm->simplex[i],&nm->f_values[i])); 154a7e14dcfSSatish Balay nm->indices[i] = i; 155a7e14dcfSSatish Balay } 156a7e14dcfSSatish Balay 157a7e14dcfSSatish Balay /* Xbar = (Sum of all simplex vectors - worst vector)/N */ 1589566063dSJacob Faibussowitsch PetscCall(NelderMeadSort(nm)); 1599566063dSJacob Faibussowitsch PetscCall(VecSet(Xbar,0.0)); 160a7e14dcfSSatish Balay for (i=0;i<nm->N;i++) { 1619566063dSJacob Faibussowitsch PetscCall(VecAXPY(Xbar,1.0,nm->simplex[nm->indices[i]])); 162a7e14dcfSSatish Balay } 1639566063dSJacob Faibussowitsch PetscCall(VecScale(Xbar,nm->oneOverN)); 1643ecd9318SAlp Dener tao->reason = TAO_CONTINUE_ITERATING; 165a7e14dcfSSatish Balay while (1) { 166e1e80dc8SAlp Dener /* Call general purpose update function */ 167e1e80dc8SAlp Dener if (tao->ops->update) { 1689566063dSJacob Faibussowitsch PetscCall((*tao->ops->update)(tao, tao->niter, tao->user_update)); 169e1e80dc8SAlp Dener } 170d643b47cSToby Isaac ++tao->niter; 171a7e14dcfSSatish Balay shrink = 0; 1729566063dSJacob Faibussowitsch PetscCall(VecCopy(nm->simplex[nm->indices[0]],tao->solution)); 1739566063dSJacob Faibussowitsch PetscCall(TaoLogConvergenceHistory(tao, nm->f_values[nm->indices[0]], nm->f_values[nm->indices[nm->N]]-nm->f_values[nm->indices[0]], 0.0, tao->ksp_its)); 1749566063dSJacob Faibussowitsch PetscCall(TaoMonitor(tao,tao->niter, nm->f_values[nm->indices[0]], nm->f_values[nm->indices[nm->N]]-nm->f_values[nm->indices[0]], 0.0, 1.0)); 1759566063dSJacob Faibussowitsch PetscCall((*tao->ops->convergencetest)(tao,tao->cnvP)); 1763ecd9318SAlp Dener if (tao->reason != TAO_CONTINUE_ITERATING) break; 177a7e14dcfSSatish Balay 178a7e14dcfSSatish Balay /* x(mu) = (1 + mu)Xbar - mu*X_N+1 */ 1799566063dSJacob Faibussowitsch PetscCall(VecAXPBYPCZ(Xmur,1+nm->mu_r,-nm->mu_r,0,Xbar,nm->simplex[nm->indices[nm->N]])); 1809566063dSJacob Faibussowitsch PetscCall(TaoComputeObjective(tao,Xmur,&fr)); 181a7e14dcfSSatish Balay 182a7e14dcfSSatish Balay if (nm->f_values[nm->indices[0]] <= fr && fr < nm->f_values[nm->indices[nm->N-1]]) { 183a7e14dcfSSatish Balay /* reflect */ 184a7e14dcfSSatish Balay nm->nreflect++; 1859566063dSJacob Faibussowitsch PetscCall(PetscInfo(0,"Reflect\n")); 1869566063dSJacob Faibussowitsch PetscCall(NelderMeadReplace(nm,nm->indices[nm->N],Xmur,fr)); 18753506e15SBarry Smith } else if (fr < nm->f_values[nm->indices[0]]) { 188a7e14dcfSSatish Balay /* expand */ 189a7e14dcfSSatish Balay nm->nexpand++; 1909566063dSJacob Faibussowitsch PetscCall(PetscInfo(0,"Expand\n")); 1919566063dSJacob Faibussowitsch PetscCall(VecAXPBYPCZ(Xmue,1+nm->mu_e,-nm->mu_e,0,Xbar,nm->simplex[nm->indices[nm->N]])); 1929566063dSJacob Faibussowitsch PetscCall(TaoComputeObjective(tao,Xmue,&fe)); 193a7e14dcfSSatish Balay if (fe < fr) { 1949566063dSJacob Faibussowitsch PetscCall(NelderMeadReplace(nm,nm->indices[nm->N],Xmue,fe)); 195a7e14dcfSSatish Balay } else { 1969566063dSJacob Faibussowitsch PetscCall(NelderMeadReplace(nm,nm->indices[nm->N],Xmur,fr)); 197a7e14dcfSSatish Balay } 198a7e14dcfSSatish Balay } else if (nm->f_values[nm->indices[nm->N-1]] <= fr && fr < nm->f_values[nm->indices[nm->N]]) { 199a7e14dcfSSatish Balay /* outside contraction */ 200a7e14dcfSSatish Balay nm->noutcontract++; 2019566063dSJacob Faibussowitsch PetscCall(PetscInfo(0,"Outside Contraction\n")); 2029566063dSJacob Faibussowitsch PetscCall(VecAXPBYPCZ(Xmuc,1+nm->mu_oc,-nm->mu_oc,0,Xbar,nm->simplex[nm->indices[nm->N]])); 203a7e14dcfSSatish Balay 2049566063dSJacob Faibussowitsch PetscCall(TaoComputeObjective(tao,Xmuc,&fc)); 205a7e14dcfSSatish Balay if (fc <= fr) { 2069566063dSJacob Faibussowitsch PetscCall(NelderMeadReplace(nm,nm->indices[nm->N],Xmuc,fc)); 20753506e15SBarry Smith } else shrink=1; 208a7e14dcfSSatish Balay } else { 209a7e14dcfSSatish Balay /* inside contraction */ 210a7e14dcfSSatish Balay nm->nincontract++; 2119566063dSJacob Faibussowitsch PetscCall(PetscInfo(0,"Inside Contraction\n")); 2129566063dSJacob Faibussowitsch PetscCall(VecAXPBYPCZ(Xmuc,1+nm->mu_ic,-nm->mu_ic,0,Xbar,nm->simplex[nm->indices[nm->N]])); 2139566063dSJacob Faibussowitsch PetscCall(TaoComputeObjective(tao,Xmuc,&fc)); 214a7e14dcfSSatish Balay if (fc < nm->f_values[nm->indices[nm->N]]) { 2159566063dSJacob Faibussowitsch PetscCall(NelderMeadReplace(nm,nm->indices[nm->N],Xmuc,fc)); 21653506e15SBarry Smith } else shrink = 1; 217a7e14dcfSSatish Balay } 218a7e14dcfSSatish Balay 219a7e14dcfSSatish Balay if (shrink) { 220a7e14dcfSSatish Balay nm->nshrink++; 2219566063dSJacob Faibussowitsch PetscCall(PetscInfo(0,"Shrink\n")); 222a7e14dcfSSatish Balay 223a7e14dcfSSatish Balay for (i=1;i<nm->N+1;i++) { 2249566063dSJacob Faibussowitsch PetscCall(VecAXPBY(nm->simplex[nm->indices[i]],1.5,-0.5,nm->simplex[nm->indices[0]])); 2259566063dSJacob Faibussowitsch PetscCall(TaoComputeObjective(tao,nm->simplex[nm->indices[i]], &nm->f_values[nm->indices[i]])); 226a7e14dcfSSatish Balay } 2279566063dSJacob Faibussowitsch PetscCall(VecAXPBY(Xbar,1.5*nm->oneOverN,-0.5,nm->simplex[nm->indices[0]])); 228a7e14dcfSSatish Balay 229a7e14dcfSSatish Balay /* Add last vector's fraction of average */ 2309566063dSJacob Faibussowitsch PetscCall(VecAXPY(Xbar,nm->oneOverN,nm->simplex[nm->indices[nm->N]])); 2319566063dSJacob Faibussowitsch PetscCall(NelderMeadSort(nm)); 232a7e14dcfSSatish Balay /* Subtract new last vector from average */ 2339566063dSJacob Faibussowitsch PetscCall(VecAXPY(Xbar,-nm->oneOverN,nm->simplex[nm->indices[nm->N]])); 234a7e14dcfSSatish Balay } 235a7e14dcfSSatish Balay } 236a7e14dcfSSatish Balay PetscFunctionReturn(0); 237a7e14dcfSSatish Balay } 238a7e14dcfSSatish Balay 239a7e14dcfSSatish Balay /* ---------------------------------------------------------- */ 2401eb8069cSJason Sarich /*MC 2411eb8069cSJason Sarich TAONM - Nelder-Mead solver for derivative free, unconstrained minimization 2421eb8069cSJason Sarich 2431eb8069cSJason Sarich Options Database Keys: 2441eb8069cSJason Sarich + -tao_nm_lamda - initial step length 245a2b725a8SWilliam Gropp - -tao_nm_mu - expansion/contraction factor 2461eb8069cSJason Sarich 2471eb8069cSJason Sarich Level: beginner 2481eb8069cSJason Sarich M*/ 2491eb8069cSJason Sarich 250728e0ed0SBarry Smith PETSC_EXTERN PetscErrorCode TaoCreate_NM(Tao tao) 251a7e14dcfSSatish Balay { 252a7e14dcfSSatish Balay TAO_NelderMead *nm; 253a7e14dcfSSatish Balay 254a7e14dcfSSatish Balay PetscFunctionBegin; 2559566063dSJacob Faibussowitsch PetscCall(PetscNewLog(tao,&nm)); 256a7e14dcfSSatish Balay tao->data = (void*)nm; 257a7e14dcfSSatish Balay 258a7e14dcfSSatish Balay tao->ops->setup = TaoSetUp_NM; 259a7e14dcfSSatish Balay tao->ops->solve = TaoSolve_NM; 260a7e14dcfSSatish Balay tao->ops->view = TaoView_NM; 261a7e14dcfSSatish Balay tao->ops->setfromoptions = TaoSetFromOptions_NM; 262a7e14dcfSSatish Balay tao->ops->destroy = TaoDestroy_NM; 263a7e14dcfSSatish Balay 2646552cf8aSJason Sarich /* Override default settings (unless already changed) */ 2656552cf8aSJason Sarich if (!tao->max_it_changed) tao->max_it = 2000; 2666552cf8aSJason Sarich if (!tao->max_funcs_changed) tao->max_funcs = 4000; 267a7e14dcfSSatish Balay 26883c8fe1dSLisandro Dalcin nm->simplex = NULL; 269a7e14dcfSSatish Balay nm->lamda = 1; 270a7e14dcfSSatish Balay 271a7e14dcfSSatish Balay nm->mu_ic = -0.5; 272a7e14dcfSSatish Balay nm->mu_oc = 0.5; 273a7e14dcfSSatish Balay nm->mu_r = 1.0; 274a7e14dcfSSatish Balay nm->mu_e = 2.0; 275a7e14dcfSSatish Balay 276a7e14dcfSSatish Balay PetscFunctionReturn(0); 277a7e14dcfSSatish Balay } 278