Computing Quantum Entanglement Measures

Minimizing Relative Entropy and Robustness

How entangled is a quantum state? A yes/no answer (separable or entangled) is not enough for most purposes. We want a number. Many entanglement measures are defined as the minimum “distance” from the given state to the set of separable states. In this post we compute two of them numerically for two-qubit states:

  • the relative entropy of entanglement (a nonconvex optimization over separable states), and
  • the generalized robustness of entanglement (a semidefinite program).

We check both against exact formulas and visualize them over a two-parameter family of states, including 3D surfaces.


1. The Measures

Let $\mathrm{SEP}$ denote the set of separable states. A state is separable if it can be written as

$$
\sigma = \sum_k p_k, |a_k\rangle\langle a_k| \otimes |b_k\rangle\langle b_k| ,\qquad p_k\ge 0,\ \sum_k p_k = 1 .
$$

Relative entropy of entanglement

$$
E_R(\rho) = \min_{\sigma\in \mathrm{SEP}} S(\rho,|,\sigma),\qquad
S(\rho|\sigma) = \mathrm{Tr}\left[\rho\left(\log_2\rho - \log_2\sigma\right)\right].
$$

Generalized robustness of entanglement

This is the minimum amount of “noise” $\tau$ that must be mixed in to destroy the entanglement. Setting $Y=(1+s)\sigma$ turns it into a semidefinite program (SDP):

$$
R_G(\rho)=\min_{Y}\ \mathrm{Tr},Y - 1\quad \text{s.t.}\quad Y\succeq \rho,\quad Y^{T_B}\succeq 0 .
$$

For two qubits, “separable” is equivalent to “positive partial transpose” (the Peres–Horodecki criterion). This is why the constraint $Y^{T_B}\succeq 0$ is exact here.

The inequality connecting them

The log-robustness upper-bounds the relative entropy of entanglement:

$$
E_R(\rho)\ \le\ \log_2\bigl(1+R_G(\rho)\bigr).
$$


2. The Example Problem

Problem 1 (Werner states).

$$
\rho_W(p) = p,|\Phi^+\rangle\langle\Phi^+| + (1-p)\frac{I}{4},\qquad |\Phi^+\rangle=\frac{|00\rangle+|11\rangle}{\sqrt2}.
$$

With the singlet fraction $F=\langle\Phi^+|\rho_W|\Phi^+\rangle=\frac{3p+1}{4}$, the exact results for $F>1/2$ (that is, $p>1/3$) are

$$
E_R = 1 - h(F),\qquad h(x)=-x\log_2 x-(1-x)\log_2(1-x),\qquad R_G = 2F-1 = \frac{3p-1}{2},
$$

and both vanish for $p\le 1/3$. We recover these numerically.

Problem 2 (two-parameter family).

$$
\rho(p,\theta) = p,|\psi_\theta\rangle\langle\psi_\theta| + (1-p)\frac{I}{4},\qquad |\psi_\theta\rangle=\cos\theta,|00\rangle+\sin\theta,|11\rangle .
$$

The partial transpose has smallest eigenvalue $\frac{1-p}{4}-\frac{p\sin 2\theta}{2}$, so the state is separable exactly when

$$
p\le \frac{1}{1+2\sin 2\theta}.
$$

For pure states ($p=1$), the exact values are $E_R=h(\cos^2\theta)$ (the entanglement entropy) and $R_G=\sin 2\theta$.

We compute $E_R$ and $R_G$ on a $(p,\theta)$ grid and draw 3D surfaces.


3. Numerical Strategy

Relative entropy. The set $\mathrm{SEP}$ is hard to describe directly, so we parametrize it from the inside. We write

$$
\sigma(\mathbf{x}) = \sum_{k=1}^{K} p_k, |a_k b_k\rangle\langle a_k b_k|,\qquad
p_k=\frac{e^{\ell_k}}{\sum_j e^{\ell_j}},\qquad
|a\rangle=\begin{pmatrix}\cos\frac{\vartheta}{2}\ e^{i\varphi}\sin\frac{\vartheta}{2}\end{pmatrix}.
$$

