diff/fd: make tests parallel

This commit is contained in:
Egon Elbre
2020-03-14 12:33:07 +02:00
parent 933b96a6d3
commit 76e4eae572
6 changed files with 43 additions and 17 deletions

View File

@@ -45,6 +45,7 @@ func (w WrapperCL) CrossLaplacian(x, y []float64) float64 {
} }
func TestCrossLaplacian(t *testing.T) { func TestCrossLaplacian(t *testing.T) {
t.Parallel()
for cas, test := range []struct { for cas, test := range []struct {
l CrossLaplacianTester l CrossLaplacianTester
x, y []float64 x, y []float64

View File

@@ -112,24 +112,29 @@ func testDerivative(t *testing.T, formula Formula, tol float64, tests []testPoin
} }
func TestForward(t *testing.T) { func TestForward(t *testing.T) {
t.Parallel()
testDerivative(t, Forward, 2e-4, testsFirst) testDerivative(t, Forward, 2e-4, testsFirst)
} }
func TestBackward(t *testing.T) { func TestBackward(t *testing.T) {
t.Parallel()
testDerivative(t, Backward, 2e-4, testsFirst) testDerivative(t, Backward, 2e-4, testsFirst)
} }
func TestCentral(t *testing.T) { func TestCentral(t *testing.T) {
t.Parallel()
testDerivative(t, Central, 1e-6, testsFirst) testDerivative(t, Central, 1e-6, testsFirst)
} }
func TestCentralSecond(t *testing.T) { func TestCentralSecond(t *testing.T) {
t.Parallel()
testDerivative(t, Central2nd, 1e-3, testsSecond) testDerivative(t, Central2nd, 1e-3, testsSecond)
} }
// TestDerivativeDefault checks that the derivative works when settings is nil // TestDerivativeDefault checks that the derivative works when settings is nil
// or zero value. // or zero value.
func TestDerivativeDefault(t *testing.T) { func TestDerivativeDefault(t *testing.T) {
t.Parallel()
tol := 1e-6 tol := 1e-6
for i, test := range testsFirst { for i, test := range testsFirst {
ans := Derivative(test.f, test.loc, nil) ans := Derivative(test.f, test.loc, nil)

View File

@@ -42,7 +42,8 @@ func (r Rosenbrock) FDf(x []float64, deriv []float64) (sum float64) {
} }
func TestGradient(t *testing.T) { func TestGradient(t *testing.T) {
rand.Seed(1) t.Parallel()
rnd := rand.New(rand.NewSource(1))
for i, test := range []struct { for i, test := range []struct {
nDim int nDim int
tol float64 tol float64
@@ -71,7 +72,7 @@ func TestGradient(t *testing.T) {
} { } {
x := make([]float64, test.nDim) x := make([]float64, test.nDim)
for i := range x { for i := range x {
x[i] = rand.Float64() x[i] = rnd.Float64()
} }
xcopy := make([]float64, len(x)) xcopy := make([]float64, len(x))
copy(xcopy, x) copy(xcopy, x)
@@ -93,7 +94,7 @@ func TestGradient(t *testing.T) {
// Try with provided gradient. // Try with provided gradient.
for i := range gradient { for i := range gradient {
gradient[i] = rand.Float64() gradient[i] = rnd.Float64()
} }
Gradient(gradient, r.F, x, &Settings{ Gradient(gradient, r.F, x, &Settings{
Formula: test.formula, Formula: test.formula,
@@ -107,7 +108,7 @@ func TestGradient(t *testing.T) {
// Try with known value. // Try with known value.
for i := range gradient { for i := range gradient {
gradient[i] = rand.Float64() gradient[i] = rnd.Float64()
} }
Gradient(gradient, r.F, x, &Settings{ Gradient(gradient, r.F, x, &Settings{
Formula: test.formula, Formula: test.formula,
@@ -120,7 +121,7 @@ func TestGradient(t *testing.T) {
// Try with concurrent evaluation. // Try with concurrent evaluation.
for i := range gradient { for i := range gradient {
gradient[i] = rand.Float64() gradient[i] = rnd.Float64()
} }
Gradient(gradient, r.F, x, &Settings{ Gradient(gradient, r.F, x, &Settings{
Formula: test.formula, Formula: test.formula,
@@ -135,7 +136,7 @@ func TestGradient(t *testing.T) {
// Try with concurrent evaluation with origin known. // Try with concurrent evaluation with origin known.
for i := range gradient { for i := range gradient {
gradient[i] = rand.Float64() gradient[i] = rnd.Float64()
} }
Gradient(gradient, r.F, x, &Settings{ Gradient(gradient, r.F, x, &Settings{
Formula: test.formula, Formula: test.formula,
@@ -149,7 +150,7 @@ func TestGradient(t *testing.T) {
// Try with nil settings. // Try with nil settings.
for i := range gradient { for i := range gradient {
gradient[i] = rand.Float64() gradient[i] = rnd.Float64()
} }
Gradient(gradient, r.F, x, nil) Gradient(gradient, r.F, x, nil)
if !floats.EqualApprox(gradient, trueGradient, test.tol) { if !floats.EqualApprox(gradient, trueGradient, test.tol) {
@@ -158,7 +159,7 @@ func TestGradient(t *testing.T) {
// Try with zero-valued settings. // Try with zero-valued settings.
for i := range gradient { for i := range gradient {
gradient[i] = rand.Float64() gradient[i] = rnd.Float64()
} }
Gradient(gradient, r.F, x, &Settings{}) Gradient(gradient, r.F, x, &Settings{})
if !floats.EqualApprox(gradient, trueGradient, test.tol) { if !floats.EqualApprox(gradient, trueGradient, test.tol) {
@@ -179,6 +180,7 @@ func Panics(fun func()) (b bool) {
} }
func TestGradientPanics(t *testing.T) { func TestGradientPanics(t *testing.T) {
t.Parallel()
// Test that it panics // Test that it panics
if !Panics(func() { if !Panics(func() {
Gradient([]float64{0.0}, func(x []float64) float64 { return x[0] * x[0] }, []float64{0.0, 0.0}, nil) Gradient([]float64{0.0}, func(x []float64) float64 { return x[0] * x[0] }, []float64{0.0, 0.0}, nil)

View File

@@ -16,12 +16,14 @@ type HessianTester interface {
Hess(dst mat.MutableSymmetric, x []float64) Hess(dst mat.MutableSymmetric, x []float64)
} }
var hessianTestCases = []struct { type hessianTestCase struct {
h HessianTester h HessianTester
x []float64 x []float64
settings *Settings settings *Settings
tol float64 tol float64
}{ }
var _hessianTestCases = []hessianTestCase{
{ {
h: Watson{}, h: Watson{},
x: []float64{0.2, 0.3, 0.1, 0.4}, x: []float64{0.2, 0.3, 0.1, 0.4},
@@ -70,8 +72,22 @@ var hessianTestCases = []struct {
}, },
} }
func hessianTestCases() []hessianTestCase {
xs := []hessianTestCase{}
for _, test := range _hessianTestCases {
n := test
if test.settings != nil {
clone := *test.settings
n.settings = &clone
}
xs = append(xs, n)
}
return xs
}
func TestHessian(t *testing.T) { func TestHessian(t *testing.T) {
for cas, test := range hessianTestCases { t.Parallel()
for cas, test := range hessianTestCases() {
n := len(test.x) n := len(test.x)
var got mat.SymDense var got mat.SymDense
Hessian(&got, test.h.Func, test.x, test.settings) Hessian(&got, test.h.Func, test.x, test.settings)

View File

@@ -56,7 +56,8 @@ func vecFunc43Jac(jac *mat.Dense, x []float64) {
} }
func TestJacobian(t *testing.T) { func TestJacobian(t *testing.T) {
rand.Seed(1) t.Parallel()
rnd := rand.New(rand.NewSource(1))
// Test with default settings. // Test with default settings.
for tc, test := range []struct { for tc, test := range []struct {
@@ -85,7 +86,7 @@ func TestJacobian(t *testing.T) {
} { } {
const tol = 1e-6 const tol = 1e-6
x := randomSlice(test.n, 10) x := randomSlice(rnd, test.n, 10)
xcopy := make([]float64, test.n) xcopy := make([]float64, test.n)
copy(xcopy, x) copy(xcopy, x)
@@ -185,7 +186,7 @@ func TestJacobian(t *testing.T) {
formula: Central, formula: Central,
}, },
} { } {
x := randomSlice(test.n, 10) x := randomSlice(rnd, test.n, 10)
xcopy := make([]float64, test.n) xcopy := make([]float64, test.n)
copy(xcopy, x) copy(xcopy, x)
@@ -250,10 +251,10 @@ func TestJacobian(t *testing.T) {
} }
// randomSlice returns a slice of n elements from the interval [-bound,bound). // randomSlice returns a slice of n elements from the interval [-bound,bound).
func randomSlice(n int, bound float64) []float64 { func randomSlice(rnd *rand.Rand, n int, bound float64) []float64 {
x := make([]float64, n) x := make([]float64, n)
for i := range x { for i := range x {
x[i] = 2*bound*rand.Float64() - bound x[i] = 2*bound*rnd.Float64() - bound
} }
return x return x
} }

View File

@@ -12,7 +12,8 @@ import (
) )
func TestLaplacian(t *testing.T) { func TestLaplacian(t *testing.T) {
for cas, test := range hessianTestCases { t.Parallel()
for cas, test := range hessianTestCases() {
// Modify the test cases where the formula is set. // Modify the test cases where the formula is set.
settings := test.settings settings := test.settings
if settings != nil && !settings.Formula.isZero() { if settings != nil && !settings.Formula.isZero() {