Migration guide#
This document describes the changes that need to be made to existing code to migrate between major versions of Pulla.
From 3.x to 4.0#
The changes in 4.0 are not truly breaking, as your code should still run. However, there are some changes that might affect the compilation results, and you might want to adjust your code accordingly:
New compilation pass
prepend_reset
added to the (TimeBox-level) standard compiler stage. It adds a reset timebox to all circuits. It is the last pass of the TimeBox-level stage. If the calibration lacks reset_wait data, theprepend_reset
will have no effect.Optional attribute :attr:
.CircuitExecutionOptions.active_reset_cycles
added to CircuitExecutionOptions, that is used to control the reset functionality. By default, it is set toNone
, which results in delay by wait.:meth`.Pulla.get_standard_compiler` now has an optional argument for overriding default circuit execution options.
From 2.x to 3.0#
The function iqm.pulla.utils_qiskit.qiskit_to_cpc
was replaced by
iqm.pulla.utils_qiskit.qiskit_circuits_to_pulla()
and iqm.pulla.utils_qiskit.qiskit_to_pulla()
.
qiskit_circuits_to_pulla()
is a more direct replacement, with the difference that it also requires a
mapping of qiskit qubit indices to physical qubit names which was not required before.
This can be e.g. obtained from an iqm.qiskit_iqm.iqm_provider.IQMBackend
instance.
qiskit_to_pulla()
is a convenience method that in addition to
converting the Qiskit circuit(s) also returns a Compiler
instance that can be used to compile them
into a playlist. It takes as additional parameters a Pulla
instance (for building the compiler),
and an IQMBackend
instance (containing the calibration set ID and
qubit mapping to use). The IQMBackend instance should usually be the same one that was used to transpile
the Qiskit circuits.
# BEFORE
pulla_circuits = qiskit_to_cpc(qiskit_circuits)
# AFTER
pulla_circuits = qiskit_circuits_to_pulla(qiskit_circuits, qubit_idx_to_name)
# or
pulla_circuits, compiler = qiskit_to_pulla(pulla, backend, qiskit_circuits)
From 1.x to 2.0#
Compiler code is consolidated under the iqm.cpc.compiler.compiler
module.
There is no more iqm.cpc.compiler.compiler2
.
Compiler
, CompilationStage
are now under iqm.cpc.compiler.compiler
.
Pulla
no longer needs CoCoS URL:
# BEFORE
Pulla(cocos_url=cocos_url,station_control_url=station_control_url)
# AFTER
p = Pulla(station_control_url)
Compiler
initialization now requires all arguments to be keyword arguments.
# BEFORE
return Compiler(
calibration_set,
chip_topology,
channel_properties,
component_channels,
qubit_mapping,
stages=get_standard_stages(),
)
# AFTER
return Compiler(
calibration_set=calibration_set,
chip_topology=chip_topology,
channel_properties=channel_properties,
component_channels=component_channels,
qubit_mapping=qubit_mapping,
stages=get_standard_stages(),
)
Pulla no longer retrieves qubit mapping from CoCoS. If your circuit uses same qubits names as physical qubits
(e.g. QB1
, QB2
, etc.), then you don’t have to do anything. If your circuit uses other qubit names, then you have to
provide component_mapping
to the Compiler like so:
compiler.component_mapping = {'0':'QB1', '1':'QB2', '2':'QB3'}
If you use Qiskit, the mapping can be generated with {str(idx): qb for idx, qb in backend._idx_to_qb.items()}
.
.Compiler.set_default_implementation_for_locus
changed to Compiler.set_default_implementation_for_loci()
:
# BEFORE
compiler.set_default_implementation_for_locus('cz', 'tgss', ('QB1', 'QB2'))
# AFTER
compiler.set_default_implementation_for_loci('cz', 'tgss', [('QB1', 'QB2')])
Compiler.amend_calibration_for_gate_implementation()
now accepts a Locus (a tuple of strings)
instead of string qubit name, so you can apply the change to multiple loci in a single call:
# BEFORE
compiler.amend_calibration_for_gate_implementation('prx', 'raised_cosine', qubit, CUSTOM_CAL_DATA)
# AFTER
compiler.amend_calibration_for_gate_implementation('prx', 'raised_cosine', (qubit,), CUSTOM_CAL_DATA)
iqm.pulla.utils.qiskit_to_cpc()
and iqm.pulla.station_control_result_to_qiskit()
, previously marked for
deprecation in v. 1.0, are now removed. Use iqm.pulla.utils_qiskit.qiskit_to_cpc()
and
iqm.pulla.utils_qiskit.station_control_result_to_qiskit()
, respectively.
From 0.x to 1.0#
The main change in 1.0 is the splitting of Pulla
and Compiler
, and the move of some compiler-related methods to
the more appropriate Compiler
class. The Pulla
class now only contains methods to retrieve calibration data,
construct a standard compiler instance, and submit pulse schedules to the server.
# BEFORE
pulla = Pulla(cocos_url="<cocos_url>")
pulla.compiler.stages = STANDARD_STAGES
pulla.compiler.compile(circuits)
pulla.compiler.build_settings(context, shots=100)
pulla.execute(playlist, context, settings)
# AFTER
pulla = Pulla(cocos_url="<cocos_url>", station_control_url="<station_control_url>")
compiler = p.get_standard_compiler() # already contains standard stages by default
compiler.compile(circuits)
compiler.build_settings(context, shots=100)
pulla.execute(playlist, context, settings)
Setting default implementation is now done in the compiler directly, and there is no need to manually refresh the compiler anymore.
# BEFORE
pulla.gates['cz'].set_default_implementation('slepian')
pulla.gates['cz'].set_default_implementation_for_locus('tgss', ('QB1', 'QB2'))
pulla.refresh_compiler()
# AFTER
compiler.gates['cz'].set_default_implementation('slepian')
compiler.gates['cz'].set_default_implementation_for_locus('tgss', ('QB1', 'QB2'))
# no refresh needed
Same goes for adding implementations, and amending the calibration set with custom data for custom implementations:
# BEFORE
pulla.add_implementation(...)
pulla.amend_calibration_for_gate_implementation(...)
# AFTER
compiler.add_implementation(...)
compiler.amend_calibration_for_gate_implementation(...)
The calibration is now stored solely in the compiler instance, and can be retrieved using
Compiler.get_calibration()
:
# BEFORE
current_calibration_set = pulla.get_current_calibration()
# AFTER
current_calibration_set = compiler.get_calibration()
Fetching calibration sets from the server is still done via Pulla.fetch_latest_calibration_set()
and Pulla.fetch_calibration_set_by_id()
.
Standard compilation stages are now available via get_standard_stages()
. This ensures the immutability of
built-in standard stages.
# BEFORE
from iqm.cpc.compiler.standard_stages import STANDARD_STAGES
stages = STANDARD_STAGES
# AFTER
from iqm.cpc.compiler.standard_stages import get_standard_stages
stages = get_standard_stages()