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

Measureable channels and mixtures #4194

Merged
merged 20 commits into from
Aug 4, 2021
Merged

Measureable channels and mixtures #4194

merged 20 commits into from
Aug 4, 2021

Conversation

95-martin-orion
Copy link
Collaborator

@95-martin-orion 95-martin-orion commented Jun 11, 2021

Partially addresses #3241; qudit and non-square operator support is not part of this PR. Design is presented in this RFC.

KrausChannel and MatrixMixture both serve two purposes:

  • Provide a base type for users to create their own noisy channels (and mixtures) without creating a new type
  • Allow channels (and mixtures) to capture the selected operator index in a measurement result

The changes to act_on_state_vector_args.py enable the second item; everything else in this PR was already possible in Cirq, but previously required users to define their own classes to make use of it.

@95-martin-orion 95-martin-orion requested review from cduck, vtomole and a team as code owners June 11, 2021 21:28
@95-martin-orion 95-martin-orion requested a review from viathor June 11, 2021 21:28
@google-cla google-cla bot added the cla: yes Makes googlebot stop complaining. label Jun 11, 2021
@95-martin-orion
Copy link
Collaborator Author

Pinging @viathor for review. This is somewhat related to the recent cirq.channel -> cirq.kraus renaming; I could see cirq.channel being repurposed to return a KrausChannel if we wanted a protocol that returns a channel-like Cirq operation.

@95-martin-orion
Copy link
Collaborator Author

Discussed in Cirq internal sync: needs documentation to make this feature visible to users.

@review-notebook-app
Copy link

Check out this pull request on  ReviewNB

See visual diffs & provide feedback on Jupyter Notebooks.


Powered by ReviewNB

@95-martin-orion
Copy link
Collaborator Author

Used git push --force to correct a bad merge state.

@95-martin-orion
Copy link
Collaborator Author

It's unclear to me what's causing the KeyError: 'language_info' in the notebook tests. I was able to find this issue with a similar error, but it seems to be tied to ipykernel v5.4.0 (we use v5.3.4).

@95-martin-orion
Copy link
Collaborator Author

Pinging @viathor for review. Whatever fix is needed for the failing test shouldn't affect the overall shape of this PR, so you can safely ignore it - unless you happen to know a fix, in which case please don't ignore it 😛

@95-martin-orion 95-martin-orion linked an issue Jul 8, 2021 that may be closed by this pull request
@95-martin-orion
Copy link
Collaborator Author

Re-requesting review - the failing check has been resolved now (seems to have been a notebook parsing issue)

Copy link
Collaborator

@MichaelBroughton MichaelBroughton left a comment

Choose a reason for hiding this comment

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

These look good up to some minor tweaks in the code. Looking through #2771 it feels like we should definitely have a flag when these are built like: validate=True which indicates whether or not any validation steps should be done (linalg.is_unitary for matrixmixture and linalg.is_cptp for krauschannel). Given how short a fix for #2771 is, would you mind adding something like cirq.linalg.is_cptp ?

cirq-core/cirq/ops/kraus_channel.py Show resolved Hide resolved
cirq-core/cirq/ops/kraus_channel.py Outdated Show resolved Hide resolved
cirq-core/cirq/ops/kraus_channel.py Show resolved Hide resolved
cirq-core/cirq/ops/kraus_channel.py Outdated Show resolved Hide resolved
cirq-core/cirq/ops/matrix_mixture.py Outdated Show resolved Hide resolved
cirq-core/cirq/ops/matrix_mixture.py Outdated Show resolved Hide resolved
cirq-core/cirq/ops/matrix_mixture.py Outdated Show resolved Hide resolved
cirq-core/cirq/protocols/json_test_data/MatrixMixture.repr Outdated Show resolved Hide resolved
cirq-core/cirq/ops/matrix_mixture.py Outdated Show resolved Hide resolved
cirq-core/cirq/ops/kraus_channel.py Outdated Show resolved Hide resolved
cirq-core/cirq/ops/kraus_channel.py Show resolved Hide resolved
cirq-core/cirq/ops/kraus_channel.py Outdated Show resolved Hide resolved
@95-martin-orion
Copy link
Collaborator Author

Addressed review comments and updated the description: #3241 is not fully fixed by this change, as it does not include support for qudits or non-square operators. Qudit support should be fairly straightforward, but non-square operators will require deeper changes to Cirq.

Copy link
Collaborator

@viathor viathor left a comment

Choose a reason for hiding this comment

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

A few more comments, mostly about equality checks.

