Repository URL to install this package:
|
Version:
0.12.2 ▾
|
# This code is part of Qiskit.
#
# (C) Copyright IBM 2018, 2021.
#
# 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.
"""
Compatibility classes for changes to save instruction return types.
These subclasses include a `__getattr__` method that allows existing
code which used numpy.ndarray attributes to continue functioning with
a deprecation warning.
Numpy functions that consumed these classes should already work due to
them having an `__array__` method for implicit array conversion.
"""
import warnings
import numpy as np
import qiskit.quantum_info as qi
def _forward_attr(attr):
"""Return True if attribute should be passed to legacy class"""
# Pass Iterable magic methods on to the Numpy array. We can't pass
# `__getitem__` (and consequently `__setitem__`, `__delitem__`) on because
# `Statevector` implements them itself.
if attr[:2] == "__" or attr in ["_data", "_op_shape"]:
return False
return True
def _deprecation_warning(instance, instances_name):
class_name = instance.__class__.__name__
warnings.warn(
f"The return type of saved {instances_name} has been changed from"
f" a `numpy.ndarray` to a `qiskit.quantum_info.{class_name}` as"
" of qiskit-aer 0.10. Accessing numpy array attributes is deprecated"
" and will result in an error in a future release. To continue using"
" saved result objects as arrays you can explicitly cast them using "
" `np.asarray(object)`.",
DeprecationWarning,
stacklevel=3,
)
class Statevector(qi.Statevector):
"""Aer result backwards compatibility wrapper for qiskit Statevector."""
def __getattr__(self, attr):
if _forward_attr(attr) and hasattr(self._data, attr):
_deprecation_warning(self, "statevectors")
return getattr(self._data, attr)
return getattr(super(), attr)
def __eq__(self, other):
return (
isinstance(self, type(other))
and self._op_shape == other._op_shape
and np.allclose(self.data, other.data, rtol=self.rtol, atol=self.atol)
)
def __bool__(self):
# Explicit override to the default behaviour for Python objects to
# prevent the new `__len__` from messing with it.
return True
# Magic methods for the iterable/collection interface that need forwarding,
# but bypass `__getattr__`. `__getitem__` is defined by `Statevector`, so
# that can't be forwarded (and consequently neither can `__setitem__`
# without introducing an inconsistency).
def __len__(self):
_deprecation_warning(self, "statevectors")
return self._data.__len__()
def __iter__(self):
_deprecation_warning(self, "statevectors")
return self._data.__iter__()
def __contains__(self, value):
_deprecation_warning(self, "statevectors")
return self._data.__contains__(value)
def __reversed__(self):
_deprecation_warning(self, "statevectors")
return self._data.__reversed__()
class DensityMatrix(qi.DensityMatrix):
"""Aer result backwards compatibility wrapper for qiskit DensityMatrix."""
def __getattr__(self, attr):
if _forward_attr(attr) and hasattr(self._data, attr):
_deprecation_warning(self, "density matrices")
return getattr(self._data, attr)
return getattr(super(), attr)
def __eq__(self, other):
return (
isinstance(self, type(other))
and self._op_shape == other._op_shape
and np.allclose(self.data, other.data, rtol=self.rtol, atol=self.atol)
)
def __len__(self):
_deprecation_warning(self, "density matrices")
return self._data.__len__()
def __iter__(self):
_deprecation_warning(self, "density matrices")
return self._data.__iter__()
def __contains__(self, value):
_deprecation_warning(self, "density matrices")
return self._data.__contains__(value)
def __reversed__(self):
_deprecation_warning(self, "density matrices")
return self._data.__reversed__()
def __getitem__(self, key):
_deprecation_warning(self, "density matrices")
return self._data.__getitem__(key)
def __setitem__(self, key, value):
_deprecation_warning(self, "density matrices")
return self._data.__setitem__(key, value)
class Operator(qi.Operator):
"""Aer result backwards compatibility wrapper for qiskit Operator."""
def __getattr__(self, attr):
if _forward_attr(attr) and hasattr(self._data, attr):
_deprecation_warning(self, "unitaries")
return getattr(self._data, attr)
return getattr(super(), attr)
def __eq__(self, other):
return (
isinstance(self, type(other))
and self._op_shape == other._op_shape
and np.allclose(self.data, other.data, rtol=self.rtol, atol=self.atol)
)
def __bool__(self):
# Explicit override to the default behaviour for Python objects to
# prevent the new `__len__` from messing with it.
return True
def __len__(self):
_deprecation_warning(self, "unitaries")
return self._data.__len__()
def __iter__(self):
_deprecation_warning(self, "unitaries")
return self._data.__iter__()
def __contains__(self, value):
_deprecation_warning(self, "unitaries")
return self._data.__contains__(value)
def __reversed__(self):
_deprecation_warning(self, "unitaries")
return self._data.__reversed__()
def __getitem__(self, key):
_deprecation_warning(self, "unitaries")
return self._data.__getitem__(key)
def __setitem__(self, key, value):
_deprecation_warning(self, "unitaries")
return self._data.__setitem__(key, value)
class SuperOp(qi.SuperOp):
"""Aer result backwards compatibility wrapper for qiskit SuperOp."""
def __getattr__(self, attr):
if _forward_attr(attr) and hasattr(self._data, attr):
_deprecation_warning(self, "superoperators")
return getattr(self._data, attr)
return getattr(super(), attr)
def __eq__(self, other):
return (
isinstance(self, type(other))
and self._op_shape == other._op_shape
and np.allclose(self.data, other.data, rtol=self.rtol, atol=self.atol)
)
def __bool__(self):
# Explicit override to the default behaviour for Python objects to
# prevent the new `__len__` from messing with it.
return True
def __len__(self):
_deprecation_warning(self, "superoperators")
return self._data.__len__()
def __iter__(self):
_deprecation_warning(self, "superoperators")
return self._data.__iter__()
def __contains__(self, value):
_deprecation_warning(self, "superoperators")
return self._data.__contains__(value)
def __reversed__(self):
_deprecation_warning(self, "superoperators")
return self._data.__reversed__()
def __getitem__(self, key):
_deprecation_warning(self, "superoperators")
return self._data.__getitem__(key)
def __setitem__(self, key, value):
_deprecation_warning(self, "superoperators")
return self._data.__setitem__(key, value)
class StabilizerState(qi.StabilizerState):
"""Aer result backwards compatibility wrapper for qiskit StabilizerState."""
def __deprecation_warning(self):
warnings.warn(
"The return type of saved stabilizers has been changed from"
" a `dict` to a `qiskit.quantum_info.StabilizerState` as of qiskit-aer 0.10."
" Accessing dict attributes is deprecated and will result in an"
" error in a future release. Use the `.clifford.to_dict()` methods to access "
" the stored Clifford operator and convert to a dictionary.",
DeprecationWarning,
stacklevel=3,
)
def __getattr__(self, attr):
if _forward_attr(attr) and hasattr(dict, attr):
self.__deprecation_warning()
return getattr(self._data.to_dict(), attr)
return getattr(super(), attr)
def __getitem__(self, item):
if item in ["stabilizer", "destabilizer"]:
warnings.warn(
"The return type of saved stabilizers has been changed from"
" a `dict` to a `qiskit.quantum_info.StabilizerState` as of qiskit-aer 0.10."
" Accessing dict items is deprecated and will result in an"
" error in a future release. Use the `.clifford.to_dict()` methods to access "
" the stored Clifford operator and convert to a dictionary.",
DeprecationWarning,
stacklevel=2,
)
return self._data.to_dict()[item]
raise TypeError("'StabilizerState object is not subscriptable'")
def __bool__(self):
# Explicit override to the default behaviour for Python objects to
# prevent the new `__len__` from messing with it.
return True
def __len__(self):
self.__deprecation_warning()
return self._data.to_dict().__len__()
def __iter__(self):
self.__deprecation_warning()
return self._data.to_dict().__iter__()
def __contains__(self, value):
self.__deprecation_warning()
return self._data.to_dict().__contains__(value)
def __reversed__(self):
self.__deprecation_warning()
return self._data.to_dict().__reversed__()
def _add(self, other):
raise NotImplementedError(f"{type(self)} does not support addition")
def _multiply(self, other):
raise NotImplementedError(f"{type(self)} does not support scalar multiplication")