Skip to main contentIBM Quantum Documentation

Qiskit SDK 1.2 release notes


1.2.4

Prelude

Qiskit 1.2.4 is a patch release that fixes a QPY problem introduced in the yanked 1.2.3 bugfix release. In 1.2.3, an error would be raised when loading a QPY file that was generated with a different symengine version from the version installed when loading.

Bug Fixes

  • Fixed an issue introduced in the now yanked 1.2.3 bugfix release that would cause an exception with the error message “Qiskit doesn’t support loading a symengine payload generated with symengine >= 1.0” to be raised whenever loading a QPY file that was generated with a different symengine version from the version installed when loading. This issue could only occur in 1.2.3.

1.2.3

Prelude

Qiskit 1.2.3 is a patch release fixing a problem in QPY that could cause files generated by one Python environment to fail to load in a different Python environment, despite the format supposedly being transferable. This is related to differences in the version of the library symengine, which QPY should have protected against.

Known Issues

  • Versions of Qiskit before 1.2.4 will not be able to load QPY files dumped using qpy.dump(), even with version set appropriately, if:

    • there are unbound ParameterExpression objects in the QPY file,
    • the use_symengine=True flag was set (which is the default in Qiskit >= 1.0.0) in qpy.dump(), and
    • the version of symengine installed in the generating and loading environments are not within the same minor version.

    This applies regardless of the version of Qiskit used in the generation (at least up to Qiskit 1.2.4 inclusive).

    If you want to maximize compatibility with versions of Qiskit < 1.2.3, you should set use_symengine=False. Versions of Qiskit >= 1.2.3 should not require this.

  • QPY files from the Qiskit 0.45 series can, under a very specific and unlikely set of circumstances, fail to load with any newer version of Qiskit, including Qiskit 1.2.4. The criteria are:

    • the QuantumCircuit or ScheduleBlock to be dumped contained unbound ParameterExpression objects,
    • the installed version of symengine was in the 0.9 series (which was the most recent release during the support window of Qiskit 0.45), and
    • the use_symengine=True flag was set (which was not the default).

    Later versions of Qiskit used during generation are not affected, because they required newer versions than symengine 0.9.

    In this case, you can recover the QPY file by reloading it with an environment with Qiskit 0.45.3 and symengine 0.9.2 installed. Then, use qpy.dump() with use_symengine=False to re-export the file. This will then be readable by any newer version of Qiskit.

Upgrade Notes

  • The supported versions of symengine have been pre-emptively capped at < 0.14.0 (which is expected to be the next minor version, as of this release of Qiskit). This has been done to protect against a potential incompatibility in qpy when serializing ParameterExpression objects. The serialization used in QPY Format versions 10, 11, and 12 for ParameterExpression objects is tied to the symengine version used to generate it, and there is the potential for a future symengine release to not be compatible. This upper version cap is to prevent a future release of symengine causing incompatibilities when trying to load QPY files using qpy.load().

Bug Fixes

  • Fixed an issue with qpy.load() when loading a QPY file containing a ParameterExpression, if the versions of symengine installed in the generating and loading environments were not the same. For example, if a QPY file containing ParameterExpression objects was generated using Qiskit 1.2.2 with symengine==0.11.0 installed, Qiskit 1.2.2 with symengine==0.13.0 installed would be unable to load it.

    Previously, an error would have been raised by symengine around this version mismatch. This has been worked around for symengine 0.11 and 0.13 (there was no 0.12). However, if you’re trying to use different versions of symengine and there is a mismatch, this version of Qiskit still might not work.


1.2.2

Prelude

Qiskit 1.2.2 is a minor bugfix release for the 1.2 series.

