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

Commit c930e43

Browse files
committed
Add tests for Linesearchers
1 parent 6f5e867 commit c930e43

File tree

1 file changed

+136
-0
lines changed

1 file changed

+136
-0
lines changed

linesearcher_test.go

+136
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
// Copyright ©2015 The gonum Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package optimize
6+
7+
import (
8+
"fmt"
9+
"math"
10+
"reflect"
11+
"testing"
12+
13+
"github.com/gonum/optimize/functions"
14+
)
15+
16+
func TestMoreThuente(t *testing.T) {
17+
d := 0.001
18+
c := 0.001
19+
ls := &MoreThuente{
20+
DecreaseFactor: d,
21+
CurvatureFactor: c,
22+
}
23+
testLinesearcher(t, ls, d, c, true)
24+
}
25+
26+
func TestBisection(t *testing.T) {
27+
c := 0.1
28+
ls := &Bisection{
29+
GradConst: c,
30+
}
31+
testLinesearcher(t, ls, 0, c, true)
32+
}
33+
34+
func TestBacktracking(t *testing.T) {
35+
d := 0.001
36+
ls := &Backtracking{
37+
FuncConst: d,
38+
}
39+
testLinesearcher(t, ls, d, 0, false)
40+
}
41+
42+
type funcGrader interface {
43+
Func([]float64) float64
44+
Grad([]float64, []float64)
45+
}
46+
47+
type linesearcherTest struct {
48+
name string
49+
f func(float64) float64
50+
g func(float64) float64
51+
}
52+
53+
func newLinesearcherTest(name string, fg funcGrader) linesearcherTest {
54+
grad := make([]float64, 1)
55+
return linesearcherTest{
56+
name: name,
57+
f: func(x float64) float64 {
58+
return fg.Func([]float64{x})
59+
},
60+
g: func(x float64) float64 {
61+
fg.Grad(grad, []float64{x})
62+
return grad[0]
63+
},
64+
}
65+
}
66+
67+
func testLinesearcher(t *testing.T, ls Linesearcher, decrease, curvature float64, strongWolfe bool) {
68+
for i, prob := range []linesearcherTest{
69+
newLinesearcherTest("Concave-to-the-right function", functions.ConcaveRight{}),
70+
newLinesearcherTest("Concave-to-the-left function", functions.ConcaveLeft{}),
71+
newLinesearcherTest("Plassmann wiggly function (l=39, beta=0.01)", functions.Plassmann{39, 0.01}),
72+
newLinesearcherTest("Yanai-Ozawa-Kaneko function (beta1=0.001, beta2=0.001)", functions.YanaiOzawaKaneko{0.001, 0.001}),
73+
newLinesearcherTest("Yanai-Ozawa-Kaneko function (beta1=0.01, beta2=0.001)", functions.YanaiOzawaKaneko{0.01, 0.001}),
74+
newLinesearcherTest("Yanai-Ozawa-Kaneko function (beta1=0.001, beta2=0.01)", functions.YanaiOzawaKaneko{0.001, 0.01}),
75+
} {
76+
for _, initStep := range []float64{0.001, 0.1, 1, 10, 1000} {
77+
prefix := fmt.Sprintf("test %d (%v started from %v)", i, prob.name, initStep)
78+
79+
f0 := prob.f(0)
80+
g0 := prob.g(0)
81+
if g0 >= 0 {
82+
panic("bad test function")
83+
}
84+
85+
op := ls.Init(f0, g0, initStep)
86+
if !op.isEvaluation() {
87+
t.Errorf("%v: Linesearcher.Init returned non-evaluating operation %v", op)
88+
continue
89+
}
90+
91+
var (
92+
err error
93+
k int
94+
f, g float64
95+
step float64
96+
)
97+
loop:
98+
for {
99+
switch op {
100+
case MajorIteration:
101+
if f > f0+step*decrease*g0 {
102+
t.Errorf("%v: %v found step %v that does not satisfy the sufficient decrease condition",
103+
prefix, reflect.TypeOf(ls), step)
104+
}
105+
if strongWolfe && math.Abs(g) > curvature*(-g0) {
106+
t.Errorf("%v: %v found step %v that does not satisfy the curvature condition",
107+
prefix, reflect.TypeOf(ls), step)
108+
}
109+
break loop
110+
case FuncEvaluation:
111+
f = prob.f(step)
112+
case GradEvaluation:
113+
g = prob.g(step)
114+
case FuncEvaluation | GradEvaluation:
115+
f = prob.f(step)
116+
g = prob.g(step)
117+
default:
118+
t.Errorf("%v: Linesearcher returned an invalid operation %v", op)
119+
break loop
120+
}
121+
122+
k++
123+
if k == 1000 {
124+
t.Errorf("%v: %v did not finish", prefix, reflect.TypeOf(ls))
125+
break
126+
}
127+
128+
op, step, err = ls.Iterate(f, g)
129+
if err != nil {
130+
t.Errorf("%v: %v failed at step %v with %v", prefix, reflect.TypeOf(ls), step, err)
131+
break
132+
}
133+
}
134+
}
135+
}
136+
}

0 commit comments

Comments
 (0)