Skip to content
This repository was archived by the owner on Nov 23, 2018. It is now read-only.

Commit e731aac

Browse files
committed
Merge branch 'decrease-factor'
Closes #155
2 parents 4358607 + ee51ef5 commit e731aac

5 files changed

+46
-44
lines changed

backtracking.go

+20-21
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,27 @@
55
package optimize
66

77
const (
8-
defaultBacktrackingDecrease = 0.5
9-
defaultBacktrackingFuncConst = 1e-4
10-
minimumBacktrackingStepSize = 1e-20
8+
defaultBacktrackingContraction = 0.5
9+
defaultBacktrackingDecrease = 1e-4
10+
minimumBacktrackingStepSize = 1e-20
1111
)
1212

1313
// Backtracking is a Linesearcher that uses backtracking to find a point that
14-
// satisfies the Armijo condition with the given function constant FuncConst. If
15-
// the Armijo condition has not been met, the step size is decreased by a
16-
// factor of Decrease.
14+
// satisfies the Armijo condition with the given decrease factor. If the Armijo
15+
// condition has not been met, the step size is decreased by ContractionFactor.
1716
//
1817
// The Armijo condition only requires the gradient at the beginning of each
1918
// major iteration (not at successive step locations), and so Backtracking may
2019
// be a good linesearch for functions with expensive gradients. Backtracking is
2120
// not appropriate for optimizers that require the Wolfe conditions to be met,
2221
// such as BFGS.
2322
//
24-
// Both FuncConst and Decrease must be between zero and one, and Backtracking will
25-
// panic otherwise. If either FuncConst or Decrease are zero, it will be set to a
26-
// reasonable default.
23+
// Both DecreaseFactor and ContractionFactor must be between zero and one, and
24+
// Backtracking will panic otherwise. If either DecreaseFactor or
25+
// ContractionFactor are zero, it will be set to a reasonable default.
2726
type Backtracking struct {
28-
FuncConst float64 // Necessary function descrease for Armijo condition.
29-
Decrease float64 // Step size multiplier at each iteration (stepSize *= Decrease).
27+
DecreaseFactor float64 // Constant factor in the sufficient decrease (Armijo) condition.
28+
ContractionFactor float64 // Step size multiplier at each iteration (step *= ContractionFactor).
3029

3130
stepSize float64
3231
initF float64
@@ -43,17 +42,17 @@ func (b *Backtracking) Init(f, g float64, step float64) Operation {
4342
panic("backtracking: initial derivative is non-negative")
4443
}
4544

46-
if b.Decrease == 0 {
47-
b.Decrease = defaultBacktrackingDecrease
45+
if b.ContractionFactor == 0 {
46+
b.ContractionFactor = defaultBacktrackingContraction
4847
}
49-
if b.FuncConst == 0 {
50-
b.FuncConst = defaultBacktrackingFuncConst
48+
if b.DecreaseFactor == 0 {
49+
b.DecreaseFactor = defaultBacktrackingDecrease
5150
}
52-
if b.Decrease <= 0 || b.Decrease >= 1 {
53-
panic("backtracking: Decrease must be between 0 and 1")
51+
if b.ContractionFactor <= 0 || b.ContractionFactor >= 1 {
52+
panic("backtracking: ContractionFactor must be between 0 and 1")
5453
}
55-
if b.FuncConst <= 0 || b.FuncConst >= 1 {
56-
panic("backtracking: FuncConst must be between 0 and 1")
54+
if b.DecreaseFactor <= 0 || b.DecreaseFactor >= 1 {
55+
panic("backtracking: DecreaseFactor must be between 0 and 1")
5756
}
5857

5958
b.stepSize = step
@@ -69,11 +68,11 @@ func (b *Backtracking) Iterate(f, _ float64) (Operation, float64, error) {
6968
panic("backtracking: Init has not been called")
7069
}
7170

72-
if ArmijoConditionMet(f, b.initF, b.initG, b.stepSize, b.FuncConst) {
71+
if ArmijoConditionMet(f, b.initF, b.initG, b.stepSize, b.DecreaseFactor) {
7372
b.lastOp = MajorIteration
7473
return b.lastOp, b.stepSize, nil
7574
}
76-
b.stepSize *= b.Decrease
75+
b.stepSize *= b.ContractionFactor
7776
if b.stepSize < minimumBacktrackingStepSize {
7877
b.lastOp = NoOperation
7978
return b.lastOp, b.stepSize, ErrLinesearcherFailure

bisection.go

+12-9
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,14 @@ package optimize
77
import "math"
88

99
// Bisection is a Linesearcher that uses a bisection to find a point that
10-
// satisfies the strong Wolfe conditions with the given gradient constant and
11-
// function constant of zero. If GradConst is zero, it will be set to a reasonable
12-
// value. Bisection will panic if GradConst is not between zero and one.
10+
// satisfies the strong Wolfe conditions with the given curvature factor and
11+
// sufficient decrease factor of zero.
1312
type Bisection struct {
14-
GradConst float64
13+
// CurvatureFactor is the constant factor in the curvature condition.
14+
// Smaller values result in a more exact line search.
15+
// A set value must be in the interval (0, 1), otherwise Init will panic.
16+
// If it is zero, it will be defaulted to 0.9.
17+
CurvatureFactor float64
1518

1619
minStep float64
1720
maxStep float64
@@ -35,11 +38,11 @@ func (b *Bisection) Init(f, g float64, step float64) Operation {
3538
panic("bisection: initial derivative is non-negative")
3639
}
3740

38-
if b.GradConst == 0 {
39-
b.GradConst = 0.9
41+
if b.CurvatureFactor == 0 {
42+
b.CurvatureFactor = 0.9
4043
}
41-
if b.GradConst <= 0 || b.GradConst >= 1 {
42-
panic("bisection: GradConst not between 0 and 1")
44+
if b.CurvatureFactor <= 0 || b.CurvatureFactor >= 1 {
45+
panic("bisection: CurvatureFactor not between 0 and 1")
4346
}
4447

4548
b.minStep = 0
@@ -94,7 +97,7 @@ func (b *Bisection) Iterate(f, g float64) (Operation, float64, error) {
9497
f = b.lastF
9598
// The function value was lower. Check if this location is sufficient to
9699
// converge the linesearch, otherwise iterate.
97-
if StrongWolfeConditionsMet(f, g, minF, b.initGrad, b.currStep, 0, b.GradConst) {
100+
if StrongWolfeConditionsMet(f, g, minF, b.initGrad, b.currStep, 0, b.CurvatureFactor) {
98101
b.lastOp = MajorIteration
99102
return b.lastOp, b.currStep, nil
100103
}

linesearch.go

+11-11
Original file line numberDiff line numberDiff line change
@@ -183,9 +183,9 @@ func (ls *LinesearchMethod) initNextLinesearch(loc *Location) (Operation, error)
183183
// true, though this is not enforced:
184184
// - initGrad < 0
185185
// - step > 0
186-
// - 0 < funcConst < 1
187-
func ArmijoConditionMet(currObj, initObj, initGrad, step, funcConst float64) bool {
188-
return currObj <= initObj+funcConst*step*initGrad
186+
// - 0 < decrease < 1
187+
func ArmijoConditionMet(currObj, initObj, initGrad, step, decrease float64) bool {
188+
return currObj <= initObj+decrease*step*initGrad
189189
}
190190

191191
// StrongWolfeConditionsMet returns true if the strong Wolfe conditions have been met.
@@ -195,12 +195,12 @@ func ArmijoConditionMet(currObj, initObj, initGrad, step, funcConst float64) boo
195195
// enforced:
196196
// - initGrad < 0
197197
// - step > 0
198-
// - 0 <= funcConst < gradConst < 1
199-
func StrongWolfeConditionsMet(currObj, currGrad, initObj, initGrad, step, funcConst, gradConst float64) bool {
200-
if currObj > initObj+funcConst*step*initGrad {
198+
// - 0 <= decrease < curvature < 1
199+
func StrongWolfeConditionsMet(currObj, currGrad, initObj, initGrad, step, decrease, curvature float64) bool {
200+
if currObj > initObj+decrease*step*initGrad {
201201
return false
202202
}
203-
return math.Abs(currGrad) < gradConst*math.Abs(initGrad)
203+
return math.Abs(currGrad) < curvature*math.Abs(initGrad)
204204
}
205205

206206
// WeakWolfeConditionsMet returns true if the weak Wolfe conditions have been met.
@@ -209,10 +209,10 @@ func StrongWolfeConditionsMet(currObj, currGrad, initObj, initGrad, step, funcCo
209209
// conditions, the following should be true, though this is not enforced:
210210
// - initGrad < 0
211211
// - step > 0
212-
// - 0 <= funcConst < gradConst < 1
213-
func WeakWolfeConditionsMet(currObj, currGrad, initObj, initGrad, step, funcConst, gradConst float64) bool {
214-
if currObj > initObj+funcConst*step*initGrad {
212+
// - 0 <= decrease < curvature< 1
213+
func WeakWolfeConditionsMet(currObj, currGrad, initObj, initGrad, step, decrease, curvature float64) bool {
214+
if currObj > initObj+decrease*step*initGrad {
215215
return false
216216
}
217-
return currGrad >= gradConst*initGrad
217+
return currGrad >= curvature*initGrad
218218
}

linesearcher_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,15 @@ func TestMoreThuente(t *testing.T) {
2626
func TestBisection(t *testing.T) {
2727
c := 0.1
2828
ls := &Bisection{
29-
GradConst: c,
29+
CurvatureFactor: c,
3030
}
3131
testLinesearcher(t, ls, 0, c, true)
3232
}
3333

3434
func TestBacktracking(t *testing.T) {
3535
d := 0.001
3636
ls := &Backtracking{
37-
FuncConst: d,
37+
DecreaseFactor: d,
3838
}
3939
testLinesearcher(t, ls, d, 0, false)
4040
}

unconstrained_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1016,7 +1016,7 @@ func TestGradientDescent(t *testing.T) {
10161016
func TestGradientDescentBacktracking(t *testing.T) {
10171017
testLocal(t, gradientDescentTests, &GradientDescent{
10181018
Linesearcher: &Backtracking{
1019-
FuncConst: 0.1,
1019+
DecreaseFactor: 0.1,
10201020
},
10211021
})
10221022
}

0 commit comments

Comments
 (0)