Qiskit v0.45 is here!

Qiskit
Qiskit
Published in
9 min readNov 6, 2023

By Abby Mitchell, Luciano Bello, Matthew Treinish, Jake Lishman

We’re excited to announce the release of Qiskit v0.45! Read on for a summary of the key highlights and, as always, you can find the full release notes in our documentation here. With this being the last release before Qiskit 1.0, you’ll notice a lot of changes which we’ve highlighted in the article below.

The TL;DR

The biggest updates we’re going to cover include the following:

  • New passmanager submodule to make constructing passmanagers easier
  • New hardware-aware synthesis functionality, so you can now write a synthesis plugin that uses hardware information
  • New methods to make it easier to use TranspileLayout
  • New SabrePreLayout pass to provide a better “first guess” initial layout before running SabreLayout
  • Performance improvements due to refactoring gates into singletons (Note: Some attributes will now error because of mutability changes)
  • Unroller pass, bind_parameters() and any duplicated gate methods are now deprecated. qiskit.extensions is pending deprecation
  • Deprecated code from old releases (0.16, 0.19, 0.20 and 0.21) has been removed

An important note about package versioning

If you’re confused about version numbers and think you may have missed out on a lot — don’t panic! In our last release, we announced that we had renamed Qiskit Terra to just Qiskit. This means the python package qiskit (which used to refer to the metapackage codebase) now refers to the codebase that was formerly named qiskit-terra. The last phase of this renaming process is to sync the version numbers between the old qiskit metapackage (the last release was v0.44) and the old qiskit-terra (the last release was v0.25). We chose to stick with the higher version number, so this release of qiskit will be v0.45.

Top new features & improvements

In this section we’ll cover some of the most important new features and enhancements included in this release. If you want to know more about these, or other features that didn’t make it into this article, you can see the full list of new features here.

New passmanager sub-module

The passmanager has been significantly refactored to make it easier to use and more performant. Users can use this new module to create their own custom passmanager using their own intermediate representations.

The following example demonstrates how you can construct a toy passmanager that, when run, will take in a row of numbers and remove any digits that equal 5. In this example, the input and outputs are integers, whereas the intermediate representation is a string:

from qiskit.passmanager import BasePassManager, GenericPass, ConditionalController

# create custom passmanager using BasePassManager
class ToyPassManager(BasePassManager):

# convert input integer to string
def _passmanager_frontend(self, input_program: int, **kwargs) -> str:
return str(input_program)

# convert IR string to integer for output
def _passmanager_backend(self, passmanager_ir: str, in_program: int, **kwargs) -> int:
return int(passmanager_ir)


# Create a pass to remove a number if it equals 5
class RemoveFive(GenericPass):

def run(self, passmanager_ir: str):
return passmanager_ir.replace("5", "")

# Initialize pass
task = RemoveFive()

# Initialize passmanager
pm = ToyPassManager()

# Add pass to passmanager
pm.append(task)

# Run the passmanager
pm.run([123456789, 45654, 36785554])

Output:

[12346789, 464, 36784]

Improved workflow for transpiler layout

A number of new methods have been added to simplify the workflow for using and applying the TranspileLayout class.

TranspileLayout itself now has the following new methods:

  • .initial_index_layout() — returns a python list of TranspileLayout.initial_layout
  • .routing_permutation() — returns a python list of TranspileLayout.final_layout
  • .initial_virtual_layout() — same functionality as TranspileLayout.initial_layout but with the option to exclude auxilary qubits by setting the argument filter_ancillas=False
  • .final_index_layout() — returns a python list of the output positions for each qubit from the input circuit to the transpiler
  • .final_virtual_layout() — returns a Layout object of the output positions for each qubit from the input circuit to the transpiler

In addition, the SparsePauliOp class now has a new method, apply_layout(), that enables a transpiled layout to be applied to an observable locally before passing it to a primitive .run() function. E.g.:

from qiskit.circuit.library import RealAmplitudes
from qiskit.quantum_info import SparsePauliOp
from qiskit.primitives import BackendEstimator
from qiskit.compiler import transpile
from qiskit.providers.fake_provider import FakeNairobiV2

psi = RealAmplitudes(num_qubits=2, reps=2)
H1 = SparsePauliOp.from_list([("YX", 1), ("XZ", 2), ("XI", 3)])
backend = FakeNairobiV2()
estimator = BackendEstimator(backend=backend, skip_transpilation=True)

