fixed dependencies
This commit is contained in:
218
vendor/gonum.org/v1/gonum/optimize/linesearch.go
generated
vendored
Normal file
218
vendor/gonum.org/v1/gonum/optimize/linesearch.go
generated
vendored
Normal file
@@ -0,0 +1,218 @@
|
||||
// Copyright ©2014 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"
|
||||
|
||||
"gonum.org/v1/gonum/floats"
|
||||
)
|
||||
|
||||
// LinesearchMethod represents an abstract optimization method in which a
|
||||
// function is optimized through successive line search optimizations.
|
||||
type LinesearchMethod struct {
|
||||
// NextDirectioner specifies the search direction of each linesearch.
|
||||
NextDirectioner NextDirectioner
|
||||
// Linesearcher performs a linesearch along the search direction.
|
||||
Linesearcher Linesearcher
|
||||
|
||||
x []float64 // Starting point for the current iteration.
|
||||
dir []float64 // Search direction for the current iteration.
|
||||
|
||||
first bool // Indicator of the first iteration.
|
||||
nextMajor bool // Indicates that MajorIteration must be commanded at the next call to Iterate.
|
||||
eval Operation // Indicator of valid fields in Location.
|
||||
|
||||
lastStep float64 // Step taken from x in the previous call to Iterate.
|
||||
lastOp Operation // Operation returned from the previous call to Iterate.
|
||||
}
|
||||
|
||||
func (ls *LinesearchMethod) Init(loc *Location) (Operation, error) {
|
||||
if loc.Gradient == nil {
|
||||
panic("linesearch: gradient is nil")
|
||||
}
|
||||
|
||||
dim := len(loc.X)
|
||||
ls.x = resize(ls.x, dim)
|
||||
ls.dir = resize(ls.dir, dim)
|
||||
|
||||
ls.first = true
|
||||
ls.nextMajor = false
|
||||
|
||||
// Indicate that all fields of loc are valid.
|
||||
ls.eval = FuncEvaluation | GradEvaluation
|
||||
if loc.Hessian != nil {
|
||||
ls.eval |= HessEvaluation
|
||||
}
|
||||
|
||||
ls.lastStep = math.NaN()
|
||||
ls.lastOp = NoOperation
|
||||
|
||||
return ls.initNextLinesearch(loc)
|
||||
}
|
||||
|
||||
func (ls *LinesearchMethod) Iterate(loc *Location) (Operation, error) {
|
||||
switch ls.lastOp {
|
||||
case NoOperation:
|
||||
// TODO(vladimir-ch): Either Init has not been called, or the caller is
|
||||
// trying to resume the optimization run after Iterate previously
|
||||
// returned with an error. Decide what is the proper thing to do. See also #125.
|
||||
|
||||
case MajorIteration:
|
||||
// The previous updated location did not converge the full
|
||||
// optimization. Initialize a new Linesearch.
|
||||
return ls.initNextLinesearch(loc)
|
||||
|
||||
default:
|
||||
// Update the indicator of valid fields of loc.
|
||||
ls.eval |= ls.lastOp
|
||||
|
||||
if ls.nextMajor {
|
||||
ls.nextMajor = false
|
||||
|
||||
// Linesearcher previously finished, and the invalid fields of loc
|
||||
// have now been validated. Announce MajorIteration.
|
||||
ls.lastOp = MajorIteration
|
||||
return ls.lastOp, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Continue the linesearch.
|
||||
|
||||
f := math.NaN()
|
||||
if ls.eval&FuncEvaluation != 0 {
|
||||
f = loc.F
|
||||
}
|
||||
projGrad := math.NaN()
|
||||
if ls.eval&GradEvaluation != 0 {
|
||||
projGrad = floats.Dot(loc.Gradient, ls.dir)
|
||||
}
|
||||
op, step, err := ls.Linesearcher.Iterate(f, projGrad)
|
||||
if err != nil {
|
||||
return ls.error(err)
|
||||
}
|
||||
|
||||
switch op {
|
||||
case MajorIteration:
|
||||
// Linesearch has been finished.
|
||||
|
||||
ls.lastOp = complementEval(loc, ls.eval)
|
||||
if ls.lastOp == NoOperation {
|
||||
// loc is complete, MajorIteration can be declared directly.
|
||||
ls.lastOp = MajorIteration
|
||||
} else {
|
||||
// Declare MajorIteration on the next call to Iterate.
|
||||
ls.nextMajor = true
|
||||
}
|
||||
|
||||
case FuncEvaluation, GradEvaluation, FuncEvaluation | GradEvaluation:
|
||||
if step != ls.lastStep {
|
||||
// We are moving to a new location, and not, say, evaluating extra
|
||||
// information at the current location.
|
||||
|
||||
// Compute the next evaluation point and store it in loc.X.
|
||||
floats.AddScaledTo(loc.X, ls.x, step, ls.dir)
|
||||
if floats.Equal(ls.x, loc.X) {
|
||||
// Step size has become so small that the next evaluation point is
|
||||
// indistinguishable from the starting point for the current
|
||||
// iteration due to rounding errors.
|
||||
return ls.error(ErrNoProgress)
|
||||
}
|
||||
ls.lastStep = step
|
||||
ls.eval = NoOperation // Indicate all invalid fields of loc.
|
||||
}
|
||||
ls.lastOp = op
|
||||
|
||||
default:
|
||||
panic("linesearch: Linesearcher returned invalid operation")
|
||||
}
|
||||
|
||||
return ls.lastOp, nil
|
||||
}
|
||||
|
||||
func (ls *LinesearchMethod) error(err error) (Operation, error) {
|
||||
ls.lastOp = NoOperation
|
||||
return ls.lastOp, err
|
||||
}
|
||||
|
||||
// initNextLinesearch initializes the next linesearch using the previous
|
||||
// complete location stored in loc. It fills loc.X and returns an evaluation
|
||||
// to be performed at loc.X.
|
||||
func (ls *LinesearchMethod) initNextLinesearch(loc *Location) (Operation, error) {
|
||||
copy(ls.x, loc.X)
|
||||
|
||||
var step float64
|
||||
if ls.first {
|
||||
ls.first = false
|
||||
step = ls.NextDirectioner.InitDirection(loc, ls.dir)
|
||||
} else {
|
||||
step = ls.NextDirectioner.NextDirection(loc, ls.dir)
|
||||
}
|
||||
|
||||
projGrad := floats.Dot(loc.Gradient, ls.dir)
|
||||
if projGrad >= 0 {
|
||||
return ls.error(ErrNonDescentDirection)
|
||||
}
|
||||
|
||||
op := ls.Linesearcher.Init(loc.F, projGrad, step)
|
||||
switch op {
|
||||
case FuncEvaluation, GradEvaluation, FuncEvaluation | GradEvaluation:
|
||||
default:
|
||||
panic("linesearch: Linesearcher returned invalid operation")
|
||||
}
|
||||
|
||||
floats.AddScaledTo(loc.X, ls.x, step, ls.dir)
|
||||
if floats.Equal(ls.x, loc.X) {
|
||||
// Step size is so small that the next evaluation point is
|
||||
// indistinguishable from the starting point for the current iteration
|
||||
// due to rounding errors.
|
||||
return ls.error(ErrNoProgress)
|
||||
}
|
||||
|
||||
ls.lastStep = step
|
||||
ls.eval = NoOperation // Invalidate all fields of loc.
|
||||
|
||||
ls.lastOp = op
|
||||
return ls.lastOp, nil
|
||||
}
|
||||
|
||||
// ArmijoConditionMet returns true if the Armijo condition (aka sufficient
|
||||
// decrease) has been met. Under normal conditions, the following should be
|
||||
// true, though this is not enforced:
|
||||
// - initGrad < 0
|
||||
// - step > 0
|
||||
// - 0 < decrease < 1
|
||||
func ArmijoConditionMet(currObj, initObj, initGrad, step, decrease float64) bool {
|
||||
return currObj <= initObj+decrease*step*initGrad
|
||||
}
|
||||
|
||||
// StrongWolfeConditionsMet returns true if the strong Wolfe conditions have been met.
|
||||
// The strong Wolfe conditions ensure sufficient decrease in the function
|
||||
// value, and sufficient decrease in the magnitude of the projected gradient.
|
||||
// Under normal conditions, the following should be true, though this is not
|
||||
// enforced:
|
||||
// - initGrad < 0
|
||||
// - step > 0
|
||||
// - 0 <= decrease < curvature < 1
|
||||
func StrongWolfeConditionsMet(currObj, currGrad, initObj, initGrad, step, decrease, curvature float64) bool {
|
||||
if currObj > initObj+decrease*step*initGrad {
|
||||
return false
|
||||
}
|
||||
return math.Abs(currGrad) < curvature*math.Abs(initGrad)
|
||||
}
|
||||
|
||||
// WeakWolfeConditionsMet returns true if the weak Wolfe conditions have been met.
|
||||
// The weak Wolfe conditions ensure sufficient decrease in the function value,
|
||||
// and sufficient decrease in the value of the projected gradient. Under normal
|
||||
// conditions, the following should be true, though this is not enforced:
|
||||
// - initGrad < 0
|
||||
// - step > 0
|
||||
// - 0 <= decrease < curvature< 1
|
||||
func WeakWolfeConditionsMet(currObj, currGrad, initObj, initGrad, step, decrease, curvature float64) bool {
|
||||
if currObj > initObj+decrease*step*initGrad {
|
||||
return false
|
||||
}
|
||||
return currGrad >= curvature*initGrad
|
||||
}
|
||||
Reference in New Issue
Block a user