Source code for toqito.matrix_props.majorizes

"""Determine if one vector or matrix majorizes another."""
from __future__ import annotations
import numpy as np


[docs] def majorizes(a_var: np.ndarray | list[int], b_var: np.ndarray | list[int]) -> bool: r""" Determine if one vector or matrix majorizes another. [WikMajorization]_. Given :math:`a, b \in \mathbb{R}^d`, we say that :math:`a` **weakly majorizes** (or dominates) :math:`b` from below if and only if .. math:: \sum_{i=1}^k a_i^{\downarrow} \geq \sum_{i=1}^k b_i^{\downarrow} for all :math:`k \in \{1, \ldots, d\}`. This function was adapted from the QETLAB package. Examples ========== Simple example illustrating that the vector :math:`(3, 0, 0)` majorizes the vector :math:`(1, 1, 1)`. >>> from toqito.matrix_props import majorizes >>> majorizes([3, 0, 0], [1, 1, 1]) True The majorization criterion says that every separable state :math:`\rho \in \text{D}(\mathcal{A} \otimes \mathcal{B})` is such that :math:`\text{Tr}_{\mathcal{B}}(\rho)` majorizes :math:`\text{Tr}_{\mathcal{A}}(\rho)`. >>> from toqito.matrix_props import majorizes >>> from toqito.states import max_entangled >>> from toqito.channels import partial_trace >>> >>> v_vec = max_entangled(3) >>> rho = v_vec * v_vec.conj().T >>> majorizes(partial_trace(rho), rho) False References ========== .. [WikMajorization] Wikipedia: Majorization https://en.wikipedia.org/wiki/Majorization :param a_var: Matrix or vector provided as list or np.array. :param b_var: Matrix or vector provided as list or np.array. :return: Return :code:`True` if :code:`a_var` majorizes :code:`b_var` and :code:`False` otherwise. """ # If input if provided as list, convert to np.array. if isinstance(a_var, list): a_var = np.array(a_var) if isinstance(b_var, list): b_var = np.array(b_var) # If matrix, obtain singular values for majorization. if len(a_var.shape) == 1: a_var = np.sort(a_var)[::-1] # Otherwise, just sort in descending order. else: _, a_var, _ = np.linalg.svd(a_var) # Do the same for second input argument. if len(b_var.shape) == 1: b_var = np.sort(b_var)[::-1] else: _, b_var, _ = np.linalg.svd(b_var) la_var = len(a_var) lb_var = len(b_var) # If different length vectors, pad with zeros. if la_var < lb_var: a_var = np.pad(a_var, (0, lb_var - la_var), "constant") elif lb_var < la_var: b_var = np.pad(b_var, (0, la_var - lb_var), "constant") cta = 0 ctb = -np.linalg.norm(a_var) * np.finfo(float).eps ** (3 / 4) # Check for majorization. for k, _ in enumerate(a_var): cta = cta + a_var[k] ctb = ctb + b_var[k] if cta < ctb: return False return True