gonum.org/v1/gonum@v0.14.0/optimize/guessandcheck.go (about) 1 // Copyright ©2016 The Gonum Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package optimize 6 7 import ( 8 "math" 9 10 "gonum.org/v1/gonum/stat/distmv" 11 ) 12 13 var _ Method = (*GuessAndCheck)(nil) 14 15 // GuessAndCheck is a global optimizer that evaluates the function at random 16 // locations. Not a good optimizer, but useful for comparison and debugging. 17 type GuessAndCheck struct { 18 Rander distmv.Rander 19 20 bestF float64 21 bestX []float64 22 } 23 24 func (*GuessAndCheck) Uses(has Available) (uses Available, err error) { 25 return has.function() 26 } 27 28 func (g *GuessAndCheck) Init(dim, tasks int) int { 29 if dim <= 0 { 30 panic(nonpositiveDimension) 31 } 32 if tasks < 0 { 33 panic(negativeTasks) 34 } 35 g.bestF = math.Inf(1) 36 g.bestX = resize(g.bestX, dim) 37 return tasks 38 } 39 40 func (g *GuessAndCheck) sendNewLoc(operation chan<- Task, task Task) { 41 g.Rander.Rand(task.X) 42 task.Op = FuncEvaluation 43 operation <- task 44 } 45 46 func (g *GuessAndCheck) updateMajor(operation chan<- Task, task Task) { 47 // Update the best value seen so far, and send a MajorIteration. 48 if task.F < g.bestF { 49 g.bestF = task.F 50 copy(g.bestX, task.X) 51 } else { 52 task.F = g.bestF 53 copy(task.X, g.bestX) 54 } 55 task.Op = MajorIteration 56 operation <- task 57 } 58 59 func (g *GuessAndCheck) Run(operation chan<- Task, result <-chan Task, tasks []Task) { 60 // Send initial tasks to evaluate 61 for _, task := range tasks { 62 g.sendNewLoc(operation, task) 63 } 64 65 // Read from the channel until PostIteration is sent. 66 Loop: 67 for { 68 task := <-result 69 switch task.Op { 70 default: 71 panic("unknown operation") 72 case PostIteration: 73 break Loop 74 case MajorIteration: 75 g.sendNewLoc(operation, task) 76 case FuncEvaluation: 77 g.updateMajor(operation, task) 78 } 79 } 80 81 // PostIteration was sent. Update the best new values. 82 for task := range result { 83 switch task.Op { 84 default: 85 panic("unknown operation") 86 case MajorIteration: 87 case FuncEvaluation: 88 g.updateMajor(operation, task) 89 } 90 } 91 close(operation) 92 }