Bug Fixes

  • Fixed a bug in the transpiler pass ElidePermutations where the qubit mapping was not updated correctly in the presence of PermutationGates.

  • Fixed a potential source of non-determinism in DenseLayout (and by extension SabreLayout) when targeting a CouplingMap or Target that has more than one subgraph with the same degree of connectivity. In these case the exact output layout from the pass could previously fluctuate based on the number of local CPUs and thread execution speed.

  • The HighLevelSynthesis transpiler pass no longer raises an exception when encountering a custom gate that is called “qft” but is not an instance of QFTGate. Instead, the synthesis plugins for QFT gates ignore such a gate, and the gate’s definition is used (if provided).

  • Fixed a bug in the circuit drawers, which could fail or omit wires if idle_wires=False. Fixed #13128 and #13146.

  • Fixed an issue when calling transpile() or the method StagedPassManager.run() of 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. Previously under these conditions the transpiler would run the ElidePermutations pass as part of the init stage, as under normal conditions this is a useful optimization to remove SwapGate and PermutationGate instances from the circuit. But when routing_method="none" this optimization wasn’t expected as it permutes the circuit in a similar manner to routing, which shouldn’t be performed when routing_method="none". This has been fixed by no longer running ElidePermutations if routing_method="none" is set. Fixed #13144.

  • The OpenQASM 3 exporter has restored its behavior of accepting non-standard-library include files in the includes argument to qasm3.dump(), dumps(), and Exporter. These will insert a suitable include statement into the output as before, and the exporter remains unaware of the intended gates in that include file; you should pass the gates you expect it to define in the basis_gates argument to the same functions.

    We expect to improve the export mechanism against non-standard include files in a future release of Qiskit.


1.2.1

Prelude

Qiskit 1.2.1 is a minor bugfix release for the 1.2 series.

Bug Fixes

  • Fixed an issue with the visualizations of some backends/coupling maps that showed as folded on their own. The default ``neato` setting <https://graphviz.org/docs/layouts/neato/>`_ works well in most cases. However, prism overlap returns a more regular layout for other scenarios.

  • Parametric controlled standard-library gates (such as CRXGate) will now get correctly extracted to a Rust-space standard gate when using QuantumCircuit.append() and the gate object. Previously there was a discrepancy where using the QuantumCircuit.crx() method would cause a correct extraction in Rust space, but the append() form would not. The bug should generally not have caused any unsoundness from Python.

  • Fixed a bug in TwoQubitBasisDecomposer where the Rust-based code would panic if the given KAK gate was not a default version of the standard gates (for example, using CXGate(ctrl_state=0)). Fixed #12998.

  • Fixed a bug where InstructionDurations.from_backend() did not work for BackendV2 backends. Fixed #12760.

  • Fixed the definition of the CUGate matrix in Rust-space. While this was not noticable when handling the CUGate purely on the Python side, this had knock-on effects when transpiler passes were using the Rust representation, such as could happen in Consolidate2qBlocks. Fixed #13118.

  • Fixed a bug in HoareOptimizer where a controlled gate was simplified by removing its controls but the new gate was not handled correctly. Fixed #13079.

  • generate_preset_pass_manager() now correctly raises an exception, if seed_transpiler is set to an invalid value (i.e., it is not a non-negative integer). Fixed #12938.

  • Fixed an edge case in SabreLayout, where, in rare cases on large devices and challenging circuits, the routing would fail. This was due to the release valve making more than one two-qubit gate routable, where only one was expected. Fixed #13081.

  • Fixed a bug in Split2QUnitaries where it would fail to run on circuits with custom Gate objects that did not implement __array__. See #12970.

  • Fixed a bug in StatePreparation where the normalize argument was ignored for input arrays. Fixed #12984.

  • Fixed a bug where various synthesis methods created circuits without quantum or classical registers. This also affected functions that internally used the synthesis methods, such as Clifford.to_circuit(). While the circuits were valid, this could cause issues when comparing circuits with registers. Fixed #13041.

  • Fixed a bug that caused the method Initialize.gates_to_uncompute() fail. Fixed #12969.

  • Fixed an edge case when transpiling a circuit with optimization_level 2 or 3 with an incomplete 1-qubit basis gate set on a circuit containing 2-qubit gates, that can be implemented as a product of single qubit gates. This bug is resolved by restricting Split2QUnitaries to consider only UnitaryGate objects. Fixed #12970.


1.2.0

Prelude

The Qiskit 1.2.0 release focuses mainly on improving performance and quality of the compiler. Also, it is the last release supporting Python 3.8. In Qiskit 1.3.0 the minimal required Python version will be 3.9. Among a wide range of new features, improvements, and fixes, the release highlights are:

  • The circuit infrastructure, including gates and operations, is moved to Rust. This enables a series of speedups in circuit construction and circuit manipulation.
  • Leveraging the above point, parts of the synthesis library are now constructing circuits in Rust. This produces a significant speedup when synthesizing operations such as Cliffords, permutations, or linear functions. As example, decomposing 50+ qubit Cliffords benefit from an approximate 1000-fold speedup in runtime.
  • The quality of compiled circuits is improved by optimizing with a unitary peephole optimization at the initial stage of the transpilation workflow (at optimization level >1), and by using a dense layout as a Sabre layouting trial (at optimization level >0).

New Features

  • Added a new class QFTGate for natively representing Quantum Fourier Transforms (QFTs). The older way of representing QFTs via quantum circuits, see QFT, remains for backward compatibility. The new way of representing a QFT via a gate avoids synthesizing its definition circuit when the gate is declared, delaying the actual synthesis to the transpiler. It also allows to easily choose between several different algorithms for synthesizing QFTs, which are available as high-level-synthesis plugins.

  • Added a synthesis method synth_qft_full() for constructing a QFT circuit assuming a fully-connected architecture.

  • Added two high-level-synthesis plugins for synthesizing a QFTGate. The class QFTSynthesisFull is based on synth_qft_full() and synthesizes a QFT gate assuming an all-to-all connectivity. The class QFTSynthesisLine is based on synth_qft_line() and synthesizes a QFT gate assuming a linear-nearest-neighbor connectivity.

  • Added two parameters to GenericBackendV2 to exclude error (noise_info) and pulse channel information (pulse_channels) from the construction of the backend. These parameters are True by default, replicating the initial default behavior of the constructor. A memory-sensitive user may set these options to False to reduce the memory overhead by 40x when transpiling on large- scale GenericBackendV2.

  • The StabilizerState class now has a new method StabilizerState.probabilities_dict_from_bitstring() allowing the user to pass single bitstring to measure an outcome for. Previouslly the StabilizerState.probabilities_dict() would be utilized and would at worst case calculate (2n2^n) number of probability calculations (depending on the state), even if a user wanted a single result. With this new method the user can calculate just the single outcome bitstring value a user passes to measure the probability for. As the number of qubits increases, the more prevelant the performance enhancement may be (depending on the state) as only 1 bitstring result is measured.

  • Implemented UniformSuperpositionGate class, which allows the creation of a uniform superposition state using the Shukla-Vedula algorithm. This feature facilitates the creation of quantum circuits that produce a uniform superposition state 1Mj=0M1j\frac{1}{\sqrt{M}} \sum_{j=0}^{M-1} |j\rangle, where MM is a positive integer representing the number of computational basis states with an amplitude of 1M\frac{1}{\sqrt{M}}. This implementation supports the efficient creation of uniform superposition states, requiring only O(log2(M))O(\log_2 (M)) qubits and O(log2(M))O(\log_2 (M)) gates. Usage example:

    from qiskit import QuantumCircuit 
    from qiskit.circuit.library.data_preparation import UniformSuperpositionGate
     
    M = 5
    num_qubits = 3
    usp_gate = UniformSuperpositionGate(M, num_qubits)
    qc = QuantumCircuit(num_qubits)
    qc.append(usp_gate, list(range(num_qubits)))
     
    qc.draw()

