-
Notifications
You must be signed in to change notification settings - Fork 27
/
test_primitives.py
69 lines (56 loc) · 2.14 KB
/
test_primitives.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import unittest
import numpy as np
import legume.backend as bd
import legume
class TestGMEgrad(unittest.TestCase):
'''
Tests of various primitives
'''
def test_eigh(self):
try:
from autograd import grad
legume.set_backend('autograd')
except:
return 0
def obj(mat):
# We make a Hermitian matrix using the upper triangular part of mat
# as the real symmetric and the lower triangular part of mat as the
# imaginary antisymmetric part
mat_sym = bd.triu(mat) + bd.triu(mat, 1).transpose()
mat_low = bd.triu(bd.transpose(mat), 1)
mat_her = mat_sym + 1j*mat_low - 1j*bd.transpose(mat_low)
w, v = bd.eigh(mat_her)
return bd.sum(bd.abs(w)) + bd.sum(bd.abs(v))
np.random.seed(0)
N = 6
mat = np.random.randn(N, N)
gr_ag = grad(obj)(mat)
# Numerical gradients
gr_num = legume.utils.grad_num(obj, mat)
diff = np.sum(np.abs(gr_num - gr_ag)**2) / np.linalg.norm(gr_num)
self.assertLessEqual(diff, 1e-4)
def test_eigsh(self):
try:
from autograd import grad
legume.set_backend('autograd')
except:
return 0
def obj(mat, k=3):
# We make a Hermitian matrix using the upper triangular part of mat
# as the real symmetric and the lower triangular part of mat as the
# imaginary antisymmetric part
mat_sym = bd.triu(mat) + bd.triu(mat, 1).transpose()
mat_low = bd.triu(bd.transpose(mat), 1)
mat_her = mat_sym + 1j*mat_low - 1j*bd.transpose(mat_low)
w, v = bd.eigsh(mat_her, k=k)
return bd.sum(bd.abs(w)) + bd.sum(bd.abs(v))
np.random.seed(0)
N = 6
mat = np.random.randn(N, N)
gr_ag = grad(obj)(mat)
# Numerical gradients
gr_num = legume.utils.grad_num(obj, mat)
diff = np.sum(np.abs(gr_num - gr_ag)**2) / np.linalg.norm(gr_num)
self.assertLessEqual(diff, 1e-4)
if __name__ == '__main__':
unittest.main()