In-Place Matrix Multiplication#

In this example we will demonstrate how the inplace_matrix_app function can be utilized to perform an inplace multiplication of a QuantumArray with a classical matrix.

>>> from qrisp import QuantumArray, QuantumFloat, inplace_matrix_app
>>> import numpy as np

Due to reversibility, this operation can only be realized with an invertible matrix. Overflow is handled by a modular behavior, such that the matrix needs to be invertible over \(\mathbb{Z}/{2^n}\mathbb{Z} \). This is equivalent to the determinant being odd. We generate a random matrix having this property.

import random

def generate_random_inv_matrix(n, bit):


    found = False

    while found == False:
        matrix = np.zeros((n, n))
        for i in range(n):
            for j in range(n):
                matrix[i, j] = random.randint(0, 2 ** bit - 1)

        det = np.round(np.linalg.det(matrix) % 2 ** bit)

        found = bool(det%2)

    return matrix

The in-place matrix multiplication applies a classical matrix (in the form of a numpy array) to a QuantumArray of suitable size.

bit = 5
n = 3

qtype = QuantumFloat(bit)
vector = QuantumArray(qtype = qtype, shape = n)

x_values = np.array([0, 2, 1])
vector[:] = x_values

matrix = generate_random_inv_matrix(n, bit)

inplace_matrix_app(vector, matrix)

Evaluate the result:

>>> print(vector)
{OutcomeArray([ 8, 25, 17]): 1.0}

Compare with the classical expectation:

>>> print(((np.dot(matrix, x_values)) % (2 ** bit)).astype(int).transpose())
[ 8 25 17]