Skip to content

Commit ff02bbd

Browse files
anurudhpmpharrigan
andauthored
Add precision parameter to GQSP (#1299)
* add precision param to GQSP * autogen notebooks --------- Co-authored-by: Matthew Harrigan <mpharrigan@google.com>
1 parent ca5edd2 commit ff02bbd

5 files changed

Lines changed: 21 additions & 8 deletions

File tree

qualtran/bloqs/hamiltonian_simulation/hamiltonian_simulation_by_gqsp.ipynb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@
8585
"#### Parameters\n",
8686
" - `walk_operator`: qubitization walk operator of $H$ constructed from SELECT and PREPARE oracles.\n",
8787
" - `t`: time to simulate the Hamiltonian, i.e. $e^{-iHt}$\n",
88-
" - `precision`: the precision $\\epsilon$ to approximate $e^{it\\cos\\theta}$ to a polynomial.\n"
88+
" - `precision`: the precision $\\epsilon$ of the final block encoded $e^{-iHt}$. Split into two: half to approximate $e^{it\\cos\\theta}$ to a polynomial, and half to synthesize the underlying GQSP rotations.\n"
8989
]
9090
},
9191
{

qualtran/bloqs/hamiltonian_simulation/hamiltonian_simulation_by_gqsp.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,9 @@ class HamiltonianSimulationByGQSP(GateWithRegisters):
8585
Args:
8686
walk_operator: qubitization walk operator of $H$ constructed from SELECT and PREPARE oracles.
8787
t: time to simulate the Hamiltonian, i.e. $e^{-iHt}$
88-
precision: the precision $\epsilon$ to approximate $e^{it\cos\theta}$ to a polynomial.
88+
precision: the precision $\epsilon$ of the final block encoded $e^{-iHt}$. Split into two:
89+
half to approximate $e^{it\cos\theta}$ to a polynomial, and half to synthesize
90+
the underlying GQSP rotations.
8991
"""
9092

9193
walk_operator: QubitizationWalkOperator
@@ -108,7 +110,7 @@ def alpha(self):
108110
@cached_property
109111
def degree(self) -> SymbolicInt:
110112
r"""degree of the polynomial to approximate the function e^{it\cos(\theta)}"""
111-
return degree_jacobi_anger_approximation(self.t * self.alpha, precision=self.precision)
113+
return degree_jacobi_anger_approximation(self.t * self.alpha, precision=self.precision / 2)
112114

113115
@cached_property
114116
def approx_cos(self) -> Union[NDArray[np.complex128], Shaped]:
@@ -128,6 +130,7 @@ def gqsp(self) -> GeneralizedQSP:
128130
self.walk_operator,
129131
self.approx_cos,
130132
negative_power=self.degree,
133+
precision=self.precision / 2,
131134
verify=True,
132135
verify_precision=1e-4,
133136
)

qualtran/bloqs/hamiltonian_simulation/hamiltonian_simulation_by_gqsp_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,5 +107,5 @@ def test_hamiltonian_simulation_by_gqsp_t_complexity():
107107

108108
symbolic_hamsim_by_gqsp = _symbolic_hamsim_by_gqsp()
109109
tau, t, inv_eps = sympy.symbols(r"\tau t \epsilon^{-1}", positive=True)
110-
T = big_O(tau * t + sympy.log(inv_eps) / sympy.log(sympy.log(inv_eps)))
110+
T = big_O(tau * t + sympy.log(2 * inv_eps) / sympy.log(sympy.log(2 * inv_eps)))
111111
assert symbolic_hamsim_by_gqsp.t_complexity() == TComplexity(t=T, clifford=T, rotations=T) # type: ignore[arg-type]

qualtran/bloqs/qsp/generalized_qsp.ipynb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,8 @@
8484
" - `U`: Unitary operation.\n",
8585
" - `P`: Co-efficients of a complex QSP polynomial.\n",
8686
" - `Q`: Co-efficients of a complex QSP polynomial.\n",
87-
" - `negative_power`: value of $k$, which effectively applies $z^{-k} P(z)$. defaults to 0. \n",
87+
" - `negative_power`: value of $k$, which effectively applies $z^{-k} P(z)$. defaults to 0.\n",
88+
" - `precision`: The error in the synthesized unitary. This is used to compute the required precision for each single qubit SU2 rotation. \n",
8889
"\n",
8990
"#### References\n",
9091
" - [Generalized Quantum Signal Processing](https://arxiv.org/abs/2308.01501). Motlagh and Wiebe. (2023). Theorem 3; Figure 2; Theorem 6.\n"

qualtran/bloqs/qsp/generalized_qsp.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
)
3232
from qualtran.bloqs.basic_gates.su2_rotation import SU2RotationGate
3333
from qualtran.linalg.polynomial.qsp_testing import assert_is_qsp_polynomial
34-
from qualtran.symbolics import is_symbolic, Shaped, slen, smax, smin, SymbolicInt
34+
from qualtran.symbolics import is_symbolic, Shaped, slen, smax, smin, SymbolicFloat, SymbolicInt
3535

3636
if TYPE_CHECKING:
3737
import cirq
@@ -263,6 +263,8 @@ class GeneralizedQSP(GateWithRegisters):
263263
P: Co-efficients of a complex QSP polynomial.
264264
Q: Co-efficients of a complex QSP polynomial.
265265
negative_power: value of $k$, which effectively applies $z^{-k} P(z)$. defaults to 0.
266+
precision: The error in the synthesized unitary. This is used to compute the required
267+
precision for each single qubit SU2 rotation.
266268
267269
References:
268270
[Generalized Quantum Signal Processing](https://arxiv.org/abs/2308.01501)
@@ -273,6 +275,7 @@ class GeneralizedQSP(GateWithRegisters):
273275
P: Union[Tuple[complex, ...], Shaped] = field(converter=_to_tuple)
274276
Q: Union[Tuple[complex, ...], Shaped] = field(converter=_to_tuple)
275277
negative_power: SymbolicInt = field(default=0, kw_only=True)
278+
precision: SymbolicFloat = field(default=1e-11, kw_only=True)
276279

277280
@P.validator
278281
@Q.validator
@@ -292,6 +295,7 @@ def from_qsp_polynomial(
292295
P: Union[NDArray[np.number], Sequence[complex], Shaped],
293296
*,
294297
negative_power: SymbolicInt = 0,
298+
precision: SymbolicFloat = 0,
295299
verify: bool = False,
296300
verify_precision=1e-7,
297301
) -> 'GeneralizedQSP':
@@ -301,7 +305,7 @@ def from_qsp_polynomial(
301305
if verify:
302306
assert_is_qsp_polynomial(P)
303307
Q = qsp_complementary_polynomial(P, verify=verify, verify_precision=verify_precision)
304-
return GeneralizedQSP(U, P, Q, negative_power=negative_power)
308+
return GeneralizedQSP(U, P, Q, negative_power=negative_power, precision=precision)
305309

306310
@cached_property
307311
def _qsp_phases(self) -> Tuple[NDArray[np.floating], NDArray[np.floating], float]:
@@ -311,13 +315,18 @@ def _qsp_phases(self) -> Tuple[NDArray[np.floating], NDArray[np.floating], float
311315
)
312316
return qsp_phase_factors(self.P, self.Q)
313317

318+
@cached_property
319+
def _eps_per_rotation(self):
320+
"""precision to synthesize each SU2 rotation."""
321+
return self.precision / (slen(self.P) + 1)
322+
314323
@cached_property
315324
def signal_rotations(self) -> NDArray[SU2RotationGate]: # type: ignore[type-var]
316325
thetas, phis, lambd = self._qsp_phases
317326

318327
return np.array(
319328
[
320-
SU2RotationGate(theta, phi, lambd if i == 0 else 0)
329+
SU2RotationGate(theta, phi, lambd if i == 0 else 0, eps=self._eps_per_rotation)
321330
for i, (theta, phi) in enumerate(zip(thetas, phis))
322331
]
323332
)

0 commit comments

Comments
 (0)