1
- // Copyright ©2014 The gonum Authors. All rights reserved.
1
+ // Copyright ©2015 The gonum Authors. All rights reserved.
2
2
// Use of this source code is governed by a BSD-style
3
3
// license that can be found in the LICENSE file.
4
4
@@ -49,7 +49,10 @@ func (n nmVertexSorter) Swap(i, j int) {
49
49
//
50
50
// If an initial simplex is provided, it is used and initLoc is ignored. If
51
51
// InitialVertices and InitialValues are both nil, an initial simplex will be
52
- // generated automatically. If the simplex update parameters (Reflection, etc.)
52
+ // generated automatically using the initial location as one vertex, and each
53
+ // additional vertex as SimplexSize away in one dimension.
54
+ //
55
+ // If the simplex update parameters (Reflection, etc.)
53
56
// are zero, they will be set automatically based on the dimension according to
54
57
// the recommendations in
55
58
//
@@ -61,6 +64,12 @@ type NelderMead struct {
61
64
Expansion float64 // Expansion parameter (>1)
62
65
Contraction float64 // Contraction parameter (>0, <1)
63
66
Shrink float64 // Shrink parameter (>0, <1)
67
+ SimplexSize float64 // size of auto-constructed initial simplex
68
+
69
+ reflection float64
70
+ expansion float64
71
+ contraction float64
72
+ shrink float64
64
73
65
74
vertices [][]float64 // location of the vertices sorted in ascending f
66
75
values []float64 // function values at the vertices sorted in ascending f
@@ -85,19 +94,27 @@ func (n *NelderMead) Init(loc *Location, f *FunctionInfo, xNext []float64) (Eval
85
94
n .centroid = resize (n .centroid , dim )
86
95
n .reflectedPoint = resize (n .reflectedPoint , dim )
87
96
97
+ if n .SimplexSize == 0 {
98
+ n .SimplexSize = 0.05
99
+ }
100
+
88
101
// Default parameter choices are chosen in a dimension-dependent way
89
102
// from http://www.webpages.uidaho.edu/~fuchang/res/ANMS.pdf
90
- if n .Reflection == 0 {
91
- n .Reflection = 1
103
+ n .reflection = n .Reflection
104
+ if n .reflection == 0 {
105
+ n .reflection = 1
92
106
}
93
- if n .Expansion == 0 {
94
- n .Expansion = 1 + 2.0 / float64 (dim )
107
+ n .expansion = n .Expansion
108
+ if n .expansion == 0 {
109
+ n .expansion = 1 + 2 / float64 (dim )
95
110
}
96
- if n .Contraction == 0 {
97
- n .Contraction = 0.75 - 1.0 / (2.0 * float64 (dim ))
111
+ n .contraction = n .Contraction
112
+ if n .contraction == 0 {
113
+ n .contraction = 0.75 - 1 / (2 * float64 (dim ))
98
114
}
99
- if n .Shrink == 0 {
100
- n .Shrink = 1 - 1.0 / float64 (dim )
115
+ n .shrink = n .Shrink
116
+ if n .shrink == 0 {
117
+ n .shrink = 1 - 1 / float64 (dim )
101
118
}
102
119
103
120
if n .InitialVertices != nil {
@@ -126,8 +143,7 @@ func (n *NelderMead) Init(loc *Location, f *FunctionInfo, xNext []float64) (Eval
126
143
n .values [dim ] = loc .F
127
144
n .fillIdx = 0
128
145
copy (xNext , loc .X )
129
- xNext [0 ] += 1
130
- copy (n .vertices [0 ], xNext )
146
+ xNext [0 ] += n .SimplexSize
131
147
n .lastIter = nmInitialize
132
148
return FuncEvaluation , InitIteration , nil
133
149
}
@@ -155,17 +171,16 @@ func (n *NelderMead) Iterate(loc *Location, xNext []float64) (EvaluationType, It
155
171
switch n .lastIter {
156
172
case nmInitialize :
157
173
n .values [n .fillIdx ] = loc .F
174
+ copy (n .vertices [n .fillIdx ], loc .X )
158
175
n .fillIdx ++
159
176
if n .fillIdx == dim {
160
177
// Successfully finished building initial simplex.
161
178
sort .Sort (nmVertexSorter {n .vertices , n .values })
162
179
computeCentroid (n .vertices , n .centroid )
163
180
return n .returnNext (nmReflected , xNext )
164
181
}
165
- copy (xNext , loc .X )
166
- xNext [n .fillIdx - 1 ] -= 1
167
- xNext [n .fillIdx ] += 1
168
- copy (n .vertices [n .fillIdx ], xNext )
182
+ copy (xNext , n .vertices [dim ])
183
+ xNext [n .fillIdx ] += n .SimplexSize
169
184
return FuncEvaluation , InitIteration , nil
170
185
case nmReflected :
171
186
n .reflectedValue = loc .F
@@ -228,13 +243,13 @@ func (n *NelderMead) returnNext(iter nmIterType, xNext []float64) (EvaluationTyp
228
243
var scale float64
229
244
switch iter {
230
245
case nmReflected :
231
- scale = n .Reflection
246
+ scale = n .reflection
232
247
case nmExpanded :
233
- scale = n .Reflection * n .Expansion
248
+ scale = n .reflection * n .expansion
234
249
case nmContractedOutside :
235
- scale = n .Reflection * n .Contraction
250
+ scale = n .reflection * n .contraction
236
251
case nmContractedInside :
237
- scale = - n .Contraction
252
+ scale = - n .contraction
238
253
}
239
254
floats .SubTo (xNext , n .centroid , n .vertices [dim ])
240
255
floats .Scale (scale , xNext )
@@ -248,7 +263,7 @@ func (n *NelderMead) returnNext(iter nmIterType, xNext []float64) (EvaluationTyp
248
263
case nmShrink :
249
264
// x_shrink = x_best + delta * (x_i + x_best)
250
265
floats .SubTo (xNext , n .vertices [n .fillIdx ], n .vertices [0 ])
251
- floats .Scale (n .Shrink , xNext )
266
+ floats .Scale (n .shrink , xNext )
252
267
floats .Add (xNext , n .vertices [0 ])
253
268
return FuncEvaluation , SubIteration , nil
254
269
default :
@@ -280,3 +295,13 @@ func (n *NelderMead) replaceWorst(x []float64, f float64) {
280
295
floats .AddScaled (n .centroid , - 1 / float64 (dim ), n .vertices [dim ])
281
296
floats .AddScaled (n .centroid , 1 / float64 (dim ), x )
282
297
}
298
+
299
+ func (* NelderMead ) Needs () struct {
300
+ Gradient bool
301
+ Hessian bool
302
+ } {
303
+ return struct {
304
+ Gradient bool
305
+ Hessian bool
306
+ }{false , false }
307
+ }
0 commit comments