Source code for toqito.state_props.is_mutually_orthogonal

"""Checks if quantum states are mutually orthogonal."""

from typing import Any

import numpy as np


[docs] def is_mutually_orthogonal(vec_list: list[np.ndarray | list[float | Any]]) -> bool: r"""Check if list of vectors are mutually orthogonal [@WikiOrthog]. We say that two bases \[ \begin{equation} \mathcal{B}_0 = \left\{u_a: a \in \Sigma \right\} \subset \mathbb{C}^{\Sigma} \quad \text{and} \quad \mathcal{B}_1 = \left\{v_a: a \in \Sigma \right\} \subset \mathbb{C}^{\Sigma} \end{equation} \] are *mutually orthogonal* if and only if \(\left|\langle u_a, v_b \rangle\right| = 0\) for all \(a, b \in \Sigma\). For \(n \in \mathbb{N}\), a set of bases \(\left\{ \mathcal{B}_0, \ldots, \mathcal{B}_{n-1} \right\}\) are mutually orthogonal if and only if every basis is orthogonal with every other basis in the set, i.e. \(\mathcal{B}_x\) is orthogonal with \(\mathcal{B}_x^{\prime}\) for all \(x \not= x^{\prime}\) with \(x, x^{\prime} \in \Sigma\). Examples: The Bell states constitute a set of mutually orthogonal vectors. ```python exec="1" source="above" from toqito.states import bell from toqito.state_props import is_mutually_orthogonal states = [bell(0), bell(1), bell(2), bell(3)] print(is_mutually_orthogonal(states)) ``` The following is an example of a list of vectors that are not mutually orthogonal. ```python exec="1" source="above" import numpy as np from toqito.states import bell from toqito.state_props import is_mutually_orthogonal states = [np.array([1, 0]), np.array([1, 1])] print(is_mutually_orthogonal(states)) ``` Raises: ValueError: If at least two vectors are not provided. Args: vec_list: The list of vectors to check. Returns: `True` if `vec_list` are mutually orthogonal, and `False` otherwise. """ if len(vec_list) <= 1: raise ValueError("There must be at least two vectors provided as input.") # Convert list of vectors to a 2D array (each vector is a column) mat = np.column_stack(vec_list) # Compute the matrix of inner products inner_product_matrix = np.dot(mat.T.conj(), mat) # The diagonal elements will be non-zero (norm of each vector) # Set the diagonal elements to zero for the comparison np.fill_diagonal(inner_product_matrix, 0) # Check if all off-diagonal elements are close to zero return np.allclose(inner_product_matrix, 0)