Skip to content
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

negativity_cost_fn and density qnode functions #53

Merged
merged 2 commits into from
Aug 3, 2024

Conversation

m-bhatia
Copy link
Contributor

@m-bhatia m-bhatia commented Dec 1, 2023

No description provided.

@bdoolittle bdoolittle self-requested a review December 1, 2023 14:26
Copy link
Member

@bdoolittle bdoolittle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @m-bhatia, these changes look great and will make a fine addition to qnetvo! I've left a few comments detailing some changes to the existing code. In addition to these changes:

  1. Please add unit tests for each of the functions you add (density_matrix_qnode, negativity_cost_fn, and partial_transpose). The tests are located in the test directory and the naming and format should be pretty straightforward.
  2. We use black to autoformat code. To pass the styling checks, please run black -l 100 src test to reformat your changes to conform to the black styling guidelines.

Let me know if you have any questions, thanks again for your contribution!

P.S. The qnetvo contributing guidelines might be helpful.

bra_indices[-i], ket_indices[-i] = ket_indices[-i], bra_indices[-i]

einsum_str = ''.join(indices) + '->' + ''.join(bra_indices + ket_indices)
result = np.einsum(einsum_str, dm_reshaped)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's use qml.math.einsum here if it works


density_qnode = reduced_density_matrix_qnode(network_ansatz, wires, **qnode_kwargs)

def partial_transpose(dm, m, n):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two things:

  1. the partial_transpose function should have a docstring.
  2. we should move this function out of negativity_cost_fn because it is very basic and could be used broadly. At this point, the utilities.py is probably the best place for it to go.

dims = [2] * (2 * (m + n))
dm_reshaped = dm.reshape(dims)

indices = list('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')[:2 * (m + n)]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's throw a ValueError for the case when m + n > 52, the code won't behave as expected in this case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed the partial_transpose function so that it no longer has this limitation

:rtype: Function
"""

if len(wires) != m + n:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

def negativity_cost_fn(network_ansatz, m, n, wires, qnode_kwargs={}):
"""Constructs an ansatz-specific negativity cost function.

Negativity can be used to identify if two subsystems :math:`A` and :math:`B` are entangled, through the PPT criterion. Negativity is an upper bound for distillable entanglement.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there is an arxiv paper for this or other good online resource, please add a link

:returns: A cost function ``negativity_cost(*network_settings)`` parameterized by
the ansatz-specific scenario settings.
:rtype: Function
"""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a :raises ValueError: in the docstring to document the constraints on m and n

As an example, you can see docstring for the qnetvo.NetworkAnsatz class.

@qml.qnode(qml.device(**network_ansatz.dev_kwargs), **qnode_kwargs)
def circuit(settings):
network_ansatz.fn(settings)
return qml.density_matrix(wires=network_ansatz.network_wires)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return qml.density_matrix(wires=network_ansatz.network_wires)
return qml.density_matrix(wires=network_ansatz.layers_wires[-1])

In general, there may be ancillary wires in the network that aren't measured. To be more consistent with other qnodes use network_ansatz.layers_wires[-1]. The current convention in qnetvo is for all measurement nodes to be placed in the final layer, so this will get the density matrix on all measurement wires.

Comment on lines 120 to 140
def reduced_density_matrix_qnode(network_ansatz, wires, **qnode_kwargs):
"""Constructs a qnode that computes the density matrix in the computational basis
across all specified wires.

:param network_ansatz: A ``NetworkAnsatz`` class specifying the quantum network simulation.
:type network_ansatz: NetworkAnsatz

:param wires: The wires on which the node operates.
:type wires: list[int]

:returns: A qnode called as ``qnode(settings)`` for evaluating the reduced density matrix of the
network ansatz.
:rtype: ``pennylane.QNode``
"""

@qml.qnode(qml.device(**network_ansatz.dev_kwargs), **qnode_kwargs)
def circuit(settings):
network_ansatz.fn(settings)
return qml.density_matrix(wires)

return circuit
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should just wrap this into density_matrix_qnode because it is the same functionality. To do this, we'll add a wires kwarg as density_matrix_qnode(network_ansatz, wires=None, **qnode_kwargs). Then, we add the condition wires = network_ansatz.layers_wires[-1] if wires == None else wires

… functions with test cases

updated functionality of partial transpose so it works with any input size
@m-bhatia
Copy link
Contributor Author

m-bhatia commented Aug 2, 2024

I made the requested changes, as well as edited the partial_transpose function so it can work for larger density matrices. The qNetVO contributing guidelines were very helpful. Thank you!

Copy link
Member

@bdoolittle bdoolittle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great Changes @m-bhatia , Thanks for getting this done.

I made a few addittions to fix some formatting issues with the docs, but everything else looked super solid. I'll merge once the tests pass. This functionality will be available in qnetvo. v0.4.5

@bdoolittle bdoolittle merged commit f873eb9 into ChitambarLab:main Aug 3, 2024
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants