Skip to content

Commit

Permalink
Deprecate qiskit.extensions (Qiskit#10725)
Browse files Browse the repository at this point in the history
* big moves, import still works

* most tests pass (some I cannot seem to run locally)

* fix tests -- how to remove DiagonalGate?

* typehints and docs

* more type hints

* Deprecate SQU

* deprecate Snapshot

* Fix missing future annotations import

* minimize deprecation effort

* Change to pending deprecation, no exact-location import supported

* fix MCG<->MGC typo and snapshot deprecation

* fix pylint, try fixing docs

* remove gates from extensions toctree

* Add reno, fully deprecate SQU and Snapshot

* Apply Sasha's review comments

- fix usage of .squ and .snapshot w/o import
- fix docstring usage of extensions
- fix tests

* capture snapshot deprecation warning

* review comments

- capture warning of SQU
- update reno to explicitly mention pending deprecation, add DiagonalGate and ExtensionError

* missed `diagonal` method

---------

Co-authored-by: Alexander Ivrii <[email protected]>
  • Loading branch information
2 people authored and rupeshknn committed Oct 9, 2023
1 parent b77dfa4 commit 4a05048
Show file tree
Hide file tree
Showing 81 changed files with 1,453 additions and 1,297 deletions.
20 changes: 10 additions & 10 deletions docs/legacy_release_notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3619,7 +3619,7 @@ Bug Fixes
.. releasenotes/notes/0.24/qasm2-exporter-rewrite-8993dd24f930b180.yaml @ b'4152009ee6d1bae8704f1e7b9ccc5727a53933bd'

- The OpenQASM 2 exporter (:meth:`.QuantumCircuit.qasm`) will now handle multiple and nested
definitions of :class:`.UnitaryGate`. See
definitions of :class:`~.library.UnitaryGate`. See
`#4623 <https://github.com/Qiskit/qiskit-terra/issues/4623>`__,
`#6712 <https://github.com/Qiskit/qiskit-terra/issues/6712>`__,
`#7772 <https://github.com/Qiskit/qiskit-terra/issues/7772>`__, and
Expand Down Expand Up @@ -5123,7 +5123,7 @@ New Features
library gate classes have been updated to return more specific
gate objects that result in a less lossy and more efficient output.
For example, running :meth:`~.IGate.power` now returns an :class:`~.IGate`
instance instead of :class:`~.UnitaryGate` as was done previously.
instance instead of :class:`~.library.UnitaryGate` as was done previously.

The full list of output types that have been improved are:

Expand Down Expand Up @@ -9148,7 +9148,7 @@ Bug Fixes
.. releasenotes/notes/0.22/fix-qasm2-identity-as-unitary-aa2feeb05707a597.yaml @ b'618770367f7a5a3a22fd43ea9fcfb7f17393eb6a'

- The OpenQASM 2 exporter (:meth:`.QuantumCircuit.qasm`) will now correctly
define the qubit parameters for :class:`.UnitaryGate` operations that do
define the qubit parameters for :class:`~.library.UnitaryGate` operations that do
not affect all the qubits they are defined over.
Fixed `#8224 <https://github.com/Qiskit/qiskit-terra/issues/8224>`__.

Expand Down Expand Up @@ -9372,7 +9372,7 @@ Known Issues
.. releasenotes/notes/0.11/non-x86_ibm_cpu-493e51313ba222a6.yaml @ b'b7c4a322f8409fc2809b57b0701d1da6717c7efd'

- When running on Linux s390x platforms (or other big endian platforms)
running circuits that contain :class:`~.UnitaryGate` operations will not
running circuits that contain :class:`~.library.UnitaryGate` operations will not
work because of an endianess bug.
See `#1506 <https://github.com/Qiskit/qiskit-aer/issues/1506>`__ for more
details.
Expand Down Expand Up @@ -9692,7 +9692,7 @@ Bug Fixes
.. releasenotes/notes/fix-evolvedop-to-instruction-c90c4f1aa6b4232a.yaml @ b'664747a66e2199a4b20abb9b7180cccb12c61a3f'

- Fix :meth:`~.EvolvedOp.to_instruction` which previously tried to create a
:class:`~.UnitaryGate` without exponentiating the operator to evolve.
:class:`~.library.UnitaryGate` without exponentiating the operator to evolve.
Since this operator is generally not unitary, this raised an error (and if
the operator would have been unitary by chance, it would not have been the expected result).

Expand Down Expand Up @@ -10076,7 +10076,7 @@ New Features
Shannon Decomposition of arbitrary unitaries. This functionality replaces
the previous isometry-based approach in the default unitary synthesis
transpiler pass as well as when adding unitaries to a circuit using a
:class:`.UnitaryGate`.
:class:`~.library.UnitaryGate`.

The Quantum Shannon Decomposition uses about half the cnot gates as the
isometry implementation when decomposing unitary matrices of greater than
Expand Down Expand Up @@ -10732,7 +10732,7 @@ Bug Fixes
.. releasenotes/notes/fix-qasm2-identity-as-unitary-aa2feeb05707a597.yaml @ b'd7f932c8b242f69c5577afd5593bf36f839657f7'

- The OpenQASM 2 exporter (:meth:`.QuantumCircuit.qasm`) will now correctly
define the qubit parameters for :class:`.UnitaryGate` operations that do
define the qubit parameters for :class:`~.library.UnitaryGate` operations that do
not affect all the qubits they are defined over.
Fixed `#8224 <https://github.com/Qiskit/qiskit-terra/issues/8224>`__.

Expand Down Expand Up @@ -10914,10 +10914,10 @@ Known Issues
.. releasenotes/notes/ucr-gates-qpy-b8f6fb1e34fae258.yaml @ b'625b202a4dd0c223579dca44eec530b8a0813d76'

- QPY deserialization with the :func:`.qpy.load` function of a directly
instantiated :class:`~.UCPauliRotGate` object in a circuit will fail
instantiated :class:`~.library.UCPauliRotGate` object in a circuit will fail
because the rotation axis argument to the class isn't stored in a standard
place. To workaround this you can instead use the subclasses:
:class:`~.UCRXGate`, :class:`~.UCRYGate`, or :class:`~.UCRZGate` (based on
:class:`~.library.UCRXGate`, :class:`~.library.UCRYGate`, or :class:`~.library.UCRZGate` (based on
whether you're using a rotation axis of ``"X"``, ``"Y"``, or ``"Z"``
respectively) which embeds the rotation axis in the class constructor and
will work correctly in QPY.
Expand Down Expand Up @@ -11016,7 +11016,7 @@ Bug Fixes
.. releasenotes/notes/ucr-gates-qpy-b8f6fb1e34fae258.yaml @ b'625b202a4dd0c223579dca44eec530b8a0813d76'

- Fixed an issue with QPY deserialization via the :func:`.qpy.load` function
of the :class:`~.UCRXGate`, :class:`~.UCRYGate`, and :class:`~.UCRZGate`
of the :class:`~.library.UCRXGate`, :class:`~.library.UCRYGate`, and :class:`~.library.UCRZGate`
classes.
Previously, a QPY file that contained any of these gates would error
when trying to load the file.
Expand Down
6 changes: 3 additions & 3 deletions docs/migration_guides/opflow_migration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1004,8 +1004,8 @@ delayed synthesis of the gates or efficient transpilation of the circuits, so th
(for example, :class:`~qiskit.algorithms.time_evolvers.trotterization.TrotterQRTE`\).

In a similar manner, the :class:`qiskit.opflow.evolutions.MatrixEvolution` class performs evolution by classical matrix exponentiation,
constructing a circuit with :class:`.UnitaryGate`\s or :class:`.HamiltonianGate`\s containing the exponentiation of the operator.
This class is no longer necessary, as the :class:`.HamiltonianGate`\s can be directly handled by the algorithms.
constructing a circuit with :class:`~.library.UnitaryGate`\s or :class:`~.library.HamiltonianGate`\s containing the exponentiation of the operator.
This class is no longer necessary, as the :class:`~.library.HamiltonianGate`\s can be directly handled by the algorithms.

Trotterizations
---------------
Expand Down Expand Up @@ -1046,7 +1046,7 @@ Other Evolution Classes
- No direct replacement. The workflow no longer requires a specific operator for evolutions.

* - :class:`~qiskit.opflow.evolutions.MatrixEvolution`
- :class:`.HamiltonianGate`
- :class:`~.library.HamiltonianGate`

* - :class:`~qiskit.opflow.evolutions.PauliTrotterEvolution`
- :class:`.PauliEvolutionGate`
Expand Down
3 changes: 0 additions & 3 deletions qiskit/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,6 @@
# user config
from qiskit import user_config as _user_config

# The qiskit.extensions.x imports needs to be placed here due to the
# mechanism for adding gates dynamically.
import qiskit.extensions
import qiskit.circuit.measure
import qiskit.circuit.reset

Expand Down
26 changes: 18 additions & 8 deletions qiskit/assembler/disassemble.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,20 @@
# and a header dictionary.
PulseModule = NewType("PulseModule", Tuple[List[pulse.Schedule], Dict[str, Any], Dict[str, Any]])

# Prevent the disassembler from accessing deprecated circuit methods. This can happen for
# gates where the name of the gate matches a circuit method (e.g. Isometry.name is "isometry")
# and the circuit attribute is also QuantumCircuit.isometry
_DEPRECATED_CIRCUIT_METHODS = {
"isometry",
"snapshot",
"ucrx",
"ucry",
"ucrz",
"squ",
"diagonal",
"hamiltonian",
}


def disassemble(qobj) -> Union[CircuitModule, PulseModule]:
"""Disassemble a qobj and return the circuits or pulse schedules, run_config, and user header.
Expand Down Expand Up @@ -165,16 +179,12 @@ def _experiments_to_circuits(qobj):
clbits.append(creg_dict[clbit_label[0]][clbit_label[1]])
except Exception: # pylint: disable=broad-except
pass
if hasattr(circuit, name):
# TODO remove the check that name is not in the deprecated circuit methods
# once the methods have been removed
if hasattr(circuit, name) and name not in _DEPRECATED_CIRCUIT_METHODS:
instr_method = getattr(circuit, name)
if i.name in ["snapshot"]:
_inst = instr_method(
i.label, snapshot_type=i.snapshot_type, qubits=qubits, params=params
)
elif i.name == "initialize":
if i.name == "initialize":
_inst = instr_method(params, qubits)
elif i.name == "isometry":
_inst = instr_method(*params, qubits, clbits)
elif i.name in ["mcx", "mcu1", "mcp"]:
_inst = instr_method(*params, qubits[:-1], qubits[-1], *clbits)
else:
Expand Down
2 changes: 1 addition & 1 deletion qiskit/circuit/add_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from __future__ import annotations

from qiskit.circuit.exceptions import CircuitError
from qiskit.extensions import UnitaryGate
from qiskit.circuit.library import UnitaryGate
from . import ControlledGate, Gate, QuantumRegister, QuantumCircuit
from ._utils import _ctrl_state_to_int

Expand Down
8 changes: 5 additions & 3 deletions qiskit/circuit/gate.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,15 @@ def power(self, exponent: float):
exponent (float): Gate^exponent
Returns:
qiskit.extensions.UnitaryGate: To which `to_matrix` is self.to_matrix^exponent.
.library.UnitaryGate: To which `to_matrix` is self.to_matrix^exponent.
Raises:
CircuitError: If Gate is not unitary
"""
from qiskit.quantum_info.operators import Operator # pylint: disable=cyclic-import
from qiskit.extensions.unitary import UnitaryGate # pylint: disable=cyclic-import
# pylint: disable=cyclic-import
from qiskit.quantum_info.operators import Operator
from qiskit.circuit.library.generalized_gates.unitary import UnitaryGate

from scipy.linalg import schur

# Should be diagonalized because it's a unitary.
Expand Down
27 changes: 26 additions & 1 deletion qiskit/circuit/library/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@
:template: autosummary/class_no_inherited_members.rst
Diagonal
DiagonalGate
MCMT
MCMTVChain
Permutation
Expand All @@ -198,6 +199,13 @@
RVGate
PauliGate
LinearFunction
Isometry
UnitaryGate
UCGate
UCPauliRotGate
UCRXGate
UCRYGate
UCRZGate
Boolean Logic Circuits
======================
Expand Down Expand Up @@ -324,6 +332,7 @@
PhaseOracle
EvolvedOperatorAnsatz
PauliEvolutionGate
HamiltonianGate
N-local circuits
Expand Down Expand Up @@ -360,6 +369,7 @@
ZFeatureMap
ZZFeatureMap
StatePreparation
Initialize
Template circuits
=================
Expand Down Expand Up @@ -492,6 +502,7 @@
from .blueprintcircuit import BlueprintCircuit
from .generalized_gates import (
Diagonal,
DiagonalGate,
MCMT,
MCMTVChain,
Permutation,
Expand All @@ -505,8 +516,16 @@
RVGate,
PauliGate,
LinearFunction,
Isometry,
UnitaryGate,
UCGate,
UCPauliRotGate,
UCRXGate,
UCRYGate,
UCRZGate,
)
from .pauli_evolution import PauliEvolutionGate
from .hamiltonian_gate import HamiltonianGate
from .boolean_logic import (
AND,
OR,
Expand Down Expand Up @@ -542,7 +561,13 @@
ExcitationPreserving,
QAOAAnsatz,
)
from .data_preparation import PauliFeatureMap, ZFeatureMap, ZZFeatureMap, StatePreparation
from .data_preparation import (
PauliFeatureMap,
ZFeatureMap,
ZZFeatureMap,
StatePreparation,
Initialize,
)
from .quantum_volume import QuantumVolume
from .fourier_checking import FourierChecking
from .graph_state import GraphState
Expand Down
2 changes: 1 addition & 1 deletion qiskit/circuit/library/arithmetic/exact_reciprocal.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from math import isclose
import numpy as np
from qiskit.circuit import QuantumCircuit, QuantumRegister
from qiskit.extensions.quantum_initializer import UCRYGate
from qiskit.circuit.library.generalized_gates import UCRYGate


class ExactReciprocal(QuantumCircuit):
Expand Down
3 changes: 2 additions & 1 deletion qiskit/circuit/library/data_preparation/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,6 @@
from .z_feature_map import ZFeatureMap
from .zz_feature_map import ZZFeatureMap
from .state_preparation import StatePreparation
from .initializer import Initialize

__all__ = ["PauliFeatureMap", "ZFeatureMap", "ZZFeatureMap", "StatePreparation"]
__all__ = ["PauliFeatureMap", "ZFeatureMap", "ZZFeatureMap", "StatePreparation", "Initialize"]
96 changes: 96 additions & 0 deletions qiskit/circuit/library/data_preparation/initializer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# This code is part of Qiskit.
#
# (C) Copyright IBM 2017.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.

"""
Initialize qubit registers to desired arbitrary state.
"""

from __future__ import annotations
from collections.abc import Sequence
import typing

from qiskit.circuit.quantumcircuit import QuantumCircuit
from qiskit.circuit.quantumregister import QuantumRegister
from qiskit.circuit.instruction import Instruction
from .state_preparation import StatePreparation

if typing.TYPE_CHECKING:
from qiskit.quantum_info.states.statevector import Statevector

_EPS = 1e-10 # global variable used to chop very small numbers to zero


class Initialize(Instruction):
"""Complex amplitude initialization.
Class that initializes some flexible collection of qubit registers, implemented by calling
the :class:`~.library.StatePreparation` class.
Note that ``Initialize`` is an :class:`~.circuit.Instruction` and not a :class:`.Gate` since it
contains a reset instruction, which is not unitary.
"""

def __init__(
self,
params: Statevector | Sequence[complex] | str | int,
num_qubits: int | None = None,
normalize: bool = False,
) -> None:
r"""
Args:
params: The state to initialize to, can be either of the following.
* Statevector or vector of complex amplitudes to initialize to.
* Labels of basis states of the Pauli eigenstates Z, X, Y. See
:meth:`.Statevector.from_label`. Notice the order of the labels is reversed with
respect to the qubit index to be applied to. Example label '01' initializes the
qubit zero to :math:`|1\rangle` and the qubit one to :math:`|0\rangle`.
* An integer that is used as a bitmap indicating which qubits to initialize to
:math:`|1\rangle`. Example: setting params to 5 would initialize qubit 0 and qubit
2 to :math:`|1\rangle` and qubit 1 to :math:`|0\rangle`.
num_qubits: This parameter is only used if params is an int. Indicates the total
number of qubits in the `initialize` call. Example: `initialize` covers 5 qubits
and params is 3. This allows qubits 0 and 1 to be initialized to :math:`|1\rangle`
and the remaining 3 qubits to be initialized to :math:`|0\rangle`.
normalize: Whether to normalize an input array to a unit vector.
"""
self._stateprep = StatePreparation(params, num_qubits, normalize=normalize)

super().__init__("initialize", self._stateprep.num_qubits, 0, self._stateprep.params)

def _define(self):
q = QuantumRegister(self.num_qubits, "q")
initialize_circuit = QuantumCircuit(q, name="init_def")
initialize_circuit.reset(q)
initialize_circuit.append(self._stateprep, q)
self.definition = initialize_circuit

def gates_to_uncompute(self) -> QuantumCircuit:
"""Call to create a circuit with gates that take the desired vector to zero.
Returns:
Circuit to take ``self.params`` vector to :math:`|{00\\ldots0}\\rangle`
"""
return self._stateprep._gates_to_uncompute()

@property
def params(self):
"""Return initialize params."""
return self._stateprep.params

@params.setter
def params(self, parameters: Statevector | Sequence[complex] | str | int) -> None:
"""Set initialize params."""
self._stateprep.params = parameters

def broadcast_arguments(self, qargs, cargs):
return self._stateprep.broadcast_arguments(qargs, cargs)
5 changes: 3 additions & 2 deletions qiskit/circuit/library/data_preparation/state_preparation.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,16 @@
import numpy as np

from qiskit.exceptions import QiskitError
from qiskit.circuit import QuantumCircuit, QuantumRegister, Qubit
from qiskit.circuit.quantumcircuit import QuantumCircuit
from qiskit.circuit.quantumregister import QuantumRegister, Qubit
from qiskit.circuit.gate import Gate
from qiskit.circuit.library.standard_gates.x import CXGate, XGate
from qiskit.circuit.library.standard_gates.h import HGate
from qiskit.circuit.library.standard_gates.s import SGate, SdgGate
from qiskit.circuit.library.standard_gates.ry import RYGate
from qiskit.circuit.library.standard_gates.rz import RZGate
from qiskit.circuit.exceptions import CircuitError
from qiskit.quantum_info import Statevector
from qiskit.quantum_info.states.statevector import Statevector # pylint: disable=cyclic-import

_EPS = 1e-10 # global variable used to chop very small numbers to zero

Expand Down
Loading

0 comments on commit 4a05048

Please sign in to comment.