Skip to main contentIBM 

Release news: Qiskit SDK v1.3 is here!

Technical release summary for Qiskit SDK v1.3, including details on top new features and improvements, and new deprecations.


4 Dec 2024

Qiskit Team

Today, we're excited to announce the release of Qiskit SDK v1.3! The latest SDK release represents a substantial step forward in our ongoing efforts to rewrite Qiskit's core data model in Rust, a transition that continues to yield new efficiencies and performance improvements.

As you likely already know, Rust is a high-performance programming language that has helped alleviate many bottlenecks that previously came from having key components of the Qiskit SDK written in Python. Today, nearly a quarter of of the lines of code that make up the SDK’s core are written in Rust, up from just over 5% with the Qiskit SDK 1.0 release back in February.

So far, most of that conversion has taken place in the core data model for circuits and transpilation, which are now almost entirely Python-free. Today, the majority of our transpiler passes that we run in the default pass managers are written primarily in Rust, which has made binding and transpiling significantly faster.

The long-term goal is to enable the addition of a C language API on top of Qiskit, which is on track to be introduced at some point during the Qiskit SDK v2.x series. This is one of the biggest motivators for migrating both the core data model behind Qiskit's circuit representation and the transpiler internals to Rust without any runtime dependency on Python. This work will bring considerable performance improvements to Qiskit for all users, regardless of your choice of interface. Qiskit SDK v1.3 is an important milestone, but there is still plenty of work left to do.

Stay tuned for more details on our long-term journey towards complete Rust conversion, and read on for more information on the latest minor version release, Qiskit SDK v1.3!

The TL;DR

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

  • Most of the passes used during quantum circuit transpilation are now in Rust, resulting in a ~6x speedup for transpiling tasks.

  • The circuit library has undergone a major refactor as part of an effort to clarify the distinction between circuits that are defined by their structure (e.g. quantum volume circuits or circuits in the n-local family) and circuits defined by an abstract mathematical operation (e.g. QFT or Pauli evolution).

  • As part of the circuit library refactor, you will now have new gates support for HighLevelSynthesis plugins, which also includes ancilla support. One of these changes includes the PauliEvolution gate that now offers the option to use Rustiq, a popular external library that has been integrated into the core stack.

  • IBM is in the process of deprecating pulse-level control on IBM Quantum hardware, and will remove it from all QPUs as of 3 February, 2025. The SDK’s support of pulse will be deprecated in Qiskit SDK v1.3. You can use the new fractional gates or resources like Qiskit Dynamics as a replacement for many common Qiskit Pulse use cases.

Top New Features & Improvements

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

Most transpilation passes now in Rust for ~6x speedup

All of the main passes in the default pass manager are now written in Rust. This has resulted in significant performance improvements, such that running the full Benchpress suite of performance benchmarks with Qiskit SDK v1.3 now takes less than an hour, as opposed to the 6+ hours required for Qiskit SDK v1.2.

As you can see from the chart below, these improvements occur across the board for all but five out of the 1,000+ Benchpress tests:

Qiskit-SDK-v1_3-image1.png

This chart shows a runtime performance comparison between v1.2.4 and v1.3.0. Each dot represents an individual Benchpress test. Dots which appear above the black diagonal line in the center of the chart indicate that the test’s runtime has improved in v1.3 as compared to v1.2. If the dot appears on the line, its runtime is equal in both v1.2 and v1.3. Dots that appear the below black line represent the few tests for which runtime is now longer in v1.3 as compared to v1.2. The lines separating the shaded regions above the black line indicate runtime improvements of 5x, 20x, 80x, and 320x.

Refactoring the circuit library

The circuit library has undergone a major refactor that should help create a clearer distinction between circuits that are defined by their structure and circuits defined by an abstract mathematical operation.

Circuits defined by their structure have a unique decomposition. They are now being exposed as functions to generate the circuit, rather than as QuantumCircuit subclasses. Functions are a better fit for generating a circuit object with a given structure. By contrast, the QuantumCircuit subclasses didn’t offer any specialization; they were just circuit objects. The majority of these new functions are also being written in Rust to deliver significantly improved construction speed. See pull requests here and here for examples of that speedup.

Here is an example of how to construct a real-amplitudes 2-local circuit:

Qiskit-SDK-v1_3-image2-RealAmplitudes.png

Circuits that represent an abstract operation are being rewritten as gate classes and will have new plugins written for high-level synthesis. In these cases, there is no one way to synthesize the operation, so representing the operation as gate classes gives the transpiler an opportunity to choose a better synthesis depending on how the operation functions in the context of the circuit.

Take the following example, where the multi-controlled X gate (MCXGate) is an abstract operation:

Qiskit-SDK-v1_3-image3v3-mcx.png

At transpilation-time, the gate is synthesized using the context around it. In this case, it can use auxiliary qubits that are available:

Qiskit-SDK-v1_3-image4-mcx_synth.png

Note that the previous versions of library circuits, which were all instances of QuantumCircuit are still supported. However, we strongly suggest you move to the new versions leveraging better performance and more optimized decompositions. In the following figure, we compare construction and decomposition into standard gates for a set of circuits between Qiskit 1.0 and Qiskit 1.3. Due to construction in Rust, the circuit library is faster than (potentially optimized) manual circuit constructions, too.

