@@ -49,22 +49,25 @@ import (
49
49
// function evaluations. If you would like to put limits on this, for example
50
50
// maximum runtime or maximum function evaluations, please modify the Settings
51
51
// input struct.
52
- func Local (f Function , initX []float64 , settings * Settings , method Method ) (* Result , error ) {
52
+ func Local (p Problem , initX []float64 , settings * Settings , method Method ) (* Result , error ) {
53
+ if p .Func == nil {
54
+ panic ("optimize: objective function is undefined" )
55
+ }
53
56
if len (initX ) == 0 {
54
57
panic ("optimize: initial X has zero length" )
55
58
}
56
59
57
60
startTime := time .Now ()
58
- funcInfo := newFunctionInfo ( f )
61
+
59
62
if method == nil {
60
- method = getDefaultMethod (funcInfo )
63
+ method = getDefaultMethod (& p )
61
64
}
62
- if err := funcInfo .satisfies (method ); err != nil {
65
+ if err := p .satisfies (method ); err != nil {
63
66
return nil , err
64
67
}
65
68
66
- if funcInfo . IsStatuser {
67
- _ , err := funcInfo . statuser .Status ()
69
+ if p . Status != nil {
70
+ _ , err := p .Status ()
68
71
if err != nil {
69
72
return nil , err
70
73
}
@@ -84,7 +87,7 @@ func Local(f Function, initX []float64, settings *Settings, method Method) (*Res
84
87
}
85
88
86
89
stats := & Stats {}
87
- optLoc , evalType , err := getStartingLocation (funcInfo , method , initX , stats , settings )
90
+ optLoc , evalType , err := getStartingLocation (& p , method , initX , stats , settings )
88
91
if err != nil {
89
92
return nil , err
90
93
}
@@ -106,7 +109,7 @@ func Local(f Function, initX []float64, settings *Settings, method Method) (*Res
106
109
// The starting location is not good enough, we need to perform a
107
110
// minimization. The optimal location will be stored in-place in
108
111
// optLoc.
109
- status , err = minimize (settings , method , funcInfo , stats , optLoc , startTime )
112
+ status , err = minimize (settings , method , & p , stats , optLoc , startTime )
110
113
}
111
114
112
115
if settings .Recorder != nil && err == nil {
@@ -121,30 +124,30 @@ func Local(f Function, initX []float64, settings *Settings, method Method) (*Res
121
124
}, err
122
125
}
123
126
124
- func minimize (settings * Settings , method Method , funcInfo * functionInfo , stats * Stats , optLoc * Location , startTime time.Time ) (status Status , err error ) {
127
+ func minimize (settings * Settings , method Method , p * Problem , stats * Stats , optLoc * Location , startTime time.Time ) (status Status , err error ) {
125
128
loc := & Location {}
126
129
copyLocation (loc , optLoc )
127
130
xNext := make ([]float64 , len (loc .X ))
128
131
129
132
methodStatus , methodIsStatuser := method .(Statuser )
130
133
131
- evalType , iterType , err := method .Init (loc , & funcInfo . FunctionInfo , xNext )
134
+ evalType , iterType , err := method .Init (loc , newProblemInfo ( p ) , xNext )
132
135
if err != nil {
133
136
return Failure , err
134
137
}
135
138
136
139
for {
137
- if funcInfo . IsStatuser {
140
+ if p . Status != nil {
138
141
// Check the function status before evaluating.
139
- status , err = funcInfo . statuser .Status ()
142
+ status , err = p .Status ()
140
143
if err != nil || status != NotTerminated {
141
144
return
142
145
}
143
146
}
144
147
145
148
// Perform evalType evaluation of the function at xNext and store the
146
149
// result in location.
147
- evaluate (funcInfo , evalType , xNext , loc , stats )
150
+ evaluate (p , evalType , xNext , loc , stats )
148
151
// Update the stats and optLoc.
149
152
update (loc , optLoc , stats , iterType , startTime )
150
153
// Get the convergence status before recording the new location.
@@ -198,15 +201,15 @@ func copyLocation(dst, src *Location) {
198
201
}
199
202
}
200
203
201
- func getDefaultMethod (funcInfo * functionInfo ) Method {
202
- if funcInfo . IsGradient {
204
+ func getDefaultMethod (p * Problem ) Method {
205
+ if p . Grad != nil {
203
206
return & BFGS {}
204
207
}
205
208
return & NelderMead {}
206
209
}
207
210
208
211
// getStartingLocation allocates and initializes the starting location for the minimization.
209
- func getStartingLocation (funcInfo * functionInfo , method Method , initX []float64 , stats * Stats , settings * Settings ) (* Location , EvaluationType , error ) {
212
+ func getStartingLocation (p * Problem , method Method , initX []float64 , stats * Stats , settings * Settings ) (* Location , EvaluationType , error ) {
210
213
dim := len (initX )
211
214
loc := & Location {
212
215
X : make ([]float64 , dim ),
@@ -250,7 +253,7 @@ func getStartingLocation(funcInfo *functionInfo, method Method, initX []float64,
250
253
if loc .Hessian != nil {
251
254
evalType |= HessEvaluation
252
255
}
253
- evaluate (funcInfo , evalType , loc .X , loc , stats )
256
+ evaluate (p , evalType , loc .X , loc , stats )
254
257
}
255
258
256
259
if math .IsNaN (loc .F ) {
@@ -345,11 +348,11 @@ func invalidate(loc *Location) {
345
348
}
346
349
}
347
350
348
- // evaluate evaluates the function given by f at xNext, stores the answer into
351
+ // evaluate evaluates the problem given by p at xNext, stores the answer into
349
352
// loc and updates stats. If loc.X is not equal to xNext, then unused fields of
350
353
// loc are set to NaN.
351
354
// evaluate panics if the function does not support the requested evalType.
352
- func evaluate (f * functionInfo , evalType EvaluationType , xNext []float64 , loc * Location , stats * Stats ) {
355
+ func evaluate (p * Problem , evalType EvaluationType , xNext []float64 , loc * Location , stats * Stats ) {
353
356
if ! floats .Equal (loc .X , xNext ) {
354
357
if evalType == NoEvaluation {
355
358
// Optimizers should not request NoEvaluation at a new location.
@@ -362,17 +365,17 @@ func evaluate(f *functionInfo, evalType EvaluationType, xNext []float64, loc *Lo
362
365
363
366
toEval := evalType
364
367
if evalType & FuncEvaluation != 0 {
365
- loc .F = f . function .Func (loc .X )
368
+ loc .F = p .Func (loc .X )
366
369
stats .FuncEvaluations ++
367
370
toEval &= ^ FuncEvaluation
368
371
}
369
372
if evalType & GradEvaluation != 0 {
370
- f . gradient .Grad (loc .X , loc .Gradient )
373
+ p .Grad (loc .X , loc .Gradient )
371
374
stats .GradEvaluations ++
372
375
toEval &= ^ GradEvaluation
373
376
}
374
377
if evalType & HessEvaluation != 0 {
375
- f . hessian .Hess (loc .X , loc .Hessian )
378
+ p .Hess (loc .X , loc .Hessian )
376
379
stats .HessEvaluations ++
377
380
toEval &= ^ HessEvaluation
378
381
}
0 commit comments