Skip to content

Commit

Permalink
Add new processor selector parameters in cirq-google/engine run metho…
Browse files Browse the repository at this point in the history
…ds (#6267)

* Add new processor selector parameters to engine_program run methods

* Add new processor selector parameters to engine run methods

* Add new processor selector parameters to processor run methods

* Add device configuration  parameters to processor sampler class

* small docstring fix

* test sampler with incomplete device configuraion throws

* Address cxing comments

* fix abstract processor run

---------

Co-authored-by: Jose Urruticoechea <urruti@google.com>
  • Loading branch information
jurruti and Jose Urruticoechea authored Aug 30, 2023
1 parent b28bfce commit b70b2fc
Show file tree
Hide file tree
Showing 9 changed files with 374 additions and 46 deletions.
41 changes: 39 additions & 2 deletions cirq-google/cirq_google/engine/abstract_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ async def run_async(
program_labels: Optional[Dict[str, str]] = None,
job_description: Optional[str] = None,
job_labels: Optional[Dict[str, str]] = None,
run_name: str = "",
device_config_name: str = "",
) -> cirq.Result:
"""Runs the supplied Circuit on this processor.
Expand All @@ -85,6 +87,12 @@ async def run_async(
program_labels: Optional set of labels to set on the program.
job_description: An optional description to set on the job.
job_labels: Optional set of labels to set on the job.
run_name: A unique identifier representing an automation run for the
processor. An Automation Run contains a collection of device
configurations for the processor.
device_config_name: An identifier used to select the processor configuration
utilized to run the job. A configuration identifies the set of
available qubits, couplers, and supported gates in the processor.
Returns:
A single Result for this run.
"""
Expand All @@ -98,6 +106,8 @@ async def run_async(
program_labels=program_labels,
job_description=job_description,
job_labels=job_labels,
run_name=run_name,
device_config_name=device_config_name,
)
return job.results()[0]

Expand All @@ -115,6 +125,8 @@ async def run_sweep_async(
program_labels: Optional[Dict[str, str]] = None,
job_description: Optional[str] = None,
job_labels: Optional[Dict[str, str]] = None,
run_name: str = "",
device_config_name: str = "",
) -> 'abstract_job.AbstractJob':
"""Runs the supplied Circuit on this processor.
Expand All @@ -138,6 +150,12 @@ async def run_sweep_async(
program_labels: Optional set of labels to set on the program.
job_description: An optional description to set on the job.
job_labels: Optional set of labels to set on the job.
run_name: A unique identifier representing an automation run for the
processor. An Automation Run contains a collection of device
configurations for the processor.
device_config_name: An identifier used to select the processor configuration
utilized to run the job. A configuration identifies the set of
available qubits, couplers, and supported gates in the processor.
Returns:
An AbstractJob. If this is iterated over it returns a list of
`cirq.Result`, one for each parameter sweep.
Expand All @@ -157,6 +175,8 @@ async def run_batch_async(
program_labels: Optional[Dict[str, str]] = None,
job_description: Optional[str] = None,
job_labels: Optional[Dict[str, str]] = None,
run_name: str = "",
device_config_name: str = "",
) -> 'abstract_job.AbstractJob':
"""Runs the supplied Circuits on this processor.
Expand Down Expand Up @@ -188,6 +208,12 @@ async def run_batch_async(
program_labels: Optional set of labels to set on the program.
job_description: An optional description to set on the job.
job_labels: Optional set of labels to set on the job.
run_name: A unique identifier representing an automation run for the
processor. An Automation Run contains a collection of device
configurations for the processor.
device_config_name: An identifier used to select the processor configuration
utilized to run the job. A configuration identifies the set of
available qubits, couplers, and supported gates in the processor.
Returns:
An AbstractJob. If this is iterated over it returns a list of
`cirq.Result`. All Results for the first circuit are listed
Expand Down Expand Up @@ -244,8 +270,19 @@ async def run_calibration_async(
run_calibration = duet.sync(run_calibration_async)

@abc.abstractmethod
def get_sampler(self) -> 'cg.ProcessorSampler':
"""Returns a sampler backed by the processor."""
def get_sampler(
self, run_name: str = "", device_config_name: str = ""
) -> 'cg.ProcessorSampler':
"""Returns a sampler backed by the processor.
Args:
run_name: A unique identifier representing an automation run for the
processor. An Automation Run contains a collection of device
configurations for the processor.
device_config_name: An identifier used to select the processor configuration
utilized to run the job. A configuration identifies the set of
available qubits, couplers, and supported gates in the processor.
"""

@abc.abstractmethod
def engine(self) -> Optional['abstract_engine.AbstractEngine']:
Expand Down
103 changes: 91 additions & 12 deletions cirq-google/cirq_google/engine/engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ def __init__(
def __str__(self) -> str:
return f'Engine(project_id={self.project_id!r})'

# TODO(#6271): Deprecate and remove processor_ids before v1.4
def run(
self,
program: cirq.AbstractCircuit,
Expand All @@ -219,6 +220,10 @@ def run(
program_labels: Optional[Dict[str, str]] = None,
job_description: Optional[str] = None,
job_labels: Optional[Dict[str, str]] = None,
*,
processor_id: str = "",
run_name: str = "",
device_config_name: str = "",
) -> cirq.Result:
"""Runs the supplied Circuit via Quantum Engine.
Expand All @@ -236,19 +241,34 @@ def run(
and day.
param_resolver: Parameters to run with the program.
repetitions: The number of repetitions to simulate.
processor_ids: The engine processors that should be candidates
to run the program. Only one of these will be scheduled for
execution.
processor_ids: Deprecated list of candidate processor ids to run the program.
Only allowed to contain one processor_id. If the argument `processor_id`
is non-empty, `processor_ids` will be ignored.
program_description: An optional description to set on the program.
program_labels: Optional set of labels to set on the program.
job_description: An optional description to set on the job.
job_labels: Optional set of labels to set on the job.
processor_id: Processor id for running the program. If not set,
`processor_ids` will be used.
run_name: A unique identifier representing an automation run for the
specified processor. An Automation Run contains a collection of
device configurations for a processor. If specified, `processor_id`
is required to be set.
device_config_name: An identifier used to select the processor configuration
utilized to run the job. A configuration identifies the set of
available qubits, couplers, and supported gates in the processor.
If specified, `processor_id` is required to be set.
Returns:
A single Result for this run.
Raises:
ValueError: If no gate set is provided.
ValueError: If neither `processor_id` or `processor_ids` are set.
ValueError: If only one of `run_name` and `device_config_name` are specified.
ValueError: If `processor_ids` has more than one processor id.
ValueError: If either `run_name` and `device_config_name` are set but
`processor_id` is empty.
"""
return list(
self.run_sweep(
Expand All @@ -262,9 +282,13 @@ def run(
program_labels=program_labels,
job_description=job_description,
job_labels=job_labels,
processor_id=processor_id,
run_name=run_name,
device_config_name=device_config_name,
)
)[0]

# TODO(#6271): Deprecate and remove processor_ids before v1.4
async def run_sweep_async(
self,
program: cirq.AbstractCircuit,
Expand All @@ -277,6 +301,10 @@ async def run_sweep_async(
program_labels: Optional[Dict[str, str]] = None,
job_description: Optional[str] = None,
job_labels: Optional[Dict[str, str]] = None,
*,
processor_id: str = "",
run_name: str = "",
device_config_name: str = "",
) -> engine_job.EngineJob:
"""Runs the supplied Circuit via Quantum Engine.Creates
Expand All @@ -297,20 +325,35 @@ async def run_sweep_async(
and day.
params: Parameters to run with the program.
repetitions: The number of circuit repetitions to run.
processor_ids: The engine processors that should be candidates
to run the program. Only one of these will be scheduled for
execution.
processor_ids: Deprecated list of candidate processor ids to run the program.
Only allowed to contain one processor_id. If the argument `processor_id`
is non-empty, `processor_ids` will be ignored.
program_description: An optional description to set on the program.
program_labels: Optional set of labels to set on the program.
job_description: An optional description to set on the job.
job_labels: Optional set of labels to set on the job.
processor_id: Processor id for running the program. If not set,
`processor_ids` will be used.
run_name: A unique identifier representing an automation run for the
specified processor. An Automation Run contains a collection of
device configurations for a processor. If specified, `processor_id`
is required to be set.
device_config_name: An identifier used to select the processor configuration
utilized to run the job. A configuration identifies the set of
available qubits, couplers, and supported gates in the processor.
If specified, `processor_id` is required to be set.
Returns:
An EngineJob. If this is iterated over it returns a list of
TrialResults, one for each parameter sweep.
Raises:
ValueError: If no gate set is provided.
ValueError: If neither `processor_id` or `processor_ids` are set.
ValueError: If only one of `run_name` and `device_config_name` are specified.
ValueError: If `processor_ids` has more than one processor id.
ValueError: If either `run_name` and `device_config_name` are set but
`processor_id` is empty.
"""
engine_program = await self.create_program_async(
program, program_id, description=program_description, labels=program_labels
Expand All @@ -322,10 +365,14 @@ async def run_sweep_async(
processor_ids=processor_ids,
description=job_description,
labels=job_labels,
processor_id=processor_id,
run_name=run_name,
device_config_name=device_config_name,
)

run_sweep = duet.sync(run_sweep_async)

# TODO(#6271): Deprecate and remove processor_ids before v1.4
async def run_batch_async(
self,
programs: Sequence[cirq.AbstractCircuit],
Expand All @@ -338,6 +385,10 @@ async def run_batch_async(
program_labels: Optional[Dict[str, str]] = None,
job_description: Optional[str] = None,
job_labels: Optional[Dict[str, str]] = None,
*,
processor_id: str = "",
run_name: str = "",
device_config_name: str = "",
) -> engine_job.EngineJob:
"""Runs the supplied Circuits via Quantum Engine.Creates
Expand Down Expand Up @@ -367,13 +418,23 @@ async def run_batch_async(
require sweeps.
repetitions: Number of circuit repetitions to run. Each sweep value
of each circuit in the batch will run with the same repetitions.
processor_ids: The engine processors that should be candidates
to run the program. Only one of these will be scheduled for
execution.
processor_ids: Deprecated list of candidate processor ids to run the program.
Only allowed to contain one processor_id. If the argument `processor_id`
is non-empty, `processor_ids` will be ignored.
program_description: An optional description to set on the program.
program_labels: Optional set of labels to set on the program.
job_description: An optional description to set on the job.
job_labels: Optional set of labels to set on the job.
processor_id: Processor id for running the program. If not set,
`processor_ids` will be used.
run_name: A unique identifier representing an automation run for the
specified processor. An Automation Run contains a collection of
device configurations for a processor. If specified, `processor_id`
is required to be set.
device_config_name: An identifier used to select the processor configuration
utilized to run the job. A configuration identifies the set of
available qubits, couplers, and supported gates in the processor.
If specified, `processor_id` is required to be set.
Returns:
An EngineJob. If this is iterated over it returns a list of
Expand All @@ -385,12 +446,17 @@ async def run_batch_async(
Raises:
ValueError: If the length of programs mismatches that of params_list, or
`processor_ids` is not supplied.
ValueError: If neither `processor_id` or `processor_ids` are set.
ValueError: If only one of `run_name` and `device_config_name` are specified.
ValueError: If `processor_ids` has more than one processor id.
ValueError: If either `run_name` and `device_config_name` are set but
`processor_id` is empty.
"""
if params_list is None:
params_list = [None] * len(programs)
elif len(programs) != len(params_list):
raise ValueError('Number of circuits and sweeps must match')
if not processor_ids:
if not processor_ids and not processor_id:
raise ValueError('Processor id must be specified.')
engine_program = await self.create_batch_program_async(
programs, program_id, description=program_description, labels=program_labels
Expand All @@ -402,6 +468,9 @@ async def run_batch_async(
processor_ids=processor_ids,
description=job_description,
labels=job_labels,
processor_id=processor_id,
run_name=run_name,
device_config_name=device_config_name,
)

run_batch = duet.sync(run_batch_async)
Expand Down Expand Up @@ -778,11 +847,19 @@ def sampler(self, processor_id: Union[str, List[str]]) -> 'cirq_google.Processor
"""
return self.get_sampler(processor_id)

def get_sampler(self, processor_id: Union[str, List[str]]) -> 'cirq_google.ProcessorSampler':
def get_sampler(
self, processor_id: Union[str, List[str]], run_name: str = "", device_config_name: str = ""
) -> 'cirq_google.ProcessorSampler':
"""Returns a sampler backed by the engine.
Args:
processor_id: String identifier of which processor should be used to sample.
run_name: A unique identifier representing an automation run for the
processor. An Automation Run contains a collection of device
configurations for the processor.
device_config_name: An identifier used to select the processor configuration
utilized to run the job. A configuration identifies the set of
available qubits, couplers, and supported gates in the processor.
Returns:
A `cirq.Sampler` instance (specifically a `engine_sampler.ProcessorSampler`
Expand All @@ -798,7 +875,9 @@ def get_sampler(self, processor_id: Union[str, List[str]]) -> 'cirq_google.Proce
'to get_sampler() no longer supported. Use Engine.run() instead if '
'you need to specify a list.'
)
return self.get_processor(processor_id).get_sampler()
return self.get_processor(processor_id).get_sampler(
run_name=run_name, device_config_name=device_config_name
)


def get_engine(project_id: Optional[str] = None) -> Engine:
Expand Down
6 changes: 5 additions & 1 deletion cirq-google/cirq_google/engine/engine_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -397,12 +397,16 @@ async def create_job_async(
) -> Tuple[str, quantum.QuantumJob]:
"""Creates and runs a job on Quantum Engine.
Either both `run_name` and `device_config_name` must be set, or neither
of them must be set. If none of them are set, a default internal device
configuration will be used.
Args:
project_id: A project_id of the parent Google Cloud Project.
program_id: Unique ID of the program within the parent project.
job_id: Unique ID of the job within the parent program.
run_context: Properly serialized run context.
processor_ids: Deprecated list of processor ids for running the program.
processor_ids: Deprecated list of candidate processor ids to run the program.
Only allowed to contain one processor_id. If the argument `processor_id`
is non-empty, `processor_ids` will be ignored. Otherwise the deprecated
decorator will fix the arguments and call create_job_async using
Expand Down
Loading

0 comments on commit b70b2fc

Please sign in to comment.