Transpilation

Transpilation#

Two helpers, transpile_subcircuits() and transpile_experiments(), differing in when they run:

fake = IQMFakeAdonis() #noisy
sim = AerSimulator() #ideal

transpile_circuits() does whichever of the two the thing it is given calls for. Each subcircuit once, before the experiment circuits are built:

transpiled = ck.transpile_circuits(cut_circuit, fake, optimization_level=3)
cut_experiment = ck.get_experiment_circuits(transpiled, observables)

Or every experiment circuit, afterwards:

cut_experiment = ck.transpile_circuits(
    ck.get_experiment_circuits(cut_circuit, observables), fake, optimization_level=3
)

Given a cut circuit it is much the faster of the two, but the subcircuits still carry the cut and observable placeholders, so the transpiler is working on a circuit it cannot see all of. It therefore disallows remove_final_rzs (False by default on iqm_client>=36.0.0) and optimize_single_qubits and raises if you pass them. Given an experiment there are no placeholders left, so it optimises further.

A cut circuit is transpiled as its subcircuits, never as the whole circuit: the pieces run separately, so each is placed on the device on its own, and the whole circuit need not fit the device at all. The transpiled CutCircuit remembers the backend it was transpiled for, which is what Primitives check before running it.

Plain circuits are transpiled as they are, which is what a backend handed circuits rather than an experiment needs. See Running on several backends.

On an IQM backend both use IQM’s own transpiler. Pass use_iqm_transpiler=False for the ordinary Qiskit path. On a resonator device such as IQMFakeDeneb the MOVE gates are routed in for you.