diff --git a/qualtran/bloqs/basic_gates/rotation.py b/qualtran/bloqs/basic_gates/rotation.py index 9adb439e1..ae297c974 100644 --- a/qualtran/bloqs/basic_gates/rotation.py +++ b/qualtran/bloqs/basic_gates/rotation.py @@ -108,7 +108,7 @@ def _z_pow() -> ZPowGate: @frozen class CZPowGate(CirqGateAsBloqBase): - exponent: float = 1.0 + exponent: SymbolicFloat = 1.0 global_shift: float = 0.0 eps: SymbolicFloat = 1e-11 diff --git a/qualtran/cirq_interop/_cirq_to_bloq.py b/qualtran/cirq_interop/_cirq_to_bloq.py index f71810df9..b74383534 100644 --- a/qualtran/cirq_interop/_cirq_to_bloq.py +++ b/qualtran/cirq_interop/_cirq_to_bloq.py @@ -150,9 +150,11 @@ def cirq_gate(self) -> cirq.Gate: def my_static_costs(self, cost_key: 'CostKey'): if isinstance(cost_key, QECGatesCost): t_count = _from_directly_countable_cirq(self.cirq_gate) - if t_count is None: - raise ValueError(f"Cirq gate must be directly countable, not {self.cirq_gate}") - return GateCounts(t=t_count.t, rotation=t_count.rotations, clifford=t_count.clifford) + if t_count is not None: + return GateCounts( + t=t_count.t, rotation=t_count.rotations, clifford=t_count.clifford + ) + return NotImplemented def _cirq_wire_symbol_to_qualtran_wire_symbol(symbol: str, side: Side) -> 'WireSymbol': diff --git a/qualtran/cirq_interop/_cirq_to_bloq_test.py b/qualtran/cirq_interop/_cirq_to_bloq_test.py index a016d85a6..314c404a4 100644 --- a/qualtran/cirq_interop/_cirq_to_bloq_test.py +++ b/qualtran/cirq_interop/_cirq_to_bloq_test.py @@ -17,6 +17,7 @@ import cirq import numpy as np import pytest +import sympy from attrs import frozen import qualtran @@ -34,11 +35,12 @@ SoquetT, ) from qualtran._infra.gate_with_registers import get_named_qubits -from qualtran.bloqs.basic_gates import CNOT, GlobalPhase, OneState +from qualtran.bloqs.basic_gates import CNOT, CZPowGate, GlobalPhase, OneState, YPowGate from qualtran.bloqs.bookkeeping import Allocate, Free, Join, Split from qualtran.bloqs.mcmt.and_bloq import And from qualtran.cirq_interop import cirq_optree_to_cbloq, CirqGateAsBloq, CirqQuregT from qualtran.cirq_interop.t_complexity_protocol import TComplexity +from qualtran.resource_counting import GateCounts, get_cost_value, QECGatesCost @frozen @@ -228,3 +230,16 @@ def test_cirq_gate_as_bloq_decompose_raises(): def test_cirq_gate_as_bloq_diagram_info(): assert cirq.circuit_diagram_info(GlobalPhase(exponent=0.5)) is None + + +def test_cirq_gate_cost_via_decomp(): + theta = sympy.Symbol("theta", real=True) + cirq_swappow = cirq.SwapPowGate(exponent=theta) + + swappow_bloq = CirqGateAsBloq(cirq_swappow) + + _, sigma = swappow_bloq.call_graph() + assert sigma == {CNOT(): 2, YPowGate(0.5): 1, YPowGate(-0.5): 1, CZPowGate(theta): 1} + + gc_swappow = get_cost_value(swappow_bloq, QECGatesCost()) + assert gc_swappow == GateCounts(clifford=4, rotation=1)