-
Notifications
You must be signed in to change notification settings - Fork 100
CSWAP and CMultiSWAP #176
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
CSWAP and CMultiSWAP #176
Changes from all commits
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 |
|---|---|---|
| @@ -0,0 +1,101 @@ | ||
| from functools import cached_property | ||
| from typing import Dict | ||
|
|
||
| import numpy as np | ||
| from attrs import frozen | ||
| from numpy.typing import NDArray | ||
|
|
||
| from cirq_qubitization import TComplexity | ||
| from cirq_qubitization.quantum_graph.bloq import Bloq | ||
| from cirq_qubitization.quantum_graph.composite_bloq import CompositeBloq, Soquet, SoquetT | ||
| from cirq_qubitization.quantum_graph.fancy_registers import FancyRegister, FancyRegisters | ||
|
|
||
|
|
||
| @frozen | ||
| class CSWAP(Bloq): | ||
| """A controlled swap between two-qubits | ||
|
|
||
| Args: | ||
| cv1: Whether the control bit is a positive (1) control. | ||
| Alternatively, control bit can be negatively (0) controlled. | ||
|
|
||
| Registers: | ||
| - ctrl: A two-bit control register. | ||
| - x: first bit to swap | ||
| - y: second bit to swap | ||
| """ | ||
|
|
||
| cv1: int = 1 | ||
|
|
||
| @cached_property | ||
| def registers(self) -> FancyRegisters: | ||
| return FancyRegisters( | ||
| [ | ||
| FancyRegister('ctrl', 1, wireshape=(1,)), | ||
| FancyRegister('x', 1, wireshape=(1,)), | ||
| FancyRegister('y', 1, wireshape=(1,)), | ||
| ] | ||
| ) | ||
|
|
||
| def t_complexity(self) -> 'TComplexity': | ||
| """The `TComplexity` for this bloq. | ||
|
|
||
| C-swap is decomposed into two CNOT + 1 Toffoli. | ||
| Each Toffoli is 7 T-gates, 8 Cliffords, and 0 rotations | ||
| """ | ||
| num_toffoli = 1 | ||
| return TComplexity(t=num_toffoli * 7, clifford=2 + 8 * num_toffoli, rotations=0) | ||
|
|
||
|
|
||
| @frozen | ||
| class CMultiSWAP(Bloq): | ||
| """A controlled n-bit swap between two registers | ||
|
|
||
| Args: | ||
| cv1: Whether the control bit is a positive (1) control. | ||
| Alternatively, control bit can be negatively (0) controlled. | ||
| reg_length: Length of the registers | ||
|
|
||
| Registers: | ||
| - ctrl: A two-bit control register. | ||
| - reg_x: The first register of size n-bits | ||
| - reg_y: The second register of size n-bits | ||
| """ | ||
|
|
||
| reg_length: int = None | ||
| cv1: int = 1 | ||
|
|
||
| @cached_property | ||
| def registers(self) -> FancyRegisters: | ||
| return FancyRegisters( | ||
| [ | ||
| FancyRegister('ctrl', 1, wireshape=(1,)), | ||
| FancyRegister('reg_x', self.reg_length, wireshape=(1,)), | ||
| FancyRegister('reg_y', self.reg_length, wireshape=(1,)), | ||
| ] | ||
| ) | ||
|
|
||
| def pretty_name(self) -> str: | ||
| return "CSWAP" | ||
|
|
||
| def build_composite_bloq( | ||
|
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. have you tried actually decomposing the bloq? That's when it will check the code to see if it results in a well-formed composite bloq. bloq = CMultiSWAP(...)
cbloq = bloq.decompose_bloq()
from cirq_qubitization.jupyter_tools import show_bloq
show_bloq(cbloq)
Collaborator
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 haven't yet..but I will tomorrow! |
||
| self, bb: 'CompositeBloqBuilder', *, cntrl_and_targets: NDArray[Soquet] | ||
|
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. The arguments should match the registers, so you should have three arguments (following the |
||
| ) -> Dict[str, 'SoquetT']: | ||
| """Decomposes multi-cswap `CnSWAP` in-terms of an `CSWAP`""" | ||
| ctrl = (cntrl_and_targets[0],) | ||
| reg_x = cntrl_and_targets[1 : self.reg_length + 1] | ||
| reg_y = cntrl_and_targets[self.reg_length + 1 :] | ||
| returned_x = [] | ||
| returned_y = [] | ||
| for n_idx in range(self.reg_length): | ||
| # overwrite control with same control | ||
| ctrl, out_reg_x, out_reg_y = bb.add( | ||
| CSWAP(cv1=self.cv1), ctrl=ctrl, x=reg_x[n_idx], y=reg_y[n_idx] | ||
| ) | ||
| returned_x.append(out_reg_x) | ||
| returned_y.append(out_reg_y) | ||
|
Comment on lines
+95
to
+96
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. this style is good for making it clear that the output quantum variables are distinct from the input ones. You can be more concise by just overwriting the original array values ctrl, reg_x[n_idx], reg_y[n_idx] = bb.add(...) |
||
| return { | ||
| 'ctrl': np.asarray([ctrl]), | ||
| 'reg_x': np.asarray(returned_x), | ||
| 'reg_y': np.asarray(returned_y), | ||
| } | ||
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.
wireshape=(1,)is equivalent to "list of length 1", which can have a use (usually when writing generic code that works for a list of any size) but is probably inappropriate here.wireshape=tuple()(which is the default argument, so you can just not put it) is analogous to "the item itself -- not in a list".