From 3de09347e6c126d2bc779b1884edfdcd64d8b87a Mon Sep 17 00:00:00 2001 From: Kshitij Chhabra Date: Fri, 25 Feb 2022 15:07:11 -0800 Subject: [PATCH] sync: Sync changes from oqc-without-qasm (#177) * Added integration tests and LHR region to device configuration (#174) * fix: Add LHR to the list of device regions * test updates * fix: Add integration tests * formatting changes * fix: Return DiGraph for device.topology_graph (#175) * sync: Merge from public repository (#176) * infra: Pin docutils<0.18 in doc requirements (#283) docutils 0.18 was released on October 26, 2021, and with it came some [breaking changes](https://github.com/readthedocs/readthedocs.org/issues/8616) for sphinx, and in turn [readthedocs builds](https://readthedocs.org/projects/amazon-braket-sdk-python/builds/15168485/). To keep doc builds working, docutils will be constrained to versions below 0.18. * prepare release v1.9.5.post0 * update development version to v1.9.6.dev0 * feature: Add support for jobs (#287) Co-authored-by: Viraj Chaudhari Co-authored-by: Milan Krneta Co-authored-by: Aaron Berdy Co-authored-by: Lin Co-authored-by: Roald Bradley Severtson Co-authored-by: Christian Madsen * fix: Skip jobs integration tests (#288) * prepare release v1.10.0 * update development version to v1.10.1.dev0 * feature: Adding integration tests for DM1 (#286) * feature: Adding integration tests for DM1 * Moved many_layers to test_quantum_task * formatting changes only Co-authored-by: Cody Wang * prepare release v1.11.0 * update development version to v1.11.1.dev0 * fix: remove extraneous reference from local job container setup (#292) * prepare release v1.11.1 * update development version to v1.11.2.dev0 * feature: optimize IAM role retrieval (#299) * fix: Enable jobs integration tests (#289) * feature: Added is_available property to AwsDevice (#290) Added is_available property to AwsDevice that parses the availability window and current device status to return a boolean flag if the device is currently available. * prepare release v1.12.0 * update development version to v1.12.1.dev0 * feature: added controlled-sqrt-not gate (#297) * feature: added controlled-sqrt-not gate This makes certain circuits, like CHSH, more straightforward. This commit works in line with the following branches (also committed, separately): https://github.com/unprovable/amazon-braket-schemas-python.git@ctrl-v-gate https://github.com/unprovable/amazon-braket-default-simulator-python.git@ctrl-v-gate * fix: ran tox linters * fix: reverted tox.ini Co-authored-by: Mark C Co-authored-by: Mark C Co-authored-by: Cody Wang * prepare release v1.13.0 * update development version to v1.13.1.dev0 * feature: adding TwoQubitPauliChannel (#300) * prepare release v1.14.0 * update development version to v1.14.1.dev0 * documentation: fix documentation on environment variable to match the code. (#302) * prepare release v1.14.0.post0 * update development version to v1.14.1.dev0 * feat: Update region switching for regional device arns (#169) (#303) * prepare release v1.15.0 * update development version to v1.15.1.dev0 Co-authored-by: Cody Wang Co-authored-by: ci Co-authored-by: Viraj Chaudhari Co-authored-by: Milan Krneta Co-authored-by: Aaron Berdy Co-authored-by: Lin Co-authored-by: Roald Bradley Severtson Co-authored-by: Christian Madsen Co-authored-by: Jacob Feldman Co-authored-by: Mark Sweat <37444469+surfkansas@users.noreply.github.com> Co-authored-by: Mark C Co-authored-by: Mark C Co-authored-by: Mark C Co-authored-by: mbeach-aws <85963088+mbeach-aws@users.noreply.github.com> Co-authored-by: Yiheng Duan <98372300+duanyh12@users.noreply.github.com> Co-authored-by: Cody Wang Co-authored-by: Viraj Chaudhari Co-authored-by: Milan Krneta Co-authored-by: Aaron Berdy Co-authored-by: Lin Co-authored-by: Roald Bradley Severtson Co-authored-by: Christian Madsen Co-authored-by: Jacob Feldman Co-authored-by: Mark Sweat <37444469+surfkansas@users.noreply.github.com> Co-authored-by: Mark C Co-authored-by: Mark C Co-authored-by: Mark C Co-authored-by: mbeach-aws <85963088+mbeach-aws@users.noreply.github.com> Co-authored-by: Yiheng Duan <98372300+duanyh12@users.noreply.github.com> --- CHANGELOG.md | 12 +++++ src/braket/_sdk/_version.py | 2 +- src/braket/aws/aws_device.py | 20 +++---- src/braket/jobs/data_persistence.py | 4 +- test/integ_tests/test_device_creation.py | 12 +++-- .../braket/aws/common_test_utils.py | 1 + test/unit_tests/braket/aws/test_aws_device.py | 53 ++++++++++++++++--- 7 files changed, 82 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b75c6ebb2..672de8f5d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## v1.15.0 (2022-02-15) + +### Features + + * Update region switching for regional device arns (#169) + +## v1.14.0.post0 (2022-02-11) + +### Documentation Changes + + * fix documentation on environment variable to match the code. + ## v1.14.0 (2022-02-02) ### Features diff --git a/src/braket/_sdk/_version.py b/src/braket/_sdk/_version.py index 9855c1a60..e264b40eb 100644 --- a/src/braket/_sdk/_version.py +++ b/src/braket/_sdk/_version.py @@ -15,4 +15,4 @@ Version number (major.minor.patch[-label]) """ -__version__ = "1.14.1.dev0" +__version__ = "1.15.1.dev0" diff --git a/src/braket/aws/aws_device.py b/src/braket/aws/aws_device.py index f29f50363..0e1e3f81d 100644 --- a/src/braket/aws/aws_device.py +++ b/src/braket/aws/aws_device.py @@ -19,7 +19,7 @@ from typing import List, Optional, Union from botocore.errorfactory import ClientError -from networkx import Graph, complete_graph, from_edgelist +from networkx import DiGraph, complete_graph, from_edgelist from braket.annealing.problem import Problem from braket.aws.aws_quantum_task import AwsQuantumTask @@ -47,7 +47,7 @@ class AwsDevice(Device): device. """ - REGIONS = ("us-east-1", "us-west-1", "us-west-2") + REGIONS = ("us-east-1", "us-west-1", "us-west-2", "eu-west-2") DEFAULT_SHOTS_QPU = 1000 DEFAULT_SHOTS_SIMULATOR = 0 @@ -367,8 +367,8 @@ def properties(self) -> DeviceCapabilities: return self._properties @property - def topology_graph(self) -> Graph: - """Graph: topology of device as a networkx `Graph` object. + def topology_graph(self) -> DiGraph: + """DiGraph: topology of device as a networkx `DiGraph` object. Returns `None` if the topology is not available for the device. Examples: @@ -383,29 +383,31 @@ def topology_graph(self) -> Graph: """ return self._topology_graph - def _construct_topology_graph(self) -> Graph: + def _construct_topology_graph(self) -> DiGraph: """ Construct topology graph. If no such metadata is available, return `None`. Returns: - Graph: topology of QPU as a networkx `Graph` object. + DiGraph: topology of QPU as a networkx `DiGraph` object. """ if hasattr(self.properties, "paradigm") and isinstance( self.properties.paradigm, GateModelQpuParadigmProperties ): if self.properties.paradigm.connectivity.fullyConnected: - return complete_graph(int(self.properties.paradigm.qubitCount)) + return complete_graph( + int(self.properties.paradigm.qubitCount), create_using=DiGraph() + ) adjacency_lists = self.properties.paradigm.connectivity.connectivityGraph edges = [] for item in adjacency_lists.items(): i = item[0] edges.extend([(int(i), int(j)) for j in item[1]]) - return from_edgelist(edges) + return from_edgelist(edges, create_using=DiGraph()) elif hasattr(self.properties, "provider") and isinstance( self.properties.provider, DwaveProviderProperties ): edges = self.properties.provider.couplers - return from_edgelist(edges) + return from_edgelist(edges, create_using=DiGraph()) else: return None diff --git a/src/braket/jobs/data_persistence.py b/src/braket/jobs/data_persistence.py index f969a5984..d41f4d27c 100644 --- a/src/braket/jobs/data_persistence.py +++ b/src/braket/jobs/data_persistence.py @@ -110,8 +110,8 @@ def save_job_result( ) -> None: """ Saves the `result_data` to the local output directory that is specified by the container - environment variable `OUTPUT_DIR`, with the filename 'results.json'. The `result_data` - values are serialized to the specified `data_format`. + environment variable `AMZN_BRAKET_JOB_RESULTS_DIR`, with the filename 'results.json'. + The `result_data` values are serialized to the specified `data_format`. Note: This function for storing the results is only for use inside the job container as it writes data to directories and references env variables set in the containers. diff --git a/test/integ_tests/test_device_creation.py b/test/integ_tests/test_device_creation.py index 63b7a3716..f1ca875ca 100644 --- a/test/integ_tests/test_device_creation.py +++ b/test/integ_tests/test_device_creation.py @@ -19,9 +19,12 @@ RIGETTI_ARN = "arn:aws:braket:::device/qpu/rigetti/Aspen-10" IONQ_ARN = "arn:aws:braket:::device/qpu/ionq/ionQdevice" SIMULATOR_ARN = "arn:aws:braket:::device/quantum-simulator/amazon/sv1" +OQC_ARN = "arn:aws:braket:eu-west-2::device/qpu/oqc/Lucy" -@pytest.mark.parametrize("arn", [(RIGETTI_ARN), (IONQ_ARN), (DWAVE_ARN), (SIMULATOR_ARN)]) +@pytest.mark.parametrize( + "arn", [(RIGETTI_ARN), (IONQ_ARN), (DWAVE_ARN), (OQC_ARN), (SIMULATOR_ARN)] +) def test_device_creation(arn, aws_session): device = AwsDevice(arn, aws_session=aws_session) assert device.arn == arn @@ -36,9 +39,12 @@ def test_device_across_regions(aws_session): # assert QPUs across different regions can be created using the same aws_session AwsDevice(RIGETTI_ARN, aws_session) AwsDevice(IONQ_ARN, aws_session) + AwsDevice(OQC_ARN, aws_session) -@pytest.mark.parametrize("arn", [(RIGETTI_ARN), (IONQ_ARN), (DWAVE_ARN), (SIMULATOR_ARN)]) +@pytest.mark.parametrize( + "arn", [(RIGETTI_ARN), (IONQ_ARN), (DWAVE_ARN), (OQC_ARN), (SIMULATOR_ARN)] +) def test_get_devices_arn(arn): results = AwsDevice.get_devices(arns=[arn]) assert results[0].arn == arn @@ -58,5 +64,5 @@ def test_get_devices_others(): def test_get_devices_all(): result_arns = [result.arn for result in AwsDevice.get_devices()] - for arn in [DWAVE_ARN, RIGETTI_ARN, IONQ_ARN, SIMULATOR_ARN]: + for arn in [DWAVE_ARN, RIGETTI_ARN, IONQ_ARN, SIMULATOR_ARN, OQC_ARN]: assert arn in result_arns diff --git a/test/unit_tests/braket/aws/common_test_utils.py b/test/unit_tests/braket/aws/common_test_utils.py index 8eaaa367c..9ea1e2b1b 100644 --- a/test/unit_tests/braket/aws/common_test_utils.py +++ b/test/unit_tests/braket/aws/common_test_utils.py @@ -19,6 +19,7 @@ DWAVE_ARN = "arn:aws:braket:::device/qpu/d-wave/Advantage_system1" RIGETTI_ARN = "arn:aws:braket:::device/qpu/rigetti/Aspen-10" IONQ_ARN = "arn:aws:braket:::device/qpu/ionq/ionQdevice" +OQC_ARN = "arn:aws:braket:eu-west-2::device/qpu/oqc/Lucy" SV1_ARN = "arn:aws:braket:::device/quantum-simulator/amazon/sv1" TN1_ARN = "arn:aws:braket:::device/quantum-simulator/amazon/tn1" diff --git a/test/unit_tests/braket/aws/test_aws_device.py b/test/unit_tests/braket/aws/test_aws_device.py index 4773a7d17..3029f69f6 100644 --- a/test/unit_tests/braket/aws/test_aws_device.py +++ b/test/unit_tests/braket/aws/test_aws_device.py @@ -15,11 +15,13 @@ from datetime import datetime from unittest.mock import Mock, patch +import networkx as nx import pytest from botocore.exceptions import ClientError from common_test_utils import ( DWAVE_ARN, IONQ_ARN, + OQC_ARN, RIGETTI_ARN, RIGETTI_REGION, SV1_ARN, @@ -132,6 +134,14 @@ def test_mock_rigetti_schema_2(): "deviceCapabilities": MOCK_GATE_MODEL_QPU_CAPABILITIES_2.json(), } +MOCK_GATE_MODEL_QPU_3 = { + "deviceName": "Lucy", + "deviceType": "QPU", + "providerName": "OQC", + "deviceStatus": "OFFLINE", + "deviceCapabilities": MOCK_GATE_MODEL_QPU_CAPABILITIES_1.json(), +} + MOCK_DWAVE_QPU_CAPABILITIES_JSON = { "braketSchemaHeader": { "name": "braket.device_schema.dwave.dwave_device_capabilities", @@ -142,7 +152,7 @@ def test_mock_rigetti_schema_2(): "annealingOffsetStepPhi0": 1.45, "annealingOffsetRanges": [[1.45, 1.45], [1.45, 1.45]], "annealingDurationRange": [1, 2, 3], - "couplers": [[1, 2], [1, 2]], + "couplers": [[1, 2], [2, 3]], "defaultAnnealingDuration": 1, "defaultProgrammingThermalizationDuration": 1, "defaultReadoutThermalizationDuration": 1, @@ -619,10 +629,11 @@ def test_run_with_shots_kwargs(aws_quantum_task_mock, device, circuit, s3_destin @patch("braket.aws.aws_quantum_task.AwsQuantumTask.create") -def test_run_with_qpu_no_shots(aws_quantum_task_mock, device, circuit, s3_destination_folder): +def test_default_bucket_not_called(aws_quantum_task_mock, device, circuit, s3_destination_folder): + device = device(RIGETTI_ARN) run_and_assert( aws_quantum_task_mock, - device(RIGETTI_ARN), + device, MOCK_DEFAULT_S3_DESTINATION_FOLDER, AwsDevice.DEFAULT_SHOTS_QPU, AwsQuantumTask.DEFAULT_RESULTS_POLL_TIMEOUT, @@ -635,6 +646,7 @@ def test_run_with_qpu_no_shots(aws_quantum_task_mock, device, circuit, s3_destin None, None, ) + device._aws_session.default_bucket.assert_not_called() @patch("braket.aws.aws_quantum_task.AwsQuantumTask.create") @@ -875,23 +887,34 @@ def test_get_devices(mock_copy_session, aws_session): "providerName": "Amazon Braket", }, ], + # eu-west-2 + [ + { + "deviceArn": OQC_ARN, + "deviceName": "Lucy", + "deviceType": "QPU", + "deviceStatus": "ONLINE", + "providerName": "OQC", + } + ], # Only two regions to search outside of current ValueError("should not be reachable"), ] session_for_region.get_device.side_effect = [ MOCK_DWAVE_QPU, MOCK_GATE_MODEL_QPU_2, + MOCK_GATE_MODEL_QPU_3, ValueError("should not be reachable"), ] mock_copy_session.return_value = session_for_region - # Search order: us-east-1, us-west-1, us-west-2 + # Search order: us-east-1, us-west-1, us-west-2, eu-west-2 results = AwsDevice.get_devices( - arns=[SV1_ARN, DWAVE_ARN, IONQ_ARN], - provider_names=["Amazon Braket", "D-Wave", "IonQ"], + arns=[SV1_ARN, DWAVE_ARN, IONQ_ARN, OQC_ARN], + provider_names=["Amazon Braket", "D-Wave", "IonQ", "OQC"], statuses=["ONLINE"], aws_session=aws_session, ) - assert [result.name for result in results] == ["Advantage_system1.1", "Blah", "SV1"] + assert [result.name for result in results] == ["Advantage_system1.1", "Blah", "Lucy", "SV1"] @patch("braket.aws.aws_device.AwsSession.copy_session") @@ -1064,3 +1087,19 @@ def __init__(self, status, *execution_window_args): assert ( expected == actual ), f"device_name: {device_name}, test_date: {test_date}, expected: {expected}, actual: {actual}" + + +@pytest.mark.parametrize( + "get_device_data, expected_graph", + [ + (MOCK_GATE_MODEL_QPU_1, nx.DiGraph([(1, 2), (1, 3)])), + (MOCK_GATE_MODEL_QPU_2, nx.complete_graph(30, nx.DiGraph())), + (MOCK_DWAVE_QPU, nx.DiGraph([(1, 2), (2, 3)])), + ], +) +def test_device_topology_graph_data(get_device_data, expected_graph, arn): + mock_session = Mock() + mock_session.get_device.return_value = get_device_data + mock_session.region = RIGETTI_REGION + device = AwsDevice(arn, mock_session) + assert nx.is_isomorphic(device.topology_graph, expected_graph)