-
Notifications
You must be signed in to change notification settings - Fork 104
Add a phased classical action for SelectedMajoranaFermion #1778
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
base: main
Are you sure you want to change the base?
Changes from 12 commits
8a546b1
7d9760f
a80e56b
17b197c
6ccedf1
e78143b
0ab0153
68e1c34
8ddf870
60e02f4
9305db5
b133c37
a0ba13c
8811944
059c26e
ba4c7df
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 | ||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -13,7 +13,7 @@ | |||||||||||||||||||||||||||||||
| # limitations under the License. | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| from functools import cached_property | ||||||||||||||||||||||||||||||||
| from typing import Iterator, Sequence, Tuple, Union | ||||||||||||||||||||||||||||||||
| from typing import Dict, Iterator, Sequence, Tuple, Union | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| import attrs | ||||||||||||||||||||||||||||||||
| import cirq | ||||||||||||||||||||||||||||||||
|
|
@@ -25,6 +25,7 @@ | |||||||||||||||||||||||||||||||
| from qualtran._infra.data_types import BQUInt | ||||||||||||||||||||||||||||||||
| from qualtran._infra.gate_with_registers import total_bits | ||||||||||||||||||||||||||||||||
| from qualtran.bloqs.multiplexers.unary_iteration_bloq import UnaryIterationGate | ||||||||||||||||||||||||||||||||
| from qualtran.simulation.classical_sim import ClassicalValT | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| @attrs.frozen | ||||||||||||||||||||||||||||||||
|
|
@@ -137,5 +138,36 @@ def nth_operation( # type: ignore[override] | |||||||||||||||||||||||||||||||
| yield self.target_gate(target[target_idx]).controlled_by(control) | ||||||||||||||||||||||||||||||||
| yield cirq.CZ(*accumulator, target[target_idx]) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| def on_classical_vals(self, **vals) -> Dict[str, 'ClassicalValT']: | ||||||||||||||||||||||||||||||||
| if self.target_gate != cirq.X: | ||||||||||||||||||||||||||||||||
| return NotImplemented | ||||||||||||||||||||||||||||||||
| if len(self.control_registers) > 1 or len(self.selection_registers) > 1: | ||||||||||||||||||||||||||||||||
| return NotImplemented | ||||||||||||||||||||||||||||||||
|
Collaborator
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. is this restriction necessary?
Contributor
Author
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'm not sure - it is hard for me to understand what this gate does in the general case. Is my understanding in #1699 (comment) correct?
Contributor
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. The current check
Suggested change
Contributor
Author
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. Done. |
||||||||||||||||||||||||||||||||
| control_name = self.control_registers[0].name | ||||||||||||||||||||||||||||||||
| control = vals[control_name] | ||||||||||||||||||||||||||||||||
| selection_name = self.selection_registers[0].name | ||||||||||||||||||||||||||||||||
| selection = vals[selection_name] | ||||||||||||||||||||||||||||||||
| target = vals['target'] | ||||||||||||||||||||||||||||||||
| if control: | ||||||||||||||||||||||||||||||||
| max_selection = self.selection_registers[0].dtype.iteration_length_or_zero() - 1 | ||||||||||||||||||||||||||||||||
| target = (2 ** (max_selection - selection)) ^ target | ||||||||||||||||||||||||||||||||
|
Comment on lines
+156
to
+157
Collaborator
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. can you add a comment describing how this logic works
Contributor
Author
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. Done.
Collaborator
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. Can you be even more explicit with how the bit twiddling operations correspond to the promised action of the subroutine "flip the selection-th bit in target. the selection-th bit is addressed with the unsigned integer 2^(N - i) in our big endian convention" or something like that
Contributor
Author
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. Done.
Comment on lines
+155
to
+157
Contributor
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. If
Suggested change
Contributor
Author
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. Having selection > max_selection indicates an invalid input vals, so it is working as intended for there to be an error. |
||||||||||||||||||||||||||||||||
| return {control_name: control, selection_name: selection, 'target': target} | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| def basis_state_phase(self, **vals) -> Union[complex, None]: | ||||||||||||||||||||||||||||||||
| if self.target_gate != cirq.X: | ||||||||||||||||||||||||||||||||
| return None | ||||||||||||||||||||||||||||||||
| if len(self.control_registers) > 1 or len(self.selection_registers) > 1: | ||||||||||||||||||||||||||||||||
| return None | ||||||||||||||||||||||||||||||||
|
Contributor
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. Similar to
Suggested change
Contributor
Author
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. Done. |
||||||||||||||||||||||||||||||||
| control_name = self.control_registers[0].name | ||||||||||||||||||||||||||||||||
| control = vals[control_name] | ||||||||||||||||||||||||||||||||
| selection_name = self.selection_registers[0].name | ||||||||||||||||||||||||||||||||
| selection = vals[selection_name] | ||||||||||||||||||||||||||||||||
| target = vals['target'] | ||||||||||||||||||||||||||||||||
| if control: | ||||||||||||||||||||||||||||||||
| max_selection = self.selection_registers[0].dtype.iteration_length_or_zero() - 1 | ||||||||||||||||||||||||||||||||
| num_phases = (target >> (max_selection - selection + 1)).bit_count() | ||||||||||||||||||||||||||||||||
| return 1 if (num_phases % 2) == 0 else -1 | ||||||||||||||||||||||||||||||||
|
Comment on lines
+172
to
+187
Contributor
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. If
Suggested change
Contributor
Author
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. Same as above. |
||||||||||||||||||||||||||||||||
| return 1 | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| def __str__(self): | ||||||||||||||||||||||||||||||||
| return f'SelectedMajoranaFermion({self.target_gate})' | ||||||||||||||||||||||||||||||||
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.
In combination with basis_state_phase, this should be able to support
Zas well. Z imparts a phase (and leaves the computational basis states unaffected)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 now added Z.