-
Notifications
You must be signed in to change notification settings - Fork 188
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add connection to device spec API (#429)
* Implement a get_device method * Return DeviceSpec fro get_device * Split get_device method * Add devicespec class * Fix formatting * write out docstrings * add to documentation * linting * update changelog * add PR link * done * blacking * undo weird string concatenation * Fix minor error * Add tests * Fix failing test * adding tests * add initialization test * Add kwargs and return to docstring * Update .github/CHANGELOG.md Co-authored-by: antalszava <antalszava@gmail.com> * suggested changes * Update strawberryfields/api/devicespec.py Co-authored-by: Theodor <theodor@xanadu.ai> * suggested changes Co-authored-by: Josh Izaac <josh146@gmail.com> Co-authored-by: antalszava <antalszava@gmail.com>
- Loading branch information
1 parent
f77e879
commit e980b02
Showing
8 changed files
with
336 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
# Copyright 2020 Xanadu Quantum Technologies Inc. | ||
|
||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
|
||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
|
||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License 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. | ||
""" | ||
This module contains a class that represents the specifications of | ||
a device available via the API. | ||
""" | ||
from collections.abc import Sequence | ||
|
||
import strawberryfields as sf | ||
import blackbird | ||
|
||
from strawberryfields.circuitspecs import Ranges | ||
|
||
|
||
class DeviceSpec: | ||
"""The specifications for a specific hardware device. | ||
Args: | ||
target (str): name of the target hardware device | ||
spec (dict): dictionary representing the raw device specification. | ||
This dictionary should contain the following key-value pairs: | ||
- layout (str): string containing the Blackbird circuit layout | ||
- modes (int): number of modes supported by the target | ||
- compiler (list): list of supported compilers | ||
- gate_parameters (dict): parameters for the circuit gates | ||
connection (strawberryfields.api.Connection): connection over which the | ||
job is managed | ||
""" | ||
|
||
def __init__(self, target, spec, connection): | ||
self._target = target | ||
self._connection = connection | ||
self._spec = spec | ||
|
||
@property | ||
def target(self): | ||
"""str: The name of the target hardware device.""" | ||
return self._target | ||
|
||
@property | ||
def layout(self): | ||
"""str: Returns a string containing the Blackbird circuit layout.""" | ||
return self._spec["layout"] | ||
|
||
@property | ||
def modes(self): | ||
"""int: Number of modes supported by the device.""" | ||
return self._spec["modes"] | ||
|
||
@property | ||
def compiler(self): | ||
"""list[str]: A list of strings corresponding to Strawberry Fields compilers supported | ||
by the hardware device.""" | ||
return self._spec["compiler"] | ||
|
||
@property | ||
def gate_parameters(self): | ||
"""dict[str, strawberryfields.circuitspecs.Ranges]: A dictionary of gate parameters | ||
and allowed ranges. | ||
The parameter names correspond to those present in the Blackbird circuit layout. | ||
**Example** | ||
>>> spec.gate_parameters | ||
{'squeezing_amplitude_0': x=0, x=1, 'phase_0': x=0, 0≤x≤6.283185307179586} | ||
""" | ||
gate_parameters = dict() | ||
|
||
for gate_name, param_ranges in self._spec["gate_parameters"].items(): | ||
# convert gate parameter allowed ranges to Range objects | ||
range_list = [[i] if not isinstance(i, Sequence) else i for i in param_ranges] | ||
gate_parameters[gate_name] = Ranges(*range_list) | ||
|
||
return gate_parameters | ||
|
||
def create_program(self, **parameters): | ||
"""Create a Strawberry Fields program matching the low-level layout of the | ||
device. | ||
Gate arguments should be passed as keyword arguments, with names | ||
correspond to those present in the Blackbird circuit layout. Parameters not | ||
present will be assumed to have a value of 0. | ||
**Example** | ||
Device specifications can be retrieved from the API by using the | ||
:class:`~.Connection` class: | ||
>>> spec.create_program(squeezing_amplitude_0=0.43) | ||
<strawberryfields.program.Program at 0x7fd37e27ff50> | ||
Keyword Args: | ||
Supported parameter values for the specific device | ||
Returns: | ||
strawberryfields.program.Program: program compiled to the device | ||
""" | ||
bb = blackbird.loads(self.layout) | ||
|
||
# check that all provided parameters are valid | ||
for p, v in parameters.items(): | ||
if p in self.gate_parameters and v not in self.gate_parameters[p]: | ||
# parameter is present in the device specifications | ||
# but the user has provided a disallowed value | ||
raise ValueError( | ||
f"{p} has invalid value {v}. Only {self.gate_parameters[p]} allowed." | ||
) | ||
|
||
if p not in self.gate_parameters: | ||
raise ValueError(f"Parameter {p} not a valid parameter for this device") | ||
|
||
# determine parameter value if not provided | ||
extra_params = set(self.gate_parameters) - set(parameters) | ||
|
||
for p in extra_params: | ||
# Set parameter value as the first allowed | ||
# value in the gate parameters dictionary. | ||
parameters[p] = self.gate_parameters[p].ranges[0].x | ||
|
||
# evaluate the blackbird template | ||
bb = bb(**parameters) | ||
prog = sf.io.to_program(bb) | ||
return prog | ||
|
||
def refresh(self): | ||
"""Refreshes the device specifications""" | ||
self._spec = self._connection._get_device_dict(self.target) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.