-
Notifications
You must be signed in to change notification settings - Fork 48
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Simplify
QubitizationWalkOperator
: remove specializations for contr…
…ol/adjoint and use defaults instead (#1481) * simplify walk operator * add ctrl systems for various bloqs * special adjoint wrapper for bloqs with specialized ctrl * fix ctrl sys for `CZ` and `CY`: target register names of uncontrolled and controlled versions do not match * nb * fix bug in select hubbard (`0` ctrl not supported by decomp, so fallback to default) * move new adjoint bloq to `mcmt.specialized_ctrl` * add tests for adjoint * imports and mypy * `Y, Z`: explicitly implement ctrl sys (avoids AutoPartition in decomp) * docstring `AdjointWithSpecializedCtrl` * add notebook * format * simplify ctrl sys for CZ, CY * hubbard: not impl error on cv=0
- Loading branch information
Showing
13 changed files
with
460 additions
and
86 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,201 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "markdown", | ||
"id": "0", | ||
"metadata": {}, | ||
"source": [ | ||
"## Bloqs with specialized controlled implementations\n", | ||
"\n", | ||
"In some cases, a bloq may have a specialized singly-controlled version (e.g. `LCUBlockEncoding`).\n", | ||
"Qualtran provides a convenience methods `get_ctrl_system_1bit_cv` and `get_ctrl_system_1bit_cv_from_bloqs` to override the `get_ctrl_system`. These methods ensure that multiply-controlled bloqs are correctly reduced to the provided singly-controlled variants.\n", | ||
"\n", | ||
"- `get_ctrl_system_1bit_cv_from_bloqs` - Override when a specialized controlled-by-1 implementation is available.\n", | ||
"- `get_ctrl_system_1bit_cv` - Override when both specialized controlled-by-1 and controlled-by-0 implementations are available.\n", | ||
"\n", | ||
"The following demonstrates an example for a bloq implementing $T^\\dagger X T$, where the controlled version only needs to control the $X$." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"id": "1", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"import attrs\n", | ||
"from qualtran import Bloq, BloqBuilder, Soquet, SoquetT, Signature, CtrlSpec, AddControlledT\n", | ||
"from qualtran.bloqs.basic_gates import TGate, XGate, CNOT\n", | ||
"\n", | ||
"\n", | ||
"@attrs.frozen\n", | ||
"class BloqWithSpecializedCtrl(Bloq):\n", | ||
" \"\"\"Bloq implementing $T^\\dagger X T$\"\"\"\n", | ||
" is_controlled: bool = False\n", | ||
"\n", | ||
" @property\n", | ||
" def signature(self) -> 'Signature':\n", | ||
" n_ctrls = 1 if self.is_controlled else 0\n", | ||
" return Signature.build(ctrl=n_ctrls, q=1)\n", | ||
" \n", | ||
" def build_composite_bloq(self, bb: 'BloqBuilder', q: 'Soquet', **soqs) -> dict[str, 'SoquetT']:\n", | ||
" ctrl = soqs.pop('ctrl', None)\n", | ||
" \n", | ||
" q = bb.add(TGate(), q=q)\n", | ||
" if self.is_controlled:\n", | ||
" ctrl, q = bb.add(CNOT(), ctrl=ctrl, target=q)\n", | ||
" else:\n", | ||
" ctrl, q = bb.add(XGate(), ctrl=ctrl, target=q)\n", | ||
" q = bb.add(TGate().adjoint(), q=q)\n", | ||
" \n", | ||
" out_soqs = {'q': q}\n", | ||
" if ctrl:\n", | ||
" out_soqs |= {'ctrl': ctrl}\n", | ||
" return out_soqs\n", | ||
" \n", | ||
" def get_ctrl_system(self, ctrl_spec: 'CtrlSpec') -> tuple['Bloq', 'AddControlledT']:\n", | ||
" from qualtran.bloqs.mcmt.specialized_ctrl import get_ctrl_system_1bit_cv_from_bloqs\n", | ||
"\n", | ||
" return get_ctrl_system_1bit_cv_from_bloqs(\n", | ||
" self,\n", | ||
" ctrl_spec,\n", | ||
" current_ctrl_bit=1 if self.is_controlled else None,\n", | ||
" bloq_with_ctrl=attrs.evolve(self, is_controlled=True),\n", | ||
" ctrl_reg_name='ctrl',\n", | ||
" )" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"id": "2", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"from qualtran.drawing import show_bloq, show_call_graph\n", | ||
"\n", | ||
"bloq = BloqWithSpecializedCtrl().controlled().controlled()\n", | ||
"show_bloq(bloq.decompose_bloq().flatten())\n", | ||
"show_call_graph(bloq)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "3", | ||
"metadata": {}, | ||
"source": [ | ||
"## Propagating the Adjoint\n", | ||
"\n", | ||
"In the above bloq, calling controlled on the adjoint does not push the controls into the bloq, and therefore does not use the specialized implementation provided." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"id": "4", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"BloqWithSpecializedCtrl().adjoint().controlled()" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "5", | ||
"metadata": {}, | ||
"source": [ | ||
"This can be fixed by overriding the adjoint using a special wrapper for this case - `AdjointWithSpecializedCtrl`. This is a subclass of the default `Adjoint` metabloq, and ensures that single-qubit controls are pushed into the underlying bloq." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"id": "6", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"@attrs.frozen\n", | ||
"class BloqWithSpecializedCtrlWithAdjoint(Bloq):\n", | ||
" \"\"\"Bloq implementing $T^\\dagger X T$\"\"\"\n", | ||
" is_controlled: bool = False\n", | ||
"\n", | ||
" @property\n", | ||
" def signature(self) -> 'Signature':\n", | ||
" n_ctrls = 1 if self.is_controlled else 0\n", | ||
" return Signature.build(ctrl=n_ctrls, q=1)\n", | ||
" \n", | ||
" def build_composite_bloq(self, bb: 'BloqBuilder', q: 'Soquet', **soqs) -> dict[str, 'SoquetT']:\n", | ||
" ctrl = soqs.pop('ctrl', None)\n", | ||
" \n", | ||
" q = bb.add(TGate(), q=q)\n", | ||
" if self.is_controlled:\n", | ||
" ctrl, q = bb.add(CNOT(), ctrl=ctrl, target=q)\n", | ||
" else:\n", | ||
" ctrl, q = bb.add(XGate(), ctrl=ctrl, target=q)\n", | ||
" q = bb.add(TGate().adjoint(), q=q)\n", | ||
" \n", | ||
" out_soqs = {'q': q}\n", | ||
" if ctrl:\n", | ||
" out_soqs |= {'ctrl': ctrl}\n", | ||
" return out_soqs\n", | ||
" \n", | ||
" def get_ctrl_system(self, ctrl_spec: 'CtrlSpec') -> tuple['Bloq', 'AddControlledT']:\n", | ||
" from qualtran.bloqs.mcmt.specialized_ctrl import get_ctrl_system_1bit_cv_from_bloqs\n", | ||
"\n", | ||
" return get_ctrl_system_1bit_cv_from_bloqs(\n", | ||
" self,\n", | ||
" ctrl_spec,\n", | ||
" current_ctrl_bit=1 if self.is_controlled else None,\n", | ||
" bloq_with_ctrl=attrs.evolve(self, is_controlled=True),\n", | ||
" ctrl_reg_name='ctrl',\n", | ||
" )\n", | ||
"\n", | ||
" def adjoint(self):\n", | ||
" from qualtran.bloqs.mcmt.specialized_ctrl import AdjointWithSpecializedCtrl, SpecializeOnCtrlBit\n", | ||
" \n", | ||
" return AdjointWithSpecializedCtrl(self, SpecializeOnCtrlBit.ONE)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"id": "7", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"BloqWithSpecializedCtrlWithAdjoint().adjoint().controlled()" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"id": "8", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"assert BloqWithSpecializedCtrlWithAdjoint().adjoint().controlled() == BloqWithSpecializedCtrlWithAdjoint(is_controlled=True).adjoint()" | ||
] | ||
} | ||
], | ||
"metadata": { | ||
"kernelspec": { | ||
"display_name": "Python 3 (ipykernel)", | ||
"language": "python", | ||
"name": "python3" | ||
}, | ||
"language_info": { | ||
"codemirror_mode": { | ||
"name": "ipython", | ||
"version": 3 | ||
}, | ||
"file_extension": ".py", | ||
"mimetype": "text/x-python", | ||
"name": "python", | ||
"nbconvert_exporter": "python", | ||
"pygments_lexer": "ipython3", | ||
"version": "3.11.9" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 5 | ||
} |
Oops, something went wrong.