diff --git a/qermit/coherent_pauli_checks/pauli_sampler.py b/qermit/coherent_pauli_checks/pauli_sampler.py index 5fc40655..8a12188e 100644 --- a/qermit/coherent_pauli_checks/pauli_sampler.py +++ b/qermit/coherent_pauli_checks/pauli_sampler.py @@ -69,6 +69,8 @@ def add_pauli_checks_to_circbox( circ=clifford_subcircuit, ) + print("start_stabiliser_list: ", start_stabiliser_list[0]) + # TODO: check that register names do not already exist control_qubit_list = [ Qubit(name="ancilla", index=i) @@ -188,7 +190,7 @@ def sample(self, circ: Circuit) -> List[QermitPauli]: :return: Z Pauli string of length equal to the circuit. """ return [ - QermitPauli.from_qubit_pauli_tensor( + QermitPauli( QubitPauliTensor( string=QubitPauliString( map={qubit: Pauli.Z for qubit in circ.qubits} @@ -209,7 +211,7 @@ def sample(self, circ: Circuit) -> List[QermitPauli]: :return: X Pauli string of length equal to the circuit. """ return [ - QermitPauli.from_qubit_pauli_tensor( + QermitPauli( QubitPauliTensor( string=QubitPauliString( map={qubit: Pauli.X for qubit in circ.qubits} @@ -258,7 +260,7 @@ def sample( coeff=1, ) if qpt != QubitPauliTensor(): - stabiliser_list.append(QermitPauli.from_qubit_pauli_tensor(qpt)) + stabiliser_list.append(QermitPauli(qpt)) return stabiliser_list @@ -352,8 +354,6 @@ def sample( # ) return [ - QermitPauli.from_qubit_pauli_tensor( - QubitPauliTensor(string=smallest_commute_prob_pauli, coeff=1) - ) + QermitPauli(QubitPauliTensor(string=smallest_commute_prob_pauli, coeff=1)) for smallest_commute_prob_pauli in smallest_commute_prob_pauli_list ] diff --git a/qermit/noise_model/noise_model.py b/qermit/noise_model/noise_model.py index 9a49162f..6f4c05be 100644 --- a/qermit/noise_model/noise_model.py +++ b/qermit/noise_model/noise_model.py @@ -636,7 +636,7 @@ def random_propagate( :raises Exception: Raised if direction is invalid. :return: Resulting logical error. """ - pauli_error = QermitPauli.from_qubit_pauli_tensor( + pauli_error = QermitPauli( QubitPauliTensor( string=QubitPauliString( map={qubit: Pauli.I for qubit in cliff_circ.qubits} diff --git a/qermit/noise_model/qermit_pauli.py b/qermit/noise_model/qermit_pauli.py index c9d8584f..89242971 100644 --- a/qermit/noise_model/qermit_pauli.py +++ b/qermit/noise_model/qermit_pauli.py @@ -23,39 +23,22 @@ class QermitPauli: coeff_to_phase = {1 + 0j: 0, 0 + 1j: 1, -1 + 0j: 2, 0 - 1j: 3} - def __init__( - self, - Z_list: list[int], - X_list: list[int], - qubit_list: list[Qubit], - phase: int = 0, - ): - coeff = self.phase_dict[phase] - - self.qubit_list = qubit_list - - self.unitary_tableau = UnitaryTableau(nqb=len(qubit_list)) - - self.qubit_index = {qubit: Qubit(i) for i, qubit in enumerate(qubit_list)} - self.index_qubit = {Qubit(i): qubit for i, qubit in enumerate(qubit_list)} - - paulis = [] - - for Z, X in zip(Z_list, X_list): - if X and Z: - paulis.append(Pauli.Y) - coeff *= -1j - elif X: - paulis.append(Pauli.X) - elif Z: - paulis.append(Pauli.Z) - else: - paulis.append(Pauli.I) + def __init__(self, qpt: QubitPauliTensor) -> None: + self.qubit_list = list(qpt.string.map.keys()) + + self.unitary_tableau = UnitaryTableau(nqb=len(self.qubit_list)) + + self.qubit_index = {qubit: Qubit(i) for i, qubit in enumerate(self.qubit_list)} + self.index_qubit = {Qubit(i): qubit for i, qubit in enumerate(self.qubit_list)} self.input_pauli_tensor = QubitPauliTensor( - qubits=[qubit_index for qubit_index in self.qubit_index.values()], - paulis=paulis, - coeff=coeff, + string=QubitPauliString( + map={ + self.qubit_index[qubit]: pauli + for qubit, pauli in qpt.string.map.items() + } + ), + coeff=qpt.coeff, ) def is_measureable(self, qubit_list: List[Qubit]) -> bool: @@ -83,7 +66,7 @@ def reduce_qubits(self, qubit_list: List[Qubit]) -> QermitPauli: :param qubit_list: Qubits in Pauli which should be removed. :return: Reduced Pauli. """ - return self.from_qubit_pauli_tensor( + return QermitPauli( QubitPauliTensor( string=QubitPauliString( map={ @@ -101,52 +84,52 @@ def dagger(self) -> QermitPauli: :return: Conjugate transpose of the Pauli. """ - return QermitPauli.from_qubit_pauli_tensor( + return QermitPauli( qpt=QubitPauliTensor( string=self.qubit_pauli_tensor.string, coeff=self.qubit_pauli_tensor.coeff.conjugate(), ) ) - @classmethod - def from_qubit_pauli_tensor(cls, qpt: QubitPauliTensor) -> QermitPauli: - """Create a Pauli from a qubit pauli string. + # @classmethod + # def from_qubit_pauli_tensor(cls, qpt: QubitPauliTensor) -> QermitPauli: + # """Create a Pauli from a qubit pauli string. - :param qps: Qubit pauli string to be converted to a Pauli. - :return: Pauli created from qubit pauli string. - """ + # :param qps: Qubit pauli string to be converted to a Pauli. + # :return: Pauli created from qubit pauli string. + # """ - Z_list = [] - X_list = [] - phase = cls.coeff_to_phase[qpt.coeff] - qubit_list = [] + # Z_list = [] + # X_list = [] + # phase = cls.coeff_to_phase[qpt.coeff] + # qubit_list = [] - qps = qpt.string + # qps = qpt.string - for pauli in qps.to_list(): - qubit = Qubit(name=pauli[0][0], index=pauli[0][1]) - qubit_list.append(qubit) + # for pauli in qps.to_list(): + # qubit = Qubit(name=pauli[0][0], index=pauli[0][1]) + # qubit_list.append(qubit) - if pauli[1] in ["Z", "Y"]: - Z_list.append(1) - else: - Z_list.append(0) + # if pauli[1] in ["Z", "Y"]: + # Z_list.append(1) + # else: + # Z_list.append(0) - if pauli[1] in ["X", "Y"]: - X_list.append(1) - else: - X_list.append(0) + # if pauli[1] in ["X", "Y"]: + # X_list.append(1) + # else: + # X_list.append(0) - if pauli[1] == "Y": - phase += 1 - phase %= 4 + # if pauli[1] == "Y": + # phase += 1 + # phase %= 4 - return cls( - Z_list=Z_list, - X_list=X_list, - qubit_list=qubit_list, - phase=phase, - ) + # return cls( + # Z_list=Z_list, + # X_list=X_list, + # qubit_list=qubit_list, + # phase=phase, + # ) def __hash__(self): return self.qubit_pauli_tensor.__hash__() @@ -354,7 +337,7 @@ def from_pauli_list( :param qubit_list: The qubits on which the resulting pauli will act. :return: The pauli corresponding to the given iterable. """ - return cls.from_qubit_pauli_tensor( + return cls( qpt=QubitPauliTensor( string=QubitPauliString( qubits=qubit_list, diff --git a/tests/coherent_pauli_checks_test.py b/tests/coherent_pauli_checks_test.py index 3f28635b..a795ff09 100644 --- a/tests/coherent_pauli_checks_test.py +++ b/tests/coherent_pauli_checks_test.py @@ -802,7 +802,7 @@ def test_optimal_pauli_sampler(): circ=cliff_circ, ) - assert stab[0] == QermitPauli.from_qubit_pauli_tensor( + assert stab[0] == QermitPauli( QubitPauliTensor( string=QubitPauliString(qubits=qubits, paulis=[Pauli.I, Pauli.I, Pauli.Y]), coeff=1, @@ -836,7 +836,7 @@ class DeterministicPauliSampler(PauliSampler): def sample(self, circ, **kwargs): qubit_list = circ.qubits return [ - QermitPauli.from_qubit_pauli_tensor( + QermitPauli( QubitPauliTensor( string=QubitPauliString( pauli=Pauli.Y, @@ -974,7 +974,7 @@ def test_error_sampler(): ) ideal = Counter( { - QermitPauli.from_qubit_pauli_tensor( + QermitPauli( QubitPauliTensor( string=QubitPauliString( map={ @@ -986,7 +986,7 @@ def test_error_sampler(): coeff=1, ) ): 190, - QermitPauli.from_qubit_pauli_tensor( + QermitPauli( QubitPauliTensor( string=QubitPauliString( map={ @@ -998,11 +998,11 @@ def test_error_sampler(): coeff=1, ) ): 164, - QermitPauli.from_qubit_pauli_tensor( + QermitPauli( QubitPauliTensor( string=QubitPauliString( map={ - Qubit(name="ancilla", index=0): Pauli.X, + Qubit(name="ancilla", index=0): Pauli.I, Qubit(name="my_reg", index=0): Pauli.X, Qubit(name="my_reg", index=1): Pauli.X, } diff --git a/tests/noise_model_test.py b/tests/noise_model_test.py index f7c86bf9..37941691 100644 --- a/tests/noise_model_test.py +++ b/tests/noise_model_test.py @@ -134,7 +134,7 @@ def test_noise_model_logical_error_propagation() -> None: logical_distribution = noise_model.counter_propagate( pytket_ciruit, n_counts=10000, direction=Direction.forward ) - ideal_error = QermitPauli.from_qubit_pauli_tensor( + ideal_error = QermitPauli( QubitPauliTensor( string=QubitPauliString(map={Qubit(0): Pauli.X, Qubit(1): Pauli.I}), coeff=1 ) @@ -240,12 +240,8 @@ def test_error_distribution_post_select() -> None: ) pauli_error_counter = Counter( { - QermitPauli.from_qubit_pauli_tensor( - QubitPauliTensor(string=qps_remove, coeff=1) - ): 50, - QermitPauli.from_qubit_pauli_tensor( - QubitPauliTensor(string=qps_keep, coeff=1) - ): 50, + QermitPauli(QubitPauliTensor(string=qps_remove, coeff=1)): 50, + QermitPauli(QubitPauliTensor(string=qps_keep, coeff=1)): 50, } ) error_distribution = LogicalErrorDistribution( @@ -387,7 +383,7 @@ def test_error_backpropagation() -> None: name = "my_reg" qubit_list = [Qubit(name=name, index=0), Qubit(name=name, index=1)] - stabilise = QermitPauli.from_qubit_pauli_tensor( + stabilise = QermitPauli( QubitPauliTensor( string=QubitPauliString(map={qubit: Pauli.I for qubit in qubit_list}), coeff=1, @@ -409,7 +405,7 @@ def test_error_backpropagation() -> None: coeff=-1j, ) - stabilise = QermitPauli.from_qubit_pauli_tensor( + stabilise = QermitPauli( QubitPauliTensor( string=QubitPauliString(map={qubit: Pauli.I for qubit in qubit_list}), coeff=1, @@ -509,7 +505,7 @@ def test_effective_error_distribution() -> None: assert ( abs( effective_error_dist.pauli_error_counter[ - QermitPauli.from_qubit_pauli_tensor( + QermitPauli( QubitPauliTensor( string=QubitPauliString( qubits=qubits, paulis=[Pauli.X, Pauli.I, Pauli.X] @@ -526,7 +522,7 @@ def test_effective_error_distribution() -> None: assert ( abs( effective_error_dist.pauli_error_counter[ - QermitPauli.from_qubit_pauli_tensor( + QermitPauli( QubitPauliTensor( string=QubitPauliString( qubits=qubits, paulis=[Pauli.Y, Pauli.Y, Pauli.Z] @@ -543,7 +539,7 @@ def test_effective_error_distribution() -> None: assert ( abs( effective_error_dist.pauli_error_counter[ - QermitPauli.from_qubit_pauli_tensor( + QermitPauli( QubitPauliTensor( string=QubitPauliString( qubits=qubits, paulis=[Pauli.I, Pauli.I, Pauli.Z] @@ -557,7 +553,7 @@ def test_effective_error_distribution() -> None: < 100 ) - pauli_error = QermitPauli.from_qubit_pauli_tensor( + pauli_error = QermitPauli( QubitPauliTensor( string=QubitPauliString(qubits=qubits, paulis=[Pauli.Z, Pauli.Y, Pauli.X]), coeff=1j, @@ -570,7 +566,7 @@ def test_qermit_pauli_circuit() -> None: circ = Circuit(3) circ.CZ(0, 1).add_barrier([0, 2]).H(1).H(2).SWAP(1, 2).S(1).Y(0) - L = QermitPauli.from_qubit_pauli_tensor( + L = QermitPauli( QubitPauliTensor( string=QubitPauliString( paulis=[Pauli.Z, Pauli.Z, Pauli.Z], @@ -580,7 +576,7 @@ def test_qermit_pauli_circuit() -> None: ) L_circ = L.circuit - R = QermitPauli.from_qubit_pauli_tensor( + R = QermitPauli( QubitPauliTensor( string=QubitPauliString( paulis=[Pauli.Z, Pauli.Z, Pauli.Z], @@ -603,7 +599,7 @@ def test_qermit_pauli_circuit() -> None: def test_initialisation() -> None: - pauli = QermitPauli.from_qubit_pauli_tensor( + pauli = QermitPauli( QubitPauliTensor( string=QubitPauliString( map={Qubit(0): Pauli.I, Qubit(1): Pauli.I, Qubit(2): Pauli.Z} @@ -624,7 +620,7 @@ def test_identity_clifford() -> None: circ.X(1).H(1).X(1).X(0).Sdg(1).X(0).CZ(1, 0) qubit_list = circ.qubits - pauli = QermitPauli.from_qubit_pauli_tensor( + pauli = QermitPauli( QubitPauliTensor( string=QubitPauliString(map={qubit: Pauli.Z for qubit in qubit_list}), coeff=1, @@ -640,7 +636,7 @@ def test_identity_clifford() -> None: def test_H() -> None: qubit_list = [Qubit(0)] - pauli = QermitPauli.from_qubit_pauli_tensor( + pauli = QermitPauli( QubitPauliTensor( string=QubitPauliString(qubit=Qubit(0), pauli=Pauli.Z), coeff=1 ) @@ -661,7 +657,7 @@ def test_H() -> None: def test_h_series_gates() -> None: circ = Circuit(2).ZZPhase(3.5, 0, 1).PhasedX(1.5, 0.5, 0) - stab = QermitPauli.from_qubit_pauli_tensor( + stab = QermitPauli( QubitPauliTensor( string=QubitPauliString(map={qubit: Pauli.Y for qubit in circ.qubits}), coeff=-1, @@ -673,7 +669,7 @@ def test_h_series_gates() -> None: def test_apply_circuit() -> None: circ = Circuit(2).H(0).S(0).CX(0, 1) qubit_list = circ.qubits - pauli = QermitPauli.from_qubit_pauli_tensor( + pauli = QermitPauli( QubitPauliTensor( string=QubitPauliString(map={qubit: Pauli.Z for qubit in circ.qubits}), coeff=1, @@ -691,7 +687,7 @@ def test_apply_circuit() -> None: def test_apply_gate() -> None: qubit_list = [Qubit(0), Qubit(1), Qubit(2)] - pauli = QermitPauli.from_qubit_pauli_tensor( + pauli = QermitPauli( QubitPauliTensor( string=QubitPauliString( map={ @@ -730,7 +726,7 @@ def test_apply_gate() -> None: def test_qubit_pauli_string() -> None: qubit_list = [Qubit(0), Qubit(1), Qubit(2)] - pauli = QermitPauli.from_qubit_pauli_tensor( + pauli = QermitPauli( QubitPauliTensor( string=QubitPauliString( map={ @@ -786,7 +782,7 @@ def test_qubit_pauli_string() -> None: def test_clifford_incremental() -> None: qubit_list = [Qubit(0), Qubit(1), Qubit(2)] - pauli = QermitPauli.from_qubit_pauli_tensor( + pauli = QermitPauli( QubitPauliTensor( string=QubitPauliString( map={ @@ -915,7 +911,7 @@ def test_to_from_qps() -> None: qubits=qubits, paulis=paulis, ) - stab = QermitPauli.from_qubit_pauli_tensor( + stab = QermitPauli( QubitPauliTensor( string=qubit_pauli_string, coeff=1, @@ -926,7 +922,7 @@ def test_to_from_qps() -> None: def test_is_measureable() -> None: - stab = QermitPauli.from_qubit_pauli_tensor( + stab = QermitPauli( QubitPauliTensor( string=QubitPauliString( map={