From 32ad347ae1063068a93b5da87bdb959120efa438 Mon Sep 17 00:00:00 2001 From: Fionn Malone Date: Fri, 17 May 2024 12:13:45 -0700 Subject: [PATCH] Add HWP Trotter bloqs and costs to notebook. (#946) * Small fixes to hubbard bloqs. * Add cost notebook. * Fix eps type. * Add hamming weight phasing bloqs. * Add costs to notebook. * Add costs to notebook. * Add hwp trotter factory. * Fix up notebook. * Fix formatting. * Fix mypy errors. * Fix serialization. * Use symbolicfloat. * Fix bug. * Add notebook test. * Add missing semicolon. * Fix test. --------- Co-authored-by: Matthew Harrigan --- .../chemistry/trotter/hubbard/hopping.py | 90 +++++++++++++++++-- .../chemistry/trotter/hubbard/hopping_test.py | 24 ++++- .../chemistry/trotter/hubbard/interaction.py | 71 +++++++++++++-- .../trotter/hubbard/interaction_test.py | 24 ++++- .../hubbard/qpe_cost_optimization.ipynb | 53 +++++++++++ .../chemistry/trotter/hubbard/trotter_step.py | 73 +++++++++++++-- .../trotter/hubbard/trotter_step_test.py | 8 ++ .../chemistry/trotter/trotterized_unitary.py | 6 +- .../bloqs/rotations/hamming_weight_phasing.py | 6 +- .../rotations/quantum_variable_rotation.py | 19 ++-- qualtran/serialization/resolver_dict.py | 2 + 11 files changed, 336 insertions(+), 40 deletions(-) diff --git a/qualtran/bloqs/chemistry/trotter/hubbard/hopping.py b/qualtran/bloqs/chemistry/trotter/hubbard/hopping.py index 0b1ce4e75..b54672b4a 100644 --- a/qualtran/bloqs/chemistry/trotter/hubbard/hopping.py +++ b/qualtran/bloqs/chemistry/trotter/hubbard/hopping.py @@ -15,12 +15,13 @@ from functools import cached_property from typing import Set, TYPE_CHECKING, Union -import sympy from attrs import frozen from qualtran import Bloq, bloq_example, BloqDocSpec, QAny, QBit, Register, Signature from qualtran.bloqs.basic_gates import Rz from qualtran.bloqs.qft.two_bit_ffft import TwoBitFFFT +from qualtran.bloqs.rotations.hamming_weight_phasing import HammingWeightPhasing +from qualtran.symbolics import SymbolicFloat, SymbolicInt if TYPE_CHECKING: from qualtran.resource_counting import BloqCountT, SympySymbolAllocator @@ -66,8 +67,8 @@ class HoppingPlaquette(Bloq): page 13 Eq. E4 and E5 (Appendix E) """ - kappa: Union[float, sympy.Expr] - eps: Union[float, sympy.Expr] = 1e-9 + kappa: Union[SymbolicFloat] + eps: Union[SymbolicFloat] = 1e-9 @cached_property def signature(self) -> Signature: @@ -109,10 +110,10 @@ class HoppingTile(Bloq): see Eq. 21 and App E. """ - length: Union[int, sympy.Expr] - angle: Union[float, sympy.Expr] + length: Union[SymbolicInt] + angle: Union[SymbolicFloat] tau: float = 1.0 - eps: Union[float, sympy.Expr] = 1e-9 + eps: Union[SymbolicFloat] = 1e-9 pink: bool = True def __attrs_post_init__(self): @@ -134,6 +135,68 @@ def build_call_graph(self, ssa: 'SympySymbolAllocator') -> Set['BloqCountT']: } +@frozen +class HoppingTileHWP(HoppingTile): + r"""Bloq implementing a "tile" of the one-body hopping unitary using Hamming weight phasing. + + Implements the unitary + $$ + e^{i H_h^{x}} = \prod_{k\sigma} e^{i t H_h^{x(k,\sigma)}} + $$ + for a particular choise of of plaquette hamiltonian $H_h^x$, where $x$ = pink or gold. + + Each plaquette Hamiltonian can be split into $L^2/4$ commuting terms. Each + term can be implemented using the 4-qubit HoppingPlaquette above. The + HoppingPlaquette bloq contains 2 arbitrary rotations which are flanked by Clifford operations. + All of the rotations within a HoppingTile have the same angle so we can use + HammingWeightPhaseing to reduce the number of T gates that need to be + synthesized. Accounting for spin there are then $2 \times 2 \times L^2/4$ + arbitrary rotations in each Tile, but only $L^2/2$ of them can be applied + at the same time due to the $e^{iXX} e^{iYY}$ circuit not permitting parallel $R_z$ gates. + + Unlike in the HoppingTile implementation where we can neatly factor + everything into sub-bloqs, here we would need to apply any clifford and F + gates first in parallel then bulk apply the rotations in parallel using + HammingWeightPhasing and then apply another layer of clifford and F gates. + + Args: + length: Lattice side length L. + angle: The prefactor scaling the Hopping hamiltonian in the unitary (`t` above). + This should contain any relevant prefactors including the time step + and any splitting coefficients. + tau: The Hopping hamiltonian parameter. Typically the hubbard model is + defined relative to $\tau$ so it's defaulted to 1. + eps: The precision of the single qubit rotations. + pink: The colour of the plaquette. + + Registers: + system: The system register of size 2 `length`. + + References: + [Early fault-tolerant simulations of the Hubbard model]( + https://arxiv.org/abs/2012.09238) see Eq. 21 and App E. + """ + + def short_name(self) -> str: + l = 'p' if self.pink else 'g' + return f'H_h^{l}(HWP)' + + def build_call_graph(self, ssa: 'SympySymbolAllocator') -> Set['BloqCountT']: + # Page 5, text after Eq. 22. There are L^2 / 4 plaquettes of a given colour and x2 for spin. + # Each plaquette contributes 4 TwoBitFFFT gates and two arbitrary rotations. + # We use Hamming weight phasing to apply all 2 * L^2/4 (two for spin + # here) for both of these rotations. + return { + (TwoBitFFFT(0, 1, self.eps), 4 * self.length**2 // 2), + ( + HammingWeightPhasing( + 2 * self.length**2 // 4, self.tau * self.angle, eps=self.eps + ), + 2, + ), + } + + @bloq_example def _hopping_tile() -> HoppingTile: length = 8 @@ -162,3 +225,18 @@ def _plaquette() -> HoppingPlaquette: import_line='from qualtran.bloqs.chemistry.trotter.hubbard.hopping import HoppingPlaquette', examples=(_plaquette,), ) + + +@bloq_example +def _hopping_tile_hwp() -> HoppingTileHWP: + length = 8 + angle = 0.15 + hopping_tile_hwp = HoppingTileHWP(length, angle) + return hopping_tile_hwp + + +_HOPPING_TILE_HWP_DOC = BloqDocSpec( + bloq_cls=HoppingTileHWP, + import_line='from qualtran.bloqs.chemistry.trotter.hubbard.hopping import HoppingTileHWP', + examples=(_hopping_tile_hwp,), +) diff --git a/qualtran/bloqs/chemistry/trotter/hubbard/hopping_test.py b/qualtran/bloqs/chemistry/trotter/hubbard/hopping_test.py index c7f729458..84a586bae 100644 --- a/qualtran/bloqs/chemistry/trotter/hubbard/hopping_test.py +++ b/qualtran/bloqs/chemistry/trotter/hubbard/hopping_test.py @@ -12,8 +12,12 @@ # See the License for the specific language governing permissions and # limitations under the License. from qualtran import Bloq -from qualtran.bloqs.basic_gates import Rz, TGate -from qualtran.bloqs.chemistry.trotter.hubbard.hopping import _hopping_tile, _plaquette +from qualtran.bloqs.basic_gates import Rz, TGate, ZPowGate +from qualtran.bloqs.chemistry.trotter.hubbard.hopping import ( + _hopping_tile, + _hopping_tile_hwp, + _plaquette, +) from qualtran.bloqs.util_bloqs import ArbitraryClifford from qualtran.resource_counting.generalizers import PHI @@ -27,8 +31,10 @@ def test_hopping_plaquette(bloq_autotester): def catch_rotations(bloq) -> Bloq: - if isinstance(bloq, Rz): - if abs(float(bloq.angle)) < 1e-12: + if isinstance(bloq, (Rz, ZPowGate)): + if isinstance(bloq, ZPowGate): + return Rz(angle=PHI) + elif abs(float(bloq.angle)) < 1e-12: return ArbitraryClifford(1) else: return Rz(angle=PHI) @@ -40,3 +46,13 @@ def test_hopping_tile_t_counts(): _, counts = bloq.call_graph(generalizer=catch_rotations) assert counts[TGate()] == 8 * bloq.length**2 // 2 assert counts[Rz(PHI)] == 2 * bloq.length**2 // 2 + + +def test_hopping_tile_hwp_t_counts(): + bloq = _hopping_tile_hwp() + _, counts = bloq.call_graph(generalizer=catch_rotations) + n_rot_par = bloq.length**2 // 2 + assert counts[Rz(PHI)] == 2 * n_rot_par.bit_length() + assert counts[TGate()] == 8 * bloq.length**2 // 2 + 2 * 4 * ( + n_rot_par - n_rot_par.bit_count() + ) diff --git a/qualtran/bloqs/chemistry/trotter/hubbard/interaction.py b/qualtran/bloqs/chemistry/trotter/hubbard/interaction.py index ff7768a79..0cbd49275 100644 --- a/qualtran/bloqs/chemistry/trotter/hubbard/interaction.py +++ b/qualtran/bloqs/chemistry/trotter/hubbard/interaction.py @@ -16,11 +16,12 @@ from functools import cached_property from typing import Set, TYPE_CHECKING, Union -import sympy from attrs import frozen from qualtran import Bloq, bloq_example, BloqDocSpec, QAny, Register, Signature from qualtran.bloqs.basic_gates import Rz +from qualtran.bloqs.rotations.hamming_weight_phasing import HammingWeightPhasing +from qualtran.symbolics import SymbolicFloat, SymbolicInt if TYPE_CHECKING: from qualtran.resource_counting import BloqCountT, SympySymbolAllocator @@ -52,10 +53,10 @@ class Interaction(Bloq): Eq. 6 page 2 and page 13 paragraph 1. """ - length: Union[int, sympy.Expr] - angle: Union[float, sympy.Expr] - hubb_u: Union[float, sympy.Expr] - eps: Union[float, sympy.Expr] = 1e-9 + length: Union[SymbolicInt] + angle: Union[SymbolicFloat] + hubb_u: Union[SymbolicFloat] + eps: Union[SymbolicFloat] = 1e-9 @cached_property def signature(self) -> Signature: @@ -66,6 +67,50 @@ def build_call_graph(self, ssa: 'SympySymbolAllocator') -> Set['BloqCountT']: return {(Rz(angle=self.angle * self.hubb_u, eps=self.eps), self.length**2)} +@frozen +class InteractionHWP(Bloq): + r"""Bloq implementing the hubbard U part of the hamiltonian using Hamming weight phasing. + + Specifically: + $$ + U_I = e^{i t H_I} + $$ + which can be implemented using equal angle single-qubit Z rotations. + + Each interaction term can be implemented using a e^{iZZ} gate, which + decomposes into a single Rz gate flanked by cliffords. There are L^2 + equal angle rotations in total all of which may be applied in parallel using HWP. + + Args: + length: Lattice length L. + angle: The rotation angle for unitary. + hubb_u: The hubbard U parameter. + eps: The precision for single qubit rotations. + + Registers: + system: The system register of size 2 `length`. + + References: + [Early fault-tolerant simulations of the Hubbard model]( + https://arxiv.org/abs/2012.09238) Eq. page 13 paragraph 1, and page + 14 paragraph 3 right column. The apply 2 batches of $L^2/2$ rotations. + """ + + length: Union[SymbolicInt] + angle: Union[SymbolicFloat] + hubb_u: Union[SymbolicFloat] + eps: Union[SymbolicFloat] = 1e-9 + + @cached_property + def signature(self) -> Signature: + return Signature([Register('system', QAny(self.length), shape=(2,))]) + + def build_call_graph(self, ssa: 'SympySymbolAllocator') -> Set['BloqCountT']: + return { + (HammingWeightPhasing(self.length**2 // 2, self.angle * self.hubb_u, eps=self.eps), 2) + } + + @bloq_example def _interaction() -> Interaction: length = 8 @@ -80,3 +125,19 @@ def _interaction() -> Interaction: import_line='from qualtran.bloqs.chemistry.trotter.hubbard.interaction import Interaction', examples=(_interaction,), ) + + +@bloq_example +def _interaction_hwp() -> InteractionHWP: + length = 8 + angle = 0.5 + hubb_u = 4.0 + interaction = InteractionHWP(length, angle, hubb_u) + return interaction + + +_INTERACTION_HWP_DOC = BloqDocSpec( + bloq_cls=InteractionHWP, + import_line='from qualtran.bloqs.chemistry.trotter.hubbard.interaction import InteractionHWP', + examples=(_interaction_hwp,), +) diff --git a/qualtran/bloqs/chemistry/trotter/hubbard/interaction_test.py b/qualtran/bloqs/chemistry/trotter/hubbard/interaction_test.py index 199b9aea2..43b0479b5 100644 --- a/qualtran/bloqs/chemistry/trotter/hubbard/interaction_test.py +++ b/qualtran/bloqs/chemistry/trotter/hubbard/interaction_test.py @@ -11,8 +11,30 @@ # 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 qualtran.bloqs.chemistry.trotter.hubbard.interaction import _interaction +from qualtran.bloqs.basic_gates import Rz, TGate +from qualtran.bloqs.chemistry.trotter.hubbard.hopping_test import catch_rotations +from qualtran.bloqs.chemistry.trotter.hubbard.interaction import _interaction, _interaction_hwp +from qualtran.resource_counting.generalizers import PHI def test_hopping_tile(bloq_autotester): bloq_autotester(_interaction) + + +def test_interaction_hwp(bloq_autotester): + bloq_autotester(_interaction_hwp) + + +def test_interaction_hwp_bloq_counts(): + bloq = _interaction_hwp() + _, counts = bloq.call_graph(generalizer=catch_rotations) + n_rot_par = bloq.length**2 // 2 + assert counts[Rz(PHI)] == 2 * n_rot_par.bit_length() + assert counts[TGate()] == 2 * 4 * (n_rot_par - n_rot_par.bit_count()) + + +def test_interaction_bloq_counts(): + bloq = _interaction() + _, counts = bloq.call_graph(generalizer=catch_rotations) + n_rot = bloq.length**2 + assert counts[Rz(PHI)] == n_rot diff --git a/qualtran/bloqs/chemistry/trotter/hubbard/qpe_cost_optimization.ipynb b/qualtran/bloqs/chemistry/trotter/hubbard/qpe_cost_optimization.ipynb index 27990787a..f5c3aa054 100644 --- a/qualtran/bloqs/chemistry/trotter/hubbard/qpe_cost_optimization.ipynb +++ b/qualtran/bloqs/chemistry/trotter/hubbard/qpe_cost_optimization.ipynb @@ -446,6 +446,59 @@ "print(rf\"T_{{opt}} = {t_opt:4.3e}\")" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Using Hamming Weight Phasing " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can compare this cost to that found using Hamming weight phasing for the equal angle rotations. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from qualtran.bloqs.chemistry.trotter.hubbard.trotter_step import build_plaq_hwp_unitary_second_order_suzuki\n", + "trotter_step_hwp = build_plaq_hwp_unitary_second_order_suzuki(length, hubb_u, timestep, eps=1e-10)\n", + "n_t_hwp, n_rot_hwp = t_and_rot_counts_from_sigma(trotter_step_hwp.call_graph(generalizer=catch_rotations)[1])\n", + "print(f\"N_T(HWP) = {n_t_hwp} vs {(3*length**2 // 2)*8}\")\n", + "print(f\"N_rot(HWP) = {n_rot_hwp} vs {(3 * length**2 + 2*length**2)}\")\n", + "delta_ht_opt, delta_ts_opt, delta_pe_opt, t_opt = minimize_linesearch(n_rot_hwp, n_t_hwp, xi_bound, prod_ord)\n", + "print(rf\"T_{{OPT}}(HWP) = {t_opt:4.3e}\")\n", + "# The reference counts Toffolis as 2 T gates, we count them as 4.\n", + "print(rf\"Reference value = {1.7e6 + 4 * 1.8e5:4.3e}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Our value is slightly higher as we included all terms in the Trotter step. The reference only counts one layer of interaction gates. Let's correct for that." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "trotter_step_hwp = build_plaq_hwp_unitary_second_order_suzuki(length, hubb_u, timestep, eps=1e-10, strip_layer=True)\n", + "n_t_hwp, n_rot_hwp = t_and_rot_counts_from_sigma(trotter_step_hwp.call_graph(generalizer=catch_rotations)[1])\n", + "print(f\"N_T(HWP) = {n_t_hwp}\")\n", + "print(f\"N_rot(HWP) = {n_rot_hwp}\")\n", + "delta_ht_opt, delta_ts_opt, delta_pe_opt, t_opt = minimize_linesearch(n_rot_hwp, n_t_hwp, xi_bound, prod_ord)\n", + "print(rf\"T_{{OPT}}(HWP) = {t_opt:4.3e}\")\n", + "print(rf\"Reference value = {1.7e6 + 4 * 1.8e5:4.3e}\")" + ] + }, { "cell_type": "markdown", "metadata": {}, diff --git a/qualtran/bloqs/chemistry/trotter/hubbard/trotter_step.py b/qualtran/bloqs/chemistry/trotter/hubbard/trotter_step.py index bf5a5677e..807d1bbe6 100644 --- a/qualtran/bloqs/chemistry/trotter/hubbard/trotter_step.py +++ b/qualtran/bloqs/chemistry/trotter/hubbard/trotter_step.py @@ -21,13 +21,20 @@ $$ """ -from qualtran.bloqs.chemistry.trotter.hubbard.hopping import HoppingTile -from qualtran.bloqs.chemistry.trotter.hubbard.interaction import Interaction +from typing import Sequence + +from qualtran.bloqs.chemistry.trotter.hubbard.hopping import HoppingTile, HoppingTileHWP +from qualtran.bloqs.chemistry.trotter.hubbard.interaction import Interaction, InteractionHWP from qualtran.bloqs.chemistry.trotter.trotterized_unitary import TrotterizedUnitary def build_plaq_unitary_second_order_suzuki( - length: int, hubb_u: float, timestep: float, hubb_t: float = 1.0, eps: float = 1e-9 + length: int, + hubb_u: float, + timestep: float, + hubb_t: float = 1.0, + eps: float = 1e-9, + strip_layer: bool = False, ) -> TrotterizedUnitary: """Build second order Suzuki-Trotter unitary for the square lattice Hubbard model. @@ -37,18 +44,72 @@ def build_plaq_unitary_second_order_suzuki( timestep: The time step for the unitary. hubb_t: Hubbard t. Default = 1. eps: The precision for single-qubit rotations. + strip_layer: Whether to strip one application of the interaction term + which is a common optimization if multiple trotter step are merged. Returns: unitary: The trotterized approximation to the unitary e^{-i t H}. """ - # Trotter splitting parameters when H = H_I + H_h^p + H_h^g - indices = (0, 1, 2, 1, 0) - coeffs = (0.5, 0.5, 1.0, 0.5, 0.5) # Build the basic bloqs which make up the 2nd order PlAQ unitary. # The pink and gold "tiles". pink = HoppingTile(length=length, angle=0, eps=eps, pink=True, tau=hubb_t) gold = HoppingTile(length=length, angle=0, eps=eps, pink=False, tau=hubb_t) interaction = Interaction(length=length, angle=0, eps=eps, hubb_u=hubb_u) + indices: Sequence[int] = () + coeffs: Sequence[float] = () + if strip_layer: + # H_p H_g H_p H_I + indices = (1, 2, 1, 0) + coeffs = (0.5, 1, 0.5, 1) + else: + # Trotter splitting parameters when H = H_I + H_h^p + H_h^g + indices = (0, 1, 2, 1, 0) + coeffs = (0.5, 0.5, 1.0, 0.5, 0.5) + unitary = TrotterizedUnitary( + (interaction, pink, gold), indices=indices, coeffs=coeffs, timestep=timestep + ) + return unitary + + +def build_plaq_hwp_unitary_second_order_suzuki( + length: int, + hubb_u: float, + timestep: float, + hubb_t: float = 1.0, + eps: float = 1e-9, + strip_layer: bool = False, +) -> TrotterizedUnitary: + """Build second order Suzuki-Trotter unitary for the square lattice Hubbard model. + + This variant uses Hamming weight phasing for the rotations. + + Args: + length: box length + hubb_u: Hubbard u. + timestep: The time step for the unitary. + hubb_t: Hubbard t. Default = 1. + eps: The precision for single-qubit rotations. + strip_layer: Whether to strip one application of the interaction term + which is a common optimization if multiple trotter step are merged. + + Returns: + unitary: The trotterized approximation to the unitary e^{-i t H}. + """ + # Build the basic bloqs which make up the 2nd order PlAQ unitary. + # The pink and gold "tiles". + pink = HoppingTileHWP(length=length, angle=0, eps=eps, pink=True, tau=hubb_t) + gold = HoppingTileHWP(length=length, angle=0, eps=eps, pink=False, tau=hubb_t) + interaction = InteractionHWP(length=length, angle=0, eps=eps, hubb_u=hubb_u) + indices: Sequence[int] = () + coeffs: Sequence[float] = () + if strip_layer: + # H_p H_g H_p H_I + indices = (1, 2, 1, 0) + coeffs = (0.5, 1, 0.5, 1) + else: + # Trotter splitting parameters when H = H_I + H_h^p + H_h^g + indices = (0, 1, 2, 1, 0) + coeffs = (0.5, 0.5, 1.0, 0.5, 0.5) unitary = TrotterizedUnitary( (interaction, pink, gold), indices=indices, coeffs=coeffs, timestep=timestep ) diff --git a/qualtran/bloqs/chemistry/trotter/hubbard/trotter_step_test.py b/qualtran/bloqs/chemistry/trotter/hubbard/trotter_step_test.py index f877f5700..a74af1f09 100644 --- a/qualtran/bloqs/chemistry/trotter/hubbard/trotter_step_test.py +++ b/qualtran/bloqs/chemistry/trotter/hubbard/trotter_step_test.py @@ -11,6 +11,8 @@ # 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 + from qualtran import Bloq from qualtran.bloqs.basic_gates import Rz from qualtran.bloqs.basic_gates.t_gate import TGate @@ -19,6 +21,7 @@ ) from qualtran.bloqs.util_bloqs import ArbitraryClifford from qualtran.resource_counting.generalizers import PHI +from qualtran.testing import execute_notebook def catch_rotations(bloq) -> Bloq: @@ -40,3 +43,8 @@ def test_second_order_suzuki_costs(): assert sigma[TGate()] == (3 * length**2 // 2) * 8 # 3 hopping unitaries and 2 interaction unitaries assert sigma[Rz(PHI)] == (3 * length**2 + 2 * length**2) + + +@pytest.mark.notebook +def test_notebook(): + execute_notebook('qpe_cost_optimization') diff --git a/qualtran/bloqs/chemistry/trotter/trotterized_unitary.py b/qualtran/bloqs/chemistry/trotter/trotterized_unitary.py index 637ad17eb..78624a29a 100644 --- a/qualtran/bloqs/chemistry/trotter/trotterized_unitary.py +++ b/qualtran/bloqs/chemistry/trotter/trotterized_unitary.py @@ -17,9 +17,9 @@ from typing import Dict, Sequence, Union import attrs -import sympy from qualtran import Bloq, bloq_example, BloqBuilder, BloqDocSpec, Signature, SoquetT +from qualtran.symbolics import SymbolicFloat @attrs.frozen @@ -83,8 +83,8 @@ class TrotterizedUnitary(Bloq): bloqs: Sequence[Bloq] indices: Sequence[int] - coeffs: Sequence[Union[float, sympy.Expr]] - timestep: Union[float, sympy.Expr] + coeffs: Sequence[Union[SymbolicFloat]] + timestep: Union[SymbolicFloat] def __attrs_post_init__(self): ref_sig = self.bloqs[0].signature diff --git a/qualtran/bloqs/rotations/hamming_weight_phasing.py b/qualtran/bloqs/rotations/hamming_weight_phasing.py index 082519085..160712d89 100644 --- a/qualtran/bloqs/rotations/hamming_weight_phasing.py +++ b/qualtran/bloqs/rotations/hamming_weight_phasing.py @@ -13,7 +13,7 @@ # limitations under the License. from functools import cached_property -from typing import Dict, Set, TYPE_CHECKING +from typing import Dict, Set, TYPE_CHECKING, Union import attrs @@ -21,11 +21,11 @@ from qualtran.bloqs.arithmetic import HammingWeightCompute from qualtran.bloqs.basic_gates import ZPowGate from qualtran.bloqs.rotations.quantum_variable_rotation import QvrPhaseGradient +from qualtran.symbolics import SymbolicFloat, SymbolicInt if TYPE_CHECKING: from qualtran import BloqBuilder, SoquetT from qualtran.resource_counting import BloqCountT, SympySymbolAllocator - from qualtran.symbolics import SymbolicInt @attrs.frozen @@ -60,7 +60,7 @@ class HammingWeightPhasing(GateWithRegisters): bitsize: int exponent: float - eps: float = 1e-10 + eps: Union[SymbolicFloat] = 1e-10 @cached_property def signature(self) -> 'Signature': diff --git a/qualtran/bloqs/rotations/quantum_variable_rotation.py b/qualtran/bloqs/rotations/quantum_variable_rotation.py index ab9feff85..5fb3dc24d 100644 --- a/qualtran/bloqs/rotations/quantum_variable_rotation.py +++ b/qualtran/bloqs/rotations/quantum_variable_rotation.py @@ -84,6 +84,7 @@ sabs, smax, smin, + SymbolicFloat, SymbolicInt, ) @@ -145,15 +146,12 @@ class QvrZPow(QvrInterface): """ cost_reg: Register - gamma: Union[float, sympy.Expr] = 1.0 - eps: Union[float, sympy.Expr] = 1e-9 + gamma: Union[SymbolicFloat] = 1.0 + eps: Union[SymbolicFloat] = 1e-9 @classmethod def from_bitsize( - cls, - bitsize: int, - gamma: Union[float, sympy.Expr] = 1.0, - eps: Union[float, sympy.Expr] = 1e-9, + cls, bitsize: int, gamma: Union[SymbolicFloat] = 1.0, eps: Union[SymbolicFloat] = 1e-9 ) -> 'QvrZPow': cost_reg = Register("x", QFxp(bitsize, bitsize, signed=False)) return QvrZPow(cost_reg, gamma=gamma, eps=eps) @@ -381,8 +379,8 @@ class QvrPhaseGradient(QvrInterface): """ cost_reg: Register - gamma: Union[float, sympy.Expr] = 1.0 - eps: Union[float, sympy.Expr] = 1e-9 + gamma: Union[SymbolicFloat] = 1.0 + eps: Union[SymbolicFloat] = 1e-9 def __attrs_post_init__(self): dtype = self.cost_reg.dtype @@ -391,10 +389,7 @@ def __attrs_post_init__(self): @classmethod def from_bitsize( - cls, - bitsize: int, - gamma: Union[float, sympy.Expr] = 1.0, - eps: Union[float, sympy.Expr] = 1e-9, + cls, bitsize: int, gamma: Union[SymbolicFloat] = 1.0, eps: Union[SymbolicFloat] = 1e-9 ) -> 'QvrPhaseGradient': cost_reg = Register("x", QFxp(bitsize, bitsize, signed=False)) return QvrPhaseGradient(cost_reg, gamma=gamma, eps=eps) diff --git a/qualtran/serialization/resolver_dict.py b/qualtran/serialization/resolver_dict.py index eb3bc5fde..ade1ce2ce 100644 --- a/qualtran/serialization/resolver_dict.py +++ b/qualtran/serialization/resolver_dict.py @@ -240,8 +240,10 @@ "qualtran.bloqs.chemistry.trotter.ising.unitaries.IsingXUnitary": qualtran.bloqs.chemistry.trotter.ising.unitaries.IsingXUnitary, "qualtran.bloqs.chemistry.trotter.ising.unitaries.IsingZZUnitary": qualtran.bloqs.chemistry.trotter.ising.unitaries.IsingZZUnitary, "qualtran.bloqs.chemistry.trotter.hubbard.interaction.Interaction": qualtran.bloqs.chemistry.trotter.hubbard.interaction.Interaction, + "qualtran.bloqs.chemistry.trotter.hubbard.interaction.InteractionHWP": qualtran.bloqs.chemistry.trotter.hubbard.interaction.InteractionHWP, "qualtran.bloqs.chemistry.trotter.hubbard.hopping.HoppingPlaquette": qualtran.bloqs.chemistry.trotter.hubbard.hopping.HoppingPlaquette, "qualtran.bloqs.chemistry.trotter.hubbard.hopping.HoppingTile": qualtran.bloqs.chemistry.trotter.hubbard.hopping.HoppingTile, + "qualtran.bloqs.chemistry.trotter.hubbard.hopping.HoppingTileHWP": qualtran.bloqs.chemistry.trotter.hubbard.hopping.HoppingTileHWP, "qualtran.bloqs.chemistry.trotter.trotterized_unitary": qualtran.bloqs.chemistry.trotter.trotterized_unitary, "qualtran.bloqs.data_loading.qrom.QROM": qualtran.bloqs.data_loading.qrom.QROM, "qualtran.bloqs.data_loading.select_swap_qrom.SelectSwapQROM": qualtran.bloqs.data_loading.select_swap_qrom.SelectSwapQROM,