Circuits Features

  • Added a new function random_clifford_circuit() to qiskit.circuit, that allows to generate a pseudo-random Clifford circuit with gates from the standard library. Example usage:

    from qiskit.circuit.random import random_clifford_circuit
     
    circ = random_clifford_circuit(num_qubits=2, num_gates=6)
    circ.draw(output='mpl')
    _images/release_notes-1.png
  • Added support for AnnotatedOperation.params and AnnotatedOperation.validate_parameter(), which enable circuit-level parameter handling (such as binding parameters) for annotated operations.

  • CircuitInstruction and DAGOpNode each have new methods to query various properties of their internal Operation, without necessarily needing to access it. These methods are:

    If applicable, using any of these methods is significantly faster than querying CircuitInstruction.operation or DAGOpNode.op directly, especially if the instruction or node represents a Qiskit standard gate. This is because the standard gates are stored natively in Rust, and their Python representation is only created when requested.

  • A native rust representation of Qiskit’s standard gate library has been added. When a standard gate is added to a QuantumCircuit or DAGCircuit it is now represented in a more efficient manner directly in Rust. Accessing that gate object from a circuit or DAG will return a new Python object representing the standard gate. This leads to faster and more efficient transpilation and manipulation of circuits for functionality written in Rust.

  • The random_circuit() function has a new feature where users can specify a distribution num_operand_distribution (a dict) that specifies the ratio of 1-qubit, 2-qubit, 3-qubit, and 4-qubit gates in the random circuit. For example, if num_operand_distribution = {1: 0.25, 2: 0.25, 3: 0.25, 4: 0.25} is passed to the function then the generated circuit will have approximately 25% of 1-qubit, 2-qubit, 3-qubit, and 4-qubit gates. Also it should be noted that the if num_operand_distribution is not specified then max_operands will default to 4 and a random circuit with a random gate distribution will be generated. If both num_operand_distribution and max_operands are specified at the same time then num_operand_distribution will be used to generate the random circuit.

    Example usage:

    from qiskit.circuit.random import random_circuit
     
    circ = random_circuit(
      num_qubits=6, depth=5, num_operand_distribution={1: 0.25, 2: 0.25, 3: 0.25, 4: 0.25}
    )
    circ.draw(output="mpl")
    _images/release_notes-2.png
  • Improved performance of the method DAGCircuit.quantum_causal_cone() by not examining the same non-directive node multiple times when reached from different paths.

  • Added the insert_barriers keyword argument to the QuantumCircuit.repeat() method. Setting it to True will insert barriers between circuit repetitions.

  • Replacing the internal synthesis algorithm of StatePreparation and Initialize of Shende et al. by the algorithm given in Isometry of Iten et al. The new algorithm reduces the number of CX gates and the circuit depth by a factor of 2.

  • ParameterExpression now supports the unary + operator.

Primitives Features

OpenQASM Features

  • The internal symbol table of the OpenQASM 3 exporter (qiskit.qasm3) has been rewritten, which should result in cleaner outputs when using Qiskit standard-library gates that are not in the OpenQASM 3 standard-library headers, and more deterministic outputs. For example, using several RZXGates will now result in only a single parametric definition, and when naming collisions occur, the symbol table will assign a deterministic counter to make names unique, rather than a non-deterministic integer (previously, the object identity was used).

  • The vendored version of the OpenQASM 3.0 standard library has been updated to match the state as of commit 4ca1d79383. This should generally have no effect on your use of Qiskit, unless you were retrieving our vendored file for your own use.