This $\sigma$ is separable for every parameter value, so minimizing $S(\rho|\sigma(\mathbf x))$ with L-BFGS-B gives an upper bound on $E_R$ that converges to the true value as the optimizer converges. We use $K=8$ product states and several random restarts.

Robustness. This is a convex SDP, so we hand it to CVXPY.


4. Source Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
import time
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import minimize
from mpl_toolkits.mplot3d import Axes3D # noqa: F401

try:
import cvxpy as cp
except ImportError:
import subprocess, sys
subprocess.check_call([sys.executable, "-m", "pip", "install", "-q", "cvxpy"])
import cvxpy as cp

np.set_printoptions(precision=5, suppress=True)
rng = np.random.default_rng(7)

# ---------------------------------------------------------------
# Basic quantum-information tools
# ---------------------------------------------------------------
def ket(v):
return np.array(v, dtype=complex).reshape(-1, 1)

phi_plus = (ket([1, 0, 0, 0]) + ket([0, 0, 0, 1])) / np.sqrt(2)
I4 = np.eye(4, dtype=complex)

def werner(p):
"""rho = p |Phi+><Phi+| + (1-p) I/4"""
return p * (phi_plus @ phi_plus.conj().T) + (1 - p) * I4 / 4

def family(p, theta):
"""rho = p |psi><psi| + (1-p) I/4, |psi> = cos(theta)|00> + sin(theta)|11>"""
psi = np.cos(theta) * ket([1, 0, 0, 0]) + np.sin(theta) * ket([0, 0, 0, 1])
return p * (psi @ psi.conj().T) + (1 - p) * I4 / 4

def partial_transpose(rho):
"""Partial transpose on the second qubit."""
r = rho.reshape(2, 2, 2, 2)
return r.transpose(0, 3, 2, 1).reshape(4, 4)

def fidelity_phi_plus(rho):
return float(np.real((phi_plus.conj().T @ rho @ phi_plus)[0, 0]))

def binary_entropy(x):
x = np.clip(x, 1e-15, 1 - 1e-15)
return -x * np.log2(x) - (1 - x) * np.log2(1 - x)

def negativity(rho):
ev = np.linalg.eigvalsh(partial_transpose(rho))
return float(np.sum(np.abs(ev[ev < 0])))

def neg_entropy(rho):
"""Tr rho log2 rho"""
w = np.linalg.eigvalsh(rho)
w = w[w > 1e-14]
return float(np.sum(w * np.log2(w)))

# ---------------------------------------------------------------
# (1) Relative entropy of entanglement
# sigma = sum_k p_k |a_k b_k><a_k b_k| (separable by construction)
# ---------------------------------------------------------------
K = 8 # number of product states

def build_sigma(x):
logits = x[:K]
ang = x[K:].reshape(4, K)
w = np.exp(logits - logits.max())
w /= w.sum()
ta, pa, tb, pb = ang
A = np.stack([np.cos(ta / 2), np.exp(1j * pa) * np.sin(ta / 2)], axis=1)
B = np.stack([np.cos(tb / 2), np.exp(1j * pb) * np.sin(tb / 2)], axis=1)
psi = (A[:, :, None] * B[:, None, :]).reshape(K, 4)
return np.einsum("k,ki,kj->ij", w, psi, psi.conj())

def make_objective(rho):
c = neg_entropy(rho)
def f(x):
sigma = build_sigma(x)
w, V = np.linalg.eigh(sigma)
lw = np.log2(np.clip(w, 1e-13, None))
log_sigma = (V * lw) @ V.conj().T
return c - float(np.real(np.trace(rho @ log_sigma)))
return f

