|
| 1 | +# test/test_injection_qiskit.py |
| 2 | +""" |
| 3 | +Qiskit 2-qubit injection test suite. |
| 4 | +Verifies that log-negativity and Bell fidelity correctly distinguish |
| 5 | +entangled states from product-state noise. |
| 6 | +
|
| 7 | +Skipped automatically if qiskit / qiskit-aer are not installed. |
| 8 | +""" |
| 9 | + |
| 10 | +import pytest |
| 11 | + |
| 12 | +try: |
| 13 | + from qiskit import QuantumCircuit # noqa: F401 |
| 14 | + QISKIT_AVAILABLE = True |
| 15 | +except ImportError: |
| 16 | + QISKIT_AVAILABLE = False |
| 17 | + |
| 18 | +skip_if_no_qiskit = pytest.mark.skipif( |
| 19 | + not QISKIT_AVAILABLE, |
| 20 | + reason="qiskit / qiskit-aer not installed" |
| 21 | +) |
| 22 | + |
| 23 | + |
| 24 | +@skip_if_no_qiskit |
| 25 | +def test_bell_state_log_negativity(): |
| 26 | + """Bell state |Φ+⟩ must have E_N ≈ 1.0 (maximum for 2 qubits).""" |
| 27 | + from src.ibm_validation.injection_tests import ( |
| 28 | + make_bell_circuit, compute_log_negativity |
| 29 | + ) |
| 30 | + EN = compute_log_negativity(make_bell_circuit()) |
| 31 | + assert EN > 0.95, f"Bell state E_N should be ≈1.0, got {EN:.4f}" |
| 32 | + |
| 33 | + |
| 34 | +@skip_if_no_qiskit |
| 35 | +def test_product_noise_log_negativity(): |
| 36 | + """Product (noise) states must have E_N ≈ 0 regardless of angles.""" |
| 37 | + from src.ibm_validation.injection_tests import ( |
| 38 | + make_noise_circuit, compute_log_negativity |
| 39 | + ) |
| 40 | + for seed in [0, 7, 42, 99, 123]: |
| 41 | + qc = make_noise_circuit(seed=seed) |
| 42 | + EN = compute_log_negativity(qc) |
| 43 | + assert EN < 1e-9, f"Seed {seed}: noise E_N should be 0, got {EN:.6f}" |
| 44 | + |
| 45 | + |
| 46 | +@skip_if_no_qiskit |
| 47 | +def test_bell_fidelity_is_one(): |
| 48 | + """Bell circuit fidelity with ideal |Φ+⟩ should be exactly 1.""" |
| 49 | + from src.ibm_validation.injection_tests import ( |
| 50 | + make_bell_circuit, compute_bell_fidelity |
| 51 | + ) |
| 52 | + fidelity = compute_bell_fidelity(make_bell_circuit()) |
| 53 | + assert abs(fidelity - 1.0) < 1e-9, f"Bell fidelity should be 1.0, got {fidelity}" |
| 54 | + |
| 55 | + |
| 56 | +@skip_if_no_qiskit |
| 57 | +def test_injection_signal_clearly_above_noise(): |
| 58 | + """ |
| 59 | + Core injection test: E_N(signal) >> E_N(noise). |
| 60 | + This mirrors the BasQ vorticity-vs-EM-noise validation pattern. |
| 61 | + """ |
| 62 | + from src.ibm_validation.injection_tests import ( |
| 63 | + make_bell_circuit, make_noise_circuit, compute_log_negativity |
| 64 | + ) |
| 65 | + EN_signal = compute_log_negativity(make_bell_circuit()) |
| 66 | + EN_noise = compute_log_negativity(make_noise_circuit(seed=42)) |
| 67 | + |
| 68 | + assert EN_signal > EN_noise + 0.8, ( |
| 69 | + f"Signal and noise not clearly separated: " |
| 70 | + f"E_N(signal)={EN_signal:.4f}, E_N(noise)={EN_noise:.4f}" |
| 71 | + ) |
| 72 | + |
| 73 | + |
| 74 | +@skip_if_no_qiskit |
| 75 | +def test_full_injection_run_passes(): |
| 76 | + """End-to-end injection test: run_injection_test() must pass.""" |
| 77 | + from src.ibm_validation.injection_tests import run_injection_test |
| 78 | + results = run_injection_test(shots=2000, noise_seed=42) |
| 79 | + assert results["passed"], ( |
| 80 | + f"Injection test failed.\n" |
| 81 | + f" Signal E_N = {results['signal']['log_negativity']:.4f}\n" |
| 82 | + f" Noise E_N = {results['noise']['log_negativity']:.4f}\n" |
| 83 | + f" Status: {results['status']}" |
| 84 | + ) |
0 commit comments