fixed dependencies
This commit is contained in:
146
vendor/gonum.org/v1/gonum/optimize/bisection.go
generated
vendored
Normal file
146
vendor/gonum.org/v1/gonum/optimize/bisection.go
generated
vendored
Normal file
@@ -0,0 +1,146 @@
|
||||
// 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"
|
||||
|
||||
const defaultBisectionCurvature = 0.9
|
||||
|
||||
var _ Linesearcher = (*Bisection)(nil)
|
||||
|
||||
// Bisection is a Linesearcher that uses a bisection to find a point that
|
||||
// satisfies the strong Wolfe conditions with the given curvature factor and
|
||||
// a decrease factor of zero.
|
||||
type Bisection struct {
|
||||
// CurvatureFactor is the constant factor in the curvature condition.
|
||||
// Smaller values result in a more exact line search.
|
||||
// A set value must be in the interval (0, 1), otherwise Init will panic.
|
||||
// If it is zero, it will be defaulted to 0.9.
|
||||
CurvatureFactor float64
|
||||
|
||||
minStep float64
|
||||
maxStep float64
|
||||
currStep float64
|
||||
|
||||
initF float64
|
||||
minF float64
|
||||
maxF float64
|
||||
lastF float64
|
||||
|
||||
initGrad float64
|
||||
|
||||
lastOp Operation
|
||||
}
|
||||
|
||||
func (b *Bisection) Init(f, g float64, step float64) Operation {
|
||||
if step <= 0 {
|
||||
panic("bisection: bad step size")
|
||||
}
|
||||
if g >= 0 {
|
||||
panic("bisection: initial derivative is non-negative")
|
||||
}
|
||||
|
||||
if b.CurvatureFactor == 0 {
|
||||
b.CurvatureFactor = defaultBisectionCurvature
|
||||
}
|
||||
if b.CurvatureFactor <= 0 || b.CurvatureFactor >= 1 {
|
||||
panic("bisection: CurvatureFactor not between 0 and 1")
|
||||
}
|
||||
|
||||
b.minStep = 0
|
||||
b.maxStep = math.Inf(1)
|
||||
b.currStep = step
|
||||
|
||||
b.initF = f
|
||||
b.minF = f
|
||||
b.maxF = math.NaN()
|
||||
|
||||
b.initGrad = g
|
||||
|
||||
// Only evaluate the gradient when necessary.
|
||||
b.lastOp = FuncEvaluation
|
||||
return b.lastOp
|
||||
}
|
||||
|
||||
func (b *Bisection) Iterate(f, g float64) (Operation, float64, error) {
|
||||
if b.lastOp != FuncEvaluation && b.lastOp != GradEvaluation {
|
||||
panic("bisection: Init has not been called")
|
||||
}
|
||||
minF := b.initF
|
||||
if b.maxF < minF {
|
||||
minF = b.maxF
|
||||
}
|
||||
if b.minF < minF {
|
||||
minF = b.minF
|
||||
}
|
||||
if b.lastOp == FuncEvaluation {
|
||||
// See if the function value is good enough to make progress. If it is,
|
||||
// evaluate the gradient. If not, set it to the upper bound if the bound
|
||||
// has not yet been found, otherwise iterate toward the minimum location.
|
||||
if f <= minF {
|
||||
b.lastF = f
|
||||
b.lastOp = GradEvaluation
|
||||
return b.lastOp, b.currStep, nil
|
||||
}
|
||||
if math.IsInf(b.maxStep, 1) {
|
||||
b.maxStep = b.currStep
|
||||
b.maxF = f
|
||||
return b.nextStep((b.minStep + b.maxStep) / 2)
|
||||
}
|
||||
if b.minF <= b.maxF {
|
||||
b.maxStep = b.currStep
|
||||
b.maxF = f
|
||||
} else {
|
||||
b.minStep = b.currStep
|
||||
b.minF = f
|
||||
}
|
||||
return b.nextStep((b.minStep + b.maxStep) / 2)
|
||||
}
|
||||
f = b.lastF
|
||||
// The function value was lower. Check if this location is sufficient to
|
||||
// converge the linesearch, otherwise iterate.
|
||||
if StrongWolfeConditionsMet(f, g, minF, b.initGrad, b.currStep, 0, b.CurvatureFactor) {
|
||||
b.lastOp = MajorIteration
|
||||
return b.lastOp, b.currStep, nil
|
||||
}
|
||||
if math.IsInf(b.maxStep, 1) {
|
||||
// The function value is lower. If the gradient is positive, an upper bound
|
||||
// of the minimum been found. If the gradient is negative, search farther
|
||||
// in that direction.
|
||||
if g > 0 {
|
||||
b.maxStep = b.currStep
|
||||
b.maxF = f
|
||||
return b.nextStep((b.minStep + b.maxStep) / 2)
|
||||
}
|
||||
b.minStep = b.currStep
|
||||
b.minF = f
|
||||
return b.nextStep(b.currStep * 2)
|
||||
}
|
||||
// The interval has been bounded, and we have found a new lowest value. Use
|
||||
// the gradient to decide which direction.
|
||||
if g < 0 {
|
||||
b.minStep = b.currStep
|
||||
b.minF = f
|
||||
} else {
|
||||
b.maxStep = b.currStep
|
||||
b.maxF = f
|
||||
}
|
||||
return b.nextStep((b.minStep + b.maxStep) / 2)
|
||||
}
|
||||
|
||||
// nextStep checks if the new step is equal to the old step.
|
||||
// This can happen if min and max are the same, or if the step size is infinity,
|
||||
// both of which indicate the minimization must stop. If the steps are different,
|
||||
// it sets the new step size and returns the evaluation type and the step. If the steps
|
||||
// are the same, it returns an error.
|
||||
func (b *Bisection) nextStep(step float64) (Operation, float64, error) {
|
||||
if b.currStep == step {
|
||||
b.lastOp = NoOperation
|
||||
return b.lastOp, b.currStep, ErrLinesearcherFailure
|
||||
}
|
||||
b.currStep = step
|
||||
b.lastOp = FuncEvaluation
|
||||
return b.lastOp, b.currStep, nil
|
||||
}
|
||||
Reference in New Issue
Block a user