Perceval Adapter API Reference

Adapter layer isolating Merlin from Perceval internal APIs (PML-306).

MerlinProcessor and the execution units historically reached directly into Perceval internals: RPC handler token/URL attributes, sampler command objects (probs / sample_count / samples), remote job status fields, local experiment private state, and RemoteConfig. Any Perceval version bump that renames or restructures those internals could silently break Merlin at runtime.

PercevalAdapter owns every such access. The rest of Merlin talks to this facade, so a Perceval API change is localized to this module.

The adapter is stateless (static methods) and duck-typed: it reads the same attributes Perceval exposes today, which also makes it independently testable with plain fakes.

class merlin.core.perceval_adapter.PercevalAdapter

Bases: object

Stateless facade owning all direct Perceval-internal access.

static build_from_session(session)

Build a fresh RemoteProcessor from a Perceval session.

Parameters:

session (perceval.runtime.session.ISession) – Provider session (e.g. Scaleway) able to build processors.

Returns:

Independent processor with its own handler state.

Return type:

perceval.runtime.RemoteProcessor

static cancel_job(job)

Request best-effort cancellation of a job, swallowing errors.

Parameters:

job (perceval.runtime.RemoteJob) – Job to cancel. Objects without a callable cancel are ignored; cancellation errors are suppressed by design (best-effort path).

Return type:

None

static clone_remote_processor(rp, token)

Create a sibling RemoteProcessor with its own RPC handler.

Forwards the provided token so that inline-token RemoteProcessors are cloned correctly.

Parameters:
  • rp (perceval.runtime.RemoteProcessor) – Processor whose platform name, URL, and proxies are copied.

  • token (str | None) – Authentication token forwarded to the clone.

Returns:

Independent processor targeting the same platform.

Return type:

perceval.runtime.RemoteProcessor

static configure_processor(processor, circuit, input_state)

Set the circuit and, when provided, the input state and photon filter.

Parameters:
  • processor (AProcessor) – Processor (local or remote) to configure.

  • circuit (pcvl.ACircuit) – Circuit to install.

  • input_state (Any) – Sequence of photon counts per mode, or falsy to skip input setup. When set, min_detected_photons_filter is set to the total photon count.

Return type:

None

static copy_circuit(circuit)

Return an independent copy of a circuit for one execution.

Parameters:

circuit (pcvl.ACircuit) – Circuit exported by the quantum layer.

Returns:

Independent circuit object used by a single backend execution.

Return type:

pcvl.ACircuit

static create_sampler(processor, max_shots_per_call, iterations)

Create a Sampler on processor loaded with the given iterations.

Parameters:
  • processor (perceval.runtime.AProcessor) – Configured processor (circuit and input already set).

  • max_shots_per_call (int) – Shot cap forwarded to the Perceval sampler.

  • iterations (list[dict[str, float]]) – One circuit-parameter mapping per batch row.

Returns:

Sampler ready for command dispatch.

Return type:

perceval.algorithm.Sampler

static ensure_serializable_sampler_iterator(job, sampler)

Replace Perceval 1.2 iterator objects with JSON-serializable data.

Parameters:
  • job (perceval.runtime.RemoteJob) – Prepared job whose private request payload may hold an iterator.

  • sampler (perceval.algorithm.Sampler) – Sampler used to prepare the job.

Return type:

None

Notes

Perceval 1.1 stores sampler iterations as a plain list. Perceval 1.2 stores them in a ParameterIterator object, but the Scaleway session handler still serializes payload["payload"] with json.dumps. Until Perceval exposes a public serializer for that object, Merlin normalizes the remote-job payload back to the list shape accepted by the cloud side.

static estimate_required_shots(rp, desired_samples, param_values)

Ask the remote platform estimator for the required shot count.

Parameters:
  • rp (perceval.runtime.RemoteProcessor) – Configured remote processor exposing the platform estimator.

  • desired_samples (int) – Target number of usable samples.

  • param_values (dict[str, float]) – Circuit parameter values for the input row being estimated.

