Skip to content

Commit 07a4367

Browse files
authored
Add CliffordCircuitPredicate if we're using the stabilizer simulator (#560)
1 parent 73693ba commit 07a4367

File tree

5 files changed

+48
-12
lines changed

5 files changed

+48
-12
lines changed

docs/changelog.md

+5
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44

55
# Changelog
66

7+
## Unreleased
8+
9+
- Add CliffordCircuitPredicate for circuit compilation and processing
10+
when using the stabilizer simulator.
11+
712
## 0.44.0 (February 2025)
813

914
- Remove `noise_specs` from local-emulator backends.

pytket/extensions/quantinuum/backends/quantinuum.py

+3
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
scratch_reg_resize_pass,
6666
)
6767
from pytket.predicates import (
68+
CliffordCircuitPredicate,
6869
GateSetPredicate,
6970
MaxNClRegPredicate,
7071
MaxNQubitsPredicate,
@@ -621,6 +622,8 @@ def required_predicates(self) -> list[Predicate]:
621622
assert self.backend_info is not None
622623
preds.append(MaxNQubitsPredicate(self.backend_info.n_nodes))
623624
preds.append(MaxNClRegPredicate(cast(int, self.backend_info.n_cl_reg)))
625+
if self.simulator_type == "stabilizer":
626+
preds.append(CliffordCircuitPredicate())
624627

625628
return preds
626629

tests/integration/backend_test.py

+9-10
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656
QuantinuumAPI,
5757
QuantinuumAPIError,
5858
)
59-
from pytket.extensions.quantinuum.backends.quantinuum import _ALL_GATES, GetResultFailed
59+
from pytket.extensions.quantinuum.backends.quantinuum import _ALL_GATES
6060
from pytket.predicates import CompilationUnit
6161
from pytket.wasm import WasmFileHandler
6262

@@ -530,11 +530,11 @@ def test_leakage_detection(
530530

531531

532532
@given(
533-
n_shots=st.integers(min_value=1, max_value=10), # type: ignore
533+
n_shots=st.integers(min_value=1, max_value=10),
534534
n_bits=st.integers(min_value=0, max_value=10),
535535
)
536536
@pytest.mark.timeout(120)
537-
def test_shots_bits_edgecases(n_shots, n_bits) -> None:
537+
def test_shots_bits_edgecases(n_shots: int, n_bits: int) -> None:
538538
quantinuum_backend = QuantinuumBackend("H1-1SC", machine_debug=True)
539539
c = Circuit(n_bits, n_bits)
540540

@@ -597,18 +597,17 @@ def test_simulator(
597597
assert sum(stab_counts.values()) == n_shots
598598
assert len(stab_counts) == 2
599599

600-
# test non-clifford circuit fails on stabilizer backend
601-
# unfortunately the job is accepted, then fails, so have to check get_result
600+
# test non-clifford circuit fails predicate check
601+
# when run on stabilizer backend
602602
non_stab_circ = (
603603
Circuit(2, name="non_stab_circ").H(0).Rx(0.1, 0).CX(0, 1).measure_all()
604604
)
605605
non_stab_circ = stabilizer_backend.get_compiled_circuit(non_stab_circ)
606-
broken_handle = stabilizer_backend.process_circuit(
607-
non_stab_circ, n_shots, language=language
608-
)
609606

610-
with pytest.raises(GetResultFailed) as _:
611-
_ = stabilizer_backend.get_result(broken_handle)
607+
with pytest.raises(CircuitNotValidError):
608+
_ = stabilizer_backend.process_circuit(
609+
non_stab_circ, n_shots, noisy_simulation=False, language=language
610+
)
612611

613612

614613
@pytest.mark.skipif(skip_remote_tests, reason=REASON)

tests/unit/backend.py

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import pytest
2+
3+
from pytket.extensions.quantinuum import QuantinuumAPIOffline, QuantinuumBackend
4+
from pytket.predicates import CliffordCircuitPredicate
5+
6+
7+
@pytest.mark.parametrize(
8+
"simulator_type,should_have_clifford_predicate",
9+
[
10+
("state-vector", False),
11+
("stabilizer", True),
12+
],
13+
)
14+
def test_clifford_circuits_for_stabilizer(
15+
simulator_type: str,
16+
should_have_clifford_predicate: bool,
17+
) -> None:
18+
"""Check that the stabilizer simulator restricts circuits to be Clifford circuits,
19+
and the statevector simulator does not."""
20+
qapi_offline = QuantinuumAPIOffline()
21+
backend = QuantinuumBackend(
22+
"H1-1E",
23+
api_handler=qapi_offline, # type: ignore
24+
simulator=simulator_type,
25+
)
26+
required_predicates = backend.required_predicates
27+
assert should_have_clifford_predicate == any(
28+
isinstance(pred, CliffordCircuitPredicate) for pred in required_predicates
29+
)

tests/unit/offline_backend_test.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ def test_tket_pass_submission(language: Language) -> None:
117117

118118

119119
@given(
120-
n_shots=strategies.integers(min_value=1, max_value=10), # type: ignore
120+
n_shots=strategies.integers(min_value=1, max_value=10),
121121
n_bits=strategies.integers(min_value=0, max_value=10),
122122
)
123123
@pytest.mark.parametrize(
@@ -128,7 +128,7 @@ def test_tket_pass_submission(language: Language) -> None:
128128
Language.PQIR,
129129
],
130130
)
131-
def test_shots_bits_edgecases(n_shots, n_bits, language: Language) -> None:
131+
def test_shots_bits_edgecases(n_shots: int, n_bits: int, language: Language) -> None:
132132
quantinuum_backend = QuantinuumBackend("H1-1SC", machine_debug=True)
133133
c = Circuit(n_bits, n_bits)
134134

0 commit comments

Comments
 (0)