Array Module (qiskit_dynamics.array)#
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:
datawhich returns the wrapped array objectbackendwhich 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
arrayobject 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.arraydtypekwarg. For other array backends, the specifieddtypemust be supported. If not specified, thedtypewill be inferred from the input data.order(str): Equivalent to thenumpy.arrayorderkwarg. 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. |