"""Tensor product operation."""
import numpy as np
[docs]
def tensor(*args) -> np.ndarray:
r"""
Compute the Kronecker tensor product [WikTensor]_.
Tensor two matrices or vectors together using the standard Kronecker
operation provided from numpy.
Given two matrices :math:`A` and :math:`B`, computes :math:`A \otimes B`.
The same concept also applies to two vectors :math:`v` and :math:`w` which
computes :math:`v \otimes w`.
One may also compute the tensor product one matrix `n` times with itself.
For a matrix, :math:`A` and an integer :math:`n`, the result of this
function computes :math:`A^{\otimes n}`.
Similarly for a vector :math:`v` and an integer :math:`n`, the result of
of this function computes :math:`v^{\otimes n}`.
One may also perform the tensor product on a list of matrices.
Given a list of :math:`n` matrices :math:`A_1, A_2, \ldots, A_n` the result
of this function computes
.. math::
A_1 \otimes A_2 \otimes \cdots \otimes A_n.
Similarly, for a list of :math:`n` vectors :math:`v_1, v_2, \ldots, v_n`,
the result of this function computes
.. math::
v_1 \otimes v_2 \otimes \cdots \otimes v_n.
Examples
==========
Tensor product two matrices or vectors
Consider the following ket vector
.. math::
e_0 = \left[1, 0 \right]^{\text{T}}.
Computing the following tensor product
.. math:
e_0 \otimes e_0 = \[1, 0, 0, 0 \]^{\text{T}}.
This can be accomplished in :code:`toqito` as follows.
>>> from toqito.states import basis
>>> from toqito.matrix_ops import tensor
>>> e_0 = basis(2, 0)
>>> tensor(e_0, e_0)
[[1],
[0],
[0],
[0]]
Tensor product one matrix :math:`n` times with itself.
We may also tensor some element with itself some integer number of times.
For instance we can compute
.. math::
e_0^{\otimes 3} = \left[1, 0, 0, 0, 0, 0, 0, 0 \right]^{\text{T}}
in :code:`toqito` as follows.
>>> from toqito.states import basis
>>> from toqito.matrix_ops import tensor
>>> e_0 = basis(2, 0)
>>> tensor(e_0, 3)
[[1],
[0],
[0],
[0],
[0],
[0],
[0],
[0]]
Perform the tensor product on a list of vectors or matrices.
If we wish to compute the tensor product against more than two matrices or
vectors, we can feed them in as a `list`. For instance, if we wish to
compute :math:`e_0 \otimes e_1 \otimes e_0`, we can do
so as follows.
>>> from toqito.states import basis
>>> from toqito.matrix_ops import tensor
>>> e_0, e_1 = basis(2, 0), basis(2, 1)
>>> tensor([e_0, e_1, e_0])
[[0],
[0],
[1],
[0],
[0],
[0],
[0],
[0]]
References
==========
.. [WikTensor] Wikipedia: Tensor product
https://en.wikipedia.org/wiki/Tensor_product
:raises ValueError: Input must be a vector or matrix.
:param args: Input to the tensor function is expected to be either:
- list[np.ndarray]: List of numpy matrices,
- np.ndarray, ... , np.ndarray: An arbitrary number of numpy arrays,
- np.ndarray, int: A numpy array and an integer.
:return: The computed tensor product.
"""
result = None
# Input is provided as a list of numpy matrices.
if len(args) == 1 and isinstance(args[0], list):
if len(args[0]) == 1:
return args[0][0]
if len(args[0]) == 2:
return np.kron(args[0][0], args[0][1])
if len(args[0]) >= 3:
result = args[0][0]
for i in range(1, len(args[0])):
result = np.kron(result, args[0][i])
return result
if len(args) == 1 and isinstance(args[0], np.ndarray):
# If the numpy array is just a single matrix, so the dimensions are
# provided as an (x, y)-tuple.
if len(args[0].shape) == 2:
return args[0]
if len(args[0]) == 2:
return np.kron(args[0][0], args[0][1])
if len(args[0]) >= 3:
result = args[0][0]
for i in range(1, len(args[0])):
result = np.kron(result, args[0][i])
return result
# Tensor product one matrix `n` times with itself.
if len(args) == 2 and isinstance(args[1], int):
num_tensor = args[1]
if num_tensor == 1:
return args[0]
if num_tensor == 2:
return np.kron(args[0], args[0])
if num_tensor >= 3:
result = np.kron(args[0], args[0])
for _ in range(2, num_tensor):
result = np.kron(result, args[0])
return result
# Tensor product between two or more matrices.
if len(args) == 2:
return np.kron(args[0], args[1])
if len(args) >= 3:
result = args[0]
for i in range(1, len(args)):
result = np.kron(result, args[i])
return result
raise ValueError("The `tensor` function must take either a matrix or vector.")