Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
d2d1b3b
Add new `get_sampler*` functions. Refactor existing `get_sampler`.
dyates Sep 19, 2025
5494ef7
Merge branch 'main' into refactor_get_sampler
dyates Sep 25, 2025
396438a
Change default concurrent jobs to 100.
dyates Sep 25, 2025
fcf006d
Format checks.
dyates Sep 25, 2025
36fc45d
Merge fixes.
dyates Sep 25, 2025
a7eec34
Merge branch 'main' into refactor_get_sampler
dyates Sep 25, 2025
2a7cf4a
More format fixes;Add unit tests for coverage.
dyates Sep 26, 2025
95e1046
Remove default run_name from functions
dyates Sep 26, 2025
74ac05a
Merge branch 'main' into refactor_get_sampler
dyates Sep 26, 2025
158c77b
Make function param types consistent.
dyates Sep 26, 2025
c0fe0ad
Add param doc comment for `processor_id`
dyates Sep 26, 2025
3c019ac
Fix type error.
dyates Sep 26, 2025
22d9832
Merge branch 'main' into refactor_get_sampler
dyates Oct 10, 2025
1476291
Remove get_sampler_from* functions and replace with new pattern.
dyates Oct 17, 2025
0ae580d
Merge branch 'main' into refactor_get_sampler
dyates Oct 17, 2025
4849b9a
Move `DeviceVersion` to processor_config. Remove all `*from_config/sn…
dyates Oct 24, 2025
b4b8941
Merge branch 'main' into refactor_get_sampler
dyates Oct 24, 2025
3ff91b1
Format fixes;Remove unused imports.
dyates Oct 24, 2025
64f4c21
Merge branch 'main' into refactor_get_sampler
dyates Nov 7, 2025
392b9ef
Merge branch 'main' into refactor_get_sampler
dyates Nov 21, 2025
5233165
Rename `DeviceVersion` to `DeviceConfigRevision`.
dyates Nov 21, 2025
b7de024
Rename `device_version` to `device_config_revision`.
dyates Nov 21, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 2 additions & 11 deletions cirq-google/cirq_google/engine/abstract_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,17 +180,8 @@ async def run_sweep_async(
run_sweep = duet.sync(run_sweep_async)

@abc.abstractmethod
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
Copy link
Collaborator

Choose a reason for hiding this comment

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

This removes what I would expect to be the most common use case: specify only a device config name, but not the version (run or snapshot).

@eliottrosenberg - do we really want to support a default config name ("config alias") at all? While defaults make sense to get the "latest" version, a default grid seem more risky and I think are worth forcing explicit selection.

utilized to run the job. A configuration identifies the set of
available qubits, couplers, and supported gates in the processor.
"""
def get_sampler(self) -> cg.ProcessorSampler:
"""Returns a sampler backed by the processor."""

@abc.abstractmethod
def engine(self) -> abstract_engine.AbstractEngine | None:
Expand Down
60 changes: 17 additions & 43 deletions cirq-google/cirq_google/engine/engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -592,23 +592,18 @@ def get_processor(self, processor_id: str) -> engine_processor.EngineProcessor:
def get_sampler(
self,
processor_id: str | list[str],
run_name: str = "",
device_config_name: str = "",
snapshot_id: str = "",
device_config_name: str | None = None,
device_config_revision: processor_config.DeviceConfigRevision | None = None,
max_concurrent_jobs: int = 100,
) -> 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.
snapshot_id: A unique identifier for an immutable snapshot reference. A
snapshot contains a collection of device configurations for the processor.
device_config_revision: Specifies either the snapshot_id or the run_name.
max_concurrent_jobs: The maximum number of jobs to be sent
concurrently to the Engine. This client-side throttle can be
used to proactively reduce load to the backends and avoid quota
Expand All @@ -628,41 +623,18 @@ def get_sampler(
'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(
run_name=run_name,
device_config_name=device_config_name,
snapshot_id=snapshot_id,
device_config_revision=device_config_revision,
max_concurrent_jobs=max_concurrent_jobs,
)

async def get_processor_config_from_snapshot_async(
self, processor_id: str, snapshot_id: str, config_name: str = 'default'
) -> processor_config.ProcessorConfig | None:
"""Returns a ProcessorConfig from this project and the given processor id.

Args:
processor_id: The processor unique identifier.
snapshot_id: The unique identifier for the snapshot.
config_name: The identifier for the config.

Returns:
The ProcessorConfig from this project and processor.
"""
client = self.context.client
quantum_config = await client.get_quantum_processor_config_from_snapshot_async(
project_id=self.project_id,
processor_id=processor_id,
snapshot_id=snapshot_id,
config_name=config_name,
)
if quantum_config:
return processor_config.ProcessorConfig(quantum_processor_config=quantum_config)
return None

get_processor_config_from_snapshot = duet.sync(get_processor_config_from_snapshot_async)

async def get_processor_config_from_run_async(
self, processor_id: str, run_name: str = 'current', config_name: str = 'default'
async def get_processor_config_async(
self,
processor_id: str,
device_config_revision: processor_config.DeviceConfigRevision = processor_config.Run(id='current'),
config_name: str = 'default',
) -> processor_config.ProcessorConfig | None:
"""Returns a ProcessorConfig from this project and the given processor id.

Expand All @@ -671,25 +643,27 @@ async def get_processor_config_from_run_async(

Args:
processor_id: The processor unique identifier.
run_name: The unique identifier for the automation run.
device_config_revision: Specifies either the snapshot_id or the run_name.
config_name: The identifier for the config.

Returns:
The ProcessorConfig from this project and processor.
"""
quantum_config = await self.context.client.get_quantum_processor_config_from_run_async(
quantum_config = await self.context.client.get_quantum_processor_config_async(
project_id=self.project_id,
processor_id=processor_id,
run_name=run_name,
device_config_revision=device_config_revision,
config_name=config_name,
)
if quantum_config:
return processor_config.ProcessorConfig(
quantum_processor_config=quantum_config, run_name=run_name
processor=self.get_processor(processor_id),
quantum_processor_config=quantum_config,
device_config_revision=device_config_revision,
)
return None

get_processor_config_from_run = duet.sync(get_processor_config_from_run_async)
get_processor_config = duet.sync(get_processor_config_async)


def get_engine(project_id: str | None = None) -> Engine:
Expand Down
107 changes: 39 additions & 68 deletions cirq-google/cirq_google/engine/engine_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
from cirq_google.cloud import quantum
from cirq_google.engine import stream_manager
from cirq_google.engine.asyncio_executor import AsyncioExecutor
from cirq_google.engine.processor_config import DeviceConfigRevision, Run, Snapshot

_M = TypeVar('_M', bound=proto.Message)
_R = TypeVar('_R')
Expand Down Expand Up @@ -1182,29 +1183,19 @@ async def list_time_slots_async(

list_time_slots = duet.sync(list_time_slots_async)

async def _get_quantum_processor_config(
self, name: str
) -> quantum.QuantumProcessorConfig | None:
"""Runs get_quantum_processor_config with the given resource name."""
try:
request = quantum.GetQuantumProcessorConfigRequest(name=name)
return await self._send_request_async(
self.grpc_client.get_quantum_processor_config, request
)
except EngineException as err:
if isinstance(err.__cause__, NotFound):
return None
raise

async def get_quantum_processor_config_from_snapshot_async(
self, project_id: str, processor_id: str, snapshot_id: str, config_name: str
async def get_quantum_processor_config_async(
self,
project_id: str,
processor_id: str,
config_name: str = 'default',
device_config_revision: DeviceConfigRevision = Run(id='current'),
) -> quantum.QuantumProcessorConfig | None:
"""Returns the QuantumProcessorConfig for the given snapshot id.

Args:
project_id: A project_id of the parent Google Cloud Project.
processor_id: The processor unique identifier.
snapshot_id: The id of the snapshot that contains the quantum processor config.
device_config_revision: Specifies either the snapshot_id or the run_name.
config_name: The id of the quantum processor config.

Returns:
Expand All @@ -1213,44 +1204,23 @@ async def get_quantum_processor_config_from_snapshot_async(
Raises:
EngineException: If the request to get the config fails.
"""
name = _quantum_processor_config_name_from_snapshot_id(
project_id=project_id,
processor_id=processor_id,
snapshot_id=snapshot_id,
config_name=config_name,
)
return await self._get_quantum_processor_config(name)

get_quantum_processor_config_from_snapshot = duet.sync(
get_quantum_processor_config_from_snapshot_async
)

async def get_quantum_processor_config_from_run_async(
self, project_id: str, processor_id: str, run_name: str, config_name: str
) -> quantum.QuantumProcessorConfig | None:
"""Returns the QuantumProcessorConfig for the given run_name.

Args:
project_id: A project_id of the parent Google Cloud Project.
processor_id: The processor unique identifier.
config_name: The id of the quantum processor config.
run_name: The run_name that contains the quantum processor config.

Returns:
The quantum procesor config or None if it does not exist.

Raises:
EngineException: If the request to get the config fails.
"""
name = _quantum_processor_config_name_from_run_name(
project_id=project_id,
processor_id=processor_id,
run_name=run_name,
config_name=config_name,
)
return await self._get_quantum_processor_config(name)
try:
name = _quantum_processor_config_name_from_device_config_revision(
project_id=project_id,
processor_id=processor_id,
config_name=config_name,
device_config_revision=device_config_revision,
)
request = quantum.GetQuantumProcessorConfigRequest(name=name)
return await self._send_request_async(
self.grpc_client.get_quantum_processor_config, request
)
except EngineException as err:
if isinstance(err.__cause__, NotFound):
return None
raise

get_quantum_processor_config_from_run = duet.sync(get_quantum_processor_config_from_run_async)
get_quantum_processor_config = duet.sync(get_quantum_processor_config_async)


def _project_name(project_id: str) -> str:
Expand Down Expand Up @@ -1301,22 +1271,23 @@ def _ids_from_calibration_name(calibration_name: str) -> tuple[str, str, int]:
return parts[1], parts[3], int(parts[5])


def _quantum_processor_config_name_from_snapshot_id(
project_id: str, processor_id: str, snapshot_id: str, config_name: str
) -> str:
return (
f'{_processor_name_from_ids(project_id, processor_id)}/'
f'configSnapshots/{snapshot_id}/'
f'configs/{config_name}'
)


def _quantum_processor_config_name_from_run_name(
project_id: str, processor_id: str, run_name: str, config_name: str
def _quantum_processor_config_name_from_device_config_revision(
project_id: str,
processor_id: str,
config_name: str,
device_config_revision: DeviceConfigRevision | None = None,
) -> str:
processor_resource_name = _processor_name_from_ids(project_id, processor_id)
if isinstance(device_config_revision, Snapshot):
return (
f'{processor_resource_name}/'
f'configSnapshots/{device_config_revision.id}/'
f'configs/{config_name}'
)
default_run_name = 'default'
return (
f'{_processor_name_from_ids(project_id, processor_id)}/'
f'configAutomationRuns/{run_name}/'
f'{processor_resource_name}/'
f'configAutomationRuns/{device_config_revision.id if device_config_revision else default_run_name}/'
f'configs/{config_name}'
)

Expand Down
Loading
Loading