def relative_entropy_of_entanglement(rho, n_starts=3, x0=None, maxiter=400):
f = make_objective(rho)
best_val, best_x = np.inf, None
starts = []
if x0 is not None:
starts.append(x0)
for _ in range(n_starts):
starts.append(np.concatenate([rng.normal(size=K),
rng.uniform(0, 2 * np.pi, size=4 * K)]))
for s in starts:
res = minimize(f, s, method="L-BFGS-B", options={"maxiter": maxiter})
if res.fun < best_val:
best_val, best_x = res.fun, res.x
return max(best_val, 0.0), best_x

# ---------------------------------------------------------------
# (2) Generalized robustness of entanglement (SDP)
# ---------------------------------------------------------------
def generalized_robustness(rho):
rho_r = np.real(rho)
Y = cp.Variable((4, 4), symmetric=True)
cons = [Y - rho_r >> 0, cp.partial_transpose(Y, dims=[2, 2], axis=1) >> 0]
prob = cp.Problem(cp.Minimize(cp.trace(Y) - 1), cons)
prob.solve(solver=cp.SCS, eps=1e-8)
return max(float(prob.value), 0.0)

# ---------------------------------------------------------------
# (3) Werner states: numerical result vs. analytic formulas
# ---------------------------------------------------------------
t_start = time.time()
p_list = np.linspace(0, 1, 13)
er_w, rg_w, neg_w, er_exact, rg_exact = [], [], [], [], []
for p in p_list:
rho = werner(p)
F = fidelity_phi_plus(rho)
er, _ = relative_entropy_of_entanglement(rho, n_starts=3)
er_w.append(er)
rg_w.append(generalized_robustness(rho))
neg_w.append(negativity(rho))
er_exact.append(1 - binary_entropy(F) if F > 0.5 else 0.0)
rg_exact.append(max(2 * F - 1, 0.0))
er_w, rg_w, neg_w = map(np.array, (er_w, rg_w, neg_w))
er_exact, rg_exact = np.array(er_exact), np.array(rg_exact)

print("=== Werner states: rho = p|Phi+><Phi+| + (1-p) I/4 ===")
print(f"{'p':>6} {'F':>7} {'E_R(num)':>10} {'E_R(exact)':>11} {'R_G(num)':>10} {'R_G(exact)':>11} {'N':>7}")
for p, a, b, c, d, n in zip(p_list, er_w, er_exact, rg_w, rg_exact, neg_w):
F = (3 * p + 1) / 4
print(f"{p:6.3f} {F:7.4f} {a:10.6f} {b:11.6f} {c:10.6f} {d:11.6f} {n:7.4f}")
print(f"max |E_R(num) - E_R(exact)| = {np.max(np.abs(er_w - er_exact)):.2e}")
print(f"max |R_G(num) - R_G(exact)| = {np.max(np.abs(rg_w - rg_exact)):.2e}")

# ---------------------------------------------------------------
# (4) Two-parameter family: rho(p, theta)
# ---------------------------------------------------------------
p_grid = np.linspace(0, 1, 11)
th_grid = np.linspace(0, np.pi / 4, 9)
ER = np.zeros((len(th_grid), len(p_grid)))
RG = np.zeros_like(ER)
for i, th in enumerate(th_grid):
x_prev = None
for j, p in enumerate(p_grid):
rho = family(p, th)
ER[i, j], x_prev = relative_entropy_of_entanglement(rho, n_starts=2, x0=x_prev)
RG[i, j] = generalized_robustness(rho)

# pure-state check (p = 1): E_R = entanglement entropy = h(cos^2 theta)
er_pure_exact = binary_entropy(np.cos(th_grid) ** 2)
print("\n=== Pure states (p = 1): E_R vs. entanglement entropy ===")
for th, a, b in zip(th_grid, ER[:, -1], er_pure_exact):
print(f"theta = {th:6.4f} E_R(num) = {a:.6f} entropy = {b:.6f}")
print(f"\nmax over grid of [E_R - log2(1+R_G)] = {np.max(ER - np.log2(1 + RG)):.2e} (<= 0 up to numerical tolerance)")
print(f"Total computation time: {time.time() - t_start:.1f} s")