raise ValueError('KrausChannel must have at least one operation.')
num_qubits = np.log2(kraus_ops[0].size) / 2
if not num_qubits.is_integer():
raise ValueError(
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should probably also check that kraus_ops[0].shape[0] == kraus_ops[0].shape[1].

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done. Also updated a few adjacent checks to use shape instead of size.

return NotImplemented
if self._key != other._key:
return False
return np.allclose(self._kraus_ops, other._kraus_ops)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Kraus representation is not unique, so when measurement key is unspecified this check is insufficient. Instead, we should compare, e.g. the Choi representations which determine the channel uniquely. OTOH, if the measurement key is specified, then different sets of Kraus operators that give rise to the same Choi will generally describe different channels and then the current logic almost applies. I say "almost" since there is the caveat that one could apply any complex phase factor to the Kraus operators and get equivalent KrausChannel.

I think we should do something like this:

if self._key is None and other._key is None:
    return np.allclose(cirq.kraus_to_choi(self._kraus_ops), cirq.kraus_to_choi(other._kraus_ops))
return all(cirq.equal_up_to_global_phase(k1, k2) for k1, k2 in zip(self._kraus_ops, other._kraus_ops))

This assumes that if measurement key is specified then KrausChannel instances that differ in the order of otherwise equivalent Kraus operators are to be considered unequal. This makes sense since they generate different measurement outcomes.

It'd be good to add unit tests for both cases above. You can use for example these two sets of Kraus operators for the phase damping channel:

  1. I/2 and Z/2.
  2. [[1, 0], [0, 0]] and [[0, 0], [0, 1]].

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is a reasonable operation to have, but I don't think it should be part of the __eq__ operator. It's effectively possible to add a key to a channel with the from_channel method, and calling that method with equal sets of parameters should return equal results. Would a separate method (e.g. equivalent_behavior) be acceptable?

In either case, I'll update the current __eq__ method to use equal_up_to_global_phase.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yes, defining a separate method is definitely fine (and TODO is also fine), but please add a comment to tell users that KrausChannel instances that describe the same linear map may be unequal if they're specified via different Kraus operators.

If we go this route then we should probably leave this as is and not use equal_up_to_global_phase. Otherwise it feels like a half-baked attempt at "behavioral" equality (global phase freedom is just a special case of unitary freedom in Kraus representation which is given by diagonal unitaries).

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Added a TODO for this and left the np.allclose in __eq__.

cirq-core/cirq/ops/mixed_unitary_channel.py Outdated Show resolved Hide resolved
cirq-core/cirq/ops/mixed_unitary_channel.py Show resolved Hide resolved
return MixedUnitaryChannel(mixture=list(protocols.mixture(mixture)), key=key)

def __eq__(self, other) -> bool:
if not isinstance(other, MixedUnitaryChannel):
Copy link
Collaborator

Choose a reason for hiding this comment

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

What should be the result of equality check on a KrausChannel and a MixedUnitaryChannel that define the same underlying quantum channel?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I'd be hesitant to return true for such a comparison. The two may have the same effect on the circuit (and thus these should return true for the equivalent_behavior method described above), but there are minor differences between the objects themselves: KrausChannel.has_mixture() is false even if the channel describes a mixture, and MixedUnitaryChannel has better performance due to not needing to calculate operator probabilities.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Good point. I like the equivalent_behavior idea.

@95-martin-orion
Copy link
Collaborator Author

Immediate follow-up items:

  • support qudit operations with these types
  • add equivalent_channel protocol for comparing channel Choi representations

@95-martin-orion 95-martin-orion requested a review from viathor August 2, 2021 20:30
@95-martin-orion
Copy link
Collaborator Author

@MichaelBroughton, do you have any further comments?

Copy link
Collaborator

@MichaelBroughton MichaelBroughton left a comment

Choose a reason for hiding this comment

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

LGTM

@MichaelBroughton MichaelBroughton added the automerge Tells CirqBot to sync and merge this PR. (If it's running.) label Aug 4, 2021
@CirqBot CirqBot added the front_of_queue_automerge CirqBot uses this label to indicate (and remember) what's being merged next. label Aug 4, 2021
@CirqBot CirqBot merged commit f7b882c into master Aug 4, 2021
@CirqBot CirqBot removed the automerge Tells CirqBot to sync and merge this PR. (If it's running.) label Aug 4, 2021
@CirqBot CirqBot deleted the cirq-custom-channel branch August 4, 2021 16:11
@CirqBot CirqBot removed the front_of_queue_automerge CirqBot uses this label to indicate (and remember) what's being merged next. label Aug 4, 2021
rht pushed a commit to rht/Cirq that referenced this pull request May 1, 2023
As requested in quantumlib#4194. Can be used for quantumlib#2271.

This predicate is meant to be invoked when constructing a channel to verify that the provided Kraus operators actually describe a valid quantum channel. Recommendations for cleaner `is_cptp` behavior or additional test cases are welcome.
rht pushed a commit to rht/Cirq that referenced this pull request May 1, 2023
_Partially_ addresses quantumlib#3241; qudit and non-square operator support is not part of this PR. Design is presented in [this RFC](https://tinyurl.com/cirq-custom-channel).

`KrausChannel` and `MatrixMixture` both serve two purposes:
- Provide a base type for users to create their own noisy channels (and mixtures) without creating a new type
- Allow channels (and mixtures) to capture the selected operator index in a measurement result

The changes to `act_on_state_vector_args.py` enable the second item; everything else in this PR was already possible in Cirq, but previously required users to define their own classes to make use of it.
harry-phasecraft pushed a commit to PhaseCraft/Cirq that referenced this pull request Oct 31, 2024
As requested in quantumlib#4194. Can be used for quantumlib#2271.

This predicate is meant to be invoked when constructing a channel to verify that the provided Kraus operators actually describe a valid quantum channel. Recommendations for cleaner `is_cptp` behavior or additional test cases are welcome.
harry-phasecraft pushed a commit to PhaseCraft/Cirq that referenced this pull request Oct 31, 2024
_Partially_ addresses quantumlib#3241; qudit and non-square operator support is not part of this PR. Design is presented in [this RFC](https://tinyurl.com/cirq-custom-channel).

`KrausChannel` and `MatrixMixture` both serve two purposes:
- Provide a base type for users to create their own noisy channels (and mixtures) without creating a new type
- Allow channels (and mixtures) to capture the selected operator index in a measurement result

The changes to `act_on_state_vector_args.py` enable the second item; everything else in this PR was already possible in Cirq, but previously required users to define their own classes to make use of it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cla: yes Makes googlebot stop complaining.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Expose Kraus operator selection in simulators
4 participants