Qiskit-SDK-v1_3-image5.png

This change will also give users the ability to write plugins for the synthesis of these types of objects more easily, since Qiskit already defines a place for them.

Representing abstract operations as Instructions is particularly powerful in combination with the improvements to the HighLevelSynthesis transpiler pass. When decomposing the more abstract objects into lower-level gates, this pass tries to find the highest-quality decomposition (or “synthesis”) available for a given gate. With Qiskit v1.3, it can analyze the gate context and leverage idle auxiliary qubits. This workflow is summarized below:

Qiskit-SDK-v1_3-image6-HLS.png

There are a large number of new available plugins, for example for the PauliEvolutionGate, HalfAdderGate and others. Here’s an example of using this new capability with the PauliEvolutionGate:

Additionally, HighLevelSynthesis plugin are supported for many of the gates in the circuit library, including PauliEvolutionGate. Continuing the previous example, we can instead use the “rustiq” plugin for PauliEvolutionGate, which is based on this paper:

This synthesis method may produce significantly shorter circuits for complex Hamiltonians.

Additional new features and improvements

  • Added a new observable class, SparseObservable has been introduced. This object stores observables as a sum of terms as a sequence of qubit, bit_term pairs in a memory efficient way.
  • Added evolved_operator_ansatz(), hamiltonian_variational_ansatz(), and qaoa_ansatz() to the circuit library to implement variational circuits based on operator evolutions. evolved_operator_ansatz() and qaoa_ansatz() are functionally equivalent to EvolvedOperatorAnsatz and QAOAAnsatz, but generally more performant.
  • Added a new transpiler pass, RemoveIdentityEquivalent that is used to remove gates that are equivalent to an identity up to some tolerance.

High Priority Bug Fixes

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

  • Fixed a bug that caused Statevector.expectation_values() to yield incorrect results.
  • Fixed a bug in the transpiler pass ElidePermutations where the qubit mapping was not updated correctly in the presence of PermutationGates.
  • Fixed an issue when running transpile() or run() on a pass manager generated by generate_preset_pass_manager() using optimization_level 2 or 3 when the routing_method argument is set to "none" to explicitly disable routing.

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). 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.

Deprecating pulse-level access

As we announced in the blog introducing fractional gates, pulse-level access has been deprecated in the Qiskit IBM Runtime package alongside the introduction of fractional gates, and is currently only supported on a subset of Eagle devices. This backend support for Qiskit Pulse instructions will be removed on IBM Quantum backends as of 3 February, 2025.

To align with the changes to the hardware and Runtime, and to ensure our focus remains on performance, we will be deprecating support for the qiskit.pulse module within the Qiskit SDK as well. Therefore, the qiskit.pulse module will be deprecated in this release and will be removed once Qiskit SDK v2.0 comes out.

Note that is not yet a breaking change. Qiskit Pulse will continue to be fully supported throughout the Qiskit SDK v1.x.x release cycle, and per the version strategy, the Qiskit SDK v1.x.x will continue to possess patch support 6 months after the Qiskit SDK v2.0 release. You can use the new fractional gates or resources like Qiskit Dynamics as a replacement for many common Qiskit Pulse use cases.

As part of the Qiskit Pulse deprecation, all pulse-related functionality in qiskit.providers.BackendV2 is being deprecated. This includes the following methods:

  • instruction_schedule_map()
  • drive_channel()
  • measure_channel()
  • acquire_channel()
  • control_channel()

Deprecating specifying custom gates solely by name in the transpiler

Providing custom gates by name through the basis_gates argument of transpile() and generate_preset_pass_manager() will be removed in Qiskit 2.0. You can still specify standard gates defined in qiskit.circuit.library for this argument. However, passing a name outside that set is being deprecated.

The challenge with passing a custom gate by name is that the transpiler doesn’t know what operation a given name refers to without the gate’s definitions. Custom gates are supported with a Target object which can be provided through the target argument to these functions. One can build a Target instance from scratch or use the Target.from_configuration() method with the custom_name_mapping argument which requires mapping a name with its gate object.

Deprecating certain transpile() and `generate_preset_pass_manager()’ arguments

The following transpile() and generate_preset_pass_manager() arguments are deprecated in favor of defining a custom Target. These arguments can be used to build a target with Target.from_configuration():

  • instruction_durations
  • timing_constraints
  • backend_properties

Deprecating .Instruction.condition and .Instruction.c_if

The .Instruction.condition attribute and the .Instruction.c_if method are now deprecated in favor of .if_test method, which is more flexible and completely superseded in functionality. The .if_test method allows you to express classical conditions as with contexts. For example, the following circuit using .Instruction.c_if can be expressed like this with .if_test.

Circuit using Instruction.c_if(now deprecated):

The same circuit using .if_test (new preferred method):

Final notes

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, you can take a look at the Qiskit milestones in GitHub.

Many people contributed to this release, special thanks to (in alphabetical order):

This blog post was written by Kaelyn Ferris with contributions from Abby Mitchell, Alexander Ivrii, Blake Johnson, Julien Gacon, Luciano Bello, Matthew Treinish, and Robert Davis.


View documentation