Array Module (qiskit_dynamics.array
)#
Warning
The array
and dispatch
submodules of Qiskit Dynamics have been deprecated as of version
0.5.0. The use of the Array
class is no longer required to work with different array
libraries in Qiskit Dynamics, and is broken in some cases. Refer to the user guide entry
on using different array libraries with Qiskit Dynamics.
Users can now work directly with the supported array type of their choice, without the need to
wrap them to enable dispatching. The array
and dispatch
submodules will be removed in
version 0.6.0.
This module contains an Array
class that wraps N-dimensional array objects from different
libraries. It enables working with different array libraries through a common NumPy-based interface,
along with other functionality for writing array-library agnostic code.
Array Class#
The Array
class provides a NumPy compatible wrapper to supported Python array libraries.
NumPy functions applied to an Array
class instance will be dispatched to the corresponding
function for the current Array backend, if a compatible function has been specified in the
qiskit_dynamics.dispatch
system.
The following array libraries have built in support for the
qiskit_dynamics.dispatch
module:
Basic Usage#
When using the default numpy
backend Array
, objects can be used interchangably with
numpy.ndarray
. When numpy
functions are applied to an Array
object the return type
will be an Array
instead of an numpy.ndarray
.
from qiskit_dynamics.array import Array
import numpy as np
# Initialize an Array
a = Array(np.arange(10))
# Apply numpy ufuncs
np.cos(a) + 1j * np.sin(a)
Array([ 1. +0.j , 0.54030231+0.84147098j,
-0.41614684+0.90929743j, -0.9899925 +0.14112001j,
-0.65364362-0.7568025j , 0.28366219-0.95892427j,
0.96017029-0.2794155j , 0.75390225+0.6569866j ,
-0.14550003+0.98935825j, -0.91113026+0.41211849j], backend='numpy')
For the JAX Array backend, only Numpy functions that have a corresponding function in the jax
library that have been registered with the dispatch module can be applied to the functions. Trying
to apply an unsupported numpy
function to these arrays will raise an exception.
Default Backend#
When initializing a new Array
, the backend
kwarg is used to specify which array backend
to use. This will convert the input data to an array of this backend if required. If
backend=None
, the default backend will be used. The initial default backend is always set to
"numpy"
.
The current default backend can be viewed by using the class method Array.default_backend()
. A
different default backend can be set for all Array()
instances by using the
Array.set_default_backend()
class method.
Attributes and Methods#
The Array
class exposes the same methods and attributes of the wrapped array class and adds
two additional attributes:
data
which returns the wrapped array objectbackend
which returns the backend string of the wrapped array.
All other attributes and methods of the wrapped array are accessible through this class, but with
any array return types wrapped into Array
objects. For example:
# Call an numpy.ndarray method
a.reshape((2, 5))
Array([[0, 1, 2, 3, 4],
[5, 6, 7, 8, 9]], backend='numpy')
Array Initialization#
An Array
object can be initialized as Array(data)
from any data
that is:
An
array
object of one of the supported backends.An object that can be used to initialize the backend array.
An object of a class that defines a
__qiskit_array__
method with the following signature:def __qiskit_array__(self, dtype: Optional[any] = None, backend: Optional[str]=None) -> Array: # conversion from class to Array
The Array.__init__()
method has optional kwargs:
dtype
(any
): Equivalent to thenumpy.array
dtype
kwarg. For other array backends, the specifieddtype
must be supported. If not specified, thedtype
will be inferred from the input data.order
(str
): Equivalent to thenumpy.array
order
kwarg. For other array backends, the specified order value must be supported.backend
(str
): The array backend to use. If not specified this will be inferred from the input data type if it is a backend array instance, otherwise it will be thedefault_backend()
.
Using Arrays with other Libraries#
The Array
class is intended to be used with array functions in
Python libraries that work with any of the supported Array backends.
Wrapping Functions#
Functions from other libraries can be wrapped to work with Array objects using
the wrap()
function as
from qiskit_dynamics.array import Array, wrap
# Some 3rd-party library
import library
# Wrap library function f
f = wrap(library.f)
# Apply f to an Array
a = Array([0, 1, 2, 4])
b = f(a)
The wrapped function will automatically unwrap any Array
args and kwargs
for calling the wrapped function. If the result of the function is a backend array
or an instance of a class that defines a __qiskit_array__
method, the wrapped
function will return this as an Array object. Similarly, if the result is a tuple
this conversion will be applied to each element of the tuple where appropriate.
Wrapping Decorators#
The wrap()
function can also be used to wrap function decorators by setting
the decorator=True
kwarg.
For example, to wrap autograd and jit decorators from the JAX library to work with Array functions, we can do the following
import jax
jit = wrap(jax.jit, decorator=True)
grad = wrap(jax.grad, decorator=True)
value_and_grad = wrap(jax.value_and_grad, decorator=True)
f = jit(obj)
g = grad(obj)
h = value_and_grad(obj)
Array Class#
|
Qiskit array class. |