Skip to content

Commit

Permalink
feat!: Use ExecutionOptions parameter to configure how jobs are sub…
Browse files Browse the repository at this point in the history
…mitted and retrieved from a QPU. This replaces the `use_gateway` flag on `QCSClient.load()` has been removed. (#1598)
  • Loading branch information
MarquessV authored Jul 7, 2023
1 parent 1aacd38 commit fc402d1
Show file tree
Hide file tree
Showing 9 changed files with 60 additions and 43 deletions.
28 changes: 14 additions & 14 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ rpcq = "^3.10.0"
pydantic = "^1.10.7"
networkx = ">=2.5"
importlib-metadata = { version = ">=3.7.3,<5", python = "<3.8" }
qcs-sdk-python = "0.9.1"
qcs-sdk-python = "0.10.0"
quil = "0.1.1"
tenacity = "^8.2.2"
types-python-dateutil = "^2.8.19"
Expand Down
2 changes: 2 additions & 0 deletions pyquil/api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"AbstractCompiler",
"BenchmarkConnection",
"EncryptedProgram",
"ExecutionOptions",
"get_qc",
"list_quantum_computers",
"local_forest_runtime",
Expand All @@ -40,6 +41,7 @@
]

from qcs_sdk import QCSClient
from qcs_sdk.qpu.api import ExecutionOptions

from pyquil.api._benchmark import BenchmarkConnection
from pyquil.api._compiler import (
Expand Down
9 changes: 4 additions & 5 deletions pyquil/api/_qam.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
##############################################################################
from abc import ABC, abstractmethod
from dataclasses import dataclass, field
from typing import Generic, Mapping, Optional, TypeVar, Sequence, Union
from typing import Any, Generic, Mapping, Optional, TypeVar, Sequence, Union

import numpy as np
from pyquil.api._abstract_compiler import QuantumExecutable
Expand Down Expand Up @@ -55,6 +55,7 @@ def execute(
self,
executable: QuantumExecutable,
memory_map: Optional[MemoryMap] = None,
**kwargs: Any,
) -> T:
"""
Run an executable on a QAM, returning a handle to be used to retrieve
Expand All @@ -74,11 +75,9 @@ def get_result(self, execute_response: T) -> QAMExecutionResult:
"""

def run(
self,
executable: QuantumExecutable,
memory_map: Optional[MemoryMap] = None,
self, executable: QuantumExecutable, memory_map: Optional[MemoryMap] = None, **kwargs: Any
) -> QAMExecutionResult:
"""
Run an executable to completion on the QAM.
"""
return self.get_result(self.execute(executable, memory_map))
return self.get_result(self.execute(executable, memory_map, **kwargs))
41 changes: 32 additions & 9 deletions pyquil/api/_qpu.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
##############################################################################
from dataclasses import dataclass
from collections import defaultdict
from typing import Dict, Optional, Union
from typing import Any, Dict, Optional, Union

import numpy as np
from numpy.typing import NDArray
Expand All @@ -28,7 +28,14 @@
MemoryReference,
)
from qcs_sdk import QCSClient
from qcs_sdk.qpu.api import submit, retrieve_results, ExecutionResult
from qcs_sdk.qpu.api import (
submit,
retrieve_results,
ConnectionStrategy,
ExecutionResult,
ExecutionOptions,
ExecutionOptionsBuilder,
)
from qcs_sdk.qpu.rewrite_arithmetic import build_patch_values


Expand Down Expand Up @@ -102,6 +109,7 @@ def alloc(spec: ParameterSpec) -> np.ndarray:
class QPUExecuteResponse:
job_id: str
_executable: EncryptedProgram
execution_options: Optional[ExecutionOptions]