# ---------------------------------------------------------------
# (5) One combined figure
# ---------------------------------------------------------------
P, TH = np.meshgrid(p_grid, th_grid)
fig = plt.figure(figsize=(21, 12))

ax1 = fig.add_subplot(2, 3, 1)
pp = np.linspace(0, 1, 400)
FF = (3 * pp + 1) / 4
ax1.plot(pp, np.where(FF > 0.5, 1 - binary_entropy(FF), 0), "b-", label=r"$E_R$ exact")
ax1.plot(p_list, er_w, "ro", label=r"$E_R$ numerical")
ax1.plot(pp, np.maximum(2 * FF - 1, 0), "g-", label=r"$R_G$ exact")
ax1.plot(p_list, rg_w, "ks", mfc="none", label=r"$R_G$ numerical (SDP)")
ax1.plot(p_list, neg_w, "m^--", label=r"Negativity $N$")
ax1.axvline(1 / 3, color="gray", ls=":")
ax1.set_xlabel("p"); ax1.set_ylabel("entanglement")
ax1.set_title("(a) Werner states"); ax1.legend(); ax1.grid(alpha=0.3)

ax2 = fig.add_subplot(2, 3, 2, projection="3d")
s2 = ax2.plot_surface(P, TH, ER, cmap="viridis", edgecolor="k", linewidth=0.3)
ax2.set_xlabel("p"); ax2.set_ylabel(r"$\theta$"); ax2.set_zlabel(r"$E_R$")
ax2.set_title(r"(b) Relative entropy of entanglement $E_R(p,\theta)$")
ax2.view_init(elev=28, azim=-125)
fig.colorbar(s2, ax=ax2, shrink=0.55, pad=0.1)

ax3 = fig.add_subplot(2, 3, 3, projection="3d")
s3 = ax3.plot_surface(P, TH, RG, cmap="plasma", edgecolor="k", linewidth=0.3)
ax3.set_xlabel("p"); ax3.set_ylabel(r"$\theta$"); ax3.set_zlabel(r"$R_G$")
ax3.set_title(r"(c) Generalized robustness $R_G(p,\theta)$")
ax3.view_init(elev=28, azim=-125)
fig.colorbar(s3, ax=ax3, shrink=0.55, pad=0.1)

ax4 = fig.add_subplot(2, 3, 4)
cs = ax4.contourf(P, TH, ER, levels=20, cmap="viridis")
tt4 = np.linspace(0, np.pi / 4, 200)
ax4.plot(1 / (1 + 2 * np.sin(2 * tt4)), tt4, "r--", lw=2.5, label=r"$p=1/(1+2\sin 2\theta)$")
ax4.legend(loc="upper right")
fig.colorbar(cs, ax=ax4)
ax4.set_xlabel("p"); ax4.set_ylabel(r"$\theta$")
ax4.set_title(r"(d) $E_R$ map (dashed: separable boundary)")

ax5 = fig.add_subplot(2, 3, 5)
bound = np.log2(1 + RG).ravel()
sc = ax5.scatter(bound, ER.ravel(), c=P.ravel(), cmap="coolwarm", s=40, edgecolor="k")
mx = max(bound.max(), ER.max()) * 1.05
ax5.plot([0, mx], [0, mx], "k--", label=r"$E_R=\log_2(1+R_G)$")
fig.colorbar(sc, ax=ax5, label="p")
ax5.set_xlabel(r"$\log_2(1+R_G)$"); ax5.set_ylabel(r"$E_R$")
ax5.set_title(r"(e) Inequality $E_R \leq \log_2(1+R_G)$"); ax5.legend(); ax5.grid(alpha=0.3)