Synthesis Features

  • MCXRecursive with kk control qubits and a single clean auxiliary qubit now requires at most 16k816k-8 CX gates.

  • MCXVChain has two new Boolean parameters relative_phase and action_only. If action_only is True the circuit does not clean the dirty qubits. If relative_phase is True the gate is implemented up to a global phase. Both parameters are used to optimize the decomposition of MCXVChain.

  • MCXVChain with kk controls and k2k-2 dirty auxiliary qubits now requires 8k68k-6 CX gates.

  • Port synth_permutation_acg(), used to synthesize qubit permutations, to Rust. This produces an approximate 3x performance improvement on 1000 qubit circuits.

  • Port synth_permutation_basic(), used to synthesize qubit permutations, to Rust.

  • Port synth_cnot_count_full_pmh(), used to synthesize a linear function into a CX network, to Rust. This produces approximately 44x speedup, as measured on 100 qubit circuits.

  • The function synth_cnot_count_full_pmh() now allows choosing the (heuristically) optimal section_size by setting it to None. Then, a value is chosen which attempts to minimize the upper bound on the number of CX gates, that is αlog2(n)\alpha \log_2(n) where nn is the number of qubits and α0.56\alpha \approx 0.56.

  • The function synth_clifford_bm() was ported to Rust. Recall that this function optimally synthesizes Clifford operators on 1, 2 or 3 qubits with respect to the number of CX-gates. This leads to a significant increase in performance. For Cliffords over 3 qubits, the speedup in on the order of 80 times.

  • The function synth_clifford_greedy() that synthesizes Clifford operators was ported to Rust, leading to a significant increase in performance for all numbers of qubits. For Cliffords over 50 qubits, the speedup is on the order of 1000 times.

  • Added the wrap keyword argument to the ProductFormula classes which (when enabled) wraps individual Pauli evolution terms. This can be useful when visualizing circuits.

  • The atomic_evolution argument to ProductFormula (and its subclasses) has a new function signature. Rather than taking some Pauli operator and time coefficient and returning the evolution circuit, the new function takes in an existing circuit and should append the evolution of the provided Pauli and given time to this circuit. This new implementation benefits from significantly better performance.

  • Improved the performance of synth_permutation_depth_lnn_kms(), used to synthesize permutations for linear connectivity, by porting it to Rust.

Transpiler Features

  • Added a new import path option for generate_preset_pass_manager(), so that it can now be imported as:

    from qiskit import generate_preset_pass_manager

    instead of having to type the full path:

    from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager

    The function is also importable from the qiskit.transpiler module as:

    from qiskit.transpiler import generate_preset_pass_manager
  • Added a new user config file option sabre_all_threads and a corresponding environment variable QISKIT_SABRE_ALL_THREADS. When this flag is set the preset pass managers will run the SabreLayout and SabreSwap transpiler passes using all the available CPUs on the local system. Using this option is a tradeoff between determinism of output between different computers and potentially better output with fewer SwapGates.

    These transpiler passes run multiple random trials in parallel and pick the output which results in the fewest SwapGates. As a rule of thumb, if you run more trials, this provides the algorithm more opportunities to find a better result. By default, the preset pass managers use a fixed number of trials, in this release 5 trials for levels 0 and 1, and 20 trials for levels 2 and 3, but these numbers may change in future releases (and were different in historical releases). Using a fixed number of trials results in deterministic results regardless of the local system, because even with a fixed seed if you were to default to the number of local CPUs available the results would different when running between different computers.

    If the default number of trials for a given optimization level is higher than the number of local CPUs it will use the optimization level default which is higher.

  • Added a new pass Split2QUnitaries that iterates over all two-qubit gates or unitaries in a circuit and replaces them with two single-qubit unitaries, if possible without introducing errors, i.e., the two-qubit gate/unitary is actually a tensor product of single-qubit unitaries.

  • The passes Collect2qBlocks, ConsolidateBlocks and Split2QUnitaries have been added to the init stage of the preset pass managers with optimization level 2 and optimization level 3. The modification of the init stage should allow for a more efficient routing for quantum circuits that either:

    • contain two-qubit unitaries/gates that are actually a product of single-qubit gates, or
    • contain multiple two-qubit gates in a continuous block of two-qubit gates.

    In the former case, the routing of the two-qubit gate can simply be skipped as no real interaction between a pair of qubits occurs. In the latter case, the lookahead space of routing algorithms is not ‘polluted’ by superfluous two-qubit gates, i.e., for routing it is sufficient to only consider one single two-qubit gate per continuous block of two-qubit gates. These passes are not run if the pass managers target a Target that has a discrete basis gate set, i.e., all basis gates have are not parameterized.

  • The performance of StarPreRouting, used to find a star graph connectivity subcircuit, is improved by performing the heavy lifting in Rust space.

  • The SabreLayout transpiler pass has been updated to always run an additional trial using the same algorithm as DenseLayout to choose a starting point for Sabre’s layout algorithm. The starting point used by the layout algorithm can have a large influence on the quality of the results. By default SabreLayout still start with layout_trials random trials but in addition there will be a single trial that uses the densest subgraph of the connectivity graph as the starting point. This may yield better results in some cases especially on cases with smaller circuits for larger coupling maps.

  • A new dt argument has been added to generate_preset_pass_manager() to match the set of arguments of transpile(). This will allow for the internal conversion of transpilation constraints to a Target representation.

