diff --git a/README.md b/README.md index 8e9389d..d83d17b 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ pure Python while browsing short descriptions of famous conjectures. ## Features - **State-vector simulator** implemented in [`quantum_simulator.py`](quantum_simulator.py) - with Hadamard, Pauli-X and controlled-NOT gates, custom unitaries and + with Hadamard, Pauli-X/Y/Z and controlled-NOT gates, custom unitaries and measurement utilities. - **Problem compendium** in [`problems.md`](problems.md) covering ten influential open problems such as the Riemann Hypothesis, P vs NP and the Navier–Stokes diff --git a/quantum_simulator.py b/quantum_simulator.py index 25ef6a0..705eba8 100644 --- a/quantum_simulator.py +++ b/quantum_simulator.py @@ -112,6 +112,25 @@ def pauli_x(self, qubit: int) -> None: self._apply_unitary(_X, (qubit,)) + def pauli_y(self, qubit: int) -> None: + """Apply the Pauli-Y gate to ``qubit``. + + The Pauli-Y gate flips the state of a single qubit while also applying a + relative phase factor of ``i``. When acting on ``|0⟩`` the outcome is + ``i|1⟩`` and when acting on ``|1⟩`` the outcome is ``-i|0⟩``. + """ + + self._apply_unitary(_Y, (qubit,)) + + def pauli_z(self, qubit: int) -> None: + """Apply the Pauli-Z gate to ``qubit``. + + The Pauli-Z gate leaves ``|0⟩`` unchanged and flips the phase of ``|1⟩`` + by multiplying it with ``-1``. + """ + + self._apply_unitary(_Z, (qubit,)) + def cnot(self, control: int, target: int) -> None: """Apply a controlled-NOT operation. @@ -279,6 +298,8 @@ def _distribution_from_probabilities(probabilities: np.ndarray, num_qubits: int) _H = np.array([[1, 1], [1, -1]], dtype=np.complex128) / np.sqrt(2) _X = np.array([[0, 1], [1, 0]], dtype=np.complex128) +_Y = np.array([[0, -1j], [1j, 0]], dtype=np.complex128) +_Z = np.array([[1, 0], [0, -1]], dtype=np.complex128) _CNOT = np.array( [ [1, 0, 0, 0], diff --git a/tests/test_quantum_simulator.py b/tests/test_quantum_simulator.py index c58e759..4ff2818 100644 --- a/tests/test_quantum_simulator.py +++ b/tests/test_quantum_simulator.py @@ -20,6 +20,24 @@ def test_pauli_x_flips_ground_state(): assert probs["0"] == pytest.approx(0.0) +def test_pauli_y_flips_state_with_phase(): + circuit = QuantumCircuit(1) + circuit.pauli_y(0) + probs = circuit.probabilities() + assert probs["1"] == pytest.approx(1.0) + assert probs["0"] == pytest.approx(0.0) + + +def test_pauli_z_adds_phase_without_changing_probabilities(): + circuit = QuantumCircuit(1) + circuit.hadamard(0) + circuit.pauli_z(0) + circuit.hadamard(0) + probs = circuit.probabilities() + assert probs["1"] == pytest.approx(1.0) + assert probs["0"] == pytest.approx(0.0) + + def test_cnot_creates_bell_state(): circuit = QuantumCircuit(2) circuit.hadamard(0)