thetas = [0, 1, 1, 2, 3, 5]
transpiled_psi = transpile(psi, backend, optimization_level=3)


permuted_op = H1.apply_layout(transpiled_psi.layout)

res = estimator.run(transpiled_psi, permuted_op, thetas).result()

New SabrePreLayout pass

This release includes a new transpiler pass, called SabrePreLayout, designed to provide a better initial layout before running SabreLayout. This layout attempts to improve transpilation outputs in particular for large device topologies.

The following example demonstrates how to use the SabrePreLayout pass before running a SabreLayout pass:

import math
from qiskit.transpiler import CouplingMap, PassManager
from qiskit.circuit.library import EfficientSU2
from qiskit.transpiler.passes import SabrePreLayout, SabreLayout

qc = EfficientSU2(16, entanglement='circular', reps=3, flatten=True)
qc.assign_parameters([math.pi / 2] * len(qc.parameters), inplace=True)
qc.measure_all()

coupling_map = CouplingMap.from_heavy_hex(7)

pm = PassManager(
[
SabrePreLayout(coupling_map=coupling_map),
SabreLayout(coupling_map),
]
)

pm.run(qc)

For more details on how this new pass does its thing, check out the PR for a more detailed description of the logic behind its development.

Note: This new feature is an experimental pass and is not yet included in the preset passmanagers.

Performance improvements

In this section, we’ll cover the most significant performance improvements that users will gain with this release.

Faster transpilation

The transpiler has undergone some refactoring under the hood, resulting in performance improvements across all optimization levels. Users do not need to change anything in their transpiler development workflow. However, by upgrading to the latest version of Qiskit, you should see faster transpilation times, particularly noticeable for large circuit depths.

The graphs below show the difference in transpile time between Qiskit v0.44 and v0.55 across a range of circuit depths and optimization levels:

Faster circuit construction and QASM parsing due to Singleton classes

The following unparameterised and non-controlled gate classes have been refactored to be singletons:

As a result, implementing these gates has become significantly more efficient, requiring less memory, reducing circuit construction time and speeding up QASM parsing time. These effects are most noticeable in large circuits, and highlight the efforts being made to ensure Qiskit can continue to support users as they move towards utility-scale experimentation.

See below a comparison of circuit build time and parameter binding time between Qiskit v0.44 and 0.45:

New deprecations

In this section we’ll cover some of the most important new deprecations in this release. This section aims to highlight things that will now start throwing deprecation warnings and will be removed in a later release, following Qiskit’s Deprecation Policy (documented in full here). Due to this being the last release before Qiskit 1.0, you may see more things than usual being highlighted in this section.

For guidance on how to deal with deprecation warnings, check out the deprecations section in our previous article here. You can see more detail about the deprecations specific to this release here.

qiskit.extensions

The qiskit.extensions sub-module is pending deprecation and will be fully deprecated in a future release, with its contents either being moved to other sub-modules or deprecated.

The following qiskit.extensions classes have been moved to the circuit library, users should update their import statements accordingly, using from qiskit.circuit.library import ... instead of from qiskit.extensions import ... .

  • UCPauliRotGate , UCRXGate , UCRYGate , UCRZGate , UnitaryGate , HamiltonianGate , Initialize

The following qiskit.extensions classes have been deprecated, due to them being similar to existing functionality elsewhere:

  • SingleQubitUnitary and Snapshot

Additionally, the following QuantumCircuit methods have been deprecated as part of this change:

  • .isometry(), .snapshot(), .ucrx(), .ucry(), .ucrz(), .squ(), .diagonal() and .hamiltonian()

Unroller transpiler pass

The Unroller pass has been deprecated due to its functionality being superseded by the BasisTranslator pass, which can be used in a wider range of use cases than was possible with the Unroller pass.

For users currently using the Unroller pass, we recommended updating your code to use a custom pass manager with the BasisTranslator pass. For example:

from qiskit.transpiler import PassManager
from qiskit.transpiler.passes import UnrollCustomDefinitions, BasisTranslator
from qiskit.circuit.equivalence_library import SessionEquivalenceLibrary as sel

