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

Commit e616c70

Browse files
committed
Merge branch 'remove-evaluationtype'
Closes #122 Resolves #103
2 parents 0c9c657 + 73ec231 commit e616c70

13 files changed

+448
-336
lines changed

backtracking.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ type Backtracking struct {
3333
initG float64
3434
}
3535

36-
func (b *Backtracking) Init(f, g float64, step float64) EvaluationType {
36+
func (b *Backtracking) Init(f, g float64, step float64) Operation {
3737
if step <= 0 {
3838
panic("backtracking: bad step size")
3939
}
@@ -64,10 +64,10 @@ func (b *Backtracking) Finished(f, _ float64) bool {
6464
return ArmijoConditionMet(f, b.initF, b.initG, b.stepSize, b.FuncConst)
6565
}
6666

67-
func (b *Backtracking) Iterate(_, _ float64) (float64, EvaluationType, error) {
67+
func (b *Backtracking) Iterate(_, _ float64) (float64, Operation, error) {
6868
b.stepSize *= b.Decrease
6969
if b.stepSize < minimumBacktrackingStepSize {
70-
return 0, NoEvaluation, ErrLinesearchFailure
70+
return 0, NoOperation, ErrLinesearchFailure
7171
}
7272
return b.stepSize, FuncEvaluation, nil
7373
}

bfgs.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ type BFGS struct {
3939
first bool // Is it the first iteration (used to set the scale of the initial hessian)
4040
}
4141

42-
func (b *BFGS) Init(loc *Location, xNext []float64) (EvaluationType, IterationType, error) {
42+
func (b *BFGS) Init(loc *Location) (Operation, error) {
4343
if b.Linesearcher == nil {
4444
b.Linesearcher = &Bisection{}
4545
}
@@ -49,11 +49,11 @@ func (b *BFGS) Init(loc *Location, xNext []float64) (EvaluationType, IterationTy
4949
b.ls.Linesearcher = b.Linesearcher
5050
b.ls.NextDirectioner = b
5151

52-
return b.ls.Init(loc, xNext)
52+
return b.ls.Init(loc)
5353
}
5454

55-
func (b *BFGS) Iterate(loc *Location, xNext []float64) (EvaluationType, IterationType, error) {
56-
return b.ls.Iterate(loc, xNext)
55+
func (b *BFGS) Iterate(loc *Location) (Operation, error) {
56+
return b.ls.Iterate(loc)
5757
}
5858

5959
func (b *BFGS) InitDirection(loc *Location, dir []float64) (stepSize float64) {

bisection.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ type Bisection struct {
2626
maxGrad float64
2727
}
2828

29-
func (b *Bisection) Init(f, g float64, step float64) EvaluationType {
29+
func (b *Bisection) Init(f, g float64, step float64) Operation {
3030
if step <= 0 {
3131
panic("bisection: bad step size")
3232
}
@@ -73,7 +73,7 @@ func (b *Bisection) Finished(f, g float64) bool {
7373
return false
7474
}
7575

76-
func (b *Bisection) Iterate(f, g float64) (float64, EvaluationType, error) {
76+
func (b *Bisection) Iterate(f, g float64) (float64, Operation, error) {
7777
// Deciding on the next step size
7878
if math.IsInf(b.maxStep, 1) {
7979
// Have not yet bounded the minimum
@@ -135,10 +135,10 @@ func (b *Bisection) Iterate(f, g float64) (float64, EvaluationType, error) {
135135
// both of which indicate the minimization must stop. If the steps are different,
136136
// it sets the new step size and returns the step and evaluation type. If the steps
137137
// are the same, it returns an error.
138-
func (b *Bisection) checkStepEqual(newStep float64, e EvaluationType) (float64, EvaluationType, error) {
138+
func (b *Bisection) checkStepEqual(newStep float64, op Operation) (float64, Operation, error) {
139139
if b.currStep == newStep {
140-
return b.currStep, NoEvaluation, ErrLinesearchFailure
140+
return b.currStep, NoOperation, ErrLinesearchFailure
141141
}
142142
b.currStep = newStep
143-
return newStep, e, nil
143+
return newStep, op, nil
144144
}

cg.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ type CG struct {
9494
gradPrevNorm float64
9595
}
9696

97-
func (cg *CG) Init(loc *Location, xNext []float64) (EvaluationType, IterationType, error) {
97+
func (cg *CG) Init(loc *Location) (Operation, error) {
9898
if cg.IterationRestartFactor < 0 {
9999
panic("cg: IterationRestartFactor is negative")
100100
}
@@ -125,11 +125,11 @@ func (cg *CG) Init(loc *Location, xNext []float64) (EvaluationType, IterationTyp
125125
cg.ls.Linesearcher = cg.Linesearcher
126126
cg.ls.NextDirectioner = cg
127127

128-
return cg.ls.Init(loc, xNext)
128+
return cg.ls.Init(loc)
129129
}
130130

131-
func (cg *CG) Iterate(loc *Location, xNext []float64) (EvaluationType, IterationType, error) {
132-
return cg.ls.Iterate(loc, xNext)
131+
func (cg *CG) Iterate(loc *Location) (Operation, error) {
132+
return cg.ls.Iterate(loc)
133133
}
134134

135135
func (cg *CG) InitDirection(loc *Location, dir []float64) (stepSize float64) {

gradientdescent.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ type GradientDescent struct {
1818
ls *LinesearchMethod
1919
}
2020

21-
func (g *GradientDescent) Init(loc *Location, xNext []float64) (EvaluationType, IterationType, error) {
21+
func (g *GradientDescent) Init(loc *Location) (Operation, error) {
2222
if g.StepSizer == nil {
2323
g.StepSizer = &QuadraticStepSize{}
2424
}
@@ -31,11 +31,11 @@ func (g *GradientDescent) Init(loc *Location, xNext []float64) (EvaluationType,
3131
g.ls.Linesearcher = g.Linesearcher
3232
g.ls.NextDirectioner = g
3333

34-
return g.ls.Init(loc, xNext)
34+
return g.ls.Init(loc)
3535
}
3636

37-
func (g *GradientDescent) Iterate(loc *Location, xNext []float64) (EvaluationType, IterationType, error) {
38-
return g.ls.Iterate(loc, xNext)
37+
func (g *GradientDescent) Iterate(loc *Location) (Operation, error) {
38+
return g.ls.Iterate(loc)
3939
}
4040

4141
func (g *GradientDescent) InitDirection(loc *Location, dir []float64) (stepSize float64) {

interfaces.go

+42-17
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,40 @@
55
package optimize
66

77
// A Method can optimize an objective function.
8+
//
9+
// It uses a reverse-communication interface between the optimization method
10+
// and the caller. Method acts as a client that asks the caller to perform
11+
// needed operations via RequestType returned from Init and Iterate methods.
12+
// This provides independence of the optimization algorithm on user-supplied
13+
// data and their representation, and enables automation of common operations
14+
// like checking for (various types of) convergence and maintaining statistics.
15+
//
16+
// A Method can command an Evaluation, a MajorIteration or NoOperation operations.
17+
// An evaluation operation is one or more of the Evaluation operations
18+
// (FuncEvaluation, GradEvaluation, etc.) which can be combined with
19+
// the bitwise or operator. In an evaluation operation, the requested routines
20+
// will be evaluated at the point specified in Location.X. The corresponding
21+
// fields of Location will be filled with the results from the routine and can
22+
// be retrieved upon the next call to Iterate. Alternatively, a Method can
23+
// declare a MajorIteration. In a MajorIteration, all values in Location must
24+
// be valid and consistent, and are interpreted as a new minimum. Convergence
25+
// of the optimization (GradientThreshold, etc.) will be checked using this new
26+
// minimum.
27+
//
28+
// A Method must not return InitIteration and PostIteration operations. These are
29+
// reserved for the clients to be passed to Recorders. A Method must also not
30+
// combine the Evaluation operations with the Iteration operations.
831
type Method interface {
9-
// Init initializes the method and stores the first location to evaluate
10-
// in xNext.
11-
Init(loc *Location, xNext []float64) (EvaluationType, IterationType, error)
32+
// Init initializes the method based on the initial data in loc, updates it
33+
// and returns the first operation to be carried out by the caller.
34+
// The initial location must be valid as specified by Needs().
35+
Init(loc *Location) (Operation, error)
1236

13-
// Iterate performs one iteration of the method and stores the next
14-
// location to evaluate in xNext.
15-
Iterate(loc *Location, xNext []float64) (EvaluationType, IterationType, error)
37+
// Iterate retrieves data from loc, performs one iteration of the method,
38+
// updates loc and returns the next operation.
39+
// TODO(vladimir-ch): When decided, say something whether the contents of
40+
// Location is preserved between calls to Iterate().
41+
Iterate(loc *Location) (Operation, error)
1642

1743
// Needs specifies information about the objective function needed by the
1844
// optimizer beyond just the function value. The information is used
@@ -24,6 +50,13 @@ type Method interface {
2450
}
2551
}
2652

53+
// Statuser can report the status and any error. It is intended for methods as
54+
// an additional error reporting mechanism apart from the errors returned from
55+
// Init() and Iterate().
56+
type Statuser interface {
57+
Status() (Status, error)
58+
}
59+
2760
// Linesearcher is a type that can perform a line search. It tries to find an
2861
// (approximate) minimum of the objective function along the search direction
2962
// dir_k starting at the most recent location x_k, i.e., it tries to minimize
@@ -36,7 +69,7 @@ type Linesearcher interface {
3669
// φ(0) and φ'(0), respectively, and step contains the first trial step
3770
// length. It returns the type of evaluation to be performed at
3871
// x_0 + step * dir_0.
39-
Init(value, derivative float64, step float64) EvaluationType
72+
Init(value, derivative float64, step float64) Operation
4073

4174
// Finished takes in the values of φ and φ' evaluated at the previous step,
4275
// and returns whether a sufficiently accurate minimum of φ has been found.
@@ -45,7 +78,7 @@ type Linesearcher interface {
4578
// Iterate takes in the values of φ and φ' evaluated at the previous step
4679
// and returns the next step size and the type of evaluation to be
4780
// performed at x_k + step * dir_k.
48-
Iterate(value, derivative float64) (step float64, e EvaluationType, err error)
81+
Iterate(value, derivative float64) (step float64, op Operation, err error)
4982
}
5083

5184
// NextDirectioner implements a strategy for computing a new line search
@@ -72,17 +105,9 @@ type StepSizer interface {
72105
StepSize(loc *Location, dir []float64) float64
73106
}
74107

75-
// Statuser returns the status of the Function being optimized. This can be used
76-
// by the Function to terminate early, for example with an error. The user can
77-
// use one of the pre-provided Status constants, or may call NewStatus to create
78-
// a custom Status value.
79-
type Statuser interface {
80-
Status() (Status, error)
81-
}
82-
83108
// A Recorder can record the progress of the optimization, for example to print
84109
// the progress to StdOut or to a log file. A Recorder must not modify any data.
85110
type Recorder interface {
86111
Init() error
87-
Record(*Location, EvaluationType, IterationType, *Stats) error
112+
Record(*Location, Operation, *Stats) error
88113
}

lbfgs.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ type LBFGS struct {
3838
rhoHist []float64 // last Store iterations of rho
3939
}
4040

41-
func (l *LBFGS) Init(loc *Location, xNext []float64) (EvaluationType, IterationType, error) {
41+
func (l *LBFGS) Init(loc *Location) (Operation, error) {
4242
if l.Linesearcher == nil {
4343
l.Linesearcher = &Bisection{}
4444
}
@@ -47,11 +47,11 @@ func (l *LBFGS) Init(loc *Location, xNext []float64) (EvaluationType, IterationT
4747
}
4848
l.ls.Linesearcher = l.Linesearcher
4949
l.ls.NextDirectioner = l
50-
return l.ls.Init(loc, xNext)
50+
return l.ls.Init(loc)
5151
}
5252

53-
func (l *LBFGS) Iterate(loc *Location, xNext []float64) (EvaluationType, IterationType, error) {
54-
return l.ls.Iterate(loc, xNext)
53+
func (l *LBFGS) Iterate(loc *Location) (Operation, error) {
54+
return l.ls.Iterate(loc)
5555
}
5656

5757
func (l *LBFGS) InitDirection(loc *Location, dir []float64) (stepSize float64) {

0 commit comments

Comments
 (0)