qc2pulse
Compile a digital bit-flip repetition circuit to analog Rydberg pulses (Braket AHS or Pulser).
qc2pulse is a narrow protocol compiler, not a general transpiler. It takes an odd-n
[[n,1,n]] bit-flip repetition circuit (Qiskit QuantumCircuit or an OpenQASM 2 string),
rewrites it as analog pulse IR for a Rydberg QPU, and emits either a Braket
AnalogHamiltonianSimulation or a Pulser Sequence.
Anything outside that protocol is rejected rather than approximated.
Install
pip install qc2pulse # parse + compile + decode
pip install "qc2pulse[braket]" # + to_braket_ahs
pip install "qc2pulse[pulser]" # + to_pulser
Usage
import math
from qiskit import QuantumCircuit
from qc2pulse import digital_repetition_to_analog
backend = {
"rabi": math.pi / 2.5e-7, # rad/s, a pi pulse in 250 ns
"ramp": 5e-8, # s
"min_dt": 5e-8, # s, hardware time grid
"pulse_gap": 1e-7, # s, idle between segments
"spacing": 4e-6, # m, atom pitch
"pi_logical": math.pi, # global pulse area for |1_L>
"pi_error": {0: math.pi, 1: math.pi, 2: math.pi}, # per-site inject area
}
qc = QuantumCircuit(3, 3)
qc.cx(0, 1)
qc.cx(0, 2) # encode |0_L>
qc.x(1) # injected bit-flip on site 1
qc.barrier()
qc.measure([0, 1, 2], [0, 1, 2])
out = digital_repetition_to_analog(qc, backend)
out["ir"]["code"] # '[[3,1,3]]'
out["pulse"]["segments"][0]["kind"] # 'inject'
out["decode"]["table"] # {'00': None, '10': 0, '11': 1, '01': 2}
The result is four JSON-safe keys: pulse (atom register plus Rabi trapezoid segments),
ir (what was parsed, plus the backend echo), decode (the n=3 syndrome table), and
notes (human-readable record of every rewrite and quantization).
Emit
from qc2pulse import to_braket_ahs, to_pulser
program, duration_s, n_segments = to_braket_ahs(out["pulse"], backend,
allow_global_fallback=True)
from pulser.devices import MockDevice
seq, duration_s, n_segments = to_pulser(out["pulse"], backend, MockDevice)
Both emitters return the same (program, duration_s, n_segments) shape so callers can swap
them. The IR is SI (seconds, rad/s, meters); the Pulser emitter converts to ns, rad/us, and um.
Decode
from qc2pulse import decode
table = decode.syndrome_table(3)
result = decode.decode_counts({"010": 900, "000": 100}, table)
result["logical_probs"]["0"] # majority vote after correction
Gate rules
Only a digital X becomes an analog pulse (a Rabi pi). Encoder CX is rewritten as Z-basis
codeword preparation, and syndrome CX is rewritten as destructive data readout, so neither
costs a pulse. H, S, CZ, and everything else raise CircuitNotSupportedError, which is
how a [[5,1,3]] circuit gets rejected instead of silently mis-compiled.
Limits
- Odd
n >= 3,k = 1only.[[5,1,5]]yes,[[5,1,3]]no. - At most one injected
X, on a data qubit, before the barrier. - The decode table is
n=3only. Largernstill compiles pulses, butdecode["table"]isNoneand a note says so.decode.recover_logicalstill works for any oddn. - Braket AHS amplitude is global-only, so a site-selective inject cannot be emitted
faithfully.
to_braket_ahsraises by default; passallow_global_fallback=Trueto emit the inject globally and take a warning. - Pulser local inject needs a local ground-rydberg channel. Global-only devices raise.
- An empty pulse program (
|0_L>, no injected error) still emits a singlemin_dtidle segment so AHS and Pulser both receive a legal program. pi_logicalandpi_error[site]are pulse areas in radians (nominally pi), not durations. Hold time isarea / rabi - ramp, quantized up to a multiple ofmin_dt, and the achieved area is reported next to the target so quantization error is visible.
Not in scope
Shot counts, seeds, hardware submission, result caching, plots, and emulator loops stay in
your notebook. This package has one runtime dependency (qiskit) and no numpy, pandas,
matplotlib, boto3, or cloud SDKs outside the optional emitter extras.
Development
uv venv && uv pip install -e ".[dev]"
.venv/bin/pytest # emitter tests skip without the extras
.venv/bin/ruff check src tests
.venv/bin/ruff format --check src tests
.venv/bin/python -m build && .venv/bin/twine check dist/*
pre-commit install wires up the same ruff checks, and the Tests workflow runs them on
Python 3.10 through 3.13 plus one extras-free install.
License
Apache-2.0. See LICENSE.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file qc2pulse-0.1.0.tar.gz.
File metadata
- Download URL: qc2pulse-0.1.0.tar.gz
- Upload date:
- Size: 25.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a941f43759d0c2503cd06cf25b898dd16ec3f8239905daf211690b5afbe0b194
|
|
| MD5 |
fc6ede36e9f074b8d6f7599aeef023a0
|
|
| BLAKE2b-256 |
1cae3bc62aeb157713d981a22f36a0cbd723321378e32634cd76fc277e4fb38c
|
Provenance
The following attestation bundles were made for qc2pulse-0.1.0.tar.gz:
Publisher:
release.yml on PrabhavD/qc2pulse
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
qc2pulse-0.1.0.tar.gz -
Subject digest:
a941f43759d0c2503cd06cf25b898dd16ec3f8239905daf211690b5afbe0b194 - Sigstore transparency entry: 2518009574
- Sigstore integration time:
-
Permalink:
PrabhavD/qc2pulse@a6419390f70189d691ac980e60d7482ff92b3c74 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/PrabhavD
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@a6419390f70189d691ac980e60d7482ff92b3c74 -
Trigger Event:
release
-
Statement type:
File details
Details for the file qc2pulse-0.1.0-py3-none-any.whl.
File metadata
- Download URL: qc2pulse-0.1.0-py3-none-any.whl
- Upload date:
- Size: 23.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3ff245b07c55e8f65cf6f71c1edbc90614a086f90400553d30c073b5fee2a03e
|
|
| MD5 |
ceca44ebc1210b288dd739aa4d98dd81
|
|
| BLAKE2b-256 |
0ac0f184a8b071487235771c5cb52b38e132dc6e85a17b429276041b0a232546
|
Provenance
The following attestation bundles were made for qc2pulse-0.1.0-py3-none-any.whl:
Publisher:
release.yml on PrabhavD/qc2pulse
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
qc2pulse-0.1.0-py3-none-any.whl -
Subject digest:
3ff245b07c55e8f65cf6f71c1edbc90614a086f90400553d30c073b5fee2a03e - Sigstore transparency entry: 2518010176
- Sigstore integration time:
-
Permalink:
PrabhavD/qc2pulse@a6419390f70189d691ac980e60d7482ff92b3c74 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/PrabhavD
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@a6419390f70189d691ac980e60d7482ff92b3c74 -
Trigger Event:
release
-
Statement type: