Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow external users to use snapshot_id #6739

Merged
merged 17 commits into from
Oct 14, 2024
Merged
51 changes: 35 additions & 16 deletions cirq-google/cirq_google/cloud/quantum_v1alpha1/types/quantum.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,15 +156,48 @@ class QuantumJob(proto.Message):

class DeviceConfigSelector(proto.Message):
r"""-
This message has `oneof`_ fields (mutually exclusive fields).
For each oneof, at most one member field can be set at the same time.
Setting any member of the oneof automatically clears all other
members.
.. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields
Attributes:
run_name (str):
-
This field is a member of `oneof`_ ``top_level_identifier``.
snapshot_id (str):
-
This field is a member of `oneof`_ ``top_level_identifier``.
config_alias (str):
-
"""

run_name = proto.Field(proto.STRING, number=1)
config_alias = proto.Field(proto.STRING, number=2)
run_name: str = proto.Field(proto.STRING, number=1, oneof='top_level_identifier')
snapshot_id: str = proto.Field(proto.STRING, number=3, oneof='top_level_identifier')
config_alias: str = proto.Field(proto.STRING, number=2)


class DeviceConfigKey(proto.Message):
r"""-
This message has `oneof`_ fields (mutually exclusive fields).
For each oneof, at most one member field can be set at the same time.
Setting any member of the oneof automatically clears all other
members.
.. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields
Attributes:
run (str):
-
This field is a member of `oneof`_ ``top_level_identifier``.
snapshot_id (str):
-
This field is a member of `oneof`_ ``top_level_identifier``.
config_alias (str):
-
"""

run: str = proto.Field(proto.STRING, number=1, oneof='top_level_identifier')
snapshot_id: str = proto.Field(proto.STRING, number=3, oneof='top_level_identifier')
config_alias: str = proto.Field(proto.STRING, number=2)


class SchedulingConfig(proto.Message):
Expand Down Expand Up @@ -611,18 +644,4 @@ class QuantumReservation(proto.Message):
whitelisted_users = proto.RepeatedField(proto.STRING, number=5)


class DeviceConfigKey(proto.Message):
r"""-

Attributes:
run (str):
-
config_alias (str):
-
"""

run = proto.Field(proto.STRING, number=1)
config_alias = proto.Field(proto.STRING, number=2)


__all__ = tuple(sorted(__protobuf__.manifest))
13 changes: 11 additions & 2 deletions cirq-google/cirq_google/engine/abstract_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,9 @@ async def run_async(
self,
program: cirq.Circuit,
*,
run_name: str,
device_config_name: str,
run_name: str = "",
snapshot_id: str = "",
program_id: Optional[str] = None,
job_id: Optional[str] = None,
param_resolver: Optional[cirq.ParamResolver] = None,
Expand All @@ -79,6 +80,9 @@ async def run_async(
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.
snapshot_id: A unique identifier for an immutable snapshot reference.
A snapshot contains a collection of device configurations for the
processor. Both `snapshot_id` and `run_name` should not be set.
program_id: A user-provided identifier for the program. This must
be unique within the Google Cloud project being used. If this
parameter is not provided, a random id of the format
Expand Down Expand Up @@ -109,6 +113,7 @@ async def run_async(
job_description=job_description,
job_labels=job_labels,
run_name=run_name,
snapshot_id=snapshot_id,
device_config_name=device_config_name,
)
return job.results()[0]
Expand All @@ -120,8 +125,9 @@ async def run_sweep_async(
self,
program: cirq.AbstractCircuit,
*,
run_name: str,
device_config_name: str,
run_name: str = "",
snapshot_id: str = "",
program_id: Optional[str] = None,
job_id: Optional[str] = None,
params: cirq.Sweepable = None,
Expand All @@ -144,6 +150,9 @@ async def run_sweep_async(
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.
snapshot_id: A unique identifier for an immutable snapshot reference.
A snapshot contains a collection of device configurations for the
processor. Both `snapshot_id` and `run_name` should not be set.
Comment on lines +155 to +157
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move this above the device_config_name. This should be next to the run name. Also, I feel it is good to put "Both snapshot_id and run_name should not be set." in run_name docstring as well

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

program_id: A user-provided identifier for the program. This must
be unique within the Google Cloud project being used. If this
parameter is not provided, a random id of the format
Expand Down
11 changes: 11 additions & 0 deletions cirq-google/cirq_google/engine/engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ def run(
job_labels: Optional[Dict[str, str]] = None,
*,
run_name: str = "",
snapshot_id: str = "",
device_config_name: str = "",
) -> cirq.Result:
"""Runs the supplied Circuit via Quantum Engine.
Expand Down Expand Up @@ -250,6 +251,9 @@ def run(
specified processor. An Automation Run contains a collection of
device configurations for a processor. If specified, `processor_id`
is required to be set.
snapshot_id: A unique identifier for an immutable snapshot reference.
A snapshot 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.
Expand Down Expand Up @@ -277,6 +281,7 @@ def run(
job_description=job_description,
job_labels=job_labels,
run_name=run_name,
snapshot_id=snapshot_id,
device_config_name=device_config_name,
)
)[0]
Expand All @@ -295,6 +300,7 @@ async def run_sweep_async(
job_labels: Optional[Dict[str, str]] = None,
*,
run_name: str = "",
snapshot_id: str = "",
device_config_name: str = "",
) -> engine_job.EngineJob:
"""Runs the supplied Circuit via Quantum Engine.
Expand Down Expand Up @@ -325,6 +331,9 @@ async def run_sweep_async(
specified processor. An Automation Run contains a collection of
device configurations for a processor. If specified, `processor_id`
is required to be set.
snapshot_id: A unique identifier for an immutable snapshot reference.
A snapshot 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.
Expand Down Expand Up @@ -360,6 +369,7 @@ async def run_sweep_async(
job_labels=job_labels,
processor_id=processor_id,
run_name=run_name,
snapshot_id=snapshot_id,
device_config_name=device_config_name,
)
return engine_job.EngineJob(
Expand All @@ -381,6 +391,7 @@ async def run_sweep_async(
description=job_description,
labels=job_labels,
run_name=run_name,
snapshot_id=snapshot_id,
device_config_name=device_config_name,
)

Expand Down
51 changes: 41 additions & 10 deletions cirq-google/cirq_google/engine/engine_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,7 @@ async def create_job_async(
labels: Optional[Dict[str, str]] = None,
*,
run_name: str = "",
snapshot_id: str = "",
device_config_name: str = "",
) -> Tuple[str, quantum.QuantumJob]:
"""Creates and runs a job on Quantum Engine.
Expand All @@ -409,6 +410,9 @@ async def create_job_async(
specified processor. An Automation Run contains a collection of
device configurations for a processor. If specified, `processor_id`
is required to be set.
snapshot_id: A unique identifier for an immutable snapshot reference.
A snapshot 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.
Expand All @@ -421,25 +425,36 @@ async def create_job_async(
ValueError: If only one of `run_name` and `device_config_name` are specified.
ValueError: If either `run_name` and `device_config_name` are set but
`processor_id` is empty.
ValueError: If both `run_name` and `snapshot_id` are specified.
"""
# Check program to run and program parameters.
if priority and not 0 <= priority < 1000:
raise ValueError('priority must be between 0 and 1000')
if not processor_id:
raise ValueError('Must specify a processor id when creating a job.')
if bool(run_name) ^ bool(device_config_name):
raise ValueError('Cannot specify only one of `run_name` and `device_config_name`')
if run_name and snapshot_id:
raise ValueError('Cannot specify both `run_name` and `snapshot_id`')
if (bool(run_name) or bool(snapshot_id)) ^ bool(device_config_name):
raise ValueError(
'Cannot specify only one of top level identifier and `device_config_name`'
)

# Create job.
if snapshot_id:
selector = quantum.DeviceConfigSelector(
snapshot_id=snapshot_id or None, config_alias=device_config_name
)
else:
selector = quantum.DeviceConfigSelector(
run_name=run_name or None, config_alias=device_config_name
)
job_name = _job_name_from_ids(project_id, program_id, job_id) if job_id else ''
job = quantum.QuantumJob(
name=job_name,
scheduling_config=quantum.SchedulingConfig(
processor_selector=quantum.SchedulingConfig.ProcessorSelector(
processor=_processor_name_from_ids(project_id, processor_id),
device_config_selector=quantum.DeviceConfigSelector(
run_name=run_name, config_alias=device_config_name
),
device_config_selector=selector,
)
),
run_context=run_context,
Expand Down Expand Up @@ -737,6 +752,7 @@ def run_job_over_stream(
job_labels: Optional[Dict[str, str]] = None,
processor_id: str = "",
run_name: str = "",
snapshot_id: str = "",
device_config_name: str = "",
) -> duet.AwaitableFuture[Union[quantum.QuantumResult, quantum.QuantumJob]]:
"""Runs a job with the given program and job information over a stream.
Expand All @@ -761,6 +777,9 @@ def run_job_over_stream(
specified processor. An Automation Run contains a collection of
device configurations for a processor. If specified, `processor_id`
is required to be set.
snapshot_id: A unique identifier for an immutable snapshot reference.
A snapshot 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.
Expand All @@ -773,14 +792,19 @@ def run_job_over_stream(
ValueError: If the priority is not between 0 and 1000.
ValueError: If `processor_id` is not set.
ValueError: If only one of `run_name` and `device_config_name` are specified.
ValueError: If both `run_name` and `snapshot_id` are specified.
"""
# Check program to run and program parameters.
if priority and not 0 <= priority < 1000:
raise ValueError('priority must be between 0 and 1000')
if not processor_id:
raise ValueError('Must specify a processor id when creating a job.')
if bool(run_name) ^ bool(device_config_name):
raise ValueError('Cannot specify only one of `run_name` and `device_config_name`')
if run_name and snapshot_id:
raise ValueError('Cannot specify both `run_name` and `snapshot_id`')
if (bool(run_name) or bool(snapshot_id)) ^ bool(device_config_name):
raise ValueError(
'Cannot specify only one of top level identifier and `device_config_name`'
)

project_name = _project_name(project_id)

Expand All @@ -791,14 +815,21 @@ def run_job_over_stream(
if program_labels:
program.labels.update(program_labels)

if snapshot_id:
selector = quantum.DeviceConfigSelector(
snapshot_id=snapshot_id or None, config_alias=device_config_name
)
else:
selector = quantum.DeviceConfigSelector(
run_name=run_name or None, config_alias=device_config_name
)

job = quantum.QuantumJob(
name=_job_name_from_ids(project_id, program_id, job_id),
scheduling_config=quantum.SchedulingConfig(
processor_selector=quantum.SchedulingConfig.ProcessorSelector(
processor=_processor_name_from_ids(project_id, processor_id),
device_config_selector=quantum.DeviceConfigSelector(
run_name=run_name, config_alias=device_config_name
),
device_config_selector=selector,
)
),
run_context=run_context,
Expand Down
Loading