From e1ef65f055a7f0567bec50a36b2a5ea5bf0f6345 Mon Sep 17 00:00:00 2001 From: ScoomenstheMumens Date: Mon, 25 Aug 2025 10:21:48 +0200 Subject: [PATCH 1/3] Add stabilizer --- quantumreservoirpy/stabilizer.py | 180 ++++++++++++++++++------------- 1 file changed, 105 insertions(+), 75 deletions(-) diff --git a/quantumreservoirpy/stabilizer.py b/quantumreservoirpy/stabilizer.py index 15c28f9..e06da04 100644 --- a/quantumreservoirpy/stabilizer.py +++ b/quantumreservoirpy/stabilizer.py @@ -3,13 +3,11 @@ from qiskit import QuantumCircuit, ClassicalRegister, QuantumRegister, AncillaRegister from qiskit.quantum_info import random_clifford, Clifford, Pauli from qiskit.circuit.library import PauliEvolutionGate - from quantumreservoirpy.util import randomIsing, get_Ising_circuit from quantumreservoirpy.reservoirs import Static - from typing import Iterable - - +import itertools +import random class Stabilizer(Static): def __init__( self, @@ -22,16 +20,20 @@ def __init__( memory=np.inf, backend=None, degree=1, + stab_method='random', + stab_deg=1, num_reservoirs=1, standard=False, isingparams=None, decode=True, # danger zone: this is only for testing ) -> None: super().__init__( - n_qubits + 1, memory, backend, degree=degree, num_reservoirs=num_reservoirs + n_qubits , memory, backend, degree=degree, num_reservoirs=num_reservoirs ) self.n_meas = n_meas self.decode = decode + self.stab_method=stab_method + self.stab_deg=stab_deg if not isingparams: steps = 1 @@ -61,25 +63,25 @@ def __init__( self.tableau = tableau else: self.tableau = Stabilizer.generate_tableau( - n_qubits, n_meas, codestate_preparation_circ + n_qubits, n_meas,self.stab_deg,self.stab_method,codestate_preparation_circ ) def before(self, circuit): if self.decode: - circuit.add_register(AncillaRegister(self.n_meas)) + circuit.add_register(AncillaRegister(1)) def during(self, circuit, timestep, reservoirnumber): circuit.barrier() # encode for k in range(self.n_meas): - beta = 3**k + beta = 3**(k/self.n_meas)/2*np.pi pauliop = Pauli(self.tableau["destabilizer"][k]) - evo = PauliEvolutionGate(pauliop, -beta / 2 * np.pi * timestep) - circuit.append(evo, range(self.n_qubits - 1)) - + evo = PauliEvolutionGate(pauliop, -beta * timestep) + circuit.append(evo, range(self.n_qubits )) + circuit.barrier() # reservoir - circuit.append(self.U[reservoirnumber], range(self.n_qubits - 1)) + circuit.append(self.U[reservoirnumber], range(self.n_qubits)) # decode cr = ClassicalRegister(self.n_meas) @@ -87,57 +89,86 @@ def during(self, circuit, timestep, reservoirnumber): if self.decode: Stabilizer.decoder(circuit, self.tableau) - + @staticmethod def generate_tableau( n_qubits: int, n_meas: int, - codestate_preparation_circ: Iterable[QuantumCircuit] | None = None, + stab_deg: int, + stab_method: str, + codestate_preparation_circ: Iterable[QuantumCircuit] | None = None ): - """generates a tableau for a stabilizer code based on 2**k codestate preparation circuits""" - - logical_qubits = n_qubits - n_meas # also called k - - if codestate_preparation_circ == None: # generate random stabilizer code - tableau = random_clifford(n_qubits).to_dict() - - # turn the last k stabilizers into logical Zs - # tableau["logical_z"] = tableau["stabilizer"][n_meas:] #these are just for QEC fun, not useful here - tableau["stabilizer"] = tableau["stabilizer"][:n_meas] - - # turn the last k destabilizers into logical Xs - # tableau["logical_x"] = tableau["destabilizer"][n_meas:] - tableau["destabilizer"] = tableau["destabilizer"][:n_meas] - - elif len(codestate_preparation_circ) != 2**logical_qubits: - print( - "Error : number of code state preparation circuits does not match the dimension of the codespace" - ) - return - + if stab_method == 'random': + print('ok') + """generates a tableau for a stabilizer code based on 2**k codestate preparation circuits""" + + logical_qubits = n_qubits - n_meas # also called k + + if codestate_preparation_circ == None: # generate random stabilizer code + tableau = random_clifford(n_qubits).to_dict() + + # turn the last k stabilizers into logical Zs + # tableau["logical_z"] = tableau["stabilizer"][n_meas:] #these are just for QEC fun, not useful here + tableau["stabilizer"] = tableau["stabilizer"][:n_meas] + + # turn the last k destabilizers into logical Xs + # tableau["logical_x"] = tableau["destabilizer"][n_meas:] + tableau["destabilizer"] = tableau["destabilizer"][:n_meas] + + elif len(codestate_preparation_circ) != 2**logical_qubits: + print( + "Error : number of code state preparation circuits does not match the dimension of the codespace" + ) + return + + else: + tableau = Clifford(codestate_preparation_circ[0]).to_dict() + for circ in codestate_preparation_circ[1:]: + circ_tableau = Clifford(circ).to_dict() + to_pop = [] + + for i in range(len(tableau["stabilizer"])): + if tableau["stabilizer"][i] not in circ_tableau["stabilizer"]: + to_pop.append(i) + + for i in to_pop: + tableau["stabilizer"].pop(i) + tableau["destabilizer"].pop(i) + + # check the stabilizer has the right dimension + if ( + len(tableau["stabilizer"]) != n_meas + or len(tableau["destabilizer"]) != n_meas + ): + print("Error : something went wrong with tableau generation") + print(tableau) + else: - tableau = Clifford(codestate_preparation_circ[0]).to_dict() - for circ in codestate_preparation_circ[1:]: - circ_tableau = Clifford(circ).to_dict() - to_pop = [] - - for i in range(len(tableau["stabilizer"])): - if tableau["stabilizer"][i] not in circ_tableau["stabilizer"]: - to_pop.append(i) - - for i in to_pop: - tableau["stabilizer"].pop(i) - tableau["destabilizer"].pop(i) + deg=stab_deg + stabilizers = [] + destabilizers = [] + for i in range(n_qubits - deg + 1): + pauli_z = ["I"] * n_qubits + pauli_x = ["I"] * n_qubits + + # fill in Z’s and X’s + for j in range(deg): + pauli_z[i + j] = "Z" + pauli_x[i + j] = "X" + + stabilizers.append("+" + "".join(pauli_z)) + destabilizers.append("+" + "".join(pauli_x)) + indices = random.sample(range(len(stabilizers)), n_meas) + + # Extract stabilizers and destabilizers at those indices + stabs = [stabilizers[i] for i in indices] + destabs = [destabilizers[i] for i in indices] + tableau= { + "stabilizer": stabs, + "destabilizer": destabs, + } + print(tableau) - - # check the stabilizer has the right dimension - if ( - len(tableau["stabilizer"]) != n_meas - or len(tableau["destabilizer"]) != n_meas - ): - print("Error : something went wrong with tableau generation") - print(tableau) - return tableau @staticmethod @@ -217,29 +248,28 @@ def decoder(circuit: QuantumCircuit, code_tableau: dict): circuit.barrier() # syndrome measurement operations - circuit.reset(ar) - circuit.h(ar) + for j in range(n_meas): + circuit.reset(ar) + circuit.h(ar) P = code_tableau["stabilizer"][j] - if P[0] == -1: - circuit.z(ar[j]) - for i in range(1, len(P)): - if P[i] == "X": - circuit.cx(ar[j], qr[i - 1]) - elif P[i] == "Y": - circuit.cy(ar[j], qr[i - 1]) - elif P[i] == "Z": - circuit.cz(ar[j], qr[i - 1]) - - circuit.h(ar) - - for j in range(n_meas): - circuit.measure(ar[j], cr[j]) + P_aux=P[1:][::-1] + if P[0] == str('-'): + circuit.z(ar) + for i in range(0, len(P_aux)): + if P_aux[i] == "X": + circuit.cx(ar, qr[i]) + elif P_aux[i] == "Y": + circuit.cy(ar, qr[i]) + elif P_aux[i] == "Z": + circuit.cz(ar, qr[i]) + + circuit.h(ar) + circuit.measure(ar, cr[j]) circuit.barrier() - + for j in range(n_meas): with circuit.if_test((cr[j], 1)): - circuit.pauli(code_tableau["destabilizer"][j][1:], qr[:-1]) - + circuit.pauli(code_tableau["destabilizer"][j][1:], qr) return circuit From 2aac80feaa57715069662a6329d2054189073d11 Mon Sep 17 00:00:00 2001 From: ScoomenstheMumens Date: Mon, 25 Aug 2025 11:04:36 +0200 Subject: [PATCH 2/3] Add stabilizer --- quantumreservoirpy/stabilizer.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/quantumreservoirpy/stabilizer.py b/quantumreservoirpy/stabilizer.py index e06da04..1a03dbb 100644 --- a/quantumreservoirpy/stabilizer.py +++ b/quantumreservoirpy/stabilizer.py @@ -89,7 +89,6 @@ def during(self, circuit, timestep, reservoirnumber): if self.decode: Stabilizer.decoder(circuit, self.tableau) - @staticmethod def generate_tableau( n_qubits: int, @@ -248,8 +247,6 @@ def decoder(circuit: QuantumCircuit, code_tableau: dict): circuit.barrier() # syndrome measurement operations - - for j in range(n_meas): circuit.reset(ar) circuit.h(ar) @@ -268,7 +265,6 @@ def decoder(circuit: QuantumCircuit, code_tableau: dict): circuit.h(ar) circuit.measure(ar, cr[j]) circuit.barrier() - for j in range(n_meas): with circuit.if_test((cr[j], 1)): circuit.pauli(code_tableau["destabilizer"][j][1:], qr) From ef0a205e69b59ddedc243e43d0b35992d3cdfd28 Mon Sep 17 00:00:00 2001 From: ScoomenstheMumens Date: Mon, 25 Aug 2025 11:05:45 +0200 Subject: [PATCH 3/3] Add stabilizer --- quantumreservoirpy/stabilizer.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/quantumreservoirpy/stabilizer.py b/quantumreservoirpy/stabilizer.py index 1a03dbb..9133e87 100644 --- a/quantumreservoirpy/stabilizer.py +++ b/quantumreservoirpy/stabilizer.py @@ -1,13 +1,15 @@ from itertools import combinations, product import numpy as np +from typing import Iterable +import random + from qiskit import QuantumCircuit, ClassicalRegister, QuantumRegister, AncillaRegister from qiskit.quantum_info import random_clifford, Clifford, Pauli from qiskit.circuit.library import PauliEvolutionGate + from quantumreservoirpy.util import randomIsing, get_Ising_circuit from quantumreservoirpy.reservoirs import Static -from typing import Iterable -import itertools -import random + class Stabilizer(Static): def __init__( self,