Returns:

Estimated shots, or None when the platform gives no answer.

Return type:

int | None

static execute_sync(sampler, command, max_samples=None)

Execute a sampler command synchronously and return the raw results.

Parameters:
  • sampler (perceval.algorithm.Sampler) – Sampler prepared with circuit and iterations.

  • command (str) – Sampler command to dispatch: "probs", "sample_count", or "samples".

  • max_samples (int | None) – Shots to request. None executes without a shot argument (exact probabilities). Default value is None.

Returns:

Raw Perceval results object for the executed command.

Return type:

Any

static extract_token(rp)

Extract the auth token from a RemoteProcessor.

Perceval stores the token on the RPC handler as handler.token and also embeds it in handler.headers['Authorization']. We probe both locations so that inline-token and global-config RemoteProcessor instances are both handled.

As a last resort, falls back to RemoteConfig().get_token().

Parameters:

rp (perceval.runtime.RemoteProcessor) – Remote processor to probe for authentication material.

Returns:

The resolved token, or None if every strategy fails.

Return type:

str | None

Notes

get_rpc_handler() is wrapped defensively here — unlike in get_url() — precisely because this method has a downstream fallback: if the handler is unavailable it can still resolve a token from the global RemoteConfig. Swallowing the handler error is therefore part of the control flow, not error hiding; a genuinely unresolvable token surfaces as None (which the caller turns into a TokenExtractionError).

static get_backend_capabilities(processor)

Return the backend platform name and available command snapshot.

Parameters:

processor (perceval.runtime.AProcessor) – Local or remote processor to inspect.

Returns:

Platform name and immutable snapshot of supported commands.

Return type:

tuple[str, tuple[str, …]]

static get_results(job)

Retrieve a job’s raw results, propagating Perceval errors.

Parameters:

job (perceval.runtime.RemoteJob) – Completed job to read.

Returns:

Raw Perceval results object.

Return type:

Any

Raises:

RuntimeError – Propagated unchanged from Perceval (e.g. results not yet available, cancel requested); the polling loop interprets it.

static get_url(rp)

Return the RPC handler URL of a RemoteProcessor, if exposed.

Parameters:

rp (perceval.runtime.RemoteProcessor) – Remote processor whose RPC handler is inspected.

Returns:

The handler URL, or None when the handler has no url attribute.

Return type:

str | None

Notes

get_rpc_handler() is intentionally left unguarded here — unlike in extract_token() — because this method has no fallback. A broken handler should fail fast at the real fault rather than yield url=None and a silently misconfigured clone downstream in clone_remote_processor().

static job_snapshot(job)

Read a job’s status fields into a Merlin-normalized snapshot.

Parameters:

job (perceval.runtime.RemoteJob) – Job to inspect. Missing attributes map to None/False.

Returns:

Immutable view of the job’s id, state, and completion flags.

Return type:

JobStatusSnapshot

static rebuild_local_processor(processor)

Create an isolated local Perceval processor for one execution.

Returns the fresh processor together with the LocalExperimentSnapshot the caller must apply (via restore_experiment()) after installing the execution circuit. The snapshot is an explicit return value rather than hidden state on the processor, so a caller cannot silently forget to restore it.

Parameters:

processor (perceval.runtime.AProcessor) – Local processor whose experiment and backend are copied.

Returns:

A fresh local processor (copied non-circuit experiment state and a fresh backend instance) and the experiment snapshot to restore once the execution circuit is installed.

Return type:

tuple[perceval.runtime.AProcessor, LocalExperimentSnapshot]

Raises:

TypeError – If the configured local processor cannot be reconstructed safely.

static restore_experiment(experiment, snapshot)

Restore local experiment metadata after the execution circuit is set.