Visualization Features

  • The user configuration file has a new option circuit_idle_wires, which takes a Boolean value. This allows users to set their preferred default behavior of the idle_wires option of the circuit drawers QuantumCircuit.draw() and circuit_drawer(). For example, adding a section to ~/.qiskit/settings.conf with:

    [default]
    circuit_idle_wires = false

    will change the default to not display idle wires.

Misc. Features

  • Added a new build-time environment variable QISKIT_NO_CACHE_GATES which when set to a value of 1 (i.e. QISKIT_NO_CACHE_GATES=1) decreases the memory overhead of a CircuitInstruction and DAGOpNode object at the cost of increased runtime on multiple accesses to CircuitInstruction.operation and DAGOpNode.op. If this environment variable is set when building the Qiskit Python package from source the caching of the return of these attributes will be disabled.

Circuits Upgrade Notes

  • The annotated argument of the Gate.control() method is now None by default, which allows Qiskit to choose whether to annotate a controlled operation. If the concrete implementation (annotated=False) is available, it will be returned by default. Otherwise, the annotated implementation will be returned (annotated=True). This allows, for example, to defer the synthesis of controlled, parameterized gates.

  • The Operation instances of DAGOpNode.op being returned will not necessarily share a common reference to the underlying object anymore. This was never guaranteed to be the case and mutating the DAGOpNode.op directly by reference was unsound and always likely to corrupt the DAG’s internal state tracking Due to the internal refactor of the QuantumCircuit and DAGCircuit to store standard gates in Rust, the output object from DAGOpNode.op will now likely be a copy instead of a shared instance. If you need to mutate an element should ensure that you do:

    op = dag_node.op
    op.params[0] = 3.14159
    dag.substitute_node(dag_node, op)

    instead of doing something like:

    dag_node.op.params[0] = 3.14159

    which will not work for any standard gate in this release. It would have likely worked by chance in a previous release but was never an API guarantee.

  • The Operation instances of CircuitInstruction.operation being returned will not necessarily share a common reference to the underlying object anymore. This was never guaranteed to be the case and mutating the CircuitInstruction.operation directly by reference was unsound and always likely to corrupt the circuit, especially when parameters were in use. Due to the internal refactor of the QuantumCircuit to store standard gates in Rust, the output object from CircuitInstruction.operation will now likely be a copy instead of a shared instance. If you need to mutate an element in the circuit (which is strongly not recommended as it’s inefficient and error prone) you should ensure that you do:

    from qiskit.circuit import QuantumCircuit
     
    qc = QuantumCircuit(1)
    qc.p(0)
     
    op = qc.data[0].operation
    op.params[0] = 3.14
     
    qc.data[0] = qc.data[0].replace(operation=op)

    instead of doing something like:

    from qiskit.circuit import QuantumCircuit
     
    qc = QuantumCircuit(1)
    qc.p(0)
     
    qc.data[0].operation.params[0] = 3.14

    which will not work for any standard gates in this release. It would have likely worked by chance in a previous release but was never an API guarantee.

