-
Notifications
You must be signed in to change notification settings - Fork 56
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
takagi fix #394
takagi fix #394
Changes from 7 commits
c41b49f
3ff6505
6e9b2b5
137820e
1ae82f1
05ed19d
7f1a795
cf82481
74c05b8
c81cfbb
6fb38fe
b5fbd06
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
@@ -202,6 +202,17 @@ def takagi(A, svd_order=True): | |||||||||
vals, U = takagi(Amr, svd_order=svd_order) | ||||||||||
return vals, U * np.exp(1j * phi / 2) | ||||||||||
|
||||||||||
# If the matrix is diagonal, Takagi decomposition is easy | ||||||||||
if np.allclose(A, np.diag(np.diag(A)), rtol=1e-16): | ||||||||||
d = np.diag(A) | ||||||||||
U = np.diag(np.exp(1j * 0.5 * np.angle(d))) | ||||||||||
l = np.abs(d) | ||||||||||
l = np.sort(l) | ||||||||||
U = U[np.argsort(l)] | ||||||||||
if svd_order: | ||||||||||
return l[::-1], U[:, ::-1] | ||||||||||
return l, U | ||||||||||
Comment on lines
+216
to
+218
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you can do the same thing on lines 218-220 as well if it helps, but I think this should suffice.
Suggested change
|
||||||||||
|
||||||||||
u, d, v = np.linalg.svd(A) | ||||||||||
U = u @ sqrtm((v @ np.conjugate(u)).T) | ||||||||||
if svd_order is False: | ||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,7 +19,13 @@ | |
|
||
from thewalrus.random import random_interferometer as haar_measure | ||
from thewalrus.random import random_symplectic | ||
from thewalrus.decompositions import williamson, blochmessiah, takagi, pre_iwasawa, iwasawa | ||
from thewalrus.decompositions import ( | ||
williamson, | ||
blochmessiah, | ||
takagi, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. did you do There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I did There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yup, that is the standard use in here. |
||
pre_iwasawa, | ||
iwasawa, | ||
) | ||
from thewalrus.symplectic import sympmat as omega | ||
from thewalrus.quantum.gaussian_checks import is_symplectic | ||
|
||
|
@@ -48,15 +54,19 @@ def _create_cov(nbar): | |
|
||
# interferometer 1 | ||
U1 = haar_measure(n) | ||
S1 = np.vstack([np.hstack([U1.real, -U1.imag]), np.hstack([U1.imag, U1.real])]) | ||
S1 = np.vstack( | ||
[np.hstack([U1.real, -U1.imag]), np.hstack([U1.imag, U1.real])] | ||
) | ||
|
||
# squeezing | ||
r = np.log(0.2 * np.arange(n) + 2) | ||
Sq = block_diag(np.diag(np.exp(-r)), np.diag(np.exp(r))) | ||
|
||
# interferometer 2 | ||
U2 = haar_measure(n) | ||
S2 = np.vstack([np.hstack([U2.real, -U2.imag]), np.hstack([U2.imag, U2.real])]) | ||
S2 = np.vstack( | ||
[np.hstack([U2.real, -U2.imag]), np.hstack([U2.imag, U2.real])] | ||
) | ||
|
||
# final symplectic | ||
S_final = S2 @ Sq @ S1 | ||
|
@@ -99,7 +109,9 @@ def test_even_validation(self): | |
"""Test that the graph_embed decomposition raises exception if not even number of rows""" | ||
A = np.random.rand(5, 5) + 1j * np.random.rand(5, 5) | ||
A += A.T | ||
with pytest.raises(ValueError, match="must have an even number of rows/columns"): | ||
with pytest.raises( | ||
ValueError, match="must have an even number of rows/columns" | ||
): | ||
williamson(A) | ||
|
||
def test_positive_definite_validation(self): | ||
|
@@ -172,7 +184,9 @@ def _create_transform(n, passive=True): | |
|
||
# interferometer 1 | ||
U1 = haar_measure(n) | ||
S1 = np.vstack([np.hstack([U1.real, -U1.imag]), np.hstack([U1.imag, U1.real])]) | ||
S1 = np.vstack( | ||
[np.hstack([U1.real, -U1.imag]), np.hstack([U1.imag, U1.real])] | ||
) | ||
|
||
Sq = np.identity(2 * n) | ||
if not passive: | ||
|
@@ -182,7 +196,9 @@ def _create_transform(n, passive=True): | |
|
||
# interferometer 2 | ||
U2 = haar_measure(n) | ||
S2 = np.vstack([np.hstack([U2.real, -U2.imag]), np.hstack([U2.imag, U2.real])]) | ||
S2 = np.vstack( | ||
[np.hstack([U2.real, -U2.imag]), np.hstack([U2.imag, U2.real])] | ||
) | ||
|
||
# final symplectic | ||
S_final = S2 @ Sq @ S1 | ||
|
@@ -324,6 +340,34 @@ def test_takagi_error(): | |
takagi(A) | ||
|
||
|
||
def test_takagi_diagonal_matrix(): | ||
"""Test the takagi decomposition works well for a specific matrix that was not decomposed accurately in a previous implementation. | ||
See more info in PR #393 (https://github.com/XanaduAI/thewalrus/pull/393)""" | ||
A = np.array( | ||
[ | ||
[ | ||
-8.4509484628125742e-01 + 1.0349426984742664e-16j, | ||
6.3637197288239186e-17 - 7.4398922703555097e-33j, | ||
2.6734481396039929e-32 + 1.7155650257063576e-35j, | ||
], | ||
[ | ||
6.3637197288239186e-17 - 7.4398922703555097e-33j, | ||
-2.0594021562561332e-01 + 2.2863956908382538e-17j, | ||
-5.8325863096557049e-17 + 1.6949718400585382e-18j, | ||
], | ||
[ | ||
2.6734481396039929e-32 + 1.7155650257063576e-35j, | ||
-5.8325863096557049e-17 + 1.6949718400585382e-18j, | ||
4.4171453199503476e-02 + 1.0022350742842835e-02j, | ||
], | ||
] | ||
) | ||
d, U = takagi(A) | ||
assert np.allclose(A, U @ np.diag(d) @ U.T) | ||
assert np.allclose(U @ np.conjugate(U).T, np.eye(len(U))) | ||
assert np.all(d >= 0) | ||
|
||
|
||
def test_real_degenerate(): | ||
"""Verify that the Takagi decomposition returns a matrix that is unitary and results in a | ||
correct decomposition when input a real but highly degenerate matrix. This test uses the | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd suggest you move this
rtol
as an optional parameter in the signature of the function.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have moved rtol as an optional parameter of takagi function.