Skip to content

Commit

Permalink
is_zero: catch errors thrown by Expr.equals(0), and assume it is …
Browse files Browse the repository at this point in the history
…non-zero. (#1366)

* is_zero: catch errors thrown by `Expr.equals(0)`, and assume it is non-zero.

* check for complexity match more carefully

* lint
  • Loading branch information
anurudhp authored Aug 30, 2024
1 parent 5c2c915 commit 8fc12b2
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@
)
from qualtran.bloqs.qubitization.qubitization_walk_operator import QubitizationWalkOperator
from qualtran.cirq_interop import BloqAsCirqGate
from qualtran.cirq_interop.t_complexity_protocol import TComplexity
from qualtran.resource_counting import big_O, BloqCount, get_cost_value
from qualtran.resource_counting import big_O, BloqCount, get_cost_value, QECGatesCost, QubitCount
from qualtran.symbolics import Shaped


Expand All @@ -47,6 +46,11 @@ def test_symbolic_examples(bloq_autotester):
bloq_autotester(_symbolic_hamsim_by_gqsp)


def test_qubit_count_symbolic():
bloq = _symbolic_hamsim_by_gqsp()
_ = get_cost_value(bloq, QubitCount())


@pytest.mark.parametrize("bitsize", [1, 2])
@pytest.mark.parametrize("t", [2, 3, 5, pytest.param(10, marks=pytest.mark.slow)])
@pytest.mark.parametrize("precision", [1e-5, 1e-7])
Expand Down Expand Up @@ -108,7 +112,12 @@ def test_hamiltonian_simulation_by_gqsp_t_complexity():
counts = get_cost_value(hubbard_time_evolution_by_gqsp, BloqCount.for_gateset('t+tof+cswap'))
assert t_comp.t == counts[TwoBitCSwap()] * 7 + counts[TGate()]


def test_symbolic_t_cost():
symbolic_hamsim_by_gqsp = _symbolic_hamsim_by_gqsp()
gc = get_cost_value(symbolic_hamsim_by_gqsp, QECGatesCost())
t_cost = gc.total_t_count()

tau, t, inv_eps = sympy.symbols(r"\tau t \epsilon^{-1}", positive=True)
T = big_O(tau * t + sympy.log(2 * inv_eps) / sympy.log(sympy.log(2 * inv_eps)))
assert symbolic_hamsim_by_gqsp.t_complexity() == TComplexity(t=T, clifford=T, rotations=T) # type: ignore[arg-type]
O_t_cost = sympy.O(t_cost, (tau, sympy.oo), (t, sympy.oo), (inv_eps, sympy.oo))
assert O_t_cost == big_O(tau * t + sympy.log(2 * inv_eps) / sympy.log(sympy.log(2 * inv_eps)))
7 changes: 5 additions & 2 deletions qualtran/linalg/polynomial/jacobi_anger_approximations.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import sympy
from numpy.typing import NDArray

from qualtran.resource_counting import big_O
from qualtran.symbolics import is_symbolic, SymbolicFloat, SymbolicInt


Expand All @@ -40,6 +39,8 @@ def degree_jacobi_anger_approximation(t: SymbolicFloat, *, precision: SymbolicFl
d = \mathcal{O}(t + \frac{\log(1/\epsilon)}{\log\log(1/\epsilon)})
$$
It returns `d` up to a symbolic constant. To ignore the constant, please use `big_O` on the final expression.
Args:
t: scale of the exponent in the function to approximate.
precision: $\epsilon$ in the above polynomial approximation
Expand All @@ -48,7 +49,9 @@ def degree_jacobi_anger_approximation(t: SymbolicFloat, *, precision: SymbolicFl
Truncation degree $d$ as defined above.
"""
if is_symbolic(t, precision):
return big_O(t + sympy.log(1 / precision) / sympy.log(sympy.log(1 / precision)))
# use a symbol for the constant.
c_ja = sympy.Symbol("C_{JA}", positive=True)
return c_ja * (t + sympy.log(1 / precision) / sympy.log(sympy.log(1 / precision)))

def term_too_small(n: int) -> bool:
return bool(np.isclose(scipy.special.jv(n, t), 0, atol=float(precision)))
Expand Down
7 changes: 6 additions & 1 deletion qualtran/symbolics/math_funcs.py
Original file line number Diff line number Diff line change
Expand Up @@ -323,5 +323,10 @@ def is_zero(x: SymbolicInt) -> bool:
or could not be symbolically symplified to a zero.
"""
if is_symbolic(x):
return x.equals(0)
try:
zero = x.equals(0)
except ValueError:
zero = False
return zero

return x == 0

0 comments on commit 8fc12b2

Please sign in to comment.