Skip to content

Commit

Permalink
Merge branch 'main' into feature/autoqasm
Browse files Browse the repository at this point in the history
  • Loading branch information
rmshaffer committed Apr 10, 2024
2 parents ec9c00f + f556567 commit 1e8d67f
Show file tree
Hide file tree
Showing 11 changed files with 264 additions and 162 deletions.
29 changes: 29 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,34 @@
# Changelog

## v1.77.0 (2024-04-10)

### Features

* rename shifting field to local detuning

## v1.76.3 (2024-04-09)

### Bug Fixes and Other Changes

* Replace pkg_resources with importlib.metadata

### Documentation Changes

* Improve gphase unitary matrix definition in docstring

## v1.76.2 (2024-04-08)

### Bug Fixes and Other Changes

* backwards compatiblity for local detuning

## v1.76.1 (2024-04-08)

### Bug Fixes and Other Changes

* Support single-register measurements in `from_ir`
* prevent repeated measurements on a qubit

## v1.76.0 (2024-04-01)

### Features
Expand Down
5 changes: 2 additions & 3 deletions doc/conf.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
"""Sphinx configuration."""

import datetime

import pkg_resources
from importlib.metadata import version

# Sphinx configuration below.
project = "amazon-braket-sdk"
version = pkg_resources.require(project)[0].version
version = version(project)
release = version
copyright = "{}, Amazon.com".format(datetime.datetime.now().year)

Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
# NOTE: This change should remain in the feature/autoqasm branch; do not merge to main.
"amazon-braket-default-simulator @ git+https://github.com/amazon-braket/amazon-braket-default-simulator-python.git@7245414b79856a03ac0507f86f1eae92ff697cd0#egg=amazon-braket-default-simulator", # noqa E501
"oqpy~=0.3.5",
"setuptools",
"backoff",
"boltons",
"boto3>=1.28.53",
Expand All @@ -46,6 +45,7 @@
"openpulse",
"openqasm3",
"sympy",
"backports.entry-points-selectable",
"astunparse",
"gast",
"termcolor",
Expand Down
2 changes: 1 addition & 1 deletion src/braket/_sdk/_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@
Version number (major.minor.patch[-label])
"""

__version__ = "1.76.1.dev0"
__version__ = "1.77.1.dev0"
161 changes: 161 additions & 0 deletions src/braket/ahs/local_detuning.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
# 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 __future__ import annotations

from braket.ahs.discretization_types import DiscretizationProperties
from braket.ahs.field import Field
from braket.ahs.hamiltonian import Hamiltonian
from braket.ahs.pattern import Pattern
from braket.timings.time_series import StitchBoundaryCondition, TimeSeries


class LocalDetuning(Hamiltonian):
def __init__(self, magnitude: Field) -> None:
r"""Creates a Hamiltonian term :math:`H_{shift}` representing the local detuning
that changes the energy of the Rydberg level in an AnalogHamiltonianSimulation,
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 of atom :math:`k`,
a dimensionless real number between 0 and 1,
:math:`|r_k \rangle` is the Rydberg state of atom :math:`k`.
with the sum :math:`\sum_k` taken over all target atoms.
Args:
magnitude (Field): containing the global magnitude time series :math:`\Delta(t)`,
where time is measured in seconds (s) and values are measured in rad/s, and the
local pattern :math:`h_k` of dimensionless real numbers between 0 and 1.
"""
super().__init__()
self._magnitude = magnitude

@property
def terms(self) -> list[Hamiltonian]:
return [self]

@property
def magnitude(self) -> Field:
r"""Field: containing the global magnitude time series :math:`\Delta(t)`,
where time is measured in seconds (s) and values measured in rad/s)
and the local pattern :math:`h_k` of dimensionless real numbers between 0 and 1.
"""
return self._magnitude

@staticmethod
def from_lists(times: list[float], values: list[float], pattern: list[float]) -> LocalDetuning:
"""Get the shifting field from a set of time points, values and pattern
Args:
times (list[float]): The time points of the shifting field
values (list[float]): The values of the shifting field
pattern (list[float]): The pattern of the shifting field
Raises:
ValueError: If the length of times and values differs.
Returns:
LocalDetuning: The shifting field obtained
"""
if len(times) != len(values):
raise ValueError("The length of the times and values lists must be equal.")

magnitude = TimeSeries()
for t, v in zip(times, values):
magnitude.put(t, v)
shift = LocalDetuning(Field(magnitude, Pattern(pattern)))

return shift

def stitch(
self, other: LocalDetuning, boundary: StitchBoundaryCondition = StitchBoundaryCondition.MEAN
) -> LocalDetuning:
"""Stitches two shifting fields based on TimeSeries.stitch method.
The time points of the second LocalDetuning are shifted such that the first time point of
the second LocalDetuning coincides with the last time point of the first LocalDetuning.
The boundary point value is handled according to StitchBoundaryCondition argument value.
Args:
other (LocalDetuning): The second local detuning to be stitched with.
boundary (StitchBoundaryCondition): {"mean", "left", "right"}. Boundary point handler.
Possible options are
- "mean" - take the average of the boundary value points of the first
and the second time series.
- "left" - use the last value from the left time series as the boundary point.
- "right" - use the first value from the right time series as the boundary point.
Raises:
ValueError: The LocalDetuning patterns differ.
Returns:
LocalDetuning: The stitched LocalDetuning object.
Example (StitchBoundaryCondition.MEAN):
::
time_series_1 = TimeSeries.from_lists(times=[0, 0.1], values=[1, 2])
time_series_2 = TimeSeries.from_lists(times=[0.2, 0.4], values=[4, 5])
stitch_ts = time_series_1.stitch(time_series_2, boundary=StitchBoundaryCondition.MEAN)
Result:
stitch_ts.times() = [0, 0.1, 0.3]
stitch_ts.values() = [1, 3, 5]
Example (StitchBoundaryCondition.LEFT):
::
stitch_ts = time_series_1.stitch(time_series_2, boundary=StitchBoundaryCondition.LEFT)
Result:
stitch_ts.times() = [0, 0.1, 0.3]
stitch_ts.values() = [1, 2, 5]
Example (StitchBoundaryCondition.RIGHT):
::
stitch_ts = time_series_1.stitch(time_series_2, boundary=StitchBoundaryCondition.RIGHT)
Result:
stitch_ts.times() = [0, 0.1, 0.3]
stitch_ts.values() = [1, 4, 5]
"""
if not (self.magnitude.pattern.series == other.magnitude.pattern.series):
raise ValueError("The LocalDetuning pattern for both fields must be equal.")

new_ts = self.magnitude.time_series.stitch(other.magnitude.time_series, boundary)
return LocalDetuning(Field(new_ts, self.magnitude.pattern))

def discretize(self, properties: DiscretizationProperties) -> LocalDetuning:
"""Creates a discretized version of the LocalDetuning.
Args:
properties (DiscretizationProperties): Capabilities of a device that represent the
resolution with which the device can implement the parameters.
Returns:
LocalDetuning: A new discretized LocalDetuning.
"""
shifting_parameters = properties.rydberg.rydbergLocal
discretized_magnitude = self.magnitude.discretize(
time_resolution=shifting_parameters.timeResolution,
value_resolution=shifting_parameters.commonDetuningResolution,
pattern_resolution=shifting_parameters.localDetuningResolution,
)
return LocalDetuning(discretized_magnitude)
153 changes: 6 additions & 147 deletions src/braket/ahs/shifting_field.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,151 +11,10 @@
# ANY KIND, either express or implied. See the License for the specific
# language governing permissions and limitations under the License.

from __future__ import annotations
from braket.ahs.local_detuning import LocalDetuning

from braket.ahs.discretization_types import DiscretizationProperties
from braket.ahs.field import Field
from braket.ahs.hamiltonian import Hamiltonian
from braket.ahs.pattern import Pattern
from braket.timings.time_series import StitchBoundaryCondition, TimeSeries


class ShiftingField(Hamiltonian):
def __init__(self, magnitude: Field) -> None:
r"""Creates a Hamiltonian term :math:`H_{shift}` representing the shifting field
that changes the energy of the Rydberg level in an AnalogHamiltonianSimulation,
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 of atom :math:`k`,
a dimensionless real number between 0 and 1,
:math:`|r_k \rangle` is the Rydberg state of atom :math:`k`.
with the sum :math:`\sum_k` taken over all target atoms.
Args:
magnitude (Field): containing the global magnitude time series :math:`\Delta(t)`,
where time is measured in seconds (s) and values are measured in rad/s, and the
local pattern :math:`h_k` of dimensionless real numbers between 0 and 1.
"""
super().__init__()
self._magnitude = magnitude

@property
def terms(self) -> list[Hamiltonian]:
return [self]

@property
def magnitude(self) -> Field:
r"""Field: containing the global magnitude time series :math:`\Delta(t)`,
where time is measured in seconds (s) and values measured in rad/s)
and the local pattern :math:`h_k` of dimensionless real numbers between 0 and 1.
"""
return self._magnitude

@staticmethod
def from_lists(times: list[float], values: list[float], pattern: list[float]) -> ShiftingField:
"""Get the shifting field from a set of time points, values and pattern
Args:
times (list[float]): The time points of the shifting field
values (list[float]): The values of the shifting field
pattern (list[float]): The pattern of the shifting field
Raises:
ValueError: If the length of times and values differs.
Returns:
ShiftingField: The shifting field obtained
"""
if len(times) != len(values):
raise ValueError("The length of the times and values lists must be equal.")

magnitude = TimeSeries()
for t, v in zip(times, values):
magnitude.put(t, v)
shift = ShiftingField(Field(magnitude, Pattern(pattern)))

return shift

def stitch(
self, other: ShiftingField, boundary: StitchBoundaryCondition = StitchBoundaryCondition.MEAN
) -> ShiftingField:
"""Stitches two shifting fields based on TimeSeries.stitch method.
The time points of the second ShiftingField are shifted such that the first time point of
the second ShiftingField coincides with the last time point of the first ShiftingField.
The boundary point value is handled according to StitchBoundaryCondition argument value.
Args:
other (ShiftingField): The second shifting field to be stitched with.
boundary (StitchBoundaryCondition): {"mean", "left", "right"}. Boundary point handler.
Possible options are
- "mean" - take the average of the boundary value points of the first
and the second time series.
- "left" - use the last value from the left time series as the boundary point.
- "right" - use the first value from the right time series as the boundary point.
Raises:
ValueError: The ShiftingField patterns differ.
Returns:
ShiftingField: The stitched ShiftingField object.
Example (StitchBoundaryCondition.MEAN):
::
time_series_1 = TimeSeries.from_lists(times=[0, 0.1], values=[1, 2])
time_series_2 = TimeSeries.from_lists(times=[0.2, 0.4], values=[4, 5])
stitch_ts = time_series_1.stitch(time_series_2, boundary=StitchBoundaryCondition.MEAN)
Result:
stitch_ts.times() = [0, 0.1, 0.3]
stitch_ts.values() = [1, 3, 5]
Example (StitchBoundaryCondition.LEFT):
::
stitch_ts = time_series_1.stitch(time_series_2, boundary=StitchBoundaryCondition.LEFT)
Result:
stitch_ts.times() = [0, 0.1, 0.3]
stitch_ts.values() = [1, 2, 5]
Example (StitchBoundaryCondition.RIGHT):
::
stitch_ts = time_series_1.stitch(time_series_2, boundary=StitchBoundaryCondition.RIGHT)
Result:
stitch_ts.times() = [0, 0.1, 0.3]
stitch_ts.values() = [1, 4, 5]
"""
if not (self.magnitude.pattern.series == other.magnitude.pattern.series):
raise ValueError("The ShiftingField pattern for both fields must be equal.")

new_ts = self.magnitude.time_series.stitch(other.magnitude.time_series, boundary)
return ShiftingField(Field(new_ts, self.magnitude.pattern))

def discretize(self, properties: DiscretizationProperties) -> ShiftingField:
"""Creates a discretized version of the ShiftingField.
Args:
properties (DiscretizationProperties): Capabilities of a device that represent the
resolution with which the device can implement the parameters.
Returns:
ShiftingField: A new discretized ShiftingField.
"""
shifting_parameters = properties.rydberg.rydbergLocal
discretized_magnitude = self.magnitude.discretize(
time_resolution=shifting_parameters.timeResolution,
value_resolution=shifting_parameters.commonDetuningResolution,
pattern_resolution=shifting_parameters.localDetuningResolution,
)
return ShiftingField(discretized_magnitude)
# The class `ShiftingField` is deprecated. Please use `LocalDetuning` instead.
# This file and class will be removed in a future version.
# We are retaining this now to avoid breaking backwards compatibility for users already
# utilizing this nomenclature.
ShiftingField = LocalDetuning
Loading

0 comments on commit 1e8d67f

Please sign in to comment.