Guides
Framework Interop
Import and export circuits between Superfermion, Qiskit, Cirq, PennyLane, and OpenQASM 2/3.
Import/Export Matrix
| Direction | Qiskit | Cirq | PennyLane | OpenQASM 2 | OpenQASM 3 | Braket | IonQ | Stim |
|---|---|---|---|---|---|---|---|---|
| Import → SF | from_qiskit | from_cirq | from_pennylane | from_qasm | from_qasm3 | — | — | — |
| Export SF → | to_qiskit | to_cirq | to_pennylane | to_qasm | to_qasm3 | to_braket | to_ionq | to_stim |
Qiskit
from superfermion.bridge import from_qiskit, to_qiskit
from qiskit import QuantumCircuit
import superfermion as sf
# Qiskit → Superfermion
qiskit_qc = QuantumCircuit(2)
qiskit_qc.h(0)
qiskit_qc.cx(0, 1)
sf_qc = from_qiskit(qiskit_qc)
# Superfermion → Qiskit
sf_qc = sf.Circuit(2).h(0).cnot(0, 1)
qiskit_qc = to_qiskit(sf_qc)
# Run on Qiskit Aer from Superfermion
from qiskit_aer import AerSimulator
qiskit_qc.measure_all() # measurements so get_counts() has results
result = AerSimulator().run(qiskit_qc).result()
print(result.get_counts())Stim
Export a Clifford circuit to Stim for fast
tableau sampling and access to the detector / pymatching / sinter
ecosystem. Non-Clifford gates raise ValueError.
from superfermion.bridge import to_stim
import superfermion as sf
qc = sf.Circuit(4).h(0)
for i in range(3):
qc.cnot(i, i + 1)
stim_circuit, record_cbits = to_stim(qc) # record_cbits: SF cbit per measurement
samples = stim_circuit.compile_sampler().sample(1000)record_cbits[k] is the SF classical-bit index of the k-th measurement in
Stim's record order (None if the measurement had no explicit cbit).
Cirq
from superfermion.bridge import from_cirq, to_cirq
# Cirq → Superfermion
import cirq
cirq_qc = cirq.Circuit(cirq.H(cirq.LineQubit(0)), cirq.CNOT(cirq.LineQubit(0), cirq.LineQubit(1)))
sf_qc = from_cirq(cirq_qc)
# Superfermion → Cirq
cirq_qc = to_cirq(sf_qc)PennyLane
from superfermion.bridge import from_pennylane, to_pennylane
import pennylane as qml
import superfermion as sf
# PennyLane → Superfermion
dev = qml.device("default.qubit", wires=2)
@qml.qnode(dev)
def circuit(x):
qml.RY(x, wires=0)
qml.CNOT(wires=[0, 1])
return qml.state()
# Extract the tape and convert
pl_tape = qml.workflow.construct_tape(circuit)(0.5)
sf_qc = from_pennylane(pl_tape)
print(sf.run(sf_qc.bind({"x": 0.5}), shots=100).counts)
# Superfermion → PennyLane (returns a quantum function for a QNode)
qfunc = to_pennylane(sf.Circuit(2).h(0).cnot(0, 1))
@qml.qnode(dev)
def pl_circuit():
qfunc()
return qml.state()
print(len(pl_circuit())) # 4 amplitudesOpenQASM 2.0
from superfermion.bridge import from_qasm, to_qasm
# Parse QASM (Rust-accelerated parser)
qasm_str = """
OPENQASM 2.0;
include "qelib1.inc";
qreg q[2];
h q[0];
cx q[0], q[1];
"""
sf_qc = from_qasm(qasm_str)
# Export to QASM 2
qasm_output = to_qasm(sf_qc)OpenQASM 3.0
# Export (built into Circuit)
qasm3_str = sf.Circuit(2).h(0).cnot(0, 1).to_qasm3()
# Import
from superfermion.serialization import from_qasm3
sf_qc = from_qasm3(qasm3_str)AWS Braket
from superfermion.bridge import to_braket
import superfermion as sf
# Export Superfermion circuit to AWS Braket format
sf_qc = sf.Circuit(2).h(0).cnot(0, 1)
braket_circuit = to_braket(sf_qc)
print(type(braket_circuit).__name__) # braket.circuits.Circuit
# Submit to AWS Braket (requires AWS credentials)
# from braket.aws import AwsDevice
# device = AwsDevice("arn:aws:braket:::device/quantum-simulator/amazon/sv1")
# device.run(braket_circuit, shots=1000)IonQ
from superfermion.bridge import to_ionq
# Export to IonQ's native format
ionq_circuit = to_ionq(sf_qc)JSON Round-Trip
# Serialize
json_str = sf.Circuit(2).h(0).cnot(0, 1).to_json()
# Deserialize
restored = sf.Circuit.from_json(json_str)
assert restored.gate_count == 2Gate List Export
gates = sf.Circuit(2).h(0).cnot(0, 1).to_gate_list()
# [{"name": "H", "qubits": [0]}, {"name": "CNOT", "qubits": [0, 1]}]
# Rebuild from gate list (names are uppercase, lowercase the method name)
qc = sf.Circuit(2)
for g in gates:
qc = getattr(qc, g["name"].lower())(*g.get("params", []), *g["qubits"])
print(qc.gate_count) # 2Caveats
- Gate mappings are best-effort — framework-specific gates (e.g., PennyLane's
qml.QubitUnitary) may not have a direct Superfermion equivalent - Parameter expressions — Qiskit's
ParameterExpressionis converted to symbolic parameters; complex expressions may be approximated - Classical control — OpenQASM 3's
if/whilestatements are parsed but not executed; use Superfermion's Python API for classical logic
