Skip to content

Commit ca5edd2

Browse files
authored
Add KaiserWindowState bloq to prepare initial state for high confidence QPE (#1331)
* Add KaiserWindowState bloq * Address nits * Remove gate with registers
1 parent 20069b3 commit ca5edd2

10 files changed

Lines changed: 489 additions & 0 deletions

File tree

dev_tools/autogenerate-bloqs-notebooks-v2.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -637,6 +637,13 @@
637637
qualtran.bloqs.phase_estimation.text_book_qpe._CC_TEXTBOOK_PHASE_ESTIMATION_DOC,
638638
],
639639
),
640+
NotebookSpecV2(
641+
title='Kaiser Window State for Quantum Phase Estimation',
642+
module=qualtran.bloqs.phase_estimation.kaiser_window_state,
643+
bloq_specs=[
644+
qualtran.bloqs.phase_estimation.kaiser_window_state._CC_KAISER_WINDOW_STATE_DOC
645+
],
646+
),
640647
NotebookSpecV2(
641648
title='Qubitization Walk Operator',
642649
module=qualtran.bloqs.qubitization.qubitization_walk_operator,

docs/bloqs/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ Bloqs Library
103103
qft/qft_phase_gradient.ipynb
104104
phase_estimation/lp_resource_state.ipynb
105105
phase_estimation/text_book_qpe.ipynb
106+
phase_estimation/kaiser_window_state.ipynb
106107
qubitization/qubitization_walk_operator.ipynb
107108
phase_estimation/qubitization_qpe.ipynb
108109

qualtran/bloqs/phase_estimation/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
from qualtran.bloqs.phase_estimation.kaiser_window_state import KaiserWindowState
1516
from qualtran.bloqs.phase_estimation.lp_resource_state import LPResourceState
1617
from qualtran.bloqs.phase_estimation.qpe_window_state import RectangularWindowState
1718
from qualtran.bloqs.phase_estimation.qubitization_qpe import QubitizationQPE
Lines changed: 284 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,284 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"id": "1cf5d12a",
6+
"metadata": {
7+
"cq.autogen": "title_cell"
8+
},
9+
"source": [
10+
"# Kaiser Window State for Quantum Phase Estimation"
11+
]
12+
},
13+
{
14+
"cell_type": "code",
15+
"execution_count": null,
16+
"id": "5e51f8aa",
17+
"metadata": {
18+
"cq.autogen": "top_imports"
19+
},
20+
"outputs": [],
21+
"source": [
22+
"from qualtran import Bloq, CompositeBloq, BloqBuilder, Signature, Register\n",
23+
"from qualtran import QBit, QInt, QUInt, QAny\n",
24+
"from qualtran.drawing import show_bloq, show_call_graph, show_counts_sigma\n",
25+
"from typing import *\n",
26+
"import numpy as np\n",
27+
"import sympy\n",
28+
"import cirq"
29+
]
30+
},
31+
{
32+
"cell_type": "markdown",
33+
"id": "afc0bf73",
34+
"metadata": {
35+
"cq.autogen": "KaiserWindowState.bloq_doc.md"
36+
},
37+
"source": [
38+
"## `KaiserWindowState`\n",
39+
"Bloq to prepare a Kaiser window state for high confidence Quantum Phase Estimation.\n",
40+
"\n",
41+
"Kaiser window states are optimal to minimize the probability of error outside a given\n",
42+
"confidence interval.\n",
43+
"Given the bitsize $m$ and parameter $\\alpha$, the bloq prepares an $m$-bit state with\n",
44+
"coefficients\n",
45+
"\n",
46+
"$$\n",
47+
" \\sum\\limits_{x=-M}^{M}\\frac{1}{2M} \\frac{I_0\\left(\\pi\\alpha\\sqrt{1-(x/M)^2}\\right)}{I_0\\left(\\pi\\alpha\\right)}\\ket{x}\n",
48+
"$$\n",
49+
"\n",
50+
"where $M = 2^{m-1}$. See Ref[1] for more details.\n",
51+
"\n",
52+
"\n",
53+
"#### Parameters\n",
54+
" - `bitsize`: Number of bits in the control register of QPE.\n",
55+
" - `alpha`: Shape parameter, determines trade-off between main-lobe width and side lobe level. \n",
56+
"\n",
57+
"#### References\n",
58+
" - [Analyzing Prospects for Quantum Advantage in Topological Data Analysis](https://arxiv.org/abs/2209.13581). Berry et. al. (2022). Appendix D\n"
59+
]
60+
},
61+
{
62+
"cell_type": "code",
63+
"execution_count": null,
64+
"id": "a7069b8f",
65+
"metadata": {
66+
"cq.autogen": "KaiserWindowState.bloq_doc.py"
67+
},
68+
"outputs": [],
69+
"source": [
70+
"from qualtran.bloqs.phase_estimation.kaiser_window_state import KaiserWindowState"
71+
]
72+
},
73+
{
74+
"cell_type": "markdown",
75+
"id": "e00a42ff",
76+
"metadata": {
77+
"cq.autogen": "KaiserWindowState.example_instances.md"
78+
},
79+
"source": [
80+
"### Example Instances"
81+
]
82+
},
83+
{
84+
"cell_type": "code",
85+
"execution_count": null,
86+
"id": "07877dd0",
87+
"metadata": {
88+
"cq.autogen": "KaiserWindowState.kaiser_window_state_small"
89+
},
90+
"outputs": [],
91+
"source": [
92+
"kaiser_window_state_small = KaiserWindowState(5, 2)"
93+
]
94+
},
95+
{
96+
"cell_type": "code",
97+
"execution_count": null,
98+
"id": "6fee6ed4",
99+
"metadata": {
100+
"cq.autogen": "KaiserWindowState.kaiser_window_state_symbolic"
101+
},
102+
"outputs": [],
103+
"source": [
104+
"import sympy\n",
105+
"\n",
106+
"kaiser_window_state_symbolic = KaiserWindowState(*sympy.symbols('n, alpha'))"
107+
]
108+
},
109+
{
110+
"cell_type": "markdown",
111+
"id": "c61fccb5",
112+
"metadata": {
113+
"cq.autogen": "KaiserWindowState.graphical_signature.md"
114+
},
115+
"source": [
116+
"#### Graphical Signature"
117+
]
118+
},
119+
{
120+
"cell_type": "code",
121+
"execution_count": null,
122+
"id": "5fdaba20",
123+
"metadata": {
124+
"cq.autogen": "KaiserWindowState.graphical_signature.py"
125+
},
126+
"outputs": [],
127+
"source": [
128+
"from qualtran.drawing import show_bloqs\n",
129+
"show_bloqs([kaiser_window_state_small, kaiser_window_state_symbolic],\n",
130+
" ['`kaiser_window_state_small`', '`kaiser_window_state_symbolic`'])"
131+
]
132+
},
133+
{
134+
"cell_type": "markdown",
135+
"id": "d41cf909",
136+
"metadata": {
137+
"cq.autogen": "KaiserWindowState.call_graph.md"
138+
},
139+
"source": [
140+
"### Call Graph"
141+
]
142+
},
143+
{
144+
"cell_type": "code",
145+
"execution_count": null,
146+
"id": "189bcc85",
147+
"metadata": {
148+
"cq.autogen": "KaiserWindowState.call_graph.py"
149+
},
150+
"outputs": [],
151+
"source": [
152+
"from qualtran.resource_counting.generalizers import ignore_split_join\n",
153+
"kaiser_window_state_small_g, kaiser_window_state_small_sigma = kaiser_window_state_small.call_graph(max_depth=1, generalizer=ignore_split_join)\n",
154+
"show_call_graph(kaiser_window_state_small_g)\n",
155+
"show_counts_sigma(kaiser_window_state_small_sigma)"
156+
]
157+
},
158+
{
159+
"cell_type": "markdown",
160+
"id": "19e7add5-c01c-4441-9f95-99f0475243f7",
161+
"metadata": {},
162+
"source": [
163+
"## Example of QPE comparing different window functions"
164+
]
165+
},
166+
{
167+
"cell_type": "code",
168+
"execution_count": null,
169+
"id": "ef07f4b9-39ec-43d2-a11e-92f926a6e0e4",
170+
"metadata": {},
171+
"outputs": [],
172+
"source": [
173+
"import cirq\n",
174+
"import numpy as np\n",
175+
"from qualtran import BloqBuilder, CompositeBloq\n",
176+
"from qualtran.bloqs.basic_gates import ZPowGate, OneState, OneEffect\n",
177+
"from qualtran.bloqs.phase_estimation import TextbookQPE, RectangularWindowState, LPResourceState, KaiserWindowState"
178+
]
179+
},
180+
{
181+
"cell_type": "code",
182+
"execution_count": null,
183+
"id": "ae2404c0-b51e-4196-905f-94310abac5fa",
184+
"metadata": {},
185+
"outputs": [],
186+
"source": [
187+
"def construct_composite_boq(bloq: TextbookQPE) -> CompositeBloq:\n",
188+
" bb = BloqBuilder()\n",
189+
" q = bb.add(OneState())\n",
190+
" phase_reg, q = bb.add(bloq, q=q)\n",
191+
" bb.add(OneEffect(), q=q)\n",
192+
" return bb.finalize(phase_reg=phase_reg)\n",
193+
"\n",
194+
"def simulate_theta_estimate(bloq: TextbookQPE, n_samples: int) -> float:\n",
195+
" cbloq = construct_composite_boq(bloq)\n",
196+
" final_state = cbloq.tensor_contract()\n",
197+
" samples = cirq.sample_state_vector(final_state, indices=[*range(bloq.m_bits)], repetitions=n_samples)\n",
198+
" thetas = samples.dot(1 << np.arange(samples.shape[-1] - 1, -1, -1))\n",
199+
" return thetas\n",
200+
"\n",
201+
"def holevo_variance(thetas):\n",
202+
" mu = np.mean(np.cos(thetas - theta))\n",
203+
" return 1 / mu**2 - 1"
204+
]
205+
},
206+
{
207+
"cell_type": "code",
208+
"execution_count": null,
209+
"id": "e04196ba-4d8c-481a-a498-a0cf1a991fd6",
210+
"metadata": {},
211+
"outputs": [],
212+
"source": [
213+
"theta = 0.51234\n",
214+
"unitary = ZPowGate(2 * theta)\n",
215+
"n_samples = 100_000\n",
216+
"m = 6\n",
217+
"x_vals = [x / 2**m for x in range(2**m)]\n",
218+
"# Textbook QPE\n",
219+
"qpe_textbook = TextbookQPE(unitary, RectangularWindowState(m))\n",
220+
"thetas_textbook = simulate_theta_estimate(qpe_textbook, n_samples)\n",
221+
"# SinState QPE\n",
222+
"qpe_sinstate = TextbookQPE(unitary, LPResourceState(m))\n",
223+
"thetas_sinstate = simulate_theta_estimate(qpe_sinstate, n_samples)\n",
224+
"# Kaiser QPE\n",
225+
"kaiser_window_state = KaiserWindowState.from_precision_and_delta(3, 1e-2)\n",
226+
"alpha = kaiser_window_state.alpha\n",
227+
"assert kaiser_window_state.bitsize == m, f'{kaiser_window_state.bitsize}'\n",
228+
"qpe_kaiser_state = TextbookQPE(unitary, kaiser_window_state)\n",
229+
"thetas_kaiser_state = simulate_theta_estimate(qpe_kaiser_state, n_samples)"
230+
]
231+
},
232+
{
233+
"cell_type": "code",
234+
"execution_count": null,
235+
"id": "f074f9e0-773c-4076-8461-d99560e25db0",
236+
"metadata": {},
237+
"outputs": [],
238+
"source": [
239+
"import matplotlib.pyplot as plt\n",
240+
"\n",
241+
"plt.rcParams['figure.figsize'] = (20, 10)\n",
242+
"\n",
243+
"theta_counts_textbok = np.bincount(thetas_textbook) / n_samples\n",
244+
"theta_counts_sinstate = np.bincount(thetas_sinstate) / n_samples\n",
245+
"theta_counts_kaiser = np.bincount(thetas_kaiser_state) / n_samples\n",
246+
"var_textbook = holevo_variance(thetas_textbook / 2**m)\n",
247+
"var_sinstate = holevo_variance(thetas_sinstate / 2**m)\n",
248+
"var_kaiser = holevo_variance(thetas_kaiser_state / 2**m)\n",
249+
"\n",
250+
"plt.plot(np.array(x_vals[:len(theta_counts_textbok)]), theta_counts_textbok, label=r\"TextbookQPE; var($\\tilde{\\phi}$)=\"f\"{var_textbook:.2e}\")\n",
251+
"plt.plot(np.array(x_vals[:len(theta_counts_sinstate)]), theta_counts_sinstate, label=r\"SinStateQPE; var($\\tilde{\\phi}$)=\"f\"{var_sinstate:.2e}\")\n",
252+
"plt.plot(np.array(x_vals[:len(theta_counts_kaiser)]), theta_counts_kaiser, label=f\"KaiserQPE({alpha=:0.3}); \"r\"var($\\tilde{\\phi}$)=\"f\"{var_kaiser:.2e}\")\n",
253+
"plt.vlines(theta, 0, 1, linestyles='--', label=f'True Phase $\\phi$={theta}', colors='red')\n",
254+
"plt.yscale('log', base=10)\n",
255+
"plt.ylabel(f'Fraction of samples')\n",
256+
"plt.xlabel(f'{m}-bit approximation of phase measured by running QPE. Should be close to {theta=}')\n",
257+
"plt.title(f'QPE on ZPowGate(2 * {theta}) using {m=} bit control register and {n_samples} samples.')\n",
258+
"plt.legend()\n",
259+
"plt.show()"
260+
]
261+
}
262+
],
263+
"metadata": {
264+
"kernelspec": {
265+
"display_name": "Python 3 (ipykernel)",
266+
"language": "python",
267+
"name": "python3"
268+
},
269+
"language_info": {
270+
"codemirror_mode": {
271+
"name": "ipython",
272+
"version": 3
273+
},
274+
"file_extension": ".py",
275+
"mimetype": "text/x-python",
276+
"name": "python",
277+
"nbconvert_exporter": "python",
278+
"pygments_lexer": "ipython3",
279+
"version": "3.11.8"
280+
}
281+
},
282+
"nbformat": 4,
283+
"nbformat_minor": 5
284+
}

0 commit comments

Comments
 (0)