From c8c6773786bf0511280843339abd0edce427ccdc Mon Sep 17 00:00:00 2001 From: Lishuai Xu <36893822+steven09200808@users.noreply.github.com> Date: Mon, 31 Oct 2022 08:06:18 -0700 Subject: [PATCH] feature: support new device schema quera and new ir schema ahs (#112) --- .../device_schema/device_action_properties.py | 1 + src/braket/device_schema/quera/__init__.py | 19 ++ .../quera/quera_ahs_paradigm_properties_v1.py | 234 ++++++++++++++++++ .../quera/quera_device_capabilities_v1.py | 77 ++++++ src/braket/ir/ahs/__init__.py | 20 ++ src/braket/ir/ahs/atom_arrangement.py | 42 ++++ src/braket/ir/ahs/driving_field.py | 49 ++++ src/braket/ir/ahs/hamiltonian.py | 37 +++ src/braket/ir/ahs/physical_field.py | 36 +++ src/braket/ir/ahs/program_v1.py | 56 +++++ src/braket/ir/ahs/shifting_field.py | 42 ++++ src/braket/ir/ahs/time_series.py | 33 +++ src/braket/task_result/__init__.py | 7 + src/braket/task_result/additional_metadata.py | 5 +- ...g_hamiltonian_simulation_task_result_v1.py | 87 +++++++ src/braket/task_result/quera_metadata_v1.py | 39 +++ .../test_quera_ahs_paradigm_properties_v1.py | 177 +++++++++++++ .../test_quera_device_capabilities_v1.py | 153 ++++++++++++ .../braket/ir/ahs/test_ahs_program_v1.py | 109 ++++++++ .../braket/ir/ahs/test_atom_arrangement.py | 49 ++++ .../braket/ir/ahs/test_driving_field.py | 43 ++++ .../braket/ir/ahs/test_hamiltonian.py | 42 ++++ .../braket/ir/ahs/test_physical_field.py | 56 +++++ .../braket/ir/ahs/test_shifting_field.py | 29 +++ .../braket/ir/ahs/test_time_series.py | 42 ++++ .../unit_tests/braket/task_result/conftest.py | 63 +++++ .../task_result/test_additional_metadata.py | 6 + ...g_hamiltonian_simulation_task_result_v1.py | 155 ++++++++++++ 28 files changed, 1707 insertions(+), 1 deletion(-) create mode 100644 src/braket/device_schema/quera/__init__.py create mode 100644 src/braket/device_schema/quera/quera_ahs_paradigm_properties_v1.py create mode 100644 src/braket/device_schema/quera/quera_device_capabilities_v1.py create mode 100644 src/braket/ir/ahs/__init__.py create mode 100644 src/braket/ir/ahs/atom_arrangement.py create mode 100644 src/braket/ir/ahs/driving_field.py create mode 100644 src/braket/ir/ahs/hamiltonian.py create mode 100644 src/braket/ir/ahs/physical_field.py create mode 100644 src/braket/ir/ahs/program_v1.py create mode 100644 src/braket/ir/ahs/shifting_field.py create mode 100644 src/braket/ir/ahs/time_series.py create mode 100644 src/braket/task_result/analog_hamiltonian_simulation_task_result_v1.py create mode 100644 src/braket/task_result/quera_metadata_v1.py create mode 100644 test/unit_tests/braket/device_schema/quera/test_quera_ahs_paradigm_properties_v1.py create mode 100644 test/unit_tests/braket/device_schema/quera/test_quera_device_capabilities_v1.py create mode 100644 test/unit_tests/braket/ir/ahs/test_ahs_program_v1.py create mode 100644 test/unit_tests/braket/ir/ahs/test_atom_arrangement.py create mode 100644 test/unit_tests/braket/ir/ahs/test_driving_field.py create mode 100644 test/unit_tests/braket/ir/ahs/test_hamiltonian.py create mode 100644 test/unit_tests/braket/ir/ahs/test_physical_field.py create mode 100644 test/unit_tests/braket/ir/ahs/test_shifting_field.py create mode 100644 test/unit_tests/braket/ir/ahs/test_time_series.py create mode 100644 test/unit_tests/braket/task_result/test_analog_hamiltonian_simulation_task_result_v1.py diff --git a/src/braket/device_schema/device_action_properties.py b/src/braket/device_schema/device_action_properties.py index fb60b95d..93180aaa 100644 --- a/src/braket/device_schema/device_action_properties.py +++ b/src/braket/device_schema/device_action_properties.py @@ -26,6 +26,7 @@ class DeviceActionType(str, Enum): JAQCD = "braket.ir.jaqcd.program" BLACKBIRD = "braket.ir.blackbird.program" ANNEALING = "braket.ir.annealing.problem" + AHS = "braket.ir.ahs.program" class DeviceActionProperties(BaseModel): diff --git a/src/braket/device_schema/quera/__init__.py b/src/braket/device_schema/quera/__init__.py new file mode 100644 index 00000000..502861d9 --- /dev/null +++ b/src/braket/device_schema/quera/__init__.py @@ -0,0 +1,19 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# 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 braket.device_schema.quera.quera_ahs_paradigm_properties_v1 import ( # noqa: F401, E501 + QueraAhsParadigmProperties, +) +from braket.device_schema.quera.quera_device_capabilities_v1 import ( # noqa: F401 + QueraDeviceCapabilities, +) diff --git a/src/braket/device_schema/quera/quera_ahs_paradigm_properties_v1.py b/src/braket/device_schema/quera/quera_ahs_paradigm_properties_v1.py new file mode 100644 index 00000000..3dae84ef --- /dev/null +++ b/src/braket/device_schema/quera/quera_ahs_paradigm_properties_v1.py @@ -0,0 +1,234 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# 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 decimal import Decimal +from typing import Tuple + +from pydantic import BaseModel, Field + +from braket.schema_common import BraketSchemaBase, BraketSchemaHeader + + +class Area(BaseModel): + """ + The area of the FOV + Attributes: + width (Decimal): Largest allowed difference between x + coordinates of any two sites (measured in meters) + height (Decimal): Largest allowed difference between y + coordinates of any two sites (measured in meters) + """ + + width: Decimal + height: Decimal + + +class Geometry(BaseModel): + """ + Spacing or number of sites or rows + Attributes: + spacingRadialMin (Decimal): Minimum radial spacing between any + two sites in the lattice (measured in meters) + spacingVerticalMin (Decimal): Minimum spacing between any two + rows in the lattice (measured in meters) + positionResolution (Decimal): Resolution with which site positions + can be specified (measured in meters) + numberSitesMax (int): Maximum number of sites that can be placed + in the lattice + """ + + spacingRadialMin: Decimal + spacingVerticalMin: Decimal + positionResolution: Decimal + numberSitesMax: int + + +class Lattice(BaseModel): + """ + Spacing or number of sites or rows + Attributes: + area : The rectangular area available for arranging atomic sites + geometry : Limitations of atomic site arrangements + """ + + area: Area + geometry: Geometry + + +class RydbergGlobal(BaseModel): + """ + Parameters determining the limitations on the driving field that drives the + ground-to-Rydberg transition uniformly on all atoms + Attributes: + rabiFrequencyRange (Tuple[Decimal,Decimal]): Achievable Rabi frequency + range for the global Rydberg drive waveform (measured in rad/s) + rabiFrequencyResolution (Decimal): Resolution with which global Rabi + frequency amplitude can be specified (measured in rad/s) + rabiFrequencySlewRateMax (Decimal): Maximum slew rate for changing the + global Rabi frequency (measured in (rad/s)/s) + detuningRange(Tuple[Decimal,Decimal]): Achievable detuning range for + the global Rydberg pulse (measured in rad/s) + detuningResolution(Decimal): Resolution with which global detuning can + be specified (measured in rad/s) + detuningSlewRateMax (Decimal): Maximum slew rate for detuning (measured in (rad/s)/s) + phaseRange(Tuple[Decimal,Decimal]): Achievable phase range for the global + Rydberg pulse (measured in rad) + phaseResolution(Decimal): Resolution with which global Rabi frequency phase + can be specified (measured in rad) + timeResolution(Decimal): Resolution with which times for global Rydberg drive + parameters can be specified (measured in s) + timeDeltaMin(Decimal): Minimum time step with which times for global Rydberg + drive parameters can be specified (measured in s) + timeMin (Decimal): Minimum duration of Rydberg drive (measured in s) + timeMax (Decimal): Maximum duration of Rydberg drive (measured in s) + """ + + rabiFrequencyRange: Tuple[Decimal, Decimal] + rabiFrequencyResolution: Decimal + rabiFrequencySlewRateMax: Decimal + detuningRange: Tuple[Decimal, Decimal] + detuningResolution: Decimal + detuningSlewRateMax: Decimal + phaseRange: Tuple[Decimal, Decimal] + phaseResolution: Decimal + timeResolution: Decimal + timeDeltaMin: Decimal + timeMin: Decimal + timeMax: Decimal + + +class Rydberg(BaseModel): + """ + Parameters determining the limitations of the Rydberg Hamiltonian + Attributes: + c6Coefficient (Decimal): Rydberg-Rydberg C6 interaction + coefficient (measured in (rad/s)*m^6) + rydbergGlobal: Rydberg Global + """ + + c6Coefficient: Decimal + rydbergGlobal: RydbergGlobal + + +class PerformanceLattice(BaseModel): + """ + Uncertainties of atomic site arrangements + Attributes: + positionErrorAbs (Decimal): Error between target and actual site + position (measured in meters) + """ + + positionErrorAbs: Decimal + + +class PerformanceRydbergGlobal(BaseModel): + """ + Parameters determining the limitations of the global driving field + Attributes: + rabiFrequencyErrorRel (Decimal): random error in the Rabi frequency, relative (unitless) + """ + + rabiFrequencyErrorRel: Decimal + + +class PerformanceRydberg(BaseModel): + """ + Parameters determining the limitations the Rydberg simulator + Attributes: + rydbergGlobal: Performance of Rydberg Global + """ + + rydbergGlobal: PerformanceRydbergGlobal + + +class Performance(BaseModel): + """ + Parameters determining the limitations of the QuEra device + Attributes: + performanceLattice: Uncertainties of atomic site arrangements + performanceRydberg : Parameters determining the limitations the Rydberg simulator + """ + + lattice: PerformanceLattice + rydberg: PerformanceRydberg + + +class QueraAhsParadigmProperties(BraketSchemaBase): + """ + This defines the properties common to ahs Quera devices. + + Attributes: + area: the area of the FOV + geometry: spacing or number of sites or rows + qubits: the number of qubits + rydberg: the constraint of rydberg + performance: the performance of rydberg or atom detection + Examples: + >>> import json + >>> input_json = { + ... "braketSchemaHeader": { + ... "name": "braket.device_schema.quera.quera_ahs_paradigm_properties", + ... "version": "1", + ... }, + ... "qubitCount": 256, + ... "lattice":{ + ... "area": { + ... "width": 100.0e-6, + ... "height": 100.0e-6, + ... }, + ... "geometry": { + ... "spacingRadialMin": 4.0e-6, + ... "spacingVerticalMin": 2.5e-6, + ... "positionResolution": 1e-7, + ... "numberSitesMax": 256, + ... } + ... }, + ... "rydberg": { + ... "c6Coefficient": 2*math.pi(3.14) *862690, + ... "rydbergGlobal": { + ... "rabiFrequencyRange": [0, 2*math.pi(3.14) *4.0e6], + ... "rabiFrequencyResolution": 400 + ... "rabiFrequencySlewRateMax": 2*math.pi(3.14) *4e6/100e-9, + ... "detuningRange": [-2*math.pi(3.14) *20.0e6,2*math.pi(3.14) *20.0e6], + ... "detuningResolution": 0.2, + ... "detuningSlewRateMax": 2*math.pi(3.14) *40.0e6/100e-9, + ... "phaseRange": [-99,99], + ... "phaseResolution": 5e-7, + ... "timeResolution": 1e-9, + ... "timeDeltaMin": 1e-8, + ... "timeMin": 0, + ... "timeMax": 4.0e-6, + ... }, + ... }, + ... "performance": { + ... "lattice":{ + ... "positionErrorAbs": 0.025e-6, + ... }, + ... "performanceRydberg":{ + ... "performanceRydbergGlobal":{ + ... "rabiFrequencyErrorRel:": 0.01, + ... }, + ... }, + ... }, + ... } + >>> QueraAhsParadigmProperties.parse_raw_schema(json.dumps(input_json)) + """ + + _PROGRAM_HEADER = BraketSchemaHeader( + name="braket.device_schema.quera.quera_ahs_paradigm_properties", version="1" + ) + braketSchemaHeader: BraketSchemaHeader = Field(default=_PROGRAM_HEADER, const=_PROGRAM_HEADER) + qubitCount: int + lattice: Lattice + rydberg: Rydberg + performance: Performance diff --git a/src/braket/device_schema/quera/quera_device_capabilities_v1.py b/src/braket/device_schema/quera/quera_device_capabilities_v1.py new file mode 100644 index 00000000..3251e92d --- /dev/null +++ b/src/braket/device_schema/quera/quera_device_capabilities_v1.py @@ -0,0 +1,77 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# 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 pydantic import Field + +from braket.device_schema.device_capabilities import DeviceCapabilities +from braket.device_schema.quera.quera_ahs_paradigm_properties_v1 import QueraAhsParadigmProperties +from braket.schema_common import BraketSchemaBase, BraketSchemaHeader + + +class QueraDeviceCapabilities(BraketSchemaBase, DeviceCapabilities): + """ + This defines the capabilities of a Quera device. + + Attributes: + provider: Properties specific to Quera provider + + Examples: + >>> import json + >>> input_json = { + ... "braketSchemaHeader": { + ... "name": "braket.device_schema.quera.quera_device_capabilities", + ... "version": "1", + ... }, + ... "service": { + ... "braketSchemaHeader": { + ... "name": "braket.device_schema.device_service_properties", + ... "version": "1", + ... }, + ... "executionWindows": [ + ... { + ... "executionDay": "Everyday", + ... "windowStartHour": "09:00", + ... "windowEndHour": "10:00", + ... } + ... ], + ... "shotsRange": [1, 100000], + ... "deviceCost": { + ... "price": 0.25, + ... "unit": "minute" + ... }, + ... "deviceDocumentation": { + ... "imageUrl": "image_url", + ... "summary": "Summary on the device", + ... "externalDocumentationUrl": "external doc link", + ... }, + ... "deviceLocation": "us-east-1", + ... "updatedAt": "2022-05-15T19:28:02.869136" + ... }, + ... "action": { + ... "braket.ir.ahs.program": { + ... "actionType": "braket.ir.ahs.program", + ... "version": ["1"], + ... } + ... }, + ... "paradigm": {QueraAhsParadigmProperties.schema_json()}, + ... "deviceParameters": "" + ... } + >>> QueraDeviceCapabilities.parse_raw_schema(json.dumps(input_json)) + """ + + _PROGRAM_HEADER = BraketSchemaHeader( + name="braket.device_schema.quera.quera_device_capabilities", version="1" + ) + braketSchemaHeader: BraketSchemaHeader = Field(default=_PROGRAM_HEADER, const=_PROGRAM_HEADER) + paradigm: QueraAhsParadigmProperties diff --git a/src/braket/ir/ahs/__init__.py b/src/braket/ir/ahs/__init__.py new file mode 100644 index 00000000..d35dc428 --- /dev/null +++ b/src/braket/ir/ahs/__init__.py @@ -0,0 +1,20 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# 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 braket.ir.ahs.atom_arrangement import AtomArrangement # noqa: F401 +from braket.ir.ahs.driving_field import DrivingField # noqa: F401 +from braket.ir.ahs.hamiltonian import Hamiltonian # noqa: F401 +from braket.ir.ahs.physical_field import PhysicalField # noqa: F401 +from braket.ir.ahs.program_v1 import Program, Setup # noqa: F401 +from braket.ir.ahs.shifting_field import ShiftingField # noqa: F401 +from braket.ir.ahs.time_series import TimeSeries # noqa: F401 diff --git a/src/braket/ir/ahs/atom_arrangement.py b/src/braket/ir/ahs/atom_arrangement.py new file mode 100644 index 00000000..925a1b5e --- /dev/null +++ b/src/braket/ir/ahs/atom_arrangement.py @@ -0,0 +1,42 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# 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 decimal import Decimal +from typing import List + +from pydantic import BaseModel + + +class AtomArrangement(BaseModel): + """ + Specifies the atom array + + Attributes: + sites: List of 2-d coordinates where the tweezers trap atoms + filling: Marks atoms that occupy the trap sites with 1, and empty sites with 0 + + + Examples: + >>> AtomArrangement(sites=[ + ... [0.0, 0.0], + ... [0.0, 3.0e-6], + ... [0.0, 6.0e-6], + ... [3.0e-6, 0.0], + ... [3.0e-6, 3.0e-6], + ... [3.0e-6, 6.0e-6] + ... ], + ... filling=[1,1,1,1,0,0]) + """ + + sites: List[List[Decimal]] + filling: List[int] diff --git a/src/braket/ir/ahs/driving_field.py b/src/braket/ir/ahs/driving_field.py new file mode 100644 index 00000000..54cab421 --- /dev/null +++ b/src/braket/ir/ahs/driving_field.py @@ -0,0 +1,49 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# 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 pydantic import BaseModel + +from braket.ir.ahs.physical_field import PhysicalField + + +class DrivingField(BaseModel): + r"""Specifies the driving field, defined by the formula + + .. math:: + H_{drive} (t) := \frac{\Omega(t)}{2} e^{i \phi(t)} \left( + \sum_k |g_k \rangle \langle r_k| + |r_k \rangle \langle g_k| + \right) - \Delta(t) \sum_k{| r_k \rangle \langle r_k |} + + where + + :math:`\Omega(t)` is the global Rabi frequency in rad/s, + + :math:`\phi(t)` is the global phase in rad/s, + + :math:`\Delta(t)` is the global detuning in rad/s, + + :math:`|g_k \rangle` is the ground state of atom k, + + :math:`|r_k \rangle` is the Rydberg state of atom k. + + with the sum :math:`\sum_k` taken over all target atoms. + + Attributes: + amplitude: PhysicalField(pattern=“uniform”) + phase: PhysicalField(pattern=“uniform”) + detuning: PhysicalField(pattern=“uniform”) + """ + + amplitude: PhysicalField + phase: PhysicalField + detuning: PhysicalField diff --git a/src/braket/ir/ahs/hamiltonian.py b/src/braket/ir/ahs/hamiltonian.py new file mode 100644 index 00000000..de8617f4 --- /dev/null +++ b/src/braket/ir/ahs/hamiltonian.py @@ -0,0 +1,37 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# 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 typing import List + +from pydantic import BaseModel + +from braket.ir.ahs.driving_field import DrivingField +from braket.ir.ahs.shifting_field import ShiftingField + + +class Hamiltonian(BaseModel): + """ + Specifies the Hamiltonian + + Attributes: + driving_fileds: An externally controlled force + that drives coherent transitions between selected levels of certain atom types + shifting_fields: An externally controlled polarizing force + the effect of which is accurately described by a frequency shift of certain levels. + + Examples: + >>> Hamiltonian(driving_fields=[DrivingField],shifting_fields=[ShiftingField]) + """ + + drivingFields: List[DrivingField] + shiftingFields: List[ShiftingField] diff --git a/src/braket/ir/ahs/physical_field.py b/src/braket/ir/ahs/physical_field.py new file mode 100644 index 00000000..03e09914 --- /dev/null +++ b/src/braket/ir/ahs/physical_field.py @@ -0,0 +1,36 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# 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 decimal import Decimal +from typing import List, Union + +from pydantic import BaseModel + +from braket.ir.ahs.time_series import TimeSeries + + +class PhysicalField(BaseModel): + """ + Represents the temporal and spatial dependence of a control parameter affecting the atoms + + Attributes: + time_series: TimeSeries + pattern: Values refer to the pattern at the positions setup.atom_array.sites + + Examples: + >>> PhysicalField(time_series=TimeSeries,pattern='uniform') + >>> PhysicalField(time_series=TimeSeries,pattern=[0.5, 1.0, 0.5, 0.5, 0.5, 0.5]) + """ + + time_series: TimeSeries + pattern: Union[str, List[Decimal]] diff --git a/src/braket/ir/ahs/program_v1.py b/src/braket/ir/ahs/program_v1.py new file mode 100644 index 00000000..e7f0d271 --- /dev/null +++ b/src/braket/ir/ahs/program_v1.py @@ -0,0 +1,56 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# 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 decimal import Decimal + +from pydantic import BaseModel, Field + +from braket.ir.ahs.atom_arrangement import AtomArrangement +from braket.ir.ahs.hamiltonian import Hamiltonian +from braket.schema_common import BraketSchemaBase, BraketSchemaHeader + + +class Setup(BaseModel): + """ + The initial setup of the quantum register + Attributes: + ahs_register: The spatial setup of the neutral atom program + """ + + ahs_register: AtomArrangement + + +class Program(BraketSchemaBase): + """Specifies an AHS program + + Attributes: + braketSchemaHeader (BraketSchemaHeader): Schema header. Users do not need + to set this value. Only default is allowed + setup: Neutral atom lattice set up + hamiltonian: rydberg hamiltonian + + Examples: + >>> Program( + ... setup={"ahs_register":AtomArrangement}, + ... hamiltonian={"drivingFields":DrivingField,"shiftingFields":ShiftingField} + ... ) + """ + + _PROGRAM_HEADER = BraketSchemaHeader(name="braket.ir.ahs.program", version="1") + braketSchemaHeader: BraketSchemaHeader = Field(default=_PROGRAM_HEADER, const=_PROGRAM_HEADER) + setup: Setup + hamiltonian: Hamiltonian + + class Config: + json_encoders = {Decimal: str} diff --git a/src/braket/ir/ahs/shifting_field.py b/src/braket/ir/ahs/shifting_field.py new file mode 100644 index 00000000..064cafb8 --- /dev/null +++ b/src/braket/ir/ahs/shifting_field.py @@ -0,0 +1,42 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# 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 pydantic import BaseModel + +from braket.ir.ahs.physical_field import PhysicalField + + +class ShiftingField(BaseModel): + r"""Specifies the shifting field, defined by the formula + + .. math:: + H_{shift} (t) := -\Delta(t) \sum_k h_k | r_k \rangle \langle r_k | + + where + + :math:`\Delta(t)` is the magnitude of the frequency shift in rad/s, + + :math:`h_k` is the site coefficient, + + :math:`|r_k \rangle` is the Rydberg state of atom k. + + with the sum :math:`\sum_k` taken over all target atoms. + + Attributes: + magnitude: PhysicalField + + Examples: + >>> ShiftingField(magnitude=PhysicalField) + """ + + magnitude: PhysicalField diff --git a/src/braket/ir/ahs/time_series.py b/src/braket/ir/ahs/time_series.py new file mode 100644 index 00000000..a23de2e9 --- /dev/null +++ b/src/braket/ir/ahs/time_series.py @@ -0,0 +1,33 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# 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 decimal import Decimal +from typing import List + +from pydantic import BaseModel + + +class TimeSeries(BaseModel): + """ + Specifies the TimeSeries, real-valued time series + + Attributes: + values: List[float] + times: List[float], ascending + + Examples: + >>> TimeSeries(values=[-1.25664e8,1.25664e8],times=[0.0,3.0e-6]) + """ + + values: List[Decimal] + times: List[Decimal] diff --git a/src/braket/task_result/__init__.py b/src/braket/task_result/__init__.py index 53e4f2aa..418c07e2 100644 --- a/src/braket/task_result/__init__.py +++ b/src/braket/task_result/__init__.py @@ -12,6 +12,12 @@ # language governing permissions and limitations under the License from braket.task_result.additional_metadata import AdditionalMetadata # noqa: F401 +from braket.task_result.analog_hamiltonian_simulation_task_result_v1 import ( # noqa: F401 + AnalogHamiltonianSimulationShotMeasurement, + AnalogHamiltonianSimulationShotMetadata, + AnalogHamiltonianSimulationShotResult, + AnalogHamiltonianSimulationTaskResult, +) from braket.task_result.annealing_task_result_v1 import AnnealingTaskResult # noqa: F401 from braket.task_result.dwave_metadata_v1 import DwaveMetadata, DwaveTiming # noqa: F401 from braket.task_result.gate_model_task_result_v1 import ( # noqa: F401 @@ -20,6 +26,7 @@ ) from braket.task_result.oqc_metadata_v1 import OqcMetadata # noqa: F401 from braket.task_result.photonic_model_task_result_v1 import PhotonicModelTaskResult # noqa: F401 +from braket.task_result.quera_metadata_v1 import QueraMetadata # noqa: F401 from braket.task_result.rigetti_metadata_v1 import NativeQuilMetadata, RigettiMetadata # noqa: F401 from braket.task_result.simulator_metadata_v1 import SimulatorMetadata # noqa: F401 from braket.task_result.task_metadata_v1 import TaskMetadata # noqa: F401 diff --git a/src/braket/task_result/additional_metadata.py b/src/braket/task_result/additional_metadata.py index 1c8d567c..471cb176 100644 --- a/src/braket/task_result/additional_metadata.py +++ b/src/braket/task_result/additional_metadata.py @@ -15,12 +15,14 @@ from pydantic import BaseModel +from braket.ir.ahs import Program as AHSProgram from braket.ir.annealing import Problem from braket.ir.blackbird import Program as BlackbirdProgram from braket.ir.jaqcd import Program as JaqcdProgram from braket.ir.openqasm import Program as OpenQASMProgram from braket.task_result.dwave_metadata_v1 import DwaveMetadata from braket.task_result.oqc_metadata_v1 import OqcMetadata +from braket.task_result.quera_metadata_v1 import QueraMetadata from braket.task_result.rigetti_metadata_v1 import RigettiMetadata from braket.task_result.simulator_metadata_v1 import SimulatorMetadata from braket.task_result.xanadu_metadata_v1 import XanaduMetadata @@ -40,9 +42,10 @@ class AdditionalMetadata(BaseModel): """ - action: Union[JaqcdProgram, OpenQASMProgram, BlackbirdProgram, Problem] + action: Union[JaqcdProgram, OpenQASMProgram, BlackbirdProgram, Problem, AHSProgram] dwaveMetadata: Optional[DwaveMetadata] rigettiMetadata: Optional[RigettiMetadata] oqcMetadata: Optional[OqcMetadata] xanaduMetadata: Optional[XanaduMetadata] + queraMetadata: Optional[QueraMetadata] simulatorMetadata: Optional[SimulatorMetadata] diff --git a/src/braket/task_result/analog_hamiltonian_simulation_task_result_v1.py b/src/braket/task_result/analog_hamiltonian_simulation_task_result_v1.py new file mode 100644 index 00000000..d422a46b --- /dev/null +++ b/src/braket/task_result/analog_hamiltonian_simulation_task_result_v1.py @@ -0,0 +1,87 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# 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 typing import List, Optional + +from pydantic import BaseModel, Field, conint, conlist, constr + +from braket.schema_common import BraketSchemaBase, BraketSchemaHeader +from braket.task_result.additional_metadata import AdditionalMetadata +from braket.task_result.task_metadata_v1 import TaskMetadata + + +class AnalogHamiltonianSimulationShotMetadata(BaseModel): + """ + The analog hamiltonian simulation shot metadata schema. + + Attributes: + shotStatus (str): The status of the shot. + """ + + shotStatus: constr(min_length=1) + + +class AnalogHamiltonianSimulationShotResult(BaseModel): + """ + The analog hamiltonian simulation shot result schema. + + Attributes: + preSequence (Optional[conlist(conint(ge=0, le=1), min_items=1)]): Pre-sequence measurement + bits (one for each atomic site) for each shot: 0 if site is empty, 1 if site is filled, + measured before the sequences of pulses that run the quantum evolution + postSequence (Optional[conlist(conint(ge=0, le=1), min_items=1)]): Post-sequence + measurement bits for each shot: 0 if atom is in Rydberg state or site is empty, 1 if + atom is in ground state, measured at the end of the sequences of pulses that run the + quantum evolution + """ + + preSequence: Optional[conlist(conint(ge=0, le=1), min_items=1)] + postSequence: Optional[conlist(conint(ge=0, le=1), min_items=1)] + + +class AnalogHamiltonianSimulationShotMeasurement(BaseModel): + """ + The analog hamiltonian simulation shot measurement schema. + + Attributes: + shotMetadata (AnalogHamiltonianSimulationShotMetadata): The analog hamiltonian simulation + shot metadata schema. + shotResult (AnalogHamiltonianSimulationShotResult): The analog hamiltonian simulation shot + result schema. + """ + + shotMetadata: AnalogHamiltonianSimulationShotMetadata + shotResult: AnalogHamiltonianSimulationShotResult + + +class AnalogHamiltonianSimulationTaskResult(BraketSchemaBase): + """ + The Analog Hamiltonian Simulation task result schema + + Attributes: + braketSchemaHeader (BraketSchemaHeader): Schema header. Users do not need + to set this value. Only default is allowed. + taskMetadata (TaskMetadata): The task metadata + measurements (List[AnalogHamiltonianSimulationShotMeasurement]): List of measurements for + each shot. + """ + + _AHS_TASK_RESULT_HEADER = BraketSchemaHeader( + name="braket.task_result.analog_hamiltonian_simulation_task_result", version="1" + ) + braketSchemaHeader: BraketSchemaHeader = Field( + default=_AHS_TASK_RESULT_HEADER, const=_AHS_TASK_RESULT_HEADER + ) + taskMetadata: TaskMetadata + measurements: Optional[List[AnalogHamiltonianSimulationShotMeasurement]] + additionalMetadata: Optional[AdditionalMetadata] diff --git a/src/braket/task_result/quera_metadata_v1.py b/src/braket/task_result/quera_metadata_v1.py new file mode 100644 index 00000000..d72991eb --- /dev/null +++ b/src/braket/task_result/quera_metadata_v1.py @@ -0,0 +1,39 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# 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 pydantic import Field, conint + +from braket.schema_common import BraketSchemaBase, BraketSchemaHeader + + +class QueraMetadata(BraketSchemaBase): + """ + The Querametadata result schema. + + Attributes: + braketSchemaHeader (BraketSchemaHeader): Schema header. + Users do not need to set this value. Only default is allowed. + numSuccessfulShots (int): Number of successful shots in result. + + Examples: + >>> QueraMetadata(numSuccessfulShots=100) + """ + + _QUERA_METADATA_HEADER = BraketSchemaHeader( + name="braket.task_result.quera_metadata", version="1" + ) + braketSchemaHeader: BraketSchemaHeader = Field( + default=_QUERA_METADATA_HEADER, const=_QUERA_METADATA_HEADER + ) + + numSuccessfulShots: conint(ge=0, le=1000) diff --git a/test/unit_tests/braket/device_schema/quera/test_quera_ahs_paradigm_properties_v1.py b/test/unit_tests/braket/device_schema/quera/test_quera_ahs_paradigm_properties_v1.py new file mode 100644 index 00000000..5d7c847f --- /dev/null +++ b/test/unit_tests/braket/device_schema/quera/test_quera_ahs_paradigm_properties_v1.py @@ -0,0 +1,177 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# 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. + +import json +import math + +import pytest +from pydantic import ValidationError + +from braket.device_schema.quera.quera_ahs_paradigm_properties_v1 import ( + Area, + Geometry, + QueraAhsParadigmProperties, + RydbergGlobal, +) + + +@pytest.fixture(scope="module") +def valid_input(): + input = { + "braketSchemaHeader": { + "name": "braket.device_schema.quera.quera_ahs_paradigm_properties", + "version": "1", + }, + "qubitCount": 256, + "lattice": { + "area": { + "width": 100.0e-6, + "height": 100.0e-6, + }, + "geometry": { + "spacingRadialMin": 4.0e-6, + "spacingVerticalMin": 2.5e-6, + "positionResolution": 1e-7, + "numberSitesMax": 256, + }, + }, + "rydberg": { + "c6Coefficient": 2 * math.pi * 862690, + "rydbergGlobal": { + "rabiFrequencyRange": [0, 2 * math.pi * 4.0e6], + "rabiFrequencyResolution": 400, + "rabiFrequencySlewRateMax": 2 * math.pi * 4e6 / 100e-9, + "detuningRange": [-2 * math.pi * 20.0e6, 2 * math.pi * 20.0e6], + "detuningResolution": 0.2, + "detuningSlewRateMax": 2 * math.pi * 40.0e6 / 100e-9, + "phaseRange": [-99, 99], + "phaseResolution": 5e-7, + "timeResolution": 1e-9, + "timeDeltaMin": 1e-8, + "timeMin": 0, + "timeMax": 4.0e-6, + }, + }, + "performance": { + "lattice": { + "positionErrorAbs": 0.025e-6, + }, + "rydberg": { + "rydbergGlobal": { + "rabiFrequencyErrorRel": 0.01, + }, + }, + }, + } + return input + + +def test_valid(valid_input): + result = QueraAhsParadigmProperties.parse_raw_schema(json.dumps(valid_input)) + assert ( + result.braketSchemaHeader.name == "braket.device_schema.quera.quera_ahs_paradigm_properties" + ) + + +@pytest.mark.parametrize("missing_field", ["braketSchemaHeader", "lattice", "rydberg"]) +def test_missing_field(valid_input, missing_field): + with pytest.raises(ValidationError): + valid_input.pop(missing_field) + QueraAhsParadigmProperties.parse_raw_schema(json.dumps(valid_input)) + + +@pytest.mark.xfail(raises=ValidationError) +def test_missing_field_in_area(): + Area(width=100.0e-6) + + +@pytest.mark.xfail(raises=ValidationError) +def test_invalid_field_in_area(): + Area(width=100.0e-6, height="foo") + + +@pytest.mark.xfail(raises=ValidationError) +def test_missing_field_in_geometry(): + Geometry(spacingRadiaMin=4.0e-6, spacingVerticalMin=2.5e-6) + + +@pytest.mark.xfail(raises=ValidationError) +def test_invalid_field_in_geometry(): + Geometry( + spacingRadiaMin=4.0e-6, + spacingVerticalMin="foo", + positionResolution=1e-7, + numberOfSitesMax=256, + ) + + +@pytest.mark.xfail(raises=ValidationError) +def test_missing_field_in_detection(): + Area(atomDetectionFidelity=0.99) + + +@pytest.mark.xfail(raises=ValidationError) +def test_invalid_field_in_detection(): + Area(atomDetectionFidelity=0.99, vacancyDetectionFidelity="foo") + + +@pytest.mark.xfail(raises=ValidationError) +def test_missing_field_in_sorting(): + Geometry(moveFidelity=0.98) + + +@pytest.mark.xfail(raises=ValidationError) +def test_invalid_field_in_sorting(): + Geometry(moveFidelity=4.0e-6, patternFidelitySquare="foo") + + +@pytest.mark.xfail(raises=ValidationError) +def test_missing_field_in_rydbergGlobal(): + RydbergGlobal( + rabiFrequencyRange=[0, 2 * math.pi * 4.0e6], + rabiFrequencySlewRateMax=2 * math.pi * 4e6 / 100e-9, + ) + + +@pytest.mark.xfail(raises=ValidationError) +def test_invalid_field_in_rydbergGlobal(): + RydbergGlobal( + rabiFrequencyRange=2.0, + rabiFrequencySlewRateMax=2 * math.pi * 4e6 / 100e-9, + detuningRange=[-2 * math.pi * 20.0e6, 2 * math.pi * 20.0e6], + detuningSlewRateMax=2 * math.pi * 40.0e6 / 100e-9, + phaseRange=[-99, 99], + phaseSlewRateMax=2 * math.pi / 100e-9, + timeDiscretization=1e-9, + timeMax=4.0e-6, + ) + + +@pytest.mark.xfail(raises=ValidationError) +def test_missing_field_in_perfomanceRydbergGlobal(): + RydbergGlobal(rabiFrequencyErrorRel=0.01, rabiFrequencyHomogeneityRel=0.05) + + +@pytest.mark.xfail(raises=ValidationError) +def test_invalid_field_in_perfomanceRydbergGlobal(): + RydbergGlobal( + rabiFrequencyErrorRel=0.01, + rabiFrequencyHomogeneityRel=0.05, + rabiFrequencyHomogeneityAbs=60e3, + detuningErrorAbs=2 * math.pi * 10.0e3, + phaseErrorAbs=2 * math.pi / 1000, + phaseRange=99, + omegaTau=10, + singleQubitFidelity=0.95, + twoQubitFidelity=0.95, + ) diff --git a/test/unit_tests/braket/device_schema/quera/test_quera_device_capabilities_v1.py b/test/unit_tests/braket/device_schema/quera/test_quera_device_capabilities_v1.py new file mode 100644 index 00000000..6745698f --- /dev/null +++ b/test/unit_tests/braket/device_schema/quera/test_quera_device_capabilities_v1.py @@ -0,0 +1,153 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# 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. + +import json +import math + +import pytest +from pydantic import ValidationError + +from braket.device_schema.quera import QueraDeviceCapabilities + + +@pytest.fixture(scope="module") +def valid_input(): + input = { + "braketSchemaHeader": { + "name": "braket.device_schema.quera.quera_device_capabilities", + "version": "1", + }, + "service": { + "braketSchemaHeader": { + "name": "braket.device_schema.device_service_properties", + "version": "1", + }, + "executionWindows": [ + { + "executionDay": "Everyday", + "windowStartHour": "09:00", + "windowEndHour": "10:00", + } + ], + "shotsRange": [1, 10000], + "deviceCost": {"price": 0.25, "unit": "minute"}, + "deviceDocumentation": { + "imageUrl": "image_url", + "summary": "Summary on the device", + "externalDocumentationUrl": "external doc link", + }, + "deviceLocation": "us-east-1", + "updatedAt": "2022-04-16T19:28:02.869136", + }, + "action": { + "braket.ir.ahs.program": { + "actionType": "braket.ir.ahs.program", + "version": ["1"], + } + }, + "deviceParameters": "", + "paradigm": { + "braketSchemaHeader": { + "name": "braket.device_schema.quera.quera_ahs_paradigm_properties", + "version": "1", + }, + "qubitCount": 256, + "lattice": { + "area": { + "width": 100.0e-6, + "height": 100.0e-6, + }, + "geometry": { + "spacingRadialMin": 4.0e-6, + "spacingVerticalMin": 2.5e-6, + "positionResolution": 1e-7, + "numberSitesMax": 256, + }, + }, + "rydberg": { + "c6Coefficient": 2 * math.pi * 862690, + "rydbergGlobal": { + "rabiFrequencyRange": [0, 2 * math.pi * 4.0e6], + "rabiFrequencyResolution": 400, + "rabiFrequencySlewRateMax": 2 * math.pi * 4e6 / 100e-9, + "detuningRange": [-2 * math.pi * 20.0e6, 2 * math.pi * 20.0e6], + "detuningResolution": 0.2, + "detuningSlewRateMax": 2 * math.pi * 40.0e6 / 100e-9, + "phaseRange": [-99, 99], + "phaseResolution": 5e-7, + "phaseSlewRateMax": 2 * math.pi / 100e-9, + "timeResolution": 1e-9, + "timeDeltaMin": 1e-8, + "timeMin": 0, + "timeMax": 4.0e-6, + }, + "rydbergLocal": { + "detuningRange": [0, 2 * math.pi * 50.0e6], + "commonDetuningResolution": 2000, + "localDetuningResolution": 0.01, + "detuningSlewRateMax": 1 / 100e-9, + "numberLocalDetuningSites": 256, + "spacingRadialMin": 5e-6, + "timeResolution": 1e-9, + "timeDeltaMin": 1e-8, + }, + }, + "performance": { + "lattice": { + "positionErrorAbs": 0.025e-6, + }, + "rydberg": { + "rydbergGlobal": { + "rabiFrequencyErrorRel": 0.01, + "rabiFrequencyHomogeneityRel": 0.05, + "rabiFrequencyHomogeneityAbs": 60e3, + "detuningErrorAbs": 2 * math.pi * 10.0e3, + "phaseErrorAbs": 2 * math.pi / 1000, + "omegaTau": 10, + "singleQubitFidelity": 0.95, + "twoQubitFidelity": 0.95, + }, + "rydbergLocal": { + "detuningDynamicRange": 10, + "detuningErrorRel": 0.01, + "detuningHomogeneity": 0.02, + "detuningScaleErrorRel": 0.01, + "darkErrorRete": 1e3, + "brightErrorRate": 3e6, + }, + }, + "detection": { + "atomDetectionFidelity": 0.99, + "vacancyDetectionFidelity": 0.999, + "groundStateDetectionFidelity": 0.99, + "rydbergStateDetectionFidelity": 0.99, + }, + "sorting": { + "moveFidelity": 0.98, + "patternFidelitySquare": 1e-4, + }, + }, + }, + } + return input + + +def test_valid(valid_input): + result = QueraDeviceCapabilities.parse_raw_schema(json.dumps(valid_input)) + assert result.braketSchemaHeader.name == "braket.device_schema.quera.quera_device_capabilities" + + +@pytest.mark.xfail(raises=ValidationError) +def test__missing_schemaHeader(valid_input): + valid_input.pop("braketSchemaHeader") + QueraDeviceCapabilities.parse_raw_schema(json.dumps(valid_input)) diff --git a/test/unit_tests/braket/ir/ahs/test_ahs_program_v1.py b/test/unit_tests/braket/ir/ahs/test_ahs_program_v1.py new file mode 100644 index 00000000..b520181a --- /dev/null +++ b/test/unit_tests/braket/ir/ahs/test_ahs_program_v1.py @@ -0,0 +1,109 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# 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 decimal import Decimal + +import pytest +from pydantic import ValidationError + +from braket.ir.ahs.program_v1 import Program + +valid_setup_input = { + "ahs_register": { + "sites": [ + [0.0, 0.0], + [0.0, 3.0e-6], + [0.0, 6.0e-6], + [3.0e-6, 0.0], + [3.0e-6, 3.0e-6], + [3.0e-6, 6.0e-6], + ], + "filling": [1, 1, 1, 1, 0, 0], + } +} + +valid_hamiltonian_input = { + "drivingFields": [ + { + "amplitude": { + "time_series": { + "values": [0.0, 2.51327e7, 2.51327e7, 0.0], + "times": [0.0, 3.0e-7, 2.7e-6, 3.0e-6], + }, + "pattern": "uniform", + }, + "phase": { + "time_series": {"values": [0, 0], "times": [0.0, 3.0e-6]}, + "pattern": "uniform", + }, + "detuning": { + "time_series": { + "values": [-1.25664e8, -1.25664e8, 1.25664e8, 1.25664e8], + "times": [0.0, 3.0e-7, 2.7e-6, 3.0e-6], + }, + "pattern": "uniform", + }, + } + ], + "shiftingFields": [ + { + "magnitude": { + "time_series": {"values": [-1.25664e8, 1.25664e8], "times": [0.0, 3.0e-6]}, + "pattern": [0.5, 1.0, 0.5, 0.5, 0.5, 0.5], + } + } + ], +} + + +def test_valid(): + program = Program( + setup=valid_setup_input, + hamiltonian=valid_hamiltonian_input, + ) + assert Program.parse_raw_schema(program.json()) == program + assert program == Program.parse_raw_schema(program.json()) + + +@pytest.mark.xfail(raises=ValidationError) +def test__missing_setup(): + Program( + hamiltonian=valid_hamiltonian_input, + ) + + +@pytest.mark.xfail(raises=ValidationError) +def test__missing_hamiltonian(): + Program( + setup=valid_setup_input, + ) + + +def test_correct_decimal_serialization(): + program = Program( + setup=valid_setup_input, + hamiltonian=valid_hamiltonian_input, + ) + program.hamiltonian.drivingFields[0].amplitude.time_series.times = [ + Decimal(i * 3e-6 / 7) for i in range(8) + ] + program.hamiltonian.drivingFields[0].amplitude.time_series.values = [Decimal(0.0)] * 8 + + serialized_program = program.json() + deserialized_program = Program.parse_raw(serialized_program) + + original_amplitude_times = program.hamiltonian.drivingFields[0].amplitude.time_series.times + new_amplitude_times = deserialized_program.hamiltonian.drivingFields[ + 0 + ].amplitude.time_series.times + assert new_amplitude_times == original_amplitude_times diff --git a/test/unit_tests/braket/ir/ahs/test_atom_arrangement.py b/test/unit_tests/braket/ir/ahs/test_atom_arrangement.py new file mode 100644 index 00000000..c120d31b --- /dev/null +++ b/test/unit_tests/braket/ir/ahs/test_atom_arrangement.py @@ -0,0 +1,49 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# 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 decimal import Decimal + +import pytest +from pydantic import ValidationError + +from braket.ir.ahs.atom_arrangement import AtomArrangement + +valid_site_input = [ + [Decimal(0.0), Decimal(0.0)], + [Decimal(0.0), Decimal(3.0e-6)], + [Decimal(0.0), Decimal(6.0e-6)], + [Decimal(3.0e-6), Decimal(0.0)], + [Decimal(3.0e-6), Decimal(3.0e-6)], + [Decimal(3.0e-6), Decimal(6.0e-6)], +] +valid_filling = [Decimal(1), Decimal(1), Decimal(1), Decimal(1), Decimal(0), Decimal(0)] + + +def test_valid(): + atom_array = AtomArrangement(sites=valid_site_input, filling=valid_filling) + assert atom_array.sites == valid_site_input + assert atom_array.filling == valid_filling + + +@pytest.mark.xfail(raises=ValidationError) +def test__missing_sites(): + AtomArrangement( + filling=valid_filling, + ) + + +@pytest.mark.xfail(raises=ValidationError) +def test__missing_filling(): + AtomArrangement( + sites=valid_site_input, + ) diff --git a/test/unit_tests/braket/ir/ahs/test_driving_field.py b/test/unit_tests/braket/ir/ahs/test_driving_field.py new file mode 100644 index 00000000..1dee1f68 --- /dev/null +++ b/test/unit_tests/braket/ir/ahs/test_driving_field.py @@ -0,0 +1,43 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# 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. + +import pytest +from pydantic import ValidationError + +from braket.ir.ahs.driving_field import DrivingField + +valid_atom_field = {"time_series": {"values": [], "times": []}, "pattern": ""} + + +def test_valid(): + driving_field = DrivingField( + amplitude=valid_atom_field, phase=valid_atom_field, detuning=valid_atom_field + ) + assert driving_field.amplitude == valid_atom_field + assert driving_field.phase == valid_atom_field + assert driving_field.detuning == valid_atom_field + + +@pytest.mark.xfail(raises=ValidationError) +def test__missing_amplitude(): + DrivingField(phase=valid_atom_field, detuning=valid_atom_field) + + +@pytest.mark.xfail(raises=ValidationError) +def test__missing_phase(): + DrivingField(amplitude=valid_atom_field, detuning=valid_atom_field) + + +@pytest.mark.xfail(raises=ValidationError) +def test__missing_detuning(): + DrivingField(amplitude=valid_atom_field, phase=valid_atom_field) diff --git a/test/unit_tests/braket/ir/ahs/test_hamiltonian.py b/test/unit_tests/braket/ir/ahs/test_hamiltonian.py new file mode 100644 index 00000000..16eb9dd7 --- /dev/null +++ b/test/unit_tests/braket/ir/ahs/test_hamiltonian.py @@ -0,0 +1,42 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# 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. + +import pytest +from pydantic import ValidationError + +from braket.ir.ahs.hamiltonian import Hamiltonian + +valid_driving_fields = [] +valid_shifting_fields = [] + + +def test_valid(): + hamiltonian_field = Hamiltonian( + drivingFields=valid_driving_fields, shiftingFields=valid_shifting_fields + ) + assert hamiltonian_field.drivingFields == valid_driving_fields + assert hamiltonian_field.shiftingFields == valid_shifting_fields + + +@pytest.mark.xfail(raises=ValidationError) +def test__missing_driving_fields(): + Hamiltonian( + shiftingFields=valid_shifting_fields, + ) + + +@pytest.mark.xfail(raises=ValidationError) +def test__missing_shifting_fields(): + Hamiltonian( + drivingFields=valid_driving_fields, + ) diff --git a/test/unit_tests/braket/ir/ahs/test_physical_field.py b/test/unit_tests/braket/ir/ahs/test_physical_field.py new file mode 100644 index 00000000..4bcf7d13 --- /dev/null +++ b/test/unit_tests/braket/ir/ahs/test_physical_field.py @@ -0,0 +1,56 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# 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 decimal import Decimal + +import pytest +from pydantic import ValidationError + +from braket.ir.ahs.physical_field import PhysicalField + +valid_time_series = {"values": [Decimal(0), Decimal(0)], "times": [Decimal(0.0), Decimal(3.0e-6)]} +valid_pattern_str = "uniform" +valid_pattern_list = [ + Decimal(0.5), + Decimal(1.0), + Decimal(0.5), + Decimal(0.5), + Decimal(0.5), + Decimal(0.5), +] + + +def test_valid_default_pattern(): + physical_field = PhysicalField(time_series=valid_time_series, pattern=valid_pattern_str) + assert physical_field.time_series == valid_time_series + assert physical_field.pattern == valid_pattern_str + + +def test_valid_list_pattern(): + physical_field = PhysicalField(time_series=valid_time_series, pattern=valid_pattern_list) + assert physical_field.time_series == valid_time_series + assert physical_field.pattern == valid_pattern_list + + +@pytest.mark.xfail(raises=ValidationError) +def test__missing_pattern(): + PhysicalField( + time_series=valid_time_series, + ) + + +@pytest.mark.xfail(raises=ValidationError) +def test__missing_time_series(): + PhysicalField( + pattern=valid_pattern_str, + ) diff --git a/test/unit_tests/braket/ir/ahs/test_shifting_field.py b/test/unit_tests/braket/ir/ahs/test_shifting_field.py new file mode 100644 index 00000000..6688d501 --- /dev/null +++ b/test/unit_tests/braket/ir/ahs/test_shifting_field.py @@ -0,0 +1,29 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# 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. + +import pytest +from pydantic import ValidationError + +from braket.ir.ahs.shifting_field import ShiftingField + +valid_atom_field = {"time_series": {"values": [], "times": []}, "pattern": ""} + + +def test_valid(): + shifting_field = ShiftingField(magnitude=valid_atom_field) + assert shifting_field.magnitude == valid_atom_field + + +@pytest.mark.xfail(raises=ValidationError) +def test__missing_magnitude(): + ShiftingField() diff --git a/test/unit_tests/braket/ir/ahs/test_time_series.py b/test/unit_tests/braket/ir/ahs/test_time_series.py new file mode 100644 index 00000000..7febc252 --- /dev/null +++ b/test/unit_tests/braket/ir/ahs/test_time_series.py @@ -0,0 +1,42 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# 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 decimal import Decimal + +import pytest +from pydantic import ValidationError + +from braket.ir.ahs.time_series import TimeSeries + +valid_values = [Decimal(-1.25664e8), Decimal(1.25664e8)] +valid_times = [Decimal(0.0), Decimal(3.0e-6)] + + +def test_valid(): + time_series = TimeSeries(values=valid_values, times=valid_times) + assert time_series.values == valid_values + assert time_series.times == valid_times + + +@pytest.mark.xfail(raises=ValidationError) +def test__missing_values(): + TimeSeries( + times=valid_times, + ) + + +@pytest.mark.xfail(raises=ValidationError) +def test__missing_times(): + TimeSeries( + values=valid_values, + ) diff --git a/test/unit_tests/braket/task_result/conftest.py b/test/unit_tests/braket/task_result/conftest.py index edbbb9ca..73c96615 100644 --- a/test/unit_tests/braket/task_result/conftest.py +++ b/test/unit_tests/braket/task_result/conftest.py @@ -13,6 +13,7 @@ import pytest +from braket.ir.ahs import Program as AHSProgram from braket.ir.annealing import Problem, ProblemType from braket.ir.blackbird import Program as BlackbirdProgram from braket.ir.jaqcd import CNot @@ -22,6 +23,7 @@ from braket.task_result.additional_metadata import AdditionalMetadata from braket.task_result.dwave_metadata_v1 import DwaveMetadata, DwaveTiming from braket.task_result.oqc_metadata_v1 import OqcMetadata +from braket.task_result.quera_metadata_v1 import QueraMetadata from braket.task_result.rigetti_metadata_v1 import NativeQuilMetadata, RigettiMetadata from braket.task_result.task_metadata_v1 import TaskMetadata from braket.task_result.xanadu_metadata_v1 import XanaduMetadata @@ -100,6 +102,11 @@ def oqc_metadata(compiled_program): return OqcMetadata(compiledProgram=compiled_program) +@pytest.fixture +def quera_metadata(): + return QueraMetadata(numSuccessfulShots=100) + + @pytest.fixture def problem(): return Problem( @@ -126,6 +133,57 @@ def blackbird_program(): ) +@pytest.fixture +def ahs_program(): + return AHSProgram( + setup={ + "ahs_register": { + "sites": [ + [0.0, 0.0], + [0.0, 3.0e-6], + [0.0, 6.0e-6], + [3.0e-6, 0.0], + [3.0e-6, 3.0e-6], + [3.0e-6, 6.0e-6], + ], + "filling": [1, 1, 1, 1, 0, 0], + } + }, + hamiltonian={ + "drivingFields": [ + { + "amplitude": { + "time_series": { + "values": [0.0, 2.51327e7, 2.51327e7, 0.0], + "times": [0.0, 3.0e-7, 2.7e-6, 3.0e-6], + }, + "pattern": "uniform", + }, + "phase": { + "time_series": {"values": [0, 0], "times": [0.0, 3.0e-6]}, + "pattern": "uniform", + }, + "detuning": { + "time_series": { + "values": [-1.25664e8, -1.25664e8, 1.25664e8, 1.25664e8], + "times": [0.0, 3.0e-7, 2.7e-6, 3.0e-6], + }, + "pattern": "uniform", + }, + } + ], + "shiftingFields": [ + { + "magnitude": { + "time_series": {"values": [-1.25664e8, 1.25664e8], "times": [0.0, 3.0e-6]}, + "pattern": [0.5, 1.0, 0.5, 0.5, 0.5, 0.5], + } + } + ], + }, + ) + + @pytest.fixture def openqasm_program(): return OpenQASMProgram(source="OPENQASM 3.0; cnot $0, $1;") @@ -141,6 +199,11 @@ def additional_metadata_photonic_model(blackbird_program, xanadu_metadata): return AdditionalMetadata(action=blackbird_program, xanadu_metadata=xanadu_metadata) +@pytest.fixture +def additional_metadata_ahs(ahs_program, quera_metadata): + return AdditionalMetadata(action=ahs_program, quera_metadata=quera_metadata) + + @pytest.fixture def id(): return "task_id" diff --git a/test/unit_tests/braket/task_result/test_additional_metadata.py b/test/unit_tests/braket/task_result/test_additional_metadata.py index c6c1c473..b7ed3eea 100644 --- a/test/unit_tests/braket/task_result/test_additional_metadata.py +++ b/test/unit_tests/braket/task_result/test_additional_metadata.py @@ -58,6 +58,12 @@ def test_additional_metadata_oqc(oqc_metadata, openqasm_program): assert AdditionalMetadata.parse_raw(metadata.json()) == metadata +def test_additional_metadata_quera(quera_metadata, ahs_program): + metadata = AdditionalMetadata(action=ahs_program, queraMetadata=quera_metadata) + assert metadata.queraMetadata == quera_metadata + assert AdditionalMetadata.parse_raw(metadata.json()) == metadata + + @pytest.mark.xfail(raises=ValidationError) def test_incorrect_action(dwave_metadata): AdditionalMetadata(action=dwave_metadata) diff --git a/test/unit_tests/braket/task_result/test_analog_hamiltonian_simulation_task_result_v1.py b/test/unit_tests/braket/task_result/test_analog_hamiltonian_simulation_task_result_v1.py new file mode 100644 index 00000000..1ed9f882 --- /dev/null +++ b/test/unit_tests/braket/task_result/test_analog_hamiltonian_simulation_task_result_v1.py @@ -0,0 +1,155 @@ +# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# 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. + +import pytest +from pydantic import ValidationError + +from braket.task_result.analog_hamiltonian_simulation_task_result_v1 import ( + AnalogHamiltonianSimulationShotMeasurement, + AnalogHamiltonianSimulationShotMetadata, + AnalogHamiltonianSimulationShotResult, + AnalogHamiltonianSimulationTaskResult, +) + + +@pytest.fixture +def shot_status(): + return "Success" + + +@pytest.fixture +def pre_sequence(): + return [1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1] + + +@pytest.fixture +def post_sequence(): + return [0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0] + + +@pytest.fixture +def shot_metadata(): + return AnalogHamiltonianSimulationShotMetadata(shotStatus="Success") + + +@pytest.fixture +def shot_result(): + return AnalogHamiltonianSimulationShotResult( + preSequence=[1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1], + postSequence=[0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0], + ) + + +@pytest.fixture +def ahs_measurements(): + return [ + AnalogHamiltonianSimulationShotMeasurement( + shotMetadata=AnalogHamiltonianSimulationShotMetadata(shotStatus="Success"), + shotResult=AnalogHamiltonianSimulationShotResult( + preSequence=[1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1], + post_sequence=[0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0], + ), + ) + ] + + +def test_correct_analogHamiltonianSimulationShotMetadata( + shot_status, +): + result = AnalogHamiltonianSimulationShotMetadata( + shotStatus=shot_status, + ) + assert result.shotStatus == shot_status + + +@pytest.mark.xfail(raises=ValidationError) +def test_missing_value_analogHamiltonianSimulationShotMetadata(): + AnalogHamiltonianSimulationShotMetadata( + shotStatus=None, + ) + + +def test_correct_analogHamiltonianSimulationShotResult( + pre_sequence, + post_sequence, +): + result = AnalogHamiltonianSimulationShotResult( + preSequence=pre_sequence, postSequence=post_sequence + ) + assert result.preSequence == pre_sequence + assert result.postSequence == post_sequence + + +def test_optional_value_analogHamiltonianSimulationShotResult( + pre_sequence, + post_sequence, +): + result = AnalogHamiltonianSimulationShotResult(postSequence=post_sequence) + assert result.postSequence == post_sequence + + +def test_correct_analogHamiltonianSimulationShotMeasurement( + shot_metadata, + shot_result, +): + result = AnalogHamiltonianSimulationShotMeasurement( + shotMetadata=shot_metadata, shotResult=shot_result + ) + assert result.shotMetadata == shot_metadata + assert result.shotResult == shot_result + + +@pytest.mark.xfail(raises=ValidationError) +def test_missing_value_analogHamiltonianSimulationShotMeasuremen( + shot_metadata, + shot_result, +): + AnalogHamiltonianSimulationShotMeasurement( + shotMetadata=shot_metadata, + ) + + +def test_correct_analogHamiltonianSimulationTaskResult( + task_metadata, + ahs_measurements, + additional_metadata_ahs, +): + result = AnalogHamiltonianSimulationTaskResult( + measurements=ahs_measurements, + taskMetadata=task_metadata, + additionalMetadata=additional_metadata_ahs, + ) + assert result.taskMetadata == task_metadata + assert result.measurements == ahs_measurements + assert result.additionalMetadata == additional_metadata_ahs + assert AnalogHamiltonianSimulationTaskResult.parse_raw(result.json()) == result + assert result == AnalogHamiltonianSimulationTaskResult.parse_raw_schema(result.json()) + + +def test_optional_value_analogHamiltonianSimulationTaskResult(task_metadata): + result = AnalogHamiltonianSimulationTaskResult( + taskMetadata=task_metadata, + ) + assert result.taskMetadata == task_metadata + assert AnalogHamiltonianSimulationTaskResult.parse_raw(result.json()) == result + assert result == AnalogHamiltonianSimulationTaskResult.parse_raw_schema(result.json()) + + +@pytest.mark.xfail(raises=ValidationError) +def test_missing_required_value_analogHamiltonianSimulationTaskResult( + task_metadata, + ahs_measurements, +): + AnalogHamiltonianSimulationTaskResult( + measurements=ahs_measurements, + )