-
Notifications
You must be signed in to change notification settings - Fork 1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Abstract Engine Interface (#4644)
The first four classes define abstract base classes (ABC) for the four main types of the Engine: AbstractJob, AbstractProgram, AbstractProcessor, AbstractEngine These classes closely model the currect EngineJob, EngineProgram, EngineProcessor, and Engine classes with the methods turned into abstract models. This PR is part 1 of a 3 three part series.
- Loading branch information
1 parent
3af7e89
commit 1d7436f
Showing
5 changed files
with
1,064 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
# Copyright 2021 The Cirq Developers | ||
# | ||
# 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 | ||
# | ||
# https://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. | ||
# coverage: ignore | ||
"""Interface for Engine objects. | ||
This class is an abstract class which all Engine implementations | ||
(production API or locally simulated) should follow. | ||
""" | ||
|
||
import abc | ||
import datetime | ||
from typing import Dict, List, Optional, Sequence, Set, Union | ||
|
||
import cirq | ||
from cirq_google.engine import abstract_job, abstract_program, abstract_processor | ||
from cirq_google.engine.client import quantum | ||
from cirq_google.serialization import Serializer | ||
|
||
VALID_DATE_TYPE = Union[datetime.datetime, datetime.date] | ||
|
||
|
||
class AbstractEngine(abc.ABC): | ||
"""An abstract object representing a collection of quantum processors. | ||
Each processor within the AbstractEngine can be referenced by a string | ||
identifier through the get_processor interface. | ||
The Engine interface also includes convenience methods to access | ||
programs, jobs, and sampler. | ||
This is an abstract interface and inheritors must implement the abstract methods. | ||
""" | ||
|
||
@abc.abstractmethod | ||
def get_program(self, program_id: str) -> abstract_program.AbstractProgram: | ||
"""Returns an existing AbstractProgram given an identifier. | ||
Args: | ||
program_id: Unique ID of the program. | ||
Returns: | ||
An AbstractProgram object for the program. | ||
""" | ||
|
||
@abc.abstractmethod | ||
def list_programs( | ||
self, | ||
created_before: Optional[VALID_DATE_TYPE] = None, | ||
created_after: Optional[VALID_DATE_TYPE] = None, | ||
has_labels: Optional[Dict[str, str]] = None, | ||
) -> List[abstract_program.AbstractProgram]: | ||
"""Returns a list of previously executed quantum programs. | ||
Args: | ||
created_after: retrieve programs that were created after this date | ||
or time. | ||
created_before: retrieve programs that were created before this date | ||
or time. | ||
has_labels: retrieve programs that have labels on them specified by | ||
this dict. If the value is set to `*`, programs having the label | ||
regardless of the label value will be returned. For example, to | ||
query programs that have the shape label and have the color | ||
label with value red can be queried using | ||
`{'color': 'red', 'shape': '*'}` | ||
""" | ||
|
||
@abc.abstractmethod | ||
def list_jobs( | ||
self, | ||
created_before: Optional[VALID_DATE_TYPE] = None, | ||
created_after: Optional[VALID_DATE_TYPE] = None, | ||
has_labels: Optional[Dict[str, str]] = None, | ||
execution_states: Optional[Set[quantum.enums.ExecutionStatus.State]] = None, | ||
) -> List[abstract_job.AbstractJob]: | ||
"""Returns the list of jobs that match the specified criteria. | ||
All historical jobs can be retrieved using this method and filtering | ||
options are available too, to narrow down the search based on: | ||
* creation time | ||
* job labels | ||
* execution states | ||
Args: | ||
created_after: retrieve jobs that were created after this date | ||
or time. | ||
created_before: retrieve jobs that were created before this date | ||
or time. | ||
has_labels: retrieve jobs that have labels on them specified by | ||
this dict. If the value is set to `*`, jobs having the label | ||
regardless of the label value will be returned. For example, to | ||
query programs that have the shape label and have the color | ||
label with value red can be queried using | ||
{'color': 'red', 'shape':'*'} | ||
execution_states: retrieve jobs that have an execution state that | ||
is contained in `execution_states`. See | ||
`quantum.enums.ExecutionStatus.State` enum for accepted values. | ||
""" | ||
|
||
@abc.abstractmethod | ||
def list_processors(self) -> Sequence[abstract_processor.AbstractProcessor]: | ||
"""Returns all processors in this engine visible to the user.""" | ||
|
||
@abc.abstractmethod | ||
def get_processor(self, processor_id: str) -> abstract_processor.AbstractProcessor: | ||
"""Returns an EngineProcessor for a Quantum Engine processor. | ||
Args: | ||
processor_id: The processor unique identifier. | ||
Returns: | ||
A EngineProcessor for the processor. | ||
""" | ||
|
||
@abc.abstractmethod | ||
def get_sampler( | ||
self, processor_id: Union[str, List[str]], gate_set: Serializer | ||
) -> cirq.Sampler: | ||
"""Returns a sampler backed by the engine. | ||
Args: | ||
processor_id: String identifier, or list of string identifiers, | ||
determining which processors may be used when sampling. | ||
gate_set: Determines how to serialize circuits when requesting | ||
samples. | ||
""" |
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,202 @@ | ||
# Copyright 2021 The Cirq Developers | ||
# | ||
# 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 | ||
# | ||
# https://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. | ||
"""A helper for jobs that have been created on the Quantum Engine.""" | ||
|
||
import abc | ||
from typing import Dict, Iterator, List, Optional, overload, Tuple, TYPE_CHECKING | ||
|
||
import cirq | ||
import cirq_google.engine.client.quantum as quantum | ||
|
||
|
||
if TYPE_CHECKING: | ||
import datetime | ||
import cirq_google.engine.calibration as calibration | ||
import cirq_google.engine.calibration_result as calibration_result | ||
import cirq_google.engine.abstract_engine as abstract_engine | ||
import cirq_google.engine.abstract_processor as abstract_processor | ||
import cirq_google.engine.abstract_program as abstract_program | ||
|
||
|
||
class AbstractJob(abc.ABC): | ||
"""An abstract object representing a quantum job execution. | ||
This represents the state of a possibly asynchronous Job being | ||
executed by a simulator, the cloud Engine service, or other means. | ||
This is an abstract interface that implementers of services or mocks | ||
should implement. It generally represents the execution of a circuit | ||
using a set of parameters called a sweep. It can also represent the | ||
execution of a batch job (a list of circuit/sweep pairs) or the | ||
execution of a calibration request. | ||
This job may be in a variety of states. It may be scheduling, it may be | ||
executing on a machine, or it may have entered a terminal state | ||
(either succeeding or failing). | ||
`AbstractJob`s can be iterated over, returning `Result`s. These | ||
`Result`s can also be accessed by index. Note that this will block | ||
until the results are returned. | ||
""" | ||
|
||
@abc.abstractmethod | ||
def engine(self) -> 'abstract_engine.AbstractEngine': | ||
"""Returns the parent `AbstractEngine` object.""" | ||
|
||
@abc.abstractmethod | ||
def id(self) -> str: | ||
"""Returns the id of this job.""" | ||
|
||
@abc.abstractmethod | ||
def program(self) -> 'abstract_program.AbstractProgram': | ||
"""Returns the parent `AbstractProgram`object.""" | ||
|
||
@abc.abstractmethod | ||
def create_time(self) -> 'datetime.datetime': | ||
"""Returns when the job was created.""" | ||
|
||
@abc.abstractmethod | ||
def update_time(self) -> 'datetime.datetime': | ||
"""Returns when the job was last updated.""" | ||
|
||
@abc.abstractmethod | ||
def description(self) -> str: | ||
"""Returns the description of the job.""" | ||
|
||
@abc.abstractmethod | ||
def set_description(self, description: str) -> 'AbstractJob': | ||
"""Sets the description of the job. | ||
Params: | ||
description: The new description for the job. | ||
Returns: | ||
This `AbstractJob`. | ||
""" | ||
|
||
@abc.abstractmethod | ||
def labels(self) -> Dict[str, str]: | ||
"""Returns the labels of the job.""" | ||
|
||
@abc.abstractmethod | ||
def set_labels(self, labels: Dict[str, str]) -> 'AbstractJob': | ||
"""Sets (overwriting) the labels for a previously created quantum job. | ||
Params: | ||
labels: The entire set of new job labels. | ||
Returns: | ||
This `AbstractJob`. | ||
""" | ||
|
||
@abc.abstractmethod | ||
def add_labels(self, labels: Dict[str, str]) -> 'AbstractJob': | ||
"""Adds new labels to a previously created quantum job. | ||
Params: | ||
labels: New labels to add to the existing job labels. | ||
Returns: | ||
This `AbstractJob`. | ||
""" | ||
|
||
@abc.abstractmethod | ||
def remove_labels(self, keys: List[str]) -> 'AbstractJob': | ||
"""Removes labels with given keys. | ||
Params: | ||
label_keys: Label keys to remove from the existing job labels. | ||
Returns: | ||
This `AbstractJob`. | ||
""" | ||
|
||
@abc.abstractmethod | ||
def processor_ids(self) -> List[str]: | ||
"""Returns the processor ids provided when the job was created.""" | ||
|
||
@abc.abstractmethod | ||
def execution_status(self) -> quantum.enums.ExecutionStatus.State: | ||
"""Return the execution status of the job.""" | ||
|
||
@abc.abstractmethod | ||
def failure(self) -> Optional[Tuple[str, str]]: | ||
"""Return failure code and message of the job if present.""" | ||
|
||
@abc.abstractmethod | ||
def get_repetitions_and_sweeps(self) -> Tuple[int, List[cirq.Sweep]]: | ||
"""Returns the repetitions and sweeps for the job. | ||
Returns: | ||
A tuple of the repetition count and list of sweeps. | ||
""" | ||
|
||
@abc.abstractmethod | ||
def get_processor(self) -> Optional['abstract_processor.AbstractProcessor']: | ||
"""Returns the AbstractProcessor for the processor the job is/was run on, | ||
if available, else None.""" | ||
|
||
@abc.abstractmethod | ||
def get_calibration(self) -> Optional['calibration.Calibration']: | ||
"""Returns the recorded calibration at the time when the job was run, if | ||
one was captured, else None.""" | ||
|
||
@abc.abstractmethod | ||
def cancel(self) -> Optional[bool]: | ||
"""Cancel the job.""" | ||
|
||
@abc.abstractmethod | ||
def delete(self) -> Optional[bool]: | ||
"""Deletes the job and result, if any.""" | ||
|
||
@abc.abstractmethod | ||
def batched_results(self) -> List[List[cirq.Result]]: | ||
"""Returns the job results, blocking until the job is complete. | ||
This method is intended for batched jobs. Instead of flattening | ||
results into a single list, this will return a List[Result] | ||
for each circuit in the batch. | ||
""" | ||
|
||
@abc.abstractmethod | ||
def results(self) -> List[cirq.Result]: | ||
"""Returns the job results, blocking until the job is complete.""" | ||
|
||
@abc.abstractmethod | ||
def calibration_results(self) -> List['calibration_result.CalibrationResult']: | ||
"""Returns the results of a run_calibration() call. | ||
This function will fail if any other type of results were returned. | ||
""" | ||
|
||
def __iter__(self) -> Iterator[cirq.Result]: | ||
return iter(self.results()) | ||
|
||
# pylint: disable=function-redefined | ||
@overload | ||
def __getitem__(self, item: int) -> cirq.Result: | ||
pass | ||
|
||
@overload | ||
def __getitem__(self, item: slice) -> List[cirq.Result]: | ||
pass | ||
|
||
def __getitem__(self, item): | ||
return self.results()[item] | ||
|
||
# pylint: enable=function-redefined | ||
|
||
def __len__(self) -> int: | ||
return len(self.results()) |
Oops, something went wrong.