
computabeast
2f9ef8d7-b7e2-429a-98c9-6b3ba4bc1d25/steane-code
Clone
git clone https://zoo.qernel.sh/2f9ef8d7-b7e2-429a-98c9-6b3ba4bc1d25/steane-code.git
cd steane-code
Unique clones: 3
Files
Comments
- No comments yet.
main.py
Download rawfrom qutip_qip.circuit import QubitCircuit
from qutip_qip.operations import Gate
from qutip_qip.device import LinearSpinChain
from qutip import tensor, basis, Qobj
import numpy as np
import matplotlib.pyplot as plt
import os
import json
from io import BytesIO
def _H_gate_name():
try:
QubitCircuit(1).add_gate(Gate("H", targets=[0]))
return "H"
except Exception:
return "SNOT"
HNAME = _H_gate_name()
def build_steane_encoder_qc(one=False):
qc = QubitCircuit(7)
for i in [0, 1, 3]:
qc.add_gate(Gate(HNAME, targets=[i]))
for t in [2, 4, 6]: qc.add_gate(Gate("CNOT", controls=[0], targets=[t]))
for t in [2, 5, 6]: qc.add_gate(Gate("CNOT", controls=[1], targets=[t]))
for t in [4, 5, 6]: qc.add_gate(Gate("CNOT", controls=[3], targets=[t]))
if one:
for i in range(7): qc.add_gate(Gate("X", targets=[i]))
return qc
def make_processor(nq):
# Version-tolerant constructor; tweak params if your build exposes them
proc = LinearSpinChain(num_qubits=nq) if 'LinearSpinChain' in globals() else LinearSpinChain(nq)
return proc
def pulses_from_circuit(qc, num_steps=300, title=None, show=True):
proc = make_processor(qc.N)
# This generates the control pulses & tlist for the model
proc.load_circuit(qc, schedule_mode="ASAP")
if show:
try:
proc.plot_pulses(title=title or "Pulse schedule")
except Exception:
print("Error plotting pulses")
# Access full (concatenated) arrays if you want to post-process
tlist = proc.get_full_tlist()
coeffs = proc.get_full_coeffs()
return proc, tlist, coeffs
def export_pulses_json(proc, out_path):
"""
Save the full pulse schedule (tlist + per-pulse coeffs) to JSON.
Schema:
{
"tlist": [...],
"pulses": [
{"label": str, "targets": list|int, "coeff": [...]},
...
],
"spline_kind": "step_func"|"cubic",
"pulse_mode": "discrete"|"continuous",
"num_qubits": int
}
"""
tlist = proc.get_full_tlist()
coeffs = proc.get_full_coeffs(tlist)
pulses_json = []
for i, pulse in enumerate(proc.pulses):
label = pulse.label if isinstance(pulse.label, str) and pulse.label else f"pulse_{i}"
pulses_json.append({
"label": label,
"targets": pulse.targets,
"coeff": (coeffs[i].tolist() if i < coeffs.shape[0] else [])
})
data = {
"tlist": (tlist.tolist() if tlist is not None else []),
"pulses": pulses_json,
"spline_kind": getattr(proc, "spline_kind", None),
"pulse_mode": getattr(proc, "pulse_mode", None),
"num_qubits": getattr(proc, "num_qubits", None),
}
with open(out_path, "w") as f:
json.dump(data, f, indent=2)
def export_pulses_html(proc, title, out_path, num_steps=1000):
"""
Save the pulse schedule visualization as a standalone HTML file with inline SVG.
"""
fig, _ = proc.plot_pulses(title=title, num_steps=num_steps)
buf = BytesIO()
fig.savefig(buf, format="svg", bbox_inches="tight")
plt.close(fig)
svg = buf.getvalue().decode("utf-8")
html = f"""<!DOCTYPE html>
<html lang=\"en\">
<head>
<meta charset=\"utf-8\"/>
<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"/>
<title>{title}</title>
<style>body{{margin:0; padding:0; font-family:system-ui,-apple-system,Segoe UI,Roboto;}} .wrap{{padding:16px;}} svg{{width:100%; height:auto;}}</style>
</head>
<body>
<div class=\"wrap\">{svg}</div>
</body>
</html>"""
with open(out_path, "w") as f:
f.write(html)
def simulate_processor(proc, psi0, qc=None, c_ops=None):
# If qc is provided, it will be (re)loaded before simulation
if qc is not None:
proc.load_circuit(qc, schedule_mode="ASAP")
# run_state uses QuTiP’s solvers under the hood; returns a Result object
res = proc.run_state(init_state=psi0, options={"progress_bar": False}) # add c_ops via proc.add_noise if desired
return res.states[-1]
def ket_from_bitstring(bits):
"""
Build |b0 b1 ... b6> from a string like '1010101'.
"""
return tensor([basis(2, int(b)) for b in bits])
def logical_fidelity(psi_target, psi):
"""Fidelity within codespace wrt an encoded target state."""
amp = psi_target.overlap(psi) # complex inner product ⟨psi_target|psi⟩
return float(np.abs(amp)**2)
if __name__ == "__main__":
N = 7 # number of physical qubits
words0 = [
"0000000", "1010101", "0110011", "1100110",
"0001111", "1011010", "0111100", "1101001"
]
zero_ket = Qobj(np.zeros((2**N, 1)), dims=[[2]*N, [1]])
ket0L = sum((ket_from_bitstring(w) for w in words0), zero_ket) * (1/np.sqrt(8))
# 1) Build encoder circuit
qc_enc = build_steane_encoder_qc(one=False)
# 2) Get pulses and plot
proc, tlist, coeffs = pulses_from_circuit(qc_enc, num_steps=300, show=False)
fig, _ = proc.plot_pulses(title="Steane |0_L> encoder pulses", num_steps=300)
# 2b) Export artifacts
os.makedirs("artifacts", exist_ok=True)
export_pulses_json(proc, os.path.join("artifacts", "pulses.json"))
export_pulses_html(proc, "Steane |0_L> encoder pulses", os.path.join("artifacts", "pulses.html"), num_steps=300)
plt.show()
# 3) Simulate from |0000000> and compare to your ket0L
psi0 = ket_from_bitstring("0"*7)
psi_enc = simulate_processor(proc, psi0) # runs with the pulses already loaded
print("Fidelity(|0_L>_pulses vs ket0L) =", logical_fidelity(ket0L, psi_enc))