File size: 3,809 Bytes
2a87ede
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
"""

Tests for dashboard_core.graphical_builder.ops_to_native_tuples -- the op

list produced by the drag-and-drop circuit builder component must turn

into dense_evolution's own (name, *qubits[, param]) gate tuples that run

on the exact same engine as typed OpenQASM. No Qiskit QuantumCircuit is

ever built here (see dashboard_core/engine.py's module docstring for why

that matters on macOS), so this file needs no macOS skip at all.

"""

import numpy as np
import pytest

from dashboard_core.engine import run_circuit_from_qasm
from dashboard_core.graphical_builder import ops_to_native_tuples
from dashboard_core.qasm_library import gate_tuples_to_qasm


def test_bell_state_ops_match_bell_qasm():
    ops = [
        {"gate": "h", "qubits": [0]},
        {"gate": "cx", "qubits": [0, 1]},
    ]
    native = ops_to_native_tuples(2, ops)
    qasm_from_grid = gate_tuples_to_qasm(native, 2)

    result_from_grid = run_circuit_from_qasm(qasm_from_grid, n_shots=10, seed=1)
    result_from_bell_qasm = run_circuit_from_qasm(
        'OPENQASM 2.0;\ninclude "qelib1.inc";\nqreg q[2];\ncreg c[2];\n'
        'h q[0];\ncx q[0],q[1];\nmeasure q -> c;\n',
        n_shots=10, seed=1,
    )
    assert np.allclose(result_from_grid.statevector, result_from_bell_qasm.statevector, atol=1e-9)


def test_single_qubit_gates_placed_correctly():
    ops = [{"gate": "x", "qubits": [1]}]
    native = ops_to_native_tuples(3, ops)
    qasm = gate_tuples_to_qasm(native, 3)
    result = run_circuit_from_qasm(qasm, n_shots=10, seed=1)
    # X on qubit 1 (Qiskit little-endian: qubit 1 is bit index 1) -> state |010> = index 2
    expected = np.zeros(8, dtype=complex)
    expected[0b010] = 1.0
    assert np.allclose(result.statevector, expected, atol=1e-9)


def test_cy_and_cz_gates():
    ops_cz = [{"gate": "h", "qubits": [0]}, {"gate": "cz", "qubits": [0, 1]}]
    native_cz = ops_to_native_tuples(2, ops_cz)
    assert any(op[0] == "cz" for op in native_cz)

    ops_cy = [{"gate": "h", "qubits": [0]}, {"gate": "cy", "qubits": [0, 1]}]
    native_cy = ops_to_native_tuples(2, ops_cy)
    assert any(op[0] == "cy" for op in native_cy)


def test_swap_gate():
    ops = [{"gate": "x", "qubits": [0]}, {"gate": "swap", "qubits": [0, 1]}]
    native = ops_to_native_tuples(2, ops)
    qasm = gate_tuples_to_qasm(native, 2)
    result = run_circuit_from_qasm(qasm, n_shots=10, seed=1)
    # X on qubit 0 then SWAP(0,1) -> qubit 1 ends up excited -> |10> (bit1=1,bit0=0) = index 2
    expected = np.zeros(4, dtype=complex)
    expected[0b10] = 1.0
    assert np.allclose(result.statevector, expected, atol=1e-9)


def test_rotation_gate_applies_a_real_nonzero_rotation():
    ops = [{"gate": "rx", "qubits": [0]}]
    native = ops_to_native_tuples(1, ops)
    qasm = gate_tuples_to_qasm(native, 1)
    result = run_circuit_from_qasm(qasm, n_shots=10, seed=1)
    # Rx(pi/2)|0> is an equal-ish superposition, not |0> or |1> exactly.
    assert not np.allclose(np.abs(result.statevector), [1.0, 0.0], atol=1e-6)
    assert not np.allclose(np.abs(result.statevector), [0.0, 1.0], atol=1e-6)


def test_unknown_gate_raises():
    with pytest.raises(ValueError, match="unknown gate"):
        ops_to_native_tuples(2, [{"gate": "bogus", "qubits": [0]}])


def test_out_of_range_qubit_raises():
    with pytest.raises(ValueError, match="out of range"):
        ops_to_native_tuples(2, [{"gate": "h", "qubits": [5]}])


def test_zero_qubits_raises():
    with pytest.raises(ValueError, match="at least 1 qubit"):
        ops_to_native_tuples(0, [])


def test_empty_ops_is_just_measurement():
    native = ops_to_native_tuples(2, [])
    assert native == []
    qasm = gate_tuples_to_qasm(native, 2)
    assert "measure q -> c;" in qasm