mat: fix Exp function behaviour for large norms
MODIFY
graph/network/diffusion_test.go
graph/network/diffusion_test.go
@@ -78,11 +78,11 @@ var diffuseTests = []struct {
wantTol: 1e-9,
want: map[bool]map[int64]float64{
false: {
- A: 0.0432408511, B: 0.0425986522, C: 0.0415977802, D: 0.0405588482, E: 0.0399403788,
- F: 0.0425986522, G: 0.0420083007, H: 0.0409532810, I: 0.0399982373, J: 0.0393463013,
- K: 0.0415977802, L: 0.0409532810, M: 0.0400339958, N: 0.0389913353, O: 0.0384232854,
- P: 0.0405588482, Q: 0.0399982373, R: 0.0389913353, S: 0.0380844049, T: 0.0374622025,
- U: 0.0399403788, V: 0.0393463013, W: 0.0384232854, X: 0.0374622025, Y: 0.0368918429,
+ A: 0.0432375924, B: 0.0426071834, C: 0.0415872351, D: 0.0405673794, E: 0.0399371202,
+ F: 0.0426071834, G: 0.0419859658, H: 0.0409808885, I: 0.0399759024, J: 0.0393548325,
+ K: 0.0415872351, L: 0.0409808885, M: 0.0399998711, N: 0.0390189428, O: 0.0384127403,
+ P: 0.0405673794, Q: 0.0399759024, R: 0.0390189428, S: 0.0380620700, T: 0.0374707336,
+ U: 0.0399371202, V: 0.0393548325, W: 0.0384127403, X: 0.0374707336, Y: 0.0368885843,
},
true: {
A: 0.0532814862, B: 0.0594280160, C: 0.0462076361, D: 0.0330529557, E: 0.0211688130,
@@ -102,7 +102,7 @@ var diffuseTests = []struct {
}
return m
}(),
- t: 0.01, // FIXME(kortschak): Low t used due to instability in mat.Exp.
+ t: 1, // FIXME(kortschak): Low t used due to instability in mat.Exp.
wantTol: 1e-1, // FIXME(kortschak): High tolerance used due to instability in mat.Exp.
want: map[bool]map[int64]float64{

MODIFY
mat/dense_test.go
mat/dense_test.go
@@ -895,13 +895,14 @@ func TestExp(t *testing.T) {
want [][]float64
mod func(*Dense)
}{
+ // Expected values obtained from scipy.linalg.expm with the equivalent numpy.array.
{
a: [][]float64{{-49, 24}, {-64, 31}},
- want: [][]float64{{-0.7357587581474017, 0.5518190996594223}, {-1.4715175990917921, 1.103638240717339}},
+ want: [][]float64{{-0.735758758144758, 0.551819099658100}, {-1.471517599088267, 1.103638240715576}},
},
{
a: [][]float64{{-49, 24}, {-64, 31}},
- want: [][]float64{{-0.7357587581474017, 0.5518190996594223}, {-1.4715175990917921, 1.103638240717339}},
+ want: [][]float64{{-0.735758758144758, 0.551819099658100}, {-1.471517599088267, 1.103638240715576}},
mod: func(a *Dense) {
d := make([]float64, 100)
for i := range d {
@@ -914,14 +915,30 @@ func TestExp(t *testing.T) {
a: [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}},
want: [][]float64{{2.71828182845905, 0, 0}, {0, 2.71828182845905, 0}, {0, 0, 2.71828182845905}},
},
+ {
+ a: [][]float64{
+ {-200, 100, 100, 0},
+ {100, -200, 0, 100},
+ {100, 0, -200, 100},
+ {0, 100, 100, -200},
+ },
+ want: [][]float64{
+ {0.25, 0.25, 0.25, 0.25},
+ {0.25, 0.25, 0.25, 0.25},
+ {0.25, 0.25, 0.25, 0.25},
+ {0.25, 0.25, 0.25, 0.25},
+ },
+ },
} {
var got Dense
if test.mod != nil {
test.mod(&got)
}
got.Exp(NewDense(flatten(test.a)))
- if !EqualApprox(&got, NewDense(flatten(test.want)), 1e-12) {
- t.Errorf("unexpected result for Exp test %d", i)
+ want := NewDense(flatten(test.want))
+ if !EqualApprox(&got, want, 1e-14) {
+ t.Errorf("unexpected result for Exp test %d\ngot:\n%v\nwant:\n%v",
+ i, Formatted(&got), Formatted(want))
}
}
}

mat: fix Exp function behaviour for large norms