ax6 = fig.add_subplot(2, 3, 6)
tt = np.linspace(0, np.pi / 4, 200)
ax6.plot(tt, binary_entropy(np.cos(tt) ** 2), "b-", label="entanglement entropy (exact)")
ax6.plot(th_grid, ER[:, -1], "ro", label=r"$E_R$ numerical ($p=1$)")
ax6.plot(th_grid, RG[:, -1], "gs", label=r"$R_G$ numerical ($p=1$)")
ax6.plot(tt, np.sin(2 * tt), "g-", alpha=0.5, label=r"$\sin 2\theta$")
ax6.set_xlabel(r"$\theta$"); ax6.set_ylabel("entanglement")
ax6.set_title("(f) Pure states"); ax6.legend(); ax6.grid(alpha=0.3)

plt.tight_layout()
plt.show()

5. Code Walkthrough

Basic tools

werner(p) and family(p, theta) build the $4\times4$ density matrices. partial_transpose reshapes $\rho$ into a rank-4 tensor $\rho_{i j, k l}\to\rho_{i,l,,k,j}$ by swapping the two indices of the second qubit, which is the partial transpose $T_B$. negativity sums the absolute values of the negative eigenvalues of $\rho^{T_B}$. binary_entropy is clipped away from $0$ and $1$ so that the $\log$ never produces nan.

Parametrizing separable states

build_sigma maps a flat parameter vector $\mathbf x\in\mathbb R^{5K}$ to a separable density matrix:

  1. The first $K$ entries are logits. A softmax (shifted by the maximum for numerical stability) turns them into probabilities $p_k$, so positivity and normalization hold automatically and the problem becomes unconstrained.
  2. The remaining $4K$ entries are Bloch-sphere angles $(\vartheta_A,\varphi_A,\vartheta_B,\varphi_B)$ for each term.
  3. The vectors $|a_k\rangle$ and $|b_k\rangle$ are built for all $k$ at once. The batched outer product A[:, :, None] * B[:, None, :] gives all $K$ product vectors $|a_kb_k\rangle$ in one operation.
  4. A single einsum assembles $\sigma=\sum_k p_k|\psi_k\rangle\langle\psi_k|$.

Because every $\sigma$ produced this way is separable, the optimizer can never wander outside $\mathrm{SEP}$.

Objective function

Since $S(\rho|\sigma)=\mathrm{Tr},\rho\log_2\rho-\mathrm{Tr},\rho\log_2\sigma$, the first term is a constant, computed once in make_objective. Each evaluation only diagonalizes $\sigma$ once: eigh gives $\sigma=V,\mathrm{diag}(w),V^\dagger$, and $\log_2\sigma=V,\mathrm{diag}(\log_2 w),V^\dagger$. The eigenvalues are clipped at $10^{-13}$ so that a numerically zero eigenvalue cannot produce -inf. The term (V * lw) @ V.conj().T multiplies column-wise by lw, which avoids building a diagonal matrix.

Optimization and speed-ups

The landscape is nonconvex in $\mathbf x$, so relative_entropy_of_entanglement runs L-BFGS-B from several random starts and keeps the best. The code is already in its accelerated form, and four design choices keep the runtime to roughly a minute or so on a standard CPU:

  • The objective has no Python loops over the $K$ product states (batched arrays and einsum).
  • Only one $4\times4$ eigendecomposition is needed per evaluation.
  • On the $(p,\theta)$ grid, the optimum found for the previous $p$ is passed as a warm start (x0=x_prev) for the next one, so only 2 random restarts are needed there.
  • The robustness problem is a tiny convex SDP, solved in about 10–20 ms per state.

Robustness SDP

