Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
157 changes: 157 additions & 0 deletions testing/test_single_qubit_gates.py
Original file line number Diff line number Diff line change
Expand Up @@ -455,3 +455,160 @@ def test_pauli_z_with_hadamard(self, backend_name):
f"Backend: {backend_name}, "
f"Expected |1⟩ state after H-Z-H sequence, got probability {prob:.4f}"
)


@pytest.mark.parametrize("backend_name", TESTING_BACKENDS)
class TestSingleQubitGatesEdgeCases:
"""Test class for edge cases of single-qubit gates."""

def test_gate_on_uninitialized_circuit(self, backend_name):
"""Test that gates raise error on uninitialized circuit."""
backend_config = get_backend_config(backend_name)
qumat = QuMat(backend_config)

# Try to apply gate without creating circuit
with pytest.raises(RuntimeError, match="circuit not initialized"):
qumat.apply_pauli_x_gate(0)

def test_gate_on_invalid_qubit_index(self, backend_name):
"""Test that gates handle invalid qubit indices appropriately."""
backend_config = get_backend_config(backend_name)
qumat = QuMat(backend_config)
qumat.create_empty_circuit(num_qubits=2)

# Different backends may handle this differently
try:
qumat.apply_pauli_x_gate(5) # Invalid index
except (IndexError, ValueError, RuntimeError, Exception):
pass

def test_gate_on_zero_qubit_circuit(self, backend_name):
"""Test gates on zero-qubit circuit."""
backend_config = get_backend_config(backend_name)
qumat = QuMat(backend_config)
qumat.create_empty_circuit(num_qubits=0)

try:
qumat.apply_pauli_x_gate(0)
results = qumat.execute_circuit()
assert results is not None
except (IndexError, ValueError, RuntimeError, Exception):
pass

def test_multiple_gates_on_same_qubit(self, backend_name):
"""Test applying multiple gates sequentially on the same qubit."""
backend_config = get_backend_config(backend_name)
qumat = QuMat(backend_config)
qumat.create_empty_circuit(num_qubits=1)

# Apply multiple gates in sequence
qumat.apply_pauli_x_gate(0) # |0⟩ -> |1⟩
qumat.apply_hadamard_gate(0) # |1⟩ -> |-⟩
qumat.apply_pauli_z_gate(0) # |-⟩ -> |+⟩
qumat.apply_hadamard_gate(0) # |+⟩ -> |0⟩

# Execute circuit
results = qumat.execute_circuit()

# Calculate probability of |0⟩ state
prob = get_state_probability(results, "0", num_qubits=1)

assert prob > 0.95, (
f"Expected |0⟩ state after gate sequence, got probability {prob}"
)

def test_gates_on_different_qubits_independently(self, backend_name):
"""Test that gates on different qubits operate independently."""
backend_config = get_backend_config(backend_name)
qumat = QuMat(backend_config)
qumat.create_empty_circuit(num_qubits=3)

# Apply different gates to different qubits
qumat.apply_pauli_x_gate(0) # Qubit 0: |0⟩ -> |1⟩
qumat.apply_hadamard_gate(1) # Qubit 1: |0⟩ -> |+⟩
# Qubit 2: remains |0⟩

# Execute circuit
results = qumat.execute_circuit()
if isinstance(results, list):
results = results[0]

total_shots = sum(results.values())

# Check qubit 0=|1⟩, qubit 1=superposition, qubit 2=|0⟩
# Backends use different bit ordering (little-endian vs big-endian)
target_states_count = 0
for state, count in results.items():
if isinstance(state, str):
if backend_name == "qiskit":
# Little-endian: "x01" where x is 0 or 1
if (
len(state) == 3
and state[0] in ["0", "1"]
and state[1] in ["0", "1"]
and state[2] == "1"
and state[0] == "0"
):
target_states_count += count
elif backend_name == "amazon_braket":
# Big-endian: "1x0" where x is 0 or 1
if len(state) == 3 and state[0] == "1" and state[2] == "0":
target_states_count += count
else:
# Cirq: integer format, |100⟩=4, |101⟩=5
if state in [4, 5]:
target_states_count += count

prob_target = target_states_count / total_shots
assert prob_target > 0.4, (
f"Expected high probability for target states, got {prob_target}"
)


class TestSingleQubitGatesConsistency:
"""Test class for consistency checks across all backends."""

@pytest.mark.parametrize(
"gate_name, expected_state_or_behavior",
[
("pauli_x", "1"), # Pauli X should flip |0⟩ to |1⟩
("hadamard", "superposition"), # Hadamard creates superposition
],
)
def test_gate_consistency(self, gate_name, expected_state_or_behavior):
"""Test that gates produce consistent results across 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)

# Apply the gate based on gate_name
if gate_name == "pauli_x":
qumat.apply_pauli_x_gate(0)
elif gate_name == "hadamard":
qumat.apply_hadamard_gate(0)
# Future gates can be easily added here

results = qumat.execute_circuit()

if expected_state_or_behavior == "superposition":
# For Hadamard, check superposition probabilities
prob_zero, _ = get_superposition_probabilities(results, num_qubits=1)
results_dict[backend_name] = prob_zero
else:
# For other gates, check specific state probability
prob = get_state_probability(
results, expected_state_or_behavior, num_qubits=1
)
results_dict[backend_name] = prob

# All backends should give similar results
probabilities = list(results_dict.values())
for i in range(len(probabilities)):
for j in range(i + 1, len(probabilities)):
diff = abs(probabilities[i] - probabilities[j])
assert diff < 0.05, (
f"Backends have inconsistent results for {gate_name}: {results_dict}"
)