Source code for scalerqec.Clifford.stimparser
import stim
[docs]
class stimparser:
def __init__(self):
pass
[docs]
def rewrite_stim_code(self,code: str) -> str:
"""
Rewrites a Stim program so that each line contains at most one gate or measurement.
Lines starting with TICK, R, DETECTOR(, and OBSERVABLE_INCLUDE( are kept as-is.
Multi-target lines for CX, M, and MR are split up.
"""
lines = code.splitlines()
output_lines = []
for line in lines:
stripped_line = line.strip()
if not stripped_line:
# Skip empty lines (optional: you could also preserve them)
continue
# Keep lines that we do NOT want to split
if (stripped_line.startswith("TICK") or
stripped_line.startswith("DETECTOR(") or
stripped_line.startswith("QUBIT_COORDS(") or
stripped_line.startswith("OBSERVABLE_INCLUDE(")):
output_lines.append(stripped_line)
continue
if (stripped_line.startswith("X_ERROR") or
stripped_line.startswith("DEPOLARIZE1") or
stripped_line.startswith("DEPOLARIZE2") or
stripped_line.startswith("SHIFT_COORDS")
):
continue
tokens = stripped_line.split()
gate = tokens[0]
# Handle 2-qubit gate lines like "CX 0 1 2 3 4 5 ..."
if gate == "CX":
qubits = tokens[1:]
# Pair up the qubits [q0, q1, q2, q3, ...] => (q0,q1), (q2,q3), ...
for i in range(0, len(qubits), 2):
q1, q2 = qubits[i], qubits[i + 1]
output_lines.append(f"CX {q1} {q2}")
# Handle multi-qubit measurements "M 1 3 5 ..." => each on its own line
elif gate == "M":
qubits = tokens[1:]
for q in qubits:
output_lines.append(f"M {q}")
elif gate == "MX":
qubits = tokens[1:]
for q in qubits:
output_lines.append(f"H {q}")
output_lines.append(f"M {q}")
elif gate == "MY":
qubits = tokens[1:]
for q in qubits:
output_lines.append(f"S {q}")
output_lines.append(f"S {q}")
output_lines.append(f"S {q}")
output_lines.append(f"H {q}")
output_lines.append(f"M {q}")
elif gate == "H":
qubits = tokens[1:]
for q in qubits:
output_lines.append(f"H {q}")
elif gate == "S":
qubits = tokens[1:]
for q in qubits:
output_lines.append(f"S {q}")
# Handle multi-qubit measure+reset "MR 1 3 5 ..." => each on its own line
elif gate == "MR":
qubits = tokens[1:]
for q in qubits:
output_lines.append(f"M {q}")
output_lines.append(f"R {q}")
elif gate == "R":
qubits = tokens[1:]
for q in qubits:
output_lines.append(f"R {q}")
elif gate == "RX":
qubits = tokens[1:]
for q in qubits:
output_lines.append(f"R {q}")
output_lines.append(f"H {q}")
else:
# If there's some other gate we don't specifically handle,
# keep it as is, or add more logic if needed.
output_lines.append(stripped_line)
return "\n".join(output_lines)
[docs]
def rewrite_stim_code(code: str) -> str:
"""
Rewrites a Stim program so that each line contains at most one gate or measurement.
Lines starting with TICK, R, DETECTOR(, and OBSERVABLE_INCLUDE( are kept as-is.
Multi-target lines for CX, M, and MR are split up.
"""
lines = code.splitlines()
output_lines = []
for line in lines:
stripped_line = line.strip()
if not stripped_line:
# Skip empty lines (optional: you could also preserve them)
continue
# Keep lines that we do NOT want to split
if (stripped_line.startswith("TICK") or
stripped_line.startswith("DETECTOR(") or
stripped_line.startswith("QUBIT_COORDS(") or
stripped_line.startswith("OBSERVABLE_INCLUDE(")):
output_lines.append(stripped_line)
continue
if (stripped_line.startswith("X_ERROR") or
stripped_line.startswith("DEPOLARIZE1") or
stripped_line.startswith("DEPOLARIZE2") or
stripped_line.startswith("SHIFT_COORDS")
):
continue
tokens = stripped_line.split()
gate = tokens[0]
# Handle 2-qubit gate lines like "CX 0 1 2 3 4 5 ..."
if gate == "CX":
qubits = tokens[1:]
# Pair up the qubits [q0, q1, q2, q3, ...] => (q0,q1), (q2,q3), ...
for i in range(0, len(qubits), 2):
q1, q2 = qubits[i], qubits[i + 1]
output_lines.append(f"CX {q1} {q2}")
# Handle multi-qubit measurements "M 1 3 5 ..." => each on its own line
elif gate == "M":
qubits = tokens[1:]
for q in qubits:
output_lines.append(f"M {q}")
elif gate == "MX":
qubits = tokens[1:]
for q in qubits:
output_lines.append(f"H {q}")
output_lines.append(f"M {q}")
elif gate == "MY":
qubits = tokens[1:]
for q in qubits:
output_lines.append(f"S {q}")
output_lines.append(f"S {q}")
output_lines.append(f"S {q}")
output_lines.append(f"H {q}")
output_lines.append(f"M {q}")
elif gate == "H":
qubits = tokens[1:]
for q in qubits:
output_lines.append(f"H {q}")
elif gate == "S":
qubits = tokens[1:]
for q in qubits:
output_lines.append(f"S {q}")
# Handle multi-qubit measure+reset "MR 1 3 5 ..." => each on its own line
elif gate == "MR":
qubits = tokens[1:]
for q in qubits:
output_lines.append(f"M {q}")
output_lines.append(f"R {q}")
elif gate == "R":
qubits = tokens[1:]
for q in qubits:
output_lines.append(f"R {q}")
elif gate == "RX":
qubits = tokens[1:]
for q in qubits:
output_lines.append(f"R {q}")
output_lines.append(f"H {q}")
else:
# If there's some other gate we don't specifically handle,
# keep it as is, or add more logic if needed.
output_lines.append(stripped_line)
return "\n".join(output_lines)