class QPU(QAM[QPUExecuteResponse]):
Expand All @@ -113,7 +121,7 @@ def __init__(
timeout: float = 10.0,
client_configuration: Optional[QCSClient] = None,
endpoint_id: Optional[str] = None,
use_gateway: bool = True,
execution_options: Optional[ExecutionOptions] = None,
) -> None:
"""
A connection to the QPU.
Expand All @@ -134,20 +142,34 @@ def __init__(
self._last_results: Dict[str, np.ndarray] = {}
self._memory_results: Dict[str, Optional[np.ndarray]] = defaultdict(lambda: None)
self._quantum_processor_id = quantum_processor_id
self._endpoint_id = endpoint_id

self._use_gateway = use_gateway
if execution_options is None:
execution_options_builder = ExecutionOptionsBuilder.default()
if endpoint_id is not None:
execution_options_builder.connection_strategy(ConnectionStrategy.endpoint_id(endpoint_id))
execution_options = execution_options_builder.build()
self.execution_options = execution_options

@property
def quantum_processor_id(self) -> str:
"""ID of quantum processor targeted."""
return self._quantum_processor_id

def execute(self, executable: QuantumExecutable, memory_map: Optional[MemoryMap] = None) -> QPUExecuteResponse:
def execute(
self,
executable: QuantumExecutable,
memory_map: Optional[MemoryMap] = None,
execution_options: Optional[ExecutionOptions] = None,
**__: Any,
) -> QPUExecuteResponse:
"""
Enqueue a job for execution on the QPU. Returns a ``QPUExecuteResponse``, a
job descriptor which should be passed directly to ``QPU.get_result`` to retrieve
results.
:param:
execution_options: An optional `ExecutionOptions` enum that can be used
to configure how the job is submitted and retrieved from the QPU. If unset,
an appropriate default will be used.
"""
executable = executable.copy()

Expand All @@ -165,11 +187,11 @@ def execute(self, executable: QuantumExecutable, memory_map: Optional[MemoryMap]
program=executable.program,
patch_values=patch_values,
quantum_processor_id=self.quantum_processor_id,
endpoint_id=self._endpoint_id,
client=self._client_configuration,
execution_options=execution_options or self.execution_options,
)

return QPUExecuteResponse(_executable=executable, job_id=job_id)
return QPUExecuteResponse(_executable=executable, job_id=job_id, execution_options=execution_options)

def get_result(self, execute_response: QPUExecuteResponse) -> QAMExecutionResult:
"""
Expand All @@ -180,6 +202,7 @@ def get_result(self, execute_response: QPUExecuteResponse) -> QAMExecutionResult
job_id=execute_response.job_id,
quantum_processor_id=self.quantum_processor_id,
client=self._client_configuration,
execution_options=execute_response.execution_options,
)

ro_sources = execute_response._executable.ro_sources
Expand Down
6 changes: 2 additions & 4 deletions pyquil/api/_quantum_computer.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,7 @@ def to_compiler_isa(self) -> CompilerISA:
return self.compiler.quantum_processor.to_compiler_isa()

def run(
self,
executable: QuantumExecutable,
memory_map: Optional[MemoryMap] = None,
self, executable: QuantumExecutable, memory_map: Optional[MemoryMap] = None, **kwargs: Any
) -> QAMExecutionResult:
"""
Run a quil executable. All parameters in the executable must have values applied using
Expand All @@ -139,7 +137,7 @@ def run(
region for the run.
:return: execution result including readout data.
"""
return self.qam.run(executable, memory_map)
return self.qam.run(executable, memory_map, **kwargs)

def calibrate(self, experiment: Experiment) -> List[ExperimentResult]:
"""
Expand Down
3 changes: 2 additions & 1 deletion pyquil/api/_qvm.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
# limitations under the License.
##############################################################################
from dataclasses import dataclass
from typing import Mapping, Optional, Sequence, Tuple
from typing import Any, Mapping, Optional, Sequence, Tuple

import numpy as np

Expand Down Expand Up @@ -123,6 +123,7 @@ def execute(
self,
executable: QuantumExecutable,
memory_map: Optional[MemoryMap] = None,
**__: Any,
) -> QVMExecuteResponse:
"""
Synchronously execute the input program to completion.
Expand Down
4 changes: 1 addition & 3 deletions pyquil/api/_wavefunction_simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,9 +202,7 @@ def run_and_measure(
trials,
qubits,
)
measured_qubits = qvm.api.run_and_measure(
request, options=QVMOptions(timeout_seconds=self.timeout) # type: ignore[call-arg]
)
measured_qubits = qvm.api.run_and_measure(request, options=QVMOptions(timeout_seconds=self.timeout))
return np.asarray(measured_qubits)

@staticmethod
Expand Down
8 changes: 2 additions & 6 deletions pyquil/pyqvm.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
##############################################################################
import logging
from abc import ABC, abstractmethod
from typing import Dict, List, Optional, Sequence, Type, Union
from typing import Dict, List, Optional, Sequence, Type, Union, Any

import numpy as np
from numpy.random.mtrand import RandomState
Expand Down Expand Up @@ -221,11 +221,7 @@ def _extract_defined_gates(self) -> None:
raise NotImplementedError("PyQVM does not support DEFGATE ... AS MATRIX | PAULI-SUM.")
self.defined_gates[dg.name] = dg.matrix

def execute(
self,
executable: QuantumExecutable,
memory_map: Optional[MemoryMap] = None,
) -> "PyQVM":
def execute(self, executable: QuantumExecutable, memory_map: Optional[MemoryMap] = None, **__: Any) -> "PyQVM":
"""
Execute a program on the PyQVM. Note that the state of the instance is reset on each
call to ``execute``.
Expand Down

0 comments on commit fc402d1

Please sign in to comment.