-
Notifications
You must be signed in to change notification settings - Fork 65
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
cb norm #157
cb norm #157
Conversation
…t the values are not very far apart, help required. The cb trace norm is also known as the diamond norm, therefore renamin former diamond norm to diamond norm distance. np.linalg.norm is also applicable for matrices.
@@ -0,0 +1,22 @@ | |||
import numpy as np | |||
from toqito.channels import dephasing | |||
def test_diamond_norm_quantum_channel(): |
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.
We should place in spacing between the functions and between the import statements and the functions. Refer to the other test files to see how this is done.
def test_diamond_norm_quantum_channel(): | ||
"""The diamond norm of a quantum channel is 1""" | ||
phi = dephasing(1) | ||
np.testing.assert_equal(np.isclose(diamond_norm(phi), 1, atol=1e-3), True) |
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.
Since this function will return 1
in the event that the channel is quantum, I wonder if we need the isclose
statement.
:return: The completely bounded trace norm of the channel | ||
""" | ||
|
||
elif is_quantum_channel(phi): |
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.
An elif
should follow an if
, I'm not sure if we want to start this chain of elif
statements without starting it with an if
.
from toqito.state_metrics import trace_norm | ||
import cvxpy as cp | ||
|
||
def diamond_norm(phi: np.ndarray)-> float: |
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.
Should the function name here be completely_bounded_trace_norm
?
@@ -3,7 +3,7 @@ | |||
import numpy as np | |||
|
|||
|
|||
def diamond_norm(choi_1: np.ndarray, choi_2: np.ndarray) -> float: | |||
def diamond_norm_distance(choi_1: np.ndarray, choi_2: np.ndarray) -> float: |
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.
Since the diamond_norm
function is already in the channel_metrics/
folder, it's already implied that this is a distance metric. I would opt to keep the name diamond_norm
over diamond_norm_distance
(same with the file name as well, etc.)
"Compute the completely bounded spectral norm of a quantum channel" | ||
from toqito.channel_ops import dual_channel | ||
from toqito.channel_metrics import completely_bounded_trace_norm | ||
def cb_spectral_norm(phi): |
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.
To maintain convention with the rest of the project, I would opt to rename the function to completely_bounded_spectral_norm
. It is a bit longer, but more explicit, and if the user wishes to condense the name on import, they can do that if they wish.
constraints += [y1 >> 0] | ||
A = cp.bmat([[y0, -phi], [-np.conj(phi).T, y1]]) | ||
constraints += [ A >> 0 ] | ||
objective = cp.Minimize( cp.atoms.norm_inf(cp.partial_trace(y0, dims= (dim,dim), axis = 1)) |
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 should really configure some linting pre-commit hooks to catch these things, but as a minor nitpick, dims=(dim,dim)
instead of dims = (dim, dim)
.
phi = np.array([[1, 2, 3], [4, 5, 6]]) | ||
diamond_norm(phi) | ||
|
||
if __name__ == "__main__": |
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.
It seems odd to me that the test_completely_bounded_trace_norm
file is testing the diamond norm functionality, right? We probably should also add explicit tests for the completely_bounded_spectral_norm
as well.
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 wanted to call completely_bounded_trace_norm
diamond norm, as in the Wikipedia article, which is easy to confuse with the diamond norm distance functionality in toqito. But sticking to completely_bounded_trace_norm
is maybe easier in implementation.
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.
Ah, I see where the issue here might be:
- Indeed, the completely bounded trace norm is equivalent to the diamond norm (you are completely correct)
- The
diamond_norm
function as is present ontoqito
computes the SDP for the diamond norm. - My mistake in writing the title of this issue is that I should have specified that this is for the "completely bounded norm" (not just the "completely bounded trace norm").
There shouldn't be too much to change on your end though as the completely bounded norm of a channel is equal to the diamond norm of the dual map.
Does that make sense? Let me know if anything I've said above isn't clear, and I'll be happy to clarify. Thank you again!
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.
According to sec. 4 the SDP for the distance between two channels is simpler than the SDP for the completely bounded trace norm of channels (sec. 3). Have you implemented the SDP of sec. 4 in diamond_norm.py
@vprusso ?
I have not implemented SDP from sec.3, but the QETLAB SDP, which is also cited in Wikipedia. Yet, i have not seen a mathematical derivaton of this formulation.
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.
Hi @AmanieOxana
Right, the diamond_norm.py
file in toqito
(should be) implementing the diamond norm as specified in this QETLAB file:
https://github.com/nathanieljohnston/QETLAB/blob/master/DiamondNorm.m
And, ideally, the completely_bounded_norm.py
file in toqito
for this feature would implement the same functionality as in this file on QETLAB:
https://github.com/nathanieljohnston/QETLAB/blob/master/CBNorm.m
Does that clear things up or have I made things more confusing?
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.
Hi @vprusso,
diamond_norm.py
in toqito
computes the distance between two quantum channels in contrast two DiamondNorm of QETLAB which computes the diamond norm of a single channel. As stated here the SDP for the distance and for the single channel diamond norm are different in nature (comparing sec. 3 and 4). So I do not agree that
diamond_norm.py file in toqito (should be) implementing the diamond norm > as specified in this QETLAB file:
Therefore this pull request includes two files, one for the completely bounded trace norm (aka diamond norm) and for the completely bounded spectral norm (to what you refered as cb norm)
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.
It is a new day and I have a cup of coffee now. I believe (somehow) I missed what you are saying here (which you were saying perfectly clearly before, I just missed it).
I agree with everything you've written above. Thank you for sticking with me and your patience :)
Hi @AmanieOxana . Thank you for your contribution! Added some comments on your diff. Do let me know if you have any questions, and thank you again for making the effort to work on |
Hmm, it might be the case that you are invoking the incorrect |
Hi @vprusso, I corrected the norm in the SDP and a factor 1/2, now the tests work. |
Thanks for the update, @AmanieOxana! Let me know if I can help, and thank you again for the update on this! |
Hi @vprusso, I have found a reference for the SDP. The case where the cb trace norm is the spectral diameter, could hold for mixed unitaries, but I have no specifications for this theorem at hand, that I just found in the qetlab wiki, so I left it out. For the hermitian preserving case, the only simplification I see is that the choi matrix is hermitian, but this does not make the sdp significantly faster. |
tests/test_channel_metrics/test_completely_bounded_trace_norm.py
Outdated
Show resolved
Hide resolved
Co-authored-by: georgios-ts <45130028+georgios-ts@users.noreply.github.com>
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.
Hi @AmanieOxana ,
Thanks for the ping. Overall, looks great! A few nit-pick comments, but excellent overall!
objective = cp.Minimize( cp.norm(cp.partial_trace(y0, dims=(dim,dim), axis = 1)) | ||
+ cp.norm(cp.partial_trace(y1, dims=(dim,dim), axis = 1)) ) | ||
problem = cp.Problem(objective, constraints) | ||
problem.solve(eps=1e-10) |
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.
This keyword will fail if the solver selected is not SCS
. The solver options are listed here:
https://www.cvxpy.org/tutorial/advanced/index.html#setting-solver-options
However, even if one selects the SCS
solver and does the following:
problem.solve(solver="SCS", eps=1e-10)
we get a warning:
tests/test_channel_metrics/test_completely_bounded_trace_norm.py::test_cb_trace_norm_unitaries_channel
/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/cvxpy/problems/problem.py:1337: UserWarning: Solution may be inaccurate. Try another solver, adjusting the solver settings, or solve with verbose=True for more information.
warnings.warn(
As the tolerance of 1e-10
is fairly aggressive. I would suggest ratcheting that back to something lower. I would suggest altering:
problem.solve()
|
||
|
||
def test_cb_trace_norm_unitaries_channel(): | ||
"""The diamond norm of phi = id- U id U* is the diameter of the smallest circle that contains the eigenvalues of U""" |
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.
Nitpick: (period at end of comment):
"""The diamond norm of phi = id- U id U* is the diameter of the smallest circle that contains the eigenvalues of U""" | |
"""The diamond norm of phi = id- U id U* is the diameter of the smallest circle that contains the eigenvalues of U.""" | |
@@ -0,0 +1,33 @@ | |||
"""Tests for completely_bounded_trace_norm""" |
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.
Nitpick (period at end of statement):
"""Tests for completely_bounded_trace_norm""" | |
"""Tests for completely_bounded_trace_norm.""" |
|
||
|
||
def test_cb_trace_norm_quantum_channel(): | ||
"""The diamond norm of a quantum channel is 1""" |
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.
Nitpick (period at end of statement):
"""The diamond norm of a quantum channel is 1""" | |
"""The diamond norm of a quantum channel is 1.""" |
|
||
|
||
def test_cb_trace_norm_unitaries_channel(): | ||
"""The diamond norm of phi = id- U id U* is the diameter of the smallest circle that contains the eigenvalues of U""" |
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.
Nitpick (period at end of statement)
"""The diamond norm of phi = id- U id U* is the diameter of the smallest circle that contains the eigenvalues of U""" | |
"""The diamond norm of phi = id- U id U* is the diameter of the smallest circle that contains the eigenvalues of U.""" |
@@ -0,0 +1,28 @@ | |||
"""Compute the completely bounded spectral norm of a quantum channel""" |
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.
Nitpick (period at end of statement):
"""Compute the completely bounded spectral norm of a quantum channel""" | |
"""Compute the completely bounded spectral norm of a quantum channel.""" |
|
||
def completely_bounded_spectral_norm(phi: np.ndarray) -> float: | ||
r""" | ||
Compute the completely bounded spectral norm of a quantum channel |
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.
Nitpick (period at end of statement):
Compute the completely bounded spectral norm of a quantum channel | |
Compute the completely bounded spectral norm of a quantum channel. |
v = apply_channel(np.eye(dim_Ly), dual_channel(phi)) | ||
return trace_norm(v) | ||
|
||
else: |
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.
Technically, you can remove this else:
statement, as the above conditions will either raise
or return
.
@@ -0,0 +1,65 @@ | |||
"""Compute the completely bounded trace norm of a quantum channel""" |
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.
Nitpick (period at end of statement):
"""Compute the completely bounded trace norm of a quantum channel""" | |
"""Compute the completely bounded trace norm of a quantum channel.""" |
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.
Hi @AmanieOxana ,
Thanks for the ping. Overall, looks great! A few nit-pick comments, but excellent overall!
Co-authored-by: Vincent Russo <vincentrusso1@gmail.com>
Thanks for the review @vprusso. I have changed accordingly. |
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.
Left a few minor nit-pick comments (I promise these are the last :) )
Approved and good to go once those are in! Great job, @AmanieOxana !
"""Tests for completely_bounded_spectral_norm.""" | ||
import numpy as np | ||
|
||
from toqito.channel_metrics.completely_bounded_spectral_norm import completely_bounded_spectral_norm |
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.
We should make sure that in channel_metrics/__init__.py
that we add the following lines:
from toqito.channel_metrics.completely_bounded_spectral_norm import completely_bounded_spectral_norm
from toqito.channel_metrics.completely_bounded_trace_norm import completely_bounded_trace_norm
Then, the import line can be made somewhat more succinct as:
from toqito.channel_metrics.completely_bounded_spectral_norm import completely_bounded_spectral_norm | |
from toqito.channel_metrics import ( | |
completely_bounded_spectral_norm, | |
completely_bounded_trace_norm, | |
) |
import numpy as np | ||
|
||
from toqito.channels.dephasing import dephasing | ||
from toqito.channel_metrics.completely_bounded_trace_norm import completely_bounded_trace_norm |
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.
Assuming you made the __init__.py
alteration, you can change this line as well to:
from toqito.channel_metrics.completely_bounded_trace_norm import completely_bounded_trace_norm | |
from toqito.channel_metrics import completely_bounded_trace_norm |
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.
@vprusso I made this alteration, but this import seems not to work, as not the function but a module is imported. Should I change it to the prior version, or is sth wrong with the init?
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.
Looks like the __init__.py
is incorrect. For clarity, the __init__.py
will look like this:
from toqito.channel_metrics.channel_fidelity import channel_fidelity
from toqito.channel_metrics.diamond_norm import diamond_norm
from toqito.channel_metrics.completely_bounded_spectral_norm import completely_bounded_spectral_norm
from toqito.channel_metrics.completely_bounded_trace_norm import completely_bounded_trace_norm
Then, if you want to refer to these functions in another file, you can write the more condensed:
from toqito.channel_metrics import X
instead of the longer statement
from toqito.channel_metrics.X import X
Does that make sense?
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.
changed it accordingly @vprusso , I though the init could be made also more concise, but should be fine
|
||
from toqito.channels.dephasing import dephasing | ||
from toqito.channel_metrics.completely_bounded_trace_norm import completely_bounded_trace_norm | ||
from toqito.channel_ops.kraus_to_choi import kraus_to_choi |
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.
Likewise:
from toqito.channel_ops.kraus_to_choi import kraus_to_choi | |
from toqito.channel_ops import kraus_to_choi |
:param phi: superoperator as choi matrix | ||
:return: The completely bounded trace norm of the channel | ||
""" | ||
dim_Lx, dim_Ly = phi.shape |
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.
Nitpick: Having capital letters in variable names goes against PEP-8 (link)
Perhaps we can rename dim_Lx
and dim_Ly
to dim_lx
and dim_ly
, respectively? Or do you disagree?
""" | ||
dim_Lx, dim_Ly = phi.shape | ||
|
||
if dim_Lx != dim_Ly: |
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.
The way you are doing this here is completely fine, although toqito
does have a matrix_props.is_square
function that can also be invoked. Your call as to whether or not you'd like to use that here or not.
constraints += [y1 == y1.H] | ||
constraints += [y1 >> 0] | ||
|
||
A = cp.bmat([[y0, -phi], [-phi.conj().T, y1]]) |
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.
One more pedantic PEP-8 suggestion of changing A
to a_var
(or something like that).
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.
Left a few minor nit-pick comments (I promise these are the last :) )
Approved and good to go once those are in! Great job, @AmanieOxana !
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.
Left a few minor nit-pick comments (I promise these are the last :) )
Approved and good to go once those are in! Great job, @AmanieOxana !
Thanks for the quick update, @AmanieOxana . Let me know if I can provide any further help and feel free to let me know when you think this is ready to merge! |
Sure, unless you have no further ideas for simplifications when the channel is unitary or hermitian @vprusso, I think it is ready. |
Excellent! Well, in that case, I will go ahead and put this through! Thank you again, @AmanieOxana, for your contribution to the |
Description
Added cb norm function and test.
I tried the SDP on a unitary, the values are not very far apart, but not equal, help required. resolves #148
The cb trace norm is also known as the diamond norm, therefore renamed former
diamond_norm.py
todiamond_norm_distance.py
. Btwnp.linalg.norm
is also applicable for matrices.Todos
Notable points that this PR has either accomplished or will accomplish.
Questions
Status