| // Copyright ©2015 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" |
| ) |
| |
| // Converger returns the convergence of the optimization based on |
| // locations found during optimization. Converger must not modify the value of |
| // the provided Location in any of the methods. |
| type Converger interface { |
| Init(dim int) |
| Converged(loc *Location) Status |
| } |
| |
| var ( |
| _ Converger = NeverTerminate{} |
| _ Converger = (*FunctionConverge)(nil) |
| ) |
| |
| // NeverTerminate implements Converger, always reporting NotTerminated. |
| type NeverTerminate struct{} |
| |
| func (NeverTerminate) Init(dim int) {} |
| |
| func (NeverTerminate) Converged(loc *Location) Status { |
| return NotTerminated |
| } |
| |
| // FunctionConverge tests for insufficient improvement in the optimum value |
| // over the last iterations. A FunctionConvergence status is returned if |
| // there is no significant decrease for FunctionConverge.Iterations. A |
| // significant decrease is considered if |
| // |
| // f < f_best |
| // |
| // and |
| // |
| // f_best - f > FunctionConverge.Relative * maxabs(f, f_best) + FunctionConverge.Absolute |
| // |
| // If the decrease is significant, then the iteration counter is reset and |
| // f_best is updated. |
| // |
| // If FunctionConverge.Iterations == 0, it has no effect. |
| type FunctionConverge struct { |
| Absolute float64 |
| Relative float64 |
| Iterations int |
| |
| first bool |
| best float64 |
| iter int |
| } |
| |
| func (fc *FunctionConverge) Init(dim int) { |
| fc.first = true |
| fc.best = 0 |
| fc.iter = 0 |
| } |
| |
| func (fc *FunctionConverge) Converged(l *Location) Status { |
| f := l.F |
| if fc.first { |
| fc.best = f |
| fc.first = false |
| return NotTerminated |
| } |
| if fc.Iterations == 0 { |
| return NotTerminated |
| } |
| maxAbs := math.Max(math.Abs(f), math.Abs(fc.best)) |
| if f < fc.best && fc.best-f > fc.Relative*maxAbs+fc.Absolute { |
| fc.best = f |
| fc.iter = 0 |
| return NotTerminated |
| } |
| fc.iter++ |
| if fc.iter < fc.Iterations { |
| return NotTerminated |
| } |
| return FunctionConvergence |
| } |