Skip to content

Commit

Permalink
Capabilities unit convert api (#854)
Browse files Browse the repository at this point in the history
* adding converter from braket capabilities to quera.

* adding method to scale units of capabilities from method call.

* ficing bug in conversion.

* switching to local capabilities when there is a client error.

* changing script for html coverage generation

* switching to base Exception for Boto3 error handling.
  • Loading branch information
weinbe58 authored Jan 5, 2024
1 parent c95ce07 commit e525da6
Show file tree
Hide file tree
Showing 5 changed files with 171 additions and 119 deletions.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ build = {cmd = "pdm build"}
publish = {composite = ["build", "upload"]}
test = {shell = "git clean -f && pytest tests"}
coverage = {shell = "git clean -f && coverage run -m pytest tests/ && coverage xml && coverage report"}
coverage-html = {shell = "git clean -f && coverage run -m pytest tests/ && coverage html && open htmlcov/index.html"}
coverage-html = {shell = "git clean -f && coverage run -m pytest -x -vv tests/ && coverage html && open htmlcov/index.html"}
doc = {cmd = "mkdocs serve"}
doc_build = {cmd = "mkdocs build"}
doc_deploy = {cmd = "pdm mike deploy --push --update-aliases dev"}
Expand Down
118 changes: 1 addition & 117 deletions src/bloqade/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,125 +26,9 @@ def get_capabilities() -> "QuEraCapabilities":
"""

from bloqade.submission.capabilities import get_capabilities
import bloqade.submission.ir.capabilities as cp

capabilities_schema = get_capabilities()

capabilities = capabilities_schema.capabilities

# manually convert to units
return cp.QuEraCapabilities(
version=capabilities_schema.version,
capabilities=cp.DeviceCapabilities(
task=cp.TaskCapabilities(
number_shots_max=capabilities.task.number_shots_max,
number_shots_min=capabilities.task.number_shots_min,
),
lattice=cp.LatticeCapabilities(
number_qubits_max=capabilities.lattice.number_qubits_max,
area=cp.LatticeAreaCapabilities(
width=(capabilities.lattice.area.width * Decimal("1e6")), # m
height=(capabilities.lattice.area.height * Decimal("1e6")), # m
),
geometry=cp.LatticeGeometryCapabilities(
number_sites_max=capabilities.lattice.geometry.number_sites_max,
spacing_radial_min=(
capabilities.lattice.geometry.spacing_radial_min
* Decimal("1e6")
), # m
spacing_vertical_min=(
capabilities.lattice.geometry.spacing_vertical_min
* Decimal("1e6")
), # m
position_resolution=(
capabilities.lattice.geometry.position_resolution
* Decimal("1e6")
), # m
),
),
rydberg=cp.RydbergCapabilities(
c6_coefficient=capabilities.rydberg.c6_coefficient
* Decimal("1e30"), # rad * m^6 / s
global_=cp.RydbergGlobalCapabilities(
phase_max=(capabilities.rydberg.global_.phase_max), # rad
phase_min=(capabilities.rydberg.global_.phase_min), # rad
phase_resolution=(
capabilities.rydberg.global_.phase_resolution
), # rad
rabi_frequency_max=(
capabilities.rydberg.global_.rabi_frequency_max / Decimal("1e6")
), # rad / s
rabi_frequency_min=(
capabilities.rydberg.global_.rabi_frequency_min / Decimal("1e6")
), # rad / s
rabi_frequency_resolution=(
capabilities.rydberg.global_.rabi_frequency_resolution
/ Decimal("1e6")
), # rad / s
rabi_frequency_slew_rate_max=(
capabilities.rydberg.global_.rabi_frequency_slew_rate_max
/ Decimal("1e6") ** 2
), # rad / s^2
detuning_max=(
capabilities.rydberg.global_.detuning_max / Decimal("1e6")
), # rad / s
detuning_min=(
capabilities.rydberg.global_.detuning_min / Decimal("1e6")
), # rad / s
detuning_resolution=(
capabilities.rydberg.global_.detuning_resolution
/ Decimal("1e6")
), # rad / s
detuning_slew_rate_max=(
capabilities.rydberg.global_.detuning_slew_rate_max
/ Decimal("1e6") ** 2
), # rad / s^2
time_min=(
capabilities.rydberg.global_.time_min * Decimal("1e6")
), # s
time_max=(
capabilities.rydberg.global_.time_max * Decimal("1e6")
), # s
time_resolution=(
capabilities.rydberg.global_.time_resolution * Decimal("1e6")
), # s
time_delta_min=(
capabilities.rydberg.global_.time_delta_min * Decimal("1e6")
), # s
),
local=cp.RydbergLocalCapabilities(
number_local_detuning_sites=(
capabilities.rydberg.local.number_local_detuning_sites
),
site_coefficient_max=(
capabilities.rydberg.local.site_coefficient_max
),
site_coefficient_min=(
capabilities.rydberg.local.site_coefficient_min
),
spacing_radial_min=(
capabilities.rydberg.local.spacing_radial_min * Decimal("1e6")
), # rad / s
detuning_min=(
capabilities.rydberg.local.detuning_min / Decimal("1e6")
), # rad / s
detuning_max=(
capabilities.rydberg.local.detuning_max / Decimal("1e6")
), # rad / s
detuning_slew_rate_max=(
capabilities.rydberg.local.detuning_slew_rate_max
/ Decimal("1e6") ** 2
), # rad / s^2
time_delta_min=(
capabilities.rydberg.local.time_delta_min * Decimal("1e6")
), # s
time_resolution=(
capabilities.rydberg.local.time_resolution * Decimal("1e6")
), # s
),
),
),
)
return get_capabilities().scale_units(Decimal("1e6"), Decimal("1e-6"))


@beartype
Expand Down
16 changes: 16 additions & 0 deletions src/bloqade/submission/braket.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import warnings
from bloqade.submission.base import SubmissionBackend
from bloqade.submission.ir.braket import (
from_braket_task_results,
from_braket_status_codes,
to_braket_task,
to_quera_capabilities,
)
from bloqade.submission.ir.capabilities import QuEraCapabilities
from bloqade.submission.ir.task_results import (
QuEraTaskStatusCode,
QuEraTaskResults,
Expand All @@ -28,6 +31,19 @@ def device(self) -> AwsDevice:

return self._device

def get_capabilities(self) -> QuEraCapabilities:
from botocore.exceptions import BotoCoreError

try:
to_quera_capabilities(self.device.properties.paradigm)
except BotoCoreError:
warnings.warn(
"Could not retrieve device capabilities from braket API. "
"Using local capabiltiiies file for Aquila."
)

return super().get_capabilities()

def submit_task(self, task_ir: QuEraTaskSpecification) -> str:
shots, ahs_program = to_braket_task(task_ir)
task = self.device.run(ahs_program, shots=shots)
Expand Down
50 changes: 50 additions & 0 deletions src/bloqade/submission/ir/braket.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,3 +122,53 @@ def from_braket_status_codes(braket_message: str) -> QuEraTaskStatusCode:
return QuEraTaskStatusCode.Enqueued
else:
return QuEraTaskStatusCode(braket_message.lower().capitalize())


def to_quera_capabilities(paradigm):
import bloqade.submission.ir.capabilities as cp

rydberg_global = paradigm.rydberg.rydbergGlobal

return cp.QuEraCapabilities(
version=paradigm.braketSchemaHeader.version,
capabilities=cp.DeviceCapabilities(
task=cp.TaskCapabilities(
number_shots_min=1,
number_shots_max=1000,
),
lattice=cp.LatticeCapabilities(
number_qubits_max=paradigm.qubitCount,
geometry=cp.LatticeGeometryCapabilities(
spacing_radial_min=paradigm.lattice.geometry.spacingRadialMin,
spacing_vertical_min=paradigm.lattice.geometry.spacingVerticalMin,
position_resolution=paradigm.lattice.geometry.positionResolution,
number_sites_max=paradigm.lattice.geometry.numberSitesMax,
),
area=cp.LatticeAreaCapabilities(
width=paradigm.lattice.area.width,
height=paradigm.lattice.area.height,
),
),
rydberg=cp.RydbergCapabilities(
c6_coefficient=paradigm.rydberg.c6Coefficient,
global_=cp.RydbergGlobalCapabilities(
rabi_frequency_max=rydberg_global.rabiFrequencyRange[0],
rabi_frequency_min=rydberg_global.rabiFrequencyRange[1],
rabi_frequency_resolution=rydberg_global.rabiFrequencyResolution,
rabi_frequency_slew_rate_max=rydberg_global.rabiFrequencySlewRateMax,
detuning_max=rydberg_global.detuningRange[0],
detuning_min=rydberg_global.detuningRange[1],
detuning_resolution=rydberg_global.detuningResolution,
detuning_slew_rate_max=rydberg_global.detuningSlewRateMax,
phase_min=rydberg_global.phaseRange[0],
phase_max=rydberg_global.phaseRange[1],
phase_resolution=rydberg_global.phaseResolution,
time_min=rydberg_global.timeMin,
time_max=rydberg_global.timeMax,
time_resolution=rydberg_global.timeResolution,
time_delta_min=rydberg_global.timeDeltaMin,
),
local=None,
),
),
)
104 changes: 103 additions & 1 deletion src/bloqade/submission/ir/capabilities.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from pydantic import BaseModel
from decimal import Decimal
from beartype.typing import Optional
from beartype import beartype

__all__ = ["QuEraCapabilities"]

Expand All @@ -21,6 +23,29 @@ class RydbergGlobalCapabilities(BaseModel):
time_resolution: Decimal
time_delta_min: Decimal

@beartype
def scale_units(
self, _: Decimal, energy_scale: Decimal
) -> "RydbergGlobalCapabilities":
return RydbergGlobalCapabilities(
rabi_frequency_min=self.rabi_frequency_min * energy_scale,
rabi_frequency_max=self.rabi_frequency_max * energy_scale,
rabi_frequency_resolution=self.rabi_frequency_resolution * energy_scale,
rabi_frequency_slew_rate_max=self.rabi_frequency_slew_rate_max
* energy_scale**2,
detuning_min=self.detuning_min * energy_scale,
detuning_max=self.detuning_max * energy_scale,
detuning_resolution=self.detuning_resolution * energy_scale,
detuning_slew_rate_max=self.detuning_slew_rate_max * energy_scale**2,
phase_min=self.phase_min,
phase_max=self.phase_max,
phase_resolution=self.phase_resolution,
time_min=self.time_min / energy_scale,
time_max=self.time_max / energy_scale,
time_resolution=self.time_resolution / energy_scale,
time_delta_min=self.time_delta_min / energy_scale,
)


class RydbergLocalCapabilities(BaseModel):
detuning_min: Decimal
Expand All @@ -33,46 +58,123 @@ class RydbergLocalCapabilities(BaseModel):
time_resolution: Decimal
time_delta_min: Decimal

@beartype
def scale_units(self, distance_scale, energy_scale) -> "RydbergLocalCapabilities":
return RydbergLocalCapabilities(
detuning_min=self.detuning_min * energy_scale,
detuning_max=self.detuning_max * energy_scale,
detuning_slew_rate_max=self.detuning_slew_rate_max * energy_scale**2,
site_coefficient_min=self.site_coefficient_min,
site_coefficient_max=self.site_coefficient_max,
number_local_detuning_sites=self.number_local_detuning_sites,
spacing_radial_min=self.spacing_radial_min * distance_scale,
time_resolution=self.time_resolution / energy_scale,
time_delta_min=self.time_delta_min / energy_scale,
)


class RydbergCapabilities(BaseModel):
c6_coefficient: Decimal
global_: RydbergGlobalCapabilities
local: RydbergLocalCapabilities
local: Optional[RydbergLocalCapabilities]

class Config:
allow_population_by_field_name = True
fields = {"global_": "global"}

@beartype
def scale_units(self, distance_scale, energy_scale) -> "RydbergCapabilities":
return RydbergCapabilities(
c6_coefficient=self.c6_coefficient * energy_scale * distance_scale**6,
global_=self.global_.scale_units(distance_scale, energy_scale),
local=self.local.scale_units(distance_scale, energy_scale),
)


class LatticeGeometryCapabilities(BaseModel):
spacing_radial_min: Decimal
spacing_vertical_min: Decimal
position_resolution: Decimal
number_sites_max: int

@beartype
def scale_units(
self, distance_scale: Decimal, _: Decimal
) -> "LatticeGeometryCapabilities":
return LatticeGeometryCapabilities(
spacing_radial_min=self.spacing_radial_min * distance_scale,
spacing_vertical_min=self.spacing_vertical_min * distance_scale,
position_resolution=self.position_resolution * distance_scale,
number_sites_max=self.number_sites_max,
)


class LatticeAreaCapabilities(BaseModel):
width: Decimal
height: Decimal

@beartype
def scale_units(
self, distance_scale: Decimal, _: Decimal
) -> "LatticeAreaCapabilities":
return LatticeAreaCapabilities(
width=self.width * distance_scale,
height=self.height * distance_scale,
)


class LatticeCapabilities(BaseModel):
number_qubits_max: int
area: LatticeAreaCapabilities
geometry: LatticeGeometryCapabilities

def scale_units(
self, distance_scale: Decimal, energy_scale: Decimal
) -> "LatticeCapabilities":
return LatticeCapabilities(
number_qubits_max=self.number_qubits_max,
area=self.area.scale_units(distance_scale, energy_scale),
geometry=self.geometry.scale_units(distance_scale, energy_scale),
)


class TaskCapabilities(BaseModel):
number_shots_min: int
number_shots_max: int

@beartype
def scale_units(self, _: Decimal, __: Decimal) -> "TaskCapabilities":
return TaskCapabilities(
number_shots_min=self.number_shots_min,
number_shots_max=self.number_shots_max,
)


class DeviceCapabilities(BaseModel):
task: TaskCapabilities
lattice: LatticeCapabilities
rydberg: RydbergCapabilities

@beartype
def scale_units(
self, distance_scale: Decimal, energy_scale: Decimal
) -> "DeviceCapabilities":
return DeviceCapabilities(
task=self.task.scale_units(distance_scale, energy_scale),
lattice=self.lattice.scale_units(distance_scale, energy_scale),
rydberg=self.rydberg.scale_units(distance_scale, energy_scale),
)


class QuEraCapabilities(BaseModel):
version: str
capabilities: DeviceCapabilities

@beartype
def scale_units(
self, distance_scale: Decimal, energy_scale: Decimal
) -> "QuEraCapabilities":
return QuEraCapabilities(
version=self.version,
capabilities=self.capabilities.scale_units(distance_scale, energy_scale),
)

0 comments on commit e525da6

Please sign in to comment.