Skip to main content

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 = 1 only. [[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=3 only. Larger n still compiles pulses, but decode["table"] is None and a note says so. decode.recover_logical still works for any odd n.
  • Braket AHS amplitude is global-only, so a site-selective inject cannot be emitted faithfully. to_braket_ahs raises by default; pass allow_global_fallback=True to 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 single min_dt idle segment so AHS and Pulser both receive a legal program.
  • pi_logical and pi_error[site] are pulse areas in radians (nominally pi), not durations. Hold time is area / rabi - ramp, quantized up to a multiple of min_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

qc2pulse-0.1.0.tar.gz (25.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

qc2pulse-0.1.0-py3-none-any.whl (23.3 kB view details)

Uploaded Python 3

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

Hashes for qc2pulse-0.1.0.tar.gz
Algorithm Hash digest
SHA256 a941f43759d0c2503cd06cf25b898dd16ec3f8239905daf211690b5afbe0b194
MD5 fc6ede36e9f074b8d6f7599aeef023a0
BLAKE2b-256 1cae3bc62aeb157713d981a22f36a0cbd723321378e32634cd76fc277e4fb38c

See more details on using hashes here.

Provenance

The following attestation bundles were made for qc2pulse-0.1.0.tar.gz:

Publisher: release.yml on PrabhavD/qc2pulse

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for qc2pulse-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3ff245b07c55e8f65cf6f71c1edbc90614a086f90400553d30c073b5fee2a03e
MD5 ceca44ebc1210b288dd739aa4d98dd81
BLAKE2b-256 0ac0f184a8b071487235771c5cb52b38e132dc6e85a17b429276041b0a232546

See more details on using hashes here.

Provenance

The following attestation bundles were made for qc2pulse-0.1.0-py3-none-any.whl:

Publisher: release.yml on PrabhavD/qc2pulse

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page