This is an automated email from the ASF dual-hosted git repository.

guanmingchiu pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/mahout.git


The following commit(s) were added to refs/heads/main by this push:
     new 8f4ccc3ff MAHOUT-681: Implement T-gate (π/8 gate) across all backends 
(#693)
8f4ccc3ff is described below

commit 8f4ccc3ff5d4c8a37842a5c83316d06b08be0a30
Author: Shivam Mittal <[email protected]>
AuthorDate: Fri Dec 12 11:58:34 2025 +0530

    MAHOUT-681: Implement T-gate (π/8 gate) across all backends (#693)
    
    * Implement T-gate (π/8 gate) across all backends
    
    - Add apply_t_gate() method to QuMat class with validation
    - Implement T-gate support in Qiskit, Cirq, and Amazon Braket backends
    - Restore T-gate documentation in basic_gates.md to match implementation
    
    Fixes #681
    
    * Refine T-gate docs and add coverage
    
    * chore: satisfy pre-commit hooks
---
 docs/basic_gates.md                |   2 +-
 qumat/amazon_braket_backend.py     |   4 ++
 qumat/cirq_backend.py              |   5 ++
 qumat/qiskit_backend.py            |   5 ++
 qumat/qumat.py                     |  15 +++++
 testing/test_single_qubit_gates.py | 112 +++++++++++++++++++++++++++++++++++++
 6 files changed, 142 insertions(+), 1 deletion(-)

diff --git a/docs/basic_gates.md b/docs/basic_gates.md
index 6fe2533f0..e688c6906 100644
--- a/docs/basic_gates.md
+++ b/docs/basic_gates.md
@@ -40,7 +40,7 @@ The Pauli Z gate introduces a phase flip without changing the 
qubit's state. It
 
 It's used for measuring the phase of a qubit.
 
-## T-Gate (π/8 Gate) (New Addition)
+## T-Gate (π/8 Gate)
 The T-Gate applies a **π/4 phase shift** to the qubit. It is essential for 
quantum computing because it, along with the Hadamard and CNOT gates, allows 
for **universal quantum computation**. Mathematically:
 
 \[ T|0⟩ = |0⟩ \]
diff --git a/qumat/amazon_braket_backend.py b/qumat/amazon_braket_backend.py
index 0121c70be..a5e8c1bbe 100644
--- a/qumat/amazon_braket_backend.py
+++ b/qumat/amazon_braket_backend.py
@@ -81,6 +81,10 @@ def apply_pauli_z_gate(circuit, qubit_index):
     circuit.z(qubit_index)
 
 
+def apply_t_gate(circuit, qubit_index):
+    circuit.t(qubit_index)
+
+
 def execute_circuit(circuit, backend, backend_config):
     shots = backend_config["backend_options"].get("shots", 1)
     parameter_values = backend_config.get("parameter_values", {})
diff --git a/qumat/cirq_backend.py b/qumat/cirq_backend.py
index 674d9d4d4..dc09b0856 100644
--- a/qumat/cirq_backend.py
+++ b/qumat/cirq_backend.py
@@ -95,6 +95,11 @@ def apply_pauli_z_gate(circuit, qubit_index):
     circuit.append(cirq.Z(qubit))
 
 
+def apply_t_gate(circuit, qubit_index):
+    qubit = cirq.LineQubit(qubit_index)
+    circuit.append(cirq.T(qubit))
+
+
 def execute_circuit(circuit, backend, backend_config):
     # handle 0-qubit circuits before adding measurements
     if not circuit.all_qubits():
diff --git a/qumat/qiskit_backend.py b/qumat/qiskit_backend.py
index e7156eada..94b773b89 100644
--- a/qumat/qiskit_backend.py
+++ b/qumat/qiskit_backend.py
@@ -85,6 +85,11 @@ def apply_pauli_z_gate(circuit, qubit_index):
     circuit.z(qubit_index)
 
 
+def apply_t_gate(circuit, qubit_index):
+    # Apply a T gate (π/8 gate) on the specified qubit
+    circuit.t(qubit_index)
+
+
 def execute_circuit(circuit, backend, backend_config):
     # Add measurements if they are not already present
     # Check if circuit already has measurement operations
diff --git a/qumat/qumat.py b/qumat/qumat.py
index c1d866de4..99791d8af 100644
--- a/qumat/qumat.py
+++ b/qumat/qumat.py
@@ -251,6 +251,21 @@ class QuMat:
         self._validate_qubit_index(qubit_index)
         self.backend_module.apply_pauli_z_gate(self.circuit, qubit_index)
 
+    def apply_t_gate(self, qubit_index):
+        """Apply a T-gate (π/8 gate) to the specified qubit.
+
+        Applies a relative pi/4 phase (multiplies the |1> state by e^{i*pi/4}).
+        Essential for universal quantum computation when combined with
+        Hadamard and CNOT gates.
+
+        :param qubit_index: Index of the qubit.
+        :type qubit_index: int
+        :raises RuntimeError: If the circuit has not been initialized.
+        """
+        self._ensure_circuit_initialized()
+        self._validate_qubit_index(qubit_index)
+        self.backend_module.apply_t_gate(self.circuit, qubit_index)
+
     def execute_circuit(self, parameter_values=None):
         """Execute the quantum circuit and return the measurement results.
 
diff --git a/testing/test_single_qubit_gates.py 
b/testing/test_single_qubit_gates.py
index 9b66ab4da..af1e379ea 100644
--- a/testing/test_single_qubit_gates.py
+++ b/testing/test_single_qubit_gates.py
@@ -527,6 +527,118 @@ class TestPauliZGate:
         )
 
 
[email protected]("backend_name", TESTING_BACKENDS)
+class TestTGate:
+    """Test class for T gate functionality."""
+
+    @pytest.mark.parametrize(
+        "initial_state, expected_state",
+        [
+            ("0", "0"),  # T leaves |0> unchanged
+            ("1", "1"),  # T applies phase to |1>, measurement unchanged
+        ],
+    )
+    def test_t_gate_preserves_basis_states(
+        self, backend_name, initial_state, expected_state
+    ):
+        """T gate should preserve computational basis measurement outcomes."""
+        backend_config = get_backend_config(backend_name)
+        qumat = QuMat(backend_config)
+        qumat.create_empty_circuit(num_qubits=1)
+
+        if initial_state == "1":
+            qumat.apply_pauli_x_gate(0)
+
+        qumat.apply_t_gate(0)
+        results = qumat.execute_circuit()
+
+        prob = get_state_probability(
+            results, expected_state, num_qubits=1, backend_name=backend_name
+        )
+        assert prob > 0.95, (
+            f"Backend: {backend_name}, expected |{expected_state}> after T, "
+            f"got probability {prob:.4f}"
+        )
+
+    def test_t_gate_phase_visible_via_hzh(self, backend_name):
+        """T^4 = Z; H-Z-H should act like X and flip |0> to |1>."""
+        backend_config = get_backend_config(backend_name)
+        qumat = QuMat(backend_config)
+        qumat.create_empty_circuit(num_qubits=1)
+
+        qumat.apply_hadamard_gate(0)
+        for _ in range(4):
+            qumat.apply_t_gate(0)
+        qumat.apply_hadamard_gate(0)
+
+        results = qumat.execute_circuit()
+        prob = get_state_probability(
+            results, "1", num_qubits=1, backend_name=backend_name
+        )
+        assert prob > 0.95, (
+            f"Backend: {backend_name}, expected |1> after H-T^4-H, "
+            f"got probability {prob:.4f}"
+        )
+
+    def test_t_gate_eight_applications_identity(self, backend_name):
+        """T^8 should be identity."""
+        backend_config = get_backend_config(backend_name)
+        qumat = QuMat(backend_config)
+        qumat.create_empty_circuit(num_qubits=1)
+
+        for _ in range(8):
+            qumat.apply_t_gate(0)
+
+        results = qumat.execute_circuit()
+        prob = get_state_probability(
+            results, "0", num_qubits=1, backend_name=backend_name
+        )
+        assert prob > 0.95, (
+            f"Backend: {backend_name}, expected |0> after T^8, "
+            f"got probability {prob:.4f}"
+        )
+
+
[email protected](
+    "phase_applications",
+    [
+        1,  # single T
+        2,  # T^2 = S
+        4,  # T^4 = Z
+    ],
+)
+def test_t_gate_cross_backend_consistency(phase_applications):
+    """T gate should behave consistently across all backends."""
+    results_dict = {}
+
+    for backend_name in TESTING_BACKENDS:
+        backend_config = get_backend_config(backend_name)
+        qumat = QuMat(backend_config)
+        qumat.create_empty_circuit(num_qubits=1)
+
+        # Use H ... H sandwich to turn phase into amplitude when needed
+        qumat.apply_hadamard_gate(0)
+        for _ in range(phase_applications):
+            qumat.apply_t_gate(0)
+        qumat.apply_hadamard_gate(0)
+
+        results = qumat.execute_circuit()
+        prob_one = get_state_probability(
+            results, "1", num_qubits=1, backend_name=backend_name
+        )
+        results_dict[backend_name] = prob_one
+
+    backends = list(results_dict.keys())
+    for i in range(len(backends)):
+        for j in range(i + 1, len(backends)):
+            b1, b2 = backends[i], backends[j]
+            diff = abs(results_dict[b1] - results_dict[b2])
+            assert diff < 0.05, (
+                f"T gate inconsistent between {b1} and {b2} for 
T^{phase_applications}: "
+                f"{results_dict[b1]:.4f} vs {results_dict[b2]:.4f}"
+            )
+
+
 @pytest.mark.parametrize("backend_name", TESTING_BACKENDS)
 class TestSingleQubitGatesEdgeCases:
     """Test class for edge cases of single-qubit gates."""

Reply via email to