| // Copyright ©2016 The gonum Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package optimize |
| |
| import ( |
| "math" |
| "sync" |
| |
| "gonum.org/v1/gonum/stat/distmv" |
| ) |
| |
| // GuessAndCheck is a global optimizer that evaluates the function at random |
| // locations. Not a good optimizer, but useful for comparison and debugging. |
| type GuessAndCheck struct { |
| Rander distmv.Rander |
| |
| eval []bool |
| |
| mux *sync.Mutex |
| bestF float64 |
| bestX []float64 |
| } |
| |
| func (g *GuessAndCheck) Needs() struct{ Gradient, Hessian bool } { |
| return struct{ Gradient, Hessian bool }{false, false} |
| } |
| |
| func (g *GuessAndCheck) Done() { |
| // No cleanup needed |
| } |
| |
| func (g *GuessAndCheck) InitGlobal(dim, tasks int) int { |
| g.eval = make([]bool, tasks) |
| g.bestF = math.Inf(1) |
| g.bestX = resize(g.bestX, dim) |
| g.mux = &sync.Mutex{} |
| return tasks |
| } |
| |
| func (g *GuessAndCheck) IterateGlobal(task int, loc *Location) (Operation, error) { |
| // Task is true if it contains a new function evaluation. |
| if g.eval[task] { |
| g.eval[task] = false |
| g.mux.Lock() |
| if loc.F < g.bestF { |
| g.bestF = loc.F |
| copy(g.bestX, loc.X) |
| } else { |
| loc.F = g.bestF |
| copy(loc.X, g.bestX) |
| } |
| g.mux.Unlock() |
| return MajorIteration, nil |
| } |
| g.eval[task] = true |
| g.Rander.Rand(loc.X) |
| return FuncEvaluation, nil |
| } |