From c694cfa27e4af16ebc3a77403f2ac6229a12e994 Mon Sep 17 00:00:00 2001 From: WingCode Date: Fri, 31 May 2024 01:14:31 +0200 Subject: [PATCH 1/9] Improve coverage to 100% --- tests/providers/test_adapter.py | 21 ++++++++++++++ tests/providers/test_braket_backend.py | 38 ++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/tests/providers/test_adapter.py b/tests/providers/test_adapter.py index 9a0d193..564021a 100644 --- a/tests/providers/test_adapter.py +++ b/tests/providers/test_adapter.py @@ -329,6 +329,15 @@ def test_measure(self): ) self.assertEqual(braket_circuit, expected_braket_circuit) + + def test_measure_(self): + """Tests if NotImplementedError is raised for reset operation.""" + + qiskit_circuit = QuantumCircuit(1, 1) + qiskit_circuit.reset(0) + + with self.assertRaises(NotImplementedError): + to_braket(qiskit_circuit) def test_measure_different_indices(self): """ @@ -657,6 +666,18 @@ def test_power(self): self.assertEqual(qiskit_circuit, expected_qiskit_circuit) + def test_unsupported_braket_gate(self): + """Tests if TypeError is raised for unsupported Braket gate.""" + + gate = getattr(Gate, "CNot") + op = gate() + instr = Instruction(op, range(2)) + circuit = Circuit().add_instruction(instr) + + with self.assertRaises(TypeError): + with patch.dict('qiskit_braket_provider.providers.adapter._GATE_NAME_TO_QISKIT_GATE', {'cnot': None}): + to_qiskit(circuit) + def test_measure_subset(self): """Tests the measure instruction conversion from braket to qiskit""" braket_circuit = Circuit().h(0).cnot(0, 1).measure(0) diff --git a/tests/providers/test_braket_backend.py b/tests/providers/test_braket_backend.py index 3435481..50bf38c 100644 --- a/tests/providers/test_braket_backend.py +++ b/tests/providers/test_braket_backend.py @@ -8,6 +8,7 @@ import numpy as np from botocore import errorfactory from braket.aws.queue_information import QueueDepthInfo, QueueType +from braket.device_schema import DeviceActionType from qiskit import QuantumCircuit, transpile from qiskit.circuit.library import TwoLocal from qiskit.circuit.random import random_circuit @@ -319,3 +320,40 @@ def test_target(self): self.assertEqual(len(target.operations), 2) self.assertEqual(len(target.instructions), 60) self.assertIn("Target for Amazon Braket QPU", target.description) + + def test_target_invalid_device(self): + """Tests target.""" + mock_device = Mock() + mock_device.properties = None + + with self.assertRaises(exception.QiskitBraketException): + aws_device_to_target(mock_device) + + def test_fully_connected(self): + """Tests if instruction_props is correctly populated for fully connected topology.""" + mock_device = Mock() + mock_device.properties = RIGETTI_MOCK_GATE_MODEL_QPU_CAPABILITIES.copy(deep=True) + mock_device.properties.paradigm.connectivity.fullyConnected = True + mock_device.properties.paradigm.qubitCount = 2 + mock_device.properties.action.get(DeviceActionType.OPENQASM).supportedOperations = ["CNOT"] + + instruction_props = aws_device_to_target(mock_device) + + from qiskit.circuit import Instruction + + cx_instruction = Instruction(name="cx", num_qubits=2, num_clbits=0, params=[]) + measure_instruction = Instruction(name="measure", num_qubits=1, num_clbits=1, params=[]) + + expected_instruction_props = [ + (cx_instruction, (0, 1)), + (cx_instruction, (1, 0)), + (measure_instruction, (0,)), + (measure_instruction, (1,)) + ] + for index, instruction in enumerate(instruction_props.instructions): + self.assertEqual(instruction[0].num_qubits, expected_instruction_props[index][0].num_qubits) + self.assertEqual(instruction[0].num_clbits, expected_instruction_props[index][0].num_clbits) + self.assertEqual(instruction[0].params, expected_instruction_props[index][0].params) + self.assertEqual(instruction[0].name, expected_instruction_props[index][0].name) + + self.assertEqual(instruction[1], expected_instruction_props[index][1]) From 24f1a37bc955120b7c53fdab3daff190f1e4c39e Mon Sep 17 00:00:00 2001 From: WingCode Date: Fri, 31 May 2024 03:45:48 +0200 Subject: [PATCH 2/9] Improve coverage to 100% --- tests/providers/mocks.py | 21 +++++ tests/providers/test_braket_backend.py | 109 +++++++++++++++++++++++++ 2 files changed, 130 insertions(+) diff --git a/tests/providers/mocks.py b/tests/providers/mocks.py index ae716bb..b5a9d03 100644 --- a/tests/providers/mocks.py +++ b/tests/providers/mocks.py @@ -1,6 +1,7 @@ """Mocks for testing.""" import copy +import enum import uuid from collections import Counter from typing import Dict @@ -11,6 +12,7 @@ from braket.task_result import TaskMetadata from braket.tasks import GateModelQuantumTaskResult from braket.tasks.local_quantum_task import LocalQuantumTask +from qiskit_braket_provider.providers.braket_backend import BraketBackend RIGETTI_ARN = "arn:aws:braket:::device/qpu/rigetti/Aspen-10" RIGETTI_ASPEN_ARN = "arn:aws:braket:::device/qpu/rigetti/Aspen-M-3" @@ -158,3 +160,22 @@ ) MOCK_LOCAL_QUANTUM_TASK = LocalQuantumTask(MOCK_GATE_MODEL_QUANTUM_TASK_RESULT) + +class MockBraketBackend(BraketBackend): + + @property + def target(self): + pass + + @property + def max_circuits(self): + pass + + def _default_options(self): + pass + + def run(self): + pass + +class MockMeasLevelEnum(enum.Enum): + LEVEL_TWO = 2 \ No newline at end of file diff --git a/tests/providers/test_braket_backend.py b/tests/providers/test_braket_backend.py index 50bf38c..5d15266 100644 --- a/tests/providers/test_braket_backend.py +++ b/tests/providers/test_braket_backend.py @@ -7,8 +7,11 @@ import numpy as np from botocore import errorfactory +from braket.aws import AwsDevice +from braket.aws import AwsQuantumTaskBatch from braket.aws.queue_information import QueueDepthInfo, QueueType from braket.device_schema import DeviceActionType +from braket.tasks.local_quantum_task import LocalQuantumTask from qiskit import QuantumCircuit, transpile from qiskit.circuit.library import TwoLocal from qiskit.circuit.random import random_circuit @@ -22,9 +25,12 @@ from qiskit_braket_provider import AWSBraketProvider, exception, version from qiskit_braket_provider.providers import BraketAwsBackend, BraketLocalBackend from qiskit_braket_provider.providers.adapter import aws_device_to_target +from qiskit_braket_provider.providers.braket_backend import AWSBraketBackend from tests.providers.mocks import ( RIGETTI_MOCK_GATE_MODEL_QPU_CAPABILITIES, RIGETTI_MOCK_M_3_QPU_CAPABILITIES, + MockBraketBackend, + MockMeasLevelEnum, ) @@ -54,6 +60,15 @@ def combine_dicts( return combined_dict +class TestBraketBackend(TestCase): + def test_repr(self): + backend = BraketLocalBackend(name="default") + self.assertEqual(repr(backend), "BraketBackend[default]") + + def test_device(self): + with self.assertRaises(NotImplementedError): + MockBraketBackend(name="default")._device + class TestBraketAwsBackend(TestCase): """Tests BraketBackend.""" @@ -67,6 +82,12 @@ def test_device_backend(self): self.assertIsNone(backend.max_circuits) user_agent = f"QiskitBraketProvider/" f"{version.__version__}" device.aws_session.add_braket_user_agent.assert_called_with(user_agent) + with self.assertRaises(NotImplementedError): + backend.dtm() + with self.assertRaises(NotImplementedError): + backend.meas_map() + with self.assertRaises(NotImplementedError): + backend.qubit_properties(0) with self.assertRaises(NotImplementedError): backend.drive_channel(0) with self.assertRaises(NotImplementedError): @@ -76,12 +97,25 @@ def test_device_backend(self): with self.assertRaises(NotImplementedError): backend.control_channel([0, 1]) + def test_invalid_identifiers(self): + with self.assertRaises(ValueError): + BraketAwsBackend() + + with self.assertRaises(ValueError): + BraketAwsBackend(arn="some_arn", device="some_device") + def test_local_backend(self): """Tests local backend.""" backend = BraketLocalBackend(name="default") self.assertTrue(backend) self.assertIsInstance(backend.target, Target) self.assertIsNone(backend.max_circuits) + with self.assertRaises(NotImplementedError): + backend.dtm() + with self.assertRaises(NotImplementedError): + backend.meas_map() + with self.assertRaises(NotImplementedError): + backend.qubit_properties(0) with self.assertRaises(NotImplementedError): backend.drive_channel(0) with self.assertRaises(NotImplementedError): @@ -140,6 +174,60 @@ def test_local_backend_circuit_shots0(self): result.get_statevector(), np.array([0, 0, inv_sqrt_2, inv_sqrt_2]) ) ) + + def test_deprecation_warning_on_init(self): + with self.assertWarns(DeprecationWarning): + AWSBraketBackend(device=AwsDevice("arn:aws:braket:::device/quantum-simulator/amazon/sv1")) + + def test_deprecation_warning_on_subclass(self): + with self.assertWarns(DeprecationWarning): + class SubclassAWSBraketBackend(AWSBraketBackend): + pass + + def test_run_multiple_circuits(self): + """Tests run with multiple circuits""" + device = Mock() + device.properties = RIGETTI_MOCK_GATE_MODEL_QPU_CAPABILITIES + backend = BraketAwsBackend(device=device) + mock_task_1 = Mock(spec=LocalQuantumTask) + mock_task_1.id = '0' + mock_task_2 = Mock(spec=LocalQuantumTask) + mock_task_2.id = '1' + mock_batch = Mock(spec=AwsQuantumTaskBatch) + mock_batch.tasks = [mock_task_1, mock_task_2] + backend._device.run_batch = Mock(return_value=mock_batch) + circuit = QuantumCircuit(1) + circuit.h(0) + + backend.run([circuit, circuit], shots=0, meas_level=2) + + def test_run_invalid_run_input(self): + """Tests run with invalid input to run""" + device = Mock() + device.properties = RIGETTI_MOCK_GATE_MODEL_QPU_CAPABILITIES + backend = BraketAwsBackend(device=device) + with self.assertRaises(exception.QiskitBraketException): + backend.run(1, shots=0) + + @patch('braket.devices.LocalSimulator.run', side_effect=[Mock(return_value=Mock(id='0', spec=LocalQuantumTask)), Exception('Mock exception')]) + def test_local_backend_run_exception(self, braket_devices_run): + """Tests local backend with exception thrown during second run""" + backend = BraketLocalBackend(name="default") + + circuit = QuantumCircuit(1) + circuit.h(0) + + with self.assertRaises(Exception): + backend.run([circuit, circuit], shots=0) # First run should pass + braket_devices_run.assert_called() + + def test_meas_level_enum(self): + """Check that enum meas level can be successfully accessed without error""" + backend = BraketLocalBackend(name="default") + circuit = QuantumCircuit(1, 1) + circuit.h(0) + circuit.measure(0, 0) + backend.run(circuit, shots=10, meas_level=MockMeasLevelEnum.LEVEL_TWO) def test_meas_level_2(self): """Check that there's no error for asking for classified measurement results.""" @@ -227,6 +315,27 @@ def test_random_circuits(self): f"and absolute difference {abs_diff}. Original values {values}", ) + @patch('qiskit_braket_provider.providers.braket_backend.AwsQuantumTask') + @patch('qiskit_braket_provider.providers.braket_backend.BraketQuantumTask') + def test_retrieve_job_task_ids(self, mock_braket_quantum_task, mock_aws_quantum_task): + device = Mock() + device.properties = RIGETTI_MOCK_GATE_MODEL_QPU_CAPABILITIES + backend = BraketAwsBackend(device=device) + task_id = "task1;task2;task3" + expected_task_ids = task_id.split(";") + + backend.retrieve_job(task_id) + + # Assert + mock_aws_quantum_task.assert_any_call(arn=expected_task_ids[0]) + mock_aws_quantum_task.assert_any_call(arn=expected_task_ids[1]) + mock_aws_quantum_task.assert_any_call(arn=expected_task_ids[2]) + mock_braket_quantum_task.assert_called_once_with( + task_id=task_id, + backend=backend, + tasks=[mock_aws_quantum_task(arn=task_id) for task_id in expected_task_ids] + ) + @unittest.skip("Call to external resources.") def test_retrieve_job(self): """Tests retrieve task by id.""" From 0abe1db75abb4c5bda21332d5f7e41600a7d504b Mon Sep 17 00:00:00 2001 From: WingCode Date: Thu, 6 Jun 2024 11:00:02 +0200 Subject: [PATCH 3/9] Add noise model --- .../providers/braket_backend.py | 4 ++- .../providers/braket_provider.py | 26 +++++++++++++++++-- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/qiskit_braket_provider/providers/braket_backend.py b/qiskit_braket_provider/providers/braket_backend.py index 8e7416d..31784fb 100644 --- a/qiskit_braket_provider/providers/braket_backend.py +++ b/qiskit_braket_provider/providers/braket_backend.py @@ -76,7 +76,9 @@ def __init__(self, name: str = "default", **fields): """ super().__init__(name=name, **fields) self.backend_name = name - self._local_device = LocalSimulator(backend=self.backend_name) + self._local_device = LocalSimulator( + backend=self.backend_name, noise_model=fields.get("noise_model") + ) self._target = local_simulator_to_target(self._local_device) self.status = self._local_device.status diff --git a/qiskit_braket_provider/providers/braket_provider.py b/qiskit_braket_provider/providers/braket_provider.py index 10494f8..e68ad48 100644 --- a/qiskit_braket_provider/providers/braket_provider.py +++ b/qiskit_braket_provider/providers/braket_provider.py @@ -3,6 +3,7 @@ import warnings from braket.aws import AwsDevice +from braket.circuits.noise_model import NoiseModel from braket.device_schema.dwave import DwaveDeviceCapabilities from braket.device_schema.quera import QueraDeviceCapabilities from braket.device_schema.xanadu import XanaduDeviceCapabilities @@ -29,11 +30,32 @@ class BraketProvider(ProviderV1): BraketBackend[dm1]] """ + def set_noise_model(self, noise_model: NoiseModel) -> None: + """Set the noise model of the device. + + Args: + noise_model (NoiseModel): The Braket noise model to apply to the circuit before + execution. Noise model can only be added to the devices that support noise + simulation. + """ + self._validate_noise_model_support(noise_model) + self._noise_model = noise_model + + def _validate_noise_model_support(self, noise_model: NoiseModel) -> None: + if not isinstance(noise_model, NoiseModel): + raise ValueError( + "Invalid noise model specified. Should be instance of Braket noise model" + ) + def backends(self, name=None, **kwargs): + noise_model = kwargs.get("noise_model") + if noise_model: + self.set_noise_model(noise_model) + if kwargs.get("local"): return [ - BraketLocalBackend(name="braket_sv"), - BraketLocalBackend(name="braket_dm"), + BraketLocalBackend(name="braket_sv", noise_model=noise_model), + BraketLocalBackend(name="braket_dm", noise_model=noise_model), ] names = [name] if name else None devices = AwsDevice.get_devices(names=names, **kwargs) From 2410c5d69f2e524d07d38041813975a297400a6f Mon Sep 17 00:00:00 2001 From: WingCode Date: Thu, 6 Jun 2024 12:43:13 +0200 Subject: [PATCH 4/9] Fix kwargs --- qiskit_braket_provider/providers/braket_provider.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qiskit_braket_provider/providers/braket_provider.py b/qiskit_braket_provider/providers/braket_provider.py index e68ad48..093bbae 100644 --- a/qiskit_braket_provider/providers/braket_provider.py +++ b/qiskit_braket_provider/providers/braket_provider.py @@ -48,7 +48,7 @@ def _validate_noise_model_support(self, noise_model: NoiseModel) -> None: ) def backends(self, name=None, **kwargs): - noise_model = kwargs.get("noise_model") + noise_model = kwargs.pop("noise_model") if "noise_model" in kwargs else None if noise_model: self.set_noise_model(noise_model) From 8cebd154a172e7b3b64a9cbb40da0d2dcdc1a9e4 Mon Sep 17 00:00:00 2001 From: WingCode Date: Thu, 6 Jun 2024 12:43:59 +0200 Subject: [PATCH 5/9] Add noise model tests --- tests/providers/test_braket_provider.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/providers/test_braket_provider.py b/tests/providers/test_braket_provider.py index 07295a5..96886f9 100644 --- a/tests/providers/test_braket_provider.py +++ b/tests/providers/test_braket_provider.py @@ -71,6 +71,25 @@ def test_real_devices(self): with self.subTest(f"{backend.name}"): self.assertIsInstance(backend, BraketAwsBackend) + def test_add_valid_noise_model(self): + provider = BraketProvider() + from braket.circuits.noise_model import NoiseModel + + assert provider.backends( + aws_session=self.mock_session, + types=[AwsDeviceType.SIMULATOR], + noise_model=NoiseModel(), + ) + + def test_add_invalid_noise_model(self): + provider = BraketProvider() + with self.assertRaises(ValueError): + provider.backends( + aws_session=self.mock_session, + types=[AwsDeviceType.SIMULATOR], + noise_model=Mock(), + ) + @patch("qiskit_braket_provider.providers.braket_backend.BraketAwsBackend") @patch("qiskit_braket_provider.providers.braket_backend.AwsDevice.get_devices") def test_qiskit_circuit_transpilation_run( From be70e800888c8a14e1634730b0fe54b6066e77db Mon Sep 17 00:00:00 2001 From: WingCode Date: Thu, 6 Jun 2024 12:47:34 +0200 Subject: [PATCH 6/9] Fix lint --- tests/providers/mocks.py | 6 ++- tests/providers/test_adapter.py | 13 +++-- tests/providers/test_braket_backend.py | 73 ++++++++++++++++++-------- 3 files changed, 62 insertions(+), 30 deletions(-) diff --git a/tests/providers/mocks.py b/tests/providers/mocks.py index b5a9d03..800bb6d 100644 --- a/tests/providers/mocks.py +++ b/tests/providers/mocks.py @@ -12,6 +12,7 @@ from braket.task_result import TaskMetadata from braket.tasks import GateModelQuantumTaskResult from braket.tasks.local_quantum_task import LocalQuantumTask + from qiskit_braket_provider.providers.braket_backend import BraketBackend RIGETTI_ARN = "arn:aws:braket:::device/qpu/rigetti/Aspen-10" @@ -161,8 +162,8 @@ MOCK_LOCAL_QUANTUM_TASK = LocalQuantumTask(MOCK_GATE_MODEL_QUANTUM_TASK_RESULT) -class MockBraketBackend(BraketBackend): +class MockBraketBackend(BraketBackend): @property def target(self): pass @@ -177,5 +178,6 @@ def _default_options(self): def run(self): pass + class MockMeasLevelEnum(enum.Enum): - LEVEL_TWO = 2 \ No newline at end of file + LEVEL_TWO = 2 diff --git a/tests/providers/test_adapter.py b/tests/providers/test_adapter.py index 564021a..58edcde 100644 --- a/tests/providers/test_adapter.py +++ b/tests/providers/test_adapter.py @@ -329,7 +329,7 @@ def test_measure(self): ) self.assertEqual(braket_circuit, expected_braket_circuit) - + def test_measure_(self): """Tests if NotImplementedError is raised for reset operation.""" @@ -669,14 +669,17 @@ def test_power(self): def test_unsupported_braket_gate(self): """Tests if TypeError is raised for unsupported Braket gate.""" - gate = getattr(Gate, "CNot") + gate = getattr(Gate, "CNot") op = gate() instr = Instruction(op, range(2)) circuit = Circuit().add_instruction(instr) - + with self.assertRaises(TypeError): - with patch.dict('qiskit_braket_provider.providers.adapter._GATE_NAME_TO_QISKIT_GATE', {'cnot': None}): - to_qiskit(circuit) + with patch.dict( + "qiskit_braket_provider.providers.adapter._GATE_NAME_TO_QISKIT_GATE", + {"cnot": None}, + ): + to_qiskit(circuit) def test_measure_subset(self): """Tests the measure instruction conversion from braket to qiskit""" diff --git a/tests/providers/test_braket_backend.py b/tests/providers/test_braket_backend.py index 5d15266..ee5a860 100644 --- a/tests/providers/test_braket_backend.py +++ b/tests/providers/test_braket_backend.py @@ -7,8 +7,7 @@ import numpy as np from botocore import errorfactory -from braket.aws import AwsDevice -from braket.aws import AwsQuantumTaskBatch +from braket.aws import AwsDevice, AwsQuantumTaskBatch from braket.aws.queue_information import QueueDepthInfo, QueueType from braket.device_schema import DeviceActionType from braket.tasks.local_quantum_task import LocalQuantumTask @@ -64,11 +63,12 @@ class TestBraketBackend(TestCase): def test_repr(self): backend = BraketLocalBackend(name="default") self.assertEqual(repr(backend), "BraketBackend[default]") - + def test_device(self): with self.assertRaises(NotImplementedError): MockBraketBackend(name="default")._device + class TestBraketAwsBackend(TestCase): """Tests BraketBackend.""" @@ -100,7 +100,7 @@ def test_device_backend(self): def test_invalid_identifiers(self): with self.assertRaises(ValueError): BraketAwsBackend() - + with self.assertRaises(ValueError): BraketAwsBackend(arn="some_arn", device="some_device") @@ -174,13 +174,16 @@ def test_local_backend_circuit_shots0(self): result.get_statevector(), np.array([0, 0, inv_sqrt_2, inv_sqrt_2]) ) ) - + def test_deprecation_warning_on_init(self): with self.assertWarns(DeprecationWarning): - AWSBraketBackend(device=AwsDevice("arn:aws:braket:::device/quantum-simulator/amazon/sv1")) + AWSBraketBackend( + device=AwsDevice("arn:aws:braket:::device/quantum-simulator/amazon/sv1") + ) def test_deprecation_warning_on_subclass(self): with self.assertWarns(DeprecationWarning): + class SubclassAWSBraketBackend(AWSBraketBackend): pass @@ -190,9 +193,9 @@ def test_run_multiple_circuits(self): device.properties = RIGETTI_MOCK_GATE_MODEL_QPU_CAPABILITIES backend = BraketAwsBackend(device=device) mock_task_1 = Mock(spec=LocalQuantumTask) - mock_task_1.id = '0' + mock_task_1.id = "0" mock_task_2 = Mock(spec=LocalQuantumTask) - mock_task_2.id = '1' + mock_task_2.id = "1" mock_batch = Mock(spec=AwsQuantumTaskBatch) mock_batch.tasks = [mock_task_1, mock_task_2] backend._device.run_batch = Mock(return_value=mock_batch) @@ -200,7 +203,7 @@ def test_run_multiple_circuits(self): circuit.h(0) backend.run([circuit, circuit], shots=0, meas_level=2) - + def test_run_invalid_run_input(self): """Tests run with invalid input to run""" device = Mock() @@ -209,7 +212,13 @@ def test_run_invalid_run_input(self): with self.assertRaises(exception.QiskitBraketException): backend.run(1, shots=0) - @patch('braket.devices.LocalSimulator.run', side_effect=[Mock(return_value=Mock(id='0', spec=LocalQuantumTask)), Exception('Mock exception')]) + @patch( + "braket.devices.LocalSimulator.run", + side_effect=[ + Mock(return_value=Mock(id="0", spec=LocalQuantumTask)), + Exception("Mock exception"), + ], + ) def test_local_backend_run_exception(self, braket_devices_run): """Tests local backend with exception thrown during second run""" backend = BraketLocalBackend(name="default") @@ -315,9 +324,11 @@ def test_random_circuits(self): f"and absolute difference {abs_diff}. Original values {values}", ) - @patch('qiskit_braket_provider.providers.braket_backend.AwsQuantumTask') - @patch('qiskit_braket_provider.providers.braket_backend.BraketQuantumTask') - def test_retrieve_job_task_ids(self, mock_braket_quantum_task, mock_aws_quantum_task): + @patch("qiskit_braket_provider.providers.braket_backend.AwsQuantumTask") + @patch("qiskit_braket_provider.providers.braket_backend.BraketQuantumTask") + def test_retrieve_job_task_ids( + self, mock_braket_quantum_task, mock_aws_quantum_task + ): device = Mock() device.properties = RIGETTI_MOCK_GATE_MODEL_QPU_CAPABILITIES backend = BraketAwsBackend(device=device) @@ -333,7 +344,7 @@ def test_retrieve_job_task_ids(self, mock_braket_quantum_task, mock_aws_quantum_ mock_braket_quantum_task.assert_called_once_with( task_id=task_id, backend=backend, - tasks=[mock_aws_quantum_task(arn=task_id) for task_id in expected_task_ids] + tasks=[mock_aws_quantum_task(arn=task_id) for task_id in expected_task_ids], ) @unittest.skip("Call to external resources.") @@ -441,28 +452,44 @@ def test_target_invalid_device(self): def test_fully_connected(self): """Tests if instruction_props is correctly populated for fully connected topology.""" mock_device = Mock() - mock_device.properties = RIGETTI_MOCK_GATE_MODEL_QPU_CAPABILITIES.copy(deep=True) + mock_device.properties = RIGETTI_MOCK_GATE_MODEL_QPU_CAPABILITIES.copy( + deep=True + ) mock_device.properties.paradigm.connectivity.fullyConnected = True mock_device.properties.paradigm.qubitCount = 2 - mock_device.properties.action.get(DeviceActionType.OPENQASM).supportedOperations = ["CNOT"] - + mock_device.properties.action.get( + DeviceActionType.OPENQASM + ).supportedOperations = ["CNOT"] + instruction_props = aws_device_to_target(mock_device) from qiskit.circuit import Instruction cx_instruction = Instruction(name="cx", num_qubits=2, num_clbits=0, params=[]) - measure_instruction = Instruction(name="measure", num_qubits=1, num_clbits=1, params=[]) + measure_instruction = Instruction( + name="measure", num_qubits=1, num_clbits=1, params=[] + ) expected_instruction_props = [ (cx_instruction, (0, 1)), (cx_instruction, (1, 0)), (measure_instruction, (0,)), - (measure_instruction, (1,)) + (measure_instruction, (1,)), ] for index, instruction in enumerate(instruction_props.instructions): - self.assertEqual(instruction[0].num_qubits, expected_instruction_props[index][0].num_qubits) - self.assertEqual(instruction[0].num_clbits, expected_instruction_props[index][0].num_clbits) - self.assertEqual(instruction[0].params, expected_instruction_props[index][0].params) - self.assertEqual(instruction[0].name, expected_instruction_props[index][0].name) + self.assertEqual( + instruction[0].num_qubits, + expected_instruction_props[index][0].num_qubits, + ) + self.assertEqual( + instruction[0].num_clbits, + expected_instruction_props[index][0].num_clbits, + ) + self.assertEqual( + instruction[0].params, expected_instruction_props[index][0].params + ) + self.assertEqual( + instruction[0].name, expected_instruction_props[index][0].name + ) self.assertEqual(instruction[1], expected_instruction_props[index][1]) From e262fefd0df92746eb7e689be7b80dacbe0adf81 Mon Sep 17 00:00:00 2001 From: WingCode Date: Thu, 6 Jun 2024 12:53:45 +0200 Subject: [PATCH 7/9] Fix lint --- tests/providers/test_braket_provider.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/providers/test_braket_provider.py b/tests/providers/test_braket_provider.py index 96886f9..e25b86d 100644 --- a/tests/providers/test_braket_provider.py +++ b/tests/providers/test_braket_provider.py @@ -7,6 +7,7 @@ from braket.aws import AwsDevice, AwsDeviceType, AwsQuantumTaskBatch, AwsSession from braket.aws.queue_information import QuantumTaskQueueInfo, QueueType from braket.circuits import Circuit +from braket.circuits.noise_model import NoiseModel from qiskit import QuantumCircuit from qiskit import circuit as qiskit_circuit from qiskit.compiler import transpile @@ -73,7 +74,6 @@ def test_real_devices(self): def test_add_valid_noise_model(self): provider = BraketProvider() - from braket.circuits.noise_model import NoiseModel assert provider.backends( aws_session=self.mock_session, From 8c415fd3e17ac6c80bed90ad867ecce81e66afbe Mon Sep 17 00:00:00 2001 From: WingCode Date: Thu, 6 Jun 2024 13:23:21 +0200 Subject: [PATCH 8/9] Revert changes from upstream branch --- tests/providers/mocks.py | 23 ---- tests/providers/test_adapter.py | 24 ---- tests/providers/test_braket_backend.py | 174 ------------------------- 3 files changed, 221 deletions(-) diff --git a/tests/providers/mocks.py b/tests/providers/mocks.py index 800bb6d..ae716bb 100644 --- a/tests/providers/mocks.py +++ b/tests/providers/mocks.py @@ -1,7 +1,6 @@ """Mocks for testing.""" import copy -import enum import uuid from collections import Counter from typing import Dict @@ -13,8 +12,6 @@ from braket.tasks import GateModelQuantumTaskResult from braket.tasks.local_quantum_task import LocalQuantumTask -from qiskit_braket_provider.providers.braket_backend import BraketBackend - RIGETTI_ARN = "arn:aws:braket:::device/qpu/rigetti/Aspen-10" RIGETTI_ASPEN_ARN = "arn:aws:braket:::device/qpu/rigetti/Aspen-M-3" SV1_ARN = "arn:aws:braket:::device/quantum-simulator/amazon/sv1" @@ -161,23 +158,3 @@ ) MOCK_LOCAL_QUANTUM_TASK = LocalQuantumTask(MOCK_GATE_MODEL_QUANTUM_TASK_RESULT) - - -class MockBraketBackend(BraketBackend): - @property - def target(self): - pass - - @property - def max_circuits(self): - pass - - def _default_options(self): - pass - - def run(self): - pass - - -class MockMeasLevelEnum(enum.Enum): - LEVEL_TWO = 2 diff --git a/tests/providers/test_adapter.py b/tests/providers/test_adapter.py index 58edcde..9a0d193 100644 --- a/tests/providers/test_adapter.py +++ b/tests/providers/test_adapter.py @@ -330,15 +330,6 @@ def test_measure(self): self.assertEqual(braket_circuit, expected_braket_circuit) - def test_measure_(self): - """Tests if NotImplementedError is raised for reset operation.""" - - qiskit_circuit = QuantumCircuit(1, 1) - qiskit_circuit.reset(0) - - with self.assertRaises(NotImplementedError): - to_braket(qiskit_circuit) - def test_measure_different_indices(self): """ Tests the translation of a measure instruction. @@ -666,21 +657,6 @@ def test_power(self): self.assertEqual(qiskit_circuit, expected_qiskit_circuit) - def test_unsupported_braket_gate(self): - """Tests if TypeError is raised for unsupported Braket gate.""" - - gate = getattr(Gate, "CNot") - op = gate() - instr = Instruction(op, range(2)) - circuit = Circuit().add_instruction(instr) - - with self.assertRaises(TypeError): - with patch.dict( - "qiskit_braket_provider.providers.adapter._GATE_NAME_TO_QISKIT_GATE", - {"cnot": None}, - ): - to_qiskit(circuit) - def test_measure_subset(self): """Tests the measure instruction conversion from braket to qiskit""" braket_circuit = Circuit().h(0).cnot(0, 1).measure(0) diff --git a/tests/providers/test_braket_backend.py b/tests/providers/test_braket_backend.py index ee5a860..3435481 100644 --- a/tests/providers/test_braket_backend.py +++ b/tests/providers/test_braket_backend.py @@ -7,10 +7,7 @@ import numpy as np from botocore import errorfactory -from braket.aws import AwsDevice, AwsQuantumTaskBatch from braket.aws.queue_information import QueueDepthInfo, QueueType -from braket.device_schema import DeviceActionType -from braket.tasks.local_quantum_task import LocalQuantumTask from qiskit import QuantumCircuit, transpile from qiskit.circuit.library import TwoLocal from qiskit.circuit.random import random_circuit @@ -24,12 +21,9 @@ from qiskit_braket_provider import AWSBraketProvider, exception, version from qiskit_braket_provider.providers import BraketAwsBackend, BraketLocalBackend from qiskit_braket_provider.providers.adapter import aws_device_to_target -from qiskit_braket_provider.providers.braket_backend import AWSBraketBackend from tests.providers.mocks import ( RIGETTI_MOCK_GATE_MODEL_QPU_CAPABILITIES, RIGETTI_MOCK_M_3_QPU_CAPABILITIES, - MockBraketBackend, - MockMeasLevelEnum, ) @@ -59,16 +53,6 @@ def combine_dicts( return combined_dict -class TestBraketBackend(TestCase): - def test_repr(self): - backend = BraketLocalBackend(name="default") - self.assertEqual(repr(backend), "BraketBackend[default]") - - def test_device(self): - with self.assertRaises(NotImplementedError): - MockBraketBackend(name="default")._device - - class TestBraketAwsBackend(TestCase): """Tests BraketBackend.""" @@ -82,12 +66,6 @@ def test_device_backend(self): self.assertIsNone(backend.max_circuits) user_agent = f"QiskitBraketProvider/" f"{version.__version__}" device.aws_session.add_braket_user_agent.assert_called_with(user_agent) - with self.assertRaises(NotImplementedError): - backend.dtm() - with self.assertRaises(NotImplementedError): - backend.meas_map() - with self.assertRaises(NotImplementedError): - backend.qubit_properties(0) with self.assertRaises(NotImplementedError): backend.drive_channel(0) with self.assertRaises(NotImplementedError): @@ -97,25 +75,12 @@ def test_device_backend(self): with self.assertRaises(NotImplementedError): backend.control_channel([0, 1]) - def test_invalid_identifiers(self): - with self.assertRaises(ValueError): - BraketAwsBackend() - - with self.assertRaises(ValueError): - BraketAwsBackend(arn="some_arn", device="some_device") - def test_local_backend(self): """Tests local backend.""" backend = BraketLocalBackend(name="default") self.assertTrue(backend) self.assertIsInstance(backend.target, Target) self.assertIsNone(backend.max_circuits) - with self.assertRaises(NotImplementedError): - backend.dtm() - with self.assertRaises(NotImplementedError): - backend.meas_map() - with self.assertRaises(NotImplementedError): - backend.qubit_properties(0) with self.assertRaises(NotImplementedError): backend.drive_channel(0) with self.assertRaises(NotImplementedError): @@ -175,69 +140,6 @@ def test_local_backend_circuit_shots0(self): ) ) - def test_deprecation_warning_on_init(self): - with self.assertWarns(DeprecationWarning): - AWSBraketBackend( - device=AwsDevice("arn:aws:braket:::device/quantum-simulator/amazon/sv1") - ) - - def test_deprecation_warning_on_subclass(self): - with self.assertWarns(DeprecationWarning): - - class SubclassAWSBraketBackend(AWSBraketBackend): - pass - - def test_run_multiple_circuits(self): - """Tests run with multiple circuits""" - device = Mock() - device.properties = RIGETTI_MOCK_GATE_MODEL_QPU_CAPABILITIES - backend = BraketAwsBackend(device=device) - mock_task_1 = Mock(spec=LocalQuantumTask) - mock_task_1.id = "0" - mock_task_2 = Mock(spec=LocalQuantumTask) - mock_task_2.id = "1" - mock_batch = Mock(spec=AwsQuantumTaskBatch) - mock_batch.tasks = [mock_task_1, mock_task_2] - backend._device.run_batch = Mock(return_value=mock_batch) - circuit = QuantumCircuit(1) - circuit.h(0) - - backend.run([circuit, circuit], shots=0, meas_level=2) - - def test_run_invalid_run_input(self): - """Tests run with invalid input to run""" - device = Mock() - device.properties = RIGETTI_MOCK_GATE_MODEL_QPU_CAPABILITIES - backend = BraketAwsBackend(device=device) - with self.assertRaises(exception.QiskitBraketException): - backend.run(1, shots=0) - - @patch( - "braket.devices.LocalSimulator.run", - side_effect=[ - Mock(return_value=Mock(id="0", spec=LocalQuantumTask)), - Exception("Mock exception"), - ], - ) - def test_local_backend_run_exception(self, braket_devices_run): - """Tests local backend with exception thrown during second run""" - backend = BraketLocalBackend(name="default") - - circuit = QuantumCircuit(1) - circuit.h(0) - - with self.assertRaises(Exception): - backend.run([circuit, circuit], shots=0) # First run should pass - braket_devices_run.assert_called() - - def test_meas_level_enum(self): - """Check that enum meas level can be successfully accessed without error""" - backend = BraketLocalBackend(name="default") - circuit = QuantumCircuit(1, 1) - circuit.h(0) - circuit.measure(0, 0) - backend.run(circuit, shots=10, meas_level=MockMeasLevelEnum.LEVEL_TWO) - def test_meas_level_2(self): """Check that there's no error for asking for classified measurement results.""" backend = BraketLocalBackend(name="default") @@ -324,29 +226,6 @@ def test_random_circuits(self): f"and absolute difference {abs_diff}. Original values {values}", ) - @patch("qiskit_braket_provider.providers.braket_backend.AwsQuantumTask") - @patch("qiskit_braket_provider.providers.braket_backend.BraketQuantumTask") - def test_retrieve_job_task_ids( - self, mock_braket_quantum_task, mock_aws_quantum_task - ): - device = Mock() - device.properties = RIGETTI_MOCK_GATE_MODEL_QPU_CAPABILITIES - backend = BraketAwsBackend(device=device) - task_id = "task1;task2;task3" - expected_task_ids = task_id.split(";") - - backend.retrieve_job(task_id) - - # Assert - mock_aws_quantum_task.assert_any_call(arn=expected_task_ids[0]) - mock_aws_quantum_task.assert_any_call(arn=expected_task_ids[1]) - mock_aws_quantum_task.assert_any_call(arn=expected_task_ids[2]) - mock_braket_quantum_task.assert_called_once_with( - task_id=task_id, - backend=backend, - tasks=[mock_aws_quantum_task(arn=task_id) for task_id in expected_task_ids], - ) - @unittest.skip("Call to external resources.") def test_retrieve_job(self): """Tests retrieve task by id.""" @@ -440,56 +319,3 @@ def test_target(self): self.assertEqual(len(target.operations), 2) self.assertEqual(len(target.instructions), 60) self.assertIn("Target for Amazon Braket QPU", target.description) - - def test_target_invalid_device(self): - """Tests target.""" - mock_device = Mock() - mock_device.properties = None - - with self.assertRaises(exception.QiskitBraketException): - aws_device_to_target(mock_device) - - def test_fully_connected(self): - """Tests if instruction_props is correctly populated for fully connected topology.""" - mock_device = Mock() - mock_device.properties = RIGETTI_MOCK_GATE_MODEL_QPU_CAPABILITIES.copy( - deep=True - ) - mock_device.properties.paradigm.connectivity.fullyConnected = True - mock_device.properties.paradigm.qubitCount = 2 - mock_device.properties.action.get( - DeviceActionType.OPENQASM - ).supportedOperations = ["CNOT"] - - instruction_props = aws_device_to_target(mock_device) - - from qiskit.circuit import Instruction - - cx_instruction = Instruction(name="cx", num_qubits=2, num_clbits=0, params=[]) - measure_instruction = Instruction( - name="measure", num_qubits=1, num_clbits=1, params=[] - ) - - expected_instruction_props = [ - (cx_instruction, (0, 1)), - (cx_instruction, (1, 0)), - (measure_instruction, (0,)), - (measure_instruction, (1,)), - ] - for index, instruction in enumerate(instruction_props.instructions): - self.assertEqual( - instruction[0].num_qubits, - expected_instruction_props[index][0].num_qubits, - ) - self.assertEqual( - instruction[0].num_clbits, - expected_instruction_props[index][0].num_clbits, - ) - self.assertEqual( - instruction[0].params, expected_instruction_props[index][0].params - ) - self.assertEqual( - instruction[0].name, expected_instruction_props[index][0].name - ) - - self.assertEqual(instruction[1], expected_instruction_props[index][1]) From 2bd21816ee9568660a8a356fe285c2102b967aa3 Mon Sep 17 00:00:00 2001 From: WingCode Date: Thu, 6 Jun 2024 13:26:38 +0200 Subject: [PATCH 9/9] Fix pylint --- qiskit_braket_provider/providers/braket_provider.py | 4 ++++ tests/providers/test_braket_provider.py | 2 ++ 2 files changed, 6 insertions(+) diff --git a/qiskit_braket_provider/providers/braket_provider.py b/qiskit_braket_provider/providers/braket_provider.py index 093bbae..94ada43 100644 --- a/qiskit_braket_provider/providers/braket_provider.py +++ b/qiskit_braket_provider/providers/braket_provider.py @@ -30,6 +30,10 @@ class BraketProvider(ProviderV1): BraketBackend[dm1]] """ + def __init__(self): + super().__init__() + self._noise_model = None + def set_noise_model(self, noise_model: NoiseModel) -> None: """Set the noise model of the device. diff --git a/tests/providers/test_braket_provider.py b/tests/providers/test_braket_provider.py index e25b86d..c72adcf 100644 --- a/tests/providers/test_braket_provider.py +++ b/tests/providers/test_braket_provider.py @@ -73,6 +73,7 @@ def test_real_devices(self): self.assertIsInstance(backend, BraketAwsBackend) def test_add_valid_noise_model(self): + """Tests adding a valid noise model to the provider.""" provider = BraketProvider() assert provider.backends( @@ -82,6 +83,7 @@ def test_add_valid_noise_model(self): ) def test_add_invalid_noise_model(self): + """Tests adding an invalid noise model to the provider.""" provider = BraketProvider() with self.assertRaises(ValueError): provider.backends(