Source code for toqito.state_props.entanglement_of_formation

"""Computes the entanglement of formation of a bipartite quantum state."""
from __future__ import annotations

import numpy as np
import scipy

from toqito.channels import partial_trace
from toqito.state_props import concurrence, von_neumann_entropy


[docs] def entanglement_of_formation(rho: np.ndarray, dim: list[int] | int = None) -> float: r""" Compute entanglement-of-formation of a bipartite quantum state [WikEOF]_. Entanglement-of-formation is the entropy of formation of the bipartite quantum state :code:`rho`. Note that this function currently only supports :code:`rho` being a pure state or a 2-qubit state: it is not known how to compute the entanglement-of-formation of higher-dimensional mixed states. This function was adapted from QETLAB. Examples ========== Compute the entanglement-of-formation of a Bell state. Let :math:`u = \frac{1}{\sqrt{2}} \left(|00\rangle + |11\rangle \right)` and let .. math:: \rho = uu^* = \frac{1}{2}\begin{pmatrix} 1 & 0 & 0 & 1 \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 1 & 0 & 0 & 1 \end{pmatrix}. The entanglement-of-formation of :math:`\rho` is equal to 1. >>> from toqito.state_props import entanglement_of_formation >>> from toqito.states import bell >>> >>> u_vec = bell(0) >>> rho = u_vec * u_vec.conj().T >>> entanglement_of_formation(rho) 1 References ========== .. [WikEOF] Quantiki: Entanglement-of-formation https://www.quantiki.org/wiki/entanglement-formation :param rho: A matrix or vector. :param dim: The default has both subsystems of equal dimension. :return: A value between 0 and 1 that corresponds to the entanglement-of-formation of :code:`rho`. """ dim_x, dim_y = rho.shape round_dim = int(np.round(np.sqrt(max(dim_x, dim_y)))) eps = np.finfo(float).eps if dim is None: dim = round_dim # User can specify dimension as integer. if isinstance(dim, int): dim = np.array([dim, max(dim_x, dim_y) / dim], dtype=int) if abs(dim[1] - np.round(dim[1])) >= 2 * max(dim_x, dim_y) * eps: raise ValueError( "Invalid dimension: If `dim` is provided as a " "scalar, `dim` must evenly divide `len(rho)`." ) dim[1] = np.round(dim[1]) if np.prod(dim) != max(dim_x, dim_y): raise ValueError( "Invalid dimension: Please provide local dimensions that match the size of `rho`." ) # If :code:`rho` is a rank-1 density matrix, turn it into a vector instead # so we can compute the entanglement-of-formation easily. tmp_rho = scipy.linalg.orth(rho) if dim_x == dim_y and tmp_rho.shape[1] == 1: rho = tmp_rho dim_y = 1 # Start computing entanglement-of-formation. if min(dim_x, dim_y) == 1: rho = rho[:] return von_neumann_entropy(partial_trace(rho * rho.conj().T, 2, dim)) # Case: :code:`rho` is a density matrix. if dim_x == dim_y: # In the two-qubit case, we know how to compute the # entanglement-of-formation exactly. if dim_x == 4: rho_c = concurrence(rho) rho_c1 = (1 + np.sqrt(1 - rho_c**2)) / 2 rho_c2 = (1 - np.sqrt(1 - rho_c**2)) / 2 rho_c1_log2 = 0 if rho_c1 == 0 else np.log2(rho_c1) rho_c2_log2 = 0 if rho_c2 == 0 else np.log2(rho_c2) return -rho_c1 * rho_c1_log2 - rho_c2 * rho_c2_log2 raise ValueError( "Invalid dimension: It is presently only known how to compute " "the entanglement-of-formation for two-qubit states and pure " "states." ) raise ValueError("Invalid dimension: `rho` must be either a vector or square matrix.")