Primitives Upgrade Notes

  • BitArray.slice_bits() and BitArray.slice_shots() will now raise IndexError when indices are out of bounds. They used to raise ValueError in the case.

  • BitArray.__getitem__() will now raise IndexError when indices are out of bounds or the number of dimensions of indices does not match that of BitArray. They used to raise ValueError in the case.

Synthesis Upgrade Notes

  • LieTrotter and SuzukiTrotter no longer wrap the individually evolved Pauli terms into gate definitions. If you rely on a certain decomposition level of your circuit, you have to remove one level of QuantumCircuit.decompose() or add the wrap=True keyword argument to your synthesis object.

Transpiler Upgrade Notes

  • Optimization levels 2 and 3 now additionally employ peephole optimization is now employed before the translation/synthesis stage (previously this was only done in the optimization stage). The effects of peephole optimization include the removal of gates that are very close to the identity, for example, controlled-phase gates with a rotational angle smaller than 2π2252\pi \otimes 2^{-25}.

  • The default routing pass used by optimization level 0 for generate_preset_pass_manager() and transpile() has been changed from StochasticSwap to SabreSwap. The SabreSwap pass performs exactly the same function but performs better in both runtime and output quality (in number of swap gates and depth) compared to StochasticSwap. For optimization_level=0 this shouldn’t matter because it’s not expected to run routing for the typical use case of level 0.

    If you were relying on the previous default routing algorithm for any reason you can use the routing_method argument for transpile() and generate_preset_pass_manager() to "stochastic" to use the StochasticSwap pass.

  • The generate_preset_pass_manager() function has been upgraded to, when possible, internally convert transpiler constraints into a Target instance. If a backend input of type BackendV1 is provided, it will be converted to BackendV2 to expose its Target. This change does not require any user action.

Misc. Upgrade Notes

  • The minimum version of rustworkx required to run this release has been increased from 0.14.0 to 0.15.0. This is required because Qiskit is now using new functionality added in the rustworkx 0.15.0 release which improves performance.

Circuits Deprecations

Primitives Deprecations

Providers Deprecations

Transpiler Deprecations

  • The assemble() function is now deprecated and will be removed in the 2.0 release. The function was primarily used to create a Qobj, which is no longer necessary in BackendV2-based workflows. It was also used for binding parameters, a functionality fully covered by QuantumCircuit.assign_parameters().

Visualization Deprecations

  • The justify argument of circuit_drawer() or QuantumCircuit.draw(), will no longer support invalid values (previously changing them to the default), and in a future release they will error. Valid justify values are "left", "right" or "none".

  • The visualize_transition() function has been deprecated and will be removed in the 2.0.0 release. This function had a number of limitations which limited its utility to only very specific use cases and did not fit in with the rest of the Qiskit visualization module.