generalized_robustness is a direct translation of the SDP above. Because all of our states are real, the optimal $Y$ can be taken to be real symmetric (averaging a solution with its complex conjugate keeps it feasible and optimal), so symmetric=True suffices and keeps the problem small. The constraint Y - rho_r >> 0 encodes $Y\succeq\rho$, and cp.partial_transpose(Y, dims=[2, 2], axis=1) >> 0 encodes $Y^{T_B}\succeq0$. The objective $\mathrm{Tr},Y-1$ equals $s$.

Experiments

Part (3) sweeps 13 values of the Werner parameter $p$ and compares numerical results with the exact formulas $E_R=1-h(F)$ and $R_G=2F-1$. Part (4) evaluates both measures on an $11\times 9$ grid in $(p,\theta)$, and checks the pure-state values at $p=1$ and the inequality $E_R\le\log_2(1+R_G)$.

Plotting

All six panels live in one figure. Panels (b) and (c) are 3D surfaces created with projection="3d". The legends and axis labels use TeX syntax in raw strings.


6. Execution Results

=== Werner states: rho = p|Phi+><Phi+| + (1-p) I/4 ===
     p       F   E_R(num)  E_R(exact)   R_G(num)  R_G(exact)       N
 0.000  0.2500   0.000000    0.000000   0.000000    0.000000  0.0000
 0.083  0.3125   0.000000    0.000000   0.000000    0.000000  0.0000
 0.167  0.3750   0.000000    0.000000   0.000000    0.000000  0.0000
 0.250  0.4375   0.000000    0.000000   0.000000    0.000000  0.0000
 0.333  0.5000   0.000000    0.000000   0.000000    0.000000  0.0000
 0.417  0.5625   0.011301    0.011301   0.125000    0.125000  0.0625
 0.500  0.6250   0.045566    0.045566   0.250000    0.250000  0.1250
 0.583  0.6875   0.103962    0.103962   0.375000    0.375000  0.1875
 0.667  0.7500   0.188722    0.188722   0.500000    0.500000  0.2500
 0.750  0.8125   0.303788    0.303788   0.625000    0.625000  0.3125
 0.833  0.8750   0.456436    0.456436   0.750000    0.750000  0.3750
 0.917  0.9375   0.662710    0.662710   0.875000    0.875000  0.4375
 1.000  1.0000   1.000000    1.000000   1.000000    1.000000  0.5000
max |E_R(num) - E_R(exact)| = 6.45e-08
max |R_G(num) - R_G(exact)| = 3.37e-09

=== Pure states (p = 1): E_R vs. entanglement entropy ===
theta = 0.0000   E_R(num) = 0.000000   entropy = 0.000000
theta = 0.0982   E_R(num) = 0.078179   entropy = 0.078179
theta = 0.1963   E_R(num) = 0.233327   entropy = 0.233327
theta = 0.2945   E_R(num) = 0.417032   entropy = 0.417032
theta = 0.3927   E_R(num) = 0.600876   entropy = 0.600876
theta = 0.4909   E_R(num) = 0.764191   entropy = 0.764191
theta = 0.5890   E_R(num) = 0.891619   entropy = 0.891619
theta = 0.6872   E_R(num) = 0.972369   entropy = 0.972368
theta = 0.7854   E_R(num) = 1.000000   entropy = 1.000000

max over grid of [E_R - log2(1+R_G)] = 6.28e-08  (<= 0 up to numerical tolerance)
Total computation time: 157.6 s


7. Discussion of the Results

Console output

The Werner table shows that the optimization over separable states reproduces the exact result. In my run the maximum deviation was about $6\times10^{-8}$ for $E_R$ and about $3\times10^{-9}$ for $R_G$. Some concrete values:

$p$ $F$ $E_R$ $R_G$
$0.333$ $0.5000$ $0$ $0$
$0.500$ $0.6250$ $0.045566$ $0.2500$
$0.750$ $0.8125$ $0.303788$ $0.6250$
$1.000$ $1.0000$ $1.0000$ $1.0000$

