diff --git a/src/qiskit_qir/visitor.py b/src/qiskit_qir/visitor.py index c82c6ce..40fe4cc 100644 --- a/src/qiskit_qir/visitor.py +++ b/src/qiskit_qir/visitor.py @@ -52,6 +52,7 @@ "cz", "h", "reset", + "delay", "rx", "ry", "rz", @@ -75,6 +76,7 @@ "m", "measure", "reset", + "delay", "rx", "ry", "rz", @@ -88,9 +90,7 @@ "z", ] -_NOOP_INSTRUCTIONS = ["delay"] - -_SUPPORTED_INSTRUCTIONS = _QUANTUM_INSTRUCTIONS + _NOOP_INSTRUCTIONS +_SUPPORTED_INSTRUCTIONS = _QUANTUM_INSTRUCTIONS class QuantumCircuitElementVisitor(metaclass=ABCMeta): @@ -311,7 +311,13 @@ def __branch(): if self._emit_barrier_calls: qis.barrier(self._builder) elif "delay" == instruction.name: - pass + # us is chosen as the default time unit in QIR since it is well + # suited to current performance of qubit implementations. + # When using dt, the backend-dependent time unit, the duration + # value is left untouched. + multipliers = {"s": 1e6, "ms": 1e3, "us": 1, "ns": 1e-3, "ps": 1e-6, "dt": 1} + duration = instruction.duration * multipliers[instruction.unit] + qis.delay(self._builder, duration, *qubits) elif "swap" == instruction.name: qis.swap(self._builder, *qubits) elif "ccx" == instruction.name: diff --git a/tests/test_circuits/basic_gates.py b/tests/test_circuits/basic_gates.py index 78600da..8d901a3 100644 --- a/tests/test_circuits/basic_gates.py +++ b/tests/test_circuits/basic_gates.py @@ -25,6 +25,8 @@ _measurements = {"measure": "mz"} +_delays = {"delay": "delay"} + _rotations = {"rx": "rx", "ry": "ry", "rz": "rz"} _two_qubit_gates = {"cx": "cnot", "cz": "cz", "swap": "swap"} @@ -43,6 +45,8 @@ def _map_gate_name(gate: str) -> str: return _adj_gates[gate] elif gate in _measurements: return _measurements[gate] + elif gate in _delays: + return _delays[gate] elif gate in _rotations: return _rotations[gate] elif gate in _two_qubit_gates: @@ -76,6 +80,27 @@ def test_fixture(): locals()[name] = _generate_one_qubit_fixture(gate) +def _generate_delay_gate_fixture(unit: str): + @pytest.fixture() + def test_fixture(): + circuit = QuantumCircuit(1) + if unit == 'dt': + circuit.delay(1, 0, unit=unit) + else: + circuit.delay(0.5, 0, unit=unit) + return _map_gate_name('delay'), unit, circuit + + return test_fixture + + +delay_tests = [] +# Generate time param operation fixtures +for unit in {'s', 'ms', 'us', 'ns', 'ps', 'dt'}: + name = _fixture_name('delay_' + unit) + delay_tests.append(name) + locals()[name] = _generate_delay_gate_fixture(unit) + + def _generate_rotation_fixture(gate: str): @pytest.fixture() def test_fixture(): diff --git a/tests/test_qiskit_qir.py b/tests/test_qiskit_qir.py index 62c66eb..d386193 100644 --- a/tests/test_qiskit_qir.py +++ b/tests/test_qiskit_qir.py @@ -16,6 +16,7 @@ from test_circuits.basic_gates import ( single_op_tests, adj_op_tests, + delay_tests, rotation_tests, double_op_tests, triple_op_tests, @@ -112,6 +113,7 @@ def test_adj_gates(circuit_name, request): def test_rotation_gates(circuit_name, request): qir_op, circuit = request.getfixturevalue(circuit_name) generated_qir = str(to_qir_module(circuit)[0]).splitlines() + print(generated_qir) test_utils.check_attributes(generated_qir, 1, 0) func = test_utils.get_entry_point_body(generated_qir) assert func[0] == test_utils.initialize_call_string() @@ -120,6 +122,25 @@ def test_rotation_gates(circuit_name, request): assert len(func) == 3 +@pytest.mark.parametrize("circuit_name", delay_tests) +def test_delay_gate(circuit_name, request): + qir_op, unit, circuit = request.getfixturevalue(circuit_name) + generated_qir = str(to_qir_module(circuit)[0]).splitlines() + print(circuit) + print(generated_qir) + test_utils.check_attributes(generated_qir, 1, 0) + func = test_utils.get_entry_point_body(generated_qir) + assert func[0] == test_utils.initialize_call_string() + if unit == 'dt': + assert func[1] == test_utils.rotation_call_string(qir_op, 1, 0) + else: + multipliers = {"s": 1e6, "ms": 1e3, "us": 1, "ns": 1e-3, "ps": 1e-6} + duration = 0.5 * multipliers[unit] + assert func[1] == test_utils.rotation_call_string(qir_op, duration, 0) + assert func[2] == test_utils.return_string() + assert len(func) == 3 + + @pytest.mark.parametrize("circuit_name", double_op_tests) def test_double_qubit_gates(circuit_name, request): qir_op, circuit = request.getfixturevalue(circuit_name)