Bug Fixes

  • Fixed a series of issues when controlling parameterized standard gates. The controlled version of some gates (e.g. RXXGate or RYGate for more than 1 control) cannot be synthesized if they contain unbound parameters. Previously, calling .control() in such a case failed, but now we create an AnnotatedOperation as placeholder. This allows to insert the controlled gate into a circuit, bind the parameters at a later stage, and then synthesize the operation. Fixes #10311, #10697, and #12135.

  • The SGate and SdgGate now correctly return a CSGate, resp. CSdgGate, if they are controlled on a single control qubit.

  • Fix the calculation of the standard deviation in BackendEstimatorV2, by taking into account co-variance of non-commuting Paulis. Fixed Qiskit/qiskit-ibm-runtime#1751.

  • Fixed an issue where circuit_drawer() or the QuantumCircuit.draw() method would not raise a warning when an invalid value was passed to the justify argument, before changing it to the default. Now, it will raise a warning if an invalid value is passed. Valid justify values are "left", "right" or "none". Refer to #12089 for more details.

  • Fixed SparsePauliOp.apply_layout() and Pauli.apply_layout() to raise QiskitError if duplicate indices or negative indices are provided as part of a layout.

  • Fixed a bug in the ConsolidateBlocks transpiler pass, when the input circuit contains a custom opaque gate and neither the basis_gates or target options are set the pass would raise a QiskitError and fail. This has been corrected so that the in these situations the transpiler pass will not consolidate the block identified containing a custom gate instead of failing.

  • Fixed a bug in PadDynamicalDecoupling, which previously did not correctly display the error message that a delay is not pulse-aligned, if the previous or following node was an input/output node. Now, the error message is correctly displayed.

  • The keyword argument order of the function BitArray.from_bool_array() should be "little" or "big". Added checks to raise error if an invalid value is entered.

  • Improve the decomposition of the gate generated by QuantumCircuit.mcx() without using ancilla qubits, so that the number of CXGates will grow quadratically in the number of qubits, as expected, and not exponentially.

  • Fixed SparsePauliOp.apply_layout() to work correctly with zero-qubit operators. For example, if you previously created a 0 qubit and applied a layout like:

    op = SparsePauliOp("")
    op.apply_layout(None, 3)

    this would have previously raised an error. Now this will correctly return an operator of the form: SparsePauliOp(['III'], coeffs=[1.+0.j])

  • Fixed a bug of StatevectorSampler that ignored gates with c_if. It will raise an error because Statevector cannot handle c_if.

  • Fixed an oversight in the Commuting2qGateRouter transpiler pass where the quantum register permutations were not added to the pass property set, so they would have to be tracked manually by the user. Now it is possible to access the permutation through the output circuit’s layout property and plug the pass into any transpilation pipeline without loss of information.

  • Fixed a floating-point imprecision when scaling certain pulse units between seconds and nanoseconds. If the pulse was symbolically defined, an unnecessary floating-point error could be introduced by the scaling for certain builds of symengine, which could manifest in unexpected results once the symbols were fully bound. Fixed #12392.

  • Fixed a bug in synth_cnot_count_full_pmh() where providing a section_size that did not divide the number of qubits without remainder could lead to wrong results. Now any section_size (at most equal to the number of qubits) synthesizes the correct circuit. For a (heuristically) optimal value, set section_size=None.

  • PassManager.run() will no longer waste time serializing itself when given multiple inputs if it is only going to work in serial.

  • Fixed a bug in plot_coupling_map() that caused the edges of the coupling map to be colored incorrectly. Fixed #12354.

  • The OpenQASM 2.0 parser (qasm2.load() and qasm2.loads()) can now evaluate gate-angle expressions including integer operands that would overflow the system-size integer. These will be evaluated in a double-precision floating-point context, just like the rest of the expression always has been. Beware: an arbitrarily large integer will not necessarily be exactly representable in double-precision floating-point, so there is a chance that however the circuit was generated, it had already lost all numerical precision modulo 2π2\pi.

  • The OpenQASM 3 exporter (see qiskit.qasm3) will now correctly error when asked to use a keyword or other invalid identifier as a “basis gate”, as it has no way of generating correct output in these cases.

  • The OpenQASM 3 exporter (qiskit.qasm3) will now correctly export multiple instances of PauliEvolutionGate from a circuit. Previously, only a single instance would be exported, and all other instances would silently use the same (incorrect) version.

  • The OpenQASM 3 exporter (qiskit.qasm3) will now correctly escape gate names. Previously, a gate whose name was an invalid OpenQASM 3 identifier would cause invalid OpenQASM 3 to be generated.

  • A series of input-handling inconsistencies between transpile() and generate_preset_pass_manager() have been fixed. These inconsistencies would lead to different transpilation outputs for the same inputs, or generate_preset_pass_manager() failing for certain input combinations accepted by transpile().

Was this page helpful?
Report a bug or request content on GitHub.