Actual source code: neldermead.c
1: #include "neldermead.h"
4: int NelderMeadSort(TAO_NelderMead *nm);
5: int NelderMeadReplace(TAO_NelderMead *nm, int index, TaoVec *Xmu, double f);
6: /* ---------------------------------------------------------- */
9: int TaoSetUp_NelderMead(TAO_SOLVER tao, void *solver)
10: {
11: TAO_NelderMead *nm = (TAO_NelderMead *)solver;
12: int info;
13: int size;
14: TaoVec *X;
16: TaoFunctionBegin;
18:
19: info = TaoGetSolution(tao,&X); CHKERRQ(info);
20: info = X->GetDimension(&size); CHKERRQ(info);
21: nm->N = size;
22: nm->oneOverN = 1.0/size;
23: info = X->CloneVecs(nm->N+1,&nm->simplex);
24: nm->f_values = new double[nm->N+1];
25: nm->indices =new int[nm->N+1];
26: info = X->Clone(&nm->Xbar); CHKERRQ(info);
27: info = X->Clone(&nm->Xmur); CHKERRQ(info);
28: info = X->Clone(&nm->Xmue); CHKERRQ(info);
29: info = X->Clone(&nm->Xmuc); CHKERRQ(info);
30: info = TaoSetLagrangianGradientVector(tao,0);CHKERRQ(info);
31: info = TaoSetStepDirectionVector(tao,0);CHKERRQ(info);
33: TaoFunctionReturn(0);
34: }
36: /* ---------------------------------------------------------- */
39: int TaoSetDown_NelderMead(TAO_SOLVER tao, void *solver)
40: {
41: TAO_NelderMead *nm = (TAO_NelderMead*)solver;
42: int info;
43: int i;
44: TaoFunctionBegin;
45: for (i=0;i<nm->N+1;i++) {
46: TaoVecDestroy( nm->simplex[i]);
47: }
48: delete [] nm->simplex;
50: info = TaoVecDestroy(nm->Xmuc); CHKERRQ(info);
51: info = TaoVecDestroy(nm->Xmue); CHKERRQ(info);
52: info = TaoVecDestroy(nm->Xmur); CHKERRQ(info);
53: info = TaoVecDestroy(nm->Xbar); CHKERRQ(info);
54:
55: delete [] nm->indices;
56: delete [] nm->f_values;
57: TaoFunctionReturn(0);
58: }
60: /*------------------------------------------------------------*/
63: int TaoSetOptions_NelderMead(TAO_SOLVER tao, void *solver)
64: {
65:
66: TAO_NelderMead *nm = (TAO_NelderMead*)solver;
67: int info;
68:
69: TaoFunctionBegin;
70: info = TaoOptionsHead("Nelder-Mead options"); CHKERRQ(info);
71: info = TaoOptionDouble("-tao_nm_lamda","initial step length","",
72: nm->lamda,&nm->lamda,0); CHKERRQ(info);
73: info = TaoOptionDouble("-tao_nm_mu","mu","",nm->mu_oc,&nm->mu_oc,0); CHKERRQ(info);
74: nm->mu_ic = -nm->mu_oc;
75: nm->mu_r = nm->mu_oc*2.0;
76: nm->mu_e = nm->mu_oc*4.0;
78: info = TaoOptionsTail(); CHKERRQ(info);
79: TaoFunctionReturn(0);
80: }
82: /*------------------------------------------------------------*/
85: int TaoView_NelderMead(TAO_SOLVER tao, void *solver)
86: {
87: //int info;
89: TaoFunctionBegin;
90: TaoFunctionReturn(0);
91: }
93: /*------------------------------------------------------------*/
96: int TaoSolve_NelderMead(TAO_SOLVER tao, void *solver)
97: {
98: int info;
99: TAO_NelderMead *nm = (TAO_NelderMead*)solver;
100: TaoTerminateReason reason;
101: TaoVec *xx;
102: double *x;
103: int dim;
104: double step=0.0;
105: int iter=0,i;
106: TaoVec *Xmur=nm->Xmur, *Xmue=nm->Xmue, *Xmuc=nm->Xmuc, *Xbar=nm->Xbar;
107: double fr,fe,fc;
108: int shrink;
109:
110:
111: TaoFunctionBegin;
112: info = TaoGetSolution(tao,&xx); CHKERRQ(info);
113: for (i=0;i<nm->N+1;i++){
114: info = nm->simplex[i]->CopyFrom(xx); CHKERRQ(info);
115: if (i<nm->N) {
116: info = nm->simplex[i]->GetArray(&x,&dim); CHKERRQ(info);
117: x[i] += nm->lamda;
118: info = nm->simplex[i]->RestoreArray(&x,&dim); CHKERRQ(info);
119: }
120: info = TaoComputeMeritFunction(tao,nm->simplex[i],&nm->f_values[i]); CHKERRQ(info);
121: nm->indices[i] = i;
122: }
124: // Xbar = (Sum of all simplex vectors - worst vector)/N
125: info = NelderMeadSort(nm); CHKERRQ(info);
126: info = Xbar->SetToZero(); CHKERRQ(info);
127: for (i=0;i<nm->N;i++) {
128: info = Xbar->Axpy(1.0,nm->simplex[nm->indices[i]]);
129: }
130: info = Xbar->Scale(nm->oneOverN);
132: while (1) {
133: shrink = 0;
134: info = xx->CopyFrom(nm->simplex[nm->indices[0]]); CHKERRQ(info);
135: info = TaoMonitor(tao,iter++,nm->f_values[nm->indices[0]],nm->f_values[nm->indices[nm->N]]-nm->f_values[nm->indices[0]],0,step,&reason); CHKERRQ(info);
136: if (reason != TAO_CONTINUE_ITERATING) break;
138:
139:
140: //x(mu) = (1 + mu)Xbar - mu*X_N+1
141: info = Xmur->Waxpby(1+nm->mu_r,Xbar,-nm->mu_r,
142: nm->simplex[nm->indices[nm->N]]); CHKERRQ(info);
143: info = TaoComputeMeritFunction(tao,Xmur,&fr); CHKERRQ(info);
146: if (nm->f_values[nm->indices[0]] <= fr && fr < nm->f_values[nm->indices[nm->N-1]]) {
147: // reflect
148: info = PetscInfo(0,"Reflect\n"); CHKERRQ(info);
149: info = NelderMeadReplace(nm,nm->indices[nm->N],Xmur,fr); CHKERRQ(info);
150: }
152: else if (fr < nm->f_values[nm->indices[0]]) {
153: // expand
154: info = PetscInfo(0,"Expand\n"); CHKERRQ(info);
155: info = Xmue->Waxpby(1+nm->mu_e,Xbar,-nm->mu_e,
156: nm->simplex[nm->indices[nm->N]]); CHKERRQ(info);
157: info = TaoComputeMeritFunction(tao,Xmue,&fe); CHKERRQ(info);
158: if (fe < fr) {
159: info = NelderMeadReplace(nm,nm->indices[nm->N],Xmue,fe); CHKERRQ(info);
160: } else {
161: info = NelderMeadReplace(nm,nm->indices[nm->N],Xmur,fr); CHKERRQ(info);
162: }
164: } else if (nm->f_values[nm->indices[nm->N-1]] <= fr && fr < nm->f_values[nm->indices[nm->N]]) {
165: //outside contraction
166: info = PetscInfo(0,"Outside Contraction\n"); CHKERRQ(info);
167: info = Xmuc->Waxpby(1+nm->mu_oc,Xbar,-nm->mu_oc,
168: nm->simplex[nm->indices[nm->N]]); CHKERRQ(info);
169: info = TaoComputeMeritFunction(tao,Xmuc,&fc); CHKERRQ(info);
170: if (fc <= fr) {
171: info = NelderMeadReplace(nm,nm->indices[nm->N],Xmuc,fc); CHKERRQ(info);
172: } else
173: shrink=1;
174: } else {
175: //inside contraction
176: info = PetscInfo(0,"Inside Contraction\n"); CHKERRQ(info);
177: info = Xmuc->Waxpby(1+nm->mu_ic,Xbar,-nm->mu_ic,
178: nm->simplex[nm->indices[nm->N]]); CHKERRQ(info);
179: info = TaoComputeMeritFunction(tao,Xmuc,&fc); CHKERRQ(info);
180: if (fc < nm->f_values[nm->indices[nm->N]]) {
181: info = NelderMeadReplace(nm,nm->indices[nm->N],Xmuc,fc); CHKERRQ(info);
182: } else
183: shrink = 1;
184: }
186: if (shrink) {
187: info = PetscInfo(0,"Shrink\n"); CHKERRQ(info);
188: for (i=1;i<nm->N+1;i++) {
189: info = nm->simplex[nm->indices[i]]->Axpby(1.5,nm->simplex[nm->indices[0]],-.5); CHKERRQ(info);
190: info = TaoComputeMeritFunction(tao,nm->simplex[nm->indices[i]],
191: &nm->f_values[nm->indices[i]]); CHKERRQ(info);
192: }
194: info = Xbar->Axpby(1.5*nm->oneOverN,nm->simplex[nm->indices[0]],-0.5); CHKERRQ(info);
195: // Add last vector's fraction of average
196: info = nm->Xbar->Axpy(nm->oneOverN,
197: nm->simplex[nm->indices[nm->N]]); CHKERRQ(info);
198: info = NelderMeadSort(nm);
199: // Subtract new last vector from average
200: info = nm->Xbar->Axpy(-nm->oneOverN,
201: nm->simplex[nm->indices[nm->N]]); CHKERRQ(info);
202: }
204:
205: }
206: TaoFunctionReturn(0);
207: }
209: /* ---------------------------------------------------------- */
213: int TaoCreate_NelderMead(TAO_SOLVER tao)
214: {
215: TAO_NelderMead *nm;
216: int info;
218: TaoFunctionBegin;
219: info = TaoNew(TAO_NelderMead,&nm); CHKERRQ(info);
221: info = PetscLogObjectMemory(tao,sizeof(TAO_NelderMead)); CHKERRQ(info);
223: info = TaoSetTaoSolveRoutine(tao,TaoSolve_NelderMead,(void*)nm); CHKERRQ(info);
224: info = TaoSetTaoSetUpDownRoutines(tao,TaoSetUp_NelderMead,
225: TaoSetDown_NelderMead); CHKERRQ(info);
226: info = TaoSetTaoOptionsRoutine(tao,TaoSetOptions_NelderMead); CHKERRQ(info);
227: info = TaoSetTaoViewRoutine(tao, TaoView_NelderMead); CHKERRQ(info);
228: info = TaoSetMaximumIterates(tao,2000); CHKERRQ(info);
229: info = TaoSetMaximumFunctionEvaluations(tao,4000); CHKERRQ(info);
230: info = TaoSetTolerances(tao,1e-8,1e-8,0,0); CHKERRQ(info);
233: nm->simplex = 0;
234: nm->lamda = 1;
236: nm->mu_ic = -0.5;
237: nm->mu_oc = 0.5;
238: nm->mu_r = 1.0;
239: nm->mu_e = 2.0;
241: TaoFunctionReturn(0);
242: }
244:
246: /*------------------------------------------------------------*/
249: int NelderMeadSort(TAO_NelderMead *nm) {
250: double *values = nm->f_values;
251: int *indices = nm->indices;
252: int dim = nm->N+1;
254: int i,j,index;
255: double val;
256: TaoFunctionBegin;
257: for (i=1;i<dim;i++) {
258: index = indices[i];
259: val = values[index];
260: for (j=i-1; j>=0 && values[indices[j]] > val; j--) {
261: indices[j+1] = indices[j];
262: }
263: indices[j+1] = index;
264: }
265: TaoFunctionReturn(0);
266: }
269: /*------------------------------------------------------------*/
272: int NelderMeadReplace(TAO_NelderMead *nm, int index, TaoVec *Xmu, double f)
273: {
274: int info;
275: TaoFunctionBegin;
276: // Add new vector's fraction of average
277: info = nm->Xbar->Axpy(nm->oneOverN,Xmu); CHKERRQ(info);
278: info = nm->simplex[index]->CopyFrom(Xmu); CHKERRQ(info);
279: nm->f_values[index] = f;
281: info = NelderMeadSort(nm);
282: // Subtract last vector from average
283: info = nm->Xbar->Axpy(-nm->oneOverN,
284: nm->simplex[nm->indices[nm->N]]); CHKERRQ(info);
285: TaoFunctionReturn(0);
286: }