circuit = YOUR_CIRCUIT
basis_gates = YOUR_BASIS_GATE_LIST

pm = PassManager(
[
UnrollCustomDefinitions(sel, basis_gates=basis_gates),
BasisTranslator(sel, target_basis=basis_gates),
]
)

pm.run(circuit)

In addition, as part of this deprecation, the use of the unroller value for the translation_method argument in the transpile() function is also deprecated. Users should use the default translator option instead. So, instead of transpile(qc, backend, translation_method="unroller", ...) , users can use transpile(qc, backend, ...) .

bind_parameters()

The functionality of assign_parameters() is the same as that of bind_parameters() , so we’ve made the decision to deprecate bind_parameters() in an effort to clean up the Qiskit codebase. Users should update their code to use assign_parameters() instead of bind_parameters() going forward.

Duplicated circuit gate methods

There are certain QuantumCircuit methods that apply the same gate as another existing method, so duplicated gate methods have been deprecated, and going forward only one gate method will exist for each gate. The following methods are being deprecated by this change:

  • .i() is deprecated; users should use .id() instead
  • .cnot() is deprecated; users should use .cx() instead
  • .toffoli() is deprecated; users should use .ccx() instead
  • .mct() is deprecated; users should use .mcx() instead
  • .fredkin() is deprecated; users should use .cswap() instead

Breaking changes

In this section we’ll highlight any changes that could cause user’s existing code to break when updating to this latest version, such as deprecated classes/functions that have now been removed.

Deprecated code from numerous prior releases has been removed

Due to the upcoming release of Qiskit 1.0, we are doing as much as we can to remove outdated code that has been throwing deprecation warnings for 3 months or more (in line with the removal timeline stipulated in our deprecation policy). In this release we have removed all code that was deprecated in Qiskit (Terra) releases 0.16, 0.19, 0.20 and 0.21. Users who are using deprecated code from these release versions should check the deprecation warnings for information on how to update your code, or consider pinning your Qiskit version to v0.44 or earlier.

Singleton Gates

Due to unparameterised and non-controlled gates being refactored to singletons, users will no longer be able to set the label, condition, duration, or unit attributes after instantiating a gate object. Instead users will now only be able to set these attributes as arguments when creating a new gate object, or use the new method .to_mutable() to get a mutable copy of the gate and set the attribute on that copy instead of the original object.

For example, the following code will now throw an error:

from qiskit.circuit.library import XGate

x_gate = XGate()
xgate.label = "My X Gate"

Instead, this example could be refactored like so:

from qiskit.circuit.library import XGate

x_gate = XGate(label="My X Gate")

or alternatively:

from qiskit.circuit.library import XGate

x_gate = XGate().to_mutable()
xgate.label = "My X Gate"

And there you have it! The most important details of the latest release. Remember, if you want to put ideas forward for future versions of Qiskit, you can always open a GitHub issue to request a feature or report a bug! And if you want to follow what’s coming up in the next release (as well as releases for other packages in the Qiskit Ecosystem), you can take a look at the Qiskit Release Planning Wiki.

Many people contributed to this release, special thanks to (in alphabetical order): Abby Mitchell, Abhiraj Shrotriya, Abigail J. Cross, Alexander Ivrii, AlexanderGroeger, Andir16, Aniket Patil, Christopher J. Wood, David McKay, Diego Emilio Serrano, Edwin Navarro, Elena Peña Tapia, Eric Arellano, Erick Winston, Evgenii Zheltonozhskii, Henry Zou, Hunter Kemeny, Ikko Eltociear Ashimine, Ikko Hamamura, Jake Lishman, Jay M. Gambetta, John Lapeyre, Joonghoon Lee, Julien Gacon, Kevin Hartman, Kevin J. Sung, Kyle Lund, Luciano Bello, Mahnoor Fatima, Matthew Treinish, Michał Górny, MozammilQ, Naoki Kanazawa, Paul Nation, Pieter Eendebak, Raghav, Raynel Sanchez, Ryuhei Yoshida, SamD-1998, Santhosh G S, Simone Gasperini, Takashi Imamichi, Toshinari Itoko, TsafrirA, Will Shanks, adigaboy, atharva-satpute, danielleodigie, jaeunkim, rht

--

--

Qiskit
Qiskit

An open source quantum computing framework for writing quantum experiments and applications