Source code for toqito.matrix_props.majorizes
"""Determine if one vector or matrix majorizes another."""
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 [@WikiMajorization].
Given \(a, b \in \mathbb{R}^d\), we say that \(a\) **weakly majorizes** (or dominates)
\(b\) from below if and only if
\[
\sum_{i=1}^k a_i^{\downarrow} \geq \sum_{i=1}^k b_i^{\downarrow}
\]
for all \(k \in \{1, \ldots, d\}\).
This function was adapted from the QETLAB package.
Examples:
Simple example illustrating that the vector \((3, 0, 0)\) majorizes the vector
\((1, 1, 1)\).
```python exec="1" source="above"
from toqito.matrix_props import majorizes
print(majorizes([3, 0, 0], [1, 1, 1]))
```
The majorization criterion says that every separable state
\(\rho \in \text{D}(\mathcal{A} \otimes \mathcal{B})\) is such that
\(\text{Tr}_{\mathcal{B}}(\rho)\) majorizes
\(\text{Tr}_{\mathcal{A}}(\rho)\).
```python exec="1" source="above"
from toqito.matrix_props import majorizes
from toqito.states import max_entangled
from toqito.matrix_ops import partial_trace
v_vec = max_entangled(3)
rho = v_vec @ v_vec.conj().T
print(majorizes(partial_trace(rho, [1]), rho))
```
Args:
a_var: Matrix or vector provided as list or np.array.
b_var: Matrix or vector provided as list or np.array.
Returns:
Return `True` if `a_var` majorizes `b_var` and `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