Both measures vanish for $p\le 1/3$ and become positive immediately afterward, which is the Peres–Horodecki threshold $F=1/2$. The pure-state table shows that $E_R$ matches the entanglement entropy $h(\cos^2\theta)$ to about six digits at every $\theta$. Finally, $\max[E_R-\log_2(1+R_G)]$ is of order $10^{-8}$, which is zero up to numerical tolerance (it is not exactly nonpositive because the optimizer stops at a finite tolerance). The inequality holds everywhere, with equality at the maximally entangled state.

Panel (a): Werner states

Red dots ($E_R$ from the optimizer) lie on the blue curve ($1-h(F)$). Black squares ($R_G$ from the SDP) lie on the green line $2F-1$. Both are zero up to the dotted line at $p=1/3$. Note how different the shapes are: $R_G$ grows linearly in $p$ while $E_R$ grows slowly at first, like $(F-\tfrac12)^2$ near the threshold, and only catches up at $p=1$. The negativity (magenta) is exactly half of $R_G$ for these states, so it is a rescaled copy of the robustness. Different entanglement measures agree on which states are entangled but not on how much.

Panels (b) and (c): 3D surfaces

Both surfaces are flat at zero over a large region, the separable states, and rise toward the corner $p=1$, $\theta=\pi/4$, where the state is the maximally entangled Bell state. At that corner $E_R=R_G=1$. Both surfaces are monotonic in $p$ and in $\theta$, as expected: more purity and a more balanced Schmidt decomposition give more entanglement. The robustness surface (c) is noticeably more “tent-like” and rises earlier, whereas the relative-entropy surface (b) stays low over most of the domain and shoots up near $p\to1$. This is the same linear-versus-quadratic difference seen in panel (a).

Panel (d): the entanglement map

This is a top-down view of surface (b). The dashed red curve is the analytic boundary $p=1/(1+2\sin2\theta)$, which separates separable states (below and to the left) from entangled ones. The boundary passes through $p=1/3$ at $\theta=\pi/4$ (the Werner case) and reaches $p=1$ at $\theta=0$, where the pure state is a product state. The region where $E_R$ is exactly zero coincides with this analytic boundary, which confirms that the numerical optimizer correctly detects the transition.

Panel (e): the inequality $E_R\le\log_2(1+R_G)$

Each dot is one grid state, coloured by $p$. All dots lie on or below the dashed diagonal, which is the bound $E_R\le\log_2(1+R_G)$. The points touch the diagonal only at the origin (separable states) and at the Bell state (top right). Mixed states and partially entangled pure states sit strictly below it. The gap shows that the two measures encode genuinely different information about the state.

Panel (f): pure states

For pure states, the numerical $E_R$ (red dots) matches the entanglement entropy $h(\cos^2\theta)$ (blue curve), as it must, since for pure states the closest separable state is the dephased state. The numerical $R_G$ (green squares) lies on $\sin2\theta$, in agreement with the closed form $(\sum_i\sqrt{\lambda_i})^2-1$ for pure states with Schmidt coefficients $\lambda_i$. Here $\sin 2\theta\ge h(\cos^2\theta)$ for all $\theta$, again consistent with $E_R\le\log_2(1+R_G)$.


8. Summary

  • Distance-based entanglement measures reduce to optimization problems: a nonconvex one for the relative entropy and a convex SDP for the robustness.
  • Parametrizing separable states from the inside (softmax weights times Bloch-sphere product states) turns the constrained problem into an unconstrained one that L-BFGS-B handles quickly.
  • Vectorization, a single eigendecomposition per evaluation, and warm starts keep the full 3D study down to about a minute or so.
  • The numerical results match the exact Werner, pure-state and PPT-boundary formulas to $10^{-7}$ or better, and they confirm $E_R\le\log_2(1+R_G)$.

The same approach extends to other measures, such as the geometric measure, by changing the objective, and to higher-dimensional systems, where PPT is only a relaxation of separability and the inner parametrization used here becomes the more reliable route.