Parameters:
  • experiment (Any) – Perceval experiment owned by the fresh local execution processor.

  • snapshot (LocalExperimentSnapshot) – Metadata copied from the caller’s local processor.

Raises:

ValueError – If mode-indexed metadata cannot be applied to the execution circuit because the circuit sizes differ.

Return type:

None

static set_circuit(processor, circuit)

Install a circuit on a processor without touching its input state.

Split out from configure_processor() so the local execution path can install the circuit, restore experiment metadata, and only then set the input — instead of passing a None input-state sentinel.

Parameters:
  • processor (perceval.runtime.AProcessor) – Processor (local or remote) to configure.

  • circuit (pcvl.ACircuit) – Circuit to install.

Return type:

None

static set_input(processor, input_state)

Set the input state and matching photon filter, if provided.

Split out from configure_processor() because the local execution path must restore experiment metadata between installing the circuit and setting the input.

Parameters:
  • processor (perceval.runtime.AProcessor) – Processor to receive the input state.

  • input_state (Any) – Sequence of photon counts per mode, or falsy to skip input setup.

Return type:

None

static snapshot_experiment(experiment)

Copy non-circuit local experiment metadata before Perceval clears it.

Parameters:

experiment (Any) – Perceval experiment owned by the caller’s local processor.

Returns:

Deep-copied metadata that is independent from the caller’s processor.

Return type:

LocalExperimentSnapshot

static submit_async(sampler, command, name=None, max_samples=None)

Submit a sampler command asynchronously and return the job handle.

Parameters:
  • sampler (Sampler) – Sampler prepared with circuit and iterations.

  • command (str) – Sampler command to dispatch: "probs", "sample_count", or "samples".

  • name (str | None) – Remote job name to assign before submission, if any.

  • max_samples (int | None) – Shots to request. None submits without a shot argument (exact probabilities).

Returns:

Handle of the submitted asynchronous job.

Return type:

perceval.runtime.RemoteJob

class merlin.core.perceval_adapter.JobStatusSnapshot(job_id, state, progress, stop_message, is_complete, is_failed)

Bases: object

Merlin-normalized view of a Perceval remote job’s status.

All getattr guards against Perceval job internals live in PercevalAdapter.job_snapshot(); consumers only see these fields.

is_complete: bool
is_failed: bool
job_id: Optional[str]
progress: Any
state: Any
stop_message: Any
class merlin.core.perceval_adapter.LocalExperimentSnapshot(circuit_size, in_ports, out_ports, detectors, detectors_injected, in_mode_type, out_mode_type, anon_herald_num, postselection)

Bases: object

Experiment-level state that must survive local circuit replacement.

Captures the Perceval experiment private state (ports, detectors, mode types, heralds, postselection) that clear_input_and_circuit() wipes.

anon_herald_num: int
circuit_size: int
detectors: tuple[Optional[Any], ...]
detectors_injected: tuple[int, ...]
property has_mode_metadata: bool

Return whether metadata is tied to a concrete circuit mode layout.

in_mode_type: tuple[Any, ...]
in_ports: tuple[tuple[Any, tuple[int, ...]], ...]
out_mode_type: tuple[Any, ...]
out_ports: tuple[tuple[Any, tuple[int, ...]], ...]
postselection: Any
class merlin.core.perceval_adapter.TokenExtractionError

Bases: ValueError

Signals that no auth token could be resolved for a RemoteProcessor.

Raised by callers of PercevalAdapter.extract_token() when it returns None (see MerlinProcessor.__init__). extract_token itself returns None rather than raising, so its multi-strategy fallback (handler token, Bearer header, global RemoteConfig) can run to completion before the caller decides the token is genuinely unresolvable.

Subclasses ValueError so existing callers catching the historical exception type keep working.

class merlin.core.perceval_adapter.RemoteJobFailedError

Bases: RuntimeError

Raised when a remote Perceval job reports failure.

Subclasses RuntimeError so existing callers catching the historical exception type keep working.