Farewell, Opflow and Quantum Instance

Qiskit
Qiskit
Published in
5 min readJun 21, 2023

--

By Elena Peña Tapia, Abby Mitchell and Julien Gacon

If you have read the Qiskit v0.43 release highlights (if not, go and read it here), you may have noticed that two of the former fundamental building blocks of Qiskit algorithms are being deprecated. We’re talking about Opflow and Quantum Instance. Once the deprecation period is over (in no less than three months or two releases), Opflow and Quantum Instance will be removed from our codebase.

We on the Qiskit team understand the importance of providing context when large deprecations occur, and we hope that this piece clears up any confusion you may have. The idea of this blog is to provide a deep dive into these elements, to show why we needed them before, and why we are moving towards another execution model.

Before jumping into our Qiskit history lesson, just a quick reminder to check out the following migration guides for more details on how the deprecations may affect your Qiskit workflow and how to adjust your code:

Why we’re deprecating Opflow

The decision to deprecate Opflow ultimately came down to two reasons: we wanted to prioritize a simpler user interface and improve performance with the use of qiskit.primitives.

The qiskit.opflow module was originally introduced as a layer between circuits and algorithms, a series of building blocks for quantum algorithms research and development. The core design of opflow was based on the assumption that the point of access to backends (real devices or simulators) was a backend.run() method, which takes in a circuit and returns its measurement results.

Under this assumption, all the tasks related to operator handling and building expectation value computations were left to the user to manage. Opflow helped bridge that gap by allowing users to wrap circuits and observables into operator classes that could be algebraically manipulated, so that the final result’s expectation values could be easily computed following different methods.

The recent introduction of the Qiskit primitives provided quantum algorithms with a new interface for interacting with backends. Now, instead of preparing a circuit to execute with an opflow converter that accesses backend.run(), the algorithms can leverage the Sampler and Estimator primitives, send parametrized circuits and observables, and directly receive quasi-probability distributions or expectation values respectively.

This workflow considerably simplifies the pre- and post-processing steps that previously relied on Opflow. For example, the Estimator primitive returns expectation values from a series of circuit-observable pairs, superseding most of the functionality of the
qiskit.opflow.expectations submodule. Without the need for building opflow expectations, most of the components in qiskit.opflow.operators also became redundant, as they commonly wrapped elements from qiskit.quantum_info.

Another key improvement that was made in wake of the launch of qiskit.primitives was the refactoring of the higher-level opflow sub-modules, qiskit.opflow.gradients and qiskit.opflow.evolutions, together with qiskit.algorithms, to take full advantage of the simplified primitives interface. Both gradients and new time evolution algorithms can now
be found as part of the qiskit.algorithms module.

As a result, the algorithm-writing process is much faster now. See the comparison below for developing an algorithm involving samples, expectation values, and state fidelities. The earlier version based on Opflow and backends is significantly more complex than the primitive-based version.

qiskit.algorithms.gradients (formerly qiskit.opflow.gradients) has also been improved, with the transition to primitives allowing us to provide users with an interface to plug in classical algorithms for benchmarking. We’ve also seen performance improvements, with the new gradient implementation providing less overhead and running significantly faster than before, particularly for deeper circuits:

What about Operator Globals?

If you read the opflow migration guide carefully, you might notice that all that glitters is not gold. Some convenience classes present in Opflow (operator globals), which allowed users to easily import and build from pre-made operators, are no longer available in the new framework.

However, the same operators can still be constructed following a
slightly longer path. For example, instead of doing:

from qiskit.opflow import H

operator = H ^ H

We now just need to build a quantum_info operator with the equivalent quantum circuit:

from qiskit import QuantumCircuit
from qiskit.quantum_info import Operator

qc = QuantumCircuit(2)
qc.h(0)
qc.h(1)

operator = Operator(qc)

While this implementation requires a few more lines of code, we believe that this partial loss of convenience is compensated by the flexibility and scalability of the alternative path, the simplicity of the primitive-based algorithm construction, and the potential for algorithmic performance
improvements.

All of the reasons outlined above encouraged us to move away from opflow, and find new paths of developing algorithms based on the qiskit.primitives interface and the qiskit.quantum_info module, which is a powerful tool for representing and manipulating quantum operators.

So… where does QuantumInstance fit into the picture?

Why we’re deprecating Quantum Instance

qiskit.utils.QuantumInstance was a utility class designed to encapsulate the configuration of the transpilation and execution steps for quantum algorithms. It was a wrapper over the transpiler and backend.run() to decouple the execution configuration from the algorithm configuration in the algorithm development pipeline. It was never really intended to be used as a standalone element, but rather as a supporting class that could be passed to Opflow converters instead of a specific backend.

Together with exposing a unified configuration path independent of the backend (simulator, real device, local or remote), it also provided users with job management utilities, such as job retries, setting job callbacks or establishing wait periods between jobs. This functionality is now exposed through different native implementations of primitives.

The combination of Quantum Instance and opflow’s CircuitSampler behaved like the new Sampler primitive. Meanwhile, introducing one of opflow’s expectation classes (for example, PauliExpectation) into the mix would return expectation values, a combination that can now be replaced with a single Estimator call.

So there you have it, those are the core reasons we’re saying goodbye to Opflow and Quantum Instance.

It’s worth bearing in mind that Qiskit is a living codebase, it’s constantly going through changes and improvements based on the latest advancements in quantum computing. And in order to keep up with these advancements we must balance developer time between developing new features and maintaining old ones. In some cases, there comes a point when the new, better functionality supersedes an earlier feature, so it makes more sense to focus developer time on the new and deprecate the old. This was the case with Opflow and Quantum Instance. This is always a difficult balance to strike, and we don’t make these decisions lightly, but deprecations like this are important steps for our team to take to ensure the long-term maintainability of Qiskit.

Both Opflow and Quantum Instance were introduced into our codebase to abstract away low-level Qiskit implementation details to algorithm developers. The primitives introduced a leaner alternative to these components, which allow for a more intuitive structure in algorithms, less lines of code, and help overcome certain performance bottlenecks introduced by Opflow. Hence we say:

Farewell, Opflow and Quantum Instance, and thanks for all the fish.

--

--

Qiskit
Qiskit

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