From 2acead6e0848c48101b3b1845f904c643347f475 Mon Sep 17 00:00:00 2001 From: Anurudh Peduri Date: Sun, 24 Aug 2025 05:40:01 +0200 Subject: [PATCH 1/2] Guided Hamiltonian Bloq --- .../qualtran_dev_tools/notebook_specs.py | 9 + docs/bloqs/index.rst | 1 + .../bloqs/hamiltonian_simulation/__init__.py | 1 + .../guided_hamiltonian.ipynb | 317 ++++++++++++ .../guided_hamiltonian.py | 283 +++++++++++ .../guided_hamiltonian_test.py | 39 ++ .../tutorial_guided_hamiltonian.ipynb | 451 ++++++++++++++++++ .../qubitization_walk_operator.py | 12 +- qualtran/conftest.py | 2 + qualtran/serialization/resolver_dict.py | 3 + 10 files changed, 1117 insertions(+), 1 deletion(-) create mode 100644 qualtran/bloqs/hamiltonian_simulation/guided_hamiltonian.ipynb create mode 100644 qualtran/bloqs/hamiltonian_simulation/guided_hamiltonian.py create mode 100644 qualtran/bloqs/hamiltonian_simulation/guided_hamiltonian_test.py create mode 100644 qualtran/bloqs/hamiltonian_simulation/tutorial_guided_hamiltonian.ipynb diff --git a/dev_tools/qualtran_dev_tools/notebook_specs.py b/dev_tools/qualtran_dev_tools/notebook_specs.py index be00269fe1..68c9080ba2 100644 --- a/dev_tools/qualtran_dev_tools/notebook_specs.py +++ b/dev_tools/qualtran_dev_tools/notebook_specs.py @@ -95,6 +95,7 @@ import qualtran.bloqs.gf_poly_arithmetic.gf2_poly_add import qualtran.bloqs.gf_poly_arithmetic.gf2_poly_add_k import qualtran.bloqs.gf_poly_arithmetic.gf_poly_split_and_join +import qualtran.bloqs.hamiltonian_simulation.guided_hamiltonian import qualtran.bloqs.hamiltonian_simulation.hamiltonian_simulation_by_gqsp import qualtran.bloqs.mcmt.and_bloq import qualtran.bloqs.mcmt.controlled_via_and @@ -983,6 +984,14 @@ qualtran.bloqs.hamiltonian_simulation.hamiltonian_simulation_by_gqsp._Hamiltonian_Simulation_by_GQSP_DOC ], ), + NotebookSpecV2( + title='Guided Hamiltonian Problem', + module=qualtran.bloqs.hamiltonian_simulation.guided_hamiltonian, + bloq_specs=[ + qualtran.bloqs.hamiltonian_simulation.guided_hamiltonian._GUIDED_HAMILTONIAN_DOC, + qualtran.bloqs.hamiltonian_simulation.guided_hamiltonian._GUIDED_HAMILTONIAN_PHASE_ESTIMATION_DOC, + ], + ), ] NB_BY_SECTION = [ diff --git a/docs/bloqs/index.rst b/docs/bloqs/index.rst index b85d7ba580..4902b536b6 100644 --- a/docs/bloqs/index.rst +++ b/docs/bloqs/index.rst @@ -180,3 +180,4 @@ Bloqs Library state_preparation/state_preparation_via_rotation.ipynb qsp/generalized_qsp.ipynb hamiltonian_simulation/hamiltonian_simulation_by_gqsp.ipynb + hamiltonian_simulation/guided_hamiltonian.ipynb diff --git a/qualtran/bloqs/hamiltonian_simulation/__init__.py b/qualtran/bloqs/hamiltonian_simulation/__init__.py index 15780de77b..20d19a507d 100644 --- a/qualtran/bloqs/hamiltonian_simulation/__init__.py +++ b/qualtran/bloqs/hamiltonian_simulation/__init__.py @@ -11,3 +11,4 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from .guided_hamiltonian import GuidedHamiltonian, GuidedHamiltonianPhaseEstimation diff --git a/qualtran/bloqs/hamiltonian_simulation/guided_hamiltonian.ipynb b/qualtran/bloqs/hamiltonian_simulation/guided_hamiltonian.ipynb new file mode 100644 index 0000000000..8155a579f1 --- /dev/null +++ b/qualtran/bloqs/hamiltonian_simulation/guided_hamiltonian.ipynb @@ -0,0 +1,317 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "a84f2ea4", + "metadata": { + "cq.autogen": "title_cell" + }, + "source": [ + "# Guided Hamiltonian Problem\n", + "\n", + "Section 4.4.2 Simulating the Kikuchi Hamiltonian\n", + "\n", + "This module contains oracles to implement the block-encoding of the Kikuchi\n", + "Hamiltonian corresponding to an input k-XOR-SAT instance.\n", + "\n", + "References:\n", + " [Quartic quantum speedups for planted inference](https://arxiv.org/abs/2406.19378v1)\n", + " Section 4.4.2 for algorithm. Section 2.4 for definitions and notation." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b7faaaff", + "metadata": { + "cq.autogen": "top_imports" + }, + "outputs": [], + "source": [ + "from qualtran import Bloq, CompositeBloq, BloqBuilder, Signature, Register\n", + "from qualtran import QBit, QInt, QUInt, QAny\n", + "from qualtran.drawing import show_bloq, show_call_graph, show_counts_sigma\n", + "from typing import *\n", + "import numpy as np\n", + "import sympy\n", + "import cirq" + ] + }, + { + "cell_type": "markdown", + "id": "155994ae", + "metadata": { + "cq.autogen": "GuidedHamiltonian.bloq_doc.md" + }, + "source": [ + "## `GuidedHamiltonian`\n", + "Solve the Guided (Sparse) Hamiltonian Problem.\n", + "\n", + "Definition 4.8 (modified to accept any block-encoding):\n", + "In the Guided Hamiltonian problem we are given the following as input:\n", + "\n", + "1. A $(\\sqrt{2} s, \\cdot, 0)$-block-encoding of a Hamiltonian $H$ such that $\\|H\\|_\\max \\le s$.\n", + "2. A unitary program that prepares $|\\Psi\\rangle|0^A\\rangle$.\n", + "3. Parameters $\\lambda \\in [-\\Lambda, \\Lambda]$, $\\alpha \\in (0, 1)$, $\\gamma \\in (0, 1]$.\n", + "\n", + "and we should output\n", + "\n", + "- YES (1) if $\\| \\Pi_{\\ge \\lambda} (H) |\\Psi\\rangle \\| \\ge \\gamma$\n", + "- NO (0) if $\\|H\\| \\le (1 - \\alpha) \\lambda$\n", + "\n", + "Note that the above drops the sparsity requirement, and accepts any\n", + "$(\\alpha_H, \\cdot, \\cdot)$-block-encoding of $H$.\n", + "In the sparse Hamiltonian case, $\\alpha_H = s$ (where $s$ is the sparsity).\n", + "\n", + "Algorithm (Theorem 4.9):\n", + " This uses phase estimation on the block-encoding of $e^{iHt}$, and then uses\n", + " amplitude amplification to increase the success probability to $1 - o(1)$.\n", + "\n", + "We instead directly do phase-estimation on the qubitized walk operator for $H$.\n", + "\n", + "#### Parameters\n", + " - `hamiltonian`: the block-encoding of $H$\n", + " - `guiding_state`: the unitary that prepares $|\\Psi\\rangle$\n", + " - `lambd`: parameter $\\lambda$\n", + " - `alpha`: parameter $\\alpha$\n", + " - `gamma`: parameter $\\gamma$ \n", + "\n", + "#### References\n", + " - [Quartic quantum speedups for planted inference](https://arxiv.org/abs/2406.19378v1). Section 4.2 \"Guided Sparse Hamiltonian Problem\".\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d3d433e9", + "metadata": { + "cq.autogen": "GuidedHamiltonian.bloq_doc.py" + }, + "outputs": [], + "source": [ + "from qualtran.bloqs.hamiltonian_simulation import GuidedHamiltonian" + ] + }, + { + "cell_type": "markdown", + "id": "b15c049e", + "metadata": { + "cq.autogen": "GuidedHamiltonian.example_instances.md" + }, + "source": [ + "### Example Instances" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3f52ecab", + "metadata": { + "cq.autogen": "GuidedHamiltonian.guided_hamiltonian_symb" + }, + "outputs": [], + "source": [ + "import sympy\n", + "\n", + "from qualtran.bloqs.optimization.k_xor_sat import GuidingState, KikuchiHamiltonian, KXorInstance\n", + "from qualtran.bloqs.state_preparation.black_box_prepare import BlackBoxPrepare\n", + "from qualtran.symbolics import ceil, log2\n", + "\n", + "n, k, m, c = sympy.symbols(\"n k m c\", positive=True, integer=True)\n", + "zeta = sympy.symbols(r\"\\zeta\", positive=True)\n", + "\n", + "inst_guide = KXorInstance.symbolic(n, (1 - zeta) * m, k, max_rhs=2)\n", + "inst_solve = KXorInstance.symbolic(n, zeta * m, k, max_rhs=2)\n", + "l = c * k\n", + "s = l * ceil(log2(n))\n", + "\n", + "Psi = GuidingState(inst_guide, l)\n", + "H = KikuchiHamiltonian(inst_solve, c * k, s)\n", + "\n", + "lambd, alpha, gamma = sympy.symbols(r\"\\lambda \\alpha \\gamma\", positive=True, real=True)\n", + "guided_hamiltonian_symb = GuidedHamiltonian(H, BlackBoxPrepare(Psi), lambd, alpha, gamma)" + ] + }, + { + "cell_type": "markdown", + "id": "06377668", + "metadata": { + "cq.autogen": "GuidedHamiltonian.graphical_signature.md" + }, + "source": [ + "#### Graphical Signature" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e3c32914", + "metadata": { + "cq.autogen": "GuidedHamiltonian.graphical_signature.py" + }, + "outputs": [], + "source": [ + "from qualtran.drawing import show_bloqs\n", + "show_bloqs([guided_hamiltonian_symb],\n", + " ['`guided_hamiltonian_symb`'])" + ] + }, + { + "cell_type": "markdown", + "id": "7c4949b3", + "metadata": { + "cq.autogen": "GuidedHamiltonian.call_graph.md" + }, + "source": [ + "### Call Graph" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "85d0c98d", + "metadata": { + "cq.autogen": "GuidedHamiltonian.call_graph.py" + }, + "outputs": [], + "source": [ + "from qualtran.resource_counting.generalizers import ignore_split_join\n", + "guided_hamiltonian_symb_g, guided_hamiltonian_symb_sigma = guided_hamiltonian_symb.call_graph(max_depth=1, generalizer=ignore_split_join)\n", + "show_call_graph(guided_hamiltonian_symb_g)\n", + "show_counts_sigma(guided_hamiltonian_symb_sigma)" + ] + }, + { + "cell_type": "markdown", + "id": "35fd7bde", + "metadata": { + "cq.autogen": "GuidedHamiltonianPhaseEstimation.bloq_doc.md" + }, + "source": [ + "## `GuidedHamiltonianPhaseEstimation`\n", + "Phase estimation subroutine for the Guided Hamiltonian Problem.\n", + "\n", + "Implements the algorithm $U_\\text{PE}$ used in the Guided Hamiltonian Problem.\n", + "See the bloq `GuidedHamiltonian` for the full problem definition.\n", + "\n", + "#### References\n", + " - [Quartic quantum speedups for planted inference](https://arxiv.org/abs/2406.19378v1). Section 4.2 \"Guided Sparse Hamiltonian Problem\".\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "04b36a18", + "metadata": { + "cq.autogen": "GuidedHamiltonianPhaseEstimation.bloq_doc.py" + }, + "outputs": [], + "source": [ + "from qualtran.bloqs.hamiltonian_simulation import GuidedHamiltonianPhaseEstimation" + ] + }, + { + "cell_type": "markdown", + "id": "79ebea83", + "metadata": { + "cq.autogen": "GuidedHamiltonianPhaseEstimation.example_instances.md" + }, + "source": [ + "### Example Instances" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f01c6434", + "metadata": { + "cq.autogen": "GuidedHamiltonianPhaseEstimation.guided_phase_estimate_symb" + }, + "outputs": [], + "source": [ + "import sympy\n", + "\n", + "from qualtran.bloqs.optimization.k_xor_sat import GuidingState, KikuchiHamiltonian, KXorInstance\n", + "from qualtran.bloqs.state_preparation.black_box_prepare import BlackBoxPrepare\n", + "from qualtran.symbolics import ceil, log2\n", + "\n", + "n, k, c = sympy.symbols(\"n k c\", positive=True, integer=True)\n", + "m_guide, m_solve = sympy.symbols(\"m_1 m_2\", positive=True, integer=True)\n", + "\n", + "inst_guide = KXorInstance.symbolic(n, m_guide, k, max_rhs=2)\n", + "inst_solve = KXorInstance.symbolic(n, m_solve, k, max_rhs=2)\n", + "l = c * k\n", + "s = l * ceil(log2(n))\n", + "\n", + "Psi = GuidingState(inst_guide, l)\n", + "H = KikuchiHamiltonian(inst_solve, c * k, s)\n", + "\n", + "eps, delta = sympy.symbols(r\"\\epsilon_{PE} \\delta_{PE}\", positive=True, real=True)\n", + "guided_phase_estimate_symb = GuidedHamiltonianPhaseEstimation(\n", + " H, BlackBoxPrepare(Psi), eps, delta\n", + ")\n" + ] + }, + { + "cell_type": "markdown", + "id": "aaff689f", + "metadata": { + "cq.autogen": "GuidedHamiltonianPhaseEstimation.graphical_signature.md" + }, + "source": [ + "#### Graphical Signature" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1913a0c3", + "metadata": { + "cq.autogen": "GuidedHamiltonianPhaseEstimation.graphical_signature.py" + }, + "outputs": [], + "source": [ + "from qualtran.drawing import show_bloqs\n", + "show_bloqs([guided_phase_estimate_symb],\n", + " ['`guided_phase_estimate_symb`'])" + ] + }, + { + "cell_type": "markdown", + "id": "a72035ec", + "metadata": { + "cq.autogen": "GuidedHamiltonianPhaseEstimation.call_graph.md" + }, + "source": [ + "### Call Graph" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0ce30cc4", + "metadata": { + "cq.autogen": "GuidedHamiltonianPhaseEstimation.call_graph.py" + }, + "outputs": [], + "source": [ + "from qualtran.resource_counting.generalizers import ignore_split_join\n", + "guided_phase_estimate_symb_g, guided_phase_estimate_symb_sigma = guided_phase_estimate_symb.call_graph(max_depth=1, generalizer=ignore_split_join)\n", + "show_call_graph(guided_phase_estimate_symb_g)\n", + "show_counts_sigma(guided_phase_estimate_symb_sigma)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/qualtran/bloqs/hamiltonian_simulation/guided_hamiltonian.py b/qualtran/bloqs/hamiltonian_simulation/guided_hamiltonian.py new file mode 100644 index 0000000000..847914ba4e --- /dev/null +++ b/qualtran/bloqs/hamiltonian_simulation/guided_hamiltonian.py @@ -0,0 +1,283 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from collections import Counter +from functools import cached_property + +from attrs import frozen + +from qualtran import Bloq, bloq_example, BloqDocSpec, QAny, Signature +from qualtran.bloqs.block_encoding import BlockEncoding +from qualtran.bloqs.phase_estimation import KaiserWindowState, QubitizationQPE +from qualtran.bloqs.phase_estimation.qpe_window_state import QPEWindowStateBase +from qualtran.bloqs.qubitization import QubitizationWalkOperator +from qualtran.bloqs.reflections.prepare_identity import PrepareIdentity +from qualtran.bloqs.reflections.reflection_using_prepare import ReflectionUsingPrepare +from qualtran.bloqs.state_preparation.black_box_prepare import BlackBoxPrepare +from qualtran.resource_counting import BloqCountDictT, SympySymbolAllocator +from qualtran.symbolics import ceil, ln, log2, pi, SymbolicFloat, SymbolicInt + + +@frozen +class GuidedHamiltonianPhaseEstimation(Bloq): + r"""Phase estimation subroutine for the Guided Hamiltonian Problem. + + Implements the algorithm $U_\text{PE}$ used in the Guided Hamiltonian Problem. + See the bloq `GuidedHamiltonian` for the full problem definition. + + References: + [Quartic quantum speedups for planted inference](https://arxiv.org/abs/2406.19378v1) + Section 4.2 "Guided Sparse Hamiltonian Problem". + """ + + hamiltonian: BlockEncoding + guiding_state: BlackBoxPrepare + precision: SymbolicFloat + fail_prob: SymbolicFloat + + def __attrs_post_init__(self): + assert ( + self.hamiltonian.resource_bitsize == 0 + ), "block encoding with resource regs not supported" + + assert self.hamiltonian.system_bitsize == self.guiding_state.selection_bitsize + + @cached_property + def signature(self) -> 'Signature': + return Signature.build_from_dtypes( + phase_estimate=self.qpe_window_state.m_register.dtype, + system=QAny(self.hamiltonian.system_bitsize), + walk_ancilla=QAny(self.hamiltonian.ancilla_bitsize), + guide_ancilla=QAny(self.guiding_state.junk_bitsize), + ) + + @cached_property + def walk_operator(self) -> QubitizationWalkOperator: + # TODO https://github.com/quantumlib/Qualtran/issues/1266 + # QubitizationWalkOperator currently accepts only specific + # block-encodings, but should be generalized. + # For now we ignore the type here. + return QubitizationWalkOperator(self.hamiltonian) # type: ignore + + @cached_property + def qpe_window_state(self) -> QPEWindowStateBase: + """Kaiser Window state. + Computes a slightly larger value for a simpler expression. + https://arxiv.org/abs/2209.13581, Eq D14, D15 + """ + eps, delta = self.precision, self.fail_prob + + alpha = ln(1 / delta) / pi(delta) + + N = (1 / eps) * ln(1 / delta) + m_bits = ceil(log2(N)) + return KaiserWindowState(bitsize=m_bits, alpha=alpha) + + @cached_property + def qpe_bloq(self) -> QubitizationQPE: + return QubitizationQPE(self.walk_operator, self.qpe_window_state) # type: ignore + + def build_call_graph(self, ssa: 'SympySymbolAllocator') -> 'BloqCountDictT': + return {self.guiding_state: 1, self.qpe_bloq: 1} + + +@bloq_example +def _guided_phase_estimate_symb() -> GuidedHamiltonianPhaseEstimation: + import sympy + + from qualtran.bloqs.optimization.k_xor_sat import GuidingState, KikuchiHamiltonian, KXorInstance + from qualtran.bloqs.state_preparation.black_box_prepare import BlackBoxPrepare + from qualtran.symbolics import ceil, log2 + + n, k, c = sympy.symbols("n k c", positive=True, integer=True) + m_guide, m_solve = sympy.symbols("m_1 m_2", positive=True, integer=True) + + inst_guide = KXorInstance.symbolic(n, m_guide, k, max_rhs=2) + inst_solve = KXorInstance.symbolic(n, m_solve, k, max_rhs=2) + l = c * k + s = l * ceil(log2(n)) + + Psi = GuidingState(inst_guide, l) + H = KikuchiHamiltonian(inst_solve, c * k, s) + + eps, delta = sympy.symbols(r"\epsilon_{PE} \delta_{PE}", positive=True, real=True) + guided_phase_estimate_symb = GuidedHamiltonianPhaseEstimation( + H, BlackBoxPrepare(Psi), eps, delta + ) + + return guided_phase_estimate_symb + + +_GUIDED_HAMILTONIAN_PHASE_ESTIMATION_DOC = BloqDocSpec( + bloq_cls=GuidedHamiltonianPhaseEstimation, examples=[_guided_phase_estimate_symb] +) + + +@frozen +class GuidedHamiltonian(Bloq): + r"""Solve the Guided (Sparse) Hamiltonian Problem. + + Definition 4.8 (modified to accept any block-encoding): + In the Guided Hamiltonian problem we are given the following as input: + + 1. A $(\sqrt{2} s, \cdot, 0)$-block-encoding of a Hamiltonian $H$ such that $\|H\|_\max \le s$. + 2. A unitary program that prepares $|\Psi\rangle|0^A\rangle$. + 3. Parameters $\lambda \in [-\Lambda, \Lambda]$, $\alpha \in (0, 1)$, $\gamma \in (0, 1]$. + + and we should output + + - YES (1) if $\| \Pi_{\ge \lambda} (H) |\Psi\rangle \| \ge \gamma$ + - NO (0) if $\|H\| \le (1 - \alpha) \lambda$ + + Note that the above drops the sparsity requirement, and accepts any + $(\alpha_H, \cdot, \cdot)$-block-encoding of $H$. + In the sparse Hamiltonian case, $\alpha_H = s$ (where $s$ is the sparsity). + + Algorithm (Theorem 4.9): + This uses phase estimation on the block-encoding of $e^{iHt}$, and then uses + amplitude amplification to increase the success probability to $1 - o(1)$. + + We instead directly do phase-estimation on the qubitized walk operator for $H$. + + Args: + hamiltonian: the block-encoding of $H$ + guiding_state: the unitary that prepares $|\Psi\rangle$ + lambd: parameter $\lambda$ + alpha: parameter $\alpha$ + gamma: parameter $\gamma$ + + References: + [Quartic quantum speedups for planted inference](https://arxiv.org/abs/2406.19378v1) + Section 4.2 "Guided Sparse Hamiltonian Problem". + """ + + hamiltonian: BlockEncoding + guiding_state: BlackBoxPrepare + lambd: SymbolicFloat + alpha: SymbolicFloat + gamma: SymbolicFloat + + def __attrs_post_init__(self): + assert self.hamiltonian.resource_bitsize == 0, "resource not supported" + assert ( + self.hamiltonian.system_bitsize == self.guiding_state.selection_bitsize + ), "system registers must match" + + assert self.signature == self.qpe_bloq.signature + + @cached_property + def signature(self) -> 'Signature': + return Signature.build_from_dtypes( + phase_estimate=self.qpe_bloq.qpe_window_state.m_register.dtype, + system=QAny(self.hamiltonian.system_bitsize), + walk_ancilla=QAny(self.hamiltonian.ancilla_bitsize), + guide_ancilla=QAny(self.guiding_state.junk_bitsize), + ) + + @cached_property + def qpe_precision(self) -> SymbolicFloat: + r"""The precision for phase estimation. + + Page 31, Eq 100 of the reference gives the precision value for estimating phases + of $e^{iHt}$ with $t = \pi/(2s)$. But this bloq does phase estimation directly + on the walk operator, with eigenphases $e^{-i \arccos(H/s)}$. + + To bound this, consider the two eigenvalues that are to be distinguished: + $\lambda$ and $(1 - \alpha)\lambda$. We can bound the difference in estimated phases as + + $$ + |\arccos(\lambda / s) - \arccos((1-\alpha)\lambda / s)| + \le \frac{\alpha \lambda}{s} \frac{1}{1 - ((1 - \alpha)\lambda / s)^2} + $$ + + As we know $\|H\| \le s/\sqrt{2}$, it means $\lambda/s \le 1/\sqrt{2}$, + therefore the second term is at most $\sqrt{2}$. + + In the sparse encoding case, we can increase the sparsity to $\sqrt{2} s$ + when block-encoding the input, to ensure that we have an epsilon bound of + $\alpha \lambda / s$. + """ + return self.alpha * self.lambd / self.hamiltonian.alpha + + @cached_property + def qpe_fail_prob(self) -> SymbolicFloat: + """Page 31, above Eq 104.""" + return self.gamma**3 + + @cached_property + def n_rounds_amplification(self) -> SymbolicInt: + return ceil(1 / self.gamma) + + @cached_property + def qpe_bloq(self) -> GuidedHamiltonianPhaseEstimation: + return GuidedHamiltonianPhaseEstimation( + hamiltonian=self.hamiltonian, + guiding_state=self.guiding_state, + precision=self.qpe_precision, + fail_prob=self.qpe_fail_prob, + ) + + @cached_property + def _refl_guide_ancilla(self) -> ReflectionUsingPrepare: + return ReflectionUsingPrepare.reflection_around_zero( + bitsizes=[self.guiding_state.junk_bitsize], global_phase=-1 + ) + + @cached_property + def _refl_all(self) -> ReflectionUsingPrepare: + return ReflectionUsingPrepare(PrepareIdentity(tuple(self.signature)), global_phase=-1) + + def build_call_graph(self, ssa: 'SympySymbolAllocator') -> BloqCountDictT: + counts = Counter[Bloq]() + + # prepare the initial state + counts[self.qpe_bloq] += 1 + + # reflect about the ancilla being all 0 + counts[self._refl_guide_ancilla] += self.n_rounds_amplification + + # reflect about the prepared state + counts[self.qpe_bloq.adjoint()] += self.n_rounds_amplification + counts[self._refl_all] += self.n_rounds_amplification + counts[self.qpe_bloq] += self.n_rounds_amplification + + return counts + + +@bloq_example +def _guided_hamiltonian_symb() -> GuidedHamiltonian: + import sympy + + from qualtran.bloqs.optimization.k_xor_sat import GuidingState, KikuchiHamiltonian, KXorInstance + from qualtran.bloqs.state_preparation.black_box_prepare import BlackBoxPrepare + from qualtran.symbolics import ceil, log2 + + n, k, m, c = sympy.symbols("n k m c", positive=True, integer=True) + zeta = sympy.symbols(r"\zeta", positive=True) + + inst_guide = KXorInstance.symbolic(n, (1 - zeta) * m, k, max_rhs=2) + inst_solve = KXorInstance.symbolic(n, zeta * m, k, max_rhs=2) + l = c * k + s = l * ceil(log2(n)) + + Psi = GuidingState(inst_guide, l) + H = KikuchiHamiltonian(inst_solve, c * k, s) + + lambd, alpha, gamma = sympy.symbols(r"\lambda \alpha \gamma", positive=True, real=True) + guided_hamiltonian_symb = GuidedHamiltonian(H, BlackBoxPrepare(Psi), lambd, alpha, gamma) + return guided_hamiltonian_symb + + +_GUIDED_HAMILTONIAN_DOC = BloqDocSpec( + bloq_cls=GuidedHamiltonian, examples=[_guided_hamiltonian_symb] +) diff --git a/qualtran/bloqs/hamiltonian_simulation/guided_hamiltonian_test.py b/qualtran/bloqs/hamiltonian_simulation/guided_hamiltonian_test.py new file mode 100644 index 0000000000..ffe766aff8 --- /dev/null +++ b/qualtran/bloqs/hamiltonian_simulation/guided_hamiltonian_test.py @@ -0,0 +1,39 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import pytest + +import qualtran.testing as qlt_testing +from qualtran.bloqs.hamiltonian_simulation.guided_hamiltonian import ( + _guided_hamiltonian_symb, + _guided_phase_estimate_symb, +) + + +@pytest.mark.parametrize( + "bloq_ex", + [_guided_hamiltonian_symb, _guided_phase_estimate_symb], + ids=lambda bloq_ex: bloq_ex.name, +) +def test_examples(bloq_autotester, bloq_ex): + bloq_autotester(bloq_ex) + + +@pytest.mark.notebook +def test_notebook(): + qlt_testing.execute_notebook('guided_hamiltonian') + + +@pytest.mark.notebook +def test_tutorial(): + qlt_testing.execute_notebook('tutorial_guided_hamiltonian') diff --git a/qualtran/bloqs/hamiltonian_simulation/tutorial_guided_hamiltonian.ipynb b/qualtran/bloqs/hamiltonian_simulation/tutorial_guided_hamiltonian.ipynb new file mode 100644 index 0000000000..268867bfe0 --- /dev/null +++ b/qualtran/bloqs/hamiltonian_simulation/tutorial_guided_hamiltonian.ipynb @@ -0,0 +1,451 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "0", + "metadata": {}, + "source": [ + "# Guided (sparse) Hamiltonian Problem" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1", + "metadata": {}, + "outputs": [], + "source": [ + "from attrs import frozen\n", + "import attrs\n", + "from qualtran import Bloq, Signature, Register, QAny, CtrlSpec\n", + "from qualtran.drawing import show_bloq, show_call_graph, show_counts_sigma\n", + "from qualtran.symbolics import SymbolicInt, ceil, log2, ln, is_symbolic\n", + "from qualtran.resource_counting import big_O\n", + "from qualtran.resource_counting.generalizers import ignore_alloc_free, ignore_split_join, ignore_cliffords\n", + "from qualtran.bloqs.block_encoding import BlockEncoding\n", + "from qualtran.bloqs.reflections.reflection_using_prepare import ReflectionUsingPrepare\n", + "from qualtran.bloqs.hamiltonian_simulation.guided_hamiltonian import GuidedHamiltonian\n", + "from qualtran.resource_counting import CostKey, GateCounts, QECGatesCost" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2", + "metadata": {}, + "outputs": [], + "source": [ + "from typing import Optional\n", + "\n", + "@attrs.frozen\n", + "class ArbitraryGate(Bloq):\n", + " \"\"\"Placeholder gate for costing\n", + "\n", + " Footnote 18, page 29:\n", + " By “gate complexity”, we mean the total number of (arbitrary) 1- and 2-qubit gates\n", + " used by the quantum algorithm. These gates can be further represented using a\n", + " finite universal gate set with a logarithmic overhead.\n", + "\n", + " References:\n", + " [Quartic quantum speedups for planted inference](https://arxiv.org/abs/2406.19378v1)\n", + " Section 4.4.2 for algorithm. Section 2.4 for definitions and notation.\n", + " \"\"\"\n", + "\n", + " n_ctrls: SymbolicInt = 0\n", + "\n", + " @property\n", + " def signature(self) -> 'Signature':\n", + " return Signature.build(q=1 + self.n_ctrls)\n", + "\n", + " def my_static_costs(self, cost_key: 'CostKey'):\n", + " if isinstance(cost_key, QECGatesCost):\n", + " # placeholder cost: reduce controls to single bit, and use C-SU2 (say).\n", + " return GateCounts(rotation=1, and_bloq=self.n_ctrls)\n", + "\n", + " return NotImplemented\n", + "\n", + " def adjoint(self) -> 'Bloq':\n", + " return self\n", + "\n", + " def get_ctrl_system(self, ctrl_spec: CtrlSpec):\n", + " ctrl_bloq = attrs.evolve(self, n_ctrls=self.n_ctrls + ctrl_spec.num_qubits)\n", + "\n", + " return ctrl_bloq, NotImplemented\n", + "\n", + "\n", + "def generalize_1_2_qubit_gates(b: Bloq) -> Optional[Bloq]:\n", + " from qualtran.bloqs.basic_gates import GlobalPhase, Identity\n", + " from qualtran.bloqs.bookkeeping import ArbitraryClifford\n", + " from qualtran.resource_counting.classify_bloqs import (\n", + " bloq_is_clifford,\n", + " bloq_is_rotation,\n", + " bloq_is_t_like,\n", + " )\n", + "\n", + " if bloq_is_t_like(b) or bloq_is_clifford(b) or bloq_is_rotation(b):\n", + " return ArbitraryGate()\n", + "\n", + " if isinstance(b, ArbitraryClifford):\n", + " return ArbitraryGate()\n", + "\n", + " if isinstance(b, (GlobalPhase, Identity)):\n", + " return None\n", + "\n", + " return b\n" + ] + }, + { + "cell_type": "markdown", + "id": "3", + "metadata": {}, + "source": [ + "## `GuidedHamiltonian`\n", + "Solve the guided (sparse) hamiltonian problem.\n", + "\n", + "Definition 4.8 (modified with sparsity generalized to any):\n", + "In the Guided Hamiltonian problem we are given the following as input:\n", + "\n", + "1. A Hamiltonian $H$ with $\\|H\\|_\\max \\le 1$, specified via a block-encoding.\n", + "2. A unitary program that takes $|0^N\\rangle|0^A\\rangle$ and prepares $|\\Psi\\rangle|0^A\\rangle$.\n", + "3. Parameters $\\lambda \\in [-\\Lambda, \\Lambda]$, $\\alpha \\in (0, 1)$, $\\gamma \\in (0, 1]$.\n", + "\n", + "and we should output\n", + "\n", + "- YES if $\\| \\Pi_{\\ge \\lambda} (H) |\\Psi\\rangle \\| \\ge \\gamma$\n", + "- NO if $\\|H\\| \\le (1 - \\alpha) \\lambda$\n", + "\n", + "Note that the above drops the sparse requirement, and accepts any\n", + "$(\\alpha_H, \\cdot, \\cdot)$-block-encoding of $H$.\n", + "In the sparse Hamiltonian case, $\\alpha_H = s$ (where $s$ is the sparsity).\n", + "\n", + "Algorithm (Theorem 4.9):\n", + " This uses phase estimation on the block-encoding of $e^{iHt}$, and then uses\n", + " amplitude amplification to increase the success probability to $1 - o(1)$.\n", + "\n", + "We instead directly do phase-estimation on the qubitized (Szegedy) walk operator for $H$.\n", + "\n", + "#### Parameters\n", + " - `hamiltonian`: the block-encoding of $H$\n", + " - `guiding_state`: the unitary that prepares $|\\Psi\\rangle$\n", + " - `lambd`: parameter $\\lambda$\n", + " - `alpha`: parameter $\\alpha$\n", + " - `gamma`: parameter $\\gamma$" + ] + }, + { + "cell_type": "markdown", + "id": "4", + "metadata": {}, + "source": [ + "# Computing Query Costs with Qualtran\n", + "\n", + "We will first create black-boxes for a Hamiltonian and a guiding state preparation, that can be passed to the `GuidedHamiltonian` bloq to count number of queries and gates." + ] + }, + { + "cell_type": "markdown", + "id": "5", + "metadata": {}, + "source": [ + "## Building black-box oracles" + ] + }, + { + "cell_type": "markdown", + "id": "6", + "metadata": {}, + "source": [ + "### Graph oracles for the Hamiltonian\n", + "We first build the oracles $O_F$ and $O_H$, and use them to block-encode a sparse matrix." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7", + "metadata": {}, + "outputs": [], + "source": [ + "@frozen\n", + "class oracle_O_H(Bloq):\n", + " \"\"\"given (i, j), output H_{i, j}\"\"\"\n", + " N: SymbolicInt\n", + " entry_bits: SymbolicInt\n", + "\n", + " @property\n", + " def signature(self):\n", + " return Signature.build(i=self.N, j=self.N, entry=self.entry_bits)\n", + "\n", + " def adjoint(self):\n", + " return self\n", + "\n", + "@frozen\n", + "class oracle_O_F(Bloq):\n", + " \"\"\"Given (i, k), output (i, f(i, k)) s.t. f(i, k) is the k-th non zero entry in row i\"\"\"\n", + " N: SymbolicInt\n", + " reverse: bool = False\n", + "\n", + " @property\n", + " def signature(self):\n", + " return Signature.build(i=self.N, k=self.N)\n", + "\n", + " def adjoint(self):\n", + " return oracle_O_F(self.N, reverse=not self.reverse)\n", + "\n", + "\n", + "@frozen\n", + "class EncodeSparseHamiltonian(BlockEncoding):\n", + " \"\"\"(s, N+1, 0)-block-encoding of s-sparse NxN matrix H\"\"\"\n", + " N: SymbolicInt\n", + " s: SymbolicInt # sparsity\n", + " O_F: oracle_O_F\n", + " O_H: oracle_O_H\n", + "\n", + " @property\n", + " def signature(self) -> Signature:\n", + " return Signature.build_from_dtypes(\n", + " system=QAny(self.system_bitsize),\n", + " ancilla=QAny(self.ancilla_bitsize),\n", + " )\n", + "\n", + " @property\n", + " def system_bitsize(self):\n", + " return self.N\n", + "\n", + " @property\n", + " def ancilla_bitsize(self):\n", + " return self.N + 1\n", + "\n", + " @property\n", + " def resource_bitsize(self):\n", + " return 0\n", + "\n", + " @property\n", + " def alpha(self):\n", + " return self.s\n", + "\n", + " @property\n", + " def epsilon(self):\n", + " return 0\n", + "\n", + " @property\n", + " def signal_state(self):\n", + " from qualtran.bloqs.reflections.prepare_identity import PrepareIdentity\n", + " from qualtran.bloqs.state_preparation.black_box_prepare import BlackBoxPrepare\n", + "\n", + " return BlackBoxPrepare(PrepareIdentity.from_bitsizes([self.ancilla_bitsize]))\n", + "\n", + " def build_call_graph(self, ssa):\n", + " \"\"\"\n", + " References:\n", + " [Lecture Notes on Quantum Algorithms for Scientific Computation](https://arxiv.org/abs/2201.08309). Lin Lin (2022). Ch. 6.5.\n", + " \"\"\"\n", + " log_s = ceil(log2(self.s))\n", + " return {(self.O_F, 2), (self.O_H, 2), (ArbitraryGate(), 2*log_s)}" + ] + }, + { + "cell_type": "markdown", + "id": "8", + "metadata": {}, + "source": [ + "### State-preparation Oracle for the guiding state\n", + "\n", + "Point 2. Quantum circuit that uses $G$ gates and maps $|0^N\\rangle|0^A\\rangle$ to $|\\Psi\\rangle|0^A\\rangle$" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9", + "metadata": {}, + "outputs": [], + "source": [ + "@frozen\n", + "class GuidingState(Bloq):\n", + " \"\"\"Point 2. Quantum circuit that uses G gates and maps |0^N>|0^A> to |\\Psi>|0^A>\"\"\"\n", + " N: SymbolicInt\n", + " A: SymbolicInt\n", + " G: SymbolicInt\n", + "\n", + " @property\n", + " def signature(self) -> Bloq:\n", + " return Signature.build(selection=self.N, junk=self.A)\n", + "\n", + " def build_call_graph(self, ssa):\n", + " return {(ArbitraryGate(), self.G)}\n", + "\n", + " @property\n", + " def selection_bitsize(self):\n", + " return self.N\n", + " @property\n", + " def junk_bitsize(self):\n", + " return self.A\n", + " @property\n", + " def selection_registers(self):\n", + " return (Register('selection', QAny(self.N)),)\n", + " @property\n", + " def junk_registers(self):\n", + " return (Register('junk', QAny(self.A)),)" + ] + }, + { + "cell_type": "markdown", + "id": "10", + "metadata": {}, + "source": [ + "## An example invocation\n", + "With these oracles in place, we can now invoke the `GuidedHamiltonian` algorithm." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "11", + "metadata": {}, + "outputs": [], + "source": [ + "import sympy\n", + "\n", + "def example_bloq() -> GuidedHamiltonian:\n", + " N, A, G, s = sympy.symbols(\"N A G s\", positive=True, integer=True)\n", + " lambd, alpha, gamma = sympy.symbols(r\"\\lambda \\alpha \\gamma\", positive=True, real=True)\n", + "\n", + " O_F = oracle_O_F(N)\n", + " O_H = oracle_O_H(N, 10)\n", + " be_H = EncodeSparseHamiltonian(N, s, O_F, O_H)\n", + " psi = GuidingState(N, A, G)\n", + "\n", + " return GuidedHamiltonian(be_H, psi, lambd, alpha, gamma)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "12", + "metadata": {}, + "outputs": [], + "source": [ + "bloq = example_bloq()\n", + "show_bloq(bloq)" + ] + }, + { + "cell_type": "markdown", + "id": "13", + "metadata": {}, + "source": [ + "## Query and gate costs\n", + "We will count queries to the above oracles, and arbitrary 1/2-qubit gates as described in the paper." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "14", + "metadata": {}, + "outputs": [], + "source": [ + "g, sigma = bloq.call_graph(\n", + " generalizer=[ignore_alloc_free, ignore_split_join, generalize_1_2_qubit_gates]\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "15", + "metadata": {}, + "outputs": [], + "source": [ + "show_counts_sigma(sigma)" + ] + }, + { + "cell_type": "markdown", + "id": "16", + "metadata": {}, + "source": [ + "### Cost from the paper\n", + "Theorem 4.9 of the paper states that the algorithm uses:\n", + "1. $Q = \\widetilde{O}(s / (\\gamma \\alpha \\lambda))$ queries to oracles for H\n", + "2. $\\widetilde{O}(G/\\gamma + \\text{polylog}(Q)/\\gamma + QN)$ gates\n", + "\n", + "Let us simplify the symbolic costs obtained above and verify if they match." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "17", + "metadata": {}, + "outputs": [], + "source": [ + "def simplify_2_pow_log(my_expr, inner_term):\n", + " # replace `2**(ceil(log2(T)))` upper bound `2T`.\n", + " temp = sympy.symbols(f\"_temp\", positive=True, integer=True)\n", + " my_expr = my_expr.replace(ceil(log2(inner_term)), temp)\n", + " my_expr = my_expr.replace(2**temp, 2 * inner_term)\n", + " my_expr = my_expr.replace(temp, ceil(log2(inner_term)))\n", + " return my_expr\n", + "\n", + "def simplify_expression(expr):\n", + " if not is_symbolic(expr): return expr\n", + " N, A, G, s = sympy.symbols(\"N A G s\", positive=True, integer=True)\n", + " lambd, alpha, gamma = sympy.symbols(r\"\\lambda \\alpha \\gamma\", positive=True, real=True)\n", + "\n", + " expr = simplify_2_pow_log(expr, (s * ln(1/gamma**3)) / (alpha * lambd))\n", + " expr = sympy.simplify(expr)\n", + " return expr\n", + "\n", + "sigma_simpl = {k: simplify_expression(v) for k, v in sigma.items()}\n", + "show_counts_sigma(sigma_simpl)" + ] + }, + { + "cell_type": "markdown", + "id": "18", + "metadata": {}, + "source": [ + "### Cost of Phase Estimation\n", + "\n", + "For simplicity, we can also look at the cost of a single phase estimation call (which is repeated $1/\\gamma$ times to obtain the above algorithm)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "19", + "metadata": {}, + "outputs": [], + "source": [ + "g_pe, sigma_pe = bloq.qpe_bloq.call_graph(\n", + " generalizer=[ignore_alloc_free, ignore_split_join, generalize_1_2_qubit_gates]\n", + ")\n", + "sigma_pe = {k: simplify_expression(v) for k, v in sigma_pe.items()}\n", + "show_counts_sigma(sigma_pe)" + ] + } + ], + "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 +} diff --git a/qualtran/bloqs/qubitization/qubitization_walk_operator.py b/qualtran/bloqs/qubitization/qubitization_walk_operator.py index 9e270d8ec3..117515efb1 100644 --- a/qualtran/bloqs/qubitization/qubitization_walk_operator.py +++ b/qualtran/bloqs/qubitization/qubitization_walk_operator.py @@ -49,6 +49,7 @@ ) from qualtran.bloqs.reflections.reflection_using_prepare import ReflectionUsingPrepare from qualtran.bloqs.state_preparation.prepare_base import PrepareOracle +from qualtran.resource_counting import BloqCountDictT, SympySymbolAllocator from qualtran.resource_counting.generalizers import ( cirq_to_bloqs, ignore_cliffords, @@ -116,7 +117,13 @@ def junk_registers(self) -> Tuple[Register, ...]: @cached_property def signature(self) -> Signature: - return Signature([*self.selection_registers, *self.target_registers, *self.junk_registers]) + # TODO Make `QubitizationWalkOperator` a `BlockEncoding`. + # https://github.com/quantumlib/Qualtran/issues/1266 + if isinstance(self.block_encoding, (SelectBlockEncoding, LCUBlockEncoding)): + return Signature( + [*self.selection_registers, *self.target_registers, *self.junk_registers] + ) + return self.block_encoding.signature @cached_property def reflect(self) -> ReflectionUsingPrepare: @@ -136,6 +143,9 @@ def build_composite_bloq(self, bb: 'BloqBuilder', **soqs: 'SoquetT') -> dict[str return soqs + def build_call_graph(self, ssa: 'SympySymbolAllocator') -> 'BloqCountDictT': + return {self.block_encoding: 1, self.reflect: 1} + def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) -> cirq.CircuitDiagramInfo: wire_symbols = ['W'] * self.signature.n_qubits() return cirq.CircuitDiagramInfo(wire_symbols=wire_symbols) diff --git a/qualtran/conftest.py b/qualtran/conftest.py index db8c3b21fb..9699d1a2fe 100644 --- a/qualtran/conftest.py +++ b/qualtran/conftest.py @@ -181,6 +181,8 @@ def assert_bloq_example_serializes_for_pytest(bloq_ex: BloqExample): 'kikuchi_matrix_symb', 'load_scopes', 'load_scopes_symb', + 'guided_phase_estimate_symb', + 'guided_hamiltonian_symb', ]: pytest.xfail("Skipping serialization test for bloqs that use KXorInstance.") diff --git a/qualtran/serialization/resolver_dict.py b/qualtran/serialization/resolver_dict.py index 8a8d42e4d6..a7fe614f93 100644 --- a/qualtran/serialization/resolver_dict.py +++ b/qualtran/serialization/resolver_dict.py @@ -110,6 +110,7 @@ import qualtran.bloqs.for_testing.matrix_gate import qualtran.bloqs.for_testing.with_call_graph import qualtran.bloqs.for_testing.with_decomposition +import qualtran.bloqs.hamiltonian_simulation.guided_hamiltonian import qualtran.bloqs.hamiltonian_simulation.hamiltonian_simulation_by_gqsp import qualtran.bloqs.mcmt.and_bloq import qualtran.bloqs.mcmt.controlled_via_and @@ -392,6 +393,8 @@ "qualtran.bloqs.for_testing.with_decomposition.TestIndependentParallelCombo": qualtran.bloqs.for_testing.with_decomposition.TestIndependentParallelCombo, "qualtran.bloqs.for_testing.with_decomposition.TestParallelCombo": qualtran.bloqs.for_testing.with_decomposition.TestParallelCombo, "qualtran.bloqs.for_testing.with_decomposition.TestSerialCombo": qualtran.bloqs.for_testing.with_decomposition.TestSerialCombo, + "qualtran.bloqs.hamiltonian_simulation.guided_hamiltonian.GuidedHamiltonian": qualtran.bloqs.hamiltonian_simulation.guided_hamiltonian.GuidedHamiltonian, + "qualtran.bloqs.hamiltonian_simulation.guided_hamiltonian.GuidedHamiltonianPhaseEstimation": qualtran.bloqs.hamiltonian_simulation.guided_hamiltonian.GuidedHamiltonianPhaseEstimation, "qualtran.bloqs.hamiltonian_simulation.hamiltonian_simulation_by_gqsp.HamiltonianSimulationByGQSP": qualtran.bloqs.hamiltonian_simulation.hamiltonian_simulation_by_gqsp.HamiltonianSimulationByGQSP, "qualtran.bloqs.chemistry.hubbard_model.qubitization.prepare_hubbard.PrepareHubbard": qualtran.bloqs.chemistry.hubbard_model.qubitization.prepare_hubbard.PrepareHubbard, "qualtran.bloqs.chemistry.hubbard_model.qubitization.select_hubbard.SelectHubbard": qualtran.bloqs.chemistry.hubbard_model.qubitization.select_hubbard.SelectHubbard, From 56efafcf9831fe235f5d0551a35f3768c376e8a9 Mon Sep 17 00:00:00 2001 From: Anurudh Peduri Date: Sun, 24 Aug 2025 07:18:50 +0200 Subject: [PATCH 2/2] notebook --- .../hamiltonian_simulation/guided_hamiltonian.ipynb | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/qualtran/bloqs/hamiltonian_simulation/guided_hamiltonian.ipynb b/qualtran/bloqs/hamiltonian_simulation/guided_hamiltonian.ipynb index 8155a579f1..77ad95cc41 100644 --- a/qualtran/bloqs/hamiltonian_simulation/guided_hamiltonian.ipynb +++ b/qualtran/bloqs/hamiltonian_simulation/guided_hamiltonian.ipynb @@ -7,16 +7,7 @@ "cq.autogen": "title_cell" }, "source": [ - "# Guided Hamiltonian Problem\n", - "\n", - "Section 4.4.2 Simulating the Kikuchi Hamiltonian\n", - "\n", - "This module contains oracles to implement the block-encoding of the Kikuchi\n", - "Hamiltonian corresponding to an input k-XOR-SAT instance.\n", - "\n", - "References:\n", - " [Quartic quantum speedups for planted inference](https://arxiv.org/abs/2406.19378v1)\n", - " Section 4.4.2 for algorithm. Section 2.4 for definitions and notation." + "# Guided Hamiltonian Problem" ] }, {