diff --git a/.coveragerc b/.coveragerc index 22cb4caeb..98f09ec04 100644 --- a/.coveragerc +++ b/.coveragerc @@ -35,8 +35,6 @@ exclude_lines = # Avoid type checking import conditionals if TYPE_CHECKING: - - [html] directory = build/coverage diff --git a/pyproject.toml b/pyproject.toml index aa4949aa1..1eadfe73d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,2 +1,85 @@ -[tool.black] +[tool.ruff] +target-version = "py39" line-length = 100 +format.preview = true +format.docstring-code-line-length = 100 +format.docstring-code-format = true +lint.select = [ + "ALL", +] +lint.ignore = [ + "A001", "A002", # This will be refactored out later + "ANN202", "ARG001", "ARG002", # TODO after onboarding + "ANN002", # Missing tpye annotation for `*args` in method + "ANN003", # Missing tpye annotation for `**kwargs` in method + "ANN204", # Special functions don't need return types + "ANN401", # Dynamically typed expressions (typing.Any) are disallowed in `arg`" + "B008", # Logger deinition rework + "B026", # Accepted pattern to unpack after keyword args + "BLE001", # This needs to be cleaned up later. + "COM812", # conflicts with formatter + "CPY", # No copyright header + "D", # ignore documentation for now + "D203", # `one-blank-line-before-class` (D203) and `no-blank-line-before-class` (D211) are incompatible + "D212", # `multi-line-summary-first-line` (D212) and `multi-line-summary-second-line` (D213) are incompatible + "DOC201", # no restructuredtext support yet + "DOC502", # Exceptions are documented in top level functions and no in the private methods + "DOC501", # broken with sphinx docs + "EM", # error string messages are fine + "ERA001", # This is used to capture math + "FA100", # Ignore until Python 3.10 is used + "FBT", # Booleans in methods are fine + "FIX", # Allow TODO statements for now. + "FURB101", # Same as PTH + "FURB103", # Same as PTH + "G004", # Let f strings in logger + "INP001", # no implicit namespaces here + "ISC001", # conflicts with formatter + "N802", # Function names are set now + "N803", # Allow uppercase + "N806", # Vars will break this rule based on technical names. + "N815", # Allowing reviwers to do a per case basis + "PLC2701", # Allow private function access in code + "PLR0913", # Too many variables in function + "PLR0914", # Too many local variables + "PLR0917", # Too many positional arguments + "PLR6301", # Ignore for dispath functions + "PLR2004", # Allow magic values + "PLW1510", # Subprocess implicitly uses this + "PLW0603", # Allow usage of global vars + "PLW1641", # Object with equal and not __hash__ + "PTH", # Prefer builtin path + "PYI034", # Return class type hint here instead of self + "S104", # Possible binding to all interfaces + "S403", # Pickle is used + "S404", # Using subprocess is alright. + "S603", # Using subprocess is alright. + "S607", # Partial path + "SLF", # Private methods are allowed for access + "T201", # Print statements are used in some places. Later this should be moved inline. + "TCH", # This is good to look into later on. TODO + "TD", # Allow TODO Statements + "TRY003", # Longer messages are fine. +] +lint.per-file-ignores."tests/**/*.py" = [ + "D", # don't care about documentation in tests + "FBT", # don"t care about booleans as positional arguments in tests + "INP001", # no implicit namespace + "PLR2004", # Magic value used in comparison, consider replacing with a constant variable + "S101", # asserts allowed in tests... + "S603", # `subprocess` call: check for execution of untrusted input +] +lint.isort = { known-first-party = [ + "amazon-braket-sdk", + "tests", +] } +lint.preview = true + +[tool.ruff.lint.pydocstyle] +convention = "google" + +[tool.ruff.lint.flake8-annotations] +mypy-init-return = false + +[tool.ruff.lint.flake8-builtins] +builtins-allowed-modules = ["operator"] diff --git a/setup.cfg b/setup.cfg index ab93f5955..0abcc1275 100644 --- a/setup.cfg +++ b/setup.cfg @@ -13,29 +13,4 @@ filterwarnings= # Ref: https://github.com/pytest-dev/pytest-cov/issues/557 ignore:The --rsyncdir command line argument and rsyncdirs config variable are deprecated.:DeprecationWarning -[isort] -line_length = 100 -multi_line_output = 3 -include_trailing_comma = true -profile = black -[flake8] -ignore = - # not pep8, black adds whitespace before ':' - E203, - # not pep8, https://www.python.org/dev/peps/pep-0008/#pet-peeves - E231, - # not pep8, black adds line break before binary operator - W503, - # Google Python style is not RST until after processed by Napoleon - # See https://github.com/peterjc/flake8-rst-docstrings/issues/17 - RST201,RST203,RST301, -max_line_length = 100 -max-complexity = 10 -exclude = - __pycache__ - .tox - .git - bin - build - venv diff --git a/src/braket/ahs/analog_hamiltonian_simulation.py b/src/braket/ahs/analog_hamiltonian_simulation.py index f11675d41..d22e4431b 100644 --- a/src/braket/ahs/analog_hamiltonian_simulation.py +++ b/src/braket/ahs/analog_hamiltonian_simulation.py @@ -15,6 +15,7 @@ from collections import defaultdict from functools import singledispatch +from typing import TYPE_CHECKING import braket.ir.ahs as ir from braket.ahs.atom_arrangement import AtomArrangement, SiteType @@ -25,6 +26,9 @@ from braket.device_schema import DeviceActionType from braket.timings.time_series import TimeSeries +if TYPE_CHECKING: + from braket.aws import AwsDevice + class AnalogHamiltonianSimulation: LOCAL_DETUNING_PROPERTY = "local_detuning" @@ -124,7 +128,7 @@ def _hamiltonian_to_ir(self) -> ir.Hamiltonian: localDetuning=terms[AnalogHamiltonianSimulation.LOCAL_DETUNING_PROPERTY], ) - def discretize(self, device: AwsDevice) -> AnalogHamiltonianSimulation: # noqa + def discretize(self, device: AwsDevice) -> AnalogHamiltonianSimulation: """Creates a new AnalogHamiltonianSimulation with all numerical values represented as Decimal objects with fixed precision based on the capabilities of the device. diff --git a/src/braket/ahs/atom_arrangement.py b/src/braket/ahs/atom_arrangement.py index 24d4fc9aa..fc52d3f05 100644 --- a/src/braket/ahs/atom_arrangement.py +++ b/src/braket/ahs/atom_arrangement.py @@ -18,7 +18,6 @@ from decimal import Decimal from enum import Enum from numbers import Number -from typing import Union import numpy as np @@ -63,7 +62,7 @@ def __init__(self): def add( self, - coordinate: Union[tuple[Number, Number], np.ndarray], + coordinate: tuple[Number, Number] | np.ndarray, site_type: SiteType = SiteType.FILLED, ) -> AtomArrangement: """Add a coordinate to the atom arrangement. @@ -124,6 +123,7 @@ def discretize(self, properties: DiscretizationProperties) -> AtomArrangement: round(Decimal(c) / position_res) * position_res for c in site.coordinate ) discretized_arrangement.add(new_coordinates, site.site_type) - return discretized_arrangement except Exception as e: raise DiscretizationError(f"Failed to discretize register {e}") from e + else: + return discretized_arrangement diff --git a/src/braket/ahs/driving_field.py b/src/braket/ahs/driving_field.py index cbf01838d..11d30e34a 100644 --- a/src/braket/ahs/driving_field.py +++ b/src/braket/ahs/driving_field.py @@ -13,8 +13,6 @@ from __future__ import annotations -from typing import Union - from braket.ahs.discretization_types import DiscretizationProperties from braket.ahs.field import Field from braket.ahs.hamiltonian import Hamiltonian @@ -24,9 +22,9 @@ class DrivingField(Hamiltonian): def __init__( self, - amplitude: Union[Field, TimeSeries], - phase: Union[Field, TimeSeries], - detuning: Union[Field, TimeSeries], + amplitude: Field | TimeSeries, + phase: Field | TimeSeries, + detuning: Field | TimeSeries, ) -> None: r"""Creates a Hamiltonian term :math:`H_{drive}` for the driving field that coherently transfers atoms from the ground state to the Rydberg state @@ -181,6 +179,4 @@ def from_lists( detuning.put(t, detuning_value) phase.put(t, phase_value) - drive = DrivingField(amplitude=amplitude, detuning=detuning, phase=phase) - - return drive + return DrivingField(amplitude=amplitude, detuning=detuning, phase=phase) diff --git a/src/braket/ahs/field.py b/src/braket/ahs/field.py index 28319cc99..fe9a09fe7 100644 --- a/src/braket/ahs/field.py +++ b/src/braket/ahs/field.py @@ -21,7 +21,7 @@ class Field: - def __init__(self, time_series: TimeSeries, pattern: Optional[Pattern] = None) -> None: + def __init__(self, time_series: TimeSeries, pattern: Optional[Pattern] = None) -> None: # noqa: UP007 """A space and time dependent parameter of a program. Args: @@ -37,15 +37,15 @@ def time_series(self) -> TimeSeries: return self._time_series @property - def pattern(self) -> Optional[Pattern]: + def pattern(self) -> Optional[Pattern]: # noqa: UP007 """Optional[Pattern]: The local pattern of real numbers.""" return self._pattern def discretize( self, - time_resolution: Optional[Decimal] = None, - value_resolution: Optional[Decimal] = None, - pattern_resolution: Optional[Decimal] = None, + time_resolution: Optional[Decimal] = None, # noqa: UP007 + value_resolution: Optional[Decimal] = None, # noqa: UP007 + pattern_resolution: Optional[Decimal] = None, # noqa: UP007 ) -> Field: """Creates a discretized version of the field, where time, value and pattern are rounded to the @@ -64,8 +64,7 @@ def discretize( discretized_pattern = None else: discretized_pattern = self.pattern.discretize(pattern_resolution) - discretized_field = Field(time_series=discretized_time_series, pattern=discretized_pattern) - return discretized_field + return Field(time_series=discretized_time_series, pattern=discretized_pattern) @staticmethod def from_lists(times: list[Decimal], values: list[Decimal], pattern: list[Decimal]) -> Field: @@ -90,6 +89,4 @@ def from_lists(times: list[Decimal], values: list[Decimal], pattern: list[Decima time_series = TimeSeries.from_lists(times=times, values=values) - field = Field(time_series=time_series, pattern=Pattern(pattern)) - - return field + return Field(time_series=time_series, pattern=Pattern(pattern)) diff --git a/src/braket/ahs/hamiltonian.py b/src/braket/ahs/hamiltonian.py index 548befc58..97c2b1e21 100644 --- a/src/braket/ahs/hamiltonian.py +++ b/src/braket/ahs/hamiltonian.py @@ -19,7 +19,7 @@ class Hamiltonian: - def __init__(self, terms: Optional[list[Hamiltonian]] = None): + def __init__(self, terms: Optional[list[Hamiltonian]] = None): # noqa: UP007 r"""A Hamiltonian representing a system to be simulated. A Hamiltonian :math:`H` may be expressed as a sum of multiple terms diff --git a/src/braket/ahs/local_detuning.py b/src/braket/ahs/local_detuning.py index 00b420210..43b7abaad 100644 --- a/src/braket/ahs/local_detuning.py +++ b/src/braket/ahs/local_detuning.py @@ -81,9 +81,7 @@ def from_lists(times: list[float], values: list[float], pattern: list[float]) -> magnitude = TimeSeries() for t, v in zip(times, values): magnitude.put(t, v) - shift = LocalDetuning(Field(magnitude, Pattern(pattern))) - - return shift + return LocalDetuning(Field(magnitude, Pattern(pattern))) def stitch( self, other: LocalDetuning, boundary: StitchBoundaryCondition = StitchBoundaryCondition.MEAN diff --git a/src/braket/ahs/pattern.py b/src/braket/ahs/pattern.py index 92637fe0f..2bf9be852 100644 --- a/src/braket/ahs/pattern.py +++ b/src/braket/ahs/pattern.py @@ -35,7 +35,7 @@ def series(self) -> list[Number]: """ return self._series - def discretize(self, resolution: Optional[Decimal]) -> Pattern: + def discretize(self, resolution: Optional[Decimal]) -> Pattern: # noqa: UP007 """Creates a discretized version of the pattern, where each value is rounded to the closest multiple of the resolution. diff --git a/src/braket/annealing/problem.py b/src/braket/annealing/problem.py index 9515cbfa6..80bea2d37 100644 --- a/src/braket/annealing/problem.py +++ b/src/braket/annealing/problem.py @@ -148,7 +148,6 @@ def to_ir(self) -> Problem: type=ir.ProblemType[self._problem_type.value], linear=self._linear, quadratic={ - ",".join((str(q1), str(q2))): self._quadratic[(q1, q2)] - for q1, q2 in self._quadratic + ",".join((str(q1), str(q2))): self._quadratic[q1, q2] for q1, q2 in self._quadratic }, ) diff --git a/src/braket/aws/aws_device.py b/src/braket/aws/aws_device.py index 598271424..4e4a0beaa 100644 --- a/src/braket/aws/aws_device.py +++ b/src/braket/aws/aws_device.py @@ -18,9 +18,9 @@ import os import urllib.request import warnings -from datetime import datetime +from datetime import datetime, timezone from enum import Enum -from typing import Any, ClassVar, Optional, Union +from typing import Any, ClassVar, Optional from botocore.errorfactory import ClientError from networkx import DiGraph, complete_graph, from_edgelist @@ -70,7 +70,7 @@ class AwsDevice(Device): _GET_DEVICES_ORDER_BY_KEYS = frozenset({"arn", "name", "type", "provider_name", "status"}) - _RIGETTI_GATES_TO_BRAKET: ClassVar[dict[str, str | None]] = { + _RIGETTI_GATES_TO_BRAKET: ClassVar[Optional[dict[str, str]]] = { # noqa: UP007 # Rx_12 does not exist in the Braket SDK, it is a gate between |1> and |2>. "Rx_12": None, "Cz": "CZ", @@ -82,8 +82,8 @@ class AwsDevice(Device): def __init__( self, arn: str, - aws_session: Optional[AwsSession] = None, - noise_model: Optional[NoiseModel] = None, + aws_session: Optional[AwsSession] = None, # noqa: UP007 + noise_model: Optional[NoiseModel] = None, # noqa: UP007 ): """Initializes an `AwsDevice`. @@ -120,21 +120,19 @@ def __init__( def run( self, - task_specification: Union[ - Circuit, - Problem, - OpenQasmProgram, - BlackbirdProgram, - PulseSequence, - AnalogHamiltonianSimulation, - ], - s3_destination_folder: Optional[AwsSession.S3DestinationFolder] = None, - shots: Optional[int] = None, + task_specification: Circuit + | Problem + | OpenQasmProgram + | BlackbirdProgram + | PulseSequence + | AnalogHamiltonianSimulation, + s3_destination_folder: Optional[AwsSession.S3DestinationFolder] = None, # noqa: UP007 + shots: Optional[int] = None, # noqa: UP007 poll_timeout_seconds: float = AwsQuantumTask.DEFAULT_RESULTS_POLL_TIMEOUT, - poll_interval_seconds: Optional[float] = None, - inputs: Optional[dict[str, float]] = None, - gate_definitions: Optional[dict[tuple[Gate, QubitSet], PulseSequence]] = None, - reservation_arn: str | None = None, + poll_interval_seconds: Optional[float] = None, # noqa: UP007 + inputs: Optional[dict[str, float]] = None, # noqa: UP007 + gate_definitions: Optional[dict[tuple[Gate, QubitSet], PulseSequence]] = None, # noqa: UP007 + reservation_arn: Optional[str] = None, # noqa: UP007 *aws_quantum_task_args: Any, **aws_quantum_task_kwargs: Any, ) -> AwsQuantumTask: @@ -202,7 +200,7 @@ def run( See Also: `braket.aws.aws_quantum_task.AwsQuantumTask.create()` - """ # noqa E501 + """ # noqa: E501 if self._noise_model: task_specification = self._apply_noise_model_to_circuit(task_specification) return AwsQuantumTask.create( @@ -228,35 +226,29 @@ def run( def run_batch( self, - task_specifications: Union[ - Union[ - Circuit, - Problem, - OpenQasmProgram, - BlackbirdProgram, - PulseSequence, - AnalogHamiltonianSimulation, - ], - list[ - Union[ - Circuit, - Problem, - OpenQasmProgram, - BlackbirdProgram, - PulseSequence, - AnalogHamiltonianSimulation, - ] - ], + task_specifications: Circuit + | Problem + | OpenQasmProgram + | BlackbirdProgram + | PulseSequence + | AnalogHamiltonianSimulation + | list[ + Circuit + | Problem + | OpenQasmProgram + | BlackbirdProgram + | PulseSequence + | AnalogHamiltonianSimulation ], - s3_destination_folder: Optional[AwsSession.S3DestinationFolder] = None, - shots: Optional[int] = None, - max_parallel: Optional[int] = None, + s3_destination_folder: Optional[AwsSession.S3DestinationFolder] = None, # noqa: UP007 + shots: Optional[int] = None, # noqa: UP007 + max_parallel: Optional[int] = None, # noqa: UP007 max_connections: int = AwsQuantumTaskBatch.MAX_CONNECTIONS_DEFAULT, poll_timeout_seconds: float = AwsQuantumTask.DEFAULT_RESULTS_POLL_TIMEOUT, poll_interval_seconds: float = AwsQuantumTask.DEFAULT_RESULTS_POLL_INTERVAL, - inputs: Optional[Union[dict[str, float], list[dict[str, float]]]] = None, - gate_definitions: Optional[dict[tuple[Gate, QubitSet], PulseSequence]] = None, - reservation_arn: Optional[str] = None, + inputs: Optional[dict[str, float] | list[dict[str, float]]] = None, # noqa: UP007 + gate_definitions: Optional[dict[tuple[Gate, QubitSet], PulseSequence]] = None, # noqa: UP007 + reservation_arn: Optional[str] = None, # noqa: UP007 *aws_quantum_task_args, **aws_quantum_task_kwargs, ) -> AwsQuantumTaskBatch: @@ -299,7 +291,7 @@ def run_batch( See Also: `braket.aws.aws_quantum_task_batch.AwsQuantumTaskBatch` - """ # noqa E501 + """ # noqa: E501 if self._noise_model: task_specifications = [ self._apply_noise_model_to_circuit(task_specification) @@ -349,33 +341,36 @@ def _get_regional_device_session(self, session: AwsSession) -> AwsSession: ) try: self._populate_properties(region_session) - return region_session except ClientError as e: raise ( ValueError(f"'{self._arn}' not found") if e.response["Error"]["Code"] == "ResourceNotFoundException" else e ) from e + else: + return region_session def _get_non_regional_device_session(self, session: AwsSession) -> AwsSession: current_region = session.region try: self._populate_properties(session) - return session except ClientError as e: if e.response["Error"]["Code"] != "ResourceNotFoundException": - raise e + raise if "qpu" not in self._arn: raise ValueError(f"Simulator '{self._arn}' not found in '{current_region}'") from e + else: + return session # Search remaining regions for QPU for region in frozenset(AwsDevice.REGIONS) - {current_region}: region_session = AwsSession.copy_session(session, region) try: self._populate_properties(region_session) - return region_session except ClientError as e: if e.response["Error"]["Code"] != "ResourceNotFoundException": - raise e + raise + else: + return region_session raise ValueError(f"QPU '{self._arn}' not found") def _populate_properties(self, session: AwsSession) -> None: @@ -415,7 +410,7 @@ def arn(self) -> str: return self._arn @property - def gate_calibrations(self) -> Optional[GateCalibrations]: + def gate_calibrations(self) -> Optional[GateCalibrations]: # noqa: UP007 """Calibration data for a QPU. Calibration data is shown for gates on particular gubits. If a QPU does not expose these calibrations, None is returned. @@ -439,7 +434,7 @@ def is_available(self) -> bool: is_available_result = False - current_datetime_utc = datetime.utcnow() + current_datetime_utc = datetime.now(tz=timezone.utc) for execution_window in self.properties.service.executionWindows: weekday = current_datetime_utc.weekday() current_time_utc = current_datetime_utc.time().replace(microsecond=0) @@ -537,13 +532,12 @@ def _construct_topology_graph(self) -> DiGraph: i = item[0] edges.extend([(int(i), int(j)) for j in item[1]]) return from_edgelist(edges, create_using=DiGraph()) - elif hasattr(self.properties, "provider") and isinstance( + if hasattr(self.properties, "provider") and isinstance( self.properties.provider, DwaveProviderProperties ): edges = self.properties.provider.couplers return from_edgelist(edges, create_using=DiGraph()) - else: - return None + return None @property def _default_shots(self) -> int: @@ -581,21 +575,21 @@ def ports(self) -> dict[str, Port]: @staticmethod def get_devices( - arns: Optional[list[str]] = None, - names: Optional[list[str]] = None, - types: Optional[list[AwsDeviceType]] = None, - statuses: Optional[list[str]] = None, - provider_names: Optional[list[str]] = None, + arns: Optional[list[str]] = None, # noqa: UP007 + names: Optional[list[str]] = None, # noqa: UP007 + types: Optional[list[AwsDeviceType]] = None, # noqa: UP007 + statuses: Optional[list[str]] = None, # noqa: UP007 + provider_names: Optional[list[str]] = None, # noqa: UP007 order_by: str = "name", - aws_session: Optional[AwsSession] = None, + aws_session: Optional[AwsSession] = None, # noqa: UP007 ) -> list[AwsDevice]: """Get devices based on filters and desired ordering. The result is the AND of all the filters `arns`, `names`, `types`, `statuses`, `provider_names`. Examples: - >>> AwsDevice.get_devices(provider_names=['Rigetti'], statuses=['ONLINE']) - >>> AwsDevice.get_devices(order_by='provider_name') - >>> AwsDevice.get_devices(types=['SIMULATOR']) + >>> AwsDevice.get_devices(provider_names=["Rigetti"], statuses=["ONLINE"]) + >>> AwsDevice.get_devices(order_by="provider_name") + >>> AwsDevice.get_devices(types=["SIMULATOR"]) Args: arns (Optional[list[str]]): device ARN filter, default is `None` @@ -761,7 +755,7 @@ def queue_depth(self) -> QueueDepthInfo: return QueueDepthInfo(**queue_info) - def refresh_gate_calibrations(self) -> Optional[GateCalibrations]: + def refresh_gate_calibrations(self) -> Optional[GateCalibrations]: # noqa: UP007 """Refreshes the gate calibration data upon request. If the device does not have calibration data, None is returned. @@ -779,7 +773,7 @@ def refresh_gate_calibrations(self) -> Optional[GateCalibrations]: and self.properties.pulse.nativeGateCalibrationsRef ): try: - with urllib.request.urlopen( + with urllib.request.urlopen( # noqa: S310 self.properties.pulse.nativeGateCalibrationsRef.split("?")[0] ) as f: json_calibration_data = self._parse_calibration_json( @@ -795,8 +789,8 @@ def refresh_gate_calibrations(self) -> Optional[GateCalibrations]: def _parse_waveforms(self, waveforms_json: dict) -> dict: waveforms = {} - for waveform in waveforms_json: - parsed_waveform = _parse_waveform_from_calibration_schema(waveforms_json[waveform]) + for waveform in waveforms_json.values(): + parsed_waveform = _parse_waveform_from_calibration_schema(waveform) waveforms[parsed_waveform.id] = parsed_waveform return waveforms diff --git a/src/braket/aws/aws_quantum_job.py b/src/braket/aws/aws_quantum_job.py index 37eb67603..55e903b1a 100644 --- a/src/braket/aws/aws_quantum_job.py +++ b/src/braket/aws/aws_quantum_job.py @@ -470,7 +470,7 @@ def metrics( if "startedAt" in metadata: job_start = int(metadata["startedAt"].timestamp()) if self.state() in AwsQuantumJob.TERMINAL_STATES and "endedAt" in metadata: - job_end = int(math.ceil(metadata["endedAt"].timestamp())) + job_end = math.ceil(metadata["endedAt"].timestamp()) return fetcher.get_metrics_for_job( self.name, metric_type, statistic, job_start, job_end, self._logs_prefix ) @@ -515,8 +515,7 @@ def result( except ClientError as e: if e.response["Error"]["Code"] == "404": return {} - else: - raise e + raise return AwsQuantumJob._read_and_deserialize_results(temp_dir, job_name) @staticmethod @@ -561,8 +560,7 @@ def download_result( AwsQuantumJob._attempt_results_download(self, output_s3_uri, output_s3_path) AwsQuantumJob._extract_tar_file(f"{extract_to}/{self.name}") return - else: - time.sleep(poll_interval_seconds) + time.sleep(poll_interval_seconds) raise TimeoutError( f"{job_response['jobName']}: Polling for job completion " @@ -576,7 +574,7 @@ def _attempt_results_download(self, output_bucket_uri: str, output_s3_path: str) ) except ClientError as e: if e.response["Error"]["Code"] != "404": - raise e + raise exception_response = { "Error": { "Code": "404", @@ -589,7 +587,7 @@ def _attempt_results_download(self, output_bucket_uri: str, output_s3_path: str) @staticmethod def _extract_tar_file(extract_path: str) -> None: with tarfile.open(AwsQuantumJob.RESULTS_TAR_FILENAME, "r:gz") as tar: - tar.extractall(extract_path) + tar.extractall(extract_path) # noqa: S202 def __repr__(self) -> str: return f"AwsQuantumJob('arn':'{self.arn}')" @@ -623,13 +621,14 @@ def _initialize_regional_device_session( logger.info(f"Changed session region from '{current_region}' to '{device_region}'") try: aws_session.get_device(device) - return aws_session except ClientError as e: raise ( ValueError(f"'{device}' not found.") if e.response["Error"]["Code"] == "ResourceNotFoundException" else e ) from e + else: + return aws_session @staticmethod def _initialize_non_regional_device_session( @@ -638,13 +637,14 @@ def _initialize_non_regional_device_session( original_region = aws_session.region try: aws_session.get_device(device) - return aws_session except ClientError as e: if e.response["Error"]["Code"] != "ResourceNotFoundException": - raise e + raise if "qpu" not in device: raise ValueError(f"Simulator '{device}' not found in '{original_region}'") from e + else: + return aws_session for region in frozenset(AwsDevice.REGIONS) - {original_region}: device_session = aws_session.copy_session(region=region) try: @@ -652,8 +652,9 @@ def _initialize_non_regional_device_session( logger.info( f"Changed session region from '{original_region}' to '{device_session.region}'" ) - return device_session except ClientError as e: if e.response["Error"]["Code"] != "ResourceNotFoundException": - raise e + raise + else: + return device_session raise ValueError(f"QPU '{device}' not found.") diff --git a/src/braket/aws/aws_quantum_task.py b/src/braket/aws/aws_quantum_task.py index a21c7782c..5e72ad223 100644 --- a/src/braket/aws/aws_quantum_task.py +++ b/src/braket/aws/aws_quantum_task.py @@ -14,6 +14,7 @@ from __future__ import annotations import asyncio +import contextlib import time from functools import singledispatch from logging import Logger, getLogger @@ -92,23 +93,21 @@ class AwsQuantumTask(QuantumTask): def create( aws_session: AwsSession, device_arn: str, - task_specification: Union[ - Circuit, - Problem, - OpenQASMProgram, - BlackbirdProgram, - PulseSequence, - AnalogHamiltonianSimulation, - ], + task_specification: Circuit + | Problem + | OpenQASMProgram + | BlackbirdProgram + | PulseSequence + | AnalogHamiltonianSimulation, s3_destination_folder: AwsSession.S3DestinationFolder, shots: int, - device_parameters: dict[str, Any] | None = None, + device_parameters: Optional[dict[str, Any]] = None, # noqa: UP007 disable_qubit_rewiring: bool = False, - tags: dict[str, str] | None = None, - inputs: dict[str, float] | None = None, - gate_definitions: dict[tuple[Gate, QubitSet], PulseSequence] | None = None, + tags: Optional[dict[str, str]] = None, # noqa: UP007 + inputs: Optional[dict[str, float]] = None, # noqa: UP007 + gate_definitions: Optional[dict[tuple[Gate, QubitSet], PulseSequence]] = None, # noqa: UP007 quiet: bool = False, - reservation_arn: str | None = None, + reservation_arn: Optional[str] = None, # noqa: UP007 *args, **kwargs, ) -> AwsQuantumTask: @@ -175,7 +174,7 @@ def create( See Also: `braket.aws.aws_quantum_simulator.AwsQuantumSimulator.run()` `braket.aws.aws_qpu.AwsQpu.run()` - """ # noqa E501 + """ # noqa: E501 if len(s3_destination_folder) != 2: raise ValueError( "s3_destination_folder must be of size 2 with a 'bucket' and 'key' respectively." @@ -193,16 +192,14 @@ def create( gate_definitions = gate_definitions or {} if reservation_arn: - create_task_kwargs.update( - { - "associations": [ - { - "arn": reservation_arn, - "type": "RESERVATION_TIME_WINDOW_ARN", - } - ] - } - ) + create_task_kwargs.update({ + "associations": [ + { + "arn": reservation_arn, + "type": "RESERVATION_TIME_WINDOW_ARN", + } + ] + }) if isinstance(task_specification, Circuit): param_names = {param.name for param in task_specification.parameters} @@ -228,7 +225,7 @@ def create( def __init__( self, arn: str, - aws_session: AwsSession | None = None, + aws_session: Optional[AwsSession] = None, # noqa: UP007 poll_timeout_seconds: float = DEFAULT_RESULTS_POLL_TIMEOUT, poll_interval_seconds: float = DEFAULT_RESULTS_POLL_INTERVAL, logger: Logger = getLogger(__name__), @@ -250,13 +247,13 @@ def __init__( position. Default is `False`. Examples: - >>> task = AwsQuantumTask(arn='task_arn') + >>> task = AwsQuantumTask(arn="task_arn") >>> task.state() 'COMPLETED' >>> result = task.result() AnnealingQuantumTaskResult(...) - >>> task = AwsQuantumTask(arn='task_arn', poll_timeout_seconds=300) + >>> task = AwsQuantumTask(arn="task_arn", poll_timeout_seconds=300) >>> result = task.result() GateModelQuantumTaskResult(...) """ @@ -271,8 +268,8 @@ def __init__( self._quiet = quiet self._metadata: dict[str, Any] = {} - self._result: Union[ - GateModelQuantumTaskResult, AnnealingQuantumTaskResult, PhotonicModelQuantumTaskResult + self._result: Optional[ # noqa: UP007 + GateModelQuantumTaskResult | AnnealingQuantumTaskResult | PhotonicModelQuantumTaskResult ] = None @staticmethod @@ -395,9 +392,7 @@ def _update_status_if_nonterminal(self) -> str: def result( self, - ) -> Union[ - GateModelQuantumTaskResult, AnnealingQuantumTaskResult, PhotonicModelQuantumTaskResult - ]: + ) -> GateModelQuantumTaskResult | AnnealingQuantumTaskResult | PhotonicModelQuantumTaskResult: """Get the quantum task result by polling Amazon Braket to see if the task is completed. Once the quantum task is completed, the result is retrieved from S3 and returned as a `GateModelQuantumTaskResult` or `AnnealingQuantumTaskResult` @@ -410,7 +405,7 @@ def result( Union[GateModelQuantumTaskResult, AnnealingQuantumTaskResult, PhotonicModelQuantumTaskResult]: The result of the quantum task, if the quantum task completed successfully; returns `None` if the quantum task did not complete successfully or the future timed out. - """ # noqa E501 + """ # noqa: E501 if self._result or ( self._metadata and self._status(True) in self.NO_RESULT_TERMINAL_STATES ): @@ -460,9 +455,7 @@ async def _create_future(self) -> asyncio.Task: async def _wait_for_completion( self, - ) -> Union[ - GateModelQuantumTaskResult, AnnealingQuantumTaskResult, PhotonicModelQuantumTaskResult - ]: + ) -> GateModelQuantumTaskResult | AnnealingQuantumTaskResult | PhotonicModelQuantumTaskResult: """Waits for the quantum task to be completed, then returns the result from the S3 bucket. Returns: @@ -475,7 +468,7 @@ async def _wait_for_completion( Note: Timeout and sleep intervals are defined in the constructor fields `poll_timeout_seconds` and `poll_interval_seconds` respectively. - """ # noqa E501 + """ # noqa: E501 self._logger.debug(f"Task {self._arn}: start polling for completion") start_time = time.time() @@ -490,18 +483,17 @@ async def _wait_for_completion( self._logger.debug(f"Task {self._arn}: task status {task_status}") if task_status in AwsQuantumTask.RESULTS_READY_STATES: return self._download_result() - elif task_status in AwsQuantumTask.NO_RESULT_TERMINAL_STATES: + if task_status in AwsQuantumTask.NO_RESULT_TERMINAL_STATES: self._result = None return None - else: - await asyncio.sleep(self._poll_interval_seconds) + await asyncio.sleep(self._poll_interval_seconds) # Timed out self._logger.warning( f"Task {self._arn}: polling for task completion timed out after " - + f"{time.time() - start_time} seconds. Please increase the timeout; " - + "this can be done by creating a new AwsQuantumTask with this task's ARN " - + "and a higher value for the `poll_timeout_seconds` parameter." + f"{time.time() - start_time} seconds. Please increase the timeout; " + "this can be done by creating a new AwsQuantumTask with this task's ARN " + "and a higher value for the `poll_timeout_seconds` parameter." ) self._result = None return None @@ -514,9 +506,7 @@ def _has_reservation_arn_from_metadata(self, current_metadata: dict[str, Any]) - def _download_result( self, - ) -> Union[ - GateModelQuantumTaskResult, AnnealingQuantumTaskResult, PhotonicModelQuantumTaskResult - ]: + ) -> GateModelQuantumTaskResult | AnnealingQuantumTaskResult | PhotonicModelQuantumTaskResult: current_metadata = self.metadata(True) result_string = self._aws_session.retrieve_s3_object_body( current_metadata["outputS3Bucket"], @@ -529,12 +519,10 @@ def _download_result( "execution_duration": None, "has_reservation_arn": self._has_reservation_arn_from_metadata(current_metadata), } - try: + with contextlib.suppress(AttributeError): task_event["execution_duration"] = ( self._result.additional_metadata.simulatorMetadata.executionDuration ) - except AttributeError: - pass broadcast_event(_TaskCompletionEvent(**task_event)) return self._result @@ -550,11 +538,11 @@ def __hash__(self) -> int: @singledispatch def _create_internal( - task_specification: Union[Circuit, Problem, BlackbirdProgram], + task_specification: Circuit | Problem | BlackbirdProgram, aws_session: AwsSession, create_task_kwargs: dict[str, Any], device_arn: str, - device_parameters: Union[dict, BraketSchemaBase], + device_parameters: Union[dict[str, str], BraketSchemaBase], # noqa: UP007 disable_qubit_rewiring: bool, inputs: dict[str, float], gate_definitions: dict[tuple[Gate, QubitSet], PulseSequence], @@ -570,7 +558,8 @@ def _( aws_session: AwsSession, create_task_kwargs: dict[str, Any], device_arn: str, - _device_parameters: Union[dict, BraketSchemaBase], # Not currently used for OpenQasmProgram + # Not currently used for OpenQasmProgram + _device_parameters: Union[dict[str, str], BraketSchemaBase], # noqa: UP007 _disable_qubit_rewiring: bool, inputs: dict[str, float], gate_definitions: dict[tuple[Gate, QubitSet], PulseSequence], @@ -593,7 +582,7 @@ def _( aws_session: AwsSession, create_task_kwargs: dict[str, Any], device_arn: str, - device_parameters: Union[dict, BraketSchemaBase], + device_parameters: Union[dict, BraketSchemaBase], # noqa: UP007 _disable_qubit_rewiring: bool, inputs: dict[str, float], gate_definitions: dict[tuple[Gate, QubitSet], PulseSequence], @@ -630,10 +619,10 @@ def _( aws_session: AwsSession, create_task_kwargs: dict[str, Any], device_arn: str, - device_parameters: Union[dict, BraketSchemaBase], + device_parameters: Union[dict, BraketSchemaBase], # noqa: UP007 _disable_qubit_rewiring: bool, inputs: dict[str, float], - gate_definitions: Optional[dict[tuple[Gate, QubitSet], PulseSequence]], + gate_definitions: Optional[dict[tuple[Gate, QubitSet], PulseSequence]], # noqa: UP007 *args, **kwargs, ) -> AwsQuantumTask: @@ -658,7 +647,7 @@ def _( aws_session: AwsSession, create_task_kwargs: dict[str, any], device_arn: str, - _device_parameters: Union[dict, BraketSchemaBase], + _device_parameters: Union[dict, BraketSchemaBase], # noqa: UP007 _disable_qubit_rewiring: bool, inputs: dict[str, float], gate_definitions: dict[tuple[Gate, QubitSet], PulseSequence], @@ -676,7 +665,7 @@ def _( aws_session: AwsSession, create_task_kwargs: dict[str, Any], device_arn: str, - device_parameters: Union[dict, BraketSchemaBase], + device_parameters: Union[dict, BraketSchemaBase], # noqa: UP007 disable_qubit_rewiring: bool, inputs: dict[str, float], gate_definitions: dict[tuple[Gate, QubitSet], PulseSequence], @@ -737,15 +726,12 @@ def _( aws_session: AwsSession, create_task_kwargs: dict[str, Any], device_arn: str, - device_parameters: Union[ - dict, - DwaveDeviceParameters, - DwaveAdvantageDeviceParameters, - Dwave2000QDeviceParameters, + device_parameters: Union[ # noqa: UP007 + dict, DwaveDeviceParameters, DwaveAdvantageDeviceParameters, Dwave2000QDeviceParameters ], _: bool, inputs: dict[str, float], - gate_definitions: Optional[dict[tuple[Gate, QubitSet], PulseSequence]], + gate_definitions: Optional[dict[tuple[Gate, QubitSet], PulseSequence]], # noqa: UP007 *args, **kwargs, ) -> AwsQuantumTask: @@ -768,7 +754,7 @@ def _( device_parameters: dict, _: AnalogHamiltonianSimulationTaskResult, inputs: dict[str, float], - gate_definitions: Optional[dict[tuple[Gate, QubitSet], PulseSequence]], + gate_definitions: Optional[dict[tuple[Gate, QubitSet], PulseSequence]], # noqa: UP007 *args, **kwargs, ) -> AwsQuantumTask: @@ -798,7 +784,7 @@ def _circuit_device_params_from_dict( def _create_annealing_device_params( device_params: dict[str, Any], device_arn: str -) -> Union[DwaveAdvantageDeviceParameters, Dwave2000QDeviceParameters]: +) -> DwaveAdvantageDeviceParameters | Dwave2000QDeviceParameters: """Gets Annealing Device Parameters. Args: @@ -826,15 +812,14 @@ def _create_annealing_device_params( device_level_parameters ) return DwaveAdvantageDeviceParameters(deviceLevelParameters=device_level_parameters) - elif "2000Q" in device_arn: + if "2000Q" in device_arn: device_level_parameters = Dwave2000QDeviceLevelParameters.parse_obj(device_level_parameters) return Dwave2000QDeviceParameters(deviceLevelParameters=device_level_parameters) - else: - raise Exception( - f"Amazon Braket could not find a device with ARN: {device_arn}. " - "To continue, make sure that the value of the device_arn parameter " - "corresponds to a valid QPU." - ) + raise ValueError( + f"Amazon Braket could not find a device with ARN: {device_arn}. " + "To continue, make sure that the value of the device_arn parameter " + "corresponds to a valid QPU." + ) def _create_common_params( @@ -850,8 +835,8 @@ def _create_common_params( @singledispatch def _format_result( - result: Union[GateModelTaskResult, AnnealingTaskResult, PhotonicModelTaskResult], -) -> Union[GateModelQuantumTaskResult, AnnealingQuantumTaskResult, PhotonicModelQuantumTaskResult]: + result: GateModelTaskResult | AnnealingTaskResult | PhotonicModelTaskResult, +) -> GateModelQuantumTaskResult | AnnealingQuantumTaskResult | PhotonicModelQuantumTaskResult: raise TypeError("Invalid result specification type") diff --git a/src/braket/aws/aws_quantum_task_batch.py b/src/braket/aws/aws_quantum_task_batch.py index 30c3a8658..91fcf6b84 100644 --- a/src/braket/aws/aws_quantum_task_batch.py +++ b/src/braket/aws/aws_quantum_task_batch.py @@ -16,7 +16,7 @@ import time from concurrent.futures.thread import ThreadPoolExecutor from itertools import repeat -from typing import TYPE_CHECKING, Any, Union +from typing import TYPE_CHECKING, Any, Optional from braket.ahs.analog_hamiltonian_simulation import AnalogHamiltonianSimulation from braket.annealing import Problem @@ -57,13 +57,13 @@ def __init__( self, aws_session: AwsSession, device_arn: str, - task_specifications: Union[ - Union[Circuit, Problem, OpenQasmProgram, BlackbirdProgram, AnalogHamiltonianSimulation], - list[ - Union[ - Circuit, Problem, OpenQasmProgram, BlackbirdProgram, AnalogHamiltonianSimulation - ] - ], + task_specifications: Circuit + | Problem + | OpenQasmProgram + | BlackbirdProgram + | AnalogHamiltonianSimulation + | list[ + Circuit | Problem | OpenQasmProgram | BlackbirdProgram | AnalogHamiltonianSimulation ], s3_destination_folder: AwsSession.S3DestinationFolder, shots: int, @@ -71,15 +71,14 @@ def __init__( max_workers: int = MAX_CONNECTIONS_DEFAULT, poll_timeout_seconds: float = AwsQuantumTask.DEFAULT_RESULTS_POLL_TIMEOUT, poll_interval_seconds: float = AwsQuantumTask.DEFAULT_RESULTS_POLL_INTERVAL, - inputs: Union[dict[str, float], list[dict[str, float]]] | None = None, + inputs: Optional[dict[str, float] | list[dict[str, float]]] = None, # noqa: UP007 gate_definitions: ( - Union[ - dict[tuple[Gate, QubitSet], PulseSequence], - list[dict[tuple[Gate, QubitSet], PulseSequence]], + Optional[ # noqa: UP007 + dict[tuple[Gate, QubitSet], PulseSequence] + | list[dict[tuple[Gate, QubitSet], PulseSequence]] ] - | None ) = None, - reservation_arn: str | None = None, + reservation_arn: Optional[str] = None, # noqa: UP007 *aws_quantum_task_args: Any, **aws_quantum_task_kwargs: Any, ): @@ -120,7 +119,7 @@ def __init__( Default: None. *aws_quantum_task_args (Any): Arbitrary args for `QuantumTask`. **aws_quantum_task_kwargs (Any): Arbitrary kwargs for `QuantumTask`., - """ # noqa E501 + """ # noqa: E501 self._tasks = AwsQuantumTaskBatch._execute( aws_session, device_arn, @@ -157,22 +156,22 @@ def __init__( @staticmethod def _tasks_inputs_gatedefs( - task_specifications: Union[ - Union[Circuit, Problem, OpenQasmProgram, BlackbirdProgram, AnalogHamiltonianSimulation], - list[ - Union[ - Circuit, Problem, OpenQasmProgram, BlackbirdProgram, AnalogHamiltonianSimulation - ] - ], + task_specifications: Circuit + | Problem + | OpenQasmProgram + | BlackbirdProgram + | AnalogHamiltonianSimulation + | list[ + Circuit | Problem | OpenQasmProgram | BlackbirdProgram | AnalogHamiltonianSimulation ], - inputs: Union[dict[str, float], list[dict[str, float]]] = None, - gate_definitions: Union[ - dict[tuple[Gate, QubitSet], PulseSequence], - list[dict[tuple[Gate, QubitSet], PulseSequence]], + inputs: Optional[dict[str, float] | list[dict[str, float]]] = None, # noqa: UP007 + gate_definitions: Optional[ # noqa: UP007 + dict[tuple[Gate, QubitSet], PulseSequence] + | list[dict[tuple[Gate, QubitSet], PulseSequence]] ] = None, ) -> list[ tuple[ - Union[Circuit, Problem, OpenQasmProgram, BlackbirdProgram, AnalogHamiltonianSimulation], + Circuit | Problem | OpenQasmProgram | BlackbirdProgram | AnalogHamiltonianSimulation, dict[str, float], dict[tuple[Gate, QubitSet], PulseSequence], ] @@ -200,15 +199,14 @@ def _tasks_inputs_gatedefs( arg_lengths.append(arg_length) if arg_length != 1: - if batch_length != 1 and arg_length != batch_length: + if batch_length not in {1, arg_length}: raise ValueError( "Multiple inputs, task specifications and gate definitions must " "be equal in length." ) - else: - batch_length = arg_length + batch_length = arg_length - for i, arg_length in enumerate(arg_lengths): + for i in range(len(arg_lengths)): if isinstance(args[i], (dict, single_task_type)): args[i] = repeat(args[i], batch_length) @@ -219,8 +217,7 @@ def _tasks_inputs_gatedefs( param_names = {param.name for param in task_specification.parameters} if unbounded_parameters := param_names - set(input_map.keys()): raise ValueError( - f"Cannot execute circuit with unbound parameters: " - f"{unbounded_parameters}" + f"Cannot execute circuit with unbound parameters: {unbounded_parameters}" ) return tasks_inputs_definitions @@ -229,13 +226,13 @@ def _tasks_inputs_gatedefs( def _execute( aws_session: AwsSession, device_arn: str, - task_specifications: Union[ - Union[Circuit, Problem, OpenQasmProgram, BlackbirdProgram, AnalogHamiltonianSimulation], - list[ - Union[ - Circuit, Problem, OpenQasmProgram, BlackbirdProgram, AnalogHamiltonianSimulation - ] - ], + task_specifications: Circuit + | Problem + | OpenQasmProgram + | BlackbirdProgram + | AnalogHamiltonianSimulation + | list[ + Circuit | Problem | OpenQasmProgram | BlackbirdProgram | AnalogHamiltonianSimulation ], s3_destination_folder: AwsSession.S3DestinationFolder, shots: int, @@ -243,15 +240,14 @@ def _execute( max_workers: int = MAX_CONNECTIONS_DEFAULT, poll_timeout_seconds: float = AwsQuantumTask.DEFAULT_RESULTS_POLL_TIMEOUT, poll_interval_seconds: float = AwsQuantumTask.DEFAULT_RESULTS_POLL_INTERVAL, - inputs: Union[dict[str, float], list[dict[str, float]]] = None, + inputs: Optional[dict[str, float] | list[dict[str, float]]] = None, # noqa: UP007 gate_definitions: ( - Union[ - dict[tuple[Gate, QubitSet], PulseSequence], - list[dict[tuple[Gate, QubitSet], PulseSequence]], + Optional[ # noqa: UP007 + dict[tuple[Gate, QubitSet], PulseSequence] + | list[dict[tuple[Gate, QubitSet], PulseSequence]] ] - | None ) = None, - reservation_arn: str | None = None, + reservation_arn: Optional[str] = None, # noqa: UP007 *args, **kwargs, ) -> list[AwsQuantumTask]: @@ -292,22 +288,23 @@ def _execute( remaining.clear() raise - tasks = [future.result() for future in task_futures] - return tasks + return [future.result() for future in task_futures] @staticmethod def _create_task( remaining: list[int], aws_session: AwsSession, device_arn: str, - task_specification: Union[ - Circuit, Problem, OpenQasmProgram, BlackbirdProgram, AnalogHamiltonianSimulation - ], + task_specification: Circuit + | Problem + | OpenQasmProgram + | BlackbirdProgram + | AnalogHamiltonianSimulation, s3_destination_folder: AwsSession.S3DestinationFolder, shots: int, poll_interval_seconds: float = AwsQuantumTask.DEFAULT_RESULTS_POLL_INTERVAL, - inputs: dict[str, float] = None, - gate_definitions: dict[tuple[Gate, QubitSet], PulseSequence] | None = None, + inputs: Optional[dict[str, float]] = None, # noqa: UP007 + gate_definitions: Optional[dict[tuple[Gate, QubitSet], PulseSequence]] = None, # noqa: UP007 reservation_arn: str | None = None, *args, **kwargs, @@ -361,10 +358,10 @@ def results( even when results have already been cached. Default: `True`. Returns: - list[GateModelQuantumTaskResult | AnnealingQuantumTaskResult | PhotonicModelQuantumTaskResult | AnalogHamiltonianSimulationQuantumTaskResult]: The # noqa: E501 + list[GateModelQuantumTaskResult | AnnealingQuantumTaskResult | PhotonicModelQuantumTaskResult | AnalogHamiltonianSimulationQuantumTaskResult]: The results of all of the quantum tasks in the batch. `FAILED`, `CANCELLED`, or timed out quantum tasks will have a result of None - """ + """ # noqa: E501 if not self._results or not use_cached_value: self._results = AwsQuantumTaskBatch._retrieve_results(self._tasks, self._max_workers) self._unsuccessful = { @@ -458,8 +455,8 @@ def unfinished(self) -> set[str]: with ThreadPoolExecutor(max_workers=self._max_workers) as executor: status_futures = {task.id: executor.submit(task.state) for task in self._tasks} unfinished = set() - for task_id in status_futures: - status = status_futures[task_id].result() + for task_id, task_result in status_futures.items(): + status = task_result.result() if status not in AwsQuantumTask.TERMINAL_STATES: unfinished.add(task_id) if status in AwsQuantumTask.NO_RESULT_TERMINAL_STATES: diff --git a/src/braket/aws/aws_session.py b/src/braket/aws/aws_session.py index b4cdfcd31..b29752e38 100644 --- a/src/braket/aws/aws_session.py +++ b/src/braket/aws/aws_session.py @@ -34,7 +34,7 @@ from braket.tracking.tracking_events import _TaskCreationEvent, _TaskStatusEvent -class AwsSession: +class AwsSession: # noqa: PLR0904 """Manage interactions with AWS services.""" class S3DestinationFolder(NamedTuple): @@ -45,10 +45,10 @@ class S3DestinationFolder(NamedTuple): def __init__( self, - boto_session: boto3.Session | None = None, - braket_client: client | None = None, - config: Config | None = None, - default_bucket: str | None = None, + boto_session: Optional[boto3.Session] = None, # noqa: UP007 + braket_client: Optional[client] = None, # noqa: UP007 + config: Optional[Config] = None, # noqa: UP007 + default_bucket: Optional[str] = None, # noqa: UP007 ): """Initializes an `AwsSession`. @@ -211,7 +211,7 @@ def _add_braket_user_agents_handler(self, request: awsrequest.AWSRequest, **kwar request.headers.add_header("User-Agent", self._braket_user_agents) @staticmethod - def _add_cost_tracker_count_handler(request: awsrequest.AWSRequest, **kwargs) -> None: + def _add_cost_tracker_count_handler(request: awsrequest.AWSRequest, **kwargs) -> None: # noqa: ARG004 request.headers.add_header("Braket-Trackers", str(len(active_trackers()))) # @@ -250,7 +250,8 @@ def create_quantum_task(self, **boto3_kwargs) -> str: warnings.warn( "A reservation ARN was passed to 'CreateQuantumTask', but it is being overridden " "by a 'DirectReservation' context. If this was not intended, please review your " - "reservation ARN settings or the context in which 'CreateQuantumTask' is called." + "reservation ARN settings or the context in which 'CreateQuantumTask' is called.", + stacklevel=2, ) # Ensure reservation only applies to specific device @@ -294,10 +295,10 @@ def _should_giveup(err: Exception) -> bool: return not ( isinstance(err, ClientError) and err.response["Error"]["Code"] - in [ + in { "ResourceNotFoundException", "ThrottlingException", - ] + } ) @backoff.on_exception( @@ -606,9 +607,8 @@ def _create_s3_bucket_if_it_does_not_exist(self, bucket_name: str, region: str) error_code = e.response["Error"]["Code"] message = e.response["Error"]["Message"] - if ( - error_code == "BucketAlreadyOwnedByYou" - or error_code != "BucketAlreadyExists" + if error_code == "BucketAlreadyOwnedByYou" or ( + error_code != "BucketAlreadyExists" and error_code == "OperationAborted" and "conflicting conditional operation" in message ): @@ -635,11 +635,11 @@ def get_device(self, arn: str) -> dict[str, Any]: def search_devices( self, - arns: Optional[list[str]] = None, - names: Optional[list[str]] = None, - types: Optional[list[str]] = None, - statuses: Optional[list[str]] = None, - provider_names: Optional[list[str]] = None, + arns: Optional[list[str]] = None, # noqa: UP007 + names: Optional[list[str]] = None, # noqa: UP007 + types: Optional[list[str]] = None, # noqa: UP007 + statuses: Optional[list[str]] = None, # noqa: UP007 + provider_names: Optional[list[str]] = None, # noqa: UP007 ) -> list[dict[str, Any]]: """Get devices based on filters. The result is the AND of all the filters `arns`, `names`, `types`, `statuses`, `provider_names`. @@ -714,11 +714,12 @@ def parse_s3_uri(s3_uri: str) -> tuple[str, str]: r"^[sS]3://([^./]+)/(.+)$", s3_uri ) if s3_uri_match is None: - raise AssertionError + raise AssertionError # noqa: TRY301 bucket, key = s3_uri_match.groups() - return bucket, key except (AssertionError, ValueError) as e: raise ValueError(f"Not a valid S3 uri: {s3_uri}") from e + else: + return bucket, key @staticmethod def construct_s3_uri(bucket: str, *dirs: str) -> str: @@ -743,8 +744,8 @@ def describe_log_streams( self, log_group: str, log_stream_prefix: str, - limit: Optional[int] = None, - next_token: Optional[str] = None, + limit: Optional[int] = None, # noqa: UP007 + next_token: Optional[str] = None, # noqa: UP007 ) -> dict[str, Any]: """Describes CloudWatch log streams in a log group with a given prefix. @@ -779,7 +780,7 @@ def get_log_events( log_stream: str, start_time: int, start_from_head: bool = True, - next_token: Optional[str] = None, + next_token: Optional[str] = None, # noqa: UP007 ) -> dict[str, Any]: """Gets CloudWatch log events from a given log stream. @@ -809,8 +810,8 @@ def get_log_events( def copy_session( self, - region: Optional[str] = None, - max_connections: Optional[int] = None, + region: Optional[str] = None, # noqa: UP007 + max_connections: Optional[int] = None, # noqa: UP007 ) -> AwsSession: """Creates a new AwsSession based on the region. @@ -856,7 +857,7 @@ def copy_session( copied_session._braket_user_agents = self._braket_user_agents return copied_session - @cache + @cache # noqa: B019 def get_full_image_tag(self, image_uri: str) -> str: """Get verbose image tag from image uri. diff --git a/src/braket/aws/direct_reservations.py b/src/braket/aws/direct_reservations.py index 4ffcb8fce..fe7baac82 100644 --- a/src/braket/aws/direct_reservations.py +++ b/src/braket/aws/direct_reservations.py @@ -63,7 +63,8 @@ def __init__(self, device: Device | str | None, reservation_arn: str | None): elif isinstance(device, Device) or device is None: # LocalSimulator warnings.warn( "Using a local simulator with the reservation. For a reservation on a QPU, please " - "ensure the device matches the reserved Braket device." + "ensure the device matches the reserved Braket device.", + stacklevel=2, ) self.device_arn = "" # instead of None, use empty string else: @@ -75,7 +76,7 @@ def __enter__(self): self.start() return self - def __exit__(self, exc_type, exc_val, exc_tb) -> None: + def __exit__(self, exc_type, exc_val, exc_tb) -> None: # noqa: ANN001 self.stop() def start(self) -> None: @@ -91,7 +92,7 @@ def start(self) -> None: def stop(self) -> None: """Stop the reservation context.""" if not DirectReservation._is_active: - warnings.warn("Reservation context is not active.") + warnings.warn("Reservation context is not active.", stacklevel=2) return os.environ.pop("AMZN_BRAKET_RESERVATION_DEVICE_ARN", None) os.environ.pop("AMZN_BRAKET_RESERVATION_TIME_WINDOW_ARN", None) diff --git a/src/braket/circuits/__init__.py b/src/braket/circuits/__init__.py index a5fb52980..0e0f36c14 100644 --- a/src/braket/circuits/__init__.py +++ b/src/braket/circuits/__init__.py @@ -11,15 +11,18 @@ # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. -from braket.circuits import ( # noqa: F401 - circuit, - compiler_directives, - gates, - noises, - observables, - result_types, +from braket.circuits import ( + circuit, # noqa: F401 + compiler_directives, # noqa: F401 + gates, # noqa: F401 + noises, # noqa: F401 + observables, # noqa: F401 + result_types, # noqa: F401 +) +from braket.circuits.angled_gate import ( + AngledGate, # noqa: F401 + DoubleAngledGate, # noqa: F401 ) -from braket.circuits.angled_gate import AngledGate, DoubleAngledGate # noqa: F401 from braket.circuits.circuit import Circuit # noqa: F401 from braket.circuits.circuit_diagram import CircuitDiagram # noqa: F401 from braket.circuits.compiler_directive import CompilerDirective # noqa: F401 @@ -30,16 +33,22 @@ from braket.circuits.instruction import Instruction # noqa: F401 from braket.circuits.moments import Moments, MomentsKey # noqa: F401 from braket.circuits.noise import Noise # noqa: F401 -from braket.circuits.observable import Observable, StandardObservable # noqa: F401 +from braket.circuits.observable import ( + Observable, # noqa: F401 + StandardObservable, # noqa: F401 +) from braket.circuits.operator import Operator # noqa: F401 from braket.circuits.parameterizable import Parameterizable # noqa: F401 from braket.circuits.quantum_operator import QuantumOperator # noqa: F401 from braket.circuits.qubit import Qubit, QubitInput # noqa: F401 from braket.circuits.qubit_set import QubitSet, QubitSetInput # noqa: F401 -from braket.circuits.result_type import ObservableResultType, ResultType # noqa: F401 -from braket.circuits.text_diagram_builders.ascii_circuit_diagram import ( # noqa: F401 - AsciiCircuitDiagram, +from braket.circuits.result_type import ( + ObservableResultType, # noqa: F401 + ResultType, # noqa: F401 +) +from braket.circuits.text_diagram_builders.ascii_circuit_diagram import ( + AsciiCircuitDiagram, # noqa: F401 ) -from braket.circuits.text_diagram_builders.unicode_circuit_diagram import ( # noqa: F401 - UnicodeCircuitDiagram, +from braket.circuits.text_diagram_builders.unicode_circuit_diagram import ( + UnicodeCircuitDiagram, # noqa: F401 ) diff --git a/src/braket/circuits/angled_gate.py b/src/braket/circuits/angled_gate.py index 49447e58f..5cf5c8854 100644 --- a/src/braket/circuits/angled_gate.py +++ b/src/braket/circuits/angled_gate.py @@ -17,7 +17,7 @@ import math from collections.abc import Sequence from functools import singledispatch -from typing import Optional, Union +from typing import Optional from sympy import Float @@ -31,8 +31,8 @@ class AngledGate(Gate, Parameterizable): def __init__( self, - angle: Union[FreeParameterExpression, float], - qubit_count: Optional[int], + angle: FreeParameterExpression | float, + qubit_count: Optional[int], # noqa: UP007 ascii_symbols: Sequence[str], ): """Initializes an `AngledGate`. @@ -61,7 +61,7 @@ def __init__( self._parameters = [float(angle)] # explicit casting in case angle is e.g. np.float32 @property - def parameters(self) -> list[Union[FreeParameterExpression, float]]: + def parameters(self) -> list[FreeParameterExpression | float]: """Returns the parameters associated with the object, either unbound free parameters or bound values. @@ -72,7 +72,7 @@ def parameters(self) -> list[Union[FreeParameterExpression, float]]: return self._parameters @property - def angle(self) -> Union[FreeParameterExpression, float]: + def angle(self) -> FreeParameterExpression | float: """Returns the angle of the gate Returns: @@ -128,9 +128,9 @@ class DoubleAngledGate(Gate, Parameterizable): def __init__( self, - angle_1: Union[FreeParameterExpression, float], - angle_2: Union[FreeParameterExpression, float], - qubit_count: Optional[int], + angle_1: FreeParameterExpression | float, + angle_2: FreeParameterExpression | float, + qubit_count: Optional[int], # noqa: UP007 ascii_symbols: Sequence[str], ): """Inits a `DoubleAngledGate`. @@ -165,7 +165,7 @@ def __init__( ] @property - def parameters(self) -> list[Union[FreeParameterExpression, float]]: + def parameters(self) -> list[FreeParameterExpression | float]: """Returns the parameters associated with the object, either unbound free parameters or bound values. @@ -176,7 +176,7 @@ def parameters(self) -> list[Union[FreeParameterExpression, float]]: return self._parameters @property - def angle_1(self) -> Union[FreeParameterExpression, float]: + def angle_1(self) -> FreeParameterExpression | float: """Returns the first angle of the gate Returns: @@ -185,7 +185,7 @@ def angle_1(self) -> Union[FreeParameterExpression, float]: return self._parameters[0] @property - def angle_2(self) -> Union[FreeParameterExpression, float]: + def angle_2(self) -> FreeParameterExpression | float: """Returns the second angle of the gate Returns: @@ -240,10 +240,10 @@ class TripleAngledGate(Gate, Parameterizable): def __init__( self, - angle_1: Union[FreeParameterExpression, float], - angle_2: Union[FreeParameterExpression, float], - angle_3: Union[FreeParameterExpression, float], - qubit_count: Optional[int], + angle_1: FreeParameterExpression | float, + angle_2: FreeParameterExpression | float, + angle_3: FreeParameterExpression | float, + qubit_count: Optional[int], # noqa: UP007 ascii_symbols: Sequence[str], ): """Inits a `TripleAngledGate`. @@ -281,7 +281,7 @@ def __init__( ] @property - def parameters(self) -> list[Union[FreeParameterExpression, float]]: + def parameters(self) -> list[FreeParameterExpression | float]: """Returns the parameters associated with the object, either unbound free parameters or bound values. @@ -292,7 +292,7 @@ def parameters(self) -> list[Union[FreeParameterExpression, float]]: return self._parameters @property - def angle_1(self) -> Union[FreeParameterExpression, float]: + def angle_1(self) -> FreeParameterExpression | float: """Returns the first angle of the gate Returns: @@ -301,7 +301,7 @@ def angle_1(self) -> Union[FreeParameterExpression, float]: return self._parameters[0] @property - def angle_2(self) -> Union[FreeParameterExpression, float]: + def angle_2(self) -> FreeParameterExpression | float: """Returns the second angle of the gate Returns: @@ -310,7 +310,7 @@ def angle_2(self) -> Union[FreeParameterExpression, float]: return self._parameters[1] @property - def angle_3(self) -> Union[FreeParameterExpression, float]: + def angle_3(self) -> FreeParameterExpression | float: """Returns the third angle of the gate Returns: @@ -361,17 +361,17 @@ def __hash__(self): @singledispatch def _angles_equal( - angle_1: Union[FreeParameterExpression, float], angle_2: Union[FreeParameterExpression, float] + angle_1: FreeParameterExpression | float, angle_2: FreeParameterExpression | float ) -> bool: return isinstance(angle_2, float) and math.isclose(angle_1, angle_2) @_angles_equal.register -def _(angle_1: FreeParameterExpression, angle_2: FreeParameterExpression): +def _(angle_1: FreeParameterExpression, angle_2: FreeParameterExpression): # noqa: FURB118 return angle_1 == angle_2 -def angled_ascii_characters(gate: str, angle: Union[FreeParameterExpression, float]) -> str: +def angled_ascii_characters(gate: str, angle: FreeParameterExpression | float) -> str: """Generates a formatted ascii representation of an angled gate. Args: @@ -382,12 +382,12 @@ def angled_ascii_characters(gate: str, angle: Union[FreeParameterExpression, flo str: Returns the ascii representation for an angled gate. """ - return f'{gate}({angle:{".2f" if isinstance(angle, (float, Float)) else ""}})' + return f"{gate}({angle:{'.2f' if isinstance(angle, (float, Float)) else ''}})" def _multi_angled_ascii_characters( gate: str, - *angles: Union[FreeParameterExpression, float], + *angles: FreeParameterExpression | float, ) -> str: """Generates a formatted ascii representation of an angled gate. diff --git a/src/braket/circuits/ascii_circuit_diagram.py b/src/braket/circuits/ascii_circuit_diagram.py index accbce161..217668385 100644 --- a/src/braket/circuits/ascii_circuit_diagram.py +++ b/src/braket/circuits/ascii_circuit_diagram.py @@ -13,6 +13,6 @@ # Moving ascii_circuit_diagram.py into the text_diagram_builders folder in order # to group all classes that print circuits in a text format. -from braket.circuits.text_diagram_builders.ascii_circuit_diagram import ( # noqa: F401 - AsciiCircuitDiagram, +from braket.circuits.text_diagram_builders.ascii_circuit_diagram import ( + AsciiCircuitDiagram, # noqa: F401 ) diff --git a/src/braket/circuits/basis_state.py b/src/braket/circuits/basis_state.py index 86578fc89..68f313f89 100644 --- a/src/braket/circuits/basis_state.py +++ b/src/braket/circuits/basis_state.py @@ -7,7 +7,7 @@ class BasisState: - def __init__(self, state: BasisStateInput, size: Optional[int] = None): + def __init__(self, state: BasisStateInput, size: Optional[int] = None): # noqa: UP007 self.state = _as_tuple(state, size) @property diff --git a/src/braket/circuits/circuit.py b/src/braket/circuits/circuit.py index e3181a603..e9a80dbcd 100644 --- a/src/braket/circuits/circuit.py +++ b/src/braket/circuits/circuit.py @@ -16,7 +16,7 @@ from collections import Counter from collections.abc import Callable, Iterable from numbers import Number -from typing import Any, Optional, TypeVar, Union +from typing import Any, TypeVar import numpy as np import oqpy @@ -72,7 +72,7 @@ AddableTypes = TypeVar("AddableTypes", SubroutineReturn, SubroutineCallable) -class Circuit: +class Circuit: # noqa: PLR0904 """A representation of a quantum circuit that contains the instructions to be performed on a quantum device and the requested result types. @@ -100,17 +100,15 @@ def register_subroutine(cls, func: SubroutineCallable) -> None: ... for qubit in target: ... circ += Instruction(Gate.H(), qubit) ... return circ - ... >>> Circuit.register_subroutine(h_on_all) >>> circ = Circuit().h_on_all(range(2)) >>> for instr in circ.instructions: ... print(instr) - ... Instruction('operator': 'H', 'target': QubitSet(Qubit(0),)) Instruction('operator': 'H', 'target': QubitSet(Qubit(1),)) """ - def method_from_subroutine(self, *args, **kwargs) -> SubroutineReturn: + def method_from_subroutine(self, *args, **kwargs) -> SubroutineReturn: # noqa: ANN001 return self.add(func, *args, **kwargs) function_name = func.__name__ @@ -137,14 +135,13 @@ def __init__(self, addable: AddableTypes | None = None, *args, **kwargs): >>> @circuit.subroutine(register=True) >>> def bell_pair(target): ... return Circ().h(target[0]).cnot(target[0:2]) - ... - >>> circ = Circuit(bell_pair, [4,5]) - >>> circ = Circuit().bell_pair([4,5]) + >>> circ = Circuit(bell_pair, [4, 5]) + >>> circ = Circuit().bell_pair([4, 5]) """ self._moments: Moments = Moments() self._result_types: dict[ResultType] = {} - self._qubit_observable_mapping: dict[Union[int, Circuit._ALL_QUBITS], Observable] = {} + self._qubit_observable_mapping: dict[int | Circuit._ALL_QUBITS, Observable] = {} self._qubit_observable_target_mapping: dict[int, tuple[int]] = {} self._qubit_observable_set = set() self._parameters = set() @@ -338,13 +335,12 @@ def add_result_type( return self @staticmethod - def _extract_observable(result_type: ResultType) -> Optional[Observable]: + def _extract_observable(result_type: ResultType) -> Observable | None: if isinstance(result_type, ResultType.Probability): return Observable.Z() # computational basis - elif isinstance(result_type, ObservableResultType): + if isinstance(result_type, ObservableResultType): return result_type.observable - else: - return None + return None def _add_to_qubit_observable_mapping( self, observable: Observable, observable_target: QubitSet @@ -366,9 +362,9 @@ def _add_to_qubit_observable_mapping( current_observable == identity and new_observable != identity ) if ( - not add_observable - and current_observable != identity - and new_observable != identity + not add_observable # noqa: PLR1714 + and identity != current_observable + and identity != new_observable and current_observable != new_observable ): return self._encounter_noncommuting_observable() @@ -390,6 +386,7 @@ def _add_to_qubit_observable_mapping( if all_qubits_observable and all_qubits_observable != observable: return self._encounter_noncommuting_observable() self._qubit_observable_mapping[Circuit._ALL_QUBITS] = observable + return None @staticmethod def _tensor_product_index_dict( @@ -612,7 +609,7 @@ def add_circuit( """ if target_mapping and target is not None: raise TypeError("Only one of 'target_mapping' or 'target' can be supplied.") - elif target is not None: + if target is not None: keys = sorted(circuit.qubits) values = target target_mapping = dict(zip(keys, values)) @@ -678,7 +675,7 @@ def add_verbatim_box( """ if target_mapping and target is not None: raise TypeError("Only one of 'target_mapping' or 'target' can be supplied.") - elif target is not None: + if target is not None: keys = sorted(verbatim_circuit.qubits) values = target target_mapping = dict(zip(keys, values)) @@ -760,10 +757,10 @@ def measure(self, target_qubits: QubitSetInput) -> Circuit: def apply_gate_noise( self, - noise: Union[type[Noise], Iterable[type[Noise]]], - target_gates: Optional[Union[type[Gate], Iterable[type[Gate]]]] = None, - target_unitary: Optional[np.ndarray] = None, - target_qubits: Optional[QubitSetInput] = None, + noise: type[Noise] | Iterable[type[Noise]], + target_gates: type[Gate] | Iterable[type[Gate]] | None = None, + target_unitary: np.ndarray | None = None, + target_qubits: QubitSetInput | None = None, ) -> Circuit: """Apply `noise` to the circuit according to `target_gates`, `target_unitary` and `target_qubits`. @@ -903,13 +900,12 @@ def apply_gate_noise( if target_unitary is not None: return apply_noise_to_gates(self, noise, target_unitary, target_qubits) - else: - return apply_noise_to_gates(self, noise, target_gates, target_qubits) + return apply_noise_to_gates(self, noise, target_gates, target_qubits) def apply_initialization_noise( self, - noise: Union[type[Noise], Iterable[type[Noise]]], - target_qubits: Optional[QubitSetInput] = None, + noise: type[Noise] | Iterable[type[Noise]], + target_qubits: QubitSetInput | None = None, ) -> Circuit: """Apply `noise` at the beginning of the circuit for every qubit (default) or target_qubits`. @@ -939,18 +935,18 @@ def apply_initialization_noise( not the same as `noise.qubit_count`. Examples: - >>> circ = Circuit().x(0).y(1).z(0).x(1).cnot(0,1) + >>> circ = Circuit().x(0).y(1).z(0).x(1).cnot(0, 1) >>> print(circ) >>> noise = Noise.Depolarizing(probability=0.1) - >>> circ = Circuit().x(0).y(1).z(0).x(1).cnot(0,1) + >>> circ = Circuit().x(0).y(1).z(0).x(1).cnot(0, 1) >>> print(circ.apply_initialization_noise(noise)) - >>> circ = Circuit().x(0).y(1).z(0).x(1).cnot(0,1) - >>> print(circ.apply_initialization_noise(noise, target_qubits = 1)) + >>> circ = Circuit().x(0).y(1).z(0).x(1).cnot(0, 1) + >>> print(circ.apply_initialization_noise(noise, target_qubits=1)) >>> circ = Circuit() - >>> print(circ.apply_initialization_noise(noise, target_qubits = [0, 1])) + >>> print(circ.apply_initialization_noise(noise, target_qubits=[0, 1])) """ if (len(self.qubits) == 0) and (target_qubits is None): @@ -1047,14 +1043,14 @@ def _validate_parameter_value(val: Any) -> None: ValueError: If the value is not a Number """ if not isinstance(val, Number): - raise ValueError( + raise TypeError( f"Parameters can only be assigned numeric values. Invalid inputs: {val}" ) def apply_readout_noise( self, - noise: Union[type[Noise], Iterable[type[Noise]]], - target_qubits: Optional[QubitSetInput] = None, + noise: type[Noise] | Iterable[type[Noise]], + target_qubits: QubitSetInput | None = None, ) -> Circuit: """Apply `noise` right before measurement in every qubit (default) or target_qubits`. @@ -1084,18 +1080,18 @@ def apply_readout_noise( not the same as `noise.qubit_count`. Examples: - >>> circ = Circuit().x(0).y(1).z(0).x(1).cnot(0,1) + >>> circ = Circuit().x(0).y(1).z(0).x(1).cnot(0, 1) >>> print(circ) >>> noise = Noise.Depolarizing(probability=0.1) - >>> circ = Circuit().x(0).y(1).z(0).x(1).cnot(0,1) + >>> circ = Circuit().x(0).y(1).z(0).x(1).cnot(0, 1) >>> print(circ.apply_initialization_noise(noise)) - >>> circ = Circuit().x(0).y(1).z(0).x(1).cnot(0,1) - >>> print(circ.apply_initialization_noise(noise, target_qubits = 1)) + >>> circ = Circuit().x(0).y(1).z(0).x(1).cnot(0, 1) + >>> print(circ.apply_initialization_noise(noise, target_qubits=1)) >>> circ = Circuit() - >>> print(circ.apply_initialization_noise(noise, target_qubits = [0, 1])) + >>> print(circ.apply_initialization_noise(noise, target_qubits=[0, 1])) """ if (len(self.qubits) == 0) and (target_qubits is None): @@ -1160,12 +1156,11 @@ def add(self, addable: AddableTypes, *args, **kwargs) -> Circuit: >>> @circuit.subroutine() >>> def bell_pair(target): - ... return Circuit().h(target[0]).cnot(target[0: 2]) - ... - >>> circ = Circuit().add(bell_pair, [4,5]) + ... return Circuit().h(target[0]).cnot(target[0:2]) + >>> circ = Circuit().add(bell_pair, [4, 5]) """ - def _flatten(addable: Union[Iterable, AddableTypes]) -> AddableTypes: + def _flatten(addable: Iterable | AddableTypes) -> AddableTypes: if isinstance(addable, Iterable): for item in addable: yield from _flatten(item) @@ -1219,7 +1214,7 @@ def to_ir( ir_type: IRType = IRType.JAQCD, serialization_properties: SerializationProperties | None = None, gate_definitions: dict[tuple[Gate, QubitSet], PulseSequence] | None = None, - ) -> Union[OpenQasmProgram, JaqcdProgram]: + ) -> OpenQasmProgram | JaqcdProgram: """Converts the circuit into the canonical intermediate representation. If the circuit is sent over the wire, this method is called before it is sent. @@ -1244,7 +1239,7 @@ def to_ir( gate_definitions = gate_definitions or {} if ir_type == IRType.JAQCD: return self._to_jaqcd() - elif ir_type == IRType.OPENQASM: + if ir_type == IRType.OPENQASM: if serialization_properties and not isinstance( serialization_properties, OpenQASMSerializationProperties ): @@ -1256,13 +1251,10 @@ def to_ir( serialization_properties or OpenQASMSerializationProperties(), gate_definitions.copy(), ) - else: - raise ValueError(f"Supplied ir_type {ir_type} is not supported.") + raise ValueError(f"Supplied ir_type {ir_type} is not supported.") @staticmethod - def from_ir( - source: Union[str, OpenQasmProgram], inputs: Optional[dict[str, io_type]] = None - ) -> Circuit: + def from_ir(source: str | OpenQasmProgram, inputs: dict[str, io_type] | None = None) -> Circuit: """Converts an OpenQASM program to a Braket Circuit object. Args: @@ -1278,7 +1270,7 @@ def from_ir( inputs_copy.update(inputs) inputs = inputs_copy source = source.source - from braket.circuits.braket_program_context import BraketProgramContext + from braket.circuits.braket_program_context import BraketProgramContext # noqa: PLC0415 return Interpreter(BraketProgramContext()).build_circuit( source=source, @@ -1306,24 +1298,20 @@ def _to_openqasm( ) -> OpenQasmProgram: ir_instructions = self._create_openqasm_header(serialization_properties, gate_definitions) openqasm_ir_type = IRType.OPENQASM - ir_instructions.extend( - [ - instruction.to_ir( - ir_type=openqasm_ir_type, serialization_properties=serialization_properties - ) - for instruction in self.instructions - ] - ) + ir_instructions.extend([ + instruction.to_ir( + ir_type=openqasm_ir_type, serialization_properties=serialization_properties + ) + for instruction in self.instructions + ]) if self.result_types: - ir_instructions.extend( - [ - result_type.to_ir( - ir_type=openqasm_ir_type, serialization_properties=serialization_properties - ) - for result_type in self.result_types - ] - ) + ir_instructions.extend([ + result_type.to_ir( + ir_type=openqasm_ir_type, serialization_properties=serialization_properties + ) + for result_type in self.result_types + ]) # measure all the qubits if a measure instruction is not provided elif self._measure_targets is None: qubits = ( @@ -1443,7 +1431,7 @@ def _generate_frame_wf_defcal_declarations( def _get_frames_waveforms_from_instrs( self, gate_definitions: dict[tuple[Gate, QubitSet], PulseSequence] ) -> tuple[dict[str, Frame], dict[str, Waveform]]: - from braket.circuits.gates import PulseGate + from braket.circuits.gates import PulseGate # noqa: PLC0415 frames = {} waveforms = {} @@ -1507,11 +1495,11 @@ def _add_fixed_argument_calibrations( ) if free_parameter_number == 0: continue - elif free_parameter_number < len(gate.parameters): + if free_parameter_number < len(gate.parameters): raise NotImplementedError( "Calibrations with a partial number of fixed parameters are not supported." ) - elif any( + if any( isinstance(p, FreeParameterExpression) for p in instruction.operator.parameters ): raise NotImplementedError( @@ -1521,12 +1509,10 @@ def _add_fixed_argument_calibrations( type(instruction.operator)(*instruction.operator.parameters), instruction.target, ) - additional_calibrations[bound_key] = calibration( - **{ - p.name if isinstance(p, FreeParameterExpression) else p: v - for p, v in zip(gate.parameters, instruction.operator.parameters) - } - ) + additional_calibrations[bound_key] = calibration(**{ + p.name if isinstance(p, FreeParameterExpression) else p: v + for p, v in zip(gate.parameters, instruction.operator.parameters) + }) return additional_calibrations def to_unitary(self) -> np.ndarray: @@ -1559,8 +1545,7 @@ def to_unitary(self) -> np.ndarray: """ if qubits := self.qubits: return calculate_unitary_big_endian(self.instructions, qubits) - else: - return np.zeros(0, dtype=complex) + return np.zeros(0, dtype=complex) @property def qubits_frozen(self) -> bool: @@ -1611,11 +1596,7 @@ def __add__(self, addable: AddableTypes) -> Circuit: def __repr__(self) -> str: if not self.result_types: return f"Circuit('instructions': {self.instructions})" - else: - return ( - f"Circuit('instructions': {self.instructions}" - + f", 'result_types': {self.result_types})" - ) + return f"Circuit('instructions': {self.instructions}, 'result_types': {self.result_types})" def __str__(self): return self.diagram() @@ -1661,11 +1642,9 @@ def subroutine(register: bool = False) -> Callable: >>> @circuit.subroutine(register=True) >>> def bell_circuit(): ... return Circuit().h(0).cnot(0, 1) - ... >>> circ = Circuit().bell_circuit() >>> for instr in circ.instructions: ... print(instr) - ... Instruction('operator': 'H', 'target': QubitSet(Qubit(0),)) Instruction('operator': 'H', 'target': QubitSet(Qubit(1),)) """ diff --git a/src/braket/circuits/circuit_helpers.py b/src/braket/circuits/circuit_helpers.py index 1a50c4c83..933a62fda 100644 --- a/src/braket/circuits/circuit_helpers.py +++ b/src/braket/circuits/circuit_helpers.py @@ -35,13 +35,13 @@ def validate_circuit_and_shots(circuit: Circuit, shots: int) -> None: raise ValueError( "No result types specified for circuit and shots=0. See `braket.circuits.result_types`" ) - elif shots and circuit.result_types: + if shots and circuit.result_types: if not circuit.observables_simultaneously_measurable: raise ValueError("Observables cannot be sampled simultaneously") for rt in circuit.result_types: if isinstance(rt, (ResultType.Amplitude, ResultType.StateVector)): - raise ValueError("StateVector or Amplitude cannot be specified when shots>0") - elif isinstance(rt, ResultType.Probability): + raise ValueError("StateVector or Amplitude cannot be specified when shots>0") # noqa: TRY004 + if isinstance(rt, ResultType.Probability): num_qubits = len(rt.target) or circuit.qubit_count if num_qubits > 40: raise ValueError("Probability target must be less than or equal to 40 qubits.") diff --git a/src/braket/circuits/compiler_directive.py b/src/braket/circuits/compiler_directive.py index ad2c701c6..bd961c3ee 100644 --- a/src/braket/circuits/compiler_directive.py +++ b/src/braket/circuits/compiler_directive.py @@ -72,10 +72,9 @@ def to_ir( """ if ir_type == IRType.JAQCD: return self._to_jaqcd() - elif ir_type == IRType.OPENQASM: + if ir_type == IRType.OPENQASM: return self._to_openqasm() - else: - raise ValueError(f"Supplied ir_type {ir_type} is not supported.") + raise ValueError(f"Supplied ir_type {ir_type} is not supported.") def _to_jaqcd(self) -> Any: """Returns the JAQCD representation of the compiler directive.""" diff --git a/src/braket/circuits/gate.py b/src/braket/circuits/gate.py index 453b121fd..421e3614a 100644 --- a/src/braket/circuits/gate.py +++ b/src/braket/circuits/gate.py @@ -15,7 +15,7 @@ from collections.abc import Sequence from itertools import groupby -from typing import Any, Optional +from typing import Any from braket.circuits.basis_state import BasisState, BasisStateInput from braket.circuits.quantum_operator import QuantumOperator @@ -33,7 +33,7 @@ class Gate(QuantumOperator): the metadata that defines what a gate is and what it does. """ - def __init__(self, qubit_count: Optional[int], ascii_symbols: Sequence[str]): + def __init__(self, qubit_count: int | None, ascii_symbols: Sequence[str]): """Initializes a `Gate`. Args: @@ -49,12 +49,12 @@ def __init__(self, qubit_count: Optional[int], ascii_symbols: Sequence[str]): ValueError: `qubit_count` is less than 1, `ascii_symbols` are `None`, or `ascii_symbols` length != `qubit_count` """ - # todo: implement ascii symbols for control modifier + # TODO: implement ascii symbols for control modifier super().__init__(qubit_count=qubit_count, ascii_symbols=ascii_symbols) @property def _qasm_name(self) -> NotImplementedError: - raise NotImplementedError() + raise NotImplementedError def adjoint(self) -> list[Gate]: """Returns a list of gates that implement the adjoint of this gate. @@ -70,10 +70,10 @@ def to_ir( self, target: QubitSet, ir_type: IRType = IRType.JAQCD, - serialization_properties: Optional[SerializationProperties] = None, + serialization_properties: SerializationProperties | None = None, *, - control: Optional[QubitSet] = None, - control_state: Optional[BasisStateInput] = None, + control: QubitSet | None = None, + control_state: BasisStateInput | None = None, power: float = 1, ) -> Any: r"""Returns IR object of quantum operator and target @@ -110,7 +110,7 @@ def to_ir( if control or power != 1: raise ValueError("Gate modifiers are not supported with Jaqcd.") return self._to_jaqcd(target) - elif ir_type == IRType.OPENQASM: + if ir_type == IRType.OPENQASM: if serialization_properties and not isinstance( serialization_properties, OpenQASMSerializationProperties ): @@ -125,8 +125,7 @@ def to_ir( control_state=control_state, power=power, ) - else: - raise ValueError(f"Supplied ir_type {ir_type} is not supported.") + raise ValueError(f"Supplied ir_type {ir_type} is not supported.") def _to_jaqcd(self, target: QubitSet) -> Any: """Returns the JAQCD representation of the gate. @@ -144,8 +143,8 @@ def _to_openqasm( target: QubitSet, serialization_properties: OpenQASMSerializationProperties, *, - control: Optional[QubitSet] = None, - control_state: Optional[BasisStateInput] = None, + control: QubitSet | None = None, + control_state: BasisStateInput | None = None, power: float = 1, ) -> str: """Returns the OpenQASM string representation of the gate. diff --git a/src/braket/circuits/gate_calibrations.py b/src/braket/circuits/gate_calibrations.py index 69ff66254..2d855cabf 100644 --- a/src/braket/circuits/gate_calibrations.py +++ b/src/braket/circuits/gate_calibrations.py @@ -27,10 +27,10 @@ class GateCalibrations: - """An object containing gate calibration data. The data represents the mapping on a particular gate - on a set of qubits to its calibration to be used by a quantum device. This is represented by a dictionary - with keys of `Tuple(Gate, QubitSet)` mapped to a `PulseSequence`. - """ # noqa: E501 + """An object containing gate calibration data. The data represents the mapping on a particular + gate on a set of qubits to its calibration to be used by a quantum device. This is represented + by a dictionary with keys of `Tuple(Gate, QubitSet)` mapped to a `PulseSequence`. + """ def __init__( self, @@ -119,8 +119,8 @@ def to_ir(self, calibration_key: tuple[Gate, QubitSet] | None = None) -> str: """Returns the defcal representation for the `GateCalibrations` object. Args: - calibration_key (tuple[Gate, QubitSet] | None): An optional key to get a specific defcal. - Default: None + calibration_key (tuple[Gate, QubitSet] | None): An optional key to get a + specific defcal. Default: None Raises: ValueError: Key does not exist in the `GateCalibrations` object. @@ -128,9 +128,9 @@ def to_ir(self, calibration_key: tuple[Gate, QubitSet] | None = None) -> str: Returns: str: the defcal string for the object. - """ # noqa: E501 + """ if calibration_key is not None: - if calibration_key not in self.pulse_sequences.keys(): + if calibration_key not in self.pulse_sequences: raise ValueError( f"The key {calibration_key} does not exist in this GateCalibrations object." ) @@ -139,26 +139,22 @@ def to_ir(self, calibration_key: tuple[Gate, QubitSet] | None = None) -> str: .to_ir() .replace("cal", self._def_cal_gate(calibration_key), 1) ) - else: - defcal = "\n".join( - v.to_ir().replace("cal", self._def_cal_gate(k), 1) - for (k, v) in self.pulse_sequences.items() - ) - return defcal + return "\n".join( + v.to_ir().replace("cal", self._def_cal_gate(k), 1) + for (k, v) in self.pulse_sequences.items() + ) def _def_cal_gate(self, gate_key: tuple[Gate, QubitSet]) -> str: - return " ".join( - [ - "defcal", - gate_key[0].to_ir( - target=gate_key[1], - serialization_properties=OpenQASMSerializationProperties( - QubitReferenceType.PHYSICAL - ), - ir_type=IRType.OPENQASM, - )[:-1], - ] - ) + return " ".join([ + "defcal", + gate_key[0].to_ir( + target=gate_key[1], + serialization_properties=OpenQASMSerializationProperties( + QubitReferenceType.PHYSICAL + ), + ir_type=IRType.OPENQASM, + )[:-1], + ]) def __eq__(self, other: GateCalibrations): return isinstance(other, GateCalibrations) and other.pulse_sequences == self.pulse_sequences diff --git a/src/braket/circuits/gates.py b/src/braket/circuits/gates.py index ee5ea684b..b5c6d98f7 100644 --- a/src/braket/circuits/gates.py +++ b/src/braket/circuits/gates.py @@ -15,7 +15,7 @@ from collections.abc import Iterable from copy import deepcopy -from typing import Any, Optional, Union +from typing import Any import numpy as np from oqpy import Program @@ -95,8 +95,8 @@ def fixed_qubit_count() -> int: def h( target: QubitSetInput, *, - control: Optional[QubitSetInput] = None, - control_state: Optional[BasisStateInput] = None, + control: QubitSetInput | None = None, + control_state: BasisStateInput | None = None, power: float = 1, ) -> Iterable[Instruction]: r"""Hadamard gate. @@ -173,8 +173,8 @@ def fixed_qubit_count() -> int: def i( target: QubitSetInput, *, - control: Optional[QubitSetInput] = None, - control_state: Optional[BasisStateInput] = None, + control: QubitSetInput | None = None, + control_state: BasisStateInput | None = None, power: float = 1, ) -> Iterable[Instruction]: r"""Identity gate. @@ -231,7 +231,7 @@ class GPhase(AngledGate): ValueError: If `angle` is not present """ - def __init__(self, angle: Union[FreeParameterExpression, float]): + def __init__(self, angle: FreeParameterExpression | float): # Avoid parent constructor because _qubit_count must be zero self._qubit_count = self.fixed_qubit_count() self._ascii_symbols = [] @@ -263,10 +263,10 @@ def fixed_qubit_count() -> int: @staticmethod @circuit.subroutine(register=True) def gphase( - angle: Union[FreeParameterExpression, float], + angle: FreeParameterExpression | float, *, - control: Optional[QubitSetInput] = None, - control_state: Optional[BasisStateInput] = None, + control: QubitSetInput | None = None, + control_state: BasisStateInput | None = None, power: float = 1, ) -> Instruction | Iterable[Instruction]: r"""Global phase gate. @@ -369,8 +369,8 @@ def fixed_qubit_count() -> int: def x( target: QubitSetInput, *, - control: Optional[QubitSetInput] = None, - control_state: Optional[BasisStateInput] = None, + control: QubitSetInput | None = None, + control_state: BasisStateInput | None = None, power: float = 1, ) -> Iterable[Instruction]: r"""Pauli-X gate. @@ -449,8 +449,8 @@ def fixed_qubit_count() -> int: def y( target: QubitSetInput, *, - control: Optional[QubitSetInput] = None, - control_state: Optional[BasisStateInput] = None, + control: QubitSetInput | None = None, + control_state: BasisStateInput | None = None, power: float = 1, ) -> Iterable[Instruction]: r"""Pauli-Y gate. @@ -529,8 +529,8 @@ def fixed_qubit_count() -> int: def z( target: QubitSetInput, *, - control: Optional[QubitSetInput] = None, - control_state: Optional[BasisStateInput] = None, + control: QubitSetInput | None = None, + control_state: BasisStateInput | None = None, power: float = 1, ) -> Iterable[Instruction]: r"""Pauli-Z gate. @@ -607,8 +607,8 @@ def fixed_qubit_count() -> int: def s( target: QubitSetInput, *, - control: Optional[QubitSetInput] = None, - control_state: Optional[BasisStateInput] = None, + control: QubitSetInput | None = None, + control_state: BasisStateInput | None = None, power: float = 1, ) -> Iterable[Instruction]: r"""S gate. @@ -685,8 +685,8 @@ def fixed_qubit_count() -> int: def si( target: QubitSetInput, *, - control: Optional[QubitSetInput] = None, - control_state: Optional[BasisStateInput] = None, + control: QubitSetInput | None = None, + control_state: BasisStateInput | None = None, power: float = 1, ) -> Iterable[Instruction]: r"""Conjugate transpose of S gate. @@ -763,8 +763,8 @@ def fixed_qubit_count() -> int: def t( target: QubitSetInput, *, - control: Optional[QubitSetInput] = None, - control_state: Optional[BasisStateInput] = None, + control: QubitSetInput | None = None, + control_state: BasisStateInput | None = None, power: float = 1, ) -> Iterable[Instruction]: r"""T gate. @@ -841,8 +841,8 @@ def fixed_qubit_count() -> int: def ti( target: QubitSetInput, *, - control: Optional[QubitSetInput] = None, - control_state: Optional[BasisStateInput] = None, + control: QubitSetInput | None = None, + control_state: BasisStateInput | None = None, power: float = 1, ) -> Iterable[Instruction]: r"""Conjugate transpose of T gate. @@ -919,8 +919,8 @@ def fixed_qubit_count() -> int: def v( target: QubitSetInput, *, - control: Optional[QubitSetInput] = None, - control_state: Optional[BasisStateInput] = None, + control: QubitSetInput | None = None, + control_state: BasisStateInput | None = None, power: float = 1, ) -> Iterable[Instruction]: r"""Square root of X gate (V gate). @@ -997,8 +997,8 @@ def fixed_qubit_count() -> int: def vi( target: QubitSetInput, *, - control: Optional[QubitSetInput] = None, - control_state: Optional[BasisStateInput] = None, + control: QubitSetInput | None = None, + control_state: BasisStateInput | None = None, power: float = 1, ) -> Iterable[Instruction]: r"""Conjugate transpose of square root of X gate (conjugate transpose of V). @@ -1056,7 +1056,7 @@ class Rx(AngledGate): angle (Union[FreeParameterExpression, float]): angle in radians. """ - def __init__(self, angle: Union[FreeParameterExpression, float]): + def __init__(self, angle: FreeParameterExpression | float): super().__init__( angle=angle, qubit_count=None, @@ -1091,10 +1091,10 @@ def bind_values(self, **kwargs) -> AngledGate: @circuit.subroutine(register=True) def rx( target: QubitSetInput, - angle: Union[FreeParameterExpression, float], + angle: FreeParameterExpression | float, *, - control: Optional[QubitSetInput] = None, - control_state: Optional[BasisStateInput] = None, + control: QubitSetInput | None = None, + control_state: BasisStateInput | None = None, power: float = 1, ) -> Iterable[Instruction]: r"""X-axis rotation gate. @@ -1149,7 +1149,7 @@ class Ry(AngledGate): angle (Union[FreeParameterExpression, float]): angle in radians. """ - def __init__(self, angle: Union[FreeParameterExpression, float]): + def __init__(self, angle: FreeParameterExpression | float): super().__init__( angle=angle, qubit_count=None, @@ -1184,10 +1184,10 @@ def bind_values(self, **kwargs) -> AngledGate: @circuit.subroutine(register=True) def ry( target: QubitSetInput, - angle: Union[FreeParameterExpression, float], + angle: FreeParameterExpression | float, *, - control: Optional[QubitSetInput] = None, - control_state: Optional[BasisStateInput] = None, + control: QubitSetInput | None = None, + control_state: BasisStateInput | None = None, power: float = 1, ) -> Iterable[Instruction]: r"""Y-axis rotation gate. @@ -1243,7 +1243,7 @@ class Rz(AngledGate): angle (Union[FreeParameterExpression, float]): angle in radians. """ - def __init__(self, angle: Union[FreeParameterExpression, float]): + def __init__(self, angle: FreeParameterExpression | float): super().__init__( angle=angle, qubit_count=None, @@ -1273,10 +1273,10 @@ def fixed_qubit_count() -> int: @circuit.subroutine(register=True) def rz( target: QubitSetInput, - angle: Union[FreeParameterExpression, float], + angle: FreeParameterExpression | float, *, - control: Optional[QubitSetInput] = None, - control_state: Optional[BasisStateInput] = None, + control: QubitSetInput | None = None, + control_state: BasisStateInput | None = None, power: float = 1, ) -> Iterable[Instruction]: r"""Z-axis rotation gate. @@ -1331,7 +1331,7 @@ class PhaseShift(AngledGate): angle (Union[FreeParameterExpression, float]): angle in radians. """ - def __init__(self, angle: Union[FreeParameterExpression, float]): + def __init__(self, angle: FreeParameterExpression | float): super().__init__( angle=angle, qubit_count=None, @@ -1359,10 +1359,10 @@ def fixed_qubit_count() -> int: @circuit.subroutine(register=True) def phaseshift( target: QubitSetInput, - angle: Union[FreeParameterExpression, float], + angle: FreeParameterExpression | float, *, - control: Optional[QubitSetInput] = None, - control_state: Optional[BasisStateInput] = None, + control: QubitSetInput | None = None, + control_state: BasisStateInput | None = None, power: float = 1, ) -> Iterable[Instruction]: r"""Phase shift gate. @@ -1425,9 +1425,9 @@ class U(TripleAngledGate): def __init__( self, - angle_1: Union[FreeParameterExpression, float], - angle_2: Union[FreeParameterExpression, float], - angle_3: Union[FreeParameterExpression, float], + angle_1: FreeParameterExpression | float, + angle_2: FreeParameterExpression | float, + angle_3: FreeParameterExpression | float, ): super().__init__( angle_1=angle_1, @@ -1447,21 +1447,19 @@ def to_matrix(self) -> np.ndarray: Returns: np.ndarray: The matrix representation of this gate. """ - _theta = self.angle_1 - _phi = self.angle_2 - _lambda = self.angle_3 - return np.array( + _theta = self.angle_1 # noqa: RUF052 + _phi = self.angle_2 # noqa: RUF052 + _lambda = self.angle_3 # noqa: RUF052 + return np.array([ [ - [ - np.cos(_theta / 2), - -np.exp(1j * _lambda) * np.sin(_theta / 2), - ], - [ - np.exp(1j * _phi) * np.sin(_theta / 2), - np.exp(1j * (_phi + _lambda)) * np.cos(_theta / 2), - ], - ] - ) + np.cos(_theta / 2), + -np.exp(1j * _lambda) * np.sin(_theta / 2), + ], + [ + np.exp(1j * _phi) * np.sin(_theta / 2), + np.exp(1j * (_phi + _lambda)) * np.cos(_theta / 2), + ], + ]) def adjoint(self) -> list[Gate]: return [U(-self.angle_1, -self.angle_3, -self.angle_2)] @@ -1477,12 +1475,12 @@ def bind_values(self, **kwargs) -> TripleAngledGate: @circuit.subroutine(register=True) def u( target: QubitSetInput, - angle_1: Union[FreeParameterExpression, float], - angle_2: Union[FreeParameterExpression, float], - angle_3: Union[FreeParameterExpression, float], + angle_1: FreeParameterExpression | float, + angle_2: FreeParameterExpression | float, + angle_3: FreeParameterExpression | float, *, - control: Optional[QubitSetInput] = None, - control_state: Optional[BasisStateInput] = None, + control: QubitSetInput | None = None, + control_state: BasisStateInput | None = None, power: float = 1, ) -> Iterable[Instruction]: r"""Generalized single-qubit rotation gate. @@ -1658,8 +1656,8 @@ def swap( target1: QubitInput, target2: QubitInput, *, - control: Optional[QubitSetInput] = None, - control_state: Optional[BasisStateInput] = None, + control: QubitSetInput | None = None, + control_state: BasisStateInput | None = None, power: float = 1, ) -> Instruction: r"""Swap gate. @@ -1750,8 +1748,8 @@ def iswap( target1: QubitInput, target2: QubitInput, *, - control: Optional[QubitSetInput] = None, - control_state: Optional[BasisStateInput] = None, + control: QubitSetInput | None = None, + control_state: BasisStateInput | None = None, power: float = 1, ) -> Instruction: r"""ISwap gate. @@ -1811,7 +1809,7 @@ class PSwap(AngledGate): angle (Union[FreeParameterExpression, float]): angle in radians. """ - def __init__(self, angle: Union[FreeParameterExpression, float]): + def __init__(self, angle: FreeParameterExpression | float): super().__init__( angle=angle, qubit_count=None, @@ -1851,10 +1849,10 @@ def fixed_qubit_count() -> int: def pswap( target1: QubitInput, target2: QubitInput, - angle: Union[FreeParameterExpression, float], + angle: FreeParameterExpression | float, *, - control: Optional[QubitSetInput] = None, - control_state: Optional[BasisStateInput] = None, + control: QubitSetInput | None = None, + control_state: BasisStateInput | None = None, power: float = 1, ) -> Instruction: r"""PSwap gate. @@ -1918,7 +1916,7 @@ class XY(AngledGate): angle (Union[FreeParameterExpression, float]): angle in radians. """ - def __init__(self, angle: Union[FreeParameterExpression, float]): + def __init__(self, angle: FreeParameterExpression | float): super().__init__( angle=angle, qubit_count=None, @@ -1965,10 +1963,10 @@ def fixed_qubit_count() -> int: def xy( target1: QubitInput, target2: QubitInput, - angle: Union[FreeParameterExpression, float], + angle: FreeParameterExpression | float, *, - control: Optional[QubitSetInput] = None, - control_state: Optional[BasisStateInput] = None, + control: QubitSetInput | None = None, + control_state: BasisStateInput | None = None, power: float = 1, ) -> Instruction: r"""XY gate. @@ -2029,7 +2027,7 @@ class CPhaseShift(AngledGate): angle (Union[FreeParameterExpression, float]): angle in radians. """ - def __init__(self, angle: Union[FreeParameterExpression, float]): + def __init__(self, angle: FreeParameterExpression | float): super().__init__( angle=angle, qubit_count=None, @@ -2058,7 +2056,7 @@ def fixed_qubit_count() -> int: def cphaseshift( control: QubitSetInput, target: QubitInput, - angle: Union[FreeParameterExpression, float], + angle: FreeParameterExpression | float, power: float = 1, ) -> Instruction: r"""Controlled phase shift gate. @@ -2114,7 +2112,7 @@ class CPhaseShift00(AngledGate): angle (Union[FreeParameterExpression, float]): angle in radians. """ - def __init__(self, angle: Union[FreeParameterExpression, float]): + def __init__(self, angle: FreeParameterExpression | float): super().__init__( angle=angle, qubit_count=None, @@ -2143,7 +2141,7 @@ def fixed_qubit_count() -> int: def cphaseshift00( control: QubitSetInput, target: QubitInput, - angle: Union[FreeParameterExpression, float], + angle: FreeParameterExpression | float, power: float = 1, ) -> Instruction: r"""Controlled phase shift gate for phasing the \|00> state. @@ -2199,7 +2197,7 @@ class CPhaseShift01(AngledGate): angle (Union[FreeParameterExpression, float]): angle in radians. """ - def __init__(self, angle: Union[FreeParameterExpression, float]): + def __init__(self, angle: FreeParameterExpression | float): super().__init__( angle=angle, qubit_count=None, @@ -2228,7 +2226,7 @@ def fixed_qubit_count() -> int: def cphaseshift01( control: QubitSetInput, target: QubitInput, - angle: Union[FreeParameterExpression, float], + angle: FreeParameterExpression | float, power: float = 1, ) -> Instruction: r"""Controlled phase shift gate for phasing the \|01> state. @@ -2284,7 +2282,7 @@ class CPhaseShift10(AngledGate): angle (Union[FreeParameterExpression, float]): angle in radians. """ - def __init__(self, angle: Union[FreeParameterExpression, float]): + def __init__(self, angle: FreeParameterExpression | float): super().__init__( angle=angle, qubit_count=None, @@ -2313,7 +2311,7 @@ def fixed_qubit_count() -> int: def cphaseshift10( control: QubitSetInput, target: QubitInput, - angle: Union[FreeParameterExpression, float], + angle: FreeParameterExpression | float, power: float = 1, ) -> Instruction: r"""Controlled phase shift gate for phasing the \\|10> state. @@ -2622,8 +2620,8 @@ def ecr( target1: QubitInput, target2: QubitInput, *, - control: Optional[QubitSetInput] = None, - control_state: Optional[BasisStateInput] = None, + control: QubitSetInput | None = None, + control_state: BasisStateInput | None = None, power: float = 1, ) -> Instruction: r"""An echoed RZX(pi/2) gate (ECR gate). @@ -2685,7 +2683,7 @@ class XX(AngledGate): angle (Union[FreeParameterExpression, float]): angle in radians. """ - def __init__(self, angle: Union[FreeParameterExpression, float]): + def __init__(self, angle: FreeParameterExpression | float): super().__init__( angle=angle, qubit_count=None, @@ -2732,10 +2730,10 @@ def fixed_qubit_count() -> int: def xx( target1: QubitInput, target2: QubitInput, - angle: Union[FreeParameterExpression, float], + angle: FreeParameterExpression | float, *, - control: Optional[QubitSetInput] = None, - control_state: Optional[BasisStateInput] = None, + control: QubitSetInput | None = None, + control_state: BasisStateInput | None = None, power: float = 1, ) -> Instruction: r"""Ising XX coupling gate. @@ -2798,7 +2796,7 @@ class YY(AngledGate): angle (Union[FreeParameterExpression, float]): angle in radians. """ - def __init__(self, angle: Union[FreeParameterExpression, float]): + def __init__(self, angle: FreeParameterExpression | float): super().__init__( angle=angle, qubit_count=None, @@ -2845,10 +2843,10 @@ def fixed_qubit_count() -> int: def yy( target1: QubitInput, target2: QubitInput, - angle: Union[FreeParameterExpression, float], + angle: FreeParameterExpression | float, *, - control: Optional[QubitSetInput] = None, - control_state: Optional[BasisStateInput] = None, + control: QubitSetInput | None = None, + control_state: BasisStateInput | None = None, power: float = 1, ) -> Instruction: r"""Ising YY coupling gate. @@ -2911,7 +2909,7 @@ class ZZ(AngledGate): angle (Union[FreeParameterExpression, float]): angle in radians. """ - def __init__(self, angle: Union[FreeParameterExpression, float]): + def __init__(self, angle: FreeParameterExpression | float): super().__init__( angle=angle, qubit_count=None, @@ -2951,10 +2949,10 @@ def fixed_qubit_count() -> int: def zz( target1: QubitInput, target2: QubitInput, - angle: Union[FreeParameterExpression, float], + angle: FreeParameterExpression | float, *, - control: Optional[QubitSetInput] = None, - control_state: Optional[BasisStateInput] = None, + control: QubitSetInput | None = None, + control_state: BasisStateInput | None = None, power: float = 1, ) -> Instruction: r"""Ising ZZ coupling gate. @@ -3058,8 +3056,8 @@ def ccnot( control2: QubitInput, target: QubitInput, *, - control: Optional[QubitSetInput] = None, - control_state: Optional[BasisStateInput] = None, + control: QubitSetInput | None = None, + control_state: BasisStateInput | None = None, power: float = 1, ) -> Instruction: r"""CCNOT gate or Toffoli gate. @@ -3222,7 +3220,7 @@ class GPi(AngledGate): angle (Union[FreeParameterExpression, float]): angle in radians. """ - def __init__(self, angle: Union[FreeParameterExpression, float]): + def __init__(self, angle: FreeParameterExpression | float): super().__init__( angle=angle, qubit_count=None, @@ -3234,12 +3232,10 @@ def _qasm_name(self) -> str: return "gpi" def to_matrix(self) -> np.ndarray: - return np.array( - [ - [0, np.exp(-1j * self.angle)], - [np.exp(1j * self.angle), 0], - ] - ) + return np.array([ + [0, np.exp(-1j * self.angle)], + [np.exp(1j * self.angle), 0], + ]) def adjoint(self) -> list[Gate]: return [GPi(self.angle)] @@ -3255,10 +3251,10 @@ def bind_values(self, **kwargs) -> GPi: @circuit.subroutine(register=True) def gpi( target: QubitSetInput, - angle: Union[FreeParameterExpression, float], + angle: FreeParameterExpression | float, *, - control: Optional[QubitSetInput] = None, - control_state: Optional[BasisStateInput] = None, + control: QubitSetInput | None = None, + control_state: BasisStateInput | None = None, power: float = 1, ) -> Iterable[Instruction]: r"""IonQ GPi gate. @@ -3318,8 +3314,8 @@ class PRx(DoubleAngledGate): def __init__( self, - angle_1: Union[FreeParameterExpression, float], - angle_2: Union[FreeParameterExpression, float], + angle_1: FreeParameterExpression | float, + angle_2: FreeParameterExpression | float, ): super().__init__( angle_1=angle_1, @@ -3340,18 +3336,16 @@ def to_matrix(self) -> np.ndarray: """ theta = self.angle_1 phi = self.angle_2 - return np.array( + return np.array([ [ - [ - np.cos(theta / 2), - -1j * np.exp(-1j * phi) * np.sin(theta / 2), - ], - [ - -1j * np.exp(1j * phi) * np.sin(theta / 2), - np.cos(theta / 2), - ], - ] - ) + np.cos(theta / 2), + -1j * np.exp(-1j * phi) * np.sin(theta / 2), + ], + [ + -1j * np.exp(1j * phi) * np.sin(theta / 2), + np.cos(theta / 2), + ], + ]) def adjoint(self) -> list[Gate]: return [PRx(-self.angle_1, self.angle_2)] @@ -3367,11 +3361,11 @@ def bind_values(self, **kwargs) -> PRx: @circuit.subroutine(register=True) def prx( target: QubitSetInput, - angle_1: Union[FreeParameterExpression, float], - angle_2: Union[FreeParameterExpression, float], + angle_1: FreeParameterExpression | float, + angle_2: FreeParameterExpression | float, *, - control: Optional[QubitSetInput] = None, - control_state: Optional[BasisStateInput] = None, + control: QubitSetInput | None = None, + control_state: BasisStateInput | None = None, power: float = 1, ) -> Iterable[Instruction]: r"""PhaseRx gate. @@ -3431,7 +3425,7 @@ class GPi2(AngledGate): angle (Union[FreeParameterExpression, float]): angle in radians. """ - def __init__(self, angle: Union[FreeParameterExpression, float]): + def __init__(self, angle: FreeParameterExpression | float): super().__init__( angle=angle, qubit_count=None, @@ -3443,12 +3437,10 @@ def _qasm_name(self) -> str: return "gpi2" def to_matrix(self) -> np.ndarray: - return np.array( - [ - [1, -1j * np.exp(-1j * self.angle)], - [-1j * np.exp(1j * self.angle), 1], - ] - ) / np.sqrt(2) + return np.array([ + [1, -1j * np.exp(-1j * self.angle)], + [-1j * np.exp(1j * self.angle), 1], + ]) / np.sqrt(2) def adjoint(self) -> list[Gate]: return [GPi2(self.angle + np.pi)] @@ -3464,10 +3456,10 @@ def bind_values(self, **kwargs) -> GPi2: @circuit.subroutine(register=True) def gpi2( target: QubitSetInput, - angle: Union[FreeParameterExpression, float], + angle: FreeParameterExpression | float, *, - control: Optional[QubitSetInput] = None, - control_state: Optional[BasisStateInput] = None, + control: QubitSetInput | None = None, + control_state: BasisStateInput | None = None, power: float = 1, ) -> Iterable[Instruction]: r"""IonQ GPi2 gate. @@ -3533,9 +3525,9 @@ class MS(TripleAngledGate): def __init__( self, - angle_1: Union[FreeParameterExpression, float], - angle_2: Union[FreeParameterExpression, float], - angle_3: Union[FreeParameterExpression, float] = np.pi / 2, + angle_1: FreeParameterExpression | float, + angle_2: FreeParameterExpression | float, + angle_3: FreeParameterExpression | float = np.pi / 2, ): super().__init__( angle_1=angle_1, @@ -3550,34 +3542,32 @@ def _qasm_name(self) -> str: return "ms" def to_matrix(self) -> np.ndarray: - return np.array( + return np.array([ [ - [ - np.cos(self.angle_3 / 2), - 0, - 0, - -1j * np.exp(-1j * (self.angle_1 + self.angle_2)) * np.sin(self.angle_3 / 2), - ], - [ - 0, - np.cos(self.angle_3 / 2), - -1j * np.exp(-1j * (self.angle_1 - self.angle_2)) * np.sin(self.angle_3 / 2), - 0, - ], - [ - 0, - -1j * np.exp(1j * (self.angle_1 - self.angle_2)) * np.sin(self.angle_3 / 2), - np.cos(self.angle_3 / 2), - 0, - ], - [ - -1j * np.exp(1j * (self.angle_1 + self.angle_2)) * np.sin(self.angle_3 / 2), - 0, - 0, - np.cos(self.angle_3 / 2), - ], - ] - ) + np.cos(self.angle_3 / 2), + 0, + 0, + -1j * np.exp(-1j * (self.angle_1 + self.angle_2)) * np.sin(self.angle_3 / 2), + ], + [ + 0, + np.cos(self.angle_3 / 2), + -1j * np.exp(-1j * (self.angle_1 - self.angle_2)) * np.sin(self.angle_3 / 2), + 0, + ], + [ + 0, + -1j * np.exp(1j * (self.angle_1 - self.angle_2)) * np.sin(self.angle_3 / 2), + np.cos(self.angle_3 / 2), + 0, + ], + [ + -1j * np.exp(1j * (self.angle_1 + self.angle_2)) * np.sin(self.angle_3 / 2), + 0, + 0, + np.cos(self.angle_3 / 2), + ], + ]) def adjoint(self) -> list[Gate]: return [MS(self.angle_1 + np.pi, self.angle_2, self.angle_3)] @@ -3594,12 +3584,12 @@ def bind_values(self, **kwargs) -> MS: def ms( target1: QubitInput, target2: QubitInput, - angle_1: Union[FreeParameterExpression, float], - angle_2: Union[FreeParameterExpression, float], - angle_3: Union[FreeParameterExpression, float] = np.pi / 2, + angle_1: FreeParameterExpression | float, + angle_2: FreeParameterExpression | float, + angle_3: FreeParameterExpression | float = np.pi / 2, *, - control: Optional[QubitSetInput] = None, - control_state: Optional[BasisStateInput] = None, + control: QubitSetInput | None = None, + control_state: BasisStateInput | None = None, power: float = 1, ) -> Iterable[Instruction]: r"""IonQ Mølmer-Sørensen gate. @@ -3695,7 +3685,7 @@ def _to_openqasm( formatted_matrix = np.array2string( self._matrix, separator=", ", - formatter={"all": lambda x: format_complex(x)}, + formatter={"all": format_complex}, threshold=float("inf"), ).replace("\n", "") @@ -3732,9 +3722,9 @@ def unitary(targets: QubitSet, matrix: np.ndarray, display_name: str = "U") -> I or is not unitary, Examples: - >>> circ = Circuit().unitary(matrix=np.array([[0, 1],[1, 0]]), targets=[0]) + >>> circ = Circuit().unitary(matrix=np.array([[0, 1], [1, 0]]), targets=[0]) """ - # todo: handle controlled unitary + # TODO: handle controlled unitary if 2 ** len(targets) != matrix.shape[0]: raise ValueError("Dimensions of the supplied unitary are incompatible with the targets") @@ -3804,8 +3794,8 @@ def pulse_gate( pulse_sequence: PulseSequence, display_name: str = "PG", *, - control: Optional[QubitSetInput] = None, - control_state: Optional[BasisStateInput] = None, + control: QubitSetInput | None = None, + control_state: BasisStateInput | None = None, power: float = 1, ) -> Instruction: r"""Arbitrary pulse gate which provides the ability to embed custom pulse sequences @@ -3861,7 +3851,6 @@ def format_complex(number: complex) -> str: return f"{number.real}" imag_sign = "+" if number.imag > 0 else "-" return f"{number.real} {imag_sign} {abs(number.imag)}im" - elif number.imag: + if number.imag: return f"{number.imag}im" - else: - return "0" + return "0" diff --git a/src/braket/circuits/instruction.py b/src/braket/circuits/instruction.py index bedfd0c44..8d998939e 100644 --- a/src/braket/circuits/instruction.py +++ b/src/braket/circuits/instruction.py @@ -13,7 +13,7 @@ from __future__ import annotations -from typing import Any, Optional +from typing import Any from braket.circuits.basis_state import BasisState, BasisStateInput from braket.circuits.compiler_directive import CompilerDirective @@ -36,10 +36,10 @@ class Instruction: def __init__( self, operator: InstructionOperator, - target: Optional[QubitSetInput] = None, + target: QubitSetInput | None = None, *, - control: Optional[QubitSetInput] = None, - control_state: Optional[BasisStateInput] = None, + control: QubitSetInput | None = None, + control_state: BasisStateInput | None = None, power: float = 1, ) -> Instruction: """InstructionOperator includes objects of type `Gate` and `Noise` only. @@ -149,7 +149,7 @@ def adjoint(self) -> list[Instruction]: ) for gate in operator.adjoint() ] - elif isinstance(operator, CompilerDirective): + if isinstance(operator, CompilerDirective): return [Instruction(operator.counterpart(), self._target)] raise NotImplementedError(f"Adjoint not supported for {operator}") @@ -191,11 +191,11 @@ def ascii_symbols(self) -> tuple[str, ...]: def copy( self, - target_mapping: Optional[dict[QubitInput, QubitInput]] = None, - target: Optional[QubitSetInput] = None, - control_mapping: Optional[dict[QubitInput, QubitInput]] = None, - control: Optional[QubitSetInput] = None, - control_state: Optional[BasisStateInput] = None, + target_mapping: dict[QubitInput, QubitInput] | None = None, + target: QubitSetInput | None = None, + control_mapping: dict[QubitInput, QubitInput] | None = None, + control: QubitSetInput | None = None, + control_state: BasisStateInput | None = None, power: float = 1, ) -> Instruction: """Return a shallow copy of the instruction. @@ -287,7 +287,7 @@ def __eq__(self, other: Instruction): ) return NotImplemented - def __pow__(self, power: float, modulo: float = None): + def __pow__(self, power: float, modulo: float | None = None): new_power = self.power * power if modulo is not None: new_power %= modulo diff --git a/src/braket/circuits/measure.py b/src/braket/circuits/measure.py index d31555ba9..091bf134f 100644 --- a/src/braket/circuits/measure.py +++ b/src/braket/circuits/measure.py @@ -67,12 +67,11 @@ def to_ir( """ if ir_type == IRType.JAQCD: return self._to_jaqcd() - elif ir_type == IRType.OPENQASM: + if ir_type == IRType.OPENQASM: return self._to_openqasm( target, serialization_properties or OpenQASMSerializationProperties() ** kwargs ) - else: - raise ValueError(f"supplied ir_type {ir_type} is not supported.") + raise ValueError(f"supplied ir_type {ir_type} is not supported.") def _to_jaqcd(self) -> Any: """Returns the JAQCD representation of the measure.""" diff --git a/src/braket/circuits/moments.py b/src/braket/circuits/moments.py index b2dee4151..10f236366 100644 --- a/src/braket/circuits/moments.py +++ b/src/braket/circuits/moments.py @@ -16,7 +16,7 @@ from collections import OrderedDict from collections.abc import ItemsView, Iterable, KeysView, Mapping, ValuesView from enum import Enum -from typing import Any, NamedTuple, Union +from typing import Any, NamedTuple from braket.circuits.compiler_directive import CompilerDirective from braket.circuits.gate import Gate @@ -90,7 +90,6 @@ class Moments(Mapping[MomentsKey, Instruction]): ... print(f"Item {i}") ... print(f"\\tKey: {item[0]}") ... print(f"\\tValue: {item[1]}") - ... Item 0 Key: MomentsKey(time=0, qubits=QubitSet([Qubit(0)])) Value: Instruction('operator': H, 'target': QubitSet([Qubit(0)])) @@ -157,9 +156,7 @@ def time_slices(self) -> dict[int, list[Instruction]]: return time_slices - def add( - self, instructions: Union[Iterable[Instruction], Instruction], noise_index: int = 0 - ) -> None: + def add(self, instructions: Iterable[Instruction] | Instruction, noise_index: int = 0) -> None: """Add one or more instructions to self. Args: diff --git a/src/braket/circuits/noise.py b/src/braket/circuits/noise.py index e5d4fdf8a..3ae4153e4 100644 --- a/src/braket/circuits/noise.py +++ b/src/braket/circuits/noise.py @@ -14,7 +14,7 @@ from __future__ import annotations from collections.abc import Iterable, Sequence -from typing import Any, ClassVar, Optional, Union +from typing import Any, ClassVar import numpy as np @@ -38,7 +38,7 @@ class Noise(QuantumOperator): the metadata that defines what the noise channel is and what it does. """ - def __init__(self, qubit_count: Optional[int], ascii_symbols: Sequence[str]): + def __init__(self, qubit_count: int | None, ascii_symbols: Sequence[str]): """Initializes a `Noise` object. Args: @@ -88,7 +88,7 @@ def to_ir( """ if ir_type == IRType.JAQCD: return self._to_jaqcd(target) - elif ir_type == IRType.OPENQASM: + if ir_type == IRType.OPENQASM: if serialization_properties and not isinstance( serialization_properties, OpenQASMSerializationProperties ): @@ -99,8 +99,7 @@ def to_ir( return self._to_openqasm( target, serialization_properties or OpenQASMSerializationProperties() ) - else: - raise ValueError(f"Supplied ir_type {ir_type} is not supported.") + raise ValueError(f"Supplied ir_type {ir_type} is not supported.") def _to_jaqcd(self, target: QubitSet) -> Any: """Returns the JAQCD representation of the noise. @@ -176,8 +175,8 @@ class SingleProbabilisticNoise(Noise, Parameterizable): def __init__( self, - probability: Union[FreeParameterExpression, float], - qubit_count: Optional[int], + probability: FreeParameterExpression | float, + qubit_count: int | None, ascii_symbols: Sequence[str], max_probability: float = 0.5, ): @@ -219,7 +218,7 @@ def __str__(self): return f"{self.name}({self.probability})" @property - def parameters(self) -> list[Union[FreeParameterExpression, float]]: + def parameters(self) -> list[FreeParameterExpression | float]: """Returns the parameters associated with the object, either unbound free parameter expressions or bound values. @@ -261,15 +260,15 @@ def to_dict(self) -> dict: } -class SingleProbabilisticNoise_34(SingleProbabilisticNoise): +class SingleProbabilisticNoise_34(SingleProbabilisticNoise): # noqa: N801 """Class `SingleProbabilisticNoise` represents the Depolarizing and TwoQubitDephasing noise channels parameterized by a single probability. """ def __init__( self, - probability: Union[FreeParameterExpression, float], - qubit_count: Optional[int], + probability: FreeParameterExpression | float, + qubit_count: int | None, ascii_symbols: Sequence[str], ): """Initializes a `SingleProbabilisticNoise_34`. @@ -295,15 +294,15 @@ def __init__( ) -class SingleProbabilisticNoise_1516(SingleProbabilisticNoise): +class SingleProbabilisticNoise_1516(SingleProbabilisticNoise): # noqa: N801 """Class `SingleProbabilisticNoise` represents the TwoQubitDepolarizing noise channel parameterized by a single probability. """ def __init__( self, - probability: Union[FreeParameterExpression, float], - qubit_count: Optional[int], + probability: FreeParameterExpression | float, + qubit_count: int | None, ascii_symbols: Sequence[str], ): """Initializes a `SingleProbabilisticNoise_1516`. @@ -338,8 +337,8 @@ class MultiQubitPauliNoise(Noise, Parameterizable): def __init__( self, - probabilities: dict[str, Union[FreeParameterExpression, float]], - qubit_count: Optional[int], + probabilities: dict[str, FreeParameterExpression | float], + qubit_count: int | None, ascii_symbols: Sequence[str], ): """[summary] @@ -433,7 +432,7 @@ def probabilities(self) -> dict[str, float]: return self._probabilities @property - def parameters(self) -> list[Union[FreeParameterExpression, float]]: + def parameters(self) -> list[FreeParameterExpression | float]: """Returns the parameters associated with the object, either unbound free parameter expressions or bound values. @@ -485,10 +484,10 @@ class PauliNoise(Noise, Parameterizable): def __init__( self, - probX: Union[FreeParameterExpression, float], - probY: Union[FreeParameterExpression, float], - probZ: Union[FreeParameterExpression, float], - qubit_count: Optional[int], + probX: FreeParameterExpression | float, + probY: FreeParameterExpression | float, + probZ: FreeParameterExpression | float, + qubit_count: int | None, ascii_symbols: Sequence[str], ): """Initializes a `PauliNoise`. @@ -522,7 +521,7 @@ def __init__( self._parameters = [probX, probY, probZ] @staticmethod - def _get_param_float(param: Union[FreeParameterExpression, float], param_name: str) -> float: + def _get_param_float(param: FreeParameterExpression | float, param_name: str) -> float: """Validates the value of a probability and returns its value. If param is a free parameter expression, this method returns 0. @@ -540,7 +539,7 @@ def _get_param_float(param: Union[FreeParameterExpression, float], param_name: s return float(param) @property - def probX(self) -> Union[FreeParameterExpression, float]: + def probX(self) -> FreeParameterExpression | float: """The probability of a Pauli X error. Returns: @@ -549,7 +548,7 @@ def probX(self) -> Union[FreeParameterExpression, float]: return self._parameters[0] @property - def probY(self) -> Union[FreeParameterExpression, float]: + def probY(self) -> FreeParameterExpression | float: """The probability of a Pauli Y error. Returns: @@ -558,7 +557,7 @@ def probY(self) -> Union[FreeParameterExpression, float]: return self._parameters[1] @property - def probZ(self) -> Union[FreeParameterExpression, float]: + def probZ(self) -> FreeParameterExpression | float: """The probability of a Pauli Z error. Returns: @@ -585,7 +584,7 @@ def __eq__(self, other: PauliNoise): return False @property - def parameters(self) -> list[Union[FreeParameterExpression, float]]: + def parameters(self) -> list[FreeParameterExpression | float]: """Returns the parameters associated with the object, either unbound free parameter expressions or bound values. @@ -633,8 +632,8 @@ class DampingNoise(Noise, Parameterizable): def __init__( self, - gamma: Union[FreeParameterExpression, float], - qubit_count: Optional[int], + gamma: FreeParameterExpression | float, + qubit_count: int | None, ascii_symbols: Sequence[str], ): """Initializes a `DampingNoise`. @@ -676,7 +675,7 @@ def __str__(self): return f"{self.name}({self.gamma})" @property - def parameters(self) -> list[Union[FreeParameterExpression, float]]: + def parameters(self) -> list[FreeParameterExpression | float]: """Returns the parameters associated with the object, either unbound free parameter expressions or bound values. @@ -725,9 +724,9 @@ class GeneralizedAmplitudeDampingNoise(DampingNoise): def __init__( self, - gamma: Union[FreeParameterExpression, float], - probability: Union[FreeParameterExpression, float], - qubit_count: Optional[int], + gamma: FreeParameterExpression | float, + probability: FreeParameterExpression | float, + qubit_count: int | None, ascii_symbols: Sequence[str], ): """Inits a `GeneralizedAmplitudeDampingNoise`. @@ -776,7 +775,7 @@ def __str__(self): return f"{self.name}({self.gamma}, {self.probability})" @property - def parameters(self) -> list[Union[FreeParameterExpression, float]]: + def parameters(self) -> list[FreeParameterExpression | float]: """Returns the parameters associated with the object, either unbound free parameter expressions or bound values. @@ -814,7 +813,7 @@ def to_dict(self) -> dict: def _validate_param_value( - parameter: Union[FreeParameterExpression, float], param_name: str, maximum: float = 1.0 + parameter: FreeParameterExpression | float, param_name: str, maximum: float = 1.0 ) -> None: """Validates the value of a given parameter. @@ -829,7 +828,7 @@ def _validate_param_value( raise ValueError(f"{param_name} must be a real number in the interval [0, {maximum}]") -def _parameter_to_dict(parameter: Union[FreeParameter, float]) -> Union[dict, float]: +def _parameter_to_dict(parameter: FreeParameter | float) -> dict | float: """Converts a parameter to a dictionary if it's a FreeParameter, otherwise returns the float. Args: diff --git a/src/braket/circuits/noise_helpers.py b/src/braket/circuits/noise_helpers.py index a73b7f338..708ad0464 100644 --- a/src/braket/circuits/noise_helpers.py +++ b/src/braket/circuits/noise_helpers.py @@ -15,7 +15,7 @@ import warnings from collections.abc import Iterable -from typing import TYPE_CHECKING, Any, Optional, Union +from typing import TYPE_CHECKING, Any import numpy as np @@ -105,7 +105,7 @@ def check_noise_target_unitary(noise: Noise, target_unitary: np.ndarray) -> None def check_noise_target_qubits( - circuit: Circuit, target_qubits: Optional[QubitSetInput] = None + circuit: Circuit, target_qubits: QubitSetInput | None = None ) -> QubitSet: """Helper function to check whether all the target_qubits are positive integers. @@ -155,15 +155,15 @@ def apply_noise_to_moments( for noise_channel in noise: if noise_channel.qubit_count == 1: new = [Instruction(noise_channel, qubit) for qubit in target_qubits] - noise_instructions = noise_instructions + new + noise_instructions += new else: noise_instructions.append(Instruction(noise_channel, target_qubits)) new_moments = Moments() if position == "initialization": - for noise in noise_instructions: - new_moments.add_noise(noise, "initialization_noise") + for noise_instr in noise_instructions: + new_moments.add_noise(noise_instr, "initialization_noise") # add existing instructions for moment_key in circuit.moments: @@ -176,8 +176,8 @@ def apply_noise_to_moments( new_moments.add([instruction], moment_key.noise_index) if position == "readout": - for noise in noise_instructions: - new_moments.add_noise(noise, "readout_noise") + for noise_instr in noise_instructions: + new_moments.add_noise(noise_instr, "readout_noise") circuit._moments = new_moments @@ -226,9 +226,10 @@ def _apply_noise_to_gates_helper( and instruction.target.issubset(target_qubits) ): noise_index += 1 - new_noise_instruction.append( - (Instruction(noise_channel, instruction.target), noise_index) - ) + new_noise_instruction.append(( + Instruction(noise_channel, instruction.target), + noise_index, + )) noise_applied = True return new_noise_instruction, noise_index, noise_applied @@ -237,7 +238,7 @@ def _apply_noise_to_gates_helper( def apply_noise_to_gates( circuit: Circuit, noise: Iterable[type[Noise]], - target_gates: Union[Iterable[type[Gate]], np.ndarray], + target_gates: Iterable[type[Gate]] | np.ndarray, target_qubits: QubitSet, ) -> Circuit: """Apply noise after target gates in target qubits. diff --git a/src/braket/circuits/noise_model/__init__.py b/src/braket/circuits/noise_model/__init__.py index 717e5057f..f1d25637b 100644 --- a/src/braket/circuits/noise_model/__init__.py +++ b/src/braket/circuits/noise_model/__init__.py @@ -11,20 +11,23 @@ # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. -from braket.circuits.noise_model.circuit_instruction_criteria import ( # noqa: F401 - CircuitInstructionCriteria, +from braket.circuits.noise_model.circuit_instruction_criteria import ( + CircuitInstructionCriteria, # noqa: F401 ) -from braket.circuits.noise_model.criteria import ( # noqa: F401 - Criteria, - CriteriaKey, - CriteriaKeyResult, +from braket.circuits.noise_model.criteria import ( + Criteria, # noqa: F401 + CriteriaKey, # noqa: F401 + CriteriaKeyResult, # noqa: F401 ) from braket.circuits.noise_model.gate_criteria import GateCriteria # noqa: F401 from braket.circuits.noise_model.initialization_criteria import InitializationCriteria # noqa: F401 -from braket.circuits.noise_model.noise_model import NoiseModel, NoiseModelInstruction # noqa: F401 +from braket.circuits.noise_model.noise_model import ( + NoiseModel, # noqa: F401 + NoiseModelInstruction, # noqa: F401 +) from braket.circuits.noise_model.observable_criteria import ObservableCriteria # noqa: F401 -from braket.circuits.noise_model.qubit_initialization_criteria import ( # noqa: F401 - QubitInitializationCriteria, +from braket.circuits.noise_model.qubit_initialization_criteria import ( + QubitInitializationCriteria, # noqa: F401 ) from braket.circuits.noise_model.result_type_criteria import ResultTypeCriteria # noqa: F401 from braket.circuits.noise_model.unitary_gate_criteria import UnitaryGateCriteria # noqa: F401 diff --git a/src/braket/circuits/noise_model/criteria.py b/src/braket/circuits/noise_model/criteria.py index 889211342..d0e7e7a8c 100644 --- a/src/braket/circuits/noise_model/criteria.py +++ b/src/braket/circuits/noise_model/criteria.py @@ -16,7 +16,7 @@ from abc import ABC, abstractmethod from collections.abc import Iterable from enum import Enum -from typing import Any, Union +from typing import Any class CriteriaKey(str, Enum): @@ -54,7 +54,7 @@ def applicable_key_types(self) -> Iterable[CriteriaKey]: raise NotImplementedError @abstractmethod - def get_keys(self, key_type: CriteriaKey) -> Union[CriteriaKeyResult, set[Any]]: + def get_keys(self, key_type: CriteriaKey) -> CriteriaKeyResult | set[Any]: """Returns a set of key for a given key type. Args: diff --git a/src/braket/circuits/noise_model/noise_model.py b/src/braket/circuits/noise_model/noise_model.py index e8a603075..cca792e08 100644 --- a/src/braket/circuits/noise_model/noise_model.py +++ b/src/braket/circuits/noise_model/noise_model.py @@ -15,7 +15,6 @@ from collections import defaultdict from dataclasses import dataclass -from typing import Optional from braket.circuits.circuit import Circuit from braket.circuits.gate import Gate @@ -38,9 +37,9 @@ class NoiseModelInstruction: def __init__(self, noise: Noise, criteria: Criteria): if not isinstance(noise, Noise): - raise ValueError(f"{noise} must be a Noise type.") + raise TypeError(f"{noise} must be a Noise type.") if not isinstance(criteria, Criteria): - raise ValueError(f"{criteria} must be a Criteria type.") + raise TypeError(f"{criteria} must be a Criteria type.") self.noise = noise self.criteria = criteria @@ -89,7 +88,7 @@ class NoiseModel: a phase flip. """ - def __init__(self, instructions: list[NoiseModelInstruction] = None): + def __init__(self, instructions: list[NoiseModelInstruction] | None = None): self._instructions = instructions or [] def __repr__(self): @@ -194,9 +193,9 @@ def get_instructions_by_type(self) -> NoiseModelInstructions: def from_filter( self, - qubit: Optional[QubitSetInput] = None, - gate: Optional[Gate] = None, - noise: Optional[type[Noise]] = None, + qubit: QubitSetInput | None = None, + gate: Gate | None = None, + noise: type[Noise] | None = None, ) -> NoiseModel: """Returns a new NoiseModel from this NoiseModel using a given filter. If no filters are specified, the returned NoiseModel will be the same as this one. diff --git a/src/braket/circuits/noises.py b/src/braket/circuits/noises.py index a8829f1a4..a167b2a1c 100644 --- a/src/braket/circuits/noises.py +++ b/src/braket/circuits/noises.py @@ -1164,7 +1164,7 @@ def generalized_amplitude_damping( Iterable[Instruction]: `Iterable` of GeneralizedAmplitudeDamping instructions. Examples: - >>> circ = Circuit().generalized_amplitude_damping(0, gamma=0.1, probability = 0.9) + >>> circ = Circuit().generalized_amplitude_damping(0, gamma=0.1, probability=0.9) """ return [ Instruction( @@ -1366,7 +1366,7 @@ def _to_openqasm( np.array2string( matrix, separator=", ", - formatter={"all": lambda x: format_complex(x)}, + formatter={"all": format_complex}, ).replace("\n", "") for matrix in self._matrices ) @@ -1402,7 +1402,7 @@ def kraus( Examples: >>> K0 = np.eye(4) * np.sqrt(0.9) - >>> K1 = np.kron([[1., 0.],[0., 1.]], [[0., 1.],[1., 0.]]) * np.sqrt(0.1) + >>> K1 = np.kron([[1.0, 0.0], [0.0, 1.0]], [[0.0, 1.0], [1.0, 0.0]]) * np.sqrt(0.1) >>> circ = Circuit().kraus([1, 0], matrices=[K0, K1]) """ if 2 ** len(targets) != matrices[0].shape[0]: diff --git a/src/braket/circuits/observable.py b/src/braket/circuits/observable.py index e0572e3d9..7e86ab33e 100644 --- a/src/braket/circuits/observable.py +++ b/src/braket/circuits/observable.py @@ -41,11 +41,10 @@ def __init__( ): super().__init__(qubit_count=qubit_count, ascii_symbols=ascii_symbols) targets = QubitSet(targets) - if targets: - if (num_targets := len(targets)) != qubit_count: - raise ValueError( - f"Length of target {num_targets} does not match qubit count {qubit_count}" - ) + if targets and (num_targets := len(targets)) != qubit_count: + raise ValueError( + f"Length of target {num_targets} does not match qubit count {qubit_count}" + ) self._targets = targets self._coef = 1 @@ -80,7 +79,7 @@ def to_ir( """ if ir_type == IRType.JAQCD: return self._to_jaqcd() - elif ir_type == IRType.OPENQASM: + if ir_type == IRType.OPENQASM: if serialization_properties and not isinstance( serialization_properties, OpenQASMSerializationProperties ): @@ -91,8 +90,7 @@ def to_ir( return self._to_openqasm( serialization_properties or OpenQASMSerializationProperties(), target ) - else: - raise ValueError(f"Supplied ir_type {ir_type} is not supported.") + raise ValueError(f"Supplied ir_type {ir_type} is not supported.") def _to_jaqcd(self) -> list[str | list[list[list[float]]]]: """Returns the JAQCD representation of the observable.""" @@ -177,7 +175,7 @@ def __matmul__(self, other: Observable) -> Observable.TensorProduct: if isinstance(other, Observable): return Observable.TensorProduct([self, other]) - raise ValueError("Can only perform tensor products between observables.") + raise TypeError("Can only perform tensor products between observables.") def __mul__(self, other: Observable) -> Observable: """Scalar multiplication""" @@ -192,13 +190,13 @@ def __rmul__(self, other: Observable) -> Observable: def __add__(self, other: Observable): if not isinstance(other, Observable): - raise ValueError("Can only perform addition between observables.") + raise TypeError("Can only perform addition between observables.") return Observable.Sum([self, other]) def __sub__(self, other: Observable): if not isinstance(other, Observable): - raise ValueError("Can only perform subtraction between observables.") + raise TypeError("Can only perform subtraction between observables.") return self + (-1 * other) diff --git a/src/braket/circuits/observables.py b/src/braket/circuits/observables.py index 8249d156f..5be86554a 100644 --- a/src/braket/circuits/observables.py +++ b/src/braket/circuits/observables.py @@ -18,7 +18,7 @@ import math import numbers from copy import deepcopy -from typing import ClassVar, Union +from typing import ClassVar import numpy as np @@ -110,6 +110,7 @@ def _to_openqasm( self, serialization_properties: OpenQASMSerializationProperties, target: QubitSet = None ) -> str: coef_prefix = f"{self.coefficient} * " if self.coefficient != 1 else "" + targets = target or self._targets qubit_target = int(targets[0]) if targets else None if qubit_target is not None: @@ -168,6 +169,7 @@ def _to_openqasm( self, serialization_properties: OpenQASMSerializationProperties, target: QubitSet = None ) -> str: coef_prefix = f"{self.coefficient} * " if self.coefficient != 1 else "" + targets = target or self._targets qubit_target = int(targets[0]) if targets else None if qubit_target is not None: @@ -532,7 +534,7 @@ def _to_jaqcd(self) -> list[str]: def _to_openqasm( self, serialization_properties: OpenQASMSerializationProperties, - target: list[QubitSetInput] = None, + target: list[QubitSetInput] | None = None, ) -> str: target = target or self._targets if len(self.summands) != len(target): @@ -615,8 +617,8 @@ def __init__( or, if targets is supplied, doesn't match the size of targets. Examples: - >>> observables.Hermitian(matrix=np.array([[0, 1],[1, 0]]), targets=[0]) - >>> observables.Hermitian(matrix=np.array([[0, 1],[1, 0]])) + >>> observables.Hermitian(matrix=np.array([[0, 1], [1, 0]]), targets=[0]) + >>> observables.Hermitian(matrix=np.array([[0, 1], [1, 0]])) """ verify_quantum_operator_matrix_dimensions(matrix) self._matrix = np.array(matrix, dtype=complex) @@ -652,15 +654,14 @@ def _to_openqasm( coef_prefix = f"{self.coefficient} * " if self.coefficient != 1 else "" target = target or self._targets if target: - qubit_target = ", ".join( - [serialization_properties.format_target(int(t)) for t in target] - ) + qubit_target = ", ".join([ + serialization_properties.format_target(int(t)) for t in target + ]) return ( f"{coef_prefix}" f"hermitian({self._serialized_matrix_openqasm_matrix()}) {qubit_target}" ) - else: - return f"{coef_prefix}hermitian({self._serialized_matrix_openqasm_matrix()}) all" + return f"{coef_prefix}hermitian({self._serialized_matrix_openqasm_matrix()}) all" def _serialized_matrix_openqasm_matrix(self) -> str: serialized = str([[f"{complex(elem)}" for elem in row] for row in self._matrix.tolist()]) @@ -725,7 +726,7 @@ def __repr__(self): Observable.register_observable(Hermitian) -def observable_from_ir(ir_observable: list[Union[str, list[list[list[float]]]]]) -> Observable: +def observable_from_ir(ir_observable: list[str | list[list[list[float]]]]) -> Observable: """Create an observable from the IR observable list. This can be a tensor product of observables or a single observable. @@ -737,26 +738,24 @@ def observable_from_ir(ir_observable: list[Union[str, list[list[list[float]]]]]) """ if len(ir_observable) == 1: return _observable_from_ir_list_item(ir_observable[0]) - observable = TensorProduct([_observable_from_ir_list_item(obs) for obs in ir_observable]) - return observable + return TensorProduct([_observable_from_ir_list_item(obs) for obs in ir_observable]) -def _observable_from_ir_list_item(observable: Union[str, list[list[list[float]]]]) -> Observable: +def _observable_from_ir_list_item(observable: str | list[list[list[float]]]) -> Observable: if observable == "i": return I() - elif observable == "h": + if observable == "h": return H() - elif observable == "x": + if observable == "x": return X() - elif observable == "y": + if observable == "y": return Y() - elif observable == "z": + if observable == "z": return Z() - else: - try: - matrix = np.array( - [[complex(element[0], element[1]) for element in row] for row in observable] - ) - return Hermitian(matrix) - except Exception as e: - raise ValueError(f"Invalid observable specified: {observable} error: {e}") from e + try: + matrix = np.array([ + [complex(element[0], element[1]) for element in row] for row in observable + ]) + return Hermitian(matrix) + except Exception as e: + raise ValueError(f"Invalid observable specified: {observable} error: {e}") from e diff --git a/src/braket/circuits/quantum_operator.py b/src/braket/circuits/quantum_operator.py index b706e1822..d33c69a1c 100644 --- a/src/braket/circuits/quantum_operator.py +++ b/src/braket/circuits/quantum_operator.py @@ -14,7 +14,7 @@ from __future__ import annotations from collections.abc import Sequence -from typing import Any, Optional +from typing import Any import numpy as np @@ -24,7 +24,7 @@ class QuantumOperator(Operator): """A quantum operator is the definition of a quantum operation for a quantum device.""" - def __init__(self, qubit_count: Optional[int], ascii_symbols: Sequence[str]): + def __init__(self, qubit_count: int | None, ascii_symbols: Sequence[str]): """Initializes a `QuantumOperator`. Args: @@ -55,7 +55,7 @@ def __init__(self, qubit_count: Optional[int], ascii_symbols: Sequence[str]): elif qubit_count and qubit_count != fixed_qubit_count: raise ValueError( f"Provided qubit count {qubit_count}" - "does not equal fixed qubit count {fixed_qubit_count}" + f"does not equal fixed qubit count {fixed_qubit_count}" ) else: self._qubit_count = fixed_qubit_count diff --git a/src/braket/circuits/quantum_operator_helpers.py b/src/braket/circuits/quantum_operator_helpers.py index 10c22808e..07c2d09e4 100644 --- a/src/braket/circuits/quantum_operator_helpers.py +++ b/src/braket/circuits/quantum_operator_helpers.py @@ -118,8 +118,9 @@ def get_pauli_eigenvalues(num_qubits: int) -> np.ndarray: eigs = np.array([1, -1]) eigs.setflags(write=False) return eigs - eigs = np.concatenate( - [get_pauli_eigenvalues(num_qubits - 1), -get_pauli_eigenvalues(num_qubits - 1)] - ) + eigs = np.concatenate([ + get_pauli_eigenvalues(num_qubits - 1), + -get_pauli_eigenvalues(num_qubits - 1), + ]) eigs.setflags(write=False) return eigs diff --git a/src/braket/circuits/result_type.py b/src/braket/circuits/result_type.py index 8343429e0..eadd4c02d 100644 --- a/src/braket/circuits/result_type.py +++ b/src/braket/circuits/result_type.py @@ -13,7 +13,7 @@ from __future__ import annotations -from typing import Any, Union +from typing import Any from braket.circuits.free_parameter import FreeParameter from braket.circuits.observable import Observable @@ -86,7 +86,7 @@ def to_ir( """ if ir_type == IRType.JAQCD: return self._to_jaqcd() - elif ir_type == IRType.OPENQASM: + if ir_type == IRType.OPENQASM: if serialization_properties and not isinstance( serialization_properties, OpenQASMSerializationProperties ): @@ -95,8 +95,7 @@ def to_ir( "for IRType.OPENQASM." ) return self._to_openqasm(serialization_properties or OpenQASMSerializationProperties()) - else: - raise ValueError(f"Supplied ir_type {ir_type} is not supported.") + raise ValueError(f"Supplied ir_type {ir_type} is not supported.") def _to_jaqcd(self) -> Any: """Returns the JAQCD representation of the result type.""" @@ -152,10 +151,10 @@ def copy( >>> new_result_type.target QubitSet(Qubit(5)) """ - copy = self.__copy__() + copy = self.__copy__() # noqa: PLC2801 if target_mapping and target is not None: raise TypeError("Only 'target_mapping' or 'target' can be supplied, but not both.") - elif target is not None: + if target is not None: if hasattr(copy, "target"): copy.target = target elif hasattr(copy, "target"): @@ -288,7 +287,7 @@ def __init__( ascii_symbols: list[str], observable: Observable, target: QubitSetInput | None = None, - parameters: list[Union[str, FreeParameter]] | None = None, + parameters: list[str | FreeParameter] | None = None, ): super().__init__(ascii_symbols, observable, target) diff --git a/src/braket/circuits/result_types.py b/src/braket/circuits/result_types.py index 6c1232b06..9cd42e5b9 100644 --- a/src/braket/circuits/result_types.py +++ b/src/braket/circuits/result_types.py @@ -14,7 +14,6 @@ from __future__ import annotations import re -from typing import Union import braket.ir.jaqcd as ir from braket.circuits import circuit @@ -117,8 +116,7 @@ def _to_jaqcd(self) -> ir.DensityMatrix: if self.target: # convert qubits to int as required by the ir type return ir.DensityMatrix.construct(targets=[int(qubit) for qubit in self.target]) - else: - return ir.DensityMatrix.construct() + return ir.DensityMatrix.construct() def _to_openqasm(self, serialization_properties: OpenQASMSerializationProperties) -> str: if not self.target: @@ -175,7 +173,7 @@ def __init__( self, observable: Observable, target: list[QubitSetInput] | None = None, - parameters: list[Union[str, FreeParameter]] | None = None, + parameters: list[str | FreeParameter] | None = None, ): """Inits an `AdjointGradient`. @@ -235,7 +233,7 @@ def _to_openqasm(self, serialization_properties: OpenQASMSerializationProperties def adjoint_gradient( observable: Observable, target: list[QubitSetInput] | None = None, - parameters: list[Union[str, FreeParameter]] | None = None, + parameters: list[str | FreeParameter] | None = None, ) -> ResultType: """Registers this function into the circuit class. @@ -254,7 +252,7 @@ def adjoint_gradient( ResultType: gradient computed via adjoint differentiation as a requested result type Examples: - >>> alpha, beta = FreeParameter('alpha'), FreeParameter('beta') + >>> alpha, beta = FreeParameter("alpha"), FreeParameter("beta") >>> circ = Circuit().h(0).h(1).rx(0, alpha).yy(0, 1, beta).adjoint_gradient( >>> observable=observables.Z(0), parameters=[alpha, beta] >>> ) @@ -283,13 +281,13 @@ def __init__(self, state: list[str]): state is not a list of strings of '0' and '1' Examples: - >>> result_types.Amplitude(state=['01', '10']) + >>> result_types.Amplitude(state=["01", "10"]) """ if ( not state or not isinstance(state, list) or not all( - isinstance(amplitude, str) and re.fullmatch("^[01]+$", amplitude) + isinstance(amplitude, str) and re.fullmatch(r"^[01]+$", amplitude) for amplitude in state ) ): @@ -385,8 +383,7 @@ def _to_jaqcd(self) -> ir.Probability: if self.target: # convert qubits to int as required by the ir type return ir.Probability.construct(targets=[int(qubit) for qubit in self.target]) - else: - return ir.Probability.construct() + return ir.Probability.construct() def _to_openqasm(self, serialization_properties: OpenQASMSerializationProperties) -> str: if not self.target: @@ -472,8 +469,7 @@ def _to_jaqcd(self) -> ir.Expectation: return ir.Expectation.construct( observable=self.observable.to_ir(), targets=[int(qubit) for qubit in self.target] ) - else: - return ir.Expectation.construct(observable=self.observable.to_ir()) + return ir.Expectation.construct(observable=self.observable.to_ir()) def _to_openqasm(self, serialization_properties: OpenQASMSerializationProperties) -> str: observable_ir = self.observable.to_ir( @@ -547,8 +543,7 @@ def _to_jaqcd(self) -> ir.Sample: return ir.Sample.construct( observable=self.observable.to_ir(), targets=[int(qubit) for qubit in self.target] ) - else: - return ir.Sample.construct(observable=self.observable.to_ir()) + return ir.Sample.construct(observable=self.observable.to_ir()) def _to_openqasm(self, serialization_properties: OpenQASMSerializationProperties) -> str: observable_ir = self.observable.to_ir( @@ -627,8 +622,7 @@ def _to_jaqcd(self) -> ir.Variance: return ir.Variance.construct( observable=self.observable.to_ir(), targets=[int(qubit) for qubit in self.target] ) - else: - return ir.Variance.construct(observable=self.observable.to_ir()) + return ir.Variance.construct(observable=self.observable.to_ir()) def _to_openqasm(self, serialization_properties: OpenQASMSerializationProperties) -> str: observable_ir = self.observable.to_ir( diff --git a/src/braket/circuits/text_diagram_builders/ascii_circuit_diagram.py b/src/braket/circuits/text_diagram_builders/ascii_circuit_diagram.py index 4a7c9565c..57b591173 100644 --- a/src/braket/circuits/text_diagram_builders/ascii_circuit_diagram.py +++ b/src/braket/circuits/text_diagram_builders/ascii_circuit_diagram.py @@ -14,7 +14,7 @@ from __future__ import annotations from functools import reduce -from typing import Literal, Union +from typing import Literal import braket.circuits.circuit as cir from braket.circuits.compiler_directive import CompilerDirective @@ -74,7 +74,7 @@ def _duplicate_time_at_bottom(cls, lines: str) -> None: def _create_diagram_column( cls, circuit_qubits: QubitSet, - items: list[Union[Instruction, ResultType]], + items: list[Instruction | ResultType], global_phase: float | None = None, ) -> str: """Return a column in the ASCII string diagram of the circuit for a given list of items. @@ -88,7 +88,7 @@ def _create_diagram_column( str: an ASCII string diagram for the specified moment in time for a column. """ symbols = {qubit: cls._qubit_line_character() for qubit in circuit_qubits} - connections = {qubit: "none" for qubit in circuit_qubits} + connections = dict.fromkeys(circuit_qubits, "none") for item in items: if isinstance(item, ResultType) and not item.target: @@ -135,7 +135,7 @@ def _create_diagram_column( # Determine if the qubit is part of the item or in the middle of a # multi qubit item. if qubit in target_qubits: - item_qubit_index = [ + item_qubit_index = [ # noqa: RUF015 index for index, q in enumerate(target_qubits) if q == qubit ][0] power_string = ( @@ -164,8 +164,7 @@ def _create_diagram_column( if target_and_control and qubit != min(target_and_control): connections[qubit] = "above" - output = cls._create_output(symbols, connections, circuit_qubits, global_phase) - return output + return cls._create_output(symbols, connections, circuit_qubits, global_phase) # Ignore flake8 issue caused by Literal["above", "below", "both", "none"] # flake8: noqa: BCS005 @@ -185,8 +184,8 @@ def _draw_symbol( Returns: str: a string representing the symbol. """ - connection_char = cls._vertical_delimiter() if connection in ["above"] else " " - output = "{0:{width}}\n".format( + connection_char = cls._vertical_delimiter() if connection == "above" else " " + return "{0:{width}}\n".format( connection_char, width=symbols_width + 1 ) + "{0:{fill}{align}{width}}\n".format( symbol, @@ -194,4 +193,3 @@ def _draw_symbol( align="<", width=symbols_width + 1, ) - return output diff --git a/src/braket/circuits/text_diagram_builders/text_circuit_diagram.py b/src/braket/circuits/text_diagram_builders/text_circuit_diagram.py index ad30b34a7..08bde78c5 100644 --- a/src/braket/circuits/text_diagram_builders/text_circuit_diagram.py +++ b/src/braket/circuits/text_diagram_builders/text_circuit_diagram.py @@ -1,7 +1,7 @@ from __future__ import annotations from abc import ABC, abstractmethod -from typing import Literal, Union +from typing import Literal import braket.circuits.circuit as cir from braket.circuits.circuit_diagram import CircuitDiagram @@ -178,7 +178,7 @@ def _create_diagram_column_set( cls, col_title: str, circuit_qubits: QubitSet, - items: list[Union[Instruction, ResultType]], + items: list[Instruction | ResultType], global_phase: float | None, ) -> str: """Return a set of columns in the string diagram of the circuit for a list of items. diff --git a/src/braket/circuits/text_diagram_builders/text_circuit_diagram_utils.py b/src/braket/circuits/text_diagram_builders/text_circuit_diagram_utils.py index f261b00b6..51b41ceb7 100644 --- a/src/braket/circuits/text_diagram_builders/text_circuit_diagram_utils.py +++ b/src/braket/circuits/text_diagram_builders/text_circuit_diagram_utils.py @@ -14,7 +14,6 @@ from __future__ import annotations from functools import reduce -from typing import Union import braket.circuits.circuit as cir from braket.circuits.compiler_directive import CompilerDirective @@ -43,8 +42,7 @@ def _add_footers( # A list of parameters in the circuit to the currently assigned values. if circuit.parameters: lines.append( - "\nUnassigned parameters: " - f"{sorted(circuit.parameters, key=lambda param: param.name)}." + f"\nUnassigned parameters: {sorted(circuit.parameters, key=lambda param: param.name)}." ) return "\n".join(lines) @@ -117,7 +115,7 @@ def _compute_moment_global_phase( def _group_items( circuit_qubits: QubitSet, - items: list[Union[Instruction, ResultType]], + items: list[Instruction | ResultType], ) -> list[tuple[QubitSet, list[Instruction]]]: """ Group instructions in a moment diff --git a/src/braket/circuits/text_diagram_builders/unicode_circuit_diagram.py b/src/braket/circuits/text_diagram_builders/unicode_circuit_diagram.py index 85567de28..df8ffc9ed 100644 --- a/src/braket/circuits/text_diagram_builders/unicode_circuit_diagram.py +++ b/src/braket/circuits/text_diagram_builders/unicode_circuit_diagram.py @@ -90,7 +90,7 @@ def _create_diagram_column( str: a string diagram for the specified moment in time for a column. """ symbols = {qubit: cls._qubit_line_character() for qubit in circuit_qubits} - connections = {qubit: "none" for qubit in circuit_qubits} + connections = dict.fromkeys(circuit_qubits, "none") for item in items: ( @@ -106,7 +106,7 @@ def _create_diagram_column( # Determine if the qubit is part of the item or in the middle of a # multi qubit item. if qubit in target_qubits: - item_qubit_index = [ + item_qubit_index = [ # noqa: RUF015 index for index, q in enumerate(target_qubits) if q == qubit ][0] power_string = ( @@ -132,8 +132,7 @@ def _create_diagram_column( else: symbols[qubit] = "┼" - output = cls._create_output(symbols, connections, circuit_qubits, global_phase) - return output + return cls._create_output(symbols, connections, circuit_qubits, global_phase) @classmethod def _build_parameters( @@ -184,7 +183,7 @@ def _build_parameters( @staticmethod def _update_connections(qubits: QubitSet, connections: dict[Qubit, str]) -> None: if len(qubits) > 1: - connections |= {qubit: "both" for qubit in qubits[1:-1]} + connections |= dict.fromkeys(qubits[1:-1], "both") connections[qubits[-1]] = "above" connections[qubits[0]] = "below" @@ -212,15 +211,15 @@ def _draw_symbol( top = "" bottom = "" if symbol in {"C", "N", "SWAP"}: - if connection in ["above", "both"]: + if connection in {"above", "both"}: top = _fill_symbol(cls._vertical_delimiter(), " ") - if connection in ["below", "both"]: + if connection in {"below", "both"}: bottom = _fill_symbol(cls._vertical_delimiter(), " ") new_symbol = {"C": "●", "N": "◯", "SWAP": "x"} # replace SWAP by x # the size of the moment remains as if there was a box with 4 characters inside symbol = _fill_symbol(new_symbol[symbol], cls._qubit_line_character()) - elif symbol in ["StartVerbatim", "EndVerbatim"]: + elif symbol in {"StartVerbatim", "EndVerbatim"}: top, symbol, bottom = cls._build_verbatim_box(symbol, connection) elif symbol == "┼": top = bottom = _fill_symbol(cls._vertical_delimiter(), " ") @@ -229,7 +228,10 @@ def _draw_symbol( top, symbol, bottom = cls._build_box(symbol, connection) output = f"{_fill_symbol(top, ' ', symbols_width)} \n" - output += f"{_fill_symbol(symbol, cls._qubit_line_character(), symbols_width)}{cls._qubit_line_character()}\n" + output += ( + f"{_fill_symbol(symbol, cls._qubit_line_character(), symbols_width)}" + f"{cls._qubit_line_character()}\n" + ) output += f"{_fill_symbol(bottom, ' ', symbols_width)} \n" return output @@ -237,10 +239,10 @@ def _draw_symbol( def _build_box( symbol: str, connection: Literal["above", "below", "both", "none"] ) -> tuple[str, str, str]: - top_edge_symbol = "┴" if connection in ["above", "both"] else "─" + top_edge_symbol = "┴" if connection in {"above", "both"} else "─" top = f"┌─{_fill_symbol(top_edge_symbol, '─', len(symbol))}─┐" - bottom_edge_symbol = "┬" if connection in ["below", "both"] else "─" + bottom_edge_symbol = "┬" if connection in {"below", "both"} else "─" bottom = f"└─{_fill_symbol(bottom_edge_symbol, '─', len(symbol))}─┘" symbol = f"┤ {symbol} ├" diff --git a/src/braket/circuits/translations.py b/src/braket/circuits/translations.py index 78bb7eed0..e67e3483f 100644 --- a/src/braket/circuits/translations.py +++ b/src/braket/circuits/translations.py @@ -11,8 +11,11 @@ # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. +from __future__ import annotations + +import operator from functools import reduce, singledispatch -from typing import Union +from typing import NoReturn import braket.circuits.gates as braket_gates import braket.circuits.result_types as ResultTypes # noqa: N812 @@ -98,11 +101,11 @@ } -def get_observable(obs: Union[models.Observable, list]) -> Observable: +def get_observable(obs: models.Observable | list) -> Observable: """Gets the observable. Args: - obs (Union[Observable, list]): The observable(s) to get translated. + obs (models.Observable | list): The observable(s) to get translated. Returns: Observable: The translated observable. @@ -111,12 +114,12 @@ def get_observable(obs: Union[models.Observable, list]) -> Observable: @singledispatch -def _get_observable(obs: Union[models.Observable, list]) -> Observable: +def _get_observable(obs: models.Observable | list) -> Observable: raise NotImplementedError @_get_observable.register(list) -def _(obs): +def _(obs: Observable) -> NoReturn: raise NotImplementedError @@ -125,17 +128,17 @@ def _(name: str): return getattr(observables, name.upper())() -def get_tensor_product(observable: Union[models.Observable, list]) -> Observable: +def get_tensor_product(observable: models.Observable | list) -> Observable: """Generate an braket circuit observable Args: - observable (Union[Observable, list]): ir observable or a matrix + observable (Observable | list): ir observable or a matrix Returns: Observable: braket circuit observable """ circuit_observable = [get_observable(obs) for obs in observable] - return reduce(lambda obs1, obs2: obs1 @ obs2, circuit_observable) + return reduce(operator.matmul, circuit_observable) @singledispatch diff --git a/src/braket/devices/device.py b/src/braket/devices/device.py index af3467a40..da3e37fab 100644 --- a/src/braket/devices/device.py +++ b/src/braket/devices/device.py @@ -126,7 +126,7 @@ def _validate_device_noise_model_support(self, noise_model: NoiseModel) -> None: if not noise_operators <= supported_noises: raise ValueError( f"{self.name} does not support noise simulation or the noise model includes noise " - + f"that is not supported by {self.name}." + f"that is not supported by {self.name}." ) def _apply_noise_model_to_circuit( @@ -137,7 +137,8 @@ def _apply_noise_model_to_circuit( if isinstance(instruction.operator, Noise): warnings.warn( "The noise model of the device is applied to a circuit that already has" - " noise instructions." + " noise instructions.", + stacklevel=2, ) break task_specification = self._noise_model.apply(task_specification) @@ -145,6 +146,7 @@ def _apply_noise_model_to_circuit( warnings.warn( "Noise model is only applicable to circuits. The type of the task specification is" f" {task_specification.__class__.__name__}. The noise model of the device does not" - " apply." + " apply.", + stacklevel=2, ) return task_specification diff --git a/src/braket/devices/local_simulator.py b/src/braket/devices/local_simulator.py index f9e70a1ea..557a72d65 100644 --- a/src/braket/devices/local_simulator.py +++ b/src/braket/devices/local_simulator.py @@ -17,7 +17,7 @@ from functools import singledispatchmethod from itertools import repeat from os import cpu_count -from typing import Any, Optional, Union +from typing import Any, Optional from braket.ahs.analog_hamiltonian_simulation import AnalogHamiltonianSimulation from braket.annealing.problem import Problem @@ -59,8 +59,8 @@ class LocalSimulator(Device): def __init__( self, - backend: Union[str, BraketSimulator] = "default", - noise_model: Optional[NoiseModel] = None, + backend: str | BraketSimulator = "default", + noise_model: Optional[NoiseModel] = None, # noqa: UP007 ): """Initializes a `LocalSimulator`. @@ -84,18 +84,20 @@ def __init__( def run( self, - task_specification: Union[ - Circuit, Problem, OpenQASMProgram, AnalogHamiltonianSimulation, SerializableProgram - ], + task_specification: Circuit + | Problem + | OpenQASMProgram + | AnalogHamiltonianSimulation + | SerializableProgram, shots: int = 0, - inputs: Optional[dict[str, float]] = None, + inputs: Optional[dict[str, float]] = None, # noqa: UP007 *args: Any, **kwargs: Any, ) -> LocalQuantumTask: """Runs the given task with the wrapped local simulator. Args: - task_specification (Union[Circuit, Problem, OpenQASMProgram, AnalogHamiltonianSimulation, SerializableProgram]): # noqa E501 + task_specification (Union[Circuit, Problem, OpenQASMProgram, AnalogHamiltonianSimulation, SerializableProgram]): The quantum task specification. shots (int): The number of times to run the circuit or annealing problem. Default is 0, which means that the simulator will compute the exact @@ -119,32 +121,26 @@ def run( >>> circuit = Circuit().h(0).cnot(0, 1) >>> device = LocalSimulator("default") >>> device.run(circuit, shots=1000) - """ + """ # noqa: E501 if self._noise_model: task_specification = self._apply_noise_model_to_circuit(task_specification) payload = self._construct_payload(task_specification, inputs, shots) result = self._delegate.run(payload, *args, shots=shots, **kwargs) return LocalQuantumTask(self._to_result_object(result)) - def run_batch( # noqa: C901 + def run_batch( self, - task_specifications: Union[ - Union[ - Circuit, Problem, OpenQASMProgram, AnalogHamiltonianSimulation, SerializableProgram - ], - list[ - Union[ - Circuit, - Problem, - OpenQASMProgram, - AnalogHamiltonianSimulation, - SerializableProgram, - ] - ], + task_specifications: Circuit + | Problem + | OpenQASMProgram + | AnalogHamiltonianSimulation + | SerializableProgram + | list[ + Circuit | Problem | OpenQASMProgram | AnalogHamiltonianSimulation | SerializableProgram ], - shots: Optional[int] = 0, - max_parallel: Optional[int] = None, - inputs: Optional[Union[dict[str, float], list[dict[str, float]]]] = None, + shots: int | None = 0, + max_parallel: int | None = None, + inputs: dict[str, float] | list[dict[str, float]] | None = None, *args, **kwargs, ) -> LocalQuantumTaskBatch: @@ -166,7 +162,7 @@ def run_batch( # noqa: C901 See Also: `braket.tasks.local_quantum_task_batch.LocalQuantumTaskBatch` - """ # noqa E501 + """ # noqa: E501 inputs = inputs or {} if self._noise_model: @@ -206,8 +202,7 @@ def run_batch( # noqa: C901 param_names = {param.name for param in task_specification.parameters} if unbounded_parameters := param_names - set(input_map.keys()): raise ValueError( - f"Cannot execute circuit with unbound parameters: " - f"{unbounded_parameters}" + f"Cannot execute circuit with unbound parameters: {unbounded_parameters}" ) payloads.append(self._construct_payload(task_specification, input_map, shots)) @@ -241,7 +236,7 @@ def _get_simulator(self, simulator: Any) -> BraketSimulator: raise TypeError("Simulator must either be a string or a BraketSimulator instance") @_get_simulator.register - def _(self, backend_name: str): + def _(self, backend_name: str) -> BraketSimulator: if backend_name not in _simulator_devices: raise ValueError( f"Only the following devices are available {_simulator_devices.keys()}" @@ -250,33 +245,33 @@ def _(self, backend_name: str): return device_class() @_get_simulator.register - def _(self, backend_impl: BraketSimulator): + def _(self, backend_impl: BraketSimulator) -> BraketSimulator: return backend_impl @singledispatchmethod def _construct_payload( self, task_specification: Any, - inputs: Optional[dict[str, float]], - shots: Optional[int], + inputs: dict[str, float] | None, + shots: int | None, ) -> Any: raise NotImplementedError(f"Unsupported task type {type(task_specification)}") @_construct_payload.register - def _(self, circuit: Circuit, inputs: Optional[dict[str, float]], shots: Optional[int]): + def _(self, circuit: Circuit, inputs: Optional[dict[str, float]], shots: Optional[int]): # noqa: UP007 simulator = self._delegate if DeviceActionType.OPENQASM in simulator.properties.action: validate_circuit_and_shots(circuit, shots) program = circuit.to_ir(ir_type=IRType.OPENQASM) program.inputs.update(inputs or {}) return program - elif DeviceActionType.JAQCD in simulator.properties.action: + if DeviceActionType.JAQCD in simulator.properties.action: validate_circuit_and_shots(circuit, shots) return circuit.to_ir(ir_type=IRType.JAQCD) raise NotImplementedError(f"{type(simulator)} does not support qubit gate-based programs") @_construct_payload.register - def _(self, program: OpenQASMProgram, inputs: Optional[dict[str, float]], _shots): + def _(self, program: OpenQASMProgram, inputs: Optional[dict[str, float]], _shots: int): # noqa: UP007 simulator = self._delegate if DeviceActionType.OPENQASM not in simulator.properties.action: raise NotImplementedError(f"{type(simulator)} does not support OpenQASM programs") @@ -290,12 +285,12 @@ def _(self, program: OpenQASMProgram, inputs: Optional[dict[str, float]], _shots return program @_construct_payload.register - def _(self, program: SerializableProgram, inputs: Optional[dict[str, float]], _shots): + def _(self, program: SerializableProgram, inputs: Optional[dict[str, float]], _shots: int): # noqa: UP007 inputs_copy = inputs.copy() if inputs is not None else {} return OpenQASMProgram(source=program.to_ir(ir_type=IRType.OPENQASM), inputs=inputs_copy) @_construct_payload.register - def _(self, program: AnalogHamiltonianSimulation, _inputs, _shots): + def _(self, program: AnalogHamiltonianSimulation, _inputs: dict[str, float], _shots: int): simulator = self._delegate if DeviceActionType.AHS not in simulator.properties.action: raise NotImplementedError( @@ -304,7 +299,7 @@ def _(self, program: AnalogHamiltonianSimulation, _inputs, _shots): return program.to_ir() @_construct_payload.register - def _(self, program: AHSProgram, _inputs, _shots): + def _(self, program: AHSProgram, _inputs: dict[str, float], _shots: int): simulator = self._delegate if DeviceActionType.AHS not in simulator.properties.action: raise NotImplementedError( @@ -313,7 +308,7 @@ def _(self, program: AHSProgram, _inputs, _shots): return program @_construct_payload.register - def _(self, problem: Problem, _inputs, _shots): + def _(self, problem: Problem, _inputs: dict[str, float], _shots: int): simulator = self._delegate if DeviceActionType.ANNEALING not in simulator.properties.action: raise NotImplementedError( @@ -326,17 +321,19 @@ def _to_result_object(self, result: Any) -> Any: raise NotImplementedError(f"Unsupported task result type {type(result)}") @_to_result_object.register - def _(self, result: GateModelQuantumTaskResult): + def _(self, result: GateModelQuantumTaskResult) -> GateModelQuantumTaskResult: return result @_to_result_object.register - def _(self, result: GateModelTaskResult): + def _(self, result: GateModelTaskResult) -> GateModelQuantumTaskResult: return GateModelQuantumTaskResult.from_object(result) @_to_result_object.register - def _(self, result: AnalogHamiltonianSimulationTaskResult): + def _( + self, result: AnalogHamiltonianSimulationTaskResult + ) -> AnalogHamiltonianSimulationQuantumTaskResult: return AnalogHamiltonianSimulationQuantumTaskResult.from_object(result) @_to_result_object.register - def _(self, result: AnnealingTaskResult): + def _(self, result: AnnealingTaskResult) -> AnnealingQuantumTaskResult: return AnnealingQuantumTaskResult.from_object(result) diff --git a/src/braket/jobs/data_persistence.py b/src/braket/jobs/data_persistence.py index 0386ed7a7..607901a3a 100644 --- a/src/braket/jobs/data_persistence.py +++ b/src/braket/jobs/data_persistence.py @@ -58,7 +58,7 @@ def save_job_checkpoint( if checkpoint_file_suffix else f"{checkpoint_directory}/{job_name}.json" ) - with open(checkpoint_file_path, "w") as f: + with open(checkpoint_file_path, "w", encoding="utf-8") as f: serialized_data = serialize_values(checkpoint_data or {}, data_format) persisted_data = PersistedJobData(dataDictionary=serialized_data, dataFormat=data_format) f.write(persisted_data.json()) @@ -102,18 +102,15 @@ def load_job_checkpoint( if checkpoint_file_suffix else f"{checkpoint_directory}/{job_name}.json" ) - with open(checkpoint_file_path) as f: + with open(checkpoint_file_path, encoding="utf-8") as f: persisted_data = PersistedJobData.parse_raw(f.read()) - deserialized_data = deserialize_values( - persisted_data.dataDictionary, persisted_data.dataFormat - ) - return deserialized_data + return deserialize_values(persisted_data.dataDictionary, persisted_data.dataFormat) def _load_persisted_data(filename: str | Path | None = None) -> PersistedJobData: filename = filename or Path(get_results_dir()) / "results.json" try: - with open(filename) as f: + with open(filename, encoding="utf-8") as f: return PersistedJobData.parse_raw(f.read()) except FileNotFoundError: return PersistedJobData( @@ -134,8 +131,7 @@ def load_job_result(filename: str | Path | None = None) -> dict[str, Any]: dict[str, Any]: Job result data of current job """ persisted_data = _load_persisted_data(filename) - deserialized_data = deserialize_values(persisted_data.dataDictionary, persisted_data.dataFormat) - return deserialized_data + return deserialize_values(persisted_data.dataDictionary, persisted_data.dataFormat) def save_job_result( @@ -186,7 +182,7 @@ def save_job_result( ) updated_results = current_results | result_data - with open(Path(get_results_dir()) / "results.json", "w") as f: + with open(Path(get_results_dir()) / "results.json", "w", encoding="utf-8") as f: serialized_data = serialize_values(updated_results or {}, data_format) persisted_data = PersistedJobData(dataDictionary=serialized_data, dataFormat=data_format) f.write(persisted_data.json()) diff --git a/src/braket/jobs/environment_variables.py b/src/braket/jobs/environment_variables.py index 6d7d18364..8d3fc3f97 100644 --- a/src/braket/jobs/environment_variables.py +++ b/src/braket/jobs/environment_variables.py @@ -72,6 +72,6 @@ def get_hyperparameters() -> dict[str, str]: dict[str, str]: The hyperparameters of the job. """ if "AMZN_BRAKET_HP_FILE" in os.environ: - with open(os.getenv("AMZN_BRAKET_HP_FILE")) as f: + with open(os.getenv("AMZN_BRAKET_HP_FILE"), encoding="utf-8") as f: return json.load(f) return {} diff --git a/src/braket/jobs/hybrid_job.py b/src/braket/jobs/hybrid_job.py index 77f5f43d0..3b6b62d56 100644 --- a/src/braket/jobs/hybrid_job.py +++ b/src/braket/jobs/hybrid_job.py @@ -178,18 +178,19 @@ def job_wrapper(*args: Any, **kwargs: Any) -> Callable: Returns: Callable: the callable for creating a Hybrid Job. """ - with _IncludeModules(include_modules), tempfile.TemporaryDirectory( - dir="", prefix="decorator_job_" - ) as temp_dir: + with ( + _IncludeModules(include_modules), + tempfile.TemporaryDirectory(dir="", prefix="decorator_job_") as temp_dir, + ): temp_dir_path = Path(temp_dir) entry_point_file_path = Path("entry_point.py") - with open(temp_dir_path / entry_point_file_path, "w") as entry_point_file: - template = "\n".join( - [ - _process_input_data(input_data), - _serialize_entry_point(entry_point, args, kwargs), - ] - ) + with open( + temp_dir_path / entry_point_file_path, "w", encoding="utf-8" + ) as entry_point_file: + template = "\n".join([ + _process_input_data(input_data), + _serialize_entry_point(entry_point, args, kwargs), + ]) entry_point_file.write(template) if dependencies: @@ -221,12 +222,8 @@ def job_wrapper(*args: Any, **kwargs: Any) -> Callable: "quiet": quiet, "reservation_arn": reservation_arn, } - for key, value in optional_args.items(): - if value is not None: - job_args[key] = value - - job = _create_job(job_args, local) - return job + job_args.update({key: val for key, val in optional_args.items() if val is not None}) + return _create_job(job_args, local) return job_wrapper @@ -264,12 +261,12 @@ def _process_dependencies(dependencies: str | Path | list[str], temp_dir: Path) shutil.copy(Path(dependencies).resolve(), temp_dir / "requirements.txt") else: # list of packages - with open(temp_dir / "requirements.txt", "w") as f: + with open(temp_dir / "requirements.txt", "w", encoding="utf-8") as f: f.write("\n".join(dependencies)) class _IncludeModules: - def __init__(self, modules: str | ModuleType | Iterable[str | ModuleType] = None): + def __init__(self, modules: str | ModuleType | Iterable[str | ModuleType] | None = None): modules = modules or [] if isinstance(modules, (str, ModuleType)): modules = [modules] @@ -283,7 +280,7 @@ def __enter__(self): for module in self._modules: cloudpickle.register_pickle_by_value(module) - def __exit__(self, exc_type, exc_val, exc_tb): + def __exit__(self, exc_type, exc_val, exc_tb): # noqa: ANN001 """Unregister included modules with cloudpickle to be pickled by value""" for module in self._modules: cloudpickle.unregister_pickle_by_value(module) @@ -317,10 +314,10 @@ def _log_hyperparameters(entry_point: Callable, args: tuple, kwargs: dict) -> di hyperparameters = {} for param, value in bound_args.arguments.items(): param_kind = signature.parameters[param].kind - if param_kind in [ + if param_kind in { inspect.Parameter.POSITIONAL_OR_KEYWORD, inspect.Parameter.KEYWORD_ONLY, - ]: + }: hyperparameters[param] = value elif param_kind == inspect.Parameter.VAR_KEYWORD: hyperparameters.update(**value) @@ -351,7 +348,7 @@ def _sanitize(hyperparameter: Any) -> str: # max allowed length for a hyperparameter is 2500 if len(sanitized) > 2500: # show as much as possible, including the final 20 characters - return f"{sanitized[:2500 - 23]}...{sanitized[-20:]}" + return f"{sanitized[: 2500 - 23]}...{sanitized[-20:]}" return sanitized @@ -408,7 +405,7 @@ def is_prefix(path: str) -> bool: def _create_job(job_args: dict[str, Any], local: bool = False) -> QuantumJob: """Create an AWS or Local hybrid job""" if local: - from braket.jobs.local import LocalQuantumJob + from braket.jobs.local import LocalQuantumJob # noqa: PLC0415 for aws_only_arg in [ "wait_until_complete", @@ -419,10 +416,8 @@ def _create_job(job_args: dict[str, Any], local: bool = False) -> QuantumJob: "tags", "logger", ]: - if aws_only_arg in job_args: - del job_args[aws_only_arg] + job_args.pop(aws_only_arg, None) return LocalQuantumJob.create(**job_args) - else: - from braket.aws import AwsQuantumJob + from braket.aws import AwsQuantumJob # noqa: PLC0415 - return AwsQuantumJob.create(**job_args) + return AwsQuantumJob.create(**job_args) diff --git a/src/braket/jobs/image_uris.py b/src/braket/jobs/image_uris.py index af6c5012a..213d06553 100644 --- a/src/braket/jobs/image_uris.py +++ b/src/braket/jobs/image_uris.py @@ -70,7 +70,7 @@ def _config_for_framework(framework: Framework) -> dict[str, str]: dict[str, str]: Dict that contains the configuration for the specified framework. """ fname = os.path.join(os.path.dirname(__file__), "image_uri_config", f"{framework.lower()}.json") - with open(fname) as f: + with open(fname, encoding="utf-8") as f: return json.load(f) diff --git a/src/braket/jobs/local/local_job.py b/src/braket/jobs/local/local_job.py index 4dd15607a..cac12a097 100644 --- a/src/braket/jobs/local/local_job.py +++ b/src/braket/jobs/local/local_job.py @@ -158,7 +158,7 @@ def create( env_variables = setup_container(container, session, **create_job_kwargs) container.run_local_job(env_variables) container.copy_from("/opt/ml/model", job_name) - with open(os.path.join(job_name, "log.txt"), "w") as log_file: + with open(os.path.join(job_name, "log.txt"), "w", encoding="utf-8") as log_file: log_file.write(container.run_log) if "checkpointConfig" in create_job_kwargs: checkpoint_config = create_job_kwargs["checkpointConfig"] @@ -209,7 +209,7 @@ def run_log(self) -> str: """ if not self._run_log: try: - with open(os.path.join(self.name, "log.txt")) as log_file: + with open(os.path.join(self.name, "log.txt"), encoding="utf-8") as log_file: self._run_log = log_file.read() except FileNotFoundError as e: raise ValueError( @@ -289,12 +289,9 @@ def result( dict[str, Any]: Dict specifying the hybrid job results. """ try: - with open(os.path.join(self.name, "results.json")) as f: + with open(os.path.join(self.name, "results.json"), encoding="utf-8") as f: persisted_data = PersistedJobData.parse_raw(f.read()) - deserialized_data = deserialize_values( - persisted_data.dataDictionary, persisted_data.dataFormat - ) - return deserialized_data + return deserialize_values(persisted_data.dataDictionary, persisted_data.dataFormat) except FileNotFoundError as e: raise ValueError( f"Unable to find results in the local job directory {self.name}." diff --git a/src/braket/jobs/local/local_job_container.py b/src/braket/jobs/local/local_job_container.py index 6d9d08f4f..13eb90e43 100644 --- a/src/braket/jobs/local/local_job_container.py +++ b/src/braket/jobs/local/local_job_container.py @@ -60,7 +60,7 @@ def __enter__(self): self._container_name = self._start_container(self.image_uri, self._force_update) return self - def __exit__(self, exc_type, exc_val, exc_tb): + def __exit__(self, exc_type, exc_val, exc_tb): # noqa: ANN001 """Stops and removes the local docker container.""" self._end_session() @@ -79,9 +79,8 @@ def _envs_to_list(environment_variables: dict[str, str]) -> list[str]: provided environment variables as part of the runtime. """ env_list = [] - for key in environment_variables: - env_list.append("-e") - env_list.append(f"{key}={environment_variables[key]}") + for key, val in environment_variables.items(): + env_list.extend(("-e", f"{key}={val}")) return env_list @staticmethod @@ -174,9 +173,16 @@ def _start_container(self, image_uri: str, force_update: bool) -> str: except ValueError: self._logger.warning(f"Unable to update {image_uri}.") - return self._check_output_formatted( - ["docker", "run", "-d", "--rm", image_name, "tail", "-f", "/dev/null"] - ) + return self._check_output_formatted([ + "docker", + "run", + "-d", + "--rm", + image_name, + "tail", + "-f", + "/dev/null", + ]) def makedir(self, dir_path: str) -> None: """Creates a directory path in the container. @@ -188,13 +194,18 @@ def makedir(self, dir_path: str) -> None: subprocess.CalledProcessError: If unable to make the directory. """ try: - subprocess.check_output( - ["docker", "exec", self._container_name, "mkdir", "-p", dir_path] - ) + subprocess.check_output([ + "docker", + "exec", + self._container_name, + "mkdir", + "-p", + dir_path, + ]) except subprocess.CalledProcessError as e: output = e.output.decode("utf-8").strip() - self._logger.error(output) - raise e + self._logger.exception(output) + raise def copy_to(self, source: str, destination: str) -> None: """Copies a local file or directory to the container. @@ -208,16 +219,24 @@ def copy_to(self, source: str, destination: str) -> None: """ dirname = str(PurePosixPath(destination).parent) try: - subprocess.check_output( - ["docker", "exec", self._container_name, "mkdir", "-p", dirname] - ) - subprocess.check_output( - ["docker", "cp", source, f"{self._container_name}:{destination}"] - ) + subprocess.check_output([ + "docker", + "exec", + self._container_name, + "mkdir", + "-p", + dirname, + ]) + subprocess.check_output([ + "docker", + "cp", + source, + f"{self._container_name}:{destination}", + ]) except subprocess.CalledProcessError as e: output = e.output.decode("utf-8").strip() - self._logger.error(output) - raise e + self._logger.exception(output) + raise def copy_from(self, source: str, destination: str) -> None: """Copies a file or directory from the container locally. @@ -230,13 +249,16 @@ def copy_from(self, source: str, destination: str) -> None: subprocess.CalledProcessError: If unable to copy. """ try: - subprocess.check_output( - ["docker", "cp", f"{self._container_name}:{source}", destination] - ) + subprocess.check_output([ + "docker", + "cp", + f"{self._container_name}:{source}", + destination, + ]) except subprocess.CalledProcessError as e: output = e.output.decode("utf-8").strip() - self._logger.error(output) - raise e + self._logger.exception(output) + raise def run_local_job( self, @@ -251,9 +273,13 @@ def run_local_job( Raises: ValueError: `start_program_name` is not found. """ - start_program_name = self._check_output_formatted( - ["docker", "exec", self._container_name, "printenv", "SAGEMAKER_PROGRAM"] - ) + start_program_name = self._check_output_formatted([ + "docker", + "exec", + self._container_name, + "printenv", + "SAGEMAKER_PROGRAM", + ]) if not start_program_name: raise ValueError( "Start program not found. " @@ -263,16 +289,14 @@ def run_local_job( command = ["docker", "exec", "-w", self.CONTAINER_CODE_PATH] command.extend(self._envs_to_list(environment_variables)) - command.append(self._container_name) - command.append("python") - command.append(start_program_name) + command.extend((self._container_name, "python", start_program_name)) try: process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) self.run_log = _stream_output(process) except Exception as e: self.run_log = e - self._logger.error(e) + self._logger.exception(e) # noqa: TRY401 def _end_session(self) -> None: """Stops and removes the local container.""" diff --git a/src/braket/jobs/local/local_job_container_setup.py b/src/braket/jobs/local/local_job_container_setup.py index 65cef387c..c3e68c51e 100644 --- a/src/braket/jobs/local/local_job_container_setup.py +++ b/src/braket/jobs/local/local_job_container_setup.py @@ -181,7 +181,7 @@ def _copy_hyperparameters(container: _LocalJobContainer, **creation_kwargs: str) hyperparameters = creation_kwargs["hyperParameters"] with tempfile.TemporaryDirectory() as temp_dir: file_path = Path(temp_dir, "hyperparameters.json") - with open(file_path, "w") as write_file: + with open(file_path, "w", encoding="utf-8") as write_file: json.dump(hyperparameters, write_file) container.copy_to(str(file_path), "/opt/ml/input/config/hyperparameters.json") return True diff --git a/src/braket/jobs/logs.py b/src/braket/jobs/logs.py index 9aa7dfaca..45951d646 100644 --- a/src/braket/jobs/logs.py +++ b/src/braket/jobs/logs.py @@ -11,7 +11,6 @@ # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. -import collections import os import sys from collections.abc import Generator @@ -21,13 +20,20 @@ # Support for reading logs # ############################################################################## -from typing import ClassVar, Optional +from typing import ClassVar, NamedTuple, Optional from botocore.exceptions import ClientError from braket.aws.aws_session import AwsSession +# Position is a tuple that includes the last read timestamp and the number of items that were read +# at that time. This is used to figure out which event to start with on the next read. +class Position(NamedTuple): + timestamp: str + skip: bool + + class ColorWrap: """A callable that prints text in a different color depending on the instance. Up to 5 if the standard output is a terminal or a Jupyter notebook cell. @@ -68,11 +74,6 @@ def _color_wrap(self, index: int, s: str) -> None: print(f"\x1b[{self._stream_colors[index % len(self._stream_colors)]}m{s}\x1b[0m") -# Position is a tuple that includes the last read timestamp and the number of items that were read -# at that time. This is used to figure out which event to start with on the next read. -Position = collections.namedtuple("Position", ["timestamp", "skip"]) - - def multi_stream_iter( aws_session: AwsSession, log_group: str, streams: list[str], positions: dict[str, Position] ) -> Generator[tuple[int, dict]]: @@ -99,7 +100,7 @@ def multi_stream_iter( for s in event_iters: try: events.append(next(s)) - except StopIteration: + except StopIteration: # noqa: PERF203 events.append(None) while any(events): @@ -149,12 +150,12 @@ def log_stream( events = events[skip:] skip = 0 else: - skip = skip - event_count + skip -= event_count events = [] yield from events -def flush_log_streams( # noqa C901 +def flush_log_streams( aws_session: AwsSession, log_group: str, stream_prefix: str, diff --git a/src/braket/jobs/metrics.py b/src/braket/jobs/metrics.py index 991370f35..5e58b4995 100644 --- a/src/braket/jobs/metrics.py +++ b/src/braket/jobs/metrics.py @@ -10,28 +10,28 @@ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. +from __future__ import annotations import time -from typing import Optional, Union def log_metric( metric_name: str, - value: Union[float, int], - timestamp: Optional[float] = None, - iteration_number: Optional[int] = None, + value: float, + timestamp: float | None = None, + iteration_number: int | None = None, ) -> None: """Records Braket Hybrid Job metrics. Args: metric_name (str): The name of the metric. - value (Union[float, int]): The value of the metric. + value (float): The value of the metric. - timestamp (Optional[float]): The time the metric data was received, expressed + timestamp (float | None): The time the metric data was received, expressed as the number of seconds since the epoch. Default: Current system time. - iteration_number (Optional[int]): The iteration number of the metric. + iteration_number (int | None): The iteration number of the metric. """ logged_timestamp = timestamp or time.time() metric_list = [f"Metrics - timestamp={logged_timestamp}; {metric_name}={value};"] diff --git a/src/braket/jobs/metrics_data/cwl_insights_metrics_fetcher.py b/src/braket/jobs/metrics_data/cwl_insights_metrics_fetcher.py index 8f5d3dcd5..f092163a9 100644 --- a/src/braket/jobs/metrics_data/cwl_insights_metrics_fetcher.py +++ b/src/braket/jobs/metrics_data/cwl_insights_metrics_fetcher.py @@ -15,7 +15,7 @@ import time from logging import Logger, getLogger -from typing import Any, Optional, Union +from typing import Any from braket.aws.aws_session import AwsSession from braket.jobs.metrics_data.definitions import MetricStatistic, MetricType @@ -52,9 +52,7 @@ def __init__( self._logs_client = aws_session.logs_client @staticmethod - def _get_element_from_log_line( - element_name: str, log_line: list[dict[str, Any]] - ) -> Optional[str]: + def _get_element_from_log_line(element_name: str, log_line: list[dict[str, Any]]) -> str | None: """Finds and returns an element of a log line from CloudWatch Insights results. Args: @@ -85,12 +83,11 @@ def _get_metrics_results_sync(self, query_id: str) -> list[Any]: while time.time() < timeout_time: response = self._logs_client.get_query_results(queryId=query_id) query_status = response["status"] - if query_status in ["Failed", "Cancelled"]: + if query_status in {"Failed", "Cancelled"}: raise MetricsRetrievalError(f"Query {query_id} failed with status {query_status}.") - elif query_status == "Complete": + if query_status == "Complete": return response["results"] - else: - time.sleep(self._poll_interval_seconds) + time.sleep(self._poll_interval_seconds) self._logger.warning(f"Timed out waiting for query {query_id}.") return [] @@ -111,7 +108,7 @@ def _parse_log_line(self, result_entry: list[dict[str, Any]], parser: LogMetrics def _parse_log_query_results( self, results: list[Any], metric_type: MetricType, statistic: MetricStatistic - ) -> dict[str, list[Union[str, float, int]]]: + ) -> dict[str, list[str | float | int]]: """Parses CloudWatch Insights results and returns all found metrics. Args: @@ -137,7 +134,7 @@ def get_metrics_for_job( job_start_time: int | None = None, job_end_time: int | None = None, stream_prefix: str | None = None, - ) -> dict[str, list[Union[str, float, int]]]: + ) -> dict[str, list[str | float | int]]: """Synchronously retrieves all the algorithm metrics logged by a given Hybrid Job. Args: diff --git a/src/braket/jobs/metrics_data/cwl_metrics_fetcher.py b/src/braket/jobs/metrics_data/cwl_metrics_fetcher.py index e8da4ff89..b6e331142 100644 --- a/src/braket/jobs/metrics_data/cwl_metrics_fetcher.py +++ b/src/braket/jobs/metrics_data/cwl_metrics_fetcher.py @@ -109,9 +109,7 @@ def _get_log_streams_for_job(self, job_name: str, timeout_time: float) -> list[s while time.time() < timeout_time: response = self._logs_client.describe_log_streams(**kwargs) if streams := response.get("logStreams"): - for stream in streams: - if name := stream.get("logStreamName"): - log_streams.append(name) + log_streams = [name for stream in streams if (name := stream.get("logStreamName"))] if next_token := response.get("nextToken"): kwargs["nextToken"] = next_token else: diff --git a/src/braket/jobs/metrics_data/log_metrics_parser.py b/src/braket/jobs/metrics_data/log_metrics_parser.py index 1ff5b4d49..0d30ef1ec 100644 --- a/src/braket/jobs/metrics_data/log_metrics_parser.py +++ b/src/braket/jobs/metrics_data/log_metrics_parser.py @@ -11,10 +11,11 @@ # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. +from __future__ import annotations + import re from collections.abc import Iterator from logging import Logger, getLogger -from typing import Optional, Union from braket.jobs.metrics_data.definitions import MetricStatistic, MetricType @@ -39,21 +40,21 @@ def __init__( @staticmethod def _get_value( - current_value: Optional[Union[str, float, int]], - new_value: Union[str, float, int], + current_value: str | float | None, + new_value: str | float, statistic: MetricStatistic, - ) -> Union[str, float, int]: + ) -> str | float: """Gets the value based on a statistic. Args: - current_value (Optional[Union[str, float, int]]): The current value. + current_value ( str | float | None): The current value. - new_value (Union[str, float, int]): The new value. + new_value ( str | float): The new value. statistic (MetricStatistic): The statistic to determine which value to use. Returns: - Union[str, float, int]: the value. + str | float: the value. """ if current_value is None: return new_value @@ -61,16 +62,14 @@ def _get_value( return max(current_value, new_value) return min(current_value, new_value) - def _get_metrics_from_log_line_matches( - self, all_matches: Iterator - ) -> dict[str, Union[str, float, int]]: + def _get_metrics_from_log_line_matches(self, all_matches: Iterator) -> dict[str | float]: """Converts matches from a RegEx to a set of metrics. Args: all_matches (Iterator): An iterator for RegEx matches on a log line. Returns: - dict[str, Union[str, float, int]]: The set of metrics found by the RegEx. The result + dict[str, | float]: The set of metrics found by the RegEx. The result is in the format { : }. This implies that multiple metrics with the same name are deduped to the last instance of that metric. """ @@ -107,7 +106,7 @@ def parse_log_message(self, timestamp: str, message: str) -> None: def get_columns_and_pivot_indices( self, pivot: str - ) -> tuple[dict[str, list[Union[str, float, int]]], dict[tuple[int, str], int]]: + ) -> tuple[dict[str, list[str | float]], dict[tuple[int, str], int]]: """Parses the metrics to find all the metrics that have the pivot column. The values of the pivot column are paired with the node_id and assigned a row index, so that all metrics with the same pivot value and node_id are stored in the same row. @@ -116,7 +115,7 @@ def get_columns_and_pivot_indices( pivot (str): The name of the pivot column. Must be TIMESTAMP or ITERATION_NUMBER. Returns: - tuple[dict[str, list[Union[str, float, int]]], dict[tuple[int, str], int]]: Contains: + tuple[dict[str, list[str | float]], dict[tuple[int, str], int]]: Contains: The dict[str, list[Any]] is the result table with all the metrics values initialized to None. The dict[tuple[int, str], int] is the list of pivot indices, where the value of a @@ -124,7 +123,7 @@ def get_columns_and_pivot_indices( """ row_count = 0 pivot_indices: dict[int, int] = {} - table: dict[str, list[Optional[Union[str, float, int]]]] = {} + table: dict[str, list[str | float | None]] = {} for metric in self.all_metrics: if pivot in metric: # If no node_id is present, pair pivot value with None for the key. @@ -140,7 +139,7 @@ def get_columns_and_pivot_indices( def get_metric_data_with_pivot( self, pivot: str, statistic: MetricStatistic - ) -> dict[str, list[Union[str, float, int]]]: + ) -> dict[str, list[str | float]]: """Gets the metric data for a given pivot column name. Metrics without the pivot column are not included in the results. Metrics that have the same value in the pivot column from the same node are returned in the same row. Metrics from different nodes are stored @@ -164,7 +163,7 @@ def get_metric_data_with_pivot( statistic (MetricStatistic): The statistic to determine which value to use. Returns: - dict[str, list[Union[str, float, int]]]: The metrics data. + dict[str, list[str | float]]: The metrics data. """ table, pivot_indices = self.get_columns_and_pivot_indices(pivot) for metric in self.all_metrics: @@ -179,7 +178,7 @@ def get_metric_data_with_pivot( def get_parsed_metrics( self, metric_type: MetricType, statistic: MetricStatistic - ) -> dict[str, list[Union[str, float, int]]]: + ) -> dict[str, list[str | float]]: """Gets all the metrics data, where the keys are the column names and the values are a list containing the values in each row. @@ -190,7 +189,7 @@ def get_parsed_metrics( when there is a conflict. Returns: - dict[str, list[Union[str, float, int]]]: The metrics data. + dict[str, list[str | float]]: The metrics data. Example: timestamp energy diff --git a/src/braket/jobs/quantum_job_creation.py b/src/braket/jobs/quantum_job_creation.py index 3c4a01b5c..75ce4437e 100644 --- a/src/braket/jobs/quantum_job_creation.py +++ b/src/braket/jobs/quantum_job_creation.py @@ -279,8 +279,8 @@ def _generate_default_job_name( elif not image_uri: name = "braket-job-default" else: - job_type_match = re.search("/amazon-braket-(.*)-jobs:", image_uri) or re.search( - "/amazon-braket-([^:/]*)", image_uri + job_type_match = re.search(r"/amazon-braket-(.*)-jobs:", image_uri) or re.search( + r"/amazon-braket-([^:/]*)", image_uri ) container = f"-{job_type_match.groups()[0]}" if job_type_match else "" name = f"braket-job{container}" @@ -361,7 +361,7 @@ def _validate_entry_point(source_module_path: Path, entry_point: str) -> None: importlib.invalidate_caches() module = importlib.util.find_spec(importable, source_module_path.stem) if module is None: - raise AssertionError + raise AssertionError # noqa: TRY301 except (ModuleNotFoundError, AssertionError) as e: raise ValueError(f"Entry point module was not found: {importable}") from e finally: diff --git a/src/braket/jobs/serialization.py b/src/braket/jobs/serialization.py index 179a44970..c28510494 100644 --- a/src/braket/jobs/serialization.py +++ b/src/braket/jobs/serialization.py @@ -59,7 +59,7 @@ def deserialize_values( the specified `data_format` to plaintext. """ return ( - {k: pickle.loads(codecs.decode(v.encode(), "base64")) for k, v in data_dictionary.items()} + {k: pickle.loads(codecs.decode(v.encode(), "base64")) for k, v in data_dictionary.items()} # noqa: S301 if data_format == PersistedJobDataFormat.PICKLED_V4 else data_dictionary ) diff --git a/src/braket/parametric/free_parameter.py b/src/braket/parametric/free_parameter.py index 8f437bbca..7db9f7012 100644 --- a/src/braket/parametric/free_parameter.py +++ b/src/braket/parametric/free_parameter.py @@ -14,7 +14,6 @@ from __future__ import annotations from numbers import Number -from typing import Union from sympy import Symbol @@ -108,7 +107,7 @@ def __init__(self, name: str): Examples: >>> param1 = FreeParameter("theta") - >>> param1 = FreeParameter("\u03B8") + >>> param1 = FreeParameter("\u03b8") """ self._set_name(name) super().__init__(expression=self._name) @@ -118,7 +117,7 @@ def name(self) -> str: """str: Name of this parameter.""" return self._name.name - def subs(self, parameter_values: dict[str, Number]) -> Union[FreeParameter, Number]: + def subs(self, parameter_values: dict[str, Number]) -> FreeParameter | Number: """Substitutes a value in if the parameter exists within the mapping. Args: diff --git a/src/braket/parametric/free_parameter_expression.py b/src/braket/parametric/free_parameter_expression.py index fdd2f5474..43221d35f 100644 --- a/src/braket/parametric/free_parameter_expression.py +++ b/src/braket/parametric/free_parameter_expression.py @@ -17,7 +17,7 @@ import operator from functools import reduce from numbers import Number -from typing import Any, Union +from typing import Any import sympy from oqpy.base import OQPyExpression @@ -33,7 +33,7 @@ class FreeParameterExpression: present will NOT run. Values must be substituted prior to execution. """ - def __init__(self, expression: Union[FreeParameterExpression, Number, sympy.Expr, str]): + def __init__(self, expression: FreeParameterExpression | Number | sympy.Expr | str): """Initializes a FreeParameterExpression. Best practice is to initialize using FreeParameters and Numbers. Not meant to be initialized directly. @@ -67,7 +67,7 @@ def __init__(self, expression: Union[FreeParameterExpression, Number, sympy.Expr raise NotImplementedError @property - def expression(self) -> Union[Number, sympy.Expr]: + def expression(self) -> Number | sympy.Expr: """Gets the expression. Returns: @@ -77,7 +77,7 @@ def expression(self) -> Union[Number, sympy.Expr]: def subs( self, parameter_values: dict[str, Number] - ) -> Union[FreeParameterExpression, Number, sympy.Expr]: + ) -> FreeParameterExpression | Number | sympy.Expr: """ Similar to a substitution in Sympy. Parameters are swapped for corresponding values or expressions from the dictionary. @@ -100,8 +100,7 @@ def subs( subbed_expr = self._expression.subs(new_parameter_values) if isinstance(subbed_expr, Number): return subbed_expr - else: - return FreeParameterExpression(subbed_expr) + return FreeParameterExpression(subbed_expr) def _parse_string_expression(self, expression: str) -> FreeParameterExpression: return self._eval_operation(ast.parse(expression, mode="eval").body) @@ -109,26 +108,24 @@ def _parse_string_expression(self, expression: str) -> FreeParameterExpression: def _eval_operation(self, node: Any) -> FreeParameterExpression: if isinstance(node, ast.Constant): return FreeParameterExpression(node.n) - elif isinstance(node, ast.Name): + if isinstance(node, ast.Name): return FreeParameterExpression(sympy.Symbol(node.id)) - elif isinstance(node, ast.BinOp): - if type(node.op) not in self._operations.keys(): + if isinstance(node, ast.BinOp): + if type(node.op) not in self._operations: raise ValueError(f"Unsupported binary operation: {type(node.op)}") return self._eval_operation(node.left)._operations[type(node.op)]( self._eval_operation(node.right) ) - elif isinstance(node, ast.UnaryOp): - if type(node.op) not in self._operations.keys(): + if isinstance(node, ast.UnaryOp): + if type(node.op) not in self._operations: raise ValueError(f"Unsupported unary operation: {type(node.op)}", type(node.op)) return self._eval_operation(node.operand)._operations[type(node.op)]() - else: - raise ValueError(f"Unsupported string detected: {node}") + raise ValueError(f"Unsupported string detected: {node}") def __add__(self, other: FreeParameterExpression): if issubclass(type(other), FreeParameterExpression): return FreeParameterExpression(self.expression + other.expression) - else: - return FreeParameterExpression(self.expression + other) + return FreeParameterExpression(self.expression + other) def __radd__(self, other: FreeParameterExpression): return FreeParameterExpression(other + self.expression) @@ -136,8 +133,7 @@ def __radd__(self, other: FreeParameterExpression): def __sub__(self, other: FreeParameterExpression): if issubclass(type(other), FreeParameterExpression): return FreeParameterExpression(self.expression - other.expression) - else: - return FreeParameterExpression(self.expression - other) + return FreeParameterExpression(self.expression - other) def __rsub__(self, other: FreeParameterExpression): return FreeParameterExpression(other - self.expression) @@ -145,26 +141,23 @@ def __rsub__(self, other: FreeParameterExpression): def __mul__(self, other: FreeParameterExpression): if issubclass(type(other), FreeParameterExpression): return FreeParameterExpression(self.expression * other.expression) - else: - return FreeParameterExpression(self.expression * other) + return FreeParameterExpression(self.expression * other) def __rmul__(self, other: FreeParameterExpression): return FreeParameterExpression(other * self.expression) - def __truediv__(self, other): + def __truediv__(self, other: FreeParameterExpression): if issubclass(type(other), FreeParameterExpression): return FreeParameterExpression(self.expression / other.expression) - else: - return FreeParameterExpression(self.expression / other) + return FreeParameterExpression(self.expression / other) def __rtruediv__(self, other: FreeParameterExpression): return FreeParameterExpression(other / self.expression) - def __pow__(self, other: FreeParameterExpression, modulo: float = None): + def __pow__(self, other: FreeParameterExpression, modulo: float | None = None): if issubclass(type(other), FreeParameterExpression): return FreeParameterExpression(self.expression**other.expression) - else: - return FreeParameterExpression(self.expression**other) + return FreeParameterExpression(self.expression**other) def __rpow__(self, other: FreeParameterExpression): return FreeParameterExpression(other**self.expression) @@ -195,22 +188,17 @@ def _to_oqpy_expression(self) -> OQPyExpression: if isinstance(self.expression, tuple(ops)): return reduce( ops[type(self.expression)], - map( - lambda x: FreeParameterExpression(x)._to_oqpy_expression(), self.expression.args - ), + (FreeParameterExpression(x)._to_oqpy_expression() for x in self.expression.args), ) - elif isinstance(self.expression, sympy.Number): + if isinstance(self.expression, sympy.Number): return float(self.expression) - else: - fvar = FloatVar( - name=self.expression.name, init_expression="input", needs_declaration=False - ) - fvar.size = None - fvar.type.size = None - return fvar + fvar = FloatVar(name=self.expression.name, init_expression="input", needs_declaration=False) + fvar.size = None + fvar.type.size = None + return fvar -def subs_if_free_parameter(parameter: Any, **kwargs: Union[FreeParameterExpression, str]) -> Any: +def subs_if_free_parameter(parameter: Any, **kwargs: FreeParameterExpression | str) -> Any: """Substitute a free parameter with the given kwargs, if any. Args: @@ -240,6 +228,7 @@ def _is_float(argument: str) -> bool: """ try: float(argument) - return True except ValueError: return False + else: + return True diff --git a/src/braket/parametric/parameterizable.py b/src/braket/parametric/parameterizable.py index 90c4dc589..fd59c6782 100644 --- a/src/braket/parametric/parameterizable.py +++ b/src/braket/parametric/parameterizable.py @@ -14,7 +14,7 @@ from __future__ import annotations from abc import ABC, abstractmethod -from typing import Any, Union +from typing import Any from braket.parametric.free_parameter import FreeParameter from braket.parametric.free_parameter_expression import FreeParameterExpression @@ -27,7 +27,7 @@ class Parameterizable(ABC): @property @abstractmethod - def parameters(self) -> list[Union[FreeParameterExpression, FreeParameter, float]]: + def parameters(self) -> list[FreeParameterExpression | FreeParameter | float]: """Get the parameters. Returns: @@ -37,7 +37,7 @@ def parameters(self) -> list[Union[FreeParameterExpression, FreeParameter, float """ @abstractmethod - def bind_values(self, **kwargs: Union[FreeParameter, str]) -> Any: + def bind_values(self, **kwargs: FreeParameter | str) -> Any: """Takes in parameters and returns an object with specified parameters replaced with their values. diff --git a/src/braket/pulse/__init__.py b/src/braket/pulse/__init__.py index 48f7022af..e19aad248 100644 --- a/src/braket/pulse/__init__.py +++ b/src/braket/pulse/__init__.py @@ -14,10 +14,10 @@ from braket.pulse.frame import Frame # noqa: F401 from braket.pulse.port import Port # noqa: F401 from braket.pulse.pulse_sequence import PulseSequence # noqa: F401 -from braket.pulse.waveforms import ( # noqa: F401 - ArbitraryWaveform, - ConstantWaveform, - DragGaussianWaveform, - ErfSquareWaveform, - GaussianWaveform, +from braket.pulse.waveforms import ( + ArbitraryWaveform, # noqa: F401 + ConstantWaveform, # noqa: F401 + DragGaussianWaveform, # noqa: F401 + ErfSquareWaveform, # noqa: F401 + GaussianWaveform, # noqa: F401 ) diff --git a/src/braket/pulse/ast/approximation_parser.py b/src/braket/pulse/ast/approximation_parser.py index 16c9c6726..9442f5772 100644 --- a/src/braket/pulse/ast/approximation_parser.py +++ b/src/braket/pulse/ast/approximation_parser.py @@ -49,7 +49,7 @@ class _ParseState: frame_data: dict[str, _FrameState] -class _ApproximationParser(QASMVisitor[_ParseState]): +class _ApproximationParser(QASMVisitor[_ParseState]): # noqa: PLR0904 """Walk the AST and build the output signal amplitude, frequency and phases for each channel. """ @@ -146,13 +146,13 @@ def visit_ClassicalDeclaration( Returns: Union[dict, None]: Returns a dict if WaveformType, None otherwise. - """ + """ # noqa: DOC202 identifier = self.visit(node.identifier, context) - if type(node.type) == ast.WaveformType: + if type(node.type) is ast.WaveformType: context.variables[identifier] = self.visit(node.init_expression, context) - elif type(node.type) == ast.FrameType: + elif type(node.type) is ast.FrameType: pass - elif type(node.type) != ast.PortType: + elif type(node.type) is not ast.PortType: raise NotImplementedError def visit_DelayInstruction(self, node: ast.DelayInstruction, context: _ParseState) -> None: @@ -188,9 +188,6 @@ def visit_QuantumBarrier(self, node: ast.QuantumBarrier, context: _ParseState) - Args: node (ast.QuantumBarrier): The quantum barrier. context (_ParseState): The parse state context. - - Returns: - None: No return value. """ frames = self._get_frame_parameters(node.qubits, context) if len(frames) == 0: @@ -234,8 +231,7 @@ def visit_Identifier(self, node: ast.Identifier, context: _ParseState) -> Any: """ if node.name in context.variables: return context.variables[node.name] - else: - return node.name + return node.name def visit_UnaryExpression(self, node: ast.UnaryExpression, context: _ParseState) -> bool: """Visit Unary Expression. @@ -254,15 +250,13 @@ def visit_UnaryExpression(self, node: ast.UnaryExpression, context: _ParseState) """ if node.op == ast.UnaryOperator["-"]: return -1 * self.visit(node.expression, context) - elif node.op == ast.UnaryOperator["!"]: + if node.op == ast.UnaryOperator["!"]: return not self.visit(node.expression, context) - elif node.op == ast.UnaryOperator["~"]: + if node.op == ast.UnaryOperator["~"]: return ~self.visit(node.expression, context) - else: - raise NotImplementedError + raise NotImplementedError - # flake8: noqa: C901 - def visit_BinaryExpression(self, node: ast.BinaryExpression, context: _ParseState) -> Any: + def visit_BinaryExpression(self, node: ast.BinaryExpression, context: _ParseState) -> Any: # noqa: C901, PLR0911, PLR0912 """Visit Binary Expression. node.lhs, node.rhs, node.op 1+2 @@ -287,44 +281,43 @@ def visit_BinaryExpression(self, node: ast.BinaryExpression, context: _ParseStat if node.op == op["+"]: return lhs + rhs - elif node.op == op["-"]: + if node.op == op["-"]: return lhs - rhs - elif node.op == op["*"]: + if node.op == op["*"]: return lhs * rhs - elif node.op == op["/"]: + if node.op == op["/"]: return lhs / rhs - elif node.op == op["%"]: + if node.op == op["%"]: return lhs % rhs - elif node.op == op["**"]: + if node.op == op["**"]: return lhs**rhs - elif node.op == op[">"]: + if node.op == op[">"]: return lhs > rhs - elif node.op == op["<"]: + if node.op == op["<"]: return lhs < rhs - elif node.op == op[">="]: + if node.op == op[">="]: return lhs >= rhs - elif node.op == op["<="]: + if node.op == op["<="]: return lhs <= rhs - elif node.op == op["=="]: + if node.op == op["=="]: return lhs == rhs - elif node.op == op["!="]: + if node.op == op["!="]: return lhs != rhs - elif node.op == op["&&"]: + if node.op == op["&&"]: return lhs and rhs - elif node.op == op["||"]: + if node.op == op["||"]: return lhs or rhs - elif node.op == op["|"]: + if node.op == op["|"]: return lhs | rhs - elif node.op == op["^"]: + if node.op == op["^"]: return lhs ^ rhs - elif node.op == op["&"]: + if node.op == op["&"]: return lhs & rhs - elif node.op == op["<<"]: + if node.op == op["<<"]: return lhs << rhs - elif node.op == op[">>"]: + if node.op == op[">>"]: return lhs >> rhs - else: - raise NotImplementedError + raise NotImplementedError def visit_ArrayLiteral(self, node: ast.ArrayLiteral, context: _ParseState) -> list[Any]: """Visit Array Literal. @@ -501,9 +494,6 @@ def play(self, node: ast.FunctionCall, context: _ParseState) -> None: Raises: NotImplementedError: Raises if not of type [ast.Identifier, ast.FunctionCall, ast.ArrayLiteral] - - Returns: - None: Returns None """ frame_id = self.visit(node.arguments[0], context) if isinstance(node.arguments[1], ast.ArrayLiteral): @@ -513,7 +503,7 @@ def play(self, node: ast.FunctionCall, context: _ParseState) -> None: if isinstance(amps, Waveform): amps = amps.sample(context.frame_data[frame_id].dt) elif isinstance(amps, str): - raise NameError(f"waveform '{amps}' is not defined.") + raise NameError(f"waveform '{amps}' is not defined.") # noqa: TRY004 else: raise NotImplementedError frame_data = context.frame_data[frame_id] @@ -579,11 +569,10 @@ def erf_square(self, node: ast.FunctionCall, context: _ParseState) -> Waveform: def _init_frame_data(frames: dict[str, Frame]) -> dict[str, _FrameState]: - frame_states = { + return { frameId: _FrameState(frame.port.dt, frame.frequency, frame.phase % (2 * np.pi)) for frameId, frame in frames.items() } - return frame_states def _init_qubit_frame_mapping(frames: dict[str, Frame]) -> dict[str, list[str]]: diff --git a/src/braket/pulse/ast/free_parameters.py b/src/braket/pulse/ast/free_parameters.py index 1750275ac..ce201f3c1 100644 --- a/src/braket/pulse/ast/free_parameters.py +++ b/src/braket/pulse/ast/free_parameters.py @@ -69,7 +69,7 @@ def visit_BinaryExpression( } if isinstance(rhs, ast.FloatLiteral): return ast.FloatLiteral(ops[node.op](lhs.value, rhs.value)) - elif isinstance(rhs, ast.DurationLiteral) and node.op == ast.BinaryOperator["*"]: + if isinstance(rhs, ast.DurationLiteral) and node.op == ast.BinaryOperator["*"]: return OQDurationLiteral(lhs.value * rhs.value).to_ast(self.program) return ast.BinaryExpression(op=node.op, lhs=lhs, rhs=rhs) diff --git a/src/braket/pulse/frame.py b/src/braket/pulse/frame.py index 63700d22e..e5c7893c5 100644 --- a/src/braket/pulse/frame.py +++ b/src/braket/pulse/frame.py @@ -14,7 +14,7 @@ from __future__ import annotations import math -from typing import Any, Optional +from typing import Any from oqpy import FrameVar as OQFrame from oqpy.base import OQPyExpression @@ -35,7 +35,7 @@ def __init__( frequency: float, phase: float = 0, is_predefined: bool = False, - properties: Optional[dict[str, Any]] = None, + properties: dict[str, Any] | None = None, ): """Initializes a Frame. diff --git a/src/braket/pulse/port.py b/src/braket/pulse/port.py index 99b1acca5..b4122371c 100644 --- a/src/braket/pulse/port.py +++ b/src/braket/pulse/port.py @@ -13,7 +13,7 @@ from __future__ import annotations -from typing import Any, Optional +from typing import Any from oqpy import PortVar from oqpy.base import OQPyExpression @@ -24,7 +24,7 @@ class Port: a device. See https://openqasm.com/language/openpulse.html#ports for more details. """ - def __init__(self, port_id: str, dt: float, properties: Optional[dict[str, Any]] = None): + def __init__(self, port_id: str, dt: float, properties: dict[str, Any] | None = None): """Initializes a Port. Args: diff --git a/src/braket/pulse/pulse_sequence.py b/src/braket/pulse/pulse_sequence.py index 6c5d60444..59afceaac 100644 --- a/src/braket/pulse/pulse_sequence.py +++ b/src/braket/pulse/pulse_sequence.py @@ -16,7 +16,7 @@ import builtins from copy import deepcopy from inspect import signature -from typing import Any, Union +from typing import Any from openpulse import ast from oqpy import BitVar, PhysicalQubits, Program @@ -68,7 +68,7 @@ def parameters(self) -> set[FreeParameter]: return self._free_parameters.copy() def set_frequency( - self, frame: Frame, frequency: Union[float, FreeParameterExpression] + self, frame: Frame, frequency: float | FreeParameterExpression ) -> PulseSequence: """Adds an instruction to set the frequency of the frame to the specified `frequency` value. @@ -87,7 +87,7 @@ def set_frequency( return self def shift_frequency( - self, frame: Frame, frequency: Union[float, FreeParameterExpression] + self, frame: Frame, frequency: float | FreeParameterExpression ) -> PulseSequence: """Adds an instruction to shift the frequency of the frame by the specified `frequency` value. @@ -106,9 +106,7 @@ def shift_frequency( self._frames[frame.id] = frame return self - def set_phase( - self, frame: Frame, phase: Union[float, FreeParameterExpression] - ) -> PulseSequence: + def set_phase(self, frame: Frame, phase: float | FreeParameterExpression) -> PulseSequence: """Adds an instruction to set the phase of the frame to the specified `phase` value. Args: @@ -125,9 +123,7 @@ def set_phase( self._frames[frame.id] = frame return self - def shift_phase( - self, frame: Frame, phase: Union[float, FreeParameterExpression] - ) -> PulseSequence: + def shift_phase(self, frame: Frame, phase: float | FreeParameterExpression) -> PulseSequence: """Adds an instruction to shift the phase of the frame by the specified `phase` value. Args: @@ -164,9 +160,7 @@ def swap_phases( self._frames[frame_2.id] = frame_2 return self - def set_scale( - self, frame: Frame, scale: Union[float, FreeParameterExpression] - ) -> PulseSequence: + def set_scale(self, frame: Frame, scale: float | FreeParameterExpression) -> PulseSequence: """Adds an instruction to set the scale on the frame to the specified `scale` value. Args: @@ -185,8 +179,8 @@ def set_scale( def delay( self, - qubits_or_frames: Union[Frame, list[Frame], QubitSet], - duration: Union[float, FreeParameterExpression], + qubits_or_frames: Frame | list[Frame] | QubitSet, + duration: float | FreeParameterExpression, ) -> PulseSequence: """Adds an instruction to advance the frame clock by the specified `duration` value. @@ -212,7 +206,7 @@ def delay( self._program.delay(time=duration, qubits_or_frames=physical_qubits) return self - def barrier(self, qubits_or_frames: Union[list[Frame], QubitSet]) -> PulseSequence: + def barrier(self, qubits_or_frames: list[Frame] | QubitSet) -> PulseSequence: """Adds an instruction to align the frame clocks to the latest time across all the specified frames. @@ -349,7 +343,7 @@ def to_ir(self, sort_input_parameters: bool = False) -> str: def _register_free_parameters( self, - parameter: Union[float, FreeParameterExpression], + parameter: float | FreeParameterExpression, ) -> None: if isinstance(parameter, FreeParameterExpression) and isinstance( parameter.expression, Expr @@ -367,14 +361,13 @@ def _parse_arg_from_calibration_schema( } if argument["type"] in nonprimitive_arg_type: return nonprimitive_arg_type[argument["type"]](argument["value"]) - else: - return getattr(builtins, argument["type"])(argument["value"]) + return getattr(builtins, argument["type"])(argument["value"]) @classmethod def _parse_from_calibration_schema( cls, calibration: dict, waveforms: dict[Waveform], frames: dict[Frame] ) -> PulseSequence: - """Parsing a JSON input based on https://github.com/aws/amazon-braket-schemas-python/blob/main/src/braket/device_schema/pulse/native_gate_calibrations_v1.py#L26. # noqa: E501 + """Parsing a JSON input based on https://github.com/aws/amazon-braket-schemas-python/blob/main/src/braket/device_schema/pulse/native_gate_calibrations_v1.py#L26. Args: calibration (dict): The pulse instruction to parse @@ -422,9 +415,7 @@ def _parse_from_calibration_schema( instr_function(**instr_args) return calibration_sequence - def __call__( - self, arg: Any | None = None, **kwargs: Union[FreeParameter, str] - ) -> PulseSequence: + def __call__(self, arg: Any | None = None, **kwargs: FreeParameter | str) -> PulseSequence: """Implements the call function to easily make a bound PulseSequence. Args: @@ -453,7 +444,7 @@ def __eq__(self, other: PulseSequence): def _validate_uniqueness( - mapping: dict[str, Any], values: Union[Frame, Waveform, list[Frame], list[Waveform]] + mapping: dict[str, Any], values: Frame | Waveform | list[Frame] | list[Waveform] ) -> None: if not isinstance(values, list): values = [values] diff --git a/src/braket/pulse/waveforms.py b/src/braket/pulse/waveforms.py index 9da7bee4c..bc3878698 100644 --- a/src/braket/pulse/waveforms.py +++ b/src/braket/pulse/waveforms.py @@ -16,7 +16,6 @@ import random import string from abc import ABC, abstractmethod -from typing import Optional, Union import numpy as np import scipy as sp @@ -58,7 +57,7 @@ def sample(self, dt: float) -> np.ndarray: @staticmethod @abstractmethod def _from_calibration_schema(waveform_json: dict) -> Waveform: - """Parses a JSON input and returns the BDK waveform. See https://github.com/aws/amazon-braket-schemas-python/blob/main/src/braket/device_schema/pulse/native_gate_calibrations_v1.py#L104 # noqa: E501 + """Parses a JSON input and returns the BDK waveform. See https://github.com/aws/amazon-braket-schemas-python/blob/main/src/braket/device_schema/pulse/native_gate_calibrations_v1.py#L104 Args: waveform_json (dict): A JSON object with the needed parameters for making the Waveform. @@ -73,7 +72,7 @@ class ArbitraryWaveform(Waveform): an array. """ - def __init__(self, amplitudes: list[complex], id: Optional[str] = None): + def __init__(self, amplitudes: list[complex], id: str | None = None): """Initializes an `ArbitraryWaveform`. Args: @@ -129,9 +128,7 @@ class ConstantWaveform(Waveform, Parameterizable): specified length. """ - def __init__( - self, length: Union[float, FreeParameterExpression], iq: complex, id: Optional[str] = None - ): + def __init__(self, length: float | FreeParameterExpression, iq: complex, id: str | None = None): """Initializes a `ConstantWaveform`. Args: @@ -149,7 +146,7 @@ def __repr__(self) -> str: return f"ConstantWaveform('id': {self.id}, 'length': {self.length}, 'iq': {self.iq})" @property - def parameters(self) -> list[Union[FreeParameterExpression, FreeParameter, float]]: + def parameters(self) -> list[FreeParameterExpression | FreeParameter | float]: """Returns the parameters associated with the object, either unbound free parameter expressions or bound values. @@ -158,7 +155,7 @@ def parameters(self) -> list[Union[FreeParameterExpression, FreeParameter, float """ return [self.length] - def bind_values(self, **kwargs: Union[FreeParameter, str]) -> ConstantWaveform: + def bind_values(self, **kwargs: FreeParameter | str) -> ConstantWaveform: """Takes in parameters and returns an object with specified parameters replaced with their values. @@ -207,8 +204,7 @@ def sample(self, dt: float) -> np.ndarray: """ # Amplitudes should be gated by [0:self.length] sample_range = np.arange(0, self.length, dt) - samples = self.iq * np.ones_like(sample_range) - return samples + return self.iq * np.ones_like(sample_range) @staticmethod def _from_calibration_schema(waveform_json: dict) -> ConstantWaveform: @@ -235,12 +231,12 @@ class DragGaussianWaveform(Waveform, Parameterizable): def __init__( self, - length: Union[float, FreeParameterExpression], - sigma: Union[float, FreeParameterExpression], - beta: Union[float, FreeParameterExpression], - amplitude: Union[float, FreeParameterExpression] = 1, + length: float | FreeParameterExpression, + sigma: float | FreeParameterExpression, + beta: float | FreeParameterExpression, + amplitude: float | FreeParameterExpression = 1, zero_at_edges: bool = False, - id: Optional[str] = None, + id: str | None = None, ): """Initializes a `DragGaussianWaveform`. @@ -272,13 +268,13 @@ def __repr__(self) -> str: ) @property - def parameters(self) -> list[Union[FreeParameterExpression, FreeParameter, float]]: + def parameters(self) -> list[FreeParameterExpression | FreeParameter | float]: """Returns the parameters associated with the object, either unbound free parameter expressions or bound values. """ return [self.length, self.sigma, self.beta, self.amplitude] - def bind_values(self, **kwargs: Union[FreeParameter, str]) -> DragGaussianWaveform: + def bind_values(self, **kwargs: FreeParameter | str) -> DragGaussianWaveform: """Takes in parameters and returns an object with specified parameters replaced with their values. @@ -347,7 +343,7 @@ def sample(self, dt: float) -> np.ndarray: sample_range = np.arange(0, self.length, dt) t0 = self.length / 2 zero_at_edges_int = int(self.zero_at_edges) - samples = ( + return ( (1 - (1.0j * self.beta * ((sample_range - t0) / self.sigma**2))) * ( self.amplitude @@ -358,7 +354,6 @@ def sample(self, dt: float) -> np.ndarray: - zero_at_edges_int * np.exp(-0.5 * ((self.length / (2 * self.sigma)) ** 2)) ) ) - return samples @staticmethod def _from_calibration_schema(waveform_json: dict) -> DragGaussianWaveform: @@ -377,11 +372,11 @@ class GaussianWaveform(Waveform, Parameterizable): def __init__( self, - length: Union[float, FreeParameterExpression], - sigma: Union[float, FreeParameterExpression], - amplitude: Union[float, FreeParameterExpression] = 1, + length: float | FreeParameterExpression, + sigma: float | FreeParameterExpression, + amplitude: float | FreeParameterExpression = 1, zero_at_edges: bool = False, - id: Optional[str] = None, + id: str | None = None, ): """Initializes a `GaussianWaveform`. @@ -410,13 +405,13 @@ def __repr__(self) -> str: ) @property - def parameters(self) -> list[Union[FreeParameterExpression, FreeParameter, float]]: + def parameters(self) -> list[FreeParameterExpression | FreeParameter | float]: """Returns the parameters associated with the object, either unbound free parameter expressions or bound values. """ return [self.length, self.sigma, self.amplitude] - def bind_values(self, **kwargs: Union[FreeParameter, str]) -> GaussianWaveform: + def bind_values(self, **kwargs: FreeParameter | str) -> GaussianWaveform: """Takes in parameters and returns an object with specified parameters replaced with their values. @@ -481,14 +476,13 @@ def sample(self, dt: float) -> np.ndarray: sample_range = np.arange(0, self.length, dt) t0 = self.length / 2 zero_at_edges_int = int(self.zero_at_edges) - samples = ( + return ( self.amplitude / (1 - zero_at_edges_int * np.exp(-0.5 * ((self.length / (2 * self.sigma)) ** 2))) ) * ( np.exp(-0.5 * (((sample_range - t0) / self.sigma) ** 2)) - zero_at_edges_int * np.exp(-0.5 * ((self.length / (2 * self.sigma)) ** 2)) ) - return samples @staticmethod def _from_calibration_schema(waveform_json: dict) -> GaussianWaveform: @@ -507,13 +501,13 @@ class ErfSquareWaveform(Waveform, Parameterizable): def __init__( self, - length: Union[float, FreeParameterExpression], - width: Union[float, FreeParameterExpression], - sigma: Union[float, FreeParameterExpression], - off_center: Union[float, FreeParameterExpression] = 0, - amplitude: Union[float, FreeParameterExpression] = 1, + length: float | FreeParameterExpression, + width: float | FreeParameterExpression, + sigma: float | FreeParameterExpression, + off_center: float | FreeParameterExpression = 0, + amplitude: float | FreeParameterExpression = 1, zero_at_edges: bool = False, - id: Optional[str] = None, + id: str | None = None, ): r"""Initializes a `ErfSquareWaveform`. @@ -524,20 +518,20 @@ def __init__( height. The waveform is scaled such that its maximum is equal to `amplitude`. Args: - length (Union[float, FreeParameterExpression]): Duration (in seconds) from the start + length (float | FreeParameterExpression): Duration (in seconds) from the start to the end of the waveform. - width (Union[float, FreeParameterExpression]): Duration (in seconds) between the + width (float | FreeParameterExpression): Duration (in seconds) between the half height of the two edges. - sigma (Union[float, FreeParameterExpression]): A characteristic time of how quickly + sigma (float | FreeParameterExpression): A characteristic time of how quickly the edges rise and fall. - off_center (Union[float, FreeParameterExpression]): Shift the smoothed square waveform + off_center (float | FreeParameterExpression): Shift the smoothed square waveform earlier or later in time. When positive, the smoothed square is shifted later (to the right), otherwise earlier (to the left). Defaults to 0. - amplitude (Union[float, FreeParameterExpression]): The amplitude of the waveform + amplitude (float | FreeParameterExpression): The amplitude of the waveform envelope. Defaults to 1. zero_at_edges (bool): Whether the waveform is scaled such that it has zero value at the edges. Defaults to False. - id (Optional[str]): The identifier used for declaring this waveform. A random string of + id (str | None): The identifier used for declaring this waveform. A random string of ascii characters is assigned by default. """ self.length = length @@ -556,18 +550,18 @@ def __repr__(self) -> str: ) @property - def parameters(self) -> list[Union[FreeParameterExpression, FreeParameter, float]]: + def parameters(self) -> list[FreeParameterExpression | FreeParameter | float]: """Returns the parameters associated with the object, either unbound free parameter expressions or bound values. """ return [self.length, self.width, self.sigma, self.off_center, self.amplitude] - def bind_values(self, **kwargs: Union[FreeParameter, str]) -> ErfSquareWaveform: + def bind_values(self, **kwargs: FreeParameter | str) -> ErfSquareWaveform: """Takes in parameters and returns an object with specified parameters replaced with their values. Args: - **kwargs (Union[FreeParameter, str]): Arbitrary keyword arguments. + **kwargs (FreeParameter | str): Arbitrary keyword arguments. Returns: ErfSquareWaveform: A copy of this waveform with the requested parameters bound. @@ -657,8 +651,7 @@ def sample(self, dt: float) -> np.ndarray: / (mid_waveform_height - waveform_bottom) * self.amplitude ) - else: - return samples * self.amplitude / mid_waveform_height + return samples * self.amplitude / mid_waveform_height @staticmethod def _from_calibration_schema(waveform_json: dict) -> ErfSquareWaveform: @@ -673,7 +666,7 @@ def _from_calibration_schema(waveform_json: dict) -> ErfSquareWaveform: def _make_identifier_name() -> str: - return "".join([random.choice(string.ascii_letters) for _ in range(10)]) # noqa S311 + return "".join([random.choice(string.ascii_letters) for _ in range(10)]) # noqa: S311 def _parse_waveform_from_calibration_schema(waveform: dict) -> Waveform: diff --git a/src/braket/quantum_information/pauli_string.py b/src/braket/quantum_information/pauli_string.py index 0de8e8e3b..723eb94bd 100644 --- a/src/braket/quantum_information/pauli_string.py +++ b/src/braket/quantum_information/pauli_string.py @@ -14,7 +14,6 @@ from __future__ import annotations import itertools -from typing import Optional, Union from braket.circuits.circuit import Circuit from braket.circuits.observables import I, TensorProduct, X, Y, Z @@ -37,7 +36,7 @@ class PauliString: """A lightweight representation of a Pauli string with its phase.""" - def __init__(self, pauli_string: Union[str, PauliString]): + def __init__(self, pauli_string: str | PauliString): """Initializes a `PauliString`. Args: @@ -90,19 +89,17 @@ def to_unsigned_observable(self, include_trivial: bool = False) -> TensorProduct TensorProduct: The tensor product of the unsigned factors in the Pauli string. """ if include_trivial: - return TensorProduct( - [ - ( - _PAULI_OBSERVABLES[self._nontrivial[qubit]] - if qubit in self._nontrivial - else _ID_OBS - ) - for qubit in range(self._qubit_count) - ] - ) - return TensorProduct( - [_PAULI_OBSERVABLES[self._nontrivial[qubit]] for qubit in sorted(self._nontrivial)] - ) + return TensorProduct([ + ( + _PAULI_OBSERVABLES[self._nontrivial[qubit]] + if qubit in self._nontrivial + else _ID_OBS + ) + for qubit in range(self._qubit_count) + ]) + return TensorProduct([ + _PAULI_OBSERVABLES[self._nontrivial[qubit]] for qubit in sorted(self._nontrivial) + ]) def weight_n_substrings(self, weight: int) -> tuple[PauliString, ...]: r"""Returns every substring of this Pauli string with exactly `weight` nontrivial factors. @@ -131,7 +128,7 @@ def weight_n_substrings(self, weight: int) -> tuple[PauliString, ...]: ) return tuple(substrings) - def eigenstate(self, signs: Optional[Union[str, list[int], tuple[int, ...]]] = None) -> Circuit: + def eigenstate(self, signs: str | list[int] | tuple[int, ...] | None = None) -> Circuit: """Returns the eigenstate of this Pauli string with the given factor signs. The resulting eigenstate has each qubit in the +1 eigenstate of its corresponding signed @@ -271,7 +268,7 @@ def power(self, n: int, inplace: bool = False) -> PauliString: ValueError: If `n` isn't a plain Python `int`. """ if not isinstance(n, int): - raise ValueError("Must be raised to integer power") + raise TypeError("Must be raised to integer power") # Since pauli ops involutory, result is either identity or unchanged pauli_other = PauliString(self) @@ -363,10 +360,7 @@ def __len__(self): return self._qubit_count def __repr__(self): - factors = [ - self._nontrivial[qubit] if qubit in self._nontrivial else "I" - for qubit in range(self._qubit_count) - ] + factors = [self._nontrivial.get(qubit, "I") for qubit in range(self._qubit_count)] return f"{PauliString._phase_to_str(self._phase)}{''.join(factors)}" @staticmethod diff --git a/src/braket/registers/qubit_set.py b/src/braket/registers/qubit_set.py index e7bed6aa8..f8a6c7e45 100644 --- a/src/braket/registers/qubit_set.py +++ b/src/braket/registers/qubit_set.py @@ -50,20 +50,18 @@ def __init__(self, qubits: QubitSetInput | None = None): >>> qubits = QubitSet([0, 1]) >>> for qubit in qubits: ... print(qubit) - ... Qubit(0) Qubit(1) >>> qubits = QubitSet([0, 1, [2, 3]]) >>> for qubit in qubits: ... print(qubit) - ... Qubit(0) Qubit(1) Qubit(2) Qubit(3) """ - _qubits = [Qubit.new(qubit) for qubit in _flatten(qubits)] if qubits is not None else None + _qubits = [Qubit.new(qubit) for qubit in _flatten(qubits)] if qubits is not None else None # noqa: RUF052 super().__init__(_qubits) def map(self, mapping: dict[QubitInput, QubitInput]) -> QubitSet: @@ -83,7 +81,7 @@ def map(self, mapping: dict[QubitInput, QubitInput]) -> QubitSet: >>> mapping = {0: 10, Qubit(1): Qubit(11)} >>> qubits.map(mapping) QubitSet([Qubit(10), Qubit(11)]) - """ # noqa E501 + """ # noqa: E501 new_qubits = [mapping.get(qubit, qubit) for qubit in self] return QubitSet(new_qubits) diff --git a/src/braket/tasks/__init__.py b/src/braket/tasks/__init__.py index d40b0547c..1df9081c0 100644 --- a/src/braket/tasks/__init__.py +++ b/src/braket/tasks/__init__.py @@ -18,8 +18,8 @@ ) from braket.tasks.annealing_quantum_task_result import AnnealingQuantumTaskResult # noqa: F401 from braket.tasks.gate_model_quantum_task_result import GateModelQuantumTaskResult # noqa: F401 -from braket.tasks.photonic_model_quantum_task_result import ( # noqa: F401 - PhotonicModelQuantumTaskResult, +from braket.tasks.photonic_model_quantum_task_result import ( + PhotonicModelQuantumTaskResult, # noqa: F401 ) from braket.tasks.quantum_task import QuantumTask # noqa: F401 from braket.tasks.quantum_task_batch import QuantumTaskBatch # noqa: F401 diff --git a/src/braket/tasks/analog_hamiltonian_simulation_quantum_task_result.py b/src/braket/tasks/analog_hamiltonian_simulation_quantum_task_result.py index 7bfb57eb3..8f72e7465 100644 --- a/src/braket/tasks/analog_hamiltonian_simulation_quantum_task_result.py +++ b/src/braket/tasks/analog_hamiltonian_simulation_quantum_task_result.py @@ -149,9 +149,7 @@ def get_avg_density(self) -> np.ndarray: N_ryd_cnt = np.sum(N_ryd, axis=0) N_ground_cnt = np.sum(N_ground, axis=0) - avg_density = N_ryd_cnt / (N_ryd_cnt + N_ground_cnt) - - return avg_density + return N_ryd_cnt / (N_ryd_cnt + N_ground_cnt) def _equal_sequences(sequence0: np.ndarray, sequence1: np.ndarray) -> bool: diff --git a/src/braket/tasks/annealing_quantum_task_result.py b/src/braket/tasks/annealing_quantum_task_result.py index bf5e9900d..31b055cbc 100644 --- a/src/braket/tasks/annealing_quantum_task_result.py +++ b/src/braket/tasks/annealing_quantum_task_result.py @@ -15,7 +15,6 @@ from collections.abc import Generator from dataclasses import dataclass -from typing import Optional import numpy as np @@ -47,7 +46,7 @@ class AnnealingQuantumTaskResult: def data( self, - selected_fields: Optional[list[str]] = None, + selected_fields: list[str] | None = None, sorted_by: str = "value", reverse: bool = False, ) -> Generator[tuple]: diff --git a/src/braket/tasks/gate_model_quantum_task_result.py b/src/braket/tasks/gate_model_quantum_task_result.py index e8267032f..577a74d1b 100644 --- a/src/braket/tasks/gate_model_quantum_task_result.py +++ b/src/braket/tasks/gate_model_quantum_task_result.py @@ -14,10 +14,12 @@ from __future__ import annotations import json +import operator from collections import Counter from collections.abc import Callable from dataclasses import dataclass -from typing import Any, Optional, TypeVar, Union +from itertools import starmap +from typing import Any, TypeVar import numpy as np @@ -132,7 +134,7 @@ def __eq__(self, other: GateModelQuantumTaskResult) -> bool: return self.task_metadata.id == other.task_metadata.id return NotImplemented - def get_compiled_circuit(self) -> Optional[str]: + def get_compiled_circuit(self) -> str | None: """Get the compiled circuit, if one is available. Returns: @@ -143,12 +145,11 @@ def get_compiled_circuit(self) -> Optional[str]: return None if metadata.rigettiMetadata: return metadata.rigettiMetadata.compiledProgram - elif metadata.oqcMetadata: + if metadata.oqcMetadata: return metadata.oqcMetadata.compiledProgram - elif metadata.iqmMetadata: + if metadata.iqmMetadata: return metadata.iqmMetadata.compiledProgram - else: - return None + return None @staticmethod def measurement_counts_from_measurements(measurements: np.ndarray) -> Counter: @@ -183,10 +184,7 @@ def measurement_probabilities_from_measurement_counts( """ shots = sum(measurement_counts.values()) - measurement_probabilities = { - key: count / shots for key, count in measurement_counts.items() - } - return measurement_probabilities + return {key: count / shots for key, count in measurement_counts.items()} @staticmethod def measurements_from_measurement_probabilities( @@ -206,11 +204,9 @@ def measurements_from_measurement_probabilities( Value is the probability the measurement occurred. """ measurements_list = [] - for bitstring in measurement_probabilities: + for bitstring, prob in measurement_probabilities.items(): measurement = list(bitstring) - individual_measurement_list = [measurement] * int( - round(measurement_probabilities[bitstring] * shots) - ) + individual_measurement_list = [measurement] * round(prob * shots) measurements_list.extend(individual_measurement_list) return np.asarray(measurements_list, dtype=int) @@ -254,8 +250,7 @@ def _from_object_internal(cls, result: GateModelTaskResult) -> GateModelQuantumT return GateModelQuantumTaskResult._from_object_internal_computational_basis_sampling( result ) - else: - return GateModelQuantumTaskResult._from_dict_internal_simulator_only(result) + return GateModelQuantumTaskResult._from_dict_internal_simulator_only(result) @classmethod def _from_object_internal_computational_basis_sampling( @@ -355,7 +350,7 @@ def cast_result_types(gate_model_task_result: GateModelTaskResult) -> None: elif type == "probability": result_type.value = np.array(result_type.value) elif type == "statevector": - result_type.value = np.array([complex(*value) for value in result_type.value]) + result_type.value = np.array(list(starmap(complex, result_type.value))) @staticmethod def _calculate_result_types( @@ -409,7 +404,7 @@ def _calculate_result_types( @staticmethod def _selected_measurements( - measurements: np.ndarray, measured_qubits: list[int], targets: Optional[list[int]] + measurements: np.ndarray, measured_qubits: list[int], targets: list[int] | None ) -> np.ndarray: if targets is not None and targets != measured_qubits: # Only some qubits targeted @@ -424,14 +419,13 @@ def _calculate_for_targets( measured_qubits: list[int], observable: Observable, targets: list[int], - ) -> Union[T, list[T]]: + ) -> T | list[T]: if targets: return calculate_function(measurements, measured_qubits, observable, targets) - else: - return [ - calculate_function(measurements, measured_qubits, observable, [i]) - for i in measured_qubits - ] + return [ + calculate_function(measurements, measured_qubits, observable, [i]) + for i in measured_qubits + ] @staticmethod def _measurements_base_10(measurements: np.ndarray) -> np.ndarray: @@ -441,7 +435,7 @@ def _measurements_base_10(measurements: np.ndarray) -> np.ndarray: @staticmethod def _probability_from_measurements( - measurements: np.ndarray, measured_qubits: list[int], targets: Optional[list[int]] + measurements: np.ndarray, measured_qubits: list[int], targets: list[int] | None ) -> np.ndarray: measurements = GateModelQuantumTaskResult._selected_measurements( measurements, measured_qubits, targets @@ -504,11 +498,10 @@ def _samples_from_measurements( def _result_type_hash(rt_type: dict) -> str: if hasattr(rt_type, "observable") and isinstance(rt_type.observable, list): rt_type.observable = GateModelQuantumTaskResult._replace_neg_zero(rt_type.observable) - return repr(dict(sorted(dict(rt_type).items(), key=lambda x: x[0]))) + return repr(dict(sorted(dict(rt_type).items(), key=operator.itemgetter(0)))) @staticmethod - def _replace_neg_zero(observable_matrix: Union[list, int]) -> Union[list, int]: + def _replace_neg_zero(observable_matrix: list | int) -> list | int: if isinstance(observable_matrix, list): return [GateModelQuantumTaskResult._replace_neg_zero(x) for x in observable_matrix] - else: - return 0 if observable_matrix == 0 else observable_matrix + return 0 if observable_matrix == 0 else observable_matrix diff --git a/src/braket/tasks/local_quantum_task.py b/src/braket/tasks/local_quantum_task.py index 8417c71b2..285c347c8 100644 --- a/src/braket/tasks/local_quantum_task.py +++ b/src/braket/tasks/local_quantum_task.py @@ -10,9 +10,9 @@ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. +from __future__ import annotations import asyncio -from typing import Union from braket.tasks import ( AnnealingQuantumTaskResult, @@ -30,9 +30,9 @@ class LocalQuantumTask(QuantumTask): def __init__( self, - result: Union[ - GateModelQuantumTaskResult, AnnealingQuantumTaskResult, PhotonicModelQuantumTaskResult - ], + result: GateModelQuantumTaskResult + | AnnealingQuantumTaskResult + | PhotonicModelQuantumTaskResult, ): self._id = result.task_metadata.id self._result = result @@ -60,9 +60,7 @@ def state(self) -> str: def result( self, - ) -> Union[ - GateModelQuantumTaskResult, AnnealingQuantumTaskResult, PhotonicModelQuantumTaskResult - ]: + ) -> GateModelQuantumTaskResult | AnnealingQuantumTaskResult | PhotonicModelQuantumTaskResult: return self._result def async_result(self) -> asyncio.Task: diff --git a/src/braket/tasks/quantum_task.py b/src/braket/tasks/quantum_task.py index f07a1be7b..a0c2561c7 100644 --- a/src/braket/tasks/quantum_task.py +++ b/src/braket/tasks/quantum_task.py @@ -56,7 +56,7 @@ def result( Union[GateModelQuantumTaskResult, AnnealingQuantumTaskResult, PhotonicModelQuantumTaskResult]: Get the quantum task result. Call async_result if you want the result in an asynchronous way. - """ # noqa E501 + """ # noqa: E501 @abstractmethod def async_result(self) -> asyncio.Task: @@ -66,7 +66,7 @@ def async_result(self) -> asyncio.Task: asyncio.Task: Get the quantum task result asynchronously. """ - def metadata(self, use_cached_value: bool = False) -> dict[str, Any]: # noqa B027 + def metadata(self, use_cached_value: bool = False) -> dict[str, Any]: # noqa: B027 """Get task metadata. Args: diff --git a/src/braket/timings/time_series.py b/src/braket/timings/time_series.py index 67797d6c4..f01299155 100644 --- a/src/braket/timings/time_series.py +++ b/src/braket/timings/time_series.py @@ -19,7 +19,6 @@ from decimal import Decimal from enum import Enum from numbers import Number -from typing import Optional @dataclass @@ -269,15 +268,15 @@ def stitch( return new_time_series def discretize( - self, time_resolution: Optional[Decimal], value_resolution: Optional[Decimal] + self, time_resolution: Decimal | None, value_resolution: Decimal | None ) -> TimeSeries: """Creates a discretized version of the time series, rounding all times and values to the closest multiple of the corresponding resolution. Args: - time_resolution (Optional[Decimal]): Time resolution - value_resolution (Optional[Decimal]): Value resolution + time_resolution (Decimal | None): Time resolution + value_resolution (Decimal | None): Value resolution Returns: TimeSeries: A new discretized time series. diff --git a/src/braket/tracking/pricing.py b/src/braket/tracking/pricing.py index c269208c2..3bf379393 100644 --- a/src/braket/tracking/pricing.py +++ b/src/braket/tracking/pricing.py @@ -33,7 +33,7 @@ def get_prices(self) -> None: http = urllib3.PoolManager() price_url = os.environ.get( "BRAKET_PRICE_OFFERS_URL", - "https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/AmazonBraket/current/index.csv", # noqa: E501 + "https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/AmazonBraket/current/index.csv", ) response = http.request( "GET", @@ -42,7 +42,7 @@ def get_prices(self) -> None: ) response.auto_close = False - text_response = io.TextIOWrapper(response) + text_response = io.TextIOWrapper(response, encoding="utf-8") # Data starts on line 6 # @@ -53,7 +53,7 @@ def get_prices(self) -> None: text_response.readline() self._price_list = list(csv.DictReader(text_response)) - @lru_cache + @lru_cache # noqa: B019 def price_search(self, **kwargs: str) -> list[dict[str, str]]: """Searches the price list for a given set of parameters. diff --git a/src/braket/tracking/tracker.py b/src/braket/tracking/tracker.py index 47c13625a..3b6214759 100644 --- a/src/braket/tracking/tracker.py +++ b/src/braket/tracking/tracker.py @@ -50,7 +50,7 @@ def start(self) -> Tracker: Returns: Tracker: self. """ - return self.__enter__() + return self.__enter__() # noqa: PLC2801 def stop(self) -> Tracker: """Stop tracking resources with this tracker. @@ -91,7 +91,7 @@ def qpu_tasks_cost(self) -> Decimal: total_cost = Decimal(0) for task_arn, details in self._resources.items(): if "qpu" in details["device"]: - total_cost = total_cost + _get_qpu_task_cost(task_arn, details) + total_cost += _get_qpu_task_cost(task_arn, details) return total_cost def simulator_tasks_cost(self) -> Decimal: @@ -114,7 +114,7 @@ def simulator_tasks_cost(self) -> Decimal: total_cost = Decimal(0) for task_arn, details in self._resources.items(): if "simulator" in details["device"]: - total_cost = total_cost + _get_simulator_task_cost(task_arn, details) + total_cost += _get_simulator_task_cost(task_arn, details) return total_cost def quantum_tasks_statistics(self) -> dict[str, dict[str, Any]]: @@ -142,7 +142,7 @@ def quantum_tasks_statistics(self) -> dict[str, dict[str, Any]]: 'billed_execution_duration' : datetime.timedelta(seconds=6, microseconds=123456)}} """ stats = {} - for _, details in self._resources.items(): + for details in self._resources.values(): device_stats = stats.get(details["device"], {}) shots = device_stats.get("shots", 0) + details["shots"] @@ -212,7 +212,7 @@ def _(self, event: _TaskCompletionEvent) -> None: def _get_qpu_task_cost(task_arn: str, details: dict) -> Decimal: - if details["status"] in ["FAILED", "CANCELLED"] or details.get("has_reservation_arn"): + if details["status"] in {"FAILED", "CANCELLED"} or details.get("has_reservation_arn"): return Decimal(0) task_region = task_arn.split(":")[3] @@ -291,10 +291,8 @@ def _get_simulator_task_cost(task_arn: str, details: dict) -> Decimal: if duration_price["Currency"] != "USD": raise ValueError(f"Expected USD, found {duration_price['Currency']}") - duration_cost = ( + return ( Decimal(duration_price["PricePerUnit"]) * Decimal(details["billed_duration"] / timedelta(milliseconds=1)) / Decimal(timedelta(**{duration_price["Unit"]: 1}) / timedelta(milliseconds=1)) ) - - return duration_cost diff --git a/src/braket/tracking/tracking_context.py b/src/braket/tracking/tracking_context.py index 37f4a3dc0..309383c1f 100644 --- a/src/braket/tracking/tracking_context.py +++ b/src/braket/tracking/tracking_context.py @@ -18,7 +18,7 @@ class TrackingContext: def __init__(self): self._trackers = set() - def register_tracker(self, tracker: Tracker) -> None: # noqa F821 + def register_tracker(self, tracker: Tracker) -> None: # noqa: F821 """Registers a tracker. Args: @@ -26,7 +26,7 @@ def register_tracker(self, tracker: Tracker) -> None: # noqa F821 """ self._trackers.add(tracker) - def deregister_tracker(self, tracker: Tracker) -> None: # noqa F821 + def deregister_tracker(self, tracker: Tracker) -> None: # noqa: F821 """Deregisters a tracker. Args: @@ -34,7 +34,7 @@ def deregister_tracker(self, tracker: Tracker) -> None: # noqa F821 """ self._trackers.remove(tracker) - def broadcast_event(self, event: _TrackingEvent) -> None: # noqa F821 + def broadcast_event(self, event: _TrackingEvent) -> None: # noqa: F821 """Broadcasts an event to all trackers. Args: diff --git a/src/braket/tracking/tracking_events.py b/src/braket/tracking/tracking_events.py index 793ff038c..689640632 100644 --- a/src/braket/tracking/tracking_events.py +++ b/src/braket/tracking/tracking_events.py @@ -14,7 +14,6 @@ from __future__ import annotations from dataclasses import dataclass -from typing import Optional @dataclass @@ -31,7 +30,7 @@ class _TaskCreationEvent(_TrackingEvent): @dataclass class _TaskCompletionEvent(_TrackingEvent): - execution_duration: Optional[float] + execution_duration: float | None status: str has_reservation_arn: bool = False diff --git a/test/integ_tests/gate_model_device_testing_utils.py b/test/integ_tests/gate_model_device_testing_utils.py index 901cc819e..2227f31a3 100644 --- a/test/integ_tests/gate_model_device_testing_utils.py +++ b/test/integ_tests/gate_model_device_testing_utils.py @@ -335,14 +335,12 @@ def result_types_tensor_hermitian_hermitian_testing(device: Device, run_kwargs: phi = 0.123 varphi = -0.543 matrix1 = np.array([[1, 2], [2, 4]]) - matrix2 = np.array( - [ - [-6, 2 + 1j, -3, -5 + 2j], - [2 - 1j, 0, 2 - 1j, -5 + 4j], - [-3, 2 + 1j, 0, -4 + 3j], - [-5 - 2j, -5 - 4j, -4 - 3j, -6], - ] - ) + matrix2 = np.array([ + [-6, 2 + 1j, -3, -5 + 2j], + [2 - 1j, 0, 2 - 1j, -5 + 4j], + [-3, 2 + 1j, 0, -4 + 3j], + [-5 - 2j, -5 - 4j, -4 - 3j, -6], + ]) obs = Observable.Hermitian(matrix1) @ Observable.Hermitian(matrix2) obs_targets = [0, 1, 2] circuit = get_result_types_three_qubit_circuit(theta, phi, varphi, obs, obs_targets, shots) @@ -391,14 +389,12 @@ def result_types_tensor_z_hermitian_testing(device: Device, run_kwargs: dict[str theta = 0.432 phi = 0.123 varphi = -0.543 - array = np.array( - [ - [-6, 2 + 1j, -3, -5 + 2j], - [2 - 1j, 0, 2 - 1j, -5 + 4j], - [-3, 2 + 1j, 0, -4 + 3j], - [-5 - 2j, -5 - 4j, -4 - 3j, -6], - ] - ) + array = np.array([ + [-6, 2 + 1j, -3, -5 + 2j], + [2 - 1j, 0, 2 - 1j, -5 + 4j], + [-3, 2 + 1j, 0, -4 + 3j], + [-5 - 2j, -5 - 4j, -4 - 3j, -6], + ]) obs = Observable.Z() @ Observable.Hermitian(array) obs_targets = [0, 1, 2] circuit = get_result_types_three_qubit_circuit(theta, phi, varphi, obs, obs_targets, shots) @@ -455,14 +451,12 @@ def result_types_tensor_y_hermitian_testing(device: Device, run_kwargs: dict[str theta = 0.432 phi = 0.123 varphi = -0.543 - array = np.array( - [ - [-6, 2 + 1j, -3, -5 + 2j], - [2 - 1j, 0, 2 - 1j, -5 + 4j], - [-3, 2 + 1j, 0, -4 + 3j], - [-5 - 2j, -5 - 4j, -4 - 3j, -6], - ] - ) + array = np.array([ + [-6, 2 + 1j, -3, -5 + 2j], + [2 - 1j, 0, 2 - 1j, -5 + 4j], + [-3, 2 + 1j, 0, -4 + 3j], + [-5 - 2j, -5 - 4j, -4 - 3j, -6], + ]) obs = Observable.Y() @ Observable.Hermitian(array) obs_targets = [0, 1, 2] circuit = get_result_types_three_qubit_circuit(theta, phi, varphi, obs, obs_targets, shots) @@ -484,14 +478,12 @@ def result_types_noncommuting_testing(device: Device, run_kwargs: dict[str, Any] theta = 0.432 phi = 0.123 varphi = -0.543 - array = np.array( - [ - [-6, 2 + 1j, -3, -5 + 2j], - [2 - 1j, 0, 2 - 1j, -5 + 4j], - [-3, 2 + 1j, 0, -4 + 3j], - [-5 - 2j, -5 - 4j, -4 - 3j, -6], - ] - ) + array = np.array([ + [-6, 2 + 1j, -3, -5 + 2j], + [2 - 1j, 0, 2 - 1j, -5 + 4j], + [-3, 2 + 1j, 0, -4 + 3j], + [-5 - 2j, -5 - 4j, -4 - 3j, -6], + ]) obs1 = Observable.X() @ Observable.Y() obs1_targets = [0, 2] obs2 = Observable.Z() @ Observable.Z() diff --git a/test/integ_tests/test_pulse.py b/test/integ_tests/test_pulse.py index e5f42bcd3..59b5d24a9 100644 --- a/test/integ_tests/test_pulse.py +++ b/test/integ_tests/test_pulse.py @@ -16,134 +16,132 @@ def device(): @pytest.fixture def arbitrary_waveform(): - return ArbitraryWaveform( - [ - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.00017888439538396808, - 0.00046751103636033026, - 0.0011372942989106456, - 0.002577059611929697, - 0.005443941944632366, - 0.010731922770068104, - 0.01976701723583167, - 0.03406712171899736, - 0.05503285980691202, - 0.08350670755829034, - 0.11932853352131022, - 0.16107456696238298, - 0.20614055551722368, - 0.2512065440720643, - 0.292952577513137, - 0.328774403476157, - 0.3572482512275353, - 0.3782139893154499, - 0.3925140937986156, - 0.40154918826437913, - 0.4068371690898149, - 0.4097040514225177, - 0.41114381673553674, - 0.411813599998087, - 0.4121022266390633, - 0.4122174383870584, - 0.41226003881132406, - 0.4122746298554775, - 0.4122792591252675, - 0.4122806196003006, - 0.41228098995582513, - 0.41228108334474756, - 0.4122811051578895, - 0.4122811098772742, - 0.4122811108230642, - 0.4122811109986316, - 0.41228111102881937, - 0.41228111103362725, - 0.4122811110343365, - 0.41228111103443343, - 0.4122811110344457, - 0.4122811110344471, - 0.41228111103444737, - 0.41228111103444737, - 0.41228111103444737, - 0.41228111103444737, - 0.41228111103444737, - 0.41228111103444737, - 0.41228111103444737, - 0.41228111103444737, - 0.41228111103444737, - 0.41228111103444737, - 0.41228111103444737, - 0.41228111103444737, - 0.41228111103444737, - 0.41228111103444737, - 0.41228111103444737, - 0.41228111103444737, - 0.41228111103444737, - 0.41228111103444737, - 0.41228111103444737, - 0.41228111103444737, - 0.41228111103444737, - 0.41228111103444737, - 0.41228111103444737, - 0.41228111103444737, - 0.41228111103444737, - 0.4122811110344471, - 0.4122811110344457, - 0.41228111103443343, - 0.4122811110343365, - 0.41228111103362725, - 0.41228111102881937, - 0.4122811109986316, - 0.4122811108230642, - 0.4122811098772742, - 0.4122811051578895, - 0.41228108334474756, - 0.41228098995582513, - 0.4122806196003006, - 0.4122792591252675, - 0.4122746298554775, - 0.41226003881132406, - 0.4122174383870584, - 0.4121022266390633, - 0.411813599998087, - 0.41114381673553674, - 0.4097040514225176, - 0.4068371690898149, - 0.40154918826437913, - 0.3925140937986155, - 0.37821398931544986, - 0.3572482512275351, - 0.32877440347615655, - 0.2929525775131368, - 0.2512065440720641, - 0.20614055551722307, - 0.16107456696238268, - 0.11932853352131002, - 0.08350670755829034, - 0.05503285980691184, - 0.03406712171899729, - 0.01976701723583167, - 0.010731922770068058, - 0.005443941944632366, - 0.002577059611929697, - 0.0011372942989106229, - 0.00046751103636033026, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - ] - ) + return ArbitraryWaveform([ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.00017888439538396808, + 0.00046751103636033026, + 0.0011372942989106456, + 0.002577059611929697, + 0.005443941944632366, + 0.010731922770068104, + 0.01976701723583167, + 0.03406712171899736, + 0.05503285980691202, + 0.08350670755829034, + 0.11932853352131022, + 0.16107456696238298, + 0.20614055551722368, + 0.2512065440720643, + 0.292952577513137, + 0.328774403476157, + 0.3572482512275353, + 0.3782139893154499, + 0.3925140937986156, + 0.40154918826437913, + 0.4068371690898149, + 0.4097040514225177, + 0.41114381673553674, + 0.411813599998087, + 0.4121022266390633, + 0.4122174383870584, + 0.41226003881132406, + 0.4122746298554775, + 0.4122792591252675, + 0.4122806196003006, + 0.41228098995582513, + 0.41228108334474756, + 0.4122811051578895, + 0.4122811098772742, + 0.4122811108230642, + 0.4122811109986316, + 0.41228111102881937, + 0.41228111103362725, + 0.4122811110343365, + 0.41228111103443343, + 0.4122811110344457, + 0.4122811110344471, + 0.41228111103444737, + 0.41228111103444737, + 0.41228111103444737, + 0.41228111103444737, + 0.41228111103444737, + 0.41228111103444737, + 0.41228111103444737, + 0.41228111103444737, + 0.41228111103444737, + 0.41228111103444737, + 0.41228111103444737, + 0.41228111103444737, + 0.41228111103444737, + 0.41228111103444737, + 0.41228111103444737, + 0.41228111103444737, + 0.41228111103444737, + 0.41228111103444737, + 0.41228111103444737, + 0.41228111103444737, + 0.41228111103444737, + 0.41228111103444737, + 0.41228111103444737, + 0.41228111103444737, + 0.41228111103444737, + 0.4122811110344471, + 0.4122811110344457, + 0.41228111103443343, + 0.4122811110343365, + 0.41228111103362725, + 0.41228111102881937, + 0.4122811109986316, + 0.4122811108230642, + 0.4122811098772742, + 0.4122811051578895, + 0.41228108334474756, + 0.41228098995582513, + 0.4122806196003006, + 0.4122792591252675, + 0.4122746298554775, + 0.41226003881132406, + 0.4122174383870584, + 0.4121022266390633, + 0.411813599998087, + 0.41114381673553674, + 0.4097040514225176, + 0.4068371690898149, + 0.40154918826437913, + 0.3925140937986155, + 0.37821398931544986, + 0.3572482512275351, + 0.32877440347615655, + 0.2929525775131368, + 0.2512065440720641, + 0.20614055551722307, + 0.16107456696238268, + 0.11932853352131002, + 0.08350670755829034, + 0.05503285980691184, + 0.03406712171899729, + 0.01976701723583167, + 0.010731922770068058, + 0.005443941944632366, + 0.002577059611929697, + 0.0011372942989106229, + 0.00046751103636033026, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + ]) @pytest.fixture diff --git a/test/unit_tests/braket/ahs/test_analog_hamiltonian_simulation.py b/test/unit_tests/braket/ahs/test_analog_hamiltonian_simulation.py index 3af8554a1..df18a0db9 100644 --- a/test/unit_tests/braket/ahs/test_analog_hamiltonian_simulation.py +++ b/test/unit_tests/braket/ahs/test_analog_hamiltonian_simulation.py @@ -354,13 +354,11 @@ def test_discretize(register, driving_field, local_detuning): def test_converting_numpy_array_sites_to_ir(driving_field): hamiltonian = driving_field - sites = np.array( - [ - [0.0, 0.0], - [0.0, 1.0e-6], - [1e-6, 2.0e-6], - ] - ) + sites = np.array([ + [0.0, 0.0], + [0.0, 1.0e-6], + [1e-6, 2.0e-6], + ]) register = AtomArrangement() for site in sites: register.add(site) @@ -385,14 +383,12 @@ def test_site_validation_wrong_length(): @pytest.mark.xfail(raises=TypeError) def test_site_validation_non_number(): register = AtomArrangement() - register.add( + register.add([ + "not-a-number", [ - "not-a-number", - [ - "also-not-a-number", - ], - ] - ) + "also-not-a-number", + ], + ]) @pytest.mark.xfail(raises=TypeError) diff --git a/test/unit_tests/braket/aws/common_test_utils.py b/test/unit_tests/braket/aws/common_test_utils.py index 0e1fd4d48..cf3c7e0d9 100644 --- a/test/unit_tests/braket/aws/common_test_utils.py +++ b/test/unit_tests/braket/aws/common_test_utils.py @@ -36,156 +36,146 @@ class MockS3: "deviceId": "default", } - MOCK_S3_RESULT_GATE_MODEL = json.dumps( - { - "braketSchemaHeader": { - "name": "braket.task_result.gate_model_task_result", - "version": "1", + MOCK_S3_RESULT_GATE_MODEL = json.dumps({ + "braketSchemaHeader": { + "name": "braket.task_result.gate_model_task_result", + "version": "1", + }, + "measurements": [[0, 0], [0, 0], [0, 0], [1, 1]], + "measuredQubits": [0, 1], + "taskMetadata": MOCK_TASK_METADATA, + "additionalMetadata": { + "action": { + "braketSchemaHeader": {"name": "braket.ir.jaqcd.program", "version": "1"}, + "instructions": [{"control": 0, "target": 1, "type": "cnot"}], }, - "measurements": [[0, 0], [0, 0], [0, 0], [1, 1]], - "measuredQubits": [0, 1], - "taskMetadata": MOCK_TASK_METADATA, - "additionalMetadata": { - "action": { - "braketSchemaHeader": {"name": "braket.ir.jaqcd.program", "version": "1"}, - "instructions": [{"control": 0, "target": 1, "type": "cnot"}], - }, - }, - } - ) + }, + }) - MOCK_S3_RESULT_GATE_MODEL_WITH_RESULT_TYPES = json.dumps( - { - "braketSchemaHeader": { - "name": "braket.task_result.gate_model_task_result", - "version": "1", + MOCK_S3_RESULT_GATE_MODEL_WITH_RESULT_TYPES = json.dumps({ + "braketSchemaHeader": { + "name": "braket.task_result.gate_model_task_result", + "version": "1", + }, + "measurements": [[0, 0], [0, 0], [0, 0], [1, 1]], + "measuredQubits": [0, 1], + "resultTypes": [ + { + "type": {"observable": ["h", "x"], "targets": [0, 1], "type": "expectation"}, + "value": 0.7071067811865474, }, - "measurements": [[0, 0], [0, 0], [0, 0], [1, 1]], - "measuredQubits": [0, 1], - "resultTypes": [ - { - "type": {"observable": ["h", "x"], "targets": [0, 1], "type": "expectation"}, - "value": 0.7071067811865474, - }, - { - "type": {"states": ["01", "10", "00", "11"], "type": "amplitude"}, - "value": { - "01": [0.0, 0.0], - "10": [0.0, 0.0], - "00": [0.7071067811865475, 0.0], - "11": [0.7071067811865475, 0.0], - }, - }, - ], - "taskMetadata": MOCK_TASK_METADATA, - "additionalMetadata": { - "action": { - "braketSchemaHeader": {"name": "braket.ir.jaqcd.program", "version": "1"}, - "instructions": [{"control": 0, "target": 1, "type": "cnot"}], + { + "type": {"states": ["01", "10", "00", "11"], "type": "amplitude"}, + "value": { + "01": [0.0, 0.0], + "10": [0.0, 0.0], + "00": [0.7071067811865475, 0.0], + "11": [0.7071067811865475, 0.0], }, }, - } - ) - - MOCK_S3_RESULT_ANNEALING = json.dumps( - { - "braketSchemaHeader": { - "name": "braket.task_result.annealing_task_result", - "version": "1", + ], + "taskMetadata": MOCK_TASK_METADATA, + "additionalMetadata": { + "action": { + "braketSchemaHeader": {"name": "braket.ir.jaqcd.program", "version": "1"}, + "instructions": [{"control": 0, "target": 1, "type": "cnot"}], }, - "solutions": [[-1, -1, -1, -1], [1, -1, 1, 1], [1, -1, -1, 1]], - "solutionCounts": [3, 2, 4], - "values": [0.0, 1.0, 2.0], - "variableCount": 4, - "taskMetadata": { - "id": "task_arn", - "shots": 100, - "deviceId": DWAVE_ARN, + }, + }) + + MOCK_S3_RESULT_ANNEALING = json.dumps({ + "braketSchemaHeader": { + "name": "braket.task_result.annealing_task_result", + "version": "1", + }, + "solutions": [[-1, -1, -1, -1], [1, -1, 1, 1], [1, -1, -1, 1]], + "solutionCounts": [3, 2, 4], + "values": [0.0, 1.0, 2.0], + "variableCount": 4, + "taskMetadata": { + "id": "task_arn", + "shots": 100, + "deviceId": DWAVE_ARN, + }, + "additionalMetadata": { + "action": { + "type": "ISING", + "linear": {"0": 0.3333, "1": -0.333, "4": -0.333, "5": 0.333}, + "quadratic": {"0,4": 0.667, "0,5": -1.0, "1,4": 0.667, "1,5": 0.667}, }, - "additionalMetadata": { - "action": { - "type": "ISING", - "linear": {"0": 0.3333, "1": -0.333, "4": -0.333, "5": 0.333}, - "quadratic": {"0,4": 0.667, "0,5": -1.0, "1,4": 0.667, "1,5": 0.667}, - }, - "dwaveMetadata": { - "activeVariables": [0], - "timing": { - "qpuSamplingTime": 100, - "qpuAnnealTimePerSample": 20, - "qpuAccessTime": 10917, - "qpuAccessOverheadTime": 3382, - "qpuReadoutTimePerSample": 274, - "qpuProgrammingTime": 9342, - "qpuDelayTimePerSample": 21, - "postProcessingOverheadTime": 117, - "totalPostProcessingTime": 117, - "totalRealTime": 10917, - "runTimeChip": 1575, - "annealTimePerRun": 20, - "readoutTimePerRun": 274, - }, + "dwaveMetadata": { + "activeVariables": [0], + "timing": { + "qpuSamplingTime": 100, + "qpuAnnealTimePerSample": 20, + "qpuAccessTime": 10917, + "qpuAccessOverheadTime": 3382, + "qpuReadoutTimePerSample": 274, + "qpuProgrammingTime": 9342, + "qpuDelayTimePerSample": 21, + "postProcessingOverheadTime": 117, + "totalPostProcessingTime": 117, + "totalRealTime": 10917, + "runTimeChip": 1575, + "annealTimePerRun": 20, + "readoutTimePerRun": 274, }, }, - } - ) + }, + }) - MOCK_S3_RESULT_PHOTONIC_MODEL = json.dumps( - { - "braketSchemaHeader": { - "name": "braket.task_result.photonic_model_task_result", - "version": "1", + MOCK_S3_RESULT_PHOTONIC_MODEL = json.dumps({ + "braketSchemaHeader": { + "name": "braket.task_result.photonic_model_task_result", + "version": "1", + }, + "measurements": [[[1, 2, 3, 4]], [[4, 3, 2, 1]], [[0, 0, 0, 0]]], + "taskMetadata": { + "id": "task_arn", + "shots": 3, + "deviceId": XANADU_ARN, + }, + "additionalMetadata": { + "action": { + "source": "Vac | q[0]", }, - "measurements": [[[1, 2, 3, 4]], [[4, 3, 2, 1]], [[0, 0, 0, 0]]], - "taskMetadata": { - "id": "task_arn", - "shots": 3, - "deviceId": XANADU_ARN, + "xanaduMetadata": { + "compiledProgram": "DECLARE ro BIT[2];", }, - "additionalMetadata": { - "action": { - "source": "Vac | q[0]", - }, - "xanaduMetadata": { - "compiledProgram": "DECLARE ro BIT[2];", + }, + }) + + MOCK_S3_RESULT_ANALOG_HAMILTONIAN_SIMULTION = json.dumps({ + "braketSchemaHeader": { + "name": "braket.task_result.analog_hamiltonian_simulation_task_result", + "version": "1", + }, + "taskMetadata": { + "id": "task_arn", + "shots": 3, + "deviceId": "mock_arn", + }, + "measurements": [ + { + "shotMetadata": {"shotStatus": "Success"}, + "shotResult": { + "preSequence": [1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1], + "postSequence": [0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0], }, }, - } - ) - - MOCK_S3_RESULT_ANALOG_HAMILTONIAN_SIMULTION = json.dumps( - { - "braketSchemaHeader": { - "name": "braket.task_result.analog_hamiltonian_simulation_task_result", - "version": "1", + { + "shotMetadata": {"shotStatus": "Partial Success"}, + "shotResult": { + "preSequence": [1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1], + "postSequence": None, + }, }, - "taskMetadata": { - "id": "task_arn", - "shots": 3, - "deviceId": "mock_arn", + { + "shotMetadata": {"shotStatus": "Failure"}, + "shotResult": {"preSequence": None, "postSequence": None}, }, - "measurements": [ - { - "shotMetadata": {"shotStatus": "Success"}, - "shotResult": { - "preSequence": [1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1], - "postSequence": [0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0], - }, - }, - { - "shotMetadata": {"shotStatus": "Partial Success"}, - "shotResult": { - "preSequence": [1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1], - "postSequence": None, - }, - }, - { - "shotMetadata": {"shotStatus": "Failure"}, - "shotResult": {"preSequence": None, "postSequence": None}, - }, - ], - } - ) + ], + }) def run_and_assert( @@ -352,19 +342,15 @@ def _create_task_args_and_kwargs( ] create_args += extra_args or [] create_kwargs = extra_kwargs or {} - create_kwargs.update( - { - "poll_timeout_seconds": ( - poll_timeout_seconds if poll_timeout_seconds is not None else default_poll_timeout - ), - "poll_interval_seconds": ( - poll_interval_seconds - if poll_interval_seconds is not None - else default_poll_interval - ), - "inputs": inputs, - "gate_definitions": gate_definitions, - "reservation_arn": reservation_arn, - } - ) + create_kwargs.update({ + "poll_timeout_seconds": ( + poll_timeout_seconds if poll_timeout_seconds is not None else default_poll_timeout + ), + "poll_interval_seconds": ( + poll_interval_seconds if poll_interval_seconds is not None else default_poll_interval + ), + "inputs": inputs, + "gate_definitions": gate_definitions, + "reservation_arn": reservation_arn, + }) return create_args, create_kwargs diff --git a/test/unit_tests/braket/aws/test_aws_device.py b/test/unit_tests/braket/aws/test_aws_device.py index 3fed52aa2..fd1bcacde 100644 --- a/test/unit_tests/braket/aws/test_aws_device.py +++ b/test/unit_tests/braket/aws/test_aws_device.py @@ -1902,7 +1902,6 @@ def test_get_devices_invalid_order_by(): @patch("braket.aws.aws_device.datetime") def test_get_device_availability(mock_utc_now): - class Expando: pass @@ -1913,13 +1912,11 @@ def __init__(self, status, *execution_window_args): self._properties.service = Expando() execution_windows = [ DeviceExecutionWindow.parse_raw( - json.dumps( - { - "executionDay": execution_day, - "windowStartHour": window_start_hour, - "windowEndHour": window_end_hour, - } - ) + json.dumps({ + "executionDay": execution_day, + "windowStartHour": window_start_hour, + "windowEndHour": window_end_hour, + }) ) for execution_day, window_start_hour, window_end_hour in execution_window_args ] @@ -2021,7 +2018,7 @@ def __init__(self, status, *execution_window_args): for test_set in test_sets: for test_item in test_set["test_items"]: test_date = test_item[0] - mock_utc_now.utcnow.return_value = test_date + mock_utc_now.now.return_value = test_date # flake8: noqa: C501 for i in range(len(test_item[1])): @@ -2034,9 +2031,9 @@ def __init__(self, status, *execution_window_args): ) expected = bool(test_item[1][i]) actual = device.is_available - assert ( - expected == actual - ), f"device_name: {device_name}, test_date: {test_date}, expected: {expected}, actual: {actual}" + assert expected == actual, ( + f"device_name: {device_name}, test_date: {test_date}, expected: {expected}, actual: {actual}" + ) @pytest.mark.parametrize( @@ -2102,57 +2099,53 @@ def test_parse_calibration_data(): @pytest.mark.parametrize( "bad_input", [ - ( - { - "gates": { - "0": { - "rx": [ - { - "name": "rx", - "qubits": ["0"], - "arguments": ["-1.5707963267948966"], - "calibrations": [ - { - "name": "incorrect_instr", - "arguments": [ - {"name": "qubit", "value": "0", "type": "string"} - ], - } - ], - } - ] - } - }, - "waveforms": {}, - } - ), - ( - { - "gates": { - "0": { - "rx": [ - { - "name": "cphaseshift", - "qubits": ["0"], - "arguments": ["-1.5707963267948966"], - "calibrations": [ - { - "name": "delay", - "arguments": [ - {"name": "bad_value", "value": "1", "type": "float"}, - {"name": "qubit", "value": None, "type": "string"}, - ], - } - ], - } - ] - } - }, - "waveforms": { - "blankId_waveform": {"waveformId": "blankId_waveform", "name": "bad_waveform"}, - }, - } - ), + ({ + "gates": { + "0": { + "rx": [ + { + "name": "rx", + "qubits": ["0"], + "arguments": ["-1.5707963267948966"], + "calibrations": [ + { + "name": "incorrect_instr", + "arguments": [ + {"name": "qubit", "value": "0", "type": "string"} + ], + } + ], + } + ] + } + }, + "waveforms": {}, + }), + ({ + "gates": { + "0": { + "rx": [ + { + "name": "cphaseshift", + "qubits": ["0"], + "arguments": ["-1.5707963267948966"], + "calibrations": [ + { + "name": "delay", + "arguments": [ + {"name": "bad_value", "value": "1", "type": "float"}, + {"name": "qubit", "value": None, "type": "string"}, + ], + } + ], + } + ] + } + }, + "waveforms": { + "blankId_waveform": {"waveformId": "blankId_waveform", "name": "bad_waveform"}, + }, + }), ], ) @pytest.mark.xfail(raises=ValueError) diff --git a/test/unit_tests/braket/aws/test_aws_quantum_job.py b/test/unit_tests/braket/aws/test_aws_quantum_job.py index 028ad3cc4..34e86691a 100644 --- a/test/unit_tests/braket/aws/test_aws_quantum_job.py +++ b/test/unit_tests/braket/aws/test_aws_quantum_job.py @@ -286,16 +286,14 @@ def result_setup(quantum_job_name): with open(file_path, "w") as write_file: write_file.write( - json.dumps( - { - "braketSchemaHeader": { - "name": "braket.jobs_data.persisted_job_data", - "version": "1", - }, - "dataDictionary": {"converged": True, "energy": -0.2}, - "dataFormat": "plaintext", - } - ) + json.dumps({ + "braketSchemaHeader": { + "name": "braket.jobs_data.persisted_job_data", + "version": "1", + }, + "dataDictionary": {"converged": True, "energy": -0.2}, + "dataFormat": "plaintext", + }) ) with tarfile.open("model.tar.gz", "w:gz") as tar: @@ -737,16 +735,14 @@ def test_logs( quantum_job.logs(wait=True, poll_interval_seconds=0) captured = capsys.readouterr() - assert captured.out == "\n".join( - ( - "..", - "hi there #1", - "hi there #2", - "hi there #2a", - "hi there #3", - "", - ) - ) + assert captured.out == "\n".join(( + "..", + "hi there #1", + "hi there #2", + "hi there #2a", + "hi there #3", + "", + )) def test_logs_queue_progress( @@ -777,18 +773,16 @@ def test_logs_queue_progress( quantum_job.logs(wait=True, poll_interval_seconds=0) captured = capsys.readouterr() - assert captured.out == "\n".join( - ( - f"Job queue position: {queue_info['position']}", - "Running:", - "", - "hi there #1", - "hi there #2", - "hi there #2a", - "hi there #3", - "", - ) - ) + assert captured.out == "\n".join(( + f"Job queue position: {queue_info['position']}", + "Running:", + "", + "hi there #1", + "hi there #2", + "hi there #2a", + "hi there #3", + "", + )) @patch.dict("os.environ", {"JPY_PARENT_PID": "True"}) @@ -859,21 +853,19 @@ def get_log_events(log_group, log_stream, start_time, start_from_head, next_toke quantum_job.logs(wait=True, poll_interval_seconds=0) captured = capsys.readouterr() - assert captured.out == "\n".join( - ( - "..", - "\x1b[34mhi there #1\x1b[0m", - "\x1b[35mhi there #1\x1b[0m", - "\x1b[34mhi there #2\x1b[0m", - "\x1b[35mhi there #2\x1b[0m", - "\x1b[34mhi there #2a\x1b[0m", - "\x1b[35mhi there #2a\x1b[0m", - "\x1b[34mhi there #3\x1b[0m", - "\x1b[35mhi there #3\x1b[0m", - "\x1b[35mhi there #4\x1b[0m", - "", - ) - ) + assert captured.out == "\n".join(( + "..", + "\x1b[34mhi there #1\x1b[0m", + "\x1b[35mhi there #1\x1b[0m", + "\x1b[34mhi there #2\x1b[0m", + "\x1b[35mhi there #2\x1b[0m", + "\x1b[34mhi there #2a\x1b[0m", + "\x1b[35mhi there #2a\x1b[0m", + "\x1b[34mhi there #3\x1b[0m", + "\x1b[35mhi there #3\x1b[0m", + "\x1b[35mhi there #4\x1b[0m", + "", + )) def test_logs_error(quantum_job, generate_get_job_response, capsys): diff --git a/test/unit_tests/braket/aws/test_aws_quantum_task.py b/test/unit_tests/braket/aws/test_aws_quantum_task.py index 51fe2c75f..f92a6e196 100644 --- a/test/unit_tests/braket/aws/test_aws_quantum_task.py +++ b/test/unit_tests/braket/aws/test_aws_quantum_task.py @@ -696,14 +696,12 @@ def test_create_task_with_reservation_arn(aws_session, arn, ahs_problem): def test_create_pulse_sequence(aws_session, arn, pulse_sequence): - expected_openqasm = "\n".join( - [ - "OPENQASM 3.0;", - "cal {", - " set_frequency(predefined_frame_1, 6000000.0);", - "}", - ] - ) + expected_openqasm = "\n".join([ + "OPENQASM 3.0;", + "cal {", + " set_frequency(predefined_frame_1, 6000000.0);", + "}", + ]) expected_program = OpenQASMProgram(source=expected_openqasm, inputs={}) aws_session.create_quantum_task.return_value = arn @@ -723,17 +721,15 @@ def test_create_pulse_gate_circuit( aws_session, arn, pulse_sequence, device_arn, device_parameters_class ): pulse_gate_circuit = Circuit().pulse_gate([0, 1], pulse_sequence, "my_PG") - expected_openqasm = "\n".join( - ( - "OPENQASM 3.0;", - "bit[2] b;", - "cal {", - " set_frequency(predefined_frame_1, 6000000.0);", - "}", - "b[0] = measure $0;", - "b[1] = measure $1;", - ) - ) + expected_openqasm = "\n".join(( + "OPENQASM 3.0;", + "bit[2] b;", + "cal {", + " set_frequency(predefined_frame_1, 6000000.0);", + "}", + "b[0] = measure $0;", + "b[1] = measure $1;", + )) expected_program = OpenQASMProgram(source=expected_openqasm, inputs={}) @@ -1042,29 +1038,27 @@ def test_create_circuit_with_shots_value_error(aws_session, arn, circuit): "arn:aws:braket:::device/qpu/d-wave/DW_2000Q_6", ), ( - DwaveDeviceParameters.parse_obj( - { - "providerLevelParameters": { - "postprocessingType": "OPTIMIZATION", - "annealingOffsets": [3.67, 6.123], - "annealingSchedule": [[13.37, 10.08], [3.14, 1.618]], - "annealingDuration": 1, - "autoScale": False, - "beta": 0.2, - "chains": [[0, 1, 5], [6]], - "compensateFluxDrift": False, - "fluxBiases": [1.1, 2.2, 3.3, 4.4], - "initialState": [1, 3, 0, 1], - "maxResults": 1, - "programmingThermalizationDuration": 625, - "readoutThermalizationDuration": 256, - "reduceIntersampleCorrelation": False, - "reinitializeState": True, - "resultFormat": "RAW", - "spinReversalTransformCount": 100, - } + DwaveDeviceParameters.parse_obj({ + "providerLevelParameters": { + "postprocessingType": "OPTIMIZATION", + "annealingOffsets": [3.67, 6.123], + "annealingSchedule": [[13.37, 10.08], [3.14, 1.618]], + "annealingDuration": 1, + "autoScale": False, + "beta": 0.2, + "chains": [[0, 1, 5], [6]], + "compensateFluxDrift": False, + "fluxBiases": [1.1, 2.2, 3.3, 4.4], + "initialState": [1, 3, 0, 1], + "maxResults": 1, + "programmingThermalizationDuration": 625, + "readoutThermalizationDuration": 256, + "reduceIntersampleCorrelation": False, + "reinitializeState": True, + "resultFormat": "RAW", + "spinReversalTransformCount": 100, } - ), + }), "arn:aws:braket:::device/qpu/d-wave/Advantage_system1", ), ( @@ -1119,29 +1113,27 @@ def test_create_circuit_with_shots_value_error(aws_session, arn, circuit): "arn:aws:braket:::device/qpu/d-wave/Advantage_system1", ), ( - Dwave2000QDeviceParameters.parse_obj( - { - "deviceLevelParameters": { - "postprocessingType": "OPTIMIZATION", - "annealingOffsets": [3.67, 6.123], - "annealingSchedule": [[13.37, 10.08], [3.14, 1.618]], - "annealingDuration": 1, - "autoScale": False, - "beta": 0.2, - "chains": [[0, 1, 5], [6]], - "compensateFluxDrift": False, - "fluxBiases": [1.1, 2.2, 3.3, 4.4], - "initialState": [1, 3, 0, 1], - "maxResults": 1, - "programmingThermalizationDuration": 625, - "readoutThermalizationDuration": 256, - "reduceIntersampleCorrelation": False, - "reinitializeState": True, - "resultFormat": "RAW", - "spinReversalTransformCount": 100, - } + Dwave2000QDeviceParameters.parse_obj({ + "deviceLevelParameters": { + "postprocessingType": "OPTIMIZATION", + "annealingOffsets": [3.67, 6.123], + "annealingSchedule": [[13.37, 10.08], [3.14, 1.618]], + "annealingDuration": 1, + "autoScale": False, + "beta": 0.2, + "chains": [[0, 1, 5], [6]], + "compensateFluxDrift": False, + "fluxBiases": [1.1, 2.2, 3.3, 4.4], + "initialState": [1, 3, 0, 1], + "maxResults": 1, + "programmingThermalizationDuration": 625, + "readoutThermalizationDuration": 256, + "reduceIntersampleCorrelation": False, + "reinitializeState": True, + "resultFormat": "RAW", + "spinReversalTransformCount": 100, } - ), + }), "arn:aws:braket:::device/qpu/d-wave/DW_2000Q_6", ), ( diff --git a/test/unit_tests/braket/aws/test_aws_quantum_task_batch.py b/test/unit_tests/braket/aws/test_aws_quantum_task_batch.py index 2c748ecea..d5f2331d4 100644 --- a/test/unit_tests/braket/aws/test_aws_quantum_task_batch.py +++ b/test/unit_tests/braket/aws/test_aws_quantum_task_batch.py @@ -41,8 +41,7 @@ def test_creation(mock_create): 1000, max_parallel=10, reservaion_arn=( - "arn:aws:braket:us-west-2:123456789123:" - "reservation/a1b123cd-45e6-789f-gh01-i234567jk8l9" + "arn:aws:braket:us-west-2:123456789123:reservation/a1b123cd-45e6-789f-gh01-i234567jk8l9" ), ) assert batch.size == batch_size @@ -69,8 +68,7 @@ def test_successful(mock_create): 1000, max_parallel=10, reservaion_arn=( - "arn:aws:braket:us-west-2:123456789123:" - "reservation/a1b123cd-45e6-789f-gh01-i234567jk8l9" + "arn:aws:braket:us-west-2:123456789123:reservation/a1b123cd-45e6-789f-gh01-i234567jk8l9" ), ) assert batch.size == batch_size @@ -96,8 +94,7 @@ def test_unsuccessful(mock_create): 1000, max_parallel=10, reservaion_arn=( - "arn:aws:braket:us-west-2:123456789123:" - "reservation/a1b123cd-45e6-789f-gh01-i234567jk8l9" + "arn:aws:braket:us-west-2:123456789123:reservation/a1b123cd-45e6-789f-gh01-i234567jk8l9" ), ) assert not batch.unfinished @@ -134,8 +131,7 @@ def test_retry(mock_create): 1000, max_parallel=10, reservaion_arn=( - "arn:aws:braket:us-west-2:123456789123:" - "reservation/a1b123cd-45e6-789f-gh01-i234567jk8l9" + "arn:aws:braket:us-west-2:123456789123:reservation/a1b123cd-45e6-789f-gh01-i234567jk8l9" ), ) assert not batch.unfinished diff --git a/test/unit_tests/braket/circuits/noise/test_noise_model.py b/test/unit_tests/braket/circuits/noise/test_noise_model.py index bf5974e41..c68ca7cf4 100644 --- a/test/unit_tests/braket/circuits/noise/test_noise_model.py +++ b/test/unit_tests/braket/circuits/noise/test_noise_model.py @@ -471,20 +471,20 @@ def test_remove_noise_at_invalid_index(): assert not "should not get here" -@pytest.mark.xfail(raises=ValueError) def test_add_invalid_noise(): noise_model = NoiseModel() - noise_model.add_noise(Mock(), Mock(spec=Criteria)) + with pytest.raises(TypeError): + noise_model.add_noise(Mock(), Mock(spec=Criteria)) -@pytest.mark.xfail(raises=ValueError) def test_add_invalid_criteria(): noise_model = NoiseModel() - noise_model.add_noise(Mock(spec=Noise), Mock()) + with pytest.raises(TypeError): + noise_model.add_noise(Mock(spec=Noise), Mock()) -@pytest.mark.xfail(raises=ValueError) def test_apply_to_circuit_list(): noise_model = NoiseModel() - noise_model.add_noise(Mock(), Mock(spec=Criteria)) - noise_model.apply([]) + with pytest.raises(TypeError): + noise_model.add_noise(Mock(), Mock(spec=Criteria)) + noise_model.apply([]) diff --git a/test/unit_tests/braket/circuits/test_ascii_circuit_diagram.py b/test/unit_tests/braket/circuits/test_ascii_circuit_diagram.py index b10891830..901bbbb9b 100644 --- a/test/unit_tests/braket/circuits/test_ascii_circuit_diagram.py +++ b/test/unit_tests/braket/circuits/test_ascii_circuit_diagram.py @@ -98,7 +98,7 @@ def test_one_gate_with_zero_global_phase(): def test_one_gate_one_qubit_rotation_with_unicode(): - theta = FreeParameter("\u03B8") + theta = FreeParameter("\u03b8") circ = Circuit().rx(angle=theta, target=0) # Column formats to length of the gate plus the ascii representation for the angle. expected = ( @@ -114,7 +114,7 @@ def test_one_gate_one_qubit_rotation_with_unicode(): def test_one_gate_with_parametric_expression_global_phase_(): - theta = FreeParameter("\u03B8") + theta = FreeParameter("\u03b8") circ = Circuit().x(target=0).gphase(2 * theta).x(0).gphase(1) expected = ( "T : |0| 1 | 2 |", diff --git a/test/unit_tests/braket/circuits/test_basis_state.py b/test/unit_tests/braket/circuits/test_basis_state.py index 166e7c8fc..0ce4eab38 100644 --- a/test/unit_tests/braket/circuits/test_basis_state.py +++ b/test/unit_tests/braket/circuits/test_basis_state.py @@ -98,11 +98,9 @@ def test_indexing(basis_state_input, index, substate_input): def test_bool(): - assert all( - [ - BasisState("100"), - BasisState("111"), - BasisState("1"), - ] - ) + assert all([ + BasisState("100"), + BasisState("111"), + BasisState("1"), + ]) assert not BasisState("0") diff --git a/test/unit_tests/braket/circuits/test_circuit.py b/test/unit_tests/braket/circuits/test_circuit.py index 897828b27..a6ed047c6 100644 --- a/test/unit_tests/braket/circuits/test_circuit.py +++ b/test/unit_tests/braket/circuits/test_circuit.py @@ -178,13 +178,11 @@ def gate_calibrations(pulse_sequence, pulse_sequence_2): Gate.MS(FreeParameter("alpha"), FreeParameter("beta"), FreeParameter("gamma")), QubitSet([0, 1]), ) - return GateCalibrations( - { - calibration_key: pulse_sequence, - calibration_key_2: pulse_sequence, - calibration_key_3: pulse_sequence_2, - } - ) + return GateCalibrations({ + calibration_key: pulse_sequence, + calibration_key_2: pulse_sequence, + calibration_key_3: pulse_sequence_2, + }) def test_repr_instructions(h): @@ -632,19 +630,17 @@ def test_measure_verbatim_box(): .add_instruction(Instruction(Measure(), 0)) ) expected_ir = OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "bit[1] b;", - "qubit[2] q;", - "#pragma braket verbatim", - "box{", - "x q[0];", - "x q[1];", - "}", - "b[0] = measure q[0];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "bit[1] b;", + "qubit[2] q;", + "#pragma braket verbatim", + "box{", + "x q[0];", + "x q[1];", + "}", + "b[0] = measure q[0];", + ]), inputs={}, ) assert circ == expected @@ -816,18 +812,16 @@ def test_measure_gate_after_measurement(): def test_to_ir_with_measure(): circ = Circuit().h(0).cnot(0, 1).cnot(1, 2).measure([0, 2]) expected_ir = OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "bit[2] b;", - "qubit[3] q;", - "h q[0];", - "cnot q[0], q[1];", - "cnot q[1], q[2];", - "b[0] = measure q[0];", - "b[1] = measure q[2];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "bit[2] b;", + "qubit[3] q;", + "h q[0];", + "cnot q[0], q[1];", + "cnot q[1], q[2];", + "b[0] = measure q[0];", + "b[1] = measure q[2];", + ]), inputs={}, ) assert circ.to_ir("OPENQASM") == expected_ir @@ -835,18 +829,16 @@ def test_to_ir_with_measure(): def test_from_ir_with_measure(): ir = OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "bit[1] b;", - "qubit[3] q;", - "h q[0];", - "cnot q[0], q[1];", - "cnot q[1], q[2];", - "b[0] = measure q[0];", - "b[1] = measure q[2];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "bit[1] b;", + "qubit[3] q;", + "h q[0];", + "cnot q[0], q[1];", + "cnot q[1], q[2];", + "b[0] = measure q[0];", + "b[1] = measure q[2];", + ]), inputs={}, ) expected_circ = Circuit().h(0).cnot(0, 1).cnot(1, 2).measure(0).measure(2) @@ -855,16 +847,14 @@ def test_from_ir_with_measure(): def test_from_ir_with_single_measure(): ir = OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "bit[2] b;", - "qubit[2] q;", - "h q[0];", - "cnot q[0], q[1];", - "b = measure q;", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "bit[2] b;", + "qubit[2] q;", + "h q[0];", + "cnot q[0], q[1];", + "b = measure q;", + ]), inputs={}, ) expected_circ = Circuit().h(0).cnot(0, 1).measure(0).measure(1) @@ -874,16 +864,14 @@ def test_from_ir_with_single_measure(): def test_from_ir_round_trip_transformation(): circuit = Circuit().h(0).cnot(0, 1).measure(0).measure(1) ir = OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "bit[2] b;", - "qubit[2] q;", - "h q[0];", - "cnot q[0], q[1];", - "b = measure q;", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "bit[2] b;", + "qubit[2] q;", + "h q[0];", + "cnot q[0], q[1];", + "b = measure q;", + ]), inputs={}, ) @@ -1077,19 +1065,17 @@ def test_ir_non_empty_instructions_result_types_basis_rotation_instructions(): .rx(2, 3 * FreeParameterExpression(1)), OpenQASMSerializationProperties(QubitReferenceType.VIRTUAL), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "bit[3] b;", - "qubit[3] q;", - "rx(0.15) q[0];", - "ry(0.3) q[1];", - "rx(3) q[2];", - "b[0] = measure q[0];", - "b[1] = measure q[1];", - "b[2] = measure q[2];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "bit[3] b;", + "qubit[3] q;", + "rx(0.15) q[0];", + "ry(0.3) q[1];", + "rx(3) q[2];", + "b[0] = measure q[0];", + "b[1] = measure q[1];", + "b[2] = measure q[2];", + ]), inputs={}, ), ), @@ -1112,29 +1098,27 @@ def test_circuit_to_ir_openqasm(circuit, serialization_properties, expected_ir): Circuit().rx(0, 0.15).rx(1, 0.3), OpenQASMSerializationProperties(QubitReferenceType.VIRTUAL), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "bit[2] b;", - "qubit[2] q;", - "cal {", - " waveform drag_gauss_wf = drag_gaussian" - + "(3.0ms, 400.0ms, 0.2, 1, false);", - "}", - "defcal z $0, $1 {", - " set_frequency(predefined_frame_1, 6000000.0);", - " play(predefined_frame_1, drag_gauss_wf);", - "}", - "defcal rx(0.15) $0 {", - " set_frequency(predefined_frame_1, 6000000.0);", - " play(predefined_frame_1, drag_gauss_wf);", - "}", - "rx(0.15) q[0];", - "rx(0.3) q[1];", - "b[0] = measure q[0];", - "b[1] = measure q[1];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "bit[2] b;", + "qubit[2] q;", + "cal {", + " waveform drag_gauss_wf = drag_gaussian" + + "(3.0ms, 400.0ms, 0.2, 1, false);", + "}", + "defcal z $0, $1 {", + " set_frequency(predefined_frame_1, 6000000.0);", + " play(predefined_frame_1, drag_gauss_wf);", + "}", + "defcal rx(0.15) $0 {", + " set_frequency(predefined_frame_1, 6000000.0);", + " play(predefined_frame_1, drag_gauss_wf);", + "}", + "rx(0.15) q[0];", + "rx(0.3) q[1];", + "b[0] = measure q[0];", + "b[1] = measure q[1];", + ]), inputs={}, ), ), @@ -1142,28 +1126,26 @@ def test_circuit_to_ir_openqasm(circuit, serialization_properties, expected_ir): Circuit().rx(0, 0.15).rx(4, 0.3), OpenQASMSerializationProperties(QubitReferenceType.PHYSICAL), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "bit[2] b;", - "cal {", - " waveform drag_gauss_wf = drag_gaussian" - + "(3.0ms, 400.0ms, 0.2, 1, false);", - "}", - "defcal z $0, $1 {", - " set_frequency(predefined_frame_1, 6000000.0);", - " play(predefined_frame_1, drag_gauss_wf);", - "}", - "defcal rx(0.15) $0 {", - " set_frequency(predefined_frame_1, 6000000.0);", - " play(predefined_frame_1, drag_gauss_wf);", - "}", - "rx(0.15) $0;", - "rx(0.3) $4;", - "b[0] = measure $0;", - "b[1] = measure $4;", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "bit[2] b;", + "cal {", + " waveform drag_gauss_wf = drag_gaussian" + + "(3.0ms, 400.0ms, 0.2, 1, false);", + "}", + "defcal z $0, $1 {", + " set_frequency(predefined_frame_1, 6000000.0);", + " play(predefined_frame_1, drag_gauss_wf);", + "}", + "defcal rx(0.15) $0 {", + " set_frequency(predefined_frame_1, 6000000.0);", + " play(predefined_frame_1, drag_gauss_wf);", + "}", + "rx(0.15) $0;", + "rx(0.3) $4;", + "b[0] = measure $0;", + "b[1] = measure $4;", + ]), inputs={}, ), ), @@ -1174,29 +1156,27 @@ def test_circuit_to_ir_openqasm(circuit, serialization_properties, expected_ir): .expectation(observable=Observable.I()), OpenQASMSerializationProperties(QubitReferenceType.PHYSICAL), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "cal {", - " waveform drag_gauss_wf = drag_gaussian" - + "(3.0ms, 400.0ms, 0.2, 1, false);", - "}", - "defcal z $0, $1 {", - " set_frequency(predefined_frame_1, 6000000.0);", - " play(predefined_frame_1, drag_gauss_wf);", - "}", - "defcal rx(0.15) $0 {", - " set_frequency(predefined_frame_1, 6000000.0);", - " play(predefined_frame_1, drag_gauss_wf);", - "}", - "rx(0.15) $0;", - "#pragma braket verbatim", - "box{", - "rx(0.3) $4;", - "}", - "#pragma braket result expectation i all", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "cal {", + " waveform drag_gauss_wf = drag_gaussian" + + "(3.0ms, 400.0ms, 0.2, 1, false);", + "}", + "defcal z $0, $1 {", + " set_frequency(predefined_frame_1, 6000000.0);", + " play(predefined_frame_1, drag_gauss_wf);", + "}", + "defcal rx(0.15) $0 {", + " set_frequency(predefined_frame_1, 6000000.0);", + " play(predefined_frame_1, drag_gauss_wf);", + "}", + "rx(0.15) $0;", + "#pragma braket verbatim", + "box{", + "rx(0.3) $4;", + "}", + "#pragma braket result expectation i all", + ]), inputs={}, ), ), @@ -1208,28 +1188,26 @@ def test_circuit_to_ir_openqasm(circuit, serialization_properties, expected_ir): .expectation(observable=Observable.I(), target=0), None, OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "qubit[5] q;", - "cal {", - " waveform drag_gauss_wf = drag_gaussian" - + "(3.0ms, 400.0ms, 0.2, 1, false);", - "}", - "defcal z $0, $1 {", - " set_frequency(predefined_frame_1, 6000000.0);", - " play(predefined_frame_1, drag_gauss_wf);", - "}", - "defcal rx(0.15) $0 {", - " set_frequency(predefined_frame_1, 6000000.0);", - " play(predefined_frame_1, drag_gauss_wf);", - "}", - "rx(0.15) q[0];", - "rx(0.3) q[4];", - "#pragma braket noise bit_flip(0.2) q[3]", - "#pragma braket result expectation i(q[0])", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "qubit[5] q;", + "cal {", + " waveform drag_gauss_wf = drag_gaussian" + + "(3.0ms, 400.0ms, 0.2, 1, false);", + "}", + "defcal z $0, $1 {", + " set_frequency(predefined_frame_1, 6000000.0);", + " play(predefined_frame_1, drag_gauss_wf);", + "}", + "defcal rx(0.15) $0 {", + " set_frequency(predefined_frame_1, 6000000.0);", + " play(predefined_frame_1, drag_gauss_wf);", + "}", + "rx(0.15) q[0];", + "rx(0.3) q[4];", + "#pragma braket noise bit_flip(0.2) q[3]", + "#pragma braket result expectation i(q[0])", + ]), inputs={}, ), ), @@ -1237,30 +1215,28 @@ def test_circuit_to_ir_openqasm(circuit, serialization_properties, expected_ir): Circuit().rx(0, 0.15).rx(1, FreeParameter("theta")), OpenQASMSerializationProperties(QubitReferenceType.VIRTUAL), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "input float theta;", - "bit[2] b;", - "qubit[2] q;", - "cal {", - " waveform drag_gauss_wf = drag_gaussian" - + "(3.0ms, 400.0ms, 0.2, 1, false);", - "}", - "defcal z $0, $1 {", - " set_frequency(predefined_frame_1, 6000000.0);", - " play(predefined_frame_1, drag_gauss_wf);", - "}", - "defcal rx(0.15) $0 {", - " set_frequency(predefined_frame_1, 6000000.0);", - " play(predefined_frame_1, drag_gauss_wf);", - "}", - "rx(0.15) q[0];", - "rx(theta) q[1];", - "b[0] = measure q[0];", - "b[1] = measure q[1];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "input float theta;", + "bit[2] b;", + "qubit[2] q;", + "cal {", + " waveform drag_gauss_wf = drag_gaussian" + + "(3.0ms, 400.0ms, 0.2, 1, false);", + "}", + "defcal z $0, $1 {", + " set_frequency(predefined_frame_1, 6000000.0);", + " play(predefined_frame_1, drag_gauss_wf);", + "}", + "defcal rx(0.15) $0 {", + " set_frequency(predefined_frame_1, 6000000.0);", + " play(predefined_frame_1, drag_gauss_wf);", + "}", + "rx(0.15) q[0];", + "rx(theta) q[1];", + "b[0] = measure q[0];", + "b[1] = measure q[1];", + ]), inputs={}, ), ), @@ -1271,33 +1247,31 @@ def test_circuit_to_ir_openqasm(circuit, serialization_properties, expected_ir): .cnot(target=0, control=[2, 3, 4]), OpenQASMSerializationProperties(QubitReferenceType.VIRTUAL), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "bit[5] b;", - "qubit[5] q;", - "cal {", - " waveform drag_gauss_wf = drag_gaussian" - + "(3.0ms, 400.0ms, 0.2, 1, false);", - "}", - "defcal z $0, $1 {", - " set_frequency(predefined_frame_1, 6000000.0);", - " play(predefined_frame_1, drag_gauss_wf);", - "}", - "defcal rx(0.15) $0 {", - " set_frequency(predefined_frame_1, 6000000.0);", - " play(predefined_frame_1, drag_gauss_wf);", - "}", - "negctrl @ rx(0.15) q[2], q[0];", - "ctrl(2) @ rx(0.3) q[2], q[3], q[1];", - "ctrl(2) @ cnot q[2], q[3], q[4], q[0];", - "b[0] = measure q[0];", - "b[1] = measure q[1];", - "b[2] = measure q[2];", - "b[3] = measure q[3];", - "b[4] = measure q[4];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "bit[5] b;", + "qubit[5] q;", + "cal {", + " waveform drag_gauss_wf = drag_gaussian" + + "(3.0ms, 400.0ms, 0.2, 1, false);", + "}", + "defcal z $0, $1 {", + " set_frequency(predefined_frame_1, 6000000.0);", + " play(predefined_frame_1, drag_gauss_wf);", + "}", + "defcal rx(0.15) $0 {", + " set_frequency(predefined_frame_1, 6000000.0);", + " play(predefined_frame_1, drag_gauss_wf);", + "}", + "negctrl @ rx(0.15) q[2], q[0];", + "ctrl(2) @ rx(0.3) q[2], q[3], q[1];", + "ctrl(2) @ cnot q[2], q[3], q[4], q[0];", + "b[0] = measure q[0];", + "b[1] = measure q[1];", + "b[2] = measure q[2];", + "b[3] = measure q[3];", + "b[4] = measure q[4];", + ]), inputs={}, ), ), @@ -1305,31 +1279,29 @@ def test_circuit_to_ir_openqasm(circuit, serialization_properties, expected_ir): Circuit().cnot(0, 1).cnot(target=2, control=3).cnot(target=4, control=[5, 6]), OpenQASMSerializationProperties(QubitReferenceType.VIRTUAL), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "bit[7] b;", - "qubit[7] q;", - "cal {", - " waveform drag_gauss_wf = drag_gaussian" - + "(3.0ms, 400.0ms, 0.2, 1, false);", - "}", - "defcal z $0, $1 {", - " set_frequency(predefined_frame_1, 6000000.0);", - " play(predefined_frame_1, drag_gauss_wf);", - "}", - "cnot q[0], q[1];", - "cnot q[3], q[2];", - "ctrl @ cnot q[5], q[6], q[4];", - "b[0] = measure q[0];", - "b[1] = measure q[1];", - "b[2] = measure q[2];", - "b[3] = measure q[3];", - "b[4] = measure q[4];", - "b[5] = measure q[5];", - "b[6] = measure q[6];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "bit[7] b;", + "qubit[7] q;", + "cal {", + " waveform drag_gauss_wf = drag_gaussian" + + "(3.0ms, 400.0ms, 0.2, 1, false);", + "}", + "defcal z $0, $1 {", + " set_frequency(predefined_frame_1, 6000000.0);", + " play(predefined_frame_1, drag_gauss_wf);", + "}", + "cnot q[0], q[1];", + "cnot q[3], q[2];", + "ctrl @ cnot q[5], q[6], q[4];", + "b[0] = measure q[0];", + "b[1] = measure q[1];", + "b[2] = measure q[2];", + "b[3] = measure q[3];", + "b[4] = measure q[4];", + "b[5] = measure q[5];", + "b[6] = measure q[6];", + ]), inputs={}, ), ), @@ -1337,32 +1309,30 @@ def test_circuit_to_ir_openqasm(circuit, serialization_properties, expected_ir): Circuit().h(0, power=-2.5).h(0, power=0).ms(0, 1, -0.1, -0.2, -0.3), OpenQASMSerializationProperties(QubitReferenceType.VIRTUAL), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "bit[2] b;", - "qubit[2] q;", - "cal {", - " waveform drag_gauss_wf = drag_gaussian" - + "(3.0ms, 400.0ms, 0.2, 1, false);", - "}", - "defcal z $0, $1 {", - " set_frequency(predefined_frame_1, 6000000.0);", - " play(predefined_frame_1, drag_gauss_wf);", - "}", - "defcal ms(-0.1, -0.2, -0.3) $0, $1 {", - " shift_phase(predefined_frame_1, -0.1);", - " set_phase(predefined_frame_1, -0.3);", - " shift_phase(predefined_frame_1, -0.2);", - " play(predefined_frame_1, drag_gauss_wf);", - "}", - "inv @ pow(2.5) @ h q[0];", - "pow(0) @ h q[0];", - "ms(-0.1, -0.2, -0.3) q[0], q[1];", - "b[0] = measure q[0];", - "b[1] = measure q[1];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "bit[2] b;", + "qubit[2] q;", + "cal {", + " waveform drag_gauss_wf = drag_gaussian" + + "(3.0ms, 400.0ms, 0.2, 1, false);", + "}", + "defcal z $0, $1 {", + " set_frequency(predefined_frame_1, 6000000.0);", + " play(predefined_frame_1, drag_gauss_wf);", + "}", + "defcal ms(-0.1, -0.2, -0.3) $0, $1 {", + " shift_phase(predefined_frame_1, -0.1);", + " set_phase(predefined_frame_1, -0.3);", + " shift_phase(predefined_frame_1, -0.2);", + " play(predefined_frame_1, drag_gauss_wf);", + "}", + "inv @ pow(2.5) @ h q[0];", + "pow(0) @ h q[0];", + "ms(-0.1, -0.2, -0.3) q[0], q[1];", + "b[0] = measure q[0];", + "b[1] = measure q[1];", + ]), inputs={}, ), ), @@ -1401,25 +1371,22 @@ def test_circuit_to_ir_openqasm_with_gate_calibrations( Circuit().rx(0, 0.2), (Gate.Rx(FreeParameter("alpha")), QubitSet(0)), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "input float beta;", - "bit[1] b;", - "qubit[1] q;", - "cal {", - " waveform drag_gauss_wf = drag_gaussian(3.0ms," - " 400.0ms, 0.2, 1, false);", - "}", - "defcal rx(0.2) $0 {", - " shift_phase(predefined_frame_1, 0.2);", - " shift_phase(predefined_frame_1, beta);", - " play(predefined_frame_1, drag_gauss_wf);", - "}", - "rx(0.2) q[0];", - "b[0] = measure q[0];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "input float beta;", + "bit[1] b;", + "qubit[1] q;", + "cal {", + " waveform drag_gauss_wf = drag_gaussian(3.0ms, 400.0ms, 0.2, 1, false);", + "}", + "defcal rx(0.2) $0 {", + " shift_phase(predefined_frame_1, 0.2);", + " shift_phase(predefined_frame_1, beta);", + " play(predefined_frame_1, drag_gauss_wf);", + "}", + "rx(0.2) q[0];", + "b[0] = measure q[0];", + ]), inputs={}, ), ), @@ -1427,11 +1394,9 @@ def test_circuit_to_ir_openqasm_with_gate_calibrations( ) def test_circuit_with_parametric_defcal(circuit, calibration_key, expected_ir, pulse_sequence_3): serialization_properties = OpenQASMSerializationProperties(QubitReferenceType.VIRTUAL) - gate_calibrations = GateCalibrations( - { - calibration_key: pulse_sequence_3, - } - ) + gate_calibrations = GateCalibrations({ + calibration_key: pulse_sequence_3, + }) assert ( circuit.to_ir( @@ -1448,37 +1413,33 @@ def test_parametric_circuit_with_fixed_argument_defcal(pulse_sequence): serialization_properties = OpenQASMSerializationProperties(QubitReferenceType.VIRTUAL) calibration_key = (Gate.Z(), QubitSet([0, 1])) calibration_key_2 = (Gate.Rx(0.45), QubitSet([0])) - gate_calibrations = GateCalibrations( - { - calibration_key: pulse_sequence, - calibration_key_2: pulse_sequence, - } - ) + gate_calibrations = GateCalibrations({ + calibration_key: pulse_sequence, + calibration_key_2: pulse_sequence, + }) expected_ir = OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "input float theta;", - "bit[1] b;", - "qubit[1] q;", - "cal {", - " waveform drag_gauss_wf = drag_gaussian(3.0ms, 400.0ms, 0.2, 1, false);", - "}", - "defcal z $0, $1 {", - " set_frequency(predefined_frame_1, 6000000.0);", - " play(predefined_frame_1, drag_gauss_wf);", - "}", - "defcal rx(0.45) $0 {", - " set_frequency(predefined_frame_1, 6000000.0);", - " play(predefined_frame_1, drag_gauss_wf);", - "}", - "inv @ pow(2.5) @ h q[0];", - "pow(0) @ h q[0];", - "rx(theta) q[0];", - "b[0] = measure q[0];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "input float theta;", + "bit[1] b;", + "qubit[1] q;", + "cal {", + " waveform drag_gauss_wf = drag_gaussian(3.0ms, 400.0ms, 0.2, 1, false);", + "}", + "defcal z $0, $1 {", + " set_frequency(predefined_frame_1, 6000000.0);", + " play(predefined_frame_1, drag_gauss_wf);", + "}", + "defcal rx(0.45) $0 {", + " set_frequency(predefined_frame_1, 6000000.0);", + " play(predefined_frame_1, drag_gauss_wf);", + "}", + "inv @ pow(2.5) @ h q[0];", + "pow(0) @ h q[0];", + "rx(theta) q[0];", + "b[0] = measure q[0];", + ]), inputs={}, ) @@ -1499,9 +1460,9 @@ def test_circuit_with_partial_calibrations(pulse_sequence_2): circuit = Circuit().h(0, power=-2.5).h(0, power=0).ms(0, 1, -0.1, -0.2, -0.3) serialization_properties = OpenQASMSerializationProperties(QubitReferenceType.VIRTUAL) gate_calibrations = ( - GateCalibrations( - {(Gate.MS(-0.1, FreeParameter("beta"), -0.3), QubitSet([0, 1])): pulse_sequence_2} - ), + GateCalibrations({ + (Gate.MS(-0.1, FreeParameter("beta"), -0.3), QubitSet([0, 1])): pulse_sequence_2 + }), ) circuit.to_ir( ir_type=IRType.OPENQASM, @@ -1545,33 +1506,30 @@ def foo( circ = Circuit().foo(0, -0.2) serialization_properties = OpenQASMSerializationProperties(QubitReferenceType.VIRTUAL) - gate_calibrations = GateCalibrations( - { - (Foo(FreeParameter("beta")), QubitSet(0)): pulse_sequence_2( - **{"alpha": -0.1, "gamma": -0.3} - ) - } - ) + gate_calibrations = GateCalibrations({ + (Foo(FreeParameter("beta")), QubitSet(0)): pulse_sequence_2(**{ + "alpha": -0.1, + "gamma": -0.3, + }) + }) expected_ir = OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "bit[1] b;", - "qubit[1] q;", - "cal {", - " waveform drag_gauss_wf = drag_gaussian(3.0ms, 400.0ms, 0.2, 1, false);", - "}", - "defcal foo(-0.2) $0 {", - " shift_phase(predefined_frame_1, -0.1);", - " set_phase(predefined_frame_1, -0.3);", - " shift_phase(predefined_frame_1, -0.2);", - " play(predefined_frame_1, drag_gauss_wf);", - "}", - "foo(-0.2) q[0];", - "b[0] = measure q[0];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "bit[1] b;", + "qubit[1] q;", + "cal {", + " waveform drag_gauss_wf = drag_gaussian(3.0ms, 400.0ms, 0.2, 1, false);", + "}", + "defcal foo(-0.2) $0 {", + " shift_phase(predefined_frame_1, -0.1);", + " set_phase(predefined_frame_1, -0.3);", + " shift_phase(predefined_frame_1, -0.2);", + " play(predefined_frame_1, drag_gauss_wf);", + "}", + "foo(-0.2) q[0];", + "b[0] = measure q[0];", + ]), inputs={}, ) @@ -1591,335 +1549,291 @@ def foo( ( Circuit().h(0, control=1, control_state=0).measure(0).measure(1), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "bit[2] b;", - "qubit[2] q;", - "negctrl @ h q[1], q[0];", - "b[0] = measure q[0];", - "b[1] = measure q[1];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "bit[2] b;", + "qubit[2] q;", + "negctrl @ h q[1], q[0];", + "b[0] = measure q[0];", + "b[1] = measure q[1];", + ]), inputs={}, ), ), ( Circuit().cnot(target=0, control=1).measure(0).measure(1), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "bit[2] b;", - "qubit[2] q;", - "cnot q[1], q[0];", - "b[0] = measure q[0];", - "b[1] = measure q[1];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "bit[2] b;", + "qubit[2] q;", + "cnot q[1], q[0];", + "b[0] = measure q[0];", + "b[1] = measure q[1];", + ]), inputs={}, ), ), ( Circuit().x(0, control=[1], control_state=[0]).measure(0).measure(1), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "bit[2] b;", - "qubit[2] q;", - "negctrl @ x q[1], q[0];", - "b[0] = measure q[0];", - "b[1] = measure q[1];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "bit[2] b;", + "qubit[2] q;", + "negctrl @ x q[1], q[0];", + "b[0] = measure q[0];", + "b[1] = measure q[1];", + ]), inputs={}, ), ), ( Circuit().rx(0, 0.15, control=1, control_state=1).measure(0).measure(1), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "bit[2] b;", - "qubit[2] q;", - "ctrl @ rx(0.15) q[1], q[0];", - "b[0] = measure q[0];", - "b[1] = measure q[1];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "bit[2] b;", + "qubit[2] q;", + "ctrl @ rx(0.15) q[1], q[0];", + "b[0] = measure q[0];", + "b[1] = measure q[1];", + ]), inputs={}, ), ), ( Circuit().ry(0, 0.2, control=1, control_state=1).measure(0).measure(1), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "bit[2] b;", - "qubit[2] q;", - "ctrl @ ry(0.2) q[1], q[0];", - "b[0] = measure q[0];", - "b[1] = measure q[1];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "bit[2] b;", + "qubit[2] q;", + "ctrl @ ry(0.2) q[1], q[0];", + "b[0] = measure q[0];", + "b[1] = measure q[1];", + ]), inputs={}, ), ), ( Circuit().rz(0, 0.25, control=[1], control_state=[0]).measure(0).measure(1), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "bit[2] b;", - "qubit[2] q;", - "negctrl @ rz(0.25) q[1], q[0];", - "b[0] = measure q[0];", - "b[1] = measure q[1];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "bit[2] b;", + "qubit[2] q;", + "negctrl @ rz(0.25) q[1], q[0];", + "b[0] = measure q[0];", + "b[1] = measure q[1];", + ]), inputs={}, ), ), ( Circuit().s(target=0, control=[1], control_state=[0]).measure(0).measure(1), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "bit[2] b;", - "qubit[2] q;", - "negctrl @ s q[1], q[0];", - "b[0] = measure q[0];", - "b[1] = measure q[1];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "bit[2] b;", + "qubit[2] q;", + "negctrl @ s q[1], q[0];", + "b[0] = measure q[0];", + "b[1] = measure q[1];", + ]), inputs={}, ), ), ( Circuit().t(target=1, control=[0], control_state=[0]).measure(0).measure(1), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "bit[2] b;", - "qubit[2] q;", - "negctrl @ t q[0], q[1];", - "b[0] = measure q[0];", - "b[1] = measure q[1];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "bit[2] b;", + "qubit[2] q;", + "negctrl @ t q[0], q[1];", + "b[0] = measure q[0];", + "b[1] = measure q[1];", + ]), inputs={}, ), ), ( Circuit().cphaseshift(target=0, control=1, angle=0.15).measure(0).measure(1), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "bit[2] b;", - "qubit[2] q;", - "cphaseshift(0.15) q[1], q[0];", - "b[0] = measure q[0];", - "b[1] = measure q[1];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "bit[2] b;", + "qubit[2] q;", + "cphaseshift(0.15) q[1], q[0];", + "b[0] = measure q[0];", + "b[1] = measure q[1];", + ]), inputs={}, ), ), ( Circuit().ccnot(*[0, 1], target=2).measure(0).measure(1).measure(2), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "bit[3] b;", - "qubit[3] q;", - "ccnot q[0], q[1], q[2];", - "b[0] = measure q[0];", - "b[1] = measure q[1];", - "b[2] = measure q[2];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "bit[3] b;", + "qubit[3] q;", + "ccnot q[0], q[1], q[2];", + "b[0] = measure q[0];", + "b[1] = measure q[1];", + "b[2] = measure q[2];", + ]), inputs={}, ), ), ( Circuit().h(0).state_vector(), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "qubit[1] q;", - "h q[0];", - "#pragma braket result state_vector", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "qubit[1] q;", + "h q[0];", + "#pragma braket result state_vector", + ]), inputs={}, ), ), ( Circuit().h(0).expectation(observables.X(), [0]), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "qubit[1] q;", - "h q[0];", - "#pragma braket result expectation x(q[0])", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "qubit[1] q;", + "h q[0];", + "#pragma braket result expectation x(q[0])", + ]), inputs={}, ), ), ( Circuit().h(0).expectation(observables.H() @ observables.X(), [0, 1]), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "qubit[2] q;", - "h q[0];", - "#pragma braket result expectation h(q[0]) @ x(q[1])", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "qubit[2] q;", + "h q[0];", + "#pragma braket result expectation h(q[0]) @ x(q[1])", + ]), inputs={}, ), ), ( Circuit().h(0).variance(observables.H() @ observables.X(), [0, 1]), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "qubit[2] q;", - "h q[0];", - "#pragma braket result variance h(q[0]) @ x(q[1])", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "qubit[2] q;", + "h q[0];", + "#pragma braket result variance h(q[0]) @ x(q[1])", + ]), inputs={}, ), ), ( Circuit().h(0).probability(target=[0]), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "qubit[1] q;", - "h q[0];", - "#pragma braket result probability q[0]", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "qubit[1] q;", + "h q[0];", + "#pragma braket result probability q[0]", + ]), inputs={}, ), ), ( Circuit().bit_flip(0, 0.1).measure(0), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "bit[1] b;", - "qubit[1] q;", - "#pragma braket noise bit_flip(0.1) q[0]", - "b[0] = measure q[0];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "bit[1] b;", + "qubit[1] q;", + "#pragma braket noise bit_flip(0.1) q[0]", + "b[0] = measure q[0];", + ]), inputs={}, ), ), ( Circuit().generalized_amplitude_damping(0, 0.1, 0.1).measure(0), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "bit[1] b;", - "qubit[1] q;", - "#pragma braket noise generalized_amplitude_damping(0.1, 0.1) q[0]", - "b[0] = measure q[0];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "bit[1] b;", + "qubit[1] q;", + "#pragma braket noise generalized_amplitude_damping(0.1, 0.1) q[0]", + "b[0] = measure q[0];", + ]), inputs={}, ), ), ( Circuit().phase_flip(0, 0.2).measure(0), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "bit[1] b;", - "qubit[1] q;", - "#pragma braket noise phase_flip(0.2) q[0]", - "b[0] = measure q[0];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "bit[1] b;", + "qubit[1] q;", + "#pragma braket noise phase_flip(0.2) q[0]", + "b[0] = measure q[0];", + ]), inputs={}, ), ), ( Circuit().depolarizing(0, 0.5).measure(0), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "bit[1] b;", - "qubit[1] q;", - "#pragma braket noise depolarizing(0.5) q[0]", - "b[0] = measure q[0];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "bit[1] b;", + "qubit[1] q;", + "#pragma braket noise depolarizing(0.5) q[0]", + "b[0] = measure q[0];", + ]), inputs={}, ), ), ( Circuit().amplitude_damping(0, 0.8).measure(0), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "bit[1] b;", - "qubit[1] q;", - "#pragma braket noise amplitude_damping(0.8) q[0]", - "b[0] = measure q[0];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "bit[1] b;", + "qubit[1] q;", + "#pragma braket noise amplitude_damping(0.8) q[0]", + "b[0] = measure q[0];", + ]), inputs={}, ), ), ( Circuit().phase_damping(0, 0.1).measure(0), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "bit[1] b;", - "qubit[1] q;", - "#pragma braket noise phase_damping(0.1) q[0]", - "b[0] = measure q[0];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "bit[1] b;", + "qubit[1] q;", + "#pragma braket noise phase_damping(0.1) q[0]", + "b[0] = measure q[0];", + ]), inputs={}, ), ), ( Circuit().h(0).amplitude(state=["0", "1"]), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "qubit[1] q;", - "h q[0];", - '#pragma braket result amplitude "0", "1"', - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "qubit[1] q;", + "h q[0];", + '#pragma braket result amplitude "0", "1"', + ]), inputs={}, ), ), @@ -1934,21 +1848,19 @@ def foo( .measure(3) .measure(4), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "bit[5] b;", - "qubit[5] q;", - "negctrl @ rx(0.15) q[2], q[0];", - "ctrl(2) @ rx(0.3) q[2], q[3], q[1];", - "ctrl(2) @ cnot q[2], q[3], q[4], q[0];", - "b[0] = measure q[0];", - "b[1] = measure q[1];", - "b[2] = measure q[2];", - "b[3] = measure q[3];", - "b[4] = measure q[4];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "bit[5] b;", + "qubit[5] q;", + "negctrl @ rx(0.15) q[2], q[0];", + "ctrl(2) @ rx(0.3) q[2], q[3], q[1];", + "ctrl(2) @ cnot q[2], q[3], q[4], q[0];", + "b[0] = measure q[0];", + "b[1] = measure q[1];", + "b[2] = measure q[2];", + "b[3] = measure q[3];", + "b[4] = measure q[4];", + ]), inputs={}, ), ), @@ -1965,160 +1877,140 @@ def foo( .measure(5) .measure(6), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "bit[7] b;", - "qubit[7] q;", - "cnot q[0], q[1];", - "cnot q[3], q[2];", - "ctrl @ cnot q[5], q[6], q[4];", - "b[0] = measure q[0];", - "b[1] = measure q[1];", - "b[2] = measure q[2];", - "b[3] = measure q[3];", - "b[4] = measure q[4];", - "b[5] = measure q[5];", - "b[6] = measure q[6];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "bit[7] b;", + "qubit[7] q;", + "cnot q[0], q[1];", + "cnot q[3], q[2];", + "ctrl @ cnot q[5], q[6], q[4];", + "b[0] = measure q[0];", + "b[1] = measure q[1];", + "b[2] = measure q[2];", + "b[3] = measure q[3];", + "b[4] = measure q[4];", + "b[5] = measure q[5];", + "b[6] = measure q[6];", + ]), inputs={}, ), ), ( Circuit().h(0, power=-2.5).h(0, power=0).measure(0), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "bit[1] b;", - "qubit[1] q;", - "inv @ pow(2.5) @ h q[0];", - "pow(0) @ h q[0];", - "b[0] = measure q[0];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "bit[1] b;", + "qubit[1] q;", + "inv @ pow(2.5) @ h q[0];", + "pow(0) @ h q[0];", + "b[0] = measure q[0];", + ]), inputs={}, ), ), ( Circuit().unitary(matrix=np.array([[0, 1], [1, 0]]), targets=[0]).measure(0), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "bit[1] b;", - "qubit[1] q;", - "#pragma braket unitary([[0, 1.0], [1.0, 0]]) q[0]", - "b[0] = measure q[0];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "bit[1] b;", + "qubit[1] q;", + "#pragma braket unitary([[0, 1.0], [1.0, 0]]) q[0]", + "b[0] = measure q[0];", + ]), inputs={}, ), ), ( Circuit().pauli_channel(0, probX=0.1, probY=0.2, probZ=0.3).measure(0), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "bit[1] b;", - "qubit[1] q;", - "#pragma braket noise pauli_channel(0.1, 0.2, 0.3) q[0]", - "b[0] = measure q[0];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "bit[1] b;", + "qubit[1] q;", + "#pragma braket noise pauli_channel(0.1, 0.2, 0.3) q[0]", + "b[0] = measure q[0];", + ]), inputs={}, ), ), ( Circuit().two_qubit_depolarizing(0, 1, probability=0.1).measure(0).measure(1), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "bit[2] b;", - "qubit[2] q;", - "#pragma braket noise two_qubit_depolarizing(0.1) q[0], q[1]", - "b[0] = measure q[0];", - "b[1] = measure q[1];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "bit[2] b;", + "qubit[2] q;", + "#pragma braket noise two_qubit_depolarizing(0.1) q[0], q[1]", + "b[0] = measure q[0];", + "b[1] = measure q[1];", + ]), inputs={}, ), ), ( Circuit().two_qubit_dephasing(0, 1, probability=0.1).measure(0).measure(1), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "bit[2] b;", - "qubit[2] q;", - "#pragma braket noise two_qubit_dephasing(0.1) q[0], q[1]", - "b[0] = measure q[0];", - "b[1] = measure q[1];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "bit[2] b;", + "qubit[2] q;", + "#pragma braket noise two_qubit_dephasing(0.1) q[0], q[1]", + "b[0] = measure q[0];", + "b[1] = measure q[1];", + ]), inputs={}, ), ), ( Circuit().two_qubit_dephasing(0, 1, probability=0.1).measure(0).measure(1), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "bit[2] b;", - "qubit[2] q;", - "#pragma braket noise two_qubit_dephasing(0.1) q[0], q[1]", - "b[0] = measure q[0];", - "b[1] = measure q[1];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "bit[2] b;", + "qubit[2] q;", + "#pragma braket noise two_qubit_dephasing(0.1) q[0], q[1]", + "b[0] = measure q[0];", + "b[1] = measure q[1];", + ]), inputs={}, ), ), ( Circuit().h(0).sample(observable=Observable.Z(), target=0), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "qubit[1] q;", - "h q[0];", - "#pragma braket result sample z(q[0])", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "qubit[1] q;", + "h q[0];", + "#pragma braket result sample z(q[0])", + ]), inputs={}, ), ), ( Circuit().h(0).sample(observable=Observable.Z(), target=0), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "qubit[1] q;", - "h q[0];", - "#pragma braket result sample z(q[0])", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "qubit[1] q;", + "h q[0];", + "#pragma braket result sample z(q[0])", + ]), inputs={}, ), ), ( Circuit().h(0).x(1).density_matrix(target=[0, 1]), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "qubit[2] q;", - "h q[0];", - "x q[1];", - "#pragma braket result density_matrix q[0], q[1]", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "qubit[2] q;", + "h q[0];", + "x q[1];", + "#pragma braket result density_matrix q[0], q[1]", + ]), inputs={}, ), ), @@ -2133,79 +2025,69 @@ def foo( ) .measure(0), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "bit[1] b;", - "qubit[1] q;", - "#pragma braket noise " - "kraus([[0.9486833im, 0], [0, 0.9486833im]], [[0, 0.31622777], " - "[0.31622777, 0]]) q[0]", - "b[0] = measure q[0];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "bit[1] b;", + "qubit[1] q;", + "#pragma braket noise " + "kraus([[0.9486833im, 0], [0, 0.9486833im]], [[0, 0.31622777], " + "[0.31622777, 0]]) q[0]", + "b[0] = measure q[0];", + ]), inputs={}, ), ), ( Circuit().rx(0, FreeParameter("theta")).measure(0), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "input float theta;", - "bit[1] b;", - "qubit[1] q;", - "rx(theta) q[0];", - "b[0] = measure q[0];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "input float theta;", + "bit[1] b;", + "qubit[1] q;", + "rx(theta) q[0];", + "b[0] = measure q[0];", + ]), inputs={}, ), ), ( Circuit().rx(0, np.pi).measure(0), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "bit[1] b;", - "qubit[1] q;", - "rx(π) q[0];", - "b[0] = measure q[0];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "bit[1] b;", + "qubit[1] q;", + "rx(π) q[0];", + "b[0] = measure q[0];", + ]), inputs={}, ), ), ( Circuit().rx(0, 2 * np.pi).measure(0), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "bit[1] b;", - "qubit[1] q;", - "rx(τ) q[0];", - "b[0] = measure q[0];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "bit[1] b;", + "qubit[1] q;", + "rx(τ) q[0];", + "b[0] = measure q[0];", + ]), inputs={}, ), ), ( Circuit().gphase(0.15).x(0).measure(0), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "bit[1] b;", - "qubit[1] q;", - "gphase(0.15);", - "x q[0];", - "b[0] = measure q[0];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "bit[1] b;", + "qubit[1] q;", + "gphase(0.15);", + "x q[0];", + "b[0] = measure q[0];", + ]), inputs={}, ), ), @@ -2219,18 +2101,16 @@ def test_from_ir(expected_circuit, ir): def test_from_ir_inputs_updated(): circuit = Circuit().rx(0, 0.2).ry(0, 0.1).measure(0) openqasm = OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "input float theta;", - "input float phi;", - "bit[1] b;", - "qubit[1] q;", - "rx(theta) q[0];", - "ry(phi) q[0];", - "b[0] = measure q[0];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "input float theta;", + "input float phi;", + "bit[1] b;", + "qubit[1] q;", + "rx(theta) q[0];", + "ry(phi) q[0];", + "b[0] = measure q[0];", + ]), inputs={"theta": 0.2, "phi": 0.3}, ) assert Circuit.from_ir(source=openqasm, inputs={"phi": 0.1}) == circuit @@ -2242,113 +2122,101 @@ def test_from_ir_inputs_updated(): ( Circuit().h(0).cnot(0, 1).measure(0).measure(1), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "bit[2] b;", - "qubit[2] q;", - "gate my_gate a,b {", - "h a;", - "cnot a,b;", - "}", - "my_gate q[0], q[1];", - "b[0] = measure q[0];", - "b[1] = measure q[1];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "bit[2] b;", + "qubit[2] q;", + "gate my_gate a,b {", + "h a;", + "cnot a,b;", + "}", + "my_gate q[0], q[1];", + "b[0] = measure q[0];", + "b[1] = measure q[1];", + ]), inputs={}, ), ), ( Circuit().h(0).h(1).measure(0).measure(1), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "bit[2] b;", - "qubit[2] q;", - "def my_sub(qubit q) {", - "h q;", - "}", - "h q[0];", - "my_sub(q[1]);", - "b[0] = measure q[0];", - "b[1] = measure q[1];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "bit[2] b;", + "qubit[2] q;", + "def my_sub(qubit q) {", + "h q;", + "}", + "h q[0];", + "my_sub(q[1]);", + "b[0] = measure q[0];", + "b[1] = measure q[1];", + ]), inputs={}, ), ), ( Circuit().h(0).h(1).cnot(0, 1).measure(0).measure(1), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "bit[2] b;", - "qubit[2] q;", - "for uint i in [0:1] {", - "h q[i];", - "}", - "cnot q[0], q[1];", - "b[0] = measure q[0];", - "b[1] = measure q[1];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "bit[2] b;", + "qubit[2] q;", + "for uint i in [0:1] {", + "h q[i];", + "}", + "cnot q[0], q[1];", + "b[0] = measure q[0];", + "b[1] = measure q[1];", + ]), inputs={}, ), ), ( Circuit().h(0).h(1).cnot(0, 1).measure(0).measure(1), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "bit[2] b;", - "qubit[2] q;", - "for uint i in [0:1] {", - "h q[i];", - "}", - "cnot q[0], q[1];", - "b[0] = measure q[0];", - "b[1] = measure q[1];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "bit[2] b;", + "qubit[2] q;", + "for uint i in [0:1] {", + "h q[i];", + "}", + "cnot q[0], q[1];", + "b[0] = measure q[0];", + "b[1] = measure q[1];", + ]), inputs={}, ), ), ( Circuit().x(0).measure(0), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "bit[1] b;", - "qubit[1] q;", - "bit c = 0;", - "if (c ==0){", - "x q[0];", - "}", - "b[0] = measure q[0];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "bit[1] b;", + "qubit[1] q;", + "bit c = 0;", + "if (c ==0){", + "x q[0];", + "}", + "b[0] = measure q[0];", + ]), inputs={}, ), ), ( Circuit().rx(0, FreeParameter("theta")).rx(0, 2 * FreeParameter("theta")).measure(0), OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "input float theta;", - "bit[1] b;", - "qubit[1] q;", - "rx(theta) q[0];", - "rx(2*theta) q[0];", - "b[0] = measure q[0];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "input float theta;", + "bit[1] b;", + "qubit[1] q;", + "rx(theta) q[0];", + "rx(2*theta) q[0];", + "b[0] = measure q[0];", + ]), inputs={}, ), ), @@ -3346,7 +3214,7 @@ def test_make_bound_circuit_bad_value(): theta = FreeParameter("theta") input_val = "invalid" circ = Circuit().ry(angle=theta, target=0).ry(angle=theta, target=1).ry(angle=theta, target=2) - with pytest.raises(ValueError): + with pytest.raises(TypeError): circ.make_bound_circuit({"theta": input_val}) @@ -3429,33 +3297,31 @@ def test_pulse_circuit_to_openqasm(predefined_frame_1, user_defined_frame): serialization_properties=OpenQASMSerializationProperties( qubit_reference_type=QubitReferenceType.PHYSICAL ), - ).source == "\n".join( - [ - "OPENQASM 3.0;", - "bit[2] b;", - "cal {", - " frame user_defined_frame_0 = newframe(device_port_x0, 10000000.0, 3.14);", - " waveform gauss_wf = gaussian(1.0ms, 700.0ms, 1, false);", - " waveform drag_gauss_wf = drag_gaussian(3.0ms, 400.0ms, 0.2, 1," " false);", - " waveform drag_gauss_wf_2 = drag_gaussian(3.0ms, 400.0ms, " "0.2, 1, false);", - "}", - "h $0;", - "cal {", - " set_frequency(predefined_frame_1, 3000000000.0);", - " play(predefined_frame_1, gauss_wf);", - " play(predefined_frame_1, drag_gauss_wf);", - "}", - "x $1;", - "cal {", - " set_frequency(predefined_frame_1, 3000000000.0);", - " play(user_defined_frame_0, gauss_wf);", - " play(predefined_frame_1, drag_gauss_wf_2);", - "}", - "h $1;", - "b[0] = measure $0;", - "b[1] = measure $1;", - ] - ) + ).source == "\n".join([ + "OPENQASM 3.0;", + "bit[2] b;", + "cal {", + " frame user_defined_frame_0 = newframe(device_port_x0, 10000000.0, 3.14);", + " waveform gauss_wf = gaussian(1.0ms, 700.0ms, 1, false);", + " waveform drag_gauss_wf = drag_gaussian(3.0ms, 400.0ms, 0.2, 1, false);", + " waveform drag_gauss_wf_2 = drag_gaussian(3.0ms, 400.0ms, 0.2, 1, false);", + "}", + "h $0;", + "cal {", + " set_frequency(predefined_frame_1, 3000000000.0);", + " play(predefined_frame_1, gauss_wf);", + " play(predefined_frame_1, drag_gauss_wf);", + "}", + "x $1;", + "cal {", + " set_frequency(predefined_frame_1, 3000000000.0);", + " play(user_defined_frame_0, gauss_wf);", + " play(predefined_frame_1, drag_gauss_wf_2);", + "}", + "h $1;", + "b[0] = measure $0;", + "b[1] = measure $1;", + ]) def test_pulse_circuit_conflicting_wf(predefined_frame_1, user_defined_frame): @@ -3543,24 +3409,22 @@ def test_parametrized_pulse_circuit(user_defined_frame): serialization_properties=OpenQASMSerializationProperties( qubit_reference_type=QubitReferenceType.PHYSICAL ), - ).source == "\n".join( - [ - "OPENQASM 3.0;", - "input float frequency;", - "bit[2] b;", - "cal {", - " frame user_defined_frame_0 = newframe(device_port_x0, 10000000.0, 3.14);", - " waveform gauss_wf = gaussian(10.0us, 700.0ms, 1, false);", - "}", - "rx(0.5) $0;", - "cal {", - " set_frequency(user_defined_frame_0, frequency);", - " play(user_defined_frame_0, gauss_wf);", - "}", - "b[0] = measure $0;", - "b[1] = measure $1;", - ] - ) + ).source == "\n".join([ + "OPENQASM 3.0;", + "input float frequency;", + "bit[2] b;", + "cal {", + " frame user_defined_frame_0 = newframe(device_port_x0, 10000000.0, 3.14);", + " waveform gauss_wf = gaussian(10.0us, 700.0ms, 1, false);", + "}", + "rx(0.5) $0;", + "cal {", + " set_frequency(user_defined_frame_0, frequency);", + " play(user_defined_frame_0, gauss_wf);", + "}", + "b[0] = measure $0;", + "b[1] = measure $1;", + ]) bound = bound_half(frequency=1e7) @@ -3569,23 +3433,21 @@ def test_parametrized_pulse_circuit(user_defined_frame): serialization_properties=OpenQASMSerializationProperties( qubit_reference_type=QubitReferenceType.PHYSICAL ), - ).source == "\n".join( - [ - "OPENQASM 3.0;", - "bit[2] b;", - "cal {", - " frame user_defined_frame_0 = newframe(device_port_x0, 10000000.0, 3.14);", - " waveform gauss_wf = gaussian(10.0us, 700.0ms, 1, false);", - "}", - "rx(0.5) $0;", - "cal {", - " set_frequency(user_defined_frame_0, 10000000.0);", - " play(user_defined_frame_0, gauss_wf);", - "}", - "b[0] = measure $0;", - "b[1] = measure $1;", - ] - ) + ).source == "\n".join([ + "OPENQASM 3.0;", + "bit[2] b;", + "cal {", + " frame user_defined_frame_0 = newframe(device_port_x0, 10000000.0, 3.14);", + " waveform gauss_wf = gaussian(10.0us, 700.0ms, 1, false);", + "}", + "rx(0.5) $0;", + "cal {", + " set_frequency(user_defined_frame_0, 10000000.0);", + " play(user_defined_frame_0, gauss_wf);", + "}", + "b[0] = measure $0;", + "b[1] = measure $1;", + ]) def test_free_param_float_mix(): @@ -3601,15 +3463,13 @@ def test_circuit_with_global_phase(): serialization_properties=OpenQASMSerializationProperties( qubit_reference_type=QubitReferenceType.PHYSICAL ), - ).source == "\n".join( - [ - "OPENQASM 3.0;", - "bit[1] b;", - "gphase(0.15);", - "x $0;", - "b[0] = measure $0;", - ] - ) + ).source == "\n".join([ + "OPENQASM 3.0;", + "bit[1] b;", + "gphase(0.15);", + "x $0;", + "b[0] = measure $0;", + ]) def test_from_ir_round_trip_transformation_with_targeted_measurements(): @@ -3622,18 +3482,16 @@ def test_from_ir_round_trip_transformation_with_targeted_measurements(): .add_instruction(Instruction(Measure(index=0), 0)) ) ir = OpenQasmProgram( - source="\n".join( - [ - "OPENQASM 3.0;", - "bit[3] b;", - "qubit[3] q;", - "h q[0];", - "cnot q[0], q[1];", - "b[2] = measure q[1];", - "b[1] = measure q[2];", - "b[0] = measure q[0];", - ] - ), + source="\n".join([ + "OPENQASM 3.0;", + "bit[3] b;", + "qubit[3] q;", + "h q[0];", + "cnot q[0], q[1];", + "b[2] = measure q[1];", + "b[1] = measure q[2];", + "b[0] = measure q[0];", + ]), inputs={}, ) diff --git a/test/unit_tests/braket/circuits/test_gate_calibration.py b/test/unit_tests/braket/circuits/test_gate_calibration.py index de3fa2fc6..13e7cfe8b 100644 --- a/test/unit_tests/braket/circuits/test_gate_calibration.py +++ b/test/unit_tests/braket/circuits/test_gate_calibration.py @@ -60,17 +60,16 @@ def test_filter(pulse_sequence): calibration_key = (Gate.Z(), QubitSet([0])) calibration_key_2 = (Gate.H(), QubitSet([1])) calibration_key_3 = (Gate.CZ(), QubitSet([0, 1])) - calibration = GateCalibrations( - { - calibration_key: pulse_sequence, - calibration_key_2: pulse_sequence, - calibration_key_3: pulse_sequence, - } - ) + calibration = GateCalibrations({ + calibration_key: pulse_sequence, + calibration_key_2: pulse_sequence, + calibration_key_3: pulse_sequence, + }) expected_calibration_1 = GateCalibrations({calibration_key: pulse_sequence}) - expected_calibration_2 = GateCalibrations( - {calibration_key: pulse_sequence, calibration_key_3: pulse_sequence} - ) + expected_calibration_2 = GateCalibrations({ + calibration_key: pulse_sequence, + calibration_key_3: pulse_sequence, + }) expected_calibration_3 = GateCalibrations({calibration_key_2: pulse_sequence}) expected_calibration_4 = GateCalibrations({}) expected_calibration_5 = calibration @@ -86,15 +85,13 @@ def test_filter(pulse_sequence): def test_to_ir(pulse_sequence): calibration_key = (Gate.Rx(angle=1), QubitSet([0, 1])) calibration = GateCalibrations({calibration_key: pulse_sequence}) - expected_ir = "\n".join( - [ - "OPENQASM 3.0;", - "defcal rx(1.0) $0, $1 {", - " barrier test_frame_rf;", - " delay[1000s] test_frame_rf;", - "}", - ] - ) + expected_ir = "\n".join([ + "OPENQASM 3.0;", + "defcal rx(1.0) $0, $1 {", + " barrier test_frame_rf;", + " delay[1000s] test_frame_rf;", + "}", + ]) assert calibration.to_ir() == expected_ir @@ -103,45 +100,44 @@ def test_to_ir(pulse_sequence): def test_to_ir_with_bad_key(pulse_sequence): calibration_key = (Gate.Z(), QubitSet([0, 1])) calibration_key_2 = (Gate.H(), QubitSet([0, 1])) - calibration = GateCalibrations( - {calibration_key: pulse_sequence, calibration_key_2: pulse_sequence} - ) - expected_ir = "\n".join( - [ - "OPENQASM 3.0;", - "defcal z $0, $1 {", - " barrier test_frame_rf;", - " delay[1000s] test_frame_rf;", - "}", - ] - ) + calibration = GateCalibrations({ + calibration_key: pulse_sequence, + calibration_key_2: pulse_sequence, + }) + expected_ir = "\n".join([ + "OPENQASM 3.0;", + "defcal z $0, $1 {", + " barrier test_frame_rf;", + " delay[1000s] test_frame_rf;", + "}", + ]) assert expected_ir == calibration.to_ir((Gate.Z(), QubitSet([1, 2]))) def test_to_ir_with_key(pulse_sequence): calibration_key = (Gate.Z(), QubitSet([0, 1])) calibration_key_2 = (Gate.H(), QubitSet([0, 1])) - calibration = GateCalibrations( - {calibration_key: pulse_sequence, calibration_key_2: pulse_sequence} - ) - expected_ir = "\n".join( - [ - "OPENQASM 3.0;", - "defcal z $0, $1 {", - " barrier test_frame_rf;", - " delay[1000s] test_frame_rf;", - "}", - ] - ) + calibration = GateCalibrations({ + calibration_key: pulse_sequence, + calibration_key_2: pulse_sequence, + }) + expected_ir = "\n".join([ + "OPENQASM 3.0;", + "defcal z $0, $1 {", + " barrier test_frame_rf;", + " delay[1000s] test_frame_rf;", + "}", + ]) assert expected_ir == calibration.to_ir(calibration_key) def test_gate_calibrations_length(pulse_sequence): calibration_key = (Gate.Z(), QubitSet([0, 1])) calibration_key_2 = (Gate.H(), QubitSet([0, 1])) - calibration = GateCalibrations( - {calibration_key: pulse_sequence, calibration_key_2: pulse_sequence} - ) + calibration = GateCalibrations({ + calibration_key: pulse_sequence, + calibration_key_2: pulse_sequence, + }) assert len(calibration) == 2 diff --git a/test/unit_tests/braket/circuits/test_gates.py b/test/unit_tests/braket/circuits/test_gates.py index 285b530c1..a72314ea3 100644 --- a/test/unit_tests/braket/circuits/test_gates.py +++ b/test/unit_tests/braket/circuits/test_gates.py @@ -1081,14 +1081,12 @@ def to_ir(pulse_gate): a_bound = gate.bind_values(a=a) a_bound_ir = to_ir(a_bound) - assert a_bound_ir == "\n".join( - [ - "cal {", - " set_frequency(user_frame, 3.0 + c);", - " delay[d * 1s] user_frame;", - "}", - ] - ) + assert a_bound_ir == "\n".join([ + "cal {", + " set_frequency(user_frame, 3.0 + c);", + " delay[d * 1s] user_frame;", + "}", + ]) assert a_bound_ir == to_ir( Gate.PulseGate(gate.pulse_sequence.make_bound_pulse_sequence({"a": a}), qubit_count) diff --git a/test/unit_tests/braket/circuits/test_measure.py b/test/unit_tests/braket/circuits/test_measure.py index 8911da5e4..c7df442a7 100644 --- a/test/unit_tests/braket/circuits/test_measure.py +++ b/test/unit_tests/braket/circuits/test_measure.py @@ -82,12 +82,10 @@ def test_measure_to_ir( Measure(), [1, 4], OpenQASMSerializationProperties(qubit_reference_type=QubitReferenceType.PHYSICAL), - "\n".join( - [ - "b[0] = measure $1;", - "b[1] = measure $4;", - ] - ), + "\n".join([ + "b[0] = measure $1;", + "b[1] = measure $4;", + ]), ), ], ) diff --git a/test/unit_tests/braket/circuits/test_noises.py b/test/unit_tests/braket/circuits/test_noises.py index 3b7f08dd8..0774ca53e 100644 --- a/test/unit_tests/braket/circuits/test_noises.py +++ b/test/unit_tests/braket/circuits/test_noises.py @@ -646,12 +646,10 @@ def test_valid_values_pauli_channel_two_qubit(probs): "#pragma braket noise phase_damping(0.5) $3", ), ( - Noise.Kraus( - [ - np.eye(4) * np.sqrt(0.9), - np.kron([[1.0, 0.0], [0.0, 1.0]], [[0.0, 1.0], [1.0, 0.0]]) * np.sqrt(0.1), - ] - ), + Noise.Kraus([ + np.eye(4) * np.sqrt(0.9), + np.kron([[1.0, 0.0], [0.0, 1.0]], [[0.0, 1.0], [1.0, 0.0]]) * np.sqrt(0.1), + ]), OpenQASMSerializationProperties(qubit_reference_type=QubitReferenceType.VIRTUAL), [3, 5], "#pragma braket noise kraus([" @@ -665,12 +663,10 @@ def test_valid_values_pauli_channel_two_qubit(probs): "[0, 0, 0.31622776601683794, 0]]) q[3], q[5]", ), ( - Noise.Kraus( - [ - np.eye(4) * np.sqrt(0.9), - np.kron([[1.0, 0.0], [0.0, 1.0]], [[0.0, 1.0], [1.0, 0.0]]) * np.sqrt(0.1), - ] - ), + Noise.Kraus([ + np.eye(4) * np.sqrt(0.9), + np.kron([[1.0, 0.0], [0.0, 1.0]], [[0.0, 1.0], [1.0, 0.0]]) * np.sqrt(0.1), + ]), OpenQASMSerializationProperties(qubit_reference_type=QubitReferenceType.PHYSICAL), [3, 5], "#pragma braket noise kraus([" @@ -684,12 +680,10 @@ def test_valid_values_pauli_channel_two_qubit(probs): "[0, 0, 0.31622776601683794, 0]]) $3, $5", ), ( - Noise.Kraus( - [ - np.array([[0.9486833j, 0], [0, 0.9486833j]]), - np.array([[0, 0.31622777], [0.31622777, 0]]), - ] - ), + Noise.Kraus([ + np.array([[0.9486833j, 0], [0, 0.9486833j]]), + np.array([[0, 0.31622777], [0.31622777, 0]]), + ]), OpenQASMSerializationProperties(qubit_reference_type=QubitReferenceType.VIRTUAL), [3], "#pragma braket noise kraus([" @@ -697,12 +691,10 @@ def test_valid_values_pauli_channel_two_qubit(probs): "[0, 0.31622777], [0.31622777, 0]]) q[3]", ), ( - Noise.Kraus( - [ - np.array([[0.9486833j, 0], [0, 0.9486833j]]), - np.array([[0, 0.31622777], [0.31622777, 0]]), - ] - ), + Noise.Kraus([ + np.array([[0.9486833j, 0], [0, 0.9486833j]]), + np.array([[0, 0.31622777], [0.31622777, 0]]), + ]), OpenQASMSerializationProperties(qubit_reference_type=QubitReferenceType.PHYSICAL), [3], "#pragma braket noise kraus([" diff --git a/test/unit_tests/braket/circuits/test_observable.py b/test/unit_tests/braket/circuits/test_observable.py index 38689398a..f592e1d19 100644 --- a/test/unit_tests/braket/circuits/test_observable.py +++ b/test/unit_tests/braket/circuits/test_observable.py @@ -155,7 +155,7 @@ def test_matmul_observable(): def test_matmul_non_observable(): - with pytest.raises(ValueError): + with pytest.raises(TypeError): Observable.I() @ "a" @@ -196,14 +196,14 @@ def test_observable_coeffs(observable): @pytest.mark.parametrize("parameter", ["foo", 1.2, -3]) def test_only_observables_sum_allowed(observable, parameter): add_observables_only = "Can only perform addition between observables." - with pytest.raises(ValueError, match=add_observables_only): + with pytest.raises(TypeError, match=add_observables_only): 2 * observable + parameter @pytest.mark.parametrize("parameter", ["foo", 1.2, -3]) def test_only_observables_subtraction_allowed(observable, parameter): add_observables_only = "Can only perform subtraction between observables." - with pytest.raises(ValueError, match=add_observables_only): + with pytest.raises(TypeError, match=add_observables_only): 2 * observable - parameter diff --git a/test/unit_tests/braket/circuits/test_observables.py b/test/unit_tests/braket/circuits/test_observables.py index 213a29705..1ca2523c8 100644 --- a/test/unit_tests/braket/circuits/test_observables.py +++ b/test/unit_tests/braket/circuits/test_observables.py @@ -374,9 +374,10 @@ def test_invalid_scalar_multiplication(expression, observable): [ ( (-3 * Observable.H()).to_matrix(), - np.array( - [[-2.12132034 + 0.0j, -2.12132034 + 0.0j], [-2.12132034 + 0.0j, 2.12132034 - 0.0j]] - ), + np.array([ + [-2.12132034 + 0.0j, -2.12132034 + 0.0j], + [-2.12132034 + 0.0j, 2.12132034 - 0.0j], + ]), ), ( (3 * Observable.Z()).to_matrix(), @@ -510,9 +511,12 @@ def test_flattened_tensor_product(): observable_one = Observable.Z() @ Observable.Y() observable_two = Observable.X() @ Observable.H() actual = Observable.TensorProduct([observable_one, observable_two]) - expected = Observable.TensorProduct( - [Observable.Z(), Observable.Y(), Observable.X(), Observable.H()] - ) + expected = Observable.TensorProduct([ + Observable.Z(), + Observable.Y(), + Observable.X(), + Observable.H(), + ]) assert expected == actual @@ -525,20 +529,19 @@ def test_flattened_tensor_product(): ), ( np.array([[0, -1j], [1j, 0]]), - np.array( - [[-0.70710678 + 0.0j, -0.70710678 + 0.0j], [0.0 + 0.70710678j, 0.0 - 0.70710678j]] - ) + np.array([ + [-0.70710678 + 0.0j, -0.70710678 + 0.0j], + [0.0 + 0.70710678j, 0.0 - 0.70710678j], + ]) .conj() .T, ), ( np.array([[1, 1 - 1j], [1 + 1j, -1]]), - np.array( - [ - [-0.45970084 - 0.0j, 0.62796303 - 0.62796303j], - [-0.88807383 - 0.0j, -0.32505758 + 0.32505758j], - ] - ), + np.array([ + [-0.45970084 - 0.0j, 0.62796303 - 0.62796303j], + [-0.88807383 - 0.0j, -0.32505758 + 0.32505758j], + ]), ), ], ) @@ -580,9 +583,10 @@ def test_tensor_product_to_ir(): def test_tensor_product_matmul_tensor(): t1 = Observable.TensorProduct([Observable.Z(), Observable.I(), Observable.X()]) - t2 = Observable.TensorProduct( - [Observable.Hermitian(matrix=Observable.I().to_matrix()), Observable.Y()] - ) + t2 = Observable.TensorProduct([ + Observable.Hermitian(matrix=Observable.I().to_matrix()), + Observable.Y(), + ]) t3 = t1 @ t2 assert t3.to_ir() == ["z", "i", "x", [[[1.0, 0], [0, 0]], [[0, 0], [1.0, 0]]], "y"] assert t3.qubit_count == 5 @@ -605,7 +609,7 @@ def test_tensor_product_eigenvalue_index_out_of_bounds(): def test_tensor_product_value_error(): - with pytest.raises(ValueError): + with pytest.raises(TypeError): Observable.TensorProduct([Observable.Z(), Observable.I(), Observable.X()]) @ "a" diff --git a/test/unit_tests/braket/circuits/test_unicode_circuit_diagram.py b/test/unit_tests/braket/circuits/test_unicode_circuit_diagram.py index efc87ee24..a0288ddda 100644 --- a/test/unit_tests/braket/circuits/test_unicode_circuit_diagram.py +++ b/test/unit_tests/braket/circuits/test_unicode_circuit_diagram.py @@ -110,7 +110,7 @@ def test_one_gate_with_zero_global_phase(): def test_one_gate_one_qubit_rotation_with_unicode(): - theta = FreeParameter("\u03B8") + theta = FreeParameter("\u03b8") circ = Circuit().rx(angle=theta, target=0) # Column formats to length of the gate plus the ascii representation for the angle. expected = ( @@ -126,7 +126,7 @@ def test_one_gate_one_qubit_rotation_with_unicode(): def test_one_gate_with_parametric_expression_global_phase_(): - theta = FreeParameter("\u03B8") + theta = FreeParameter("\u03b8") circ = Circuit().x(target=0).gphase(2 * theta).x(0).gphase(1) expected = ( "T : │ 0 │ 1 │ 2 │", diff --git a/test/unit_tests/braket/devices/test_local_simulator.py b/test/unit_tests/braket/devices/test_local_simulator.py index 6c2976812..39ad1c299 100644 --- a/test/unit_tests/braket/devices/test_local_simulator.py +++ b/test/unit_tests/braket/devices/test_local_simulator.py @@ -42,73 +42,67 @@ AnalogHamiltonianSimulationQuantumTaskResult, ) -GATE_MODEL_RESULT = GateModelTaskResult( - **{ - "measurements": [[0, 0], [0, 0], [0, 0], [1, 1]], - "measuredQubits": [0, 1], - "taskMetadata": { - "braketSchemaHeader": {"name": "braket.task_result.task_metadata", "version": "1"}, - "id": "task_arn", - "shots": 100, - "deviceId": "default", +GATE_MODEL_RESULT = GateModelTaskResult(**{ + "measurements": [[0, 0], [0, 0], [0, 0], [1, 1]], + "measuredQubits": [0, 1], + "taskMetadata": { + "braketSchemaHeader": {"name": "braket.task_result.task_metadata", "version": "1"}, + "id": "task_arn", + "shots": 100, + "deviceId": "default", + }, + "additionalMetadata": { + "action": { + "braketSchemaHeader": {"name": "braket.ir.jaqcd.program", "version": "1"}, + "instructions": [{"control": 0, "target": 1, "type": "cnot"}], }, - "additionalMetadata": { - "action": { - "braketSchemaHeader": {"name": "braket.ir.jaqcd.program", "version": "1"}, - "instructions": [{"control": 0, "target": 1, "type": "cnot"}], - }, - }, - } -) - -ANNEALING_RESULT = AnnealingTaskResult( - **{ - "solutions": [[-1, -1, -1, -1], [1, -1, 1, 1], [1, -1, -1, 1]], - "solutionCounts": [3, 2, 4], - "values": [0.0, 1.0, 2.0], - "variableCount": 4, - "taskMetadata": { - "id": "task_arn", - "shots": 100, - "deviceId": "device_id", + }, +}) + +ANNEALING_RESULT = AnnealingTaskResult(**{ + "solutions": [[-1, -1, -1, -1], [1, -1, 1, 1], [1, -1, -1, 1]], + "solutionCounts": [3, 2, 4], + "values": [0.0, 1.0, 2.0], + "variableCount": 4, + "taskMetadata": { + "id": "task_arn", + "shots": 100, + "deviceId": "device_id", + }, + "additionalMetadata": { + "action": { + "type": "ISING", + "linear": {"0": 0.3333, "1": -0.333, "4": -0.333, "5": 0.333}, + "quadratic": {"0,4": 0.667, "0,5": -1.0, "1,4": 0.667, "1,5": 0.667}, }, - "additionalMetadata": { - "action": { - "type": "ISING", - "linear": {"0": 0.3333, "1": -0.333, "4": -0.333, "5": 0.333}, - "quadratic": {"0,4": 0.667, "0,5": -1.0, "1,4": 0.667, "1,5": 0.667}, - }, - "dwaveMetadata": { - "activeVariables": [0], - "timing": { - "qpuSamplingTime": 100, - "qpuAnnealTimePerSample": 20, - "qpuAccessTime": 10917, - "qpuAccessOverheadTime": 3382, - "qpuReadoutTimePerSample": 274, - "qpuProgrammingTime": 9342, - "qpuDelayTimePerSample": 21, - "postProcessingOverheadTime": 117, - "totalPostProcessingTime": 117, - "totalRealTime": 10917, - "runTimeChip": 1575, - "annealTimePerRun": 20, - "readoutTimePerRun": 274, - }, + "dwaveMetadata": { + "activeVariables": [0], + "timing": { + "qpuSamplingTime": 100, + "qpuAnnealTimePerSample": 20, + "qpuAccessTime": 10917, + "qpuAccessOverheadTime": 3382, + "qpuReadoutTimePerSample": 274, + "qpuProgrammingTime": 9342, + "qpuDelayTimePerSample": 21, + "postProcessingOverheadTime": 117, + "totalPostProcessingTime": 117, + "totalRealTime": 10917, + "runTimeChip": 1575, + "annealTimePerRun": 20, + "readoutTimePerRun": 274, }, }, - } -) + }, +}) -AHS_RESULT = AnalogHamiltonianSimulationTaskResult( - **{ - "taskMetadata": { - "id": "rydberg", - "shots": 100, - "deviceId": "rydbergLocalSimulator", - }, - } -) +AHS_RESULT = AnalogHamiltonianSimulationTaskResult(**{ + "taskMetadata": { + "id": "rydberg", + "shots": 100, + "deviceId": "rydbergLocalSimulator", + }, +}) class DummyCircuitSimulator(BraketSimulator): @@ -127,31 +121,29 @@ def run( @property def properties(self) -> DeviceCapabilities: - return DeviceCapabilities.parse_obj( - { - "service": { - "executionWindows": [ - { - "executionDay": "Everyday", - "windowStartHour": "11:00", - "windowEndHour": "12:00", - } - ], - "shotsRange": [1, 10], + return DeviceCapabilities.parse_obj({ + "service": { + "executionWindows": [ + { + "executionDay": "Everyday", + "windowStartHour": "11:00", + "windowEndHour": "12:00", + } + ], + "shotsRange": [1, 10], + }, + "action": { + "braket.ir.openqasm.program": { + "actionType": "braket.ir.openqasm.program", + "version": ["1"], }, - "action": { - "braket.ir.openqasm.program": { - "actionType": "braket.ir.openqasm.program", - "version": ["1"], - }, - "braket.ir.jaqcd.program": { - "actionType": "braket.ir.jaqcd.program", - "version": ["1"], - }, + "braket.ir.jaqcd.program": { + "actionType": "braket.ir.jaqcd.program", + "version": ["1"], }, - "deviceParameters": {}, - } - ) + }, + "deviceParameters": {}, + }) class DummyJaqcdSimulator(BraketSimulator): @@ -171,27 +163,25 @@ def run( @property def properties(self) -> DeviceCapabilities: - return DeviceCapabilities.parse_obj( - { - "service": { - "executionWindows": [ - { - "executionDay": "Everyday", - "windowStartHour": "11:00", - "windowEndHour": "12:00", - } - ], - "shotsRange": [1, 10], - }, - "action": { - "braket.ir.jaqcd.program": { - "actionType": "braket.ir.jaqcd.program", - "version": ["1"], - }, + return DeviceCapabilities.parse_obj({ + "service": { + "executionWindows": [ + { + "executionDay": "Everyday", + "windowStartHour": "11:00", + "windowEndHour": "12:00", + } + ], + "shotsRange": [1, 10], + }, + "action": { + "braket.ir.jaqcd.program": { + "actionType": "braket.ir.jaqcd.program", + "version": ["1"], }, - "deviceParameters": {}, - } - ) + }, + "deviceParameters": {}, + }) def assert_shots(self, shots): assert self._shots == shots @@ -211,46 +201,42 @@ def run( @property def properties(self) -> DeviceCapabilities: - device_properties = DeviceCapabilities.parse_obj( - { - "service": { - "executionWindows": [ - { - "executionDay": "Everyday", - "windowStartHour": "00:00", - "windowEndHour": "23:59:59", - } - ], - "shotsRange": [1, 10], - }, - "action": { - "braket.ir.openqasm.program": { - "actionType": "braket.ir.openqasm.program", - "version": ["1"], + device_properties = DeviceCapabilities.parse_obj({ + "service": { + "executionWindows": [ + { + "executionDay": "Everyday", + "windowStartHour": "00:00", + "windowEndHour": "23:59:59", } - }, - "deviceParameters": {}, - } - ) - oq3_action = OpenQASMDeviceActionProperties.parse_raw( - json.dumps( - { + ], + "shotsRange": [1, 10], + }, + "action": { + "braket.ir.openqasm.program": { "actionType": "braket.ir.openqasm.program", "version": ["1"], - "supportedOperations": ["rx", "ry", "h", "cy", "cnot", "unitary"], - "supportedResultTypes": [ - {"name": "StateVector", "observables": None, "minShots": 0, "maxShots": 0}, - ], - "supportedPragmas": [ - "braket_unitary_matrix", - "braket_result_type_sample", - "braket_result_type_expectation", - "braket_result_type_variance", - "braket_result_type_probability", - "braket_result_type_state_vector", - ], } - ) + }, + "deviceParameters": {}, + }) + oq3_action = OpenQASMDeviceActionProperties.parse_raw( + json.dumps({ + "actionType": "braket.ir.openqasm.program", + "version": ["1"], + "supportedOperations": ["rx", "ry", "h", "cy", "cnot", "unitary"], + "supportedResultTypes": [ + {"name": "StateVector", "observables": None, "minShots": 0, "maxShots": 0}, + ], + "supportedPragmas": [ + "braket_unitary_matrix", + "braket_result_type_sample", + "braket_result_type_expectation", + "braket_result_type_variance", + "braket_result_type_probability", + "braket_result_type_state_vector", + ], + }) ) device_properties.action[DeviceActionType.OPENQASM] = oq3_action return device_properties @@ -283,51 +269,47 @@ def run( @property def properties(self) -> DeviceCapabilities: - device_properties = DeviceCapabilities.parse_obj( - { - "service": { - "executionWindows": [ - { - "executionDay": "Everyday", - "windowStartHour": "11:00", - "windowEndHour": "12:00", - } - ], - "shotsRange": [1, 10], - }, - "action": {}, - "deviceParameters": {}, - } - ) + device_properties = DeviceCapabilities.parse_obj({ + "service": { + "executionWindows": [ + { + "executionDay": "Everyday", + "windowStartHour": "11:00", + "windowEndHour": "12:00", + } + ], + "shotsRange": [1, 10], + }, + "action": {}, + "deviceParameters": {}, + }) oq3_action = OpenQASMDeviceActionProperties.parse_raw( - json.dumps( - { - "actionType": "braket.ir.openqasm.program", - "version": ["1"], - "supportedOperations": ["rx", "ry", "h", "cy", "cnot", "unitary"], - "supportedResultTypes": [ - {"name": "StateVector", "observables": None, "minShots": 0, "maxShots": 0}, - ], - "supportedPragmas": [ - "braket_noise_bit_flip", - "braket_noise_depolarizing", - "braket_noise_kraus", - "braket_noise_pauli_channel", - "braket_noise_generalized_amplitude_damping", - "braket_noise_amplitude_damping", - "braket_noise_phase_flip", - "braket_noise_phase_damping", - "braket_noise_two_qubit_dephasing", - "braket_noise_two_qubit_depolarizing", - "braket_unitary_matrix", - "braket_result_type_sample", - "braket_result_type_expectation", - "braket_result_type_variance", - "braket_result_type_probability", - "braket_result_type_density_matrix", - ], - } - ) + json.dumps({ + "actionType": "braket.ir.openqasm.program", + "version": ["1"], + "supportedOperations": ["rx", "ry", "h", "cy", "cnot", "unitary"], + "supportedResultTypes": [ + {"name": "StateVector", "observables": None, "minShots": 0, "maxShots": 0}, + ], + "supportedPragmas": [ + "braket_noise_bit_flip", + "braket_noise_depolarizing", + "braket_noise_kraus", + "braket_noise_pauli_channel", + "braket_noise_generalized_amplitude_damping", + "braket_noise_amplitude_damping", + "braket_noise_phase_flip", + "braket_noise_phase_damping", + "braket_noise_two_qubit_dephasing", + "braket_noise_two_qubit_depolarizing", + "braket_unitary_matrix", + "braket_result_type_sample", + "braket_result_type_expectation", + "braket_result_type_variance", + "braket_result_type_probability", + "braket_result_type_density_matrix", + ], + }) ) device_properties.action[DeviceActionType.OPENQASM] = oq3_action return device_properties @@ -339,27 +321,25 @@ def run(self, problem: ir.annealing.Problem, *args, **kwargs) -> AnnealingTaskRe @property def properties(self) -> DeviceCapabilities: - return DeviceCapabilities.parse_obj( - { - "service": { - "executionWindows": [ - { - "executionDay": "Everyday", - "windowStartHour": "11:00", - "windowEndHour": "12:00", - } - ], - "shotsRange": [1, 10], - }, - "action": { - "braket.ir.annealing.problem": { - "actionType": "braket.ir.annealing.problem", - "version": ["1"], + return DeviceCapabilities.parse_obj({ + "service": { + "executionWindows": [ + { + "executionDay": "Everyday", + "windowStartHour": "11:00", + "windowEndHour": "12:00", } - }, - "deviceParameters": {}, - } - ) + ], + "shotsRange": [1, 10], + }, + "action": { + "braket.ir.annealing.problem": { + "actionType": "braket.ir.annealing.problem", + "version": ["1"], + } + }, + "deviceParameters": {}, + }) class DummyRydbergSimulator(BraketSimulator): @@ -513,16 +493,14 @@ def test_run_gate_model_inputs(): task = sim.run(circuit, inputs={"theta": 2}, shots=10) dummy.run.assert_called_with( Program( - source="\n".join( - ( - "OPENQASM 3.0;", - "input float theta;", - "bit[1] b;", - "qubit[1] q;", - "rx(theta) q[0];", - "b[0] = measure q[0];", - ) - ), + source="\n".join(( + "OPENQASM 3.0;", + "input float theta;", + "bit[1] b;", + "qubit[1] q;", + "rx(theta) q[0];", + "b[0] = measure q[0];", + )), inputs={"theta": 2}, ), shots=10, @@ -758,8 +736,7 @@ def test_run_noisy_circuit_with_noise_model(mock_run, noise_model): _ = device.run(circuit, shots=4) expected_warning = ( - "The noise model of the device is applied to a circuit that already has noise " - "instructions." + "The noise model of the device is applied to a circuit that already has noise instructions." ) expected_circuit = textwrap.dedent( """ diff --git a/test/unit_tests/braket/jobs/local/test_local_job.py b/test/unit_tests/braket/jobs/local/test_local_job.py index 185b059e3..07f42a323 100644 --- a/test/unit_tests/braket/jobs/local/test_local_job.py +++ b/test/unit_tests/braket/jobs/local/test_local_job.py @@ -49,32 +49,24 @@ def test_envs(): @pytest.mark.parametrize( "creation_kwargs", [ - ( - { - "jobName": "Test-Job-Name", - "algorithmSpecification": {"containerImage": {"uri": "file://test-URI"}}, - "checkpointConfig": {"localPath": "test/local/path/"}, - } - ), - ( - { - "jobName": "Test-Job-Name", - "algorithmSpecification": {"containerImage": {"uri": "file://test-URI"}}, - "checkpointConfig": {}, - } - ), - ( - { - "jobName": "Test-Job-Name", - "algorithmSpecification": {"containerImage": {"uri": "file://test-URI"}}, - } - ), - ( - { - "jobName": "Test-Job-Name", - "algorithmSpecification": {}, - } - ), + ({ + "jobName": "Test-Job-Name", + "algorithmSpecification": {"containerImage": {"uri": "file://test-URI"}}, + "checkpointConfig": {"localPath": "test/local/path/"}, + }), + ({ + "jobName": "Test-Job-Name", + "algorithmSpecification": {"containerImage": {"uri": "file://test-URI"}}, + "checkpointConfig": {}, + }), + ({ + "jobName": "Test-Job-Name", + "algorithmSpecification": {"containerImage": {"uri": "file://test-URI"}}, + }), + ({ + "jobName": "Test-Job-Name", + "algorithmSpecification": {}, + }), ], ) @patch("braket.jobs.local.local_job.prepare_quantum_job") diff --git a/test/unit_tests/braket/jobs/local/test_local_job_container.py b/test/unit_tests/braket/jobs/local/test_local_job_container.py index 47efceef5..4d2827516 100644 --- a/test/unit_tests/braket/jobs/local/test_local_job_container.py +++ b/test/unit_tests/braket/jobs/local/test_local_job_container.py @@ -61,9 +61,16 @@ def test_start_and_stop(mock_run, mock_check_output, image_uri, aws_session): with _LocalJobContainer(image_uri, aws_session): pass mock_check_output.assert_any_call(["docker", "images", "-q", image_uri]) - mock_check_output.assert_any_call( - ["docker", "run", "-d", "--rm", local_image_name, "tail", "-f", "/dev/null"] - ) + mock_check_output.assert_any_call([ + "docker", + "run", + "-d", + "--rm", + local_image_name, + "tail", + "-f", + "/dev/null", + ]) assert mock_check_output.call_count == 2 mock_run.assert_any_call(["docker", "stop", running_container_name]) assert mock_run.call_count == 1 @@ -124,9 +131,16 @@ def test_pull_container( ): pass mock_check_output.assert_any_call(["docker", "images", "-q", image_uri]) - mock_check_output.assert_any_call( - ["docker", "run", "-d", "--rm", local_image_name, "tail", "-f", "/dev/null"] - ) + mock_check_output.assert_any_call([ + "docker", + "run", + "-d", + "--rm", + local_image_name, + "tail", + "-f", + "/dev/null", + ]) assert mock_check_output.call_count == len(check_output) mock_run.assert_any_call(["docker", "login", "-u", "AWS", "-p", test_token, repo_uri]) mock_run.assert_any_call(["docker", "pull", image_uri]) @@ -152,9 +166,16 @@ def test_pull_container_forced_update_invalid_name( pass mock_logger.warning.assert_called_with(f"Unable to update {local_image_name}.") mock_check_output.assert_any_call(["docker", "images", "-q", local_image_name]) - mock_check_output.assert_any_call( - ["docker", "run", "-d", "--rm", local_image_name, "tail", "-f", "/dev/null"] - ) + mock_check_output.assert_any_call([ + "docker", + "run", + "-d", + "--rm", + local_image_name, + "tail", + "-f", + "/dev/null", + ]) assert mock_check_output.call_count == 2 mock_run.assert_any_call(["docker", "stop", running_container_name]) assert mock_run.call_count == 1 @@ -183,12 +204,23 @@ def test_run_job_success( container.run_local_job(env_variables) assert container.run_log == "this\nis a\ntest\n" mock_check_output.assert_any_call(["docker", "images", "-q", image_uri]) - mock_check_output.assert_any_call( - ["docker", "run", "-d", "--rm", local_image_name, "tail", "-f", "/dev/null"] - ) - mock_check_output.assert_any_call( - ["docker", "exec", running_container_name, "printenv", "SAGEMAKER_PROGRAM"] - ) + mock_check_output.assert_any_call([ + "docker", + "run", + "-d", + "--rm", + local_image_name, + "tail", + "-f", + "/dev/null", + ]) + mock_check_output.assert_any_call([ + "docker", + "exec", + running_container_name, + "printenv", + "SAGEMAKER_PROGRAM", + ]) assert mock_check_output.call_count == 3 mock_popen.assert_called_with( [ @@ -234,12 +266,23 @@ def test_run_customer_script_fails( container.run_local_job(env_variables) assert container.run_log == "this\nis a\ntest\nProcess exited with code: 400" mock_check_output.assert_any_call(["docker", "images", "-q", image_uri]) - mock_check_output.assert_any_call( - ["docker", "run", "-d", "--rm", local_image_name, "tail", "-f", "/dev/null"] - ) - mock_check_output.assert_any_call( - ["docker", "exec", running_container_name, "printenv", "SAGEMAKER_PROGRAM"] - ) + mock_check_output.assert_any_call([ + "docker", + "run", + "-d", + "--rm", + local_image_name, + "tail", + "-f", + "/dev/null", + ]) + mock_check_output.assert_any_call([ + "docker", + "exec", + running_container_name, + "printenv", + "SAGEMAKER_PROGRAM", + ]) assert mock_check_output.call_count == 3 mock_popen.assert_called_with( [ @@ -287,7 +330,7 @@ def test_running_throws_exception( assert container.run_log == expected_exception assert mock_check_output.call_count == 3 mock_run.assert_called_with(["docker", "stop", running_container_name]) - mock_logger.error.assert_called_with(expected_exception) + mock_logger.exception.assert_called_with(expected_exception) @patch("subprocess.check_output") @@ -304,12 +347,24 @@ def test_make_dir(mock_run, mock_check_output, repo_uri, image_uri, aws_session) with _LocalJobContainer(image_uri, aws_session) as container: container.makedir(test_dir_path) mock_check_output.assert_any_call(["docker", "images", "-q", image_uri]) - mock_check_output.assert_any_call( - ["docker", "run", "-d", "--rm", local_image_name, "tail", "-f", "/dev/null"] - ) - mock_check_output.assert_any_call( - ["docker", "exec", running_container_name, "mkdir", "-p", test_dir_path] - ) + mock_check_output.assert_any_call([ + "docker", + "run", + "-d", + "--rm", + local_image_name, + "tail", + "-f", + "/dev/null", + ]) + mock_check_output.assert_any_call([ + "docker", + "exec", + running_container_name, + "mkdir", + "-p", + test_dir_path, + ]) assert mock_check_output.call_count == 3 mock_run.assert_any_call(["docker", "stop", running_container_name]) assert mock_run.call_count == 1 @@ -331,22 +386,30 @@ def test_copy_to(mock_run, mock_check_output, repo_uri, image_uri, aws_session): with _LocalJobContainer(image_uri, aws_session) as container: container.copy_to(source_path, dest_path) mock_check_output.assert_any_call(["docker", "images", "-q", image_uri]) - mock_check_output.assert_any_call( - ["docker", "run", "-d", "--rm", local_image_name, "tail", "-f", "/dev/null"] - ) - mock_check_output.assert_any_call( - [ - "docker", - "exec", - running_container_name, - "mkdir", - "-p", - str(PurePosixPath("test", "dest", "dir", "path")), - ] - ) - mock_check_output.assert_any_call( - ["docker", "cp", source_path, f"{running_container_name}:{dest_path}"] - ) + mock_check_output.assert_any_call([ + "docker", + "run", + "-d", + "--rm", + local_image_name, + "tail", + "-f", + "/dev/null", + ]) + mock_check_output.assert_any_call([ + "docker", + "exec", + running_container_name, + "mkdir", + "-p", + str(PurePosixPath("test", "dest", "dir", "path")), + ]) + mock_check_output.assert_any_call([ + "docker", + "cp", + source_path, + f"{running_container_name}:{dest_path}", + ]) assert mock_check_output.call_count == 4 mock_run.assert_any_call(["docker", "stop", running_container_name]) assert mock_run.call_count == 1 @@ -368,12 +431,22 @@ def test_copy_from(mock_run, mock_check_output, repo_uri, image_uri, aws_session with _LocalJobContainer(image_uri, aws_session) as container: container.copy_from(source_path, dest_path) mock_check_output.assert_any_call(["docker", "images", "-q", image_uri]) - mock_check_output.assert_any_call( - ["docker", "run", "-d", "--rm", local_image_name, "tail", "-f", "/dev/null"] - ) - mock_check_output.assert_any_call( - ["docker", "cp", f"{running_container_name}:{source_path}", dest_path] - ) + mock_check_output.assert_any_call([ + "docker", + "run", + "-d", + "--rm", + local_image_name, + "tail", + "-f", + "/dev/null", + ]) + mock_check_output.assert_any_call([ + "docker", + "cp", + f"{running_container_name}:{source_path}", + dest_path, + ]) assert mock_check_output.call_count == 3 mock_run.assert_any_call(["docker", "stop", running_container_name]) assert mock_run.call_count == 1 diff --git a/test/unit_tests/braket/jobs/local/test_local_job_container_setup.py b/test/unit_tests/braket/jobs/local/test_local_job_container_setup.py index 51199055f..07ca52f79 100644 --- a/test/unit_tests/braket/jobs/local/test_local_job_container_setup.py +++ b/test/unit_tests/braket/jobs/local/test_local_job_container_setup.py @@ -188,13 +188,11 @@ def test_input(container, aws_session, creation_kwargs, input_data_config): def test_duplicate_input(container, aws_session, creation_kwargs, input_data_config): - input_data_config.append( - { - # this is a duplicate channel - "channelName": "single-file", - "dataSource": {"s3DataSource": {"s3Uri": "s3://input_bucket/irrelevant"}}, - } - ) + input_data_config.append({ + # this is a duplicate channel + "channelName": "single-file", + "dataSource": {"s3DataSource": {"s3Uri": "s3://input_bucket/irrelevant"}}, + }) creation_kwargs.update({"inputDataConfig": input_data_config}) dupes_not_allowed = "Duplicate channel names not allowed for input data: single-file" with pytest.raises(ValueError, match=dupes_not_allowed): @@ -202,13 +200,11 @@ def test_duplicate_input(container, aws_session, creation_kwargs, input_data_con def test_no_data_input(container, aws_session, creation_kwargs, input_data_config): - input_data_config.append( - { - # this channel won't match any data - "channelName": "no-data", - "dataSource": {"s3DataSource": {"s3Uri": "s3://input_bucket/irrelevant"}}, - } - ) + input_data_config.append({ + # this channel won't match any data + "channelName": "no-data", + "dataSource": {"s3DataSource": {"s3Uri": "s3://input_bucket/irrelevant"}}, + }) creation_kwargs.update({"inputDataConfig": input_data_config}) no_data_found = "No data found for channel 'no-data'" with pytest.raises(RuntimeError, match=no_data_found): diff --git a/test/unit_tests/braket/jobs/test_data_persistence.py b/test/unit_tests/braket/jobs/test_data_persistence.py index a4ac78f26..bf40bdfd4 100644 --- a/test/unit_tests/braket/jobs/test_data_persistence.py +++ b/test/unit_tests/braket/jobs/test_data_persistence.py @@ -37,35 +37,31 @@ "", PersistedJobDataFormat.PLAINTEXT, {"converged": True, "energy": -0.2}, - json.dumps( - { - "braketSchemaHeader": { - "name": "braket.jobs_data.persisted_job_data", - "version": "1", - }, - "dataDictionary": {"converged": True, "energy": -0.2}, - "dataFormat": "plaintext", - } - ), + json.dumps({ + "braketSchemaHeader": { + "name": "braket.jobs_data.persisted_job_data", + "version": "1", + }, + "dataDictionary": {"converged": True, "energy": -0.2}, + "dataFormat": "plaintext", + }), ), ( "job_pickled_simple_dict", "suffix1", PersistedJobDataFormat.PICKLED_V4, {"converged": True, "energy": -0.2}, - json.dumps( - { - "braketSchemaHeader": { - "name": "braket.jobs_data.persisted_job_data", - "version": "1", - }, - "dataDictionary": { - "converged": "gASILg==\n", - "energy": "gASVCgAAAAAAAABHv8mZmZmZmZou\n", - }, - "dataFormat": "pickled_v4", - } - ), + json.dumps({ + "braketSchemaHeader": { + "name": "braket.jobs_data.persisted_job_data", + "version": "1", + }, + "dataDictionary": { + "converged": "gASILg==\n", + "energy": "gASVCgAAAAAAAABHv8mZmZmZmZou\n", + }, + "dataFormat": "pickled_v4", + }), ), ], ) @@ -105,35 +101,31 @@ def test_save_job_checkpoint_raises_error_empty_data(checkpoint_data): "job_plaintext_simple_dict", "", PersistedJobDataFormat.PLAINTEXT, - json.dumps( - { - "braketSchemaHeader": { - "name": "braket.jobs_data.persisted_job_data", - "version": "1", - }, - "dataDictionary": {"converged": True, "energy": -0.2}, - "dataFormat": "plaintext", - } - ), + json.dumps({ + "braketSchemaHeader": { + "name": "braket.jobs_data.persisted_job_data", + "version": "1", + }, + "dataDictionary": {"converged": True, "energy": -0.2}, + "dataFormat": "plaintext", + }), {"converged": True, "energy": -0.2}, ), ( "job_pickled_simple_dict", "", PersistedJobDataFormat.PICKLED_V4, - json.dumps( - { - "braketSchemaHeader": { - "name": "braket.jobs_data.persisted_job_data", - "version": "1", - }, - "dataDictionary": { - "converged": "gASILg==\n", - "energy": "gASVCgAAAAAAAABHv8mZmZmZmZou\n", - }, - "dataFormat": "pickled_v4", - } - ), + json.dumps({ + "braketSchemaHeader": { + "name": "braket.jobs_data.persisted_job_data", + "version": "1", + }, + "dataDictionary": { + "converged": "gASILg==\n", + "energy": "gASVCgAAAAAAAABHv8mZmZmZmZou\n", + }, + "dataFormat": "pickled_v4", + }), {"converged": True, "energy": -0.2}, ), ], @@ -180,19 +172,17 @@ def test_load_job_checkpoint_raises_error_corrupted_data(): file_path = f"{tmp_dir}/{job_name}_{file_suffix}.json" with open(file_path, "w") as corrupted_file: corrupted_file.write( - json.dumps( - { - "braketSchemaHeader": { - "name": "braket.jobs_data.persisted_job_data", - "version": "1", - }, - "dataDictionary": { - "converged": "gASILg==\n", - "energy": "gASVCgBHv--corrupted---\n", - }, - "dataFormat": "pickled_v4", - } - ) + json.dumps({ + "braketSchemaHeader": { + "name": "braket.jobs_data.persisted_job_data", + "version": "1", + }, + "dataDictionary": { + "converged": "gASILg==\n", + "energy": "gASVCgBHv--corrupted---\n", + }, + "dataFormat": "pickled_v4", + }) ) with patch.dict( @@ -231,33 +221,29 @@ def test_save_and_load_job_checkpoint(): ( PersistedJobDataFormat.PLAINTEXT, {"converged": True, "energy": -0.2}, - json.dumps( - { - "braketSchemaHeader": { - "name": "braket.jobs_data.persisted_job_data", - "version": "1", - }, - "dataDictionary": {"converged": True, "energy": -0.2}, - "dataFormat": "plaintext", - } - ), + json.dumps({ + "braketSchemaHeader": { + "name": "braket.jobs_data.persisted_job_data", + "version": "1", + }, + "dataDictionary": {"converged": True, "energy": -0.2}, + "dataFormat": "plaintext", + }), ), ( PersistedJobDataFormat.PICKLED_V4, {"converged": True, "energy": -0.2}, - json.dumps( - { - "braketSchemaHeader": { - "name": "braket.jobs_data.persisted_job_data", - "version": "1", - }, - "dataDictionary": { - "converged": "gASILg==\n", - "energy": "gASVCgAAAAAAAABHv8mZmZmZmZou\n", - }, - "dataFormat": "pickled_v4", - } - ), + json.dumps({ + "braketSchemaHeader": { + "name": "braket.jobs_data.persisted_job_data", + "version": "1", + }, + "dataDictionary": { + "converged": "gASILg==\n", + "energy": "gASVCgAAAAAAAABHv8mZmZmZmZou\n", + }, + "dataFormat": "pickled_v4", + }), ), ], ) diff --git a/test/unit_tests/braket/jobs/test_environment_variables.py b/test/unit_tests/braket/jobs/test_environment_variables.py index 2c8a2f546..dd1f12407 100644 --- a/test/unit_tests/braket/jobs/test_environment_variables.py +++ b/test/unit_tests/braket/jobs/test_environment_variables.py @@ -58,8 +58,9 @@ def test_hyperparameters(): "a": "a_val", "b": 2, } - with tempfile.TemporaryDirectory() as temp_dir, patch.dict( - os.environ, {"AMZN_BRAKET_HP_FILE": str(Path(temp_dir) / hp_file)} + with ( + tempfile.TemporaryDirectory() as temp_dir, + patch.dict(os.environ, {"AMZN_BRAKET_HP_FILE": str(Path(temp_dir) / hp_file)}), ): with open(str(Path(temp_dir) / hp_file), "w") as f: json.dump(hyperparameters, f) diff --git a/test/unit_tests/braket/jobs/test_hybrid_job.py b/test/unit_tests/braket/jobs/test_hybrid_job.py index b1739d879..80df96674 100644 --- a/test/unit_tests/braket/jobs/test_hybrid_job.py +++ b/test/unit_tests/braket/jobs/test_hybrid_job.py @@ -281,7 +281,9 @@ def my_entry(c=0, d: float = 1.0, **extras): aws_session=aws_session, ) assert mock_tempdir.return_value.__exit__.called - _mock_open.assert_called_with(Path(mock_tempdir_name) / "requirements.txt", "w") + _mock_open.assert_called_with( + Path(mock_tempdir_name) / "requirements.txt", "w", encoding="utf-8" + ) _mock_open.return_value.__enter__.return_value.write.assert_called_with( "\n".join(dependency_list) ) diff --git a/test/unit_tests/braket/pulse/test_pulse_sequence.py b/test/unit_tests/braket/pulse/test_pulse_sequence.py index fa6eca395..20b3bbef4 100644 --- a/test/unit_tests/braket/pulse/test_pulse_sequence.py +++ b/test/unit_tests/braket/pulse/test_pulse_sequence.py @@ -69,15 +69,13 @@ def conflicting_user_defined_frame(): def test_pulse_sequence_with_user_defined_frame(user_defined_frame): pulse_sequence = PulseSequence().set_frequency(user_defined_frame, 6e6) - expected_str = "\n".join( - [ - "OPENQASM 3.0;", - "cal {", - " frame user_defined_frame_0 = newframe(device_port_x0, 10000000.0, 3.14);", - " set_frequency(user_defined_frame_0, 6000000.0);", - "}", - ] - ) + expected_str = "\n".join([ + "OPENQASM 3.0;", + "cal {", + " frame user_defined_frame_0 = newframe(device_port_x0, 10000000.0, 3.14);", + " set_frequency(user_defined_frame_0, 6000000.0);", + "}", + ]) assert pulse_sequence.to_ir() == expected_str @@ -132,41 +130,38 @@ def test_pulse_sequence_make_bound_pulse_sequence(predefined_frame_1, predefined ) .capture_v0(predefined_frame_2) ) - expected_str_unbound = "\n".join( - [ - "OPENQASM 3.0;", - "cal {", - " bit[2] psb;", - *[ - f" input float {parameter};" - for parameter in reversed(list(pulse_sequence.parameters)) - ], - " waveform gauss_wf = gaussian(length_g * 1s, sigma_g * 1s, 1, false);", - " waveform drag_gauss_wf = drag_gaussian(length_dg * 1s," - " sigma_dg * 1s, 0.2, 1, false);", - " waveform constant_wf = constant(length_c * 1s, 2.0 + 0.3im);", - " waveform arb_wf = {1.0 + 0.4im, 0, 0.3, 0.1 + 0.2im};", - " waveform erf_square_wf = erf_square(length_es * 1s, width_es * 1s, 2.0ns," - " 8.0ns, 1, false);", - " set_frequency(predefined_frame_1, a + 2.0 * c);", - " shift_frequency(predefined_frame_1, a + 2.0 * c);", - " set_phase(predefined_frame_1, a + 2.0 * c);", - " shift_phase(predefined_frame_1, -1.0 * a + -2.0 * c);", - " set_scale(predefined_frame_1, a + 2.0 * c);", - " psb[0] = capture_v0(predefined_frame_1);", - " delay[(a + 2.0 * c) * 1s] predefined_frame_1, predefined_frame_2;", - " delay[(a + 2.0 * c) * 1s] predefined_frame_1;", - " delay[1.0ms] predefined_frame_1;", - " barrier predefined_frame_1, predefined_frame_2;", - " play(predefined_frame_1, gauss_wf);", - " play(predefined_frame_2, drag_gauss_wf);", - " play(predefined_frame_1, constant_wf);", - " play(predefined_frame_2, arb_wf);", - " play(predefined_frame_1, erf_square_wf);", - " psb[1] = capture_v0(predefined_frame_2);", - "}", - ] - ) + expected_str_unbound = "\n".join([ + "OPENQASM 3.0;", + "cal {", + " bit[2] psb;", + *[ + f" input float {parameter};" + for parameter in reversed(list(pulse_sequence.parameters)) + ], + " waveform gauss_wf = gaussian(length_g * 1s, sigma_g * 1s, 1, false);", + " waveform drag_gauss_wf = drag_gaussian(length_dg * 1s, sigma_dg * 1s, 0.2, 1, false);", + " waveform constant_wf = constant(length_c * 1s, 2.0 + 0.3im);", + " waveform arb_wf = {1.0 + 0.4im, 0, 0.3, 0.1 + 0.2im};", + " waveform erf_square_wf = erf_square(length_es * 1s, width_es * 1s, 2.0ns," + " 8.0ns, 1, false);", + " set_frequency(predefined_frame_1, a + 2.0 * c);", + " shift_frequency(predefined_frame_1, a + 2.0 * c);", + " set_phase(predefined_frame_1, a + 2.0 * c);", + " shift_phase(predefined_frame_1, -1.0 * a + -2.0 * c);", + " set_scale(predefined_frame_1, a + 2.0 * c);", + " psb[0] = capture_v0(predefined_frame_1);", + " delay[(a + 2.0 * c) * 1s] predefined_frame_1, predefined_frame_2;", + " delay[(a + 2.0 * c) * 1s] predefined_frame_1;", + " delay[1.0ms] predefined_frame_1;", + " barrier predefined_frame_1, predefined_frame_2;", + " play(predefined_frame_1, gauss_wf);", + " play(predefined_frame_2, drag_gauss_wf);", + " play(predefined_frame_1, constant_wf);", + " play(predefined_frame_2, arb_wf);", + " play(predefined_frame_1, erf_square_wf);", + " psb[1] = capture_v0(predefined_frame_2);", + "}", + ]) assert pulse_sequence.to_ir() == expected_str_unbound assert pulse_sequence.parameters == { FreeParameter("a"), @@ -179,17 +174,15 @@ def test_pulse_sequence_make_bound_pulse_sequence(predefined_frame_1, predefined FreeParameter("width_es"), FreeParameter("length_es"), } - b_bound = pulse_sequence.make_bound_pulse_sequence( - { - "c": 2, - "length_g": 1e-3, - "length_dg": 3e-3, - "sigma_dg": 0.4, - "length_c": 4e-3, - "length_es": 20e-9, - "width_es": 12e-9, - } - ) + b_bound = pulse_sequence.make_bound_pulse_sequence({ + "c": 2, + "length_g": 1e-3, + "length_dg": 3e-3, + "sigma_dg": 0.4, + "length_c": 4e-3, + "length_es": 20e-9, + "width_es": 12e-9, + }) b_bound_call = pulse_sequence( c=2, length_g=1e-3, @@ -199,70 +192,66 @@ def test_pulse_sequence_make_bound_pulse_sequence(predefined_frame_1, predefined length_es=20e-9, width_es=12e-9, ) - expected_str_b_bound = "\n".join( - [ - "OPENQASM 3.0;", - "cal {", - " bit[2] psb;", - *[f" input float {parameter};" for parameter in reversed(list(b_bound.parameters))], - " waveform gauss_wf = gaussian(1.0ms, sigma_g * 1s, 1, false);", - " waveform drag_gauss_wf = drag_gaussian(3.0ms, 400.0ms, 0.2, 1, false);", - " waveform constant_wf = constant(4.0ms, 2.0 + 0.3im);", - " waveform arb_wf = {1.0 + 0.4im, 0, 0.3, 0.1 + 0.2im};", - " waveform erf_square_wf = erf_square(20.0ns, 12.0ns, 2.0ns, 8.0ns, 1, false);", - " set_frequency(predefined_frame_1, a + 4.0);", - " shift_frequency(predefined_frame_1, a + 4.0);", - " set_phase(predefined_frame_1, a + 4.0);", - " shift_phase(predefined_frame_1, -1.0 * a + -4.0);", - " set_scale(predefined_frame_1, a + 4.0);", - " psb[0] = capture_v0(predefined_frame_1);", - " delay[(a + 4.0) * 1s] predefined_frame_1, predefined_frame_2;", - " delay[(a + 4.0) * 1s] predefined_frame_1;", - " delay[1.0ms] predefined_frame_1;", - " barrier predefined_frame_1, predefined_frame_2;", - " play(predefined_frame_1, gauss_wf);", - " play(predefined_frame_2, drag_gauss_wf);", - " play(predefined_frame_1, constant_wf);", - " play(predefined_frame_2, arb_wf);", - " play(predefined_frame_1, erf_square_wf);", - " psb[1] = capture_v0(predefined_frame_2);", - "}", - ] - ) + expected_str_b_bound = "\n".join([ + "OPENQASM 3.0;", + "cal {", + " bit[2] psb;", + *[f" input float {parameter};" for parameter in reversed(list(b_bound.parameters))], + " waveform gauss_wf = gaussian(1.0ms, sigma_g * 1s, 1, false);", + " waveform drag_gauss_wf = drag_gaussian(3.0ms, 400.0ms, 0.2, 1, false);", + " waveform constant_wf = constant(4.0ms, 2.0 + 0.3im);", + " waveform arb_wf = {1.0 + 0.4im, 0, 0.3, 0.1 + 0.2im};", + " waveform erf_square_wf = erf_square(20.0ns, 12.0ns, 2.0ns, 8.0ns, 1, false);", + " set_frequency(predefined_frame_1, a + 4.0);", + " shift_frequency(predefined_frame_1, a + 4.0);", + " set_phase(predefined_frame_1, a + 4.0);", + " shift_phase(predefined_frame_1, -1.0 * a + -4.0);", + " set_scale(predefined_frame_1, a + 4.0);", + " psb[0] = capture_v0(predefined_frame_1);", + " delay[(a + 4.0) * 1s] predefined_frame_1, predefined_frame_2;", + " delay[(a + 4.0) * 1s] predefined_frame_1;", + " delay[1.0ms] predefined_frame_1;", + " barrier predefined_frame_1, predefined_frame_2;", + " play(predefined_frame_1, gauss_wf);", + " play(predefined_frame_2, drag_gauss_wf);", + " play(predefined_frame_1, constant_wf);", + " play(predefined_frame_2, arb_wf);", + " play(predefined_frame_1, erf_square_wf);", + " psb[1] = capture_v0(predefined_frame_2);", + "}", + ]) assert b_bound.to_ir() == b_bound_call.to_ir() == expected_str_b_bound assert pulse_sequence.to_ir() == expected_str_unbound assert b_bound.parameters == {FreeParameter("sigma_g"), FreeParameter("a")} both_bound = b_bound.make_bound_pulse_sequence({"a": 1, "sigma_g": 0.7}) both_bound_call = b_bound_call(1, sigma_g=0.7) # use arg 1 for a - expected_str_both_bound = "\n".join( - [ - "OPENQASM 3.0;", - "cal {", - " bit[2] psb;", - " waveform gauss_wf = gaussian(1.0ms, 700.0ms, 1, false);", - " waveform drag_gauss_wf = drag_gaussian(3.0ms, 400.0ms, 0.2, 1, false);", - " waveform constant_wf = constant(4.0ms, 2.0 + 0.3im);", - " waveform arb_wf = {1.0 + 0.4im, 0, 0.3, 0.1 + 0.2im};", - " waveform erf_square_wf = erf_square(20.0ns, 12.0ns, 2.0ns, 8.0ns, 1, false);", - " set_frequency(predefined_frame_1, 5.0);", - " shift_frequency(predefined_frame_1, 5.0);", - " set_phase(predefined_frame_1, 5.0);", - " shift_phase(predefined_frame_1, -5.0);", - " set_scale(predefined_frame_1, 5.0);", - " psb[0] = capture_v0(predefined_frame_1);", - " delay[5.0s] predefined_frame_1, predefined_frame_2;", - " delay[5.0s] predefined_frame_1;", - " delay[1.0ms] predefined_frame_1;", - " barrier predefined_frame_1, predefined_frame_2;", - " play(predefined_frame_1, gauss_wf);", - " play(predefined_frame_2, drag_gauss_wf);", - " play(predefined_frame_1, constant_wf);", - " play(predefined_frame_2, arb_wf);", - " play(predefined_frame_1, erf_square_wf);", - " psb[1] = capture_v0(predefined_frame_2);", - "}", - ] - ) + expected_str_both_bound = "\n".join([ + "OPENQASM 3.0;", + "cal {", + " bit[2] psb;", + " waveform gauss_wf = gaussian(1.0ms, 700.0ms, 1, false);", + " waveform drag_gauss_wf = drag_gaussian(3.0ms, 400.0ms, 0.2, 1, false);", + " waveform constant_wf = constant(4.0ms, 2.0 + 0.3im);", + " waveform arb_wf = {1.0 + 0.4im, 0, 0.3, 0.1 + 0.2im};", + " waveform erf_square_wf = erf_square(20.0ns, 12.0ns, 2.0ns, 8.0ns, 1, false);", + " set_frequency(predefined_frame_1, 5.0);", + " shift_frequency(predefined_frame_1, 5.0);", + " set_phase(predefined_frame_1, 5.0);", + " shift_phase(predefined_frame_1, -5.0);", + " set_scale(predefined_frame_1, 5.0);", + " psb[0] = capture_v0(predefined_frame_1);", + " delay[5.0s] predefined_frame_1, predefined_frame_2;", + " delay[5.0s] predefined_frame_1;", + " delay[1.0ms] predefined_frame_1;", + " barrier predefined_frame_1, predefined_frame_2;", + " play(predefined_frame_1, gauss_wf);", + " play(predefined_frame_2, drag_gauss_wf);", + " play(predefined_frame_1, constant_wf);", + " play(predefined_frame_2, arb_wf);", + " play(predefined_frame_1, erf_square_wf);", + " psb[1] = capture_v0(predefined_frame_2);", + "}", + ]) assert both_bound.to_ir() == both_bound_call.to_ir() == expected_str_both_bound assert b_bound.to_ir() == b_bound_call.to_ir() == expected_str_b_bound assert pulse_sequence.to_ir() == expected_str_unbound @@ -350,36 +339,34 @@ def test_pulse_sequence_to_ir(predefined_frame_1, predefined_frame_2): ) .capture_v0(predefined_frame_2) ) - expected_str = "\n".join( - [ - "OPENQASM 3.0;", - "cal {", - " bit[2] psb;", - " waveform gauss_wf = gaussian(1.0ms, 700.0ms, 1, false);", - " waveform drag_gauss_wf = drag_gaussian(3.0ms, 400.0ms, 0.2, 1, false);", - " waveform constant_wf = constant(4.0ms, 2.0 + 0.3im);", - " waveform arb_wf = {1.0 + 0.4im, 0, 0.3, 0.1 + 0.2im};", - " waveform erf_square_wf = erf_square(32.0ns, 20.0ns, 2.0ns, 8.0ns, 1, false);", - " set_frequency(predefined_frame_1, 3000000000.0);", - " shift_frequency(predefined_frame_1, 1000000000.0);", - " set_phase(predefined_frame_1, -0.5);", - " shift_phase(predefined_frame_1, 0.1);", - " set_scale(predefined_frame_1, 0.25);", - " psb[0] = capture_v0(predefined_frame_1);", - " delay[2.0ns] predefined_frame_1, predefined_frame_2;", - " delay[1.0us] predefined_frame_1;", - " delay[1.0ms] $0;", - " barrier $0, $1;", - " barrier predefined_frame_1, predefined_frame_2;", - " play(predefined_frame_1, gauss_wf);", - " play(predefined_frame_2, drag_gauss_wf);", - " play(predefined_frame_1, constant_wf);", - " play(predefined_frame_2, arb_wf);", - " play(predefined_frame_1, erf_square_wf);", - " psb[1] = capture_v0(predefined_frame_2);", - "}", - ] - ) + expected_str = "\n".join([ + "OPENQASM 3.0;", + "cal {", + " bit[2] psb;", + " waveform gauss_wf = gaussian(1.0ms, 700.0ms, 1, false);", + " waveform drag_gauss_wf = drag_gaussian(3.0ms, 400.0ms, 0.2, 1, false);", + " waveform constant_wf = constant(4.0ms, 2.0 + 0.3im);", + " waveform arb_wf = {1.0 + 0.4im, 0, 0.3, 0.1 + 0.2im};", + " waveform erf_square_wf = erf_square(32.0ns, 20.0ns, 2.0ns, 8.0ns, 1, false);", + " set_frequency(predefined_frame_1, 3000000000.0);", + " shift_frequency(predefined_frame_1, 1000000000.0);", + " set_phase(predefined_frame_1, -0.5);", + " shift_phase(predefined_frame_1, 0.1);", + " set_scale(predefined_frame_1, 0.25);", + " psb[0] = capture_v0(predefined_frame_1);", + " delay[2.0ns] predefined_frame_1, predefined_frame_2;", + " delay[1.0us] predefined_frame_1;", + " delay[1.0ms] $0;", + " barrier $0, $1;", + " barrier predefined_frame_1, predefined_frame_2;", + " play(predefined_frame_1, gauss_wf);", + " play(predefined_frame_2, drag_gauss_wf);", + " play(predefined_frame_1, constant_wf);", + " play(predefined_frame_2, arb_wf);", + " play(predefined_frame_1, erf_square_wf);", + " psb[1] = capture_v0(predefined_frame_2);", + "}", + ]) assert pulse_sequence.to_ir() == expected_str diff --git a/test/unit_tests/braket/quantum_information/test_pauli_string.py b/test/unit_tests/braket/quantum_information/test_pauli_string.py index c3959d305..9d5f7e5bb 100644 --- a/test/unit_tests/braket/quantum_information/test_pauli_string.py +++ b/test/unit_tests/braket/quantum_information/test_pauli_string.py @@ -225,7 +225,7 @@ def test_power(circ, n, circ_res): assert circ1 == PauliString(circ_res) -@pytest.mark.xfail(raises=ValueError) +@pytest.mark.xfail(raises=TypeError) @pytest.mark.parametrize( "circ, n, operation", [ diff --git a/test/unit_tests/braket/tasks/test_gate_model_quantum_task_result.py b/test/unit_tests/braket/tasks/test_gate_model_quantum_task_result.py index 99ab7e345..1cac97e26 100644 --- a/test/unit_tests/braket/tasks/test_gate_model_quantum_task_result.py +++ b/test/unit_tests/braket/tasks/test_gate_model_quantum_task_result.py @@ -366,9 +366,14 @@ def test_get_compiled_circuit_no_metadata(result_obj_1): def test_measurement_counts_from_measurements(): - measurements: np.ndarray = np.array( - [[1, 0, 1, 0], [0, 0, 0, 0], [1, 0, 1, 0], [1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 1, 0]] - ) + measurements: np.ndarray = np.array([ + [1, 0, 1, 0], + [0, 0, 0, 0], + [1, 0, 1, 0], + [1, 0, 0, 0], + [1, 0, 0, 0], + [1, 0, 1, 0], + ]) measurement_counts = GateModelQuantumTaskResult.measurement_counts_from_measurements( measurements ) @@ -509,20 +514,18 @@ def test_calculate_ir_results(ir_result, expected_result): instructions=[jaqcd.H(target=i) for i in range(4)], results=[ir_result] ).json() measured_qubits = [0, 1, 2, 3] - measurements = np.array( - [ - [0, 0, 1, 0], - [1, 1, 1, 1], - [1, 0, 0, 1], - [0, 0, 1, 0], - [1, 1, 1, 1], - [0, 1, 1, 1], - [0, 0, 0, 1], - [0, 1, 1, 1], - [0, 0, 0, 0], - [0, 0, 0, 1], - ] - ) + measurements = np.array([ + [0, 0, 1, 0], + [1, 1, 1, 1], + [1, 0, 0, 1], + [0, 0, 1, 0], + [1, 1, 1, 1], + [0, 1, 1, 1], + [0, 0, 0, 1], + [0, 1, 1, 1], + [0, 0, 0, 0], + [0, 0, 0, 1], + ]) result_types = GateModelQuantumTaskResult._calculate_result_types( ir_string, measurements, measured_qubits ) @@ -588,56 +591,54 @@ def test_hash_result_types(observable_1, observable_2): "braket.tasks.gate_model_quantum_task_result.GateModelQuantumTaskResult._calculate_result_types" ) def test_result_type_skips_computation_already_populated(calculate_result_types_mocked): - result_str = json.dumps( - { - "braketSchemaHeader": { - "name": "braket.task_result.gate_model_task_result", - "version": "1", - }, - "measurements": [[0]], - "resultTypes": [ - {"type": {"observable": ["z"], "targets": [0], "type": "variance"}, "value": 12.0} - ], - "measuredQubits": [0], - "taskMetadata": { - "braketSchemaHeader": {"name": "braket.task_result.task_metadata", "version": "1"}, - "id": "arn:aws:braket:us-east-1:1234567890:quantum-task/22a238b2-ae96", - "shots": 1, - "deviceId": "arn:aws:braket:::device/quantum-simulator/amazon/dm1", - "deviceParameters": { + result_str = json.dumps({ + "braketSchemaHeader": { + "name": "braket.task_result.gate_model_task_result", + "version": "1", + }, + "measurements": [[0]], + "resultTypes": [ + {"type": {"observable": ["z"], "targets": [0], "type": "variance"}, "value": 12.0} + ], + "measuredQubits": [0], + "taskMetadata": { + "braketSchemaHeader": {"name": "braket.task_result.task_metadata", "version": "1"}, + "id": "arn:aws:braket:us-east-1:1234567890:quantum-task/22a238b2-ae96", + "shots": 1, + "deviceId": "arn:aws:braket:::device/quantum-simulator/amazon/dm1", + "deviceParameters": { + "braketSchemaHeader": { + "name": "braket.device_schema.simulators." + "gate_model_simulator_device_parameters", + "version": "1", + }, + "paradigmParameters": { "braketSchemaHeader": { - "name": "braket.device_schema.simulators." - "gate_model_simulator_device_parameters", + "name": "braket.device_schema.gate_model_parameters", "version": "1", }, - "paradigmParameters": { - "braketSchemaHeader": { - "name": "braket.device_schema.gate_model_parameters", - "version": "1", - }, - "qubitCount": 1, - "disableQubitRewiring": False, - }, + "qubitCount": 1, + "disableQubitRewiring": False, }, - "createdAt": "2022-01-12T06:05:22.633Z", - "endedAt": "2022-01-12T06:05:24.136Z", - "status": "COMPLETED", }, - "additionalMetadata": { - "action": { - "braketSchemaHeader": {"name": "braket.ir.openqasm.program", "version": "1"}, - "source": "\nqubit[1] q;\nh q[0];\n#pragma braket result variance z(q[0])\n", - }, - "simulatorMetadata": { - "braketSchemaHeader": { - "name": "braket.task_result.simulator_metadata", - "version": "1", - }, - "executionDuration": 16, + "createdAt": "2022-01-12T06:05:22.633Z", + "endedAt": "2022-01-12T06:05:24.136Z", + "status": "COMPLETED", + }, + "additionalMetadata": { + "action": { + "braketSchemaHeader": {"name": "braket.ir.openqasm.program", "version": "1"}, + "source": "\nqubit[1] q;\nh q[0];\n#pragma braket result variance z(q[0])\n", + }, + "simulatorMetadata": { + "braketSchemaHeader": { + "name": "braket.task_result.simulator_metadata", + "version": "1", }, + "executionDuration": 16, }, - } - ) + }, + }) res = GateModelQuantumTaskResult.from_string(result_str) assert ( res.get_value_by_result_type(ResultType.Variance(observable=Observable.Z(), target=[0])) diff --git a/test/unit_tests/braket/tasks/test_local_quantum_task_batch.py b/test/unit_tests/braket/tasks/test_local_quantum_task_batch.py index 3c7c523bb..345561bfc 100644 --- a/test/unit_tests/braket/tasks/test_local_quantum_task_batch.py +++ b/test/unit_tests/braket/tasks/test_local_quantum_task_batch.py @@ -21,9 +21,11 @@ RESULTS = [ GateModelQuantumTaskResult( - task_metadata=TaskMetadata( - **{"id": str(uuid.uuid4()), "deviceId": "default", "shots": 100} - ), + task_metadata=TaskMetadata(**{ + "id": str(uuid.uuid4()), + "deviceId": "default", + "shots": 100, + }), additional_metadata=None, measurements=np.array([[0, 1], [1, 0]]), measured_qubits=[0, 1], diff --git a/tox.ini b/tox.ini index f8da75234..d11118271 100644 --- a/tox.ini +++ b/tox.ini @@ -38,28 +38,23 @@ extras = test [testenv:linters] basepython = python3 skip_install = true +# Remove this to check what versions are installed for the env. This stops running pip freeze. +list_dependencies_command = echo deps = - {[testenv:isort]deps} - {[testenv:black]deps} - {[testenv:flake8]deps} + {[testenv:ruff-format]deps} + {[testenv:ruff-check]deps} commands = - # isort MUST come before black as it will revert any changes made by black - {[testenv:isort]commands} - {[testenv:black]commands} - {[testenv:flake8]commands} + {[testenv:ruff-format]commands} + {[testenv:ruff-check]commands} # Read only linter env [testenv:linters_check] basepython = python3 skip_install = true deps = - {[testenv:isort_check]deps} - {[testenv:black_check]deps} - {[testenv:flake8]deps} + {[testenv:ruff-check]deps} commands = - {[testenv:isort_check]commands} - {[testenv:black_check]commands} - {[testenv:flake8]commands} + {[testenv:ruff-check]commands} [testenv:flake8] basepython = python3 @@ -103,6 +98,23 @@ deps = commands = black --check ./ {posargs} + +[testenv:ruff-check] +basepython = python3 +skip_install = true +deps = + ruff +commands = + ruff check src {posargs} + +[testenv:ruff-format] +basepython = python3 +skip_install = true +deps = + ruff +commands = + ruff format . {posargs} + [testenv:docs] basepython = python3 deps =