gonum.org/v1/gonum@v0.14.0/optimize/functionconvergence.go (about) 1 // Copyright ©2015 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 11 // Converger returns the convergence of the optimization based on 12 // locations found during optimization. Converger must not modify the value of 13 // the provided Location in any of the methods. 14 type Converger interface { 15 Init(dim int) 16 Converged(loc *Location) Status 17 } 18 19 var ( 20 _ Converger = NeverTerminate{} 21 _ Converger = (*FunctionConverge)(nil) 22 ) 23 24 // NeverTerminate implements Converger, always reporting NotTerminated. 25 type NeverTerminate struct{} 26 27 func (NeverTerminate) Init(dim int) {} 28 29 func (NeverTerminate) Converged(loc *Location) Status { 30 return NotTerminated 31 } 32 33 // FunctionConverge tests for insufficient improvement in the optimum value 34 // over the last iterations. A FunctionConvergence status is returned if 35 // there is no significant decrease for FunctionConverge.Iterations. A 36 // significant decrease is considered if 37 // 38 // f < f_best 39 // 40 // and 41 // 42 // f_best - f > FunctionConverge.Relative * maxabs(f, f_best) + FunctionConverge.Absolute 43 // 44 // If the decrease is significant, then the iteration counter is reset and 45 // f_best is updated. 46 // 47 // If FunctionConverge.Iterations == 0, it has no effect. 48 type FunctionConverge struct { 49 Absolute float64 50 Relative float64 51 Iterations int 52 53 first bool 54 best float64 55 iter int 56 } 57 58 func (fc *FunctionConverge) Init(dim int) { 59 fc.first = true 60 fc.best = 0 61 fc.iter = 0 62 } 63 64 func (fc *FunctionConverge) Converged(l *Location) Status { 65 f := l.F 66 if fc.first { 67 fc.best = f 68 fc.first = false 69 return NotTerminated 70 } 71 if fc.Iterations == 0 { 72 return NotTerminated 73 } 74 maxAbs := math.Max(math.Abs(f), math.Abs(fc.best)) 75 if f < fc.best && fc.best-f > fc.Relative*maxAbs+fc.Absolute { 76 fc.best = f 77 fc.iter = 0 78 return NotTerminated 79 } 80 fc.iter++ 81 if fc.iter < fc.Iterations { 82 return NotTerminated 83 } 84 return FunctionConvergence 85 }