Skip to content

Commit

Permalink
add notebook
Browse files Browse the repository at this point in the history
  • Loading branch information
anurudhp committed Nov 1, 2024
1 parent 2d0c853 commit 3793bb8
Show file tree
Hide file tree
Showing 2 changed files with 207 additions and 0 deletions.
201 changes: 201 additions & 0 deletions qualtran/bloqs/mcmt/specialized_ctrl.ipynb
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
}
6 changes: 6 additions & 0 deletions qualtran/bloqs/mcmt/specialized_ctrl_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
SpecializeOnCtrlBit,
)
from qualtran.resource_counting import CostKey, GateCounts, get_cost_value, QECGatesCost
import qualtran.testing as qlt_testing


def _keep_and(b):
Expand Down Expand Up @@ -234,3 +235,8 @@ def build_composite_bloq(self, bb: 'BloqBuilder', **soqs: 'SoquetT') -> dict[str
def test_get_ctrl_system(ctrl_reg_name: str, target_reg_name: str):
bloq = TestBloqWithDecompose(ctrl_reg_name, target_reg_name).controlled()
_ = bloq.decompose_bloq().flatten()


@pytest.mark.notebook
def test_notebook():
qlt_testing.execute_notebook('specialized_ctrl')

0 comments on commit 3793bb8

Please sign in to comment.