Skip to content

Commit c2d120a

Browse files
authored
Release 0.4.0 (#42)
* fixing arithmetic issues. * bump patch version * Update pyproject.toml * export task probabilities (#39) * convert task_results IR into a list of probabilties conditioned on pre and post sequence. * changing datastructure to be more serializable. * exporting TaskProbabilities * adding task simulation. * adding TODOs * using filter instead of if statement. * updating python requirements to be at least 3.10 We will soon need to support pattern matching inside other QuEra projects, hence we will put a lower bound on the python requirements to work with this. * updating github actions for python version. * removing old setup files. * removing more old packaging files. * fixing version script for tagging. * update minor version indicating breaking change from dependency change.
1 parent 226efdf commit c2d120a

File tree

12 files changed

+187
-45
lines changed

12 files changed

+187
-45
lines changed

.github/workflows/CI.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ jobs:
3333
- name: python setup
3434
uses: actions/setup-python@v4
3535
with:
36-
python-version: '3.9'
36+
python-version: '3.10'
3737

3838
- name: Checking pip
3939
run: python -m ensurepip --upgrade

.github/workflows/pkg.yml

+3-3
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ jobs:
3131
- name: python setup
3232
uses: actions/setup-python@v4
3333
with:
34-
python-version: '3.9'
34+
python-version: '3.10'
3535

3636
- name: Checking pip
3737
run: python3 -m ensurepip --upgrade
@@ -52,8 +52,8 @@ jobs:
5252
password: ${{ secrets.PYPI_API_TOKEN }}
5353

5454
- name: Get Version
55-
run: echo VERSION="$(python3 setup.py --version)" >> $GITHUB_ENV
56-
55+
run: echo VERSION="$(python3 -c "import pkg_resources; print(pkg_resources.get_distribution('quera-ahs-utils').version)")" >> $GITHUB_ENV
56+
5757
- name: Tag Release
5858
uses: softprops/action-gh-release@v1
5959
with:

pyproject.toml

+14-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "quera-ahs-utils"
7-
version = "0.3.2"
7+
version = "0.4.0"
88
authors = [
99
{ name="Phillip Weinberg", email="[email protected]" },
1010
{ name="John Long", email="[email protected]" }
@@ -15,12 +15,23 @@ maintainers = [
1515
]
1616
description = "Various tools to interact with Braket Analog Hamiltonian Computing"
1717
readme = "README.md"
18-
requires-python = ">=3.7"
18+
requires-python = ">=3.10"
1919
classifiers = [
2020
"Programming Language :: Python :: 3",
2121
"Operating System :: OS Independent",
2222
]
23+
dependencies = [
24+
"amazon-braket-sdk",
25+
"networkx",
26+
"numpy",
27+
"scipy",
28+
"matplotlib",
29+
"pydantic",
30+
]
2331

2432
[project.urls]
2533
"Homepage" = "https://github.com/QuEraComputing/quera-ahs-utils"
26-
"Bug Tracker" = "https://github.com/QuEraComputing/quera-ahs-utils/issues"
34+
"Bug Tracker" = "https://github.com/QuEraComputing/quera-ahs-utils/issues"
35+
36+
[tool.setuptools.packages.find]
37+
where = ["src"]

requirements.txt

-6
This file was deleted.

setup.cfg

-22
This file was deleted.

setup.py

-5
This file was deleted.

src/quera_ahs_utils/__init__.py

Whitespace-only changes.

src/quera_ahs_utils/_version.py

-1
This file was deleted.

src/quera_ahs_utils/drive.py

+87-3
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ def get_shift(times: List[float], values: List[float], pattern: List[float]) ->
142142
return shift
143143

144144

145-
def get_time_series_value(time_series: TimeSeries, time: float, piecewise_constant: bool = False) -> float:
145+
def get_time_series_value(series: Union[TimeSeries,Field], time: float, piecewise_constant: bool = False) -> float:
146146
"""obtain value of a time series at a specific time
147147
148148
Args:
@@ -154,8 +154,12 @@ def get_time_series_value(time_series: TimeSeries, time: float, piecewise_consta
154154
Returns:
155155
float: the resulting sampled point.
156156
"""
157-
times = time_series.times()
158-
values = time_series.values()
157+
if isinstance(series, TimeSeries):
158+
times = series.times()
159+
values = series.values()
160+
elif isinstance(series, Field):
161+
times = series.time_series.times()
162+
values = series.time_series.values()
159163

160164
if piecewise_constant:
161165
index = max(0, min(len(times) - 1, np.searchsorted(times, time, side="right") - 1))
@@ -408,3 +412,83 @@ def adiabatic_drive(
408412
detuning=time_series(times,detunings),
409413
phase=time_series([0,times[-1]],[0, 0])
410414
)
415+
416+
417+
def local_detuning_state_prep(register_state: List[int], local_detuning_max: float=150.0e6) -> Tuple[DrivingField, ShiftingField]:
418+
"""Generate the DrivingField and ShiftingField required to use local detuning to prepare the register in a product state.
419+
420+
Args:
421+
register_state (List[int]): The product state you would like to prepare
422+
local_detuning_max (float, optional): The value of local detuning to apply to atoms which NOT to excit. Defaults to 150.0e6.
423+
424+
Raises:
425+
ValueError: register_state must be a list of integers with values 0 or 1.
426+
427+
Returns:
428+
Tuple[DrivingField, ShiftingField]: the driving and shifting fields respectively that contains the pulses for the state preparation.
429+
"""
430+
431+
pattern = []
432+
for state in register_state:
433+
if state == 0:
434+
pattern.append(1.0)
435+
elif state == 1:
436+
pattern.append(0.0)
437+
else:
438+
raise ValueError("`register_state` must be a list of integers with values 0 or 1 representing the ground and rydberg states respectively.")
439+
440+
# initial ramp up of local detuning
441+
ramp_up = time_series([0.0,0.07e-6],[0.0,local_detuning_max])
442+
shifting_field_start = ShiftingField(
443+
Field(
444+
time_series=ramp_up,
445+
pattern=Pattern(pattern)
446+
)
447+
)
448+
449+
driving_field_start = DrivingField(
450+
amplitude=constant_time_series(ramp_up, 0.0),
451+
phase=constant_time_series(ramp_up, 0.0),
452+
detuning=constant_time_series(ramp_up, 0.0)
453+
)
454+
455+
# resonant pi/2 pulse
456+
amplitude_max = 14.28e6 # these parameters have a
457+
amplitude = time_series(
458+
times = [0.0, 0.05e-6, 0.11e-6, 0.16e-6],
459+
values = [0.0,amplitude_max, amplitude_max, 0.0]
460+
)
461+
462+
driving_field_middle = DrivingField(
463+
amplitude=amplitude,
464+
phase=constant_time_series(amplitude, 0.0),
465+
detuning = constant_time_series(amplitude, 0.0)
466+
)
467+
468+
shifting_field_middle = ShiftingField(
469+
Field(
470+
time_series=constant_time_series(amplitude,local_detuning_max),
471+
pattern=Pattern(pattern)
472+
)
473+
)
474+
475+
# ramp down of local detuning
476+
477+
ramp_down = time_series([0.0,0.07e-6],[local_detuning_max,0.0])
478+
shifting_field_end = ShiftingField(
479+
Field(
480+
time_series=ramp_down,
481+
pattern=Pattern(pattern)
482+
)
483+
)
484+
485+
driving_field_end = DrivingField(
486+
amplitude=constant_time_series(ramp_down, 0.0),
487+
phase=constant_time_series(ramp_down, 0.0),
488+
detuning=constant_time_series(ramp_down, 0.0)
489+
)
490+
491+
total_shifting_field=concatenate_shift_list([shifting_field_start, shifting_field_middle, shifting_field_end])
492+
total_driving_field=concatenate_drive_list([driving_field_start, driving_field_middle, driving_field_end])
493+
494+
return total_driving_field, total_shifting_field

src/quera_ahs_utils/quera_ir/__init__.py

Whitespace-only changes.

src/quera_ahs_utils/quera_ir/task_results.py

+80-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
from enum import Enum
22
from pydantic import BaseModel, conlist, conint
3+
from typing import Callable, Optional, List, Tuple
4+
import numpy as np
35

46
__all__ = [
5-
"QuEraTaskResults",
7+
"QuEraTaskResults",
8+
"TaskProbabilities"
69
]
710

11+
# TODO: add version to these models.
12+
813
class QuEraShotStatusCode(str, Enum):
914
Completed = "Completed"
1015
MissingPreSequence = "MissingPreSequence"
@@ -23,8 +28,82 @@ class QuEraShotResult(BaseModel):
2328
pre_sequence: conlist(conint(ge=0, le=1), min_items=0) = []
2429
post_sequence: conlist(conint(ge=0, le=1), min_items=0) = []
2530

31+
class TaskProbabilities(BaseModel):
32+
probabilities: List[Tuple[Tuple[str,str],float]]
33+
34+
def simulate_task_results(self, shots = 1) -> 'QuEraTaskResults':
35+
bit_strings, probabilities = zip(*self.probabilities)
36+
37+
indices = np.random.choice(
38+
len(probabilities),
39+
p=probabilities,
40+
size=shots
41+
)
42+
shot_outputs = []
43+
for index in indices:
44+
pre_string, post_string = bit_strings[index]
45+
pre_sequence = [int(bit) for bit in pre_string]
46+
post_sequence = [int(bit) for bit in post_string]
47+
48+
shot_outputs.append(
49+
QuEraShotResult(
50+
shot_status = QuEraShotStatusCode.Completed,
51+
pre_sequence = pre_sequence,
52+
post_sequence = post_sequence
53+
)
54+
)
55+
56+
return QuEraTaskResults(
57+
task_status=QuEraTaskStatusCode.Completed,
58+
shot_outputs=shot_outputs
59+
)
60+
2661
class QuEraTaskResults(BaseModel):
2762
task_status: QuEraTaskStatusCode = QuEraTaskStatusCode.Failed
2863
shot_outputs: conlist(QuEraShotResult, min_items=0) = []
2964

65+
def export_as_probabilties(self, post_process=False) -> TaskProbabilities:
66+
"""converts from shot results to probabilities
3067
68+
Returns:
69+
TaskProbabilities: The task results as probabilties
70+
"""
71+
probabilities = dict()
72+
n = 0
73+
for shot_result in self.shot_outputs:
74+
if any(bit==0 for bit in shot_result.pre_sequence):
75+
continue
76+
77+
pre_sequence_str = "".join(
78+
str(bit) for bit in shot_result.pre_sequence
79+
)
80+
81+
post_sequence_str = "".join(
82+
str(bit) for bit in shot_result.post_sequence
83+
)
84+
85+
configuration = (pre_sequence_str,post_sequence_str)
86+
# iterative average
87+
probabilities[configuration] = \
88+
((n + 1.0) * probabilities.get(configuration, 0) + 1.0)/n
89+
90+
n += 1
91+
92+
return TaskProbabilities(list(probabilities.items()))
93+
94+
def post_process(self, keep_shot_result: Optional[Callable] = None, args = ()) -> 'QuEraTaskResults':
95+
96+
if keep_shot_result == None:
97+
filter_func = \
98+
lambda shot_result: \
99+
all(bit==1 for bit in shot_result.pre_sequence)
100+
else:
101+
filter_func = lambda shot_result: \
102+
keep_shot_result(shot_result, *args)
103+
104+
return QuEraTaskResults(
105+
task_status=self.task_status,
106+
shot_outputs=list(
107+
filter(filter_func, self.shot_outputs)
108+
)
109+
)

src/quera_ahs_utils/quera_ir/task_specification.py

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
"QuEraTaskSpecification"
1010
]
1111

12+
# TODO: add version to these models.
13+
1214
FloatType = Union[Decimal, float]
1315

1416
def discretize_list(list_of_values: list, resolution: FloatType):

0 commit comments

Comments
 (0)