QuantumArray#
- class QuantumArray(qtype, shape=0, qs=None, name=None)[source]#
This class allows the convenient management of multiple QuantumVariables of one type. As a subclass of numpy’s ndarray, the QuantumArray supports many convenient array manipulation methods. Similar to the numpy equivalent, creating a QuantumArray can be achieved by specifying a shape and a
qtype
:>>> import numpy as np >>> from qrisp import QuantumArray, QuantumFloat >>> qtype = QuantumFloat(5, -2) >>> q_array = QuantumArray(qtype = qtype, shape = (2, 2, 2))
Note that
qtype
is not a type object but a QuantumVariable which serves as an “example”.To retrieve the entries (i.e. QuantumVariables) from the QuantumArray, we simply index as with regular numpy arrays:
>>> from qrisp import h >>> qv = q_array[0,0,1] >>> h(qv[0]) >>> print(q_array) {OutcomeArray([[[0., 0.], [0., 0.]], [[0., 0.], [0., 0.]]]): 0.5, OutcomeArray([[[0. , 0.25], [0. , 0. ]], [[0. , 0. ], [0. , 0. ]]]): 0.5}
We see the value 0.25 in the second entry because we applied an H-gate onto the 0-th qubit of the QuantumVariable at position (0,0,1). Since the type of this array is a QuantumFloat, with exponent -2, the significance of this qubit is 0.25.
Note that the keys of the dictionary returned by the get_measurement method are no regular numpy arrays, as key objects need to be hashable. Instead, they are objects of an immutable subclass of np.ndarray called OutcomeArray, that supports hashing.
For QuantumArrays, many methods known from numpy arrays work here too:
>>> q_array = q_array.reshape(2,4)
Not only do the ndarray methods work but also many other convenience functions from the numpy module:
>>> q_array_swap = np.swapaxes(q_array, 0, 1) >>> print(q_array_swap) {OutcomeArray([[0., 0.], [0., 0.], [0., 0.], [0., 0.]]): 0.5, OutcomeArray([[0. , 0. ], [0.25, 0. ], [0. , 0. ], [0. , 0. ]]): 0.5}
To initiate the array, we use the
encode
method. Similar to QuantumVariables, we can also use the slicing operator, but this time non-trivial slices are possible as well:>>> q_array[1:,:] = 2*np.ones((1,4)) >>> print(q_array) {OutcomeArray([[0., 0., 0., 0.], [2., 2., 2., 2.]]): 0.5, OutcomeArray([[0. , 0.25, 0. , 0. ], [2. , 2. , 2. , 2. ]]): 0.5}
The shape of a QuantumArray does not have to be specified at creation. We can either set it through the
set_shape
method or by initiating:>>> q_array_1 = QuantumArray(qtype = qtype) >>> q_array_1.set_shape((2,2)) >>> print(q_array_1) {OutcomeArray([[0., 0.], [0., 0.]]): 1.0} >>> q_array_2 = QuantumArray(qtype = qtype) >>> q_array_2[:] = np.eye(2) >>> print(q_array_2) {OutcomeArray([[1., 0.], [0., 1.]]): 1.0}
Quantum indexing
QuantumArrays can be dereferenced by QuantumFloats. This returns a Quantum Environments in which the corresponding entry is avaliable as a QuantumVariable.
from qrisp import QuantumBool, QuantumArray, QuantumFloat, h, multi_measurement q_array = QuantumArray(QuantumBool(), shape = (4,4)) index_0 = QuantumFloat(2) index_1 = QuantumFloat(2) index_0[:] = 2 index_1[:] = 1 h(index_0[0]) with q_array[index_0, index_1] as entry: entry.flip()
>>> print(multi_measurement([index_0, index_1, q_array])) {(2, 1, OutcomeArray([[0., 0., 0., 0.], [0., 0., 0., 0.], [0., 1., 0., 0.], [0., 0., 0., 0.]])): 0.5, (3, 1, OutcomeArray([[0., 0., 0., 0.], [0., 0., 0., 0.], [0., 0., 0., 0.], [0., 1., 0., 0.]])): 0.5}
Note
This only works for arrays which have a size of an integer power of 2.
Matrix multiplication
For QuantumArrays with
qtype
QuantumFloat, matrix multiplication is available.>>> q_array_1 = QuantumArray(qtype) >>> q_array_2 = QuantumArray(qtype) >>> q_array_1[:] = 2*np.eye(2) >>> q_array_2[:] = [[1,2],[3,4]] >>> print(q_array_1 @ q_array_2) {OutcomeArray([[2., 4.], [6., 0.]]): 1.0}
Note
By default, the output matrix will have the same
qtype
as the first input matrix. Here, theqtype
is a QuantumFloat with 5 mantissa bits and exponent -2, implying that the result 8 yields overflow. Since qrisps unsigend arithmetic is modular, we get a 0.It is also possible to multiply classical and quantum matrices
>>> q_array = QuantumArray(qtype) >>> q_array[:] = 3*np.eye(2) >>> cl_array = np.array([[1,2],[3,4]]) >>> print(q_array @ cl_array) {OutcomeArray([[3., 6.], [1., 4.]]): 1.0}
Methods#
|
Performs the |
|
Method for acquiring measurement results for the given array. |
|
Performs a measurement and returns the most likely outcome. |
|
This method returns a fresh QuantumArray, with equal |
|
Method to specify a shape for arrays which have been created without one. |
De/Encoding states#
|
The decoder method specifies how a QuantumArray turns the outcomes of measurements into human-readable values. |
|
The encoder reverses the decoder, it turns arrays into integers based on the encoder of the |
|
The encode method allows to quickly bring a QuantumArray in a desired computational basis state. |
|
Method to initiate arbitrary quantum states